From ed44d03a7ba848d36be9a546f9c2f549bb3c37c9 Mon Sep 17 00:00:00 2001 From: Tony Troeff Date: Sun, 9 Feb 2025 17:43:24 +0200 Subject: [PATCH 1/4] Introduced a new sophisticated way to structure more robust tests for outer demands. --- .../ConstructionManagerTests.cs | 121 +++++++++++------- .../Attributes/ExternalDemandsAttribute.cs | 8 +- .../Attributes/InternalDemandsAttribute.cs | 8 +- .../Attributes/OuterDemandsAttribute.cs | 8 +- 4 files changed, 75 insertions(+), 70 deletions(-) diff --git a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs index e73fa87..e0bac72 100644 --- a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs +++ b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs @@ -2,6 +2,7 @@ using System.Text.Json; using TryAtSoftware.CleanTests.Core.Construction; +using TryAtSoftware.CleanTests.Core.Interfaces; using TryAtSoftware.CleanTests.UnitTests.Constants; using TryAtSoftware.CleanTests.UnitTests.Extensions; using TryAtSoftware.CleanTests.UnitTests.Parametrization; @@ -113,7 +114,7 @@ public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtRootLevel() } [Fact] - public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels() + public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels() { var utilitiesCount = RandomizationHelper.RandomInteger(3, 10); var setup = new EnvironmentSetup("outer_demands_env"); @@ -122,9 +123,8 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels() for (var i = 1; i <= utilitiesCount; i++) { - var characteristic = $"C-{i}"; - setup.WithCharacteristics("SL2", i, characteristic); - setup.WithOuterDemands("TL1", i, "SL2", characteristic); + setup.WithCharacteristics("SL2", i, $"C{i}"); + setup.WithOuterDemands("TL1", i, "SL2", $"D{i}"); } var assemblyTestData = setup.MaterializeAsAssemblyData(); @@ -133,67 +133,82 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels() var fl1Utilities = assemblyTestData.CleanUtilities.Get("FL1").ToArray(); Assert.Single(fl1Utilities); - var sl1Utilities = assemblyTestData.CleanUtilities.Get("SL1").ToArray(); - Assert.Single(sl1Utilities); - - var sl2Utilities = assemblyTestData.CleanUtilities.Get("SL2").ToArray(); - Assert.Equal(utilitiesCount, sl2Utilities.Length); - - var tl1Utilities = assemblyTestData.CleanUtilities.Get("TL1").ToArray(); - Assert.Equal(utilitiesCount, tl1Utilities.Length); - var utilityIds = new[] { fl1Utilities[0].Id }; var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); - Assert.Equal(utilitiesCount, constructionGraphs.Length); - for (var i = 0; i < utilitiesCount; i++) - { - var fl1ConstructionGraph = constructionGraphs[i][0]; - - Assert.NotNull(fl1Utilities); - Assert.Equal(fl1Utilities[0].Id, fl1ConstructionGraph.Id); - Assert.Equal(2, fl1ConstructionGraph.Dependencies.Count); - - var sl1ConstructionGraph = fl1ConstructionGraph.Dependencies[0]; - Assert.NotNull(sl1ConstructionGraph); - Assert.Equal(sl1Utilities[0].Id, sl1ConstructionGraph.Id); - - var sl2ConstructionGraph = fl1ConstructionGraph.Dependencies[1]; - Assert.NotNull(sl2ConstructionGraph); - Assert.Equal(sl2Utilities[i].Id, sl2ConstructionGraph.Id); - Assert.Empty(sl2ConstructionGraph.Dependencies); - - var tl1ConstructionGraph = Assert.Single(sl1ConstructionGraph.Dependencies); - Assert.NotNull(tl1ConstructionGraph); - Assert.Equal(tl1Utilities[i].Id, tl1ConstructionGraph.Id); - Assert.Empty(tl1ConstructionGraph.Dependencies); - } + Assert.Empty(constructionGraphs); } - - [Fact] - public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels() + + /// + /// |N0| -> |N1| -> ... |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}| + /// -> |Q| + /// + /// N{depth} defines outer demands towards Q + /// + [Theory] + [MemberData(nameof(GetDepthMembers))] + public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) { var utilitiesCount = RandomizationHelper.RandomInteger(3, 10); var setup = new EnvironmentSetup("outer_demands_env"); - setup.WithCategory("FL1", 1).WithCategory("SL1", 1).WithCategory("SL2", utilitiesCount).WithCategory("TL1", utilitiesCount); - setup.WithRequirements("FL1", 1, "SL1", "SL2").WithRequirements("SL1", 1, "TL1"); + + for (var i = 0; i < depth; i++) + { + setup.WithCategory($"N{i}", 1); + setup.WithRequirements($"N{i}", 1, $"N{i + 1}"); + } + + setup.WithCategory($"N{depth}", utilitiesCount).WithCategory("Q", utilitiesCount); + setup.WithRequirements($"N{depth - 2}", 1, "Q"); for (var i = 1; i <= utilitiesCount; i++) { - setup.WithCharacteristics("SL2", i, $"C{i}"); - setup.WithOuterDemands("TL1", i, "SL2", $"D{i}"); + setup.WithCharacteristics("Q", i, $"C{i}"); + setup.WithOuterDemands($"N{depth}", i, "Q", $"C{i}"); } var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - var fl1Utilities = assemblyTestData.CleanUtilities.Get("FL1").ToArray(); - Assert.Single(fl1Utilities); + // NOTE: There are depth + 1 `N#` categories and `Q`. + var utilitiesMatrix = new ICleanUtilityDescriptor[depth + 2][]; + for (var i = 0; i <= depth; i++) utilitiesMatrix[i] = assemblyTestData.CleanUtilities.Get($"N{i}").ToArray(); + utilitiesMatrix[^1] = assemblyTestData.CleanUtilities.Get("Q").ToArray(); - var utilityIds = new[] { fl1Utilities[0].Id }; - var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); + for (var i = 0; i < depth; i++) Assert.Single(utilitiesMatrix[i]); + for (var i = depth; i < utilitiesMatrix.Length; i++) Assert.Equal(utilitiesCount, utilitiesMatrix[i].Length); - Assert.Empty(constructionGraphs); + var utilityIds = new[] { utilitiesMatrix[0][0].Id }; + var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); + + Assert.Equal(utilitiesCount, constructionGraphs.Length); + for (var i = 0; i < utilitiesCount; i++) + { + var constructionGraph = constructionGraphs[i][0]; + + for (var j = 0; j < depth - 2; j++) + { + Assert.Equal(utilitiesMatrix[j][0].Id, constructionGraph.Id); + Assert.Single(constructionGraph.Dependencies); + + constructionGraph = constructionGraph.Dependencies[0]; + } + + Assert.Equal(utilitiesMatrix[depth - 2][0].Id, constructionGraph.Id); + Assert.Equal(2, constructionGraph.Dependencies.Count); + + var penultConstructionGraph = constructionGraph.Dependencies[0]; + Assert.Equal(utilitiesMatrix[depth - 1][0].Id, penultConstructionGraph.Id); + Assert.Single(penultConstructionGraph.Dependencies); + + var qConstructionGraph = constructionGraph.Dependencies[1]; + Assert.Equal(utilitiesMatrix[^1][i].Id, qConstructionGraph.Id); + Assert.Empty(qConstructionGraph.Dependencies); + + var lastConstructionGraph = penultConstructionGraph.Dependencies[0]; + Assert.Equal(utilitiesMatrix[depth][i].Id, lastConstructionGraph.Id); + Assert.Empty(lastConstructionGraph.Dependencies); + } } public static TheoryData GetDependenciesManagerSetups() @@ -201,7 +216,15 @@ public static TheoryData GetDependenciesManagerSetups( var data = new TheoryData(); foreach (var dependenciesManagerSetup in TestParameters.ConstructObservableConstructionManagerSetups()) data.Add(dependenciesManagerSetup.EnvironmentSetup, dependenciesManagerSetup.PathToExpectedResult); - + + return data; + } + + public static TheoryData GetDepthMembers() + { + var data = new TheoryData(); + for (var i = 2; i <= 10; i++) data.Add(i); + return data; } } \ No newline at end of file diff --git a/TryAtSoftware.CleanTests.Core/Attributes/ExternalDemandsAttribute.cs b/TryAtSoftware.CleanTests.Core/Attributes/ExternalDemandsAttribute.cs index ec2705c..7618c95 100644 --- a/TryAtSoftware.CleanTests.Core/Attributes/ExternalDemandsAttribute.cs +++ b/TryAtSoftware.CleanTests.Core/Attributes/ExternalDemandsAttribute.cs @@ -3,10 +3,4 @@ using System; [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -public class ExternalDemandsAttribute : BaseDemandsAttribute -{ - public ExternalDemandsAttribute(string category, params string[] demands) - : base(category, demands) - { - } -} \ No newline at end of file +public class ExternalDemandsAttribute(string category, params string[] demands) : BaseDemandsAttribute(category, demands); \ No newline at end of file diff --git a/TryAtSoftware.CleanTests.Core/Attributes/InternalDemandsAttribute.cs b/TryAtSoftware.CleanTests.Core/Attributes/InternalDemandsAttribute.cs index df3b96a..004d345 100644 --- a/TryAtSoftware.CleanTests.Core/Attributes/InternalDemandsAttribute.cs +++ b/TryAtSoftware.CleanTests.Core/Attributes/InternalDemandsAttribute.cs @@ -3,10 +3,4 @@ using System; [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -public class InternalDemandsAttribute : BaseDemandsAttribute -{ - public InternalDemandsAttribute(string category, params string[] demands) - : base(category, demands) - { - } -} \ No newline at end of file +public class InternalDemandsAttribute(string category, params string[] demands) : BaseDemandsAttribute(category, demands); \ No newline at end of file diff --git a/TryAtSoftware.CleanTests.Core/Attributes/OuterDemandsAttribute.cs b/TryAtSoftware.CleanTests.Core/Attributes/OuterDemandsAttribute.cs index a87e416..85e128b 100644 --- a/TryAtSoftware.CleanTests.Core/Attributes/OuterDemandsAttribute.cs +++ b/TryAtSoftware.CleanTests.Core/Attributes/OuterDemandsAttribute.cs @@ -3,10 +3,4 @@ using System; [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -public class OuterDemandsAttribute : BaseDemandsAttribute -{ - public OuterDemandsAttribute(string category, params string[] demands) - : base(category, demands) - { - } -} \ No newline at end of file +public class OuterDemandsAttribute(string category, params string[] demands) : BaseDemandsAttribute(category, demands); \ No newline at end of file From a9f16aebfa0b178d58251dd92ce9bc2faa61f568 Mon Sep 17 00:00:00 2001 From: Tony Troeff Date: Sun, 9 Feb 2025 23:08:21 +0200 Subject: [PATCH 2/4] Enhanced the tests for unsatisfiable outer demands as well. --- .../ConstructionManagerTests.cs | 124 +++++++++++------- 1 file changed, 75 insertions(+), 49 deletions(-) diff --git a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs index e0bac72..aac989b 100644 --- a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs +++ b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs @@ -3,6 +3,7 @@ using System.Text.Json; using TryAtSoftware.CleanTests.Core.Construction; using TryAtSoftware.CleanTests.Core.Interfaces; +using TryAtSoftware.CleanTests.Core.XUnit; using TryAtSoftware.CleanTests.UnitTests.Constants; using TryAtSoftware.CleanTests.UnitTests.Extensions; using TryAtSoftware.CleanTests.UnitTests.Parametrization; @@ -113,55 +114,20 @@ public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtRootLevel() } } - [Fact] - public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels() - { - var utilitiesCount = RandomizationHelper.RandomInteger(3, 10); - var setup = new EnvironmentSetup("outer_demands_env"); - setup.WithCategory("FL1", 1).WithCategory("SL1", 1).WithCategory("SL2", utilitiesCount).WithCategory("TL1", utilitiesCount); - setup.WithRequirements("FL1", 1, "SL1", "SL2").WithRequirements("SL1", 1, "TL1"); - - for (var i = 1; i <= utilitiesCount; i++) - { - setup.WithCharacteristics("SL2", i, $"C{i}"); - setup.WithOuterDemands("TL1", i, "SL2", $"D{i}"); - } - - var assemblyTestData = setup.MaterializeAsAssemblyData(); - var manager = new ConstructionManager(assemblyTestData); - - var fl1Utilities = assemblyTestData.CleanUtilities.Get("FL1").ToArray(); - Assert.Single(fl1Utilities); - - var utilityIds = new[] { fl1Utilities[0].Id }; - var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); - - Assert.Empty(constructionGraphs); - } - /// - /// |N0| -> |N1| -> ... |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}| + /// |N0| -> |N1| -> ... -> |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}| /// -> |Q| /// /// N{depth} defines outer demands towards Q /// - [Theory] - [MemberData(nameof(GetDepthMembers))] + [Theory, MemberData(nameof(GetDepthMembers))] public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) { - var utilitiesCount = RandomizationHelper.RandomInteger(3, 10); var setup = new EnvironmentSetup("outer_demands_env"); + var count = RandomizationHelper.RandomInteger(3, 10); + PrepareForOuterDemandsTesting(setup, depth, count); - for (var i = 0; i < depth; i++) - { - setup.WithCategory($"N{i}", 1); - setup.WithRequirements($"N{i}", 1, $"N{i + 1}"); - } - - setup.WithCategory($"N{depth}", utilitiesCount).WithCategory("Q", utilitiesCount); - setup.WithRequirements($"N{depth - 2}", 1, "Q"); - - for (var i = 1; i <= utilitiesCount; i++) + for (var i = 1; i <= count; i++) { setup.WithCharacteristics("Q", i, $"C{i}"); setup.WithOuterDemands($"N{depth}", i, "Q", $"C{i}"); @@ -171,18 +137,13 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) var manager = new ConstructionManager(assemblyTestData); // NOTE: There are depth + 1 `N#` categories and `Q`. - var utilitiesMatrix = new ICleanUtilityDescriptor[depth + 2][]; - for (var i = 0; i <= depth; i++) utilitiesMatrix[i] = assemblyTestData.CleanUtilities.Get($"N{i}").ToArray(); - utilitiesMatrix[^1] = assemblyTestData.CleanUtilities.Get("Q").ToArray(); - - for (var i = 0; i < depth; i++) Assert.Single(utilitiesMatrix[i]); - for (var i = depth; i < utilitiesMatrix.Length; i++) Assert.Equal(utilitiesCount, utilitiesMatrix[i].Length); + var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth, count); - var utilityIds = new[] { utilitiesMatrix[0][0].Id }; + var utilityIds = utilitiesMatrix[0].Select(x => x.Id); var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); - Assert.Equal(utilitiesCount, constructionGraphs.Length); - for (var i = 0; i < utilitiesCount; i++) + Assert.Equal(count, constructionGraphs.Length); + for (var i = 0; i < count; i++) { var constructionGraph = constructionGraphs[i][0]; @@ -210,6 +171,71 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) Assert.Empty(lastConstructionGraph.Dependencies); } } + + /// + /// |N0| -> |N1| -> ... -> |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}| + /// -> |Q| + /// + /// N{depth} defines outer demands towards Q + /// + [Theory, MemberData(nameof(GetDepthMembers))] + public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels(int depth) + { + var setup = new EnvironmentSetup("outer_demands_env"); + var count = RandomizationHelper.RandomInteger(3, 10); + PrepareForOuterDemandsTesting(setup, depth, count); + + for (var i = 1; i <= count; i++) + { + setup.WithCharacteristics("Q", i, $"C{i}"); + setup.WithOuterDemands($"N{depth}", i, "Q", $"D{i}"); + } + + var assemblyTestData = setup.MaterializeAsAssemblyData(); + var manager = new ConstructionManager(assemblyTestData); + + var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth, count); + + var utilityIds = utilitiesMatrix[0].Select(x => x.Id); + var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); + Assert.Empty(constructionGraphs); + } + + /// + /// |N0| -> |N1| -> ... -> |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}|
+ /// -> |Q| -----------------^ + /// + /// N{depth} defines outer demands towards Q + ///
+ private static void PrepareForOuterDemandsTesting(EnvironmentSetup setup, int depth, int count) + { + for (var i = 0; i < depth; i++) + { + setup.WithCategory($"N{i}", 1); + setup.WithRequirements($"N{i}", 1, $"N{i + 1}"); + } + + setup.WithCategory($"N{depth}", count).WithCategory("Q", count); + setup.WithRequirements($"N{depth - 2}", 1, "Q"); + } + + /// + /// Returns a matrix of length `depth + 2`: + /// - The first `depth + 1` entries are reserved for the `N#` categories. + /// - The last entry is reserved for the `Q` category. + /// + private static ICleanUtilityDescriptor[][] ExtractUtilitiesForOuterDemandsTesting(CleanTestAssemblyData assemblyTestData, int depth, int count) + { + // NOTE: There are depth + 1 `N#` categories and `Q`. + var matrix = new ICleanUtilityDescriptor[depth + 2][]; + for (var i = 0; i <= depth; i++) matrix[i] = assemblyTestData.CleanUtilities.Get($"N{i}").ToArray(); + matrix[^1] = assemblyTestData.CleanUtilities.Get("Q").ToArray(); + + for (var i = 0; i < depth; i++) Assert.Single(matrix[i]); + for (var i = depth; i < matrix.Length; i++) Assert.Equal(count, matrix[i].Length); + + return matrix; + } public static TheoryData GetDependenciesManagerSetups() { From 13810db1d129425272223a9df9b20b5a7b7bb7ee Mon Sep 17 00:00:00 2001 From: Tony Troeff Date: Sun, 9 Feb 2025 23:40:10 +0200 Subject: [PATCH 3/4] Updated all root-level tests for outer demands as well. --- .../ConstructionManagerTests.cs | 110 +++++++----------- 1 file changed, 40 insertions(+), 70 deletions(-) diff --git a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs index aac989b..5fcc760 100644 --- a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs +++ b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs @@ -35,91 +35,68 @@ public Task DependencyGraphsShouldBeConstructedSuccessfully(EnvironmentSetup set [Fact] public void OuterDemandsShouldBeAppliedCorrectlyAtRootLevel() { - var utilitiesCount = RandomizationHelper.RandomInteger(3, 10); var setup = new EnvironmentSetup("outer_demands_env"); - setup.WithCategory("FL1", 1).WithCategory("FL2", utilitiesCount).WithCategory("SL1", utilitiesCount); - setup.WithRequirements("FL1", 1, "SL1"); - - for (var i = 1; i <= utilitiesCount; i++) + var count = RandomizationHelper.RandomInteger(3, 10); + PrepareForOuterDemandsTesting(setup, depth: 1, count); + + for (var i = 1; i <= count; i++) { - var characteristic = $"C-{i}"; - setup.WithCharacteristics("FL2", i, characteristic); - setup.WithOuterDemands("SL1", i, "FL2", characteristic); + setup.WithCharacteristics("Q", i, $"C{i}"); + setup.WithOuterDemands("N1", i, "Q", $"C{i}"); } var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - var fl1Utilities = assemblyTestData.CleanUtilities.Get("FL1").ToArray(); - Assert.Single(fl1Utilities); + var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth: 1, count); - var fl2Utilities = assemblyTestData.CleanUtilities.Get("FL2").ToArray(); - Assert.Equal(utilitiesCount, fl2Utilities.Length); - - var sl1Utilities = assemblyTestData.CleanUtilities.Get("SL1").ToArray(); - Assert.Equal(utilitiesCount, sl1Utilities.Length); - - for (var i = 0; i < utilitiesCount; i++) + for (var i = 0; i < count; i++) { - var utilityIds = new[] { fl1Utilities[0].Id, fl2Utilities[i].Id }; + var utilityIds = new[] { utilitiesMatrix[0][0].Id, utilitiesMatrix[^1][i].Id }; var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); - Assert.Single(constructionGraphs); - var fl1ConstructionGraph = constructionGraphs[0][0]; - - Assert.NotNull(fl1Utilities); - Assert.Equal(fl1Utilities[0].Id, fl1ConstructionGraph.Id); - - var sl1ConstructionGraph = Assert.Single(fl1ConstructionGraph.Dependencies); - Assert.NotNull(sl1ConstructionGraph); - Assert.Equal(sl1Utilities[i].Id, sl1ConstructionGraph.Id); - - var fl2ConstructionGraph = constructionGraphs[0][1]; - Assert.NotNull(fl2ConstructionGraph); - Assert.Equal(fl2Utilities[i].Id, fl2ConstructionGraph.Id); - - Assert.Empty(fl2ConstructionGraph.Dependencies); + Assert.Equal(2, constructionGraphs[0].Length); + + var penultConstructionGraph = constructionGraphs[0][0]; + Assert.Equal(utilitiesMatrix[0][0].Id, penultConstructionGraph.Id); + Assert.Single(penultConstructionGraph.Dependencies); + + var qConstructionGraph = constructionGraphs[0][1]; + Assert.Equal(utilitiesMatrix[^1][i].Id, qConstructionGraph.Id); + Assert.Empty(qConstructionGraph.Dependencies); + + var lastConstructionGraph = penultConstructionGraph.Dependencies[0]; + Assert.Equal(utilitiesMatrix[1][i].Id, lastConstructionGraph.Id); + Assert.Empty(lastConstructionGraph.Dependencies); } } [Fact] public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtRootLevel() { - var utilitiesCount = RandomizationHelper.RandomInteger(3, 10); var setup = new EnvironmentSetup("outer_demands_env"); - setup.WithCategory("FL1", 1).WithCategory("FL2", utilitiesCount).WithCategory("SL1", utilitiesCount); - setup.WithRequirements("FL1", 1, "SL1"); + var count = RandomizationHelper.RandomInteger(3, 10); + PrepareForOuterDemandsTesting(setup, depth: 1, count); - for (var i = 1; i <= utilitiesCount; i++) + for (var i = 1; i <= count; i++) { - setup.WithCharacteristics("FL2", i, $"C{i}"); - setup.WithOuterDemands("SL1", i, "FL2", $"D{i}"); + setup.WithCharacteristics("Q", i, $"C{i}"); + setup.WithOuterDemands("N1", i, "Q", $"D{i}"); } var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - var fl1Utilities = assemblyTestData.CleanUtilities.Get("FL1").ToArray(); - Assert.Single(fl1Utilities); - - var fl2Utilities = assemblyTestData.CleanUtilities.Get("FL2").ToArray(); - Assert.Equal(utilitiesCount, fl2Utilities.Length); + var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth: 1, count); - for (var i = 0; i < utilitiesCount; i++) + for (var i = 0; i < count; i++) { - var utilityIds = new[] { fl1Utilities[0].Id, fl2Utilities[i].Id }; + var utilityIds = new[] { utilitiesMatrix[0][0].Id, utilitiesMatrix[^1][i].Id }; var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); - Assert.Empty(constructionGraphs); } } - /// - /// |N0| -> |N1| -> ... -> |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}| - /// -> |Q| - /// - /// N{depth} defines outer demands towards Q - /// [Theory, MemberData(nameof(GetDepthMembers))] public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) { @@ -136,7 +113,6 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - // NOTE: There are depth + 1 `N#` categories and `Q`. var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth, count); var utilityIds = utilitiesMatrix[0].Select(x => x.Id); @@ -145,24 +121,24 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) Assert.Equal(count, constructionGraphs.Length); for (var i = 0; i < count; i++) { - var constructionGraph = constructionGraphs[i][0]; + var analyzedGraph = Assert.Single(constructionGraphs[i]); for (var j = 0; j < depth - 2; j++) { - Assert.Equal(utilitiesMatrix[j][0].Id, constructionGraph.Id); - Assert.Single(constructionGraph.Dependencies); + Assert.Equal(utilitiesMatrix[j][0].Id, analyzedGraph.Id); + Assert.Single(analyzedGraph.Dependencies); - constructionGraph = constructionGraph.Dependencies[0]; + analyzedGraph = analyzedGraph.Dependencies[0]; } - Assert.Equal(utilitiesMatrix[depth - 2][0].Id, constructionGraph.Id); - Assert.Equal(2, constructionGraph.Dependencies.Count); + Assert.Equal(utilitiesMatrix[depth - 2][0].Id, analyzedGraph.Id); + Assert.Equal(2, analyzedGraph.Dependencies.Count); - var penultConstructionGraph = constructionGraph.Dependencies[0]; + var penultConstructionGraph = analyzedGraph.Dependencies[0]; Assert.Equal(utilitiesMatrix[depth - 1][0].Id, penultConstructionGraph.Id); Assert.Single(penultConstructionGraph.Dependencies); - var qConstructionGraph = constructionGraph.Dependencies[1]; + var qConstructionGraph = analyzedGraph.Dependencies[1]; Assert.Equal(utilitiesMatrix[^1][i].Id, qConstructionGraph.Id); Assert.Empty(qConstructionGraph.Dependencies); @@ -171,13 +147,7 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) Assert.Empty(lastConstructionGraph.Dependencies); } } - - /// - /// |N0| -> |N1| -> ... -> |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}| - /// -> |Q| - /// - /// N{depth} defines outer demands towards Q - /// + [Theory, MemberData(nameof(GetDepthMembers))] public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels(int depth) { @@ -216,7 +186,7 @@ private static void PrepareForOuterDemandsTesting(EnvironmentSetup setup, int de } setup.WithCategory($"N{depth}", count).WithCategory("Q", count); - setup.WithRequirements($"N{depth - 2}", 1, "Q"); + if (depth > 1) setup.WithRequirements($"N{depth - 2}", 1, "Q"); } /// From c3438f12575fc778e36e2b53e7c84de222ca0a9c Mon Sep 17 00:00:00 2001 From: Tony Troeff Date: Mon, 10 Feb 2025 00:30:46 +0200 Subject: [PATCH 4/4] Added tests ensuring that outer demands are targetting only the immediate higher hierarchical level. --- .../ConstructionManagerTests.cs | 139 +++++++++++------- 1 file changed, 85 insertions(+), 54 deletions(-) diff --git a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs index 5fcc760..ca5c91a 100644 --- a/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs +++ b/Tests/TryAtSoftware.CleanTests.UnitTests/ConstructionManagerTests.cs @@ -11,8 +11,7 @@ public class ConstructionManagerTests { - [Theory(Timeout = UnitTestConstants.Timeout)] - [MemberData(nameof(GetDependenciesManagerSetups))] + [Theory(Timeout = UnitTestConstants.Timeout), MemberData(nameof(GetDependenciesManagerSetups))] public Task DependencyGraphsShouldBeConstructedSuccessfully(EnvironmentSetup setup, string pathToExpectedResult) { var assemblyTestData = setup.MaterializeAsAssemblyData(); @@ -41,32 +40,32 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtRootLevel() for (var i = 1; i <= count; i++) { - setup.WithCharacteristics("Q", i, $"C{i}"); - setup.WithOuterDemands("N1", i, "Q", $"C{i}"); + setup.WithCharacteristics("Q", i, $"O{i}"); + setup.WithOuterDemands("N1", i, "Q", $"O{i}"); } var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth: 1, count); + var matrix = ExtractMatrixForOuterDemandsTesting(assemblyTestData, depth: 1, count); for (var i = 0; i < count; i++) { - var utilityIds = new[] { utilitiesMatrix[0][0].Id, utilitiesMatrix[^1][i].Id }; + var utilityIds = new[] { matrix[0][0].Id, matrix[^1][i].Id }; var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); Assert.Single(constructionGraphs); Assert.Equal(2, constructionGraphs[0].Length); var penultConstructionGraph = constructionGraphs[0][0]; - Assert.Equal(utilitiesMatrix[0][0].Id, penultConstructionGraph.Id); + Assert.Equal(matrix[0][0].Id, penultConstructionGraph.Id); Assert.Single(penultConstructionGraph.Dependencies); var qConstructionGraph = constructionGraphs[0][1]; - Assert.Equal(utilitiesMatrix[^1][i].Id, qConstructionGraph.Id); + Assert.Equal(matrix[^1][i].Id, qConstructionGraph.Id); Assert.Empty(qConstructionGraph.Dependencies); var lastConstructionGraph = penultConstructionGraph.Dependencies[0]; - Assert.Equal(utilitiesMatrix[1][i].Id, lastConstructionGraph.Id); + Assert.Equal(matrix[1][i].Id, lastConstructionGraph.Id); Assert.Empty(lastConstructionGraph.Dependencies); } } @@ -80,18 +79,18 @@ public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtRootLevel() for (var i = 1; i <= count; i++) { - setup.WithCharacteristics("Q", i, $"C{i}"); - setup.WithOuterDemands("N1", i, "Q", $"D{i}"); + setup.WithCharacteristics("Q", i, $"O{i}"); + setup.WithOuterDemands("N1", i, "Q", $"X{i}"); } var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth: 1, count); + var matrix = ExtractMatrixForOuterDemandsTesting(assemblyTestData, depth: 1, count); for (var i = 0; i < count; i++) { - var utilityIds = new[] { utilitiesMatrix[0][0].Id, utilitiesMatrix[^1][i].Id }; + var utilityIds = new[] { matrix[0][0].Id, matrix[^1][i].Id }; var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); Assert.Empty(constructionGraphs); } @@ -106,50 +105,46 @@ public void OuterDemandsShouldBeAppliedCorrectlyAtDeeperLevels(int depth) for (var i = 1; i <= count; i++) { - setup.WithCharacteristics("Q", i, $"C{i}"); - setup.WithOuterDemands($"N{depth}", i, "Q", $"C{i}"); + setup.WithCharacteristics("Q", i, $"O{i}"); + setup.WithOuterDemands($"N{depth}", i, "Q", $"O{i}"); } var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth, count); + var matrix = ExtractMatrixForOuterDemandsTesting(assemblyTestData, depth, count); + var constructionGraphs = manager.BuildIndividualConstructionGraphs(matrix[0].Select(x => x.Id)); + AssertCorrectConstructionWithOuterDemandsAtDeeperLevels(constructionGraphs, matrix, depth, count); + } - var utilityIds = utilitiesMatrix[0].Select(x => x.Id); - var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); - - Assert.Equal(count, constructionGraphs.Length); - for (var i = 0; i < count; i++) + [Theory, MemberData(nameof(GetDepthMembers))] + public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels(int depth) + { + var setup = new EnvironmentSetup("outer_demands_env"); + var count = RandomizationHelper.RandomInteger(3, 10); + PrepareForOuterDemandsTesting(setup, depth, count); + + for (var i = 1; i <= count; i++) { - var analyzedGraph = Assert.Single(constructionGraphs[i]); + setup.WithCharacteristics("Q", i, $"O{i}"); + setup.WithOuterDemands($"N{depth}", i, "Q", $"X{i}"); + } - for (var j = 0; j < depth - 2; j++) - { - Assert.Equal(utilitiesMatrix[j][0].Id, analyzedGraph.Id); - Assert.Single(analyzedGraph.Dependencies); + var assemblyTestData = setup.MaterializeAsAssemblyData(); + var manager = new ConstructionManager(assemblyTestData); - analyzedGraph = analyzedGraph.Dependencies[0]; - } - - Assert.Equal(utilitiesMatrix[depth - 2][0].Id, analyzedGraph.Id); - Assert.Equal(2, analyzedGraph.Dependencies.Count); - - var penultConstructionGraph = analyzedGraph.Dependencies[0]; - Assert.Equal(utilitiesMatrix[depth - 1][0].Id, penultConstructionGraph.Id); - Assert.Single(penultConstructionGraph.Dependencies); - - var qConstructionGraph = analyzedGraph.Dependencies[1]; - Assert.Equal(utilitiesMatrix[^1][i].Id, qConstructionGraph.Id); - Assert.Empty(qConstructionGraph.Dependencies); - - var lastConstructionGraph = penultConstructionGraph.Dependencies[0]; - Assert.Equal(utilitiesMatrix[depth][i].Id, lastConstructionGraph.Id); - Assert.Empty(lastConstructionGraph.Dependencies); - } + var matrix = ExtractMatrixForOuterDemandsTesting(assemblyTestData, depth, count); + var constructionGraphs = manager.BuildIndividualConstructionGraphs(matrix[0].Select(x => x.Id)); + Assert.Empty(constructionGraphs); } + /// + /// N{depth} defines unsatisfiable outer demands towards N0, N1, ..., N{depth - 2}. + /// These unsatisfiable demands do not impact the construction of individual graphs, + /// as the referenced utilities are not located within the immediate higher hierarchical level. + /// [Theory, MemberData(nameof(GetDepthMembers))] - public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels(int depth) + public void OuterDemandsShouldOnlyTargetTheImmediateHigherLevel(int depth) { var setup = new EnvironmentSetup("outer_demands_env"); var count = RandomizationHelper.RandomInteger(3, 10); @@ -157,22 +152,26 @@ public void UnsatisfiableOuterDemandsShouldBeHandledCorrectlyAtDeeperLevels(int for (var i = 1; i <= count; i++) { - setup.WithCharacteristics("Q", i, $"C{i}"); - setup.WithOuterDemands($"N{depth}", i, "Q", $"D{i}"); + setup.WithCharacteristics("Q", i, $"O{i}"); + setup.WithOuterDemands($"N{depth}", i, "Q", $"O{i}"); + + for (var j = 0; j < depth - 1; j++) + { + setup.WithCharacteristics($"N{j}", 1, $"O{i}"); + setup.WithOuterDemands($"N{depth}", i, $"N{j}", $"X{i}"); + } } var assemblyTestData = setup.MaterializeAsAssemblyData(); var manager = new ConstructionManager(assemblyTestData); - var utilitiesMatrix = ExtractUtilitiesForOuterDemandsTesting(assemblyTestData, depth, count); - - var utilityIds = utilitiesMatrix[0].Select(x => x.Id); - var constructionGraphs = manager.BuildIndividualConstructionGraphs(utilityIds); - Assert.Empty(constructionGraphs); + var matrix = ExtractMatrixForOuterDemandsTesting(assemblyTestData, depth, count); + var constructionGraphs = manager.BuildIndividualConstructionGraphs(matrix[0].Select(x => x.Id)); + AssertCorrectConstructionWithOuterDemandsAtDeeperLevels(constructionGraphs, matrix, depth, count); } /// - /// |N0| -> |N1| -> ... -> |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}|
+ /// |N0| -> |N1| -> ... -> |N{depth - 2}| -> |N{depth - 1}| -> |N{depth}| /// -> |Q| -----------------^ /// /// N{depth} defines outer demands towards Q @@ -194,7 +193,7 @@ private static void PrepareForOuterDemandsTesting(EnvironmentSetup setup, int de /// - The first `depth + 1` entries are reserved for the `N#` categories. /// - The last entry is reserved for the `Q` category. ///
- private static ICleanUtilityDescriptor[][] ExtractUtilitiesForOuterDemandsTesting(CleanTestAssemblyData assemblyTestData, int depth, int count) + private static ICleanUtilityDescriptor[][] ExtractMatrixForOuterDemandsTesting(CleanTestAssemblyData assemblyTestData, int depth, int count) { // NOTE: There are depth + 1 `N#` categories and `Q`. var matrix = new ICleanUtilityDescriptor[depth + 2][]; @@ -207,6 +206,38 @@ private static ICleanUtilityDescriptor[][] ExtractUtilitiesForOuterDemandsTestin return matrix; } + private static void AssertCorrectConstructionWithOuterDemandsAtDeeperLevels(IndividualCleanUtilityConstructionGraph[][] constructionGraphs, ICleanUtilityDescriptor[][] matrix, int depth, int count) + { + Assert.Equal(count, constructionGraphs.Length); + for (var i = 0; i < count; i++) + { + var analyzedGraph = Assert.Single(constructionGraphs[i]); + + for (var j = 0; j < depth - 2; j++) + { + Assert.Equal(matrix[j][0].Id, analyzedGraph.Id); + Assert.Single(analyzedGraph.Dependencies); + + analyzedGraph = analyzedGraph.Dependencies[0]; + } + + Assert.Equal(matrix[depth - 2][0].Id, analyzedGraph.Id); + Assert.Equal(2, analyzedGraph.Dependencies.Count); + + var penultConstructionGraph = analyzedGraph.Dependencies[0]; + Assert.Equal(matrix[depth - 1][0].Id, penultConstructionGraph.Id); + Assert.Single(penultConstructionGraph.Dependencies); + + var qConstructionGraph = analyzedGraph.Dependencies[1]; + Assert.Equal(matrix[^1][i].Id, qConstructionGraph.Id); + Assert.Empty(qConstructionGraph.Dependencies); + + var lastConstructionGraph = penultConstructionGraph.Dependencies[0]; + Assert.Equal(matrix[depth][i].Id, lastConstructionGraph.Id); + Assert.Empty(lastConstructionGraph.Dependencies); + } + } + public static TheoryData GetDependenciesManagerSetups() { var data = new TheoryData();