Add ExtendedAttributes config toggle for system+user attributes
When GalaxyRepository.ExtendedAttributes is true, uses the extended attributes query that includes both primitive (system) and dynamic (user-defined) attributes. Default is false (dynamic only, preserving existing behavior). Extended mode returns ~564 attributes vs ~48. Adds PrimitiveName and AttributeSource fields to GalaxyAttributeInfo. Includes 5 new unit tests and 6 new integration tests covering both standard and extended attribute modes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -48,9 +48,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.Configuration
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Galaxy Repository
|
// Galaxy Repository
|
||||||
Log.Information("GalaxyRepository.ConnectionString={ConnectionString}, ChangeDetectionInterval={ChangeInterval}s, CommandTimeout={CmdTimeout}s",
|
Log.Information("GalaxyRepository.ConnectionString={ConnectionString}, ChangeDetectionInterval={ChangeInterval}s, CommandTimeout={CmdTimeout}s, ExtendedAttributes={ExtendedAttributes}",
|
||||||
config.GalaxyRepository.ConnectionString, config.GalaxyRepository.ChangeDetectionIntervalSeconds,
|
config.GalaxyRepository.ConnectionString, config.GalaxyRepository.ChangeDetectionIntervalSeconds,
|
||||||
config.GalaxyRepository.CommandTimeoutSeconds);
|
config.GalaxyRepository.CommandTimeoutSeconds, config.GalaxyRepository.ExtendedAttributes);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(config.GalaxyRepository.ConnectionString))
|
if (string.IsNullOrWhiteSpace(config.GalaxyRepository.ConnectionString))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.Configuration
|
|||||||
public string ConnectionString { get; set; } = "Server=localhost;Database=ZB;Integrated Security=true;";
|
public string ConnectionString { get; set; } = "Server=localhost;Database=ZB;Integrated Security=true;";
|
||||||
public int ChangeDetectionIntervalSeconds { get; set; } = 30;
|
public int ChangeDetectionIntervalSeconds { get; set; } = 30;
|
||||||
public int CommandTimeoutSeconds { get; set; } = 30;
|
public int CommandTimeoutSeconds { get; set; } = 30;
|
||||||
|
public bool ExtendedAttributes { get; set; } = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.Domain
|
|||||||
public string DataTypeName { get; set; } = "";
|
public string DataTypeName { get; set; } = "";
|
||||||
public bool IsArray { get; set; }
|
public bool IsArray { get; set; }
|
||||||
public int? ArrayDimension { get; set; }
|
public int? ArrayDimension { get; set; }
|
||||||
|
public string PrimitiveName { get; set; } = "";
|
||||||
|
public string AttributeSource { get; set; } = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,112 @@ WHERE td.category_id IN (1, 3, 4, 10, 11, 13, 17, 24, 26)
|
|||||||
AND da.mx_attribute_category IN (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 24)
|
AND da.mx_attribute_category IN (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 24)
|
||||||
ORDER BY g.tag_name, da.attribute_name";
|
ORDER BY g.tag_name, da.attribute_name";
|
||||||
|
|
||||||
|
private const string ExtendedAttributesSql = @"
|
||||||
|
;WITH template_chain AS (
|
||||||
|
SELECT g.gobject_id, g.derived_from_gobject_id, 0 AS depth
|
||||||
|
FROM gobject g
|
||||||
|
WHERE g.is_template = 0
|
||||||
|
UNION ALL
|
||||||
|
SELECT tc.gobject_id, t.derived_from_gobject_id, tc.depth + 1
|
||||||
|
FROM template_chain tc
|
||||||
|
INNER JOIN gobject t ON t.gobject_id = tc.derived_from_gobject_id
|
||||||
|
WHERE tc.derived_from_gobject_id <> 0 AND tc.depth < 10
|
||||||
|
)
|
||||||
|
SELECT DISTINCT
|
||||||
|
gobject_id,
|
||||||
|
tag_name,
|
||||||
|
primitive_name,
|
||||||
|
attribute_name,
|
||||||
|
full_tag_reference,
|
||||||
|
mx_data_type,
|
||||||
|
data_type_name,
|
||||||
|
is_array,
|
||||||
|
array_dimension,
|
||||||
|
mx_attribute_category,
|
||||||
|
security_classification,
|
||||||
|
attribute_source
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
g.gobject_id,
|
||||||
|
g.tag_name,
|
||||||
|
pi.primitive_name,
|
||||||
|
ad.attribute_name,
|
||||||
|
CASE WHEN pi.primitive_name = ''
|
||||||
|
THEN g.tag_name + '.' + ad.attribute_name
|
||||||
|
ELSE g.tag_name + '.' + pi.primitive_name + '.' + ad.attribute_name
|
||||||
|
END + CASE WHEN ad.is_array = 1 THEN '[]' ELSE '' END
|
||||||
|
AS full_tag_reference,
|
||||||
|
ad.mx_data_type,
|
||||||
|
dt.description AS data_type_name,
|
||||||
|
ad.is_array,
|
||||||
|
CASE WHEN ad.is_array = 1
|
||||||
|
THEN CONVERT(int, CONVERT(varbinary(2),
|
||||||
|
SUBSTRING(ad.mx_value, 15, 2) + SUBSTRING(ad.mx_value, 13, 2), 2))
|
||||||
|
ELSE NULL
|
||||||
|
END AS array_dimension,
|
||||||
|
ad.mx_attribute_category,
|
||||||
|
ad.security_classification,
|
||||||
|
'primitive' AS attribute_source
|
||||||
|
FROM gobject g
|
||||||
|
INNER JOIN instance i
|
||||||
|
ON i.gobject_id = g.gobject_id
|
||||||
|
INNER JOIN template_definition td
|
||||||
|
ON td.template_definition_id = g.template_definition_id
|
||||||
|
AND td.runtime_clsid <> '{00000000-0000-0000-0000-000000000000}'
|
||||||
|
INNER JOIN package p
|
||||||
|
ON p.package_id = g.checked_in_package_id
|
||||||
|
INNER JOIN primitive_instance pi
|
||||||
|
ON pi.package_id = p.package_id
|
||||||
|
AND pi.property_bitmask & 0x10 <> 0x10
|
||||||
|
INNER JOIN attribute_definition ad
|
||||||
|
ON ad.primitive_definition_id = pi.primitive_definition_id
|
||||||
|
AND ad.attribute_name NOT LIKE '[_]%'
|
||||||
|
AND ad.mx_attribute_category IN (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 24)
|
||||||
|
LEFT JOIN data_type dt
|
||||||
|
ON dt.mx_data_type = ad.mx_data_type
|
||||||
|
WHERE td.category_id IN (1, 3, 4, 10, 11, 13, 17, 24, 26)
|
||||||
|
AND g.is_template = 0
|
||||||
|
AND g.deployed_package_id <> 0
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
g.gobject_id,
|
||||||
|
g.tag_name,
|
||||||
|
'' AS primitive_name,
|
||||||
|
da.attribute_name,
|
||||||
|
g.tag_name + '.' + da.attribute_name
|
||||||
|
+ CASE WHEN da.is_array = 1 THEN '[]' ELSE '' END
|
||||||
|
AS full_tag_reference,
|
||||||
|
da.mx_data_type,
|
||||||
|
dt.description AS data_type_name,
|
||||||
|
da.is_array,
|
||||||
|
CASE WHEN da.is_array = 1
|
||||||
|
THEN CONVERT(int, CONVERT(varbinary(2),
|
||||||
|
SUBSTRING(da.mx_value, 15, 2) + SUBSTRING(da.mx_value, 13, 2), 2))
|
||||||
|
ELSE NULL
|
||||||
|
END AS array_dimension,
|
||||||
|
da.mx_attribute_category,
|
||||||
|
da.security_classification,
|
||||||
|
'dynamic' AS attribute_source
|
||||||
|
FROM template_chain tc
|
||||||
|
INNER JOIN dynamic_attribute da
|
||||||
|
ON da.gobject_id = tc.derived_from_gobject_id
|
||||||
|
INNER JOIN gobject g
|
||||||
|
ON g.gobject_id = tc.gobject_id
|
||||||
|
INNER JOIN template_definition td
|
||||||
|
ON td.template_definition_id = g.template_definition_id
|
||||||
|
LEFT JOIN data_type dt
|
||||||
|
ON dt.mx_data_type = da.mx_data_type
|
||||||
|
WHERE td.category_id IN (1, 3, 4, 10, 11, 13, 17, 24, 26)
|
||||||
|
AND g.is_template = 0
|
||||||
|
AND g.deployed_package_id <> 0
|
||||||
|
AND da.attribute_name NOT LIKE '[_]%'
|
||||||
|
AND da.attribute_name NOT LIKE '%.Description'
|
||||||
|
AND da.mx_attribute_category IN (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 24)
|
||||||
|
) all_attributes
|
||||||
|
ORDER BY tag_name, primitive_name, attribute_name";
|
||||||
|
|
||||||
private const string ChangeDetectionSql = "SELECT time_of_last_deploy FROM galaxy";
|
private const string ChangeDetectionSql = "SELECT time_of_last_deploy FROM galaxy";
|
||||||
|
|
||||||
private const string TestConnectionSql = "SELECT 1";
|
private const string TestConnectionSql = "SELECT 1";
|
||||||
@@ -137,18 +243,34 @@ ORDER BY g.tag_name, da.attribute_name";
|
|||||||
public async Task<List<GalaxyAttributeInfo>> GetAttributesAsync(CancellationToken ct = default)
|
public async Task<List<GalaxyAttributeInfo>> GetAttributesAsync(CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var results = new List<GalaxyAttributeInfo>();
|
var results = new List<GalaxyAttributeInfo>();
|
||||||
|
var extended = _config.ExtendedAttributes;
|
||||||
|
var sql = extended ? ExtendedAttributesSql : AttributesSql;
|
||||||
|
|
||||||
using var conn = new SqlConnection(_config.ConnectionString);
|
using var conn = new SqlConnection(_config.ConnectionString);
|
||||||
await conn.OpenAsync(ct);
|
await conn.OpenAsync(ct);
|
||||||
|
|
||||||
using var cmd = new SqlCommand(AttributesSql, conn) { CommandTimeout = _config.CommandTimeoutSeconds };
|
using var cmd = new SqlCommand(sql, conn) { CommandTimeout = _config.CommandTimeoutSeconds };
|
||||||
using var reader = await cmd.ExecuteReaderAsync(ct);
|
using var reader = await cmd.ExecuteReaderAsync(ct);
|
||||||
|
|
||||||
while (await reader.ReadAsync(ct))
|
while (await reader.ReadAsync(ct))
|
||||||
{
|
{
|
||||||
results.Add(new GalaxyAttributeInfo
|
results.Add(extended ? ReadExtendedAttribute(reader) : ReadStandardAttribute(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Information("GetAttributesAsync returned {Count} attributes (extended={Extended})", results.Count, extended);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a row from the standard attributes query (10 columns).
|
||||||
|
/// Columns: gobject_id, tag_name, attribute_name, full_tag_reference, mx_data_type,
|
||||||
|
/// data_type_name, is_array, array_dimension, mx_attribute_category, security_classification
|
||||||
|
/// </summary>
|
||||||
|
private static GalaxyAttributeInfo ReadStandardAttribute(SqlDataReader reader)
|
||||||
{
|
{
|
||||||
GobjectId = reader.GetInt32(0),
|
return new GalaxyAttributeInfo
|
||||||
|
{
|
||||||
|
GobjectId = Convert.ToInt32(reader.GetValue(0)),
|
||||||
TagName = reader.GetString(1),
|
TagName = reader.GetString(1),
|
||||||
AttributeName = reader.GetString(2),
|
AttributeName = reader.GetString(2),
|
||||||
FullTagReference = reader.GetString(3),
|
FullTagReference = reader.GetString(3),
|
||||||
@@ -156,11 +278,30 @@ ORDER BY g.tag_name, da.attribute_name";
|
|||||||
DataTypeName = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
DataTypeName = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
||||||
IsArray = Convert.ToBoolean(reader.GetValue(6)),
|
IsArray = Convert.ToBoolean(reader.GetValue(6)),
|
||||||
ArrayDimension = reader.IsDBNull(7) ? null : (int?)Convert.ToInt32(reader.GetValue(7))
|
ArrayDimension = reader.IsDBNull(7) ? null : (int?)Convert.ToInt32(reader.GetValue(7))
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Information("GetAttributesAsync returned {Count} attributes", results.Count);
|
/// <summary>
|
||||||
return results;
|
/// Reads a row from the extended attributes query (12 columns).
|
||||||
|
/// Columns: gobject_id, tag_name, primitive_name, attribute_name, full_tag_reference,
|
||||||
|
/// mx_data_type, data_type_name, is_array, array_dimension,
|
||||||
|
/// mx_attribute_category, security_classification, attribute_source
|
||||||
|
/// </summary>
|
||||||
|
private static GalaxyAttributeInfo ReadExtendedAttribute(SqlDataReader reader)
|
||||||
|
{
|
||||||
|
return new GalaxyAttributeInfo
|
||||||
|
{
|
||||||
|
GobjectId = Convert.ToInt32(reader.GetValue(0)),
|
||||||
|
TagName = reader.GetString(1),
|
||||||
|
PrimitiveName = reader.IsDBNull(2) ? "" : reader.GetString(2),
|
||||||
|
AttributeName = reader.GetString(3),
|
||||||
|
FullTagReference = reader.GetString(4),
|
||||||
|
MxDataType = Convert.ToInt32(reader.GetValue(5)),
|
||||||
|
DataTypeName = reader.IsDBNull(6) ? "" : reader.GetString(6),
|
||||||
|
IsArray = Convert.ToBoolean(reader.GetValue(7)),
|
||||||
|
ArrayDimension = reader.IsDBNull(8) ? null : (int?)Convert.ToInt32(reader.GetValue(8)),
|
||||||
|
AttributeSource = reader.IsDBNull(11) ? "" : reader.GetString(11)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<DateTime?> GetLastDeployTimeAsync(CancellationToken ct = default)
|
public async Task<DateTime?> GetLastDeployTimeAsync(CancellationToken ct = default)
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
"GalaxyRepository": {
|
"GalaxyRepository": {
|
||||||
"ConnectionString": "Server=localhost;Database=ZB;Integrated Security=true;",
|
"ConnectionString": "Server=localhost;Database=ZB;Integrated Security=true;",
|
||||||
"ChangeDetectionIntervalSeconds": 30,
|
"ChangeDetectionIntervalSeconds": 30,
|
||||||
"CommandTimeoutSeconds": 30
|
"CommandTimeoutSeconds": 30,
|
||||||
|
"ExtendedAttributes": false
|
||||||
},
|
},
|
||||||
"Dashboard": {
|
"Dashboard": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Shouldly;
|
||||||
|
using Xunit;
|
||||||
|
using ZB.MOM.WW.LmxOpcUa.Host.Configuration;
|
||||||
|
using ZB.MOM.WW.LmxOpcUa.Host.GalaxyRepository;
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.LmxOpcUa.IntegrationTests
|
||||||
|
{
|
||||||
|
public class GalaxyRepositoryServiceTests
|
||||||
|
{
|
||||||
|
private static GalaxyRepositoryConfiguration LoadConfig(bool extendedAttributes = false)
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.test.json", optional: false)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var config = new GalaxyRepositoryConfiguration();
|
||||||
|
configuration.GetSection("GalaxyRepository").Bind(config);
|
||||||
|
config.ExtendedAttributes = extendedAttributes;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAttributesAsync_StandardMode_ReturnsRows()
|
||||||
|
{
|
||||||
|
var config = LoadConfig(extendedAttributes: false);
|
||||||
|
var service = new GalaxyRepositoryService(config);
|
||||||
|
|
||||||
|
var results = await service.GetAttributesAsync();
|
||||||
|
|
||||||
|
results.ShouldNotBeEmpty();
|
||||||
|
// Standard mode: PrimitiveName and AttributeSource should be empty
|
||||||
|
results.ShouldAllBe(r => r.PrimitiveName == "" && r.AttributeSource == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAttributesAsync_ExtendedMode_ReturnsMoreRows()
|
||||||
|
{
|
||||||
|
var standardConfig = LoadConfig(extendedAttributes: false);
|
||||||
|
var extendedConfig = LoadConfig(extendedAttributes: true);
|
||||||
|
var standardService = new GalaxyRepositoryService(standardConfig);
|
||||||
|
var extendedService = new GalaxyRepositoryService(extendedConfig);
|
||||||
|
|
||||||
|
var standardResults = await standardService.GetAttributesAsync();
|
||||||
|
var extendedResults = await extendedService.GetAttributesAsync();
|
||||||
|
|
||||||
|
extendedResults.Count.ShouldBeGreaterThan(standardResults.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAttributesAsync_ExtendedMode_IncludesPrimitiveAttributes()
|
||||||
|
{
|
||||||
|
var config = LoadConfig(extendedAttributes: true);
|
||||||
|
var service = new GalaxyRepositoryService(config);
|
||||||
|
|
||||||
|
var results = await service.GetAttributesAsync();
|
||||||
|
|
||||||
|
results.ShouldContain(r => r.AttributeSource == "primitive");
|
||||||
|
results.ShouldContain(r => r.AttributeSource == "dynamic");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAttributesAsync_ExtendedMode_PrimitiveNamePopulated()
|
||||||
|
{
|
||||||
|
var config = LoadConfig(extendedAttributes: true);
|
||||||
|
var service = new GalaxyRepositoryService(config);
|
||||||
|
|
||||||
|
var results = await service.GetAttributesAsync();
|
||||||
|
|
||||||
|
// Some primitive attributes have non-empty primitive names
|
||||||
|
// (though many have empty primitive_name for the root UDO)
|
||||||
|
results.ShouldNotBeEmpty();
|
||||||
|
// All should have an attribute source
|
||||||
|
results.ShouldAllBe(r => r.AttributeSource == "primitive" || r.AttributeSource == "dynamic");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAttributesAsync_StandardMode_AllHaveFullTagReference()
|
||||||
|
{
|
||||||
|
var config = LoadConfig(extendedAttributes: false);
|
||||||
|
var service = new GalaxyRepositoryService(config);
|
||||||
|
|
||||||
|
var results = await service.GetAttributesAsync();
|
||||||
|
|
||||||
|
results.ShouldAllBe(r => !string.IsNullOrEmpty(r.FullTagReference));
|
||||||
|
results.ShouldAllBe(r => r.FullTagReference.Contains("."));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAttributesAsync_ExtendedMode_AllHaveFullTagReference()
|
||||||
|
{
|
||||||
|
var config = LoadConfig(extendedAttributes: true);
|
||||||
|
var service = new GalaxyRepositoryService(config);
|
||||||
|
|
||||||
|
var results = await service.GetAttributesAsync();
|
||||||
|
|
||||||
|
results.ShouldAllBe(r => !string.IsNullOrEmpty(r.FullTagReference));
|
||||||
|
results.ShouldAllBe(r => r.FullTagReference.Contains("."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,6 +53,27 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Configuration
|
|||||||
config.GalaxyRepository.ConnectionString.ShouldContain("ZB");
|
config.GalaxyRepository.ConnectionString.ShouldContain("ZB");
|
||||||
config.GalaxyRepository.ChangeDetectionIntervalSeconds.ShouldBe(30);
|
config.GalaxyRepository.ChangeDetectionIntervalSeconds.ShouldBe(30);
|
||||||
config.GalaxyRepository.CommandTimeoutSeconds.ShouldBe(30);
|
config.GalaxyRepository.CommandTimeoutSeconds.ShouldBe(30);
|
||||||
|
config.GalaxyRepository.ExtendedAttributes.ShouldBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GalaxyRepository_ExtendedAttributes_DefaultsFalse()
|
||||||
|
{
|
||||||
|
var config = new GalaxyRepositoryConfiguration();
|
||||||
|
config.ExtendedAttributes.ShouldBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GalaxyRepository_ExtendedAttributes_BindsFromJson()
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.json", optional: false)
|
||||||
|
.AddInMemoryCollection(new[] { new System.Collections.Generic.KeyValuePair<string, string>("GalaxyRepository:ExtendedAttributes", "true") })
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var config = new GalaxyRepositoryConfiguration();
|
||||||
|
configuration.GetSection("GalaxyRepository").Bind(config);
|
||||||
|
config.ExtendedAttributes.ShouldBe(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using Shouldly;
|
||||||
|
using Xunit;
|
||||||
|
using ZB.MOM.WW.LmxOpcUa.Host.Domain;
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.LmxOpcUa.Tests.Domain
|
||||||
|
{
|
||||||
|
public class GalaxyAttributeInfoTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void DefaultValues_AreEmpty()
|
||||||
|
{
|
||||||
|
var info = new GalaxyAttributeInfo();
|
||||||
|
info.PrimitiveName.ShouldBe("");
|
||||||
|
info.AttributeSource.ShouldBe("");
|
||||||
|
info.TagName.ShouldBe("");
|
||||||
|
info.AttributeName.ShouldBe("");
|
||||||
|
info.FullTagReference.ShouldBe("");
|
||||||
|
info.DataTypeName.ShouldBe("");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExtendedFields_CanBeSet()
|
||||||
|
{
|
||||||
|
var info = new GalaxyAttributeInfo
|
||||||
|
{
|
||||||
|
PrimitiveName = "UDO",
|
||||||
|
AttributeSource = "primitive"
|
||||||
|
};
|
||||||
|
info.PrimitiveName.ShouldBe("UDO");
|
||||||
|
info.AttributeSource.ShouldBe("primitive");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StandardAttributes_HaveEmptyExtendedFields()
|
||||||
|
{
|
||||||
|
var info = new GalaxyAttributeInfo
|
||||||
|
{
|
||||||
|
GobjectId = 1,
|
||||||
|
TagName = "TestObj",
|
||||||
|
AttributeName = "MachineID",
|
||||||
|
FullTagReference = "TestObj.MachineID",
|
||||||
|
MxDataType = 5
|
||||||
|
};
|
||||||
|
info.PrimitiveName.ShouldBe("");
|
||||||
|
info.AttributeSource.ShouldBe("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user