From 782510813dde8483257fa608d23e3063992347f2 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Mon, 27 Sep 2021 10:30:05 +0200 Subject: [PATCH 01/11] Fix: Duplication in Puml errormessages; Signed-off-by: Stephan Joneleit --- .../Elements/Types/TypeConditionsDefinition.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs index d75ca4f76..c0d0c3679 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs @@ -348,13 +348,24 @@ ConditionResult Condition(TRuleType ruleType) .Concat(classDiagramAssociation.GetTargetNamespaceIdentifiers(ruleType)) .ToList()); + var pass = true; var dynamicFailDescription = "does depend on"; + + //Prevent failDescriptions like "does depend on X and does depend on X and does depend on Y and does depend on Y + var failDescriptionCache = new List(); + foreach (var dependency in ruleType.GetTypeDependencies()) { - if (classDiagramAssociation.Contains(dependency) && !allAllowedTargets.Any(pattern => dependency.FullNameMatches(pattern, true))) + if (classDiagramAssociation.Contains(dependency) + && !allAllowedTargets.Any(pattern => dependency.FullNameMatches(pattern, true))) { - dynamicFailDescription += pass ? " " + dependency.FullName : " and " + dependency.FullName; + if (!failDescriptionCache.Contains(dependency.FullName)) + { + dynamicFailDescription += pass ? " " + dependency.FullName : " and " + dependency.FullName; + failDescriptionCache.Add(dependency.FullName); + } + pass = false; } } From a7846b05273b7eec5a7bbbbed2080521d93cea16 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Wed, 29 Sep 2021 08:07:48 +0200 Subject: [PATCH 02/11] Update: Implemented 'Distict' to filter duplication before interation instead of during iteration; Signed-off-by: Stephan Joneleit --- .../Syntax/Elements/Types/TypeConditionsDefinition.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs index c0d0c3679..ae0018484 100644 --- a/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs +++ b/ArchUnitNET/Fluent/Syntax/Elements/Types/TypeConditionsDefinition.cs @@ -353,18 +353,13 @@ ConditionResult Condition(TRuleType ruleType) var dynamicFailDescription = "does depend on"; //Prevent failDescriptions like "does depend on X and does depend on X and does depend on Y and does depend on Y - var failDescriptionCache = new List(); - - foreach (var dependency in ruleType.GetTypeDependencies()) + var ruleTypeDependencies = ruleType.GetTypeDependencies().GroupBy(p => p.FullName).Select(g => g.First()); + foreach (var dependency in ruleTypeDependencies) { if (classDiagramAssociation.Contains(dependency) && !allAllowedTargets.Any(pattern => dependency.FullNameMatches(pattern, true))) { - if (!failDescriptionCache.Contains(dependency.FullName)) - { - dynamicFailDescription += pass ? " " + dependency.FullName : " and " + dependency.FullName; - failDescriptionCache.Add(dependency.FullName); - } + dynamicFailDescription += pass ? " " + dependency.FullName : " and " + dependency.FullName; pass = false; } From 3db719751bb462f0bbfcb6088828ad6407dabbc7 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Wed, 29 Sep 2021 08:44:07 +0200 Subject: [PATCH 03/11] Add: Test PUML; Signed-off-by: Stephan Joneleit --- ArchUnit.sln | 17 +++++-- ...chUnitNet.MSTest.CheckErrormessages.csproj | 20 ++++++++ .../PlantUMLErrormessagesCheck.cs | 14 ++++++ .../zzz_test_version_with_errors.puml | 50 +++++++++++++++++++ 4 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj create mode 100644 ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs create mode 100644 ExampleTest/Resources/zzz_test_version_with_errors.puml diff --git a/ArchUnit.sln b/ArchUnit.sln index bdb6c6949..961b5e7a5 100644 --- a/ArchUnit.sln +++ b/ArchUnit.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.16 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31702.278 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestAssembly", "TestAssembly\TestAssembly.csproj", "{7DEF5F34-AB86-457B-819D-5E7387B3FF87}" EndProject @@ -17,9 +17,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.NUnit", "ArchUn EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.NUnitTests", "ArchUnitNET.NUnitTests\ArchUnitNET.NUnitTests.csproj", "{D2AB683F-0A64-491E-9C56-EE98588C493C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchUnitNET.MSTestV2", "ArchUnitNET.MSTestV2\ArchUnitNET.MSTestV2.csproj", "{3D057987-358A-41C6-AF55-6490FCA5875F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.MSTestV2", "ArchUnitNET.MSTestV2\ArchUnitNET.MSTestV2.csproj", "{3D057987-358A-41C6-AF55-6490FCA5875F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchUnitNET.MSTestV2Tests", "ArchUnitNET.MSTestV2Tests\ArchUnitNET.MSTestV2Tests.csproj", "{6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.MSTestV2Tests", "ArchUnitNET.MSTestV2Tests\ArchUnitNET.MSTestV2Tests.csproj", "{6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchUnitNet.MSTest.CheckErrormessages", "ArchUnitNet.MSTest.CheckErrormessages\ArchUnitNet.MSTest.CheckErrormessages.csproj", "{1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -63,8 +65,15 @@ Global {6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}.Release|Any CPU.Build.0 = Release|Any CPU + {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4D8045DD-06E3-4ACF-BB1F-54AED4F124E0} + EndGlobalSection EndGlobal diff --git a/ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj b/ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj new file mode 100644 index 000000000..c7263ab6d --- /dev/null +++ b/ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj @@ -0,0 +1,20 @@ + + + + net5.0 + + false + + + + + + + + + + + + + + diff --git a/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs b/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs new file mode 100644 index 000000000..050de096a --- /dev/null +++ b/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs @@ -0,0 +1,14 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ArchUnitNet.MSTest.CheckErrormessages +{ + [TestClass] + public class PlantUMLErrormessagesCheck + { + [TestMethod] + public void StartTest() + { + + } + } +} diff --git a/ExampleTest/Resources/zzz_test_version_with_errors.puml b/ExampleTest/Resources/zzz_test_version_with_errors.puml new file mode 100644 index 000000000..566aaa207 --- /dev/null +++ b/ExampleTest/Resources/zzz_test_version_with_errors.puml @@ -0,0 +1,50 @@ +@startuml + + +' !!! Test Version !!! +' This PlantUML Diagram will cause errors when you run the ArchUnitNet PLantUML Test +' It is made to check the errormessages that you will get when the codebase architecture does not match the architecture of the PUML +' Unlogical or wrong dependencies are made on purpose + +skinparam componentStyle uml2 +skinparam component { + BorderColor #grey + BackgroundColor #white +} + +[Addresses] <> +[Customers] <> +[Orders] <> +[Products] <> +[Product Catalog] <> as catalog +[Product Import] <> as import + +' Could be some random comment +[XML] <> <> as xml + +'Causes Error +[Addresses] <-[#blue]- catalog + +'Causes Error +[Orders] <-[#blue]- [Customers] : is placed by +[Orders] --> [Products] +[Orders] --> [Addresses] + +'Causes Error +[Customers] <-[#blue]- [Addresses] +[Customers] --> [Products] + + +[Products] <--[#green]- catalog + +'Causes Error +catalog <-[#blue]- [Orders] + +import -left-> catalog : parse products +import --> xml +'Causes Error +import <-[#blue]- [Customers] + +note top on link #lightgreen: is responsible for translating XML to csharp classes + +@enduml \ No newline at end of file From 8bc0147c823c0d0d2e13d25380aed0de210e0db0 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Wed, 29 Sep 2021 11:53:04 +0200 Subject: [PATCH 04/11] Add: Test to check for duplications in errormessages; Remarks: I'm sorry but I was only able to run the test with an empty global.json file; Signed-off-by: Stephan Joneleit --- .../PlantUMLErrormessagesCheck.cs | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs b/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs index 050de096a..59499705f 100644 --- a/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs +++ b/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs @@ -1,14 +1,151 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using ArchUnitNET.Domain; +using ArchUnitNET.Fluent; +using ArchUnitNET.Loader; +using ArchUnitNET.xUnit; +using ExampleTest.PlantUml.Addresses; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; +using static ArchUnitNET.Fluent.ArchRuleDefinition; +using System.IO; +using System.Linq; +using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; + namespace ArchUnitNet.MSTest.CheckErrormessages { [TestClass] public class PlantUMLErrormessagesCheck { + public PlantUMLErrormessagesCheck() + { + string exeLocation = Directory.GetCurrentDirectory(); + string[] paths = exeLocation.Split("ArchUnitNet.MSTest.CheckErrormessages"); + Filename = Path.Combine(paths[0], "ExampleTest", "Resources" , "zzz_test_version_with_errors.puml"); + } + + private static readonly Architecture Architecture = + new ArchLoader().LoadNamespacesWithinAssembly(typeof(Address).Assembly, "ExampleTest.PlantUml").Build(); + + private static string Filename { get; set; } + + [TestMethod] public void StartTest() { + CheckByPuml(out string rawErrormessage); + //CheckForDuplications returns false when errormessage contains no duplications + bool isDuplications = !CheckForDuplications(rawErrormessage, out string explainErrormessage); + + string errormessage = "\nOriginal (ArchUnitNet) Exception:\n" + rawErrormessage + + "\n\nExplained Error:\n" + explainErrormessage + "\n"; + + Assert.IsTrue(isDuplications, errormessage); + } + + public bool CheckByPuml(out string errormessage) + { + errormessage = null; + + try + { + IArchRule adhereToPlantUmlDiagram = Types().Should().AdhereToPlantUmlDiagram(Filename); + adhereToPlantUmlDiagram.Check(Architecture); + } + //xUnit + catch (FailedArchRuleException xUFAREx) + { + errormessage = xUFAREx.Message; + + return false; + } + + return true; + } + + public bool CheckForDuplications(string uncutMessage, out string errormessage) + { + bool isDuplications = false; + errormessage = null; + StringBuilder message = new(); + + string[] errors = uncutMessage.Split('\n'); + + if (CheckGroupsForDuplications(String.Empty, errors, out errors, out errormessage)) + { + isDuplications = true; + message.Append(errormessage); + } + + foreach (string error in errors) + { + if (!String.IsNullOrWhiteSpace(error)) + { + string[] ands = error.Split("and"); + string[] veryFirstError = ands[0].Split("does depend on"); + string firstError = veryFirstError.Length == 2 ? veryFirstError[1] : String.Empty; + + if (CheckGroupsForDuplications(firstError, ands, out ands, out errormessage)) + { + isDuplications = true; + message.Append(errormessage); + } + } + } + + errormessage = message.ToString(); + if (String.IsNullOrWhiteSpace(errormessage)) + { + errormessage = "\nNo Errors\n"; + } + + + return isDuplications; + } + + public bool CheckGroupsForDuplications(string firstError, string[] splittedMessages, + out string[] filteredMessages, out string errormessage) + { + errormessage = null; + + var groups = splittedMessages.GroupBy(x => x.Trim().Trim('\t')); + var duplications = groups.Where(x => (x.Count() > 1 + && !String.IsNullOrWhiteSpace(x.FirstOrDefault())) + || firstError.Contains(x.FirstOrDefault())); + + //Checks if any group contains multiple elements + //true if it contains any duplications + bool isGroupsDuplications = duplications.Count() != 0; + + if (isGroupsDuplications) + { + errormessage = GetErrormessage(firstError, splittedMessages, duplications); + } + + filteredMessages = groups.Select(x => x.First().Trim().Trim('\t')).ToArray(); + + return isGroupsDuplications; + } + + public string GetErrormessage(string firstError, string[] originalArray, IEnumerable> duplications) + { + StringBuilder errormessage = new(); + + var array = originalArray.Select(x => "\nand " + x + " "); + errormessage.Append("\nMessage:\n" + String.Concat(array) + "\ncontains the following duplications:\n"); + + foreach (var duplication in duplications) + { + string duplicate = duplication.First(); + int count = duplication.Count(); + int duplicateCount = firstError.Contains(duplicate) ? ++count : count; + errormessage.Append("Text: " + duplicate + + "\nNumber of duplications: " + duplicateCount + "\n"); + } + return errormessage.ToString(); } } } From d63c296051cfd2f97563938cffe755270e703332 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Wed, 29 Sep 2021 13:54:53 +0200 Subject: [PATCH 05/11] Fix: Changes in the solution file; Fix: Unsupported SDK in global.json -> SDK Version 5.0.203 cannot be downloaded on the official dotnet download page (minimun 5.0.202 which is unfortunally not 5.0.203), that's why I included rollForward; Signed-off-by: Stephan Joneleit --- ArchUnit.sln | 4 ++-- global.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ArchUnit.sln b/ArchUnit.sln index 961b5e7a5..cda3ade06 100644 --- a/ArchUnit.sln +++ b/ArchUnit.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31702.278 +# Visual Studio Version 15 +VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestAssembly", "TestAssembly\TestAssembly.csproj", "{7DEF5F34-AB86-457B-819D-5E7387B3FF87}" EndProject diff --git a/global.json b/global.json index e43fedd23..a7a86e44a 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "5.0.203" + "version": "5.0.203", + "rollForward": "feature" } } \ No newline at end of file From c958bc4880ba8dfb9ca81f5b83b8ce2da36e0d35 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Wed, 29 Sep 2021 14:06:48 +0200 Subject: [PATCH 06/11] Updated: Changed version to nexr lower version that is downloadable on the .NET Website because the Bot "Travis CI" failed (maybe due different SDK Versions); Signed-off-by: Stephan Joneleit --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index a7a86e44a..bccd9613d 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "5.0.203", + "version": "5.0.202", "rollForward": "feature" } } \ No newline at end of file From f60ddd589a8447433f092e29c0b3d5c43214c267 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Wed, 29 Sep 2021 14:12:55 +0200 Subject: [PATCH 07/11] Update: global.json (again) -> found SDK Version 5.0.203; Signed-off-by: Stephan Joneleit --- global.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/global.json b/global.json index bccd9613d..4dab0595c 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,5 @@ { "sdk": { - "version": "5.0.202", - "rollForward": "feature" + "version": "5.0.203" } } \ No newline at end of file From 65948785cb0ddef042476b15b43fc9db7d8f9188 Mon Sep 17 00:00:00 2001 From: Stephan Joneleit Date: Mon, 4 Oct 2021 08:12:47 +0200 Subject: [PATCH 08/11] Update: Improved Where Condition; Signed-off-by: Stephan Joneleit --- .../PlantUMLErrormessagesCheck.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs b/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs index 59499705f..a581ff4ab 100644 --- a/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs +++ b/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs @@ -111,9 +111,9 @@ public bool CheckGroupsForDuplications(string firstError, string[] splittedMessa errormessage = null; var groups = splittedMessages.GroupBy(x => x.Trim().Trim('\t')); - var duplications = groups.Where(x => (x.Count() > 1 - && !String.IsNullOrWhiteSpace(x.FirstOrDefault())) - || firstError.Contains(x.FirstOrDefault())); + var duplications = groups.Where(x => !String.IsNullOrWhiteSpace(x.FirstOrDefault()) + && (x.Count() > 1 || firstError.Contains(x.First()))); + //Checks if any group contains multiple elements //true if it contains any duplications From 55c3985fbb723d342691d02c2808ab589c8052c0 Mon Sep 17 00:00:00 2001 From: Fritz Brandhuber Date: Mon, 4 Oct 2021 15:50:35 +0200 Subject: [PATCH 09/11] move the test class to the ArchUnitNETTests assembly (all tests for ArchUnitNET should be in there) copy the classes for the PlantUML diagram to the TestAssembly (ExampleTests should only be used for examples and not for testing purposes) Signed-off-by: Fritz Brandhuber --- ArchUnit.sln | 6 - ArchUnitNETTests/ArchUnitNETTests.csproj | 16 +- .../PlantUml/PlantUmlErrorMessagesCheck.cs | 145 +++++++++++++++++ .../zzz_test_version_with_errors.puml | 14 +- .../PlantUMLErrormessagesCheck.cs | 151 ------------------ TestAssembly/PlantUml/Addresses/Address.cs | 11 ++ .../PlantUml/Catalog/ProductCatalog.cs | 22 +++ TestAssembly/PlantUml/Customers/Customer.cs | 15 ++ .../PlantUml/Importer/ProductImport.cs | 21 +++ TestAssembly/PlantUml/Orders/Order.cs | 31 ++++ TestAssembly/PlantUml/Products/Product.cs | 21 +++ .../PlantUml/Xml/Processor/XmlProcessor.cs | 6 + TestAssembly/PlantUml/Xml/Types/XmlTypes.cs | 6 + TestAssembly/PlantUml/Xml/Utils/XmlUtils.cs | 6 + 14 files changed, 302 insertions(+), 169 deletions(-) create mode 100644 ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs rename {ExampleTest/Resources => ArchUnitNETTests/Domain/PlantUml}/zzz_test_version_with_errors.puml (69%) delete mode 100644 ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs create mode 100644 TestAssembly/PlantUml/Addresses/Address.cs create mode 100644 TestAssembly/PlantUml/Catalog/ProductCatalog.cs create mode 100644 TestAssembly/PlantUml/Customers/Customer.cs create mode 100644 TestAssembly/PlantUml/Importer/ProductImport.cs create mode 100644 TestAssembly/PlantUml/Orders/Order.cs create mode 100644 TestAssembly/PlantUml/Products/Product.cs create mode 100644 TestAssembly/PlantUml/Xml/Processor/XmlProcessor.cs create mode 100644 TestAssembly/PlantUml/Xml/Types/XmlTypes.cs create mode 100644 TestAssembly/PlantUml/Xml/Utils/XmlUtils.cs diff --git a/ArchUnit.sln b/ArchUnit.sln index cda3ade06..943da55e4 100644 --- a/ArchUnit.sln +++ b/ArchUnit.sln @@ -21,8 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.MSTestV2", "Arc EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.MSTestV2Tests", "ArchUnitNET.MSTestV2Tests\ArchUnitNET.MSTestV2Tests.csproj", "{6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchUnitNet.MSTest.CheckErrormessages", "ArchUnitNet.MSTest.CheckErrormessages\ArchUnitNet.MSTest.CheckErrormessages.csproj", "{1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,10 +63,6 @@ Global {6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}.Release|Any CPU.Build.0 = Release|Any CPU - {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1AB84ED6-92CD-4B03-ACB1-BD04E6CABAED}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ArchUnitNETTests/ArchUnitNETTests.csproj b/ArchUnitNETTests/ArchUnitNETTests.csproj index 4ac977511..fce6557f1 100644 --- a/ArchUnitNETTests/ArchUnitNETTests.csproj +++ b/ArchUnitNETTests/ArchUnitNETTests.csproj @@ -8,14 +8,20 @@ - - + + - - - + + + + + + + + PreserveNewest + diff --git a/ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs b/ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs new file mode 100644 index 000000000..cc55ababf --- /dev/null +++ b/ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using ArchUnitNET.Domain; +using ArchUnitNET.Fluent; +using ArchUnitNET.xUnit; +using Xunit; +using static ArchUnitNET.Fluent.ArchRuleDefinition; + +namespace ArchUnitNETTests.Domain.PlantUml +{ + public class PlantUmlErrorMessagesCheck + { + public PlantUmlErrorMessagesCheck() + { + Filename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Domain", "PlantUml", + "zzz_test_version_with_errors.puml"); + } + + private static readonly Architecture Architecture = StaticTestArchitectures.ArchUnitNETTestAssemblyArchitecture; + + private static string Filename { get; set; } + + + [Fact] + public void NoDuplicatesInErrorMessageTest() + { + var testPassed = CheckByPuml(out var rawErrormessage); + Assert.False(testPassed); + + //CheckForDuplications returns false when errormessage contains no duplications + var isDuplications = !CheckForDuplications(rawErrormessage, out var explainErrormessage); + + var errormessage = "\nOriginal (ArchUnitNet) Exception:\n" + rawErrormessage + + "\n\nExplained Error:\n" + explainErrormessage + "\n"; + + Assert.False(isDuplications, errormessage); + } + + private static bool CheckByPuml(out string errormessage) + { + errormessage = null; + + try + { + IArchRule adhereToPlantUmlDiagram = Types().Should().AdhereToPlantUmlDiagram(Filename); + adhereToPlantUmlDiagram.Check(Architecture); + } + //xUnit + catch (FailedArchRuleException exception) + { + errormessage = exception.Message; + + return false; + } + + return true; + } + + private bool CheckForDuplications(string uncutMessage, out string errormessage) + { + var isDuplications = false; + errormessage = null; + var message = new StringBuilder(); + + var errors = uncutMessage.Split('\n'); + + if (CheckGroupsForDuplications(string.Empty, errors, out errors, out errormessage)) + { + isDuplications = true; + message.Append(errormessage); + } + + foreach (var error in errors) + { + if (!string.IsNullOrWhiteSpace(error)) + { + var ands = error.Split("and"); + var veryFirstError = ands[0].Split("does depend on"); + var firstError = veryFirstError.Length == 2 ? veryFirstError[1] : string.Empty; + + if (CheckGroupsForDuplications(firstError, ands, out ands, out errormessage)) + { + isDuplications = true; + message.Append(errormessage); + } + } + } + + errormessage = message.ToString(); + if (string.IsNullOrWhiteSpace(errormessage)) + { + errormessage = "\nNo Errors\n"; + } + + + return isDuplications; + } + + private static bool CheckGroupsForDuplications(string firstError, string[] splitMessages, + out string[] filteredMessages, out string errormessage) + { + errormessage = null; + + var groups = splitMessages.GroupBy(x => x.Trim().Trim('\t')); + var duplications = groups.Where(x => !string.IsNullOrWhiteSpace(x.FirstOrDefault()) + && (x.Count() > 1 || firstError.Contains(x.First()))); + + //Checks if any group contains multiple elements + //true if it contains any duplications + var isGroupsDuplications = duplications.Count() != 0; + + if (isGroupsDuplications) + { + errormessage = GetErrormessage(firstError, splitMessages, duplications); + } + + filteredMessages = groups.Select(x => x.First().Trim().Trim('\t')).ToArray(); + + return isGroupsDuplications; + } + + private static string GetErrormessage(string firstError, IEnumerable originalArray, + IEnumerable> duplications) + { + var errormessage = new StringBuilder(); + + var array = originalArray.Select(x => "\nand " + x + " "); + errormessage.Append("\nMessage:\n" + string.Concat(array) + "\ncontains the following duplications:\n"); + + foreach (var duplication in duplications) + { + var duplicate = duplication.First(); + var count = duplication.Count(); + var duplicateCount = firstError.Contains(duplicate) ? ++count : count; + errormessage.Append("Text: " + duplicate + + "\nNumber of duplications: " + duplicateCount + "\n"); + } + + return errormessage.ToString(); + } + } +} \ No newline at end of file diff --git a/ExampleTest/Resources/zzz_test_version_with_errors.puml b/ArchUnitNETTests/Domain/PlantUml/zzz_test_version_with_errors.puml similarity index 69% rename from ExampleTest/Resources/zzz_test_version_with_errors.puml rename to ArchUnitNETTests/Domain/PlantUml/zzz_test_version_with_errors.puml index 566aaa207..f585911e7 100644 --- a/ExampleTest/Resources/zzz_test_version_with_errors.puml +++ b/ArchUnitNETTests/Domain/PlantUml/zzz_test_version_with_errors.puml @@ -12,15 +12,15 @@ skinparam component { BackgroundColor #white } -[Addresses] <> -[Customers] <> -[Orders] <> -[Products] <> -[Product Catalog] <> as catalog -[Product Import] <> as import +[Addresses] <> +[Customers] <> +[Orders] <> +[Products] <> +[Product Catalog] <> as catalog +[Product Import] <> as import ' Could be some random comment -[XML] <> <> as xml +[XML] <> <> as xml 'Causes Error [Addresses] <-[#blue]- catalog diff --git a/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs b/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs deleted file mode 100644 index 59499705f..000000000 --- a/ArchUnitNet.MSTest.CheckErrormessages/PlantUMLErrormessagesCheck.cs +++ /dev/null @@ -1,151 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - -using ArchUnitNET.Domain; -using ArchUnitNET.Fluent; -using ArchUnitNET.Loader; -using ArchUnitNET.xUnit; -using ExampleTest.PlantUml.Addresses; -using System; -using System.Collections.Generic; -using System.Text; -using Xunit; -using static ArchUnitNET.Fluent.ArchRuleDefinition; -using System.IO; -using System.Linq; -using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; - -namespace ArchUnitNet.MSTest.CheckErrormessages -{ - [TestClass] - public class PlantUMLErrormessagesCheck - { - public PlantUMLErrormessagesCheck() - { - string exeLocation = Directory.GetCurrentDirectory(); - string[] paths = exeLocation.Split("ArchUnitNet.MSTest.CheckErrormessages"); - Filename = Path.Combine(paths[0], "ExampleTest", "Resources" , "zzz_test_version_with_errors.puml"); - } - - private static readonly Architecture Architecture = - new ArchLoader().LoadNamespacesWithinAssembly(typeof(Address).Assembly, "ExampleTest.PlantUml").Build(); - - private static string Filename { get; set; } - - - [TestMethod] - public void StartTest() - { - CheckByPuml(out string rawErrormessage); - //CheckForDuplications returns false when errormessage contains no duplications - bool isDuplications = !CheckForDuplications(rawErrormessage, out string explainErrormessage); - - string errormessage = "\nOriginal (ArchUnitNet) Exception:\n" + rawErrormessage + - "\n\nExplained Error:\n" + explainErrormessage + "\n"; - - Assert.IsTrue(isDuplications, errormessage); - } - - public bool CheckByPuml(out string errormessage) - { - errormessage = null; - - try - { - IArchRule adhereToPlantUmlDiagram = Types().Should().AdhereToPlantUmlDiagram(Filename); - adhereToPlantUmlDiagram.Check(Architecture); - } - //xUnit - catch (FailedArchRuleException xUFAREx) - { - errormessage = xUFAREx.Message; - - return false; - } - - return true; - } - - public bool CheckForDuplications(string uncutMessage, out string errormessage) - { - bool isDuplications = false; - errormessage = null; - StringBuilder message = new(); - - string[] errors = uncutMessage.Split('\n'); - - if (CheckGroupsForDuplications(String.Empty, errors, out errors, out errormessage)) - { - isDuplications = true; - message.Append(errormessage); - } - - foreach (string error in errors) - { - if (!String.IsNullOrWhiteSpace(error)) - { - string[] ands = error.Split("and"); - string[] veryFirstError = ands[0].Split("does depend on"); - string firstError = veryFirstError.Length == 2 ? veryFirstError[1] : String.Empty; - - if (CheckGroupsForDuplications(firstError, ands, out ands, out errormessage)) - { - isDuplications = true; - message.Append(errormessage); - } - } - } - - errormessage = message.ToString(); - if (String.IsNullOrWhiteSpace(errormessage)) - { - errormessage = "\nNo Errors\n"; - } - - - return isDuplications; - } - - public bool CheckGroupsForDuplications(string firstError, string[] splittedMessages, - out string[] filteredMessages, out string errormessage) - { - errormessage = null; - - var groups = splittedMessages.GroupBy(x => x.Trim().Trim('\t')); - var duplications = groups.Where(x => (x.Count() > 1 - && !String.IsNullOrWhiteSpace(x.FirstOrDefault())) - || firstError.Contains(x.FirstOrDefault())); - - //Checks if any group contains multiple elements - //true if it contains any duplications - bool isGroupsDuplications = duplications.Count() != 0; - - if (isGroupsDuplications) - { - errormessage = GetErrormessage(firstError, splittedMessages, duplications); - } - - filteredMessages = groups.Select(x => x.First().Trim().Trim('\t')).ToArray(); - - return isGroupsDuplications; - } - - public string GetErrormessage(string firstError, string[] originalArray, IEnumerable> duplications) - { - StringBuilder errormessage = new(); - - var array = originalArray.Select(x => "\nand " + x + " "); - errormessage.Append("\nMessage:\n" + String.Concat(array) + "\ncontains the following duplications:\n"); - - foreach (var duplication in duplications) - { - string duplicate = duplication.First(); - int count = duplication.Count(); - int duplicateCount = firstError.Contains(duplicate) ? ++count : count; - errormessage.Append("Text: " + duplicate + - "\nNumber of duplications: " + duplicateCount + "\n"); - } - - return errormessage.ToString(); - } - } -} diff --git a/TestAssembly/PlantUml/Addresses/Address.cs b/TestAssembly/PlantUml/Addresses/Address.cs new file mode 100644 index 000000000..4db7a327b --- /dev/null +++ b/TestAssembly/PlantUml/Addresses/Address.cs @@ -0,0 +1,11 @@ +using TestAssembly.PlantUml.Catalog; + +namespace TestAssembly.PlantUml.Addresses +{ + public class Address + { +#pragma warning disable CS0169 + private ProductCatalog productCatalog; +#pragma warning restore CS0169 + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Catalog/ProductCatalog.cs b/TestAssembly/PlantUml/Catalog/ProductCatalog.cs new file mode 100644 index 000000000..56642c9de --- /dev/null +++ b/TestAssembly/PlantUml/Catalog/ProductCatalog.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using TestAssembly.PlantUml.Orders; +using TestAssembly.PlantUml.Products; + +namespace TestAssembly.PlantUml.Catalog +{ + public class ProductCatalog + { + private readonly List _allProducts = new List(); + + internal void GonnaDoSomethingIllegalWithOrder() + { + var order = new Order(); + foreach (var product in _allProducts) + { + product.Register(); + } + + order.AddProducts(_allProducts); + } + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Customers/Customer.cs b/TestAssembly/PlantUml/Customers/Customer.cs new file mode 100644 index 000000000..efd00e015 --- /dev/null +++ b/TestAssembly/PlantUml/Customers/Customer.cs @@ -0,0 +1,15 @@ +using TestAssembly.PlantUml.Addresses; +using TestAssembly.PlantUml.Orders; + +namespace TestAssembly.PlantUml.Customers +{ + public class Customer + { + public Address Address { get; set; } + + internal void AddOrder(Order order) + { + // simply having such a parameter violates the specified UML diagram + } + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Importer/ProductImport.cs b/TestAssembly/PlantUml/Importer/ProductImport.cs new file mode 100644 index 000000000..16f19d413 --- /dev/null +++ b/TestAssembly/PlantUml/Importer/ProductImport.cs @@ -0,0 +1,21 @@ +using TestAssembly.PlantUml.Catalog; +using TestAssembly.PlantUml.Customers; +using TestAssembly.PlantUml.Xml.Processor; +using TestAssembly.PlantUml.Xml.Types; + +namespace TestAssembly.PlantUml.Importer +{ + public class ProductImport + { + public ProductCatalog productCatalog; + public XmlTypes xmlType; + public XmlProcessor xmlProcessor; + + public Customer Customer => new Customer(); // violates diagram -> product import may not directly know Customer + + private ProductCatalog Parse(byte[] xml) + { + return new ProductCatalog(); + } + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Orders/Order.cs b/TestAssembly/PlantUml/Orders/Order.cs new file mode 100644 index 000000000..f13a0bf16 --- /dev/null +++ b/TestAssembly/PlantUml/Orders/Order.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using TestAssembly.PlantUml.Addresses; +using TestAssembly.PlantUml.Customers; +using TestAssembly.PlantUml.Products; + +namespace TestAssembly.PlantUml.Orders +{ + public class Order + { + public Customer _customer; + private readonly List _products = new List(); + + public void AddProducts(IList products) + { + _products.AddRange(products); + } + + internal void Report() + { + Report(_customer.Address); + foreach (var product in _products) + { + product.Report(); + } + } + + private void Report(Address address) + { + } + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Products/Product.cs b/TestAssembly/PlantUml/Products/Product.cs new file mode 100644 index 000000000..1a8074e1a --- /dev/null +++ b/TestAssembly/PlantUml/Products/Product.cs @@ -0,0 +1,21 @@ +using TestAssembly.PlantUml.Customers; +using TestAssembly.PlantUml.Orders; + +namespace TestAssembly.PlantUml.Products +{ + public class Product + { + public Customer _customer; + + internal Order Order => null; // the return type violates the specified UML diagram + + + public void Register() + { + } + + public void Report() + { + } + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Xml/Processor/XmlProcessor.cs b/TestAssembly/PlantUml/Xml/Processor/XmlProcessor.cs new file mode 100644 index 000000000..d3a3648dc --- /dev/null +++ b/TestAssembly/PlantUml/Xml/Processor/XmlProcessor.cs @@ -0,0 +1,6 @@ +namespace TestAssembly.PlantUml.Xml.Processor +{ + public class XmlProcessor + { + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Xml/Types/XmlTypes.cs b/TestAssembly/PlantUml/Xml/Types/XmlTypes.cs new file mode 100644 index 000000000..8575a8ce5 --- /dev/null +++ b/TestAssembly/PlantUml/Xml/Types/XmlTypes.cs @@ -0,0 +1,6 @@ +namespace TestAssembly.PlantUml.Xml.Types +{ + public class XmlTypes + { + } +} \ No newline at end of file diff --git a/TestAssembly/PlantUml/Xml/Utils/XmlUtils.cs b/TestAssembly/PlantUml/Xml/Utils/XmlUtils.cs new file mode 100644 index 000000000..6ce6f4988 --- /dev/null +++ b/TestAssembly/PlantUml/Xml/Utils/XmlUtils.cs @@ -0,0 +1,6 @@ +namespace TestAssembly.PlantUml.Xml.Utils +{ + public class XmlUtils + { + } +} \ No newline at end of file From 32a1994feff6dedc6deeead0e6349ef5d191f4aa Mon Sep 17 00:00:00 2001 From: Fritz Brandhuber Date: Mon, 4 Oct 2021 16:18:21 +0200 Subject: [PATCH 10/11] simplify the test for better readability Signed-off-by: Fritz Brandhuber --- .../PlantUml/PlantUmlErrorMessagesCheck.cs | 117 +++++------------- 1 file changed, 33 insertions(+), 84 deletions(-) diff --git a/ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs b/ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs index cc55ababf..787d4c372 100644 --- a/ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs +++ b/ArchUnitNETTests/Domain/PlantUml/PlantUmlErrorMessagesCheck.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using ArchUnitNET.Domain; using ArchUnitNET.Fluent; using ArchUnitNET.xUnit; @@ -13,39 +12,37 @@ namespace ArchUnitNETTests.Domain.PlantUml { public class PlantUmlErrorMessagesCheck { + private static readonly Architecture Architecture = StaticTestArchitectures.ArchUnitNETTestAssemblyArchitecture; + private readonly string _umlFile; + public PlantUmlErrorMessagesCheck() { - Filename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Domain", "PlantUml", + _umlFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Domain", "PlantUml", "zzz_test_version_with_errors.puml"); } - private static readonly Architecture Architecture = StaticTestArchitectures.ArchUnitNETTestAssemblyArchitecture; - - private static string Filename { get; set; } - - [Fact] public void NoDuplicatesInErrorMessageTest() { var testPassed = CheckByPuml(out var rawErrormessage); Assert.False(testPassed); - //CheckForDuplications returns false when errormessage contains no duplications - var isDuplications = !CheckForDuplications(rawErrormessage, out var explainErrormessage); + //CheckForDuplicates returns false when errormessage contains duplicates or is empty + var containsNoDuplicates = ContainsNoDuplicates(rawErrormessage, out var explainErrormessage); var errormessage = "\nOriginal (ArchUnitNet) Exception:\n" + rawErrormessage + - "\n\nExplained Error:\n" + explainErrormessage + "\n"; + "\n\nAssert Error:\n" + explainErrormessage + "\n"; - Assert.False(isDuplications, errormessage); + Assert.True(containsNoDuplicates, errormessage); } - private static bool CheckByPuml(out string errormessage) + private bool CheckByPuml(out string errormessage) { errormessage = null; try { - IArchRule adhereToPlantUmlDiagram = Types().Should().AdhereToPlantUmlDiagram(Filename); + IArchRule adhereToPlantUmlDiagram = Types().Should().AdhereToPlantUmlDiagram(_umlFile); adhereToPlantUmlDiagram.Check(Architecture); } //xUnit @@ -59,87 +56,39 @@ private static bool CheckByPuml(out string errormessage) return true; } - private bool CheckForDuplications(string uncutMessage, out string errormessage) + private static bool ContainsNoDuplicates(string uncutMessage, out string errormessage) { - var isDuplications = false; - errormessage = null; - var message = new StringBuilder(); - - var errors = uncutMessage.Split('\n'); - - if (CheckGroupsForDuplications(string.Empty, errors, out errors, out errormessage)) + if (string.IsNullOrWhiteSpace(uncutMessage)) { - isDuplications = true; - message.Append(errormessage); - } - - foreach (var error in errors) - { - if (!string.IsNullOrWhiteSpace(error)) - { - var ands = error.Split("and"); - var veryFirstError = ands[0].Split("does depend on"); - var firstError = veryFirstError.Length == 2 ? veryFirstError[1] : string.Empty; - - if (CheckGroupsForDuplications(firstError, ands, out ands, out errormessage)) - { - isDuplications = true; - message.Append(errormessage); - } - } - } - - errormessage = message.ToString(); - if (string.IsNullOrWhiteSpace(errormessage)) - { - errormessage = "\nNo Errors\n"; + errormessage = "Error message is empty."; + return false; } + var sources = new List(); - return isDuplications; - } + var errors = uncutMessage.Split('\n').Skip(1); - private static bool CheckGroupsForDuplications(string firstError, string[] splitMessages, - out string[] filteredMessages, out string errormessage) - { - errormessage = null; - - var groups = splitMessages.GroupBy(x => x.Trim().Trim('\t')); - var duplications = groups.Where(x => !string.IsNullOrWhiteSpace(x.FirstOrDefault()) - && (x.Count() > 1 || firstError.Contains(x.First()))); - - //Checks if any group contains multiple elements - //true if it contains any duplications - var isGroupsDuplications = duplications.Count() != 0; - - if (isGroupsDuplications) + foreach (var error in errors.Where(e => !string.IsNullOrWhiteSpace(e))) { - errormessage = GetErrormessage(firstError, splitMessages, duplications); - } - - filteredMessages = groups.Select(x => x.First().Trim().Trim('\t')).ToArray(); - - return isGroupsDuplications; - } - - private static string GetErrormessage(string firstError, IEnumerable originalArray, - IEnumerable> duplications) - { - var errormessage = new StringBuilder(); - - var array = originalArray.Select(x => "\nand " + x + " "); - errormessage.Append("\nMessage:\n" + string.Concat(array) + "\ncontains the following duplications:\n"); + var splitError = error.Split(" does depend on "); + var source = splitError[0].Trim(); + var targets = splitError[1].Trim().Split(" and "); + if (sources.Contains(source)) + { + errormessage = $"Two errors with {source} as source found."; + return false; + } - foreach (var duplication in duplications) - { - var duplicate = duplication.First(); - var count = duplication.Count(); - var duplicateCount = firstError.Contains(duplicate) ? ++count : count; - errormessage.Append("Text: " + duplicate + - "\nNumber of duplications: " + duplicateCount + "\n"); + sources.Add(source); + if (targets.Distinct().Count() < targets.Length) + { + errormessage = $"The error \"{error}\" contains duplicate targets."; + return false; + } } - return errormessage.ToString(); + errormessage = "No duplicates found."; + return true; } } } \ No newline at end of file From 7f9d306a5d058acf6ec0d9adeecfd00cc0b508ab Mon Sep 17 00:00:00 2001 From: Fritz Brandhuber Date: Mon, 4 Oct 2021 16:26:33 +0200 Subject: [PATCH 11/11] remove the MSTest csproj file and revert some small changes Signed-off-by: Fritz Brandhuber --- ArchUnit.sln | 9 +++------ ...chUnitNet.MSTest.CheckErrormessages.csproj | 20 ------------------- global.json | 2 +- 3 files changed, 4 insertions(+), 27 deletions(-) delete mode 100644 ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj diff --git a/ArchUnit.sln b/ArchUnit.sln index 943da55e4..bdb6c6949 100644 --- a/ArchUnit.sln +++ b/ArchUnit.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 15 +# Visual Studio 15 VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestAssembly", "TestAssembly\TestAssembly.csproj", "{7DEF5F34-AB86-457B-819D-5E7387B3FF87}" @@ -17,9 +17,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.NUnit", "ArchUn EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.NUnitTests", "ArchUnitNET.NUnitTests\ArchUnitNET.NUnitTests.csproj", "{D2AB683F-0A64-491E-9C56-EE98588C493C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.MSTestV2", "ArchUnitNET.MSTestV2\ArchUnitNET.MSTestV2.csproj", "{3D057987-358A-41C6-AF55-6490FCA5875F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchUnitNET.MSTestV2", "ArchUnitNET.MSTestV2\ArchUnitNET.MSTestV2.csproj", "{3D057987-358A-41C6-AF55-6490FCA5875F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchUnitNET.MSTestV2Tests", "ArchUnitNET.MSTestV2Tests\ArchUnitNET.MSTestV2Tests.csproj", "{6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchUnitNET.MSTestV2Tests", "ArchUnitNET.MSTestV2Tests\ArchUnitNET.MSTestV2Tests.csproj", "{6D6B6EFE-DA0B-4C4D-B710-FA658F0C68CF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -67,7 +67,4 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4D8045DD-06E3-4ACF-BB1F-54AED4F124E0} - EndGlobalSection EndGlobal diff --git a/ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj b/ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj deleted file mode 100644 index c7263ab6d..000000000 --- a/ArchUnitNet.MSTest.CheckErrormessages/ArchUnitNet.MSTest.CheckErrormessages.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net5.0 - - false - - - - - - - - - - - - - - diff --git a/global.json b/global.json index 4dab0595c..e43fedd23 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "5.0.203" + "version": "5.0.203" } } \ No newline at end of file