- WP-23: ITemplateEngineRepository full EF Core implementation - WP-1: Template CRUD with deletion constraints (instances, children, compositions) - WP-2–4: Attribute, alarm, script definitions with lock flags and override granularity - WP-5: Shared script CRUD with syntax validation - WP-6–7: Composition with recursive nesting and canonical naming - WP-8–11: Override granularity, locking rules, inheritance/composition scope - WP-12: Naming collision detection on canonical names (recursive) - WP-13: Graph acyclicity (inheritance + composition cycles) Core services: TemplateService, SharedScriptService, TemplateResolver, LockEnforcer, CollisionDetector, CycleDetector. 358 tests pass.
119 lines
4.2 KiB
C#
119 lines
4.2 KiB
C#
using System.Text.Json;
|
|
using ScadaLink.Commons.Types.Flattening;
|
|
|
|
namespace ScadaLink.TemplateEngine.Tests.Flattening;
|
|
|
|
public class DeploymentPackageTests
|
|
{
|
|
[Fact]
|
|
public void DeploymentPackage_JsonSerializable()
|
|
{
|
|
var package = new DeploymentPackage
|
|
{
|
|
InstanceUniqueName = "PumpStation1",
|
|
DeploymentId = "dep-abc123",
|
|
RevisionHash = "sha256:abcdef1234567890",
|
|
DeployedBy = "admin@company.com",
|
|
DeployedAtUtc = new DateTimeOffset(2026, 3, 16, 12, 0, 0, TimeSpan.Zero),
|
|
Configuration = new FlattenedConfiguration
|
|
{
|
|
InstanceUniqueName = "PumpStation1",
|
|
TemplateId = 1,
|
|
SiteId = 1,
|
|
Attributes =
|
|
[
|
|
new ResolvedAttribute
|
|
{
|
|
CanonicalName = "Temperature",
|
|
Value = "25.0",
|
|
DataType = "Double",
|
|
BoundDataConnectionId = 100,
|
|
BoundDataConnectionName = "OPC-Server1",
|
|
BoundDataConnectionProtocol = "OpcUa",
|
|
DataSourceReference = "ns=2;s=Temp"
|
|
}
|
|
],
|
|
Alarms =
|
|
[
|
|
new ResolvedAlarm
|
|
{
|
|
CanonicalName = "HighTemp",
|
|
TriggerType = "RangeViolation",
|
|
PriorityLevel = 1
|
|
}
|
|
],
|
|
Scripts =
|
|
[
|
|
new ResolvedScript
|
|
{
|
|
CanonicalName = "Monitor",
|
|
Code = "var x = Attributes[\"Temperature\"].Value;"
|
|
}
|
|
]
|
|
},
|
|
PreviousRevisionHash = null
|
|
};
|
|
|
|
var json = JsonSerializer.Serialize(package);
|
|
Assert.NotNull(json);
|
|
Assert.Contains("PumpStation1", json);
|
|
Assert.Contains("sha256:abcdef1234567890", json);
|
|
|
|
var deserialized = JsonSerializer.Deserialize<DeploymentPackage>(json);
|
|
Assert.NotNull(deserialized);
|
|
Assert.Equal("PumpStation1", deserialized.InstanceUniqueName);
|
|
Assert.Equal("dep-abc123", deserialized.DeploymentId);
|
|
Assert.Single(deserialized.Configuration.Attributes);
|
|
Assert.Equal("Temperature", deserialized.Configuration.Attributes[0].CanonicalName);
|
|
}
|
|
|
|
[Fact]
|
|
public void DeploymentPackage_WithDiff_Serializable()
|
|
{
|
|
var package = new DeploymentPackage
|
|
{
|
|
InstanceUniqueName = "Inst1",
|
|
DeploymentId = "dep-1",
|
|
RevisionHash = "sha256:new",
|
|
DeployedBy = "admin",
|
|
DeployedAtUtc = DateTimeOffset.UtcNow,
|
|
Configuration = new FlattenedConfiguration { InstanceUniqueName = "Inst1" },
|
|
Diff = new ConfigurationDiff
|
|
{
|
|
InstanceUniqueName = "Inst1",
|
|
OldRevisionHash = "sha256:old",
|
|
NewRevisionHash = "sha256:new",
|
|
AttributeChanges =
|
|
[
|
|
new DiffEntry<ResolvedAttribute>
|
|
{
|
|
CanonicalName = "Temp",
|
|
ChangeType = DiffChangeType.Changed,
|
|
OldValue = new ResolvedAttribute { CanonicalName = "Temp", Value = "25", DataType = "Double" },
|
|
NewValue = new ResolvedAttribute { CanonicalName = "Temp", Value = "50", DataType = "Double" }
|
|
}
|
|
]
|
|
},
|
|
PreviousRevisionHash = "sha256:old"
|
|
};
|
|
|
|
var json = JsonSerializer.Serialize(package);
|
|
var deserialized = JsonSerializer.Deserialize<DeploymentPackage>(json);
|
|
|
|
Assert.NotNull(deserialized?.Diff);
|
|
Assert.True(deserialized.Diff.HasChanges);
|
|
Assert.Equal("sha256:old", deserialized.PreviousRevisionHash);
|
|
}
|
|
|
|
[Fact]
|
|
public void FlattenedConfiguration_DefaultValues()
|
|
{
|
|
var config = new FlattenedConfiguration();
|
|
|
|
Assert.Equal(string.Empty, config.InstanceUniqueName);
|
|
Assert.Empty(config.Attributes);
|
|
Assert.Empty(config.Alarms);
|
|
Assert.Empty(config.Scripts);
|
|
}
|
|
}
|