using ScadaLink.Commons.Types.Flattening; using ScadaLink.TemplateEngine.Flattening; namespace ScadaLink.TemplateEngine.Tests.Flattening; public class DiffServiceTests { private readonly DiffService _sut = new(); [Fact] public void ComputeDiff_NullOldConfig_AllAdded() { var newConfig = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Attributes = [ new ResolvedAttribute { CanonicalName = "Temp", Value = "25", DataType = "Double" }, new ResolvedAttribute { CanonicalName = "Status", Value = "OK", DataType = "String" } ], Alarms = [ new ResolvedAlarm { CanonicalName = "HighTemp", TriggerType = "RangeViolation" } ], Scripts = [ new ResolvedScript { CanonicalName = "Monitor", Code = "// code" } ] }; var diff = _sut.ComputeDiff(null, newConfig); Assert.True(diff.HasChanges); Assert.Equal(2, diff.AttributeChanges.Count); Assert.All(diff.AttributeChanges, c => Assert.Equal(DiffChangeType.Added, c.ChangeType)); Assert.Single(diff.AlarmChanges); Assert.Single(diff.ScriptChanges); } [Fact] public void ComputeDiff_IdenticalConfigs_NoChanges() { var config = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Attributes = [new ResolvedAttribute { CanonicalName = "Temp", Value = "25", DataType = "Double" }], Alarms = [], Scripts = [] }; var diff = _sut.ComputeDiff(config, config); Assert.False(diff.HasChanges); Assert.Empty(diff.AttributeChanges); } [Fact] public void ComputeDiff_AttributeRemoved_DetectedAsRemoved() { var oldConfig = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Attributes = [ new ResolvedAttribute { CanonicalName = "Temp", Value = "25", DataType = "Double" }, new ResolvedAttribute { CanonicalName = "Removed", Value = "x", DataType = "String" } ] }; var newConfig = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Attributes = [new ResolvedAttribute { CanonicalName = "Temp", Value = "25", DataType = "Double" }] }; var diff = _sut.ComputeDiff(oldConfig, newConfig); Assert.True(diff.HasChanges); Assert.Single(diff.AttributeChanges); Assert.Equal(DiffChangeType.Removed, diff.AttributeChanges[0].ChangeType); Assert.Equal("Removed", diff.AttributeChanges[0].CanonicalName); } [Fact] public void ComputeDiff_AttributeChanged_DetectedAsChanged() { var oldConfig = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Attributes = [new ResolvedAttribute { CanonicalName = "Temp", Value = "25", DataType = "Double" }] }; var newConfig = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Attributes = [new ResolvedAttribute { CanonicalName = "Temp", Value = "50", DataType = "Double" }] }; var diff = _sut.ComputeDiff(oldConfig, newConfig); Assert.True(diff.HasChanges); Assert.Single(diff.AttributeChanges); Assert.Equal(DiffChangeType.Changed, diff.AttributeChanges[0].ChangeType); Assert.Equal("25", diff.AttributeChanges[0].OldValue?.Value); Assert.Equal("50", diff.AttributeChanges[0].NewValue?.Value); } [Fact] public void ComputeDiff_RevisionHashes_Included() { var config = new FlattenedConfiguration { InstanceUniqueName = "Instance1" }; var diff = _sut.ComputeDiff(config, config, "sha256:old", "sha256:new"); Assert.Equal("sha256:old", diff.OldRevisionHash); Assert.Equal("sha256:new", diff.NewRevisionHash); } [Fact] public void ComputeDiff_ScriptCodeChange_Detected() { var oldConfig = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Scripts = [new ResolvedScript { CanonicalName = "Script1", Code = "// v1" }] }; var newConfig = new FlattenedConfiguration { InstanceUniqueName = "Instance1", Scripts = [new ResolvedScript { CanonicalName = "Script1", Code = "// v2" }] }; var diff = _sut.ComputeDiff(oldConfig, newConfig); Assert.True(diff.HasChanges); Assert.Single(diff.ScriptChanges); Assert.Equal(DiffChangeType.Changed, diff.ScriptChanges[0].ChangeType); } }