From 7b1f67a57e0d6a7baa40fb1b080b821e0620442c Mon Sep 17 00:00:00 2001 From: "Daum Alexander (DCL ATV SC D RAD CSFW FW)" Date: Mon, 4 Dec 2023 10:53:01 +0100 Subject: [PATCH] test: Use XMLUnit to compare XMI The XMLUnit DiffBuilder used can ignore element order, but still checks for correct nesting, which the string sorting could not. --- build.gradle.kts | 1 + plantuml-asl/build.gradle.kts | 1 + plantuml-epl/build.gradle.kts | 1 + plantuml-gplv2/build.gradle.kts | 1 + plantuml-lgpl/build.gradle.kts | 1 + plantuml-mit/build.gradle.kts | 1 + test/nonreg/xmi/XmiTest.java | 50 +++++++++++++-------------------- 7 files changed, 26 insertions(+), 30 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 72fb2d760..6aa48b2dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { testImplementation("io.github.glytching:junit-extensions:2.6.0") testImplementation("org.assertj:assertj-core:3.24.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") + testImplementation("org.xmlunit:xmlunit-core:2.9.+") if (JavaVersion.current().isJava8) { testImplementation("org.mockito:mockito-core:4.+") testImplementation("org.mockito:mockito-junit-jupiter:4.+") diff --git a/plantuml-asl/build.gradle.kts b/plantuml-asl/build.gradle.kts index 79ebca686..b27324b28 100644 --- a/plantuml-asl/build.gradle.kts +++ b/plantuml-asl/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation("org.assertj:assertj-core:3.24.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") testImplementation("org.scilab.forge:jlatexmath:1.0.7") + testImplementation("org.xmlunit:xmlunit-core:2.9.+") } repositories { diff --git a/plantuml-epl/build.gradle.kts b/plantuml-epl/build.gradle.kts index 0c94e1a85..5d0683378 100644 --- a/plantuml-epl/build.gradle.kts +++ b/plantuml-epl/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation("org.assertj:assertj-core:3.24.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") testImplementation("org.scilab.forge:jlatexmath:1.0.7") + testImplementation("org.xmlunit:xmlunit-core:2.9.+") } repositories { diff --git a/plantuml-gplv2/build.gradle.kts b/plantuml-gplv2/build.gradle.kts index 740d97e91..e5903f8ba 100644 --- a/plantuml-gplv2/build.gradle.kts +++ b/plantuml-gplv2/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation("org.assertj:assertj-core:3.24.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") testImplementation("org.scilab.forge:jlatexmath:1.0.7") + testImplementation("org.xmlunit:xmlunit-core:2.9.+") } repositories { diff --git a/plantuml-lgpl/build.gradle.kts b/plantuml-lgpl/build.gradle.kts index f110030e0..5f6ebfd67 100644 --- a/plantuml-lgpl/build.gradle.kts +++ b/plantuml-lgpl/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation("org.assertj:assertj-core:3.24.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") testImplementation("org.scilab.forge:jlatexmath:1.0.7") + testImplementation("org.xmlunit:xmlunit-core:2.9.+") } repositories { diff --git a/plantuml-mit/build.gradle.kts b/plantuml-mit/build.gradle.kts index 995be47c3..4d3655bfa 100644 --- a/plantuml-mit/build.gradle.kts +++ b/plantuml-mit/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation("org.assertj:assertj-core:3.24.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") testImplementation("org.scilab.forge:jlatexmath:1.0.7") + testImplementation("org.xmlunit:xmlunit-core:2.9.+") } repositories { diff --git a/test/nonreg/xmi/XmiTest.java b/test/nonreg/xmi/XmiTest.java index db85e694d..760a2ae6a 100644 --- a/test/nonreg/xmi/XmiTest.java +++ b/test/nonreg/xmi/XmiTest.java @@ -12,9 +12,12 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicInteger; + +import org.xmlunit.builder.DiffBuilder; +import org.xmlunit.builder.Input; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.Diff; +import org.xmlunit.diff.ElementSelectors; import net.sourceforge.plantuml.FileFormat; import net.sourceforge.plantuml.FileFormatOption; @@ -30,44 +33,31 @@ public class XmiTest { final String star = removeVersion(runPlantUML(expectedDescription, FileFormat.XMI_STAR)); final String starExpected = readStringFromSourceFile(getDiagramFile(), "{{{star", "}}}star"); - // This is really a hack. Since XML generation does not guarantee the order of - // attributes, we make an easy to do check by sorting characters. - // Of course, this is really incomplete: a faulty String may match the expected - // result if, for example, an attribute is moved from a node to another. - // However, we consider that it is a good start. - if (sortString(star).equals(sortString(starExpected)) == false) { - assertEquals(starExpected, star, "XmiStar: Generated GraphML is not ok"); - } + assertXMIEqual(star, starExpected); final String argo = removeVersion(runPlantUML(expectedDescription, FileFormat.XMI_ARGO)); final String argoExpected = readStringFromSourceFile(getDiagramFile(), "{{{argo", "}}}argo"); - if (sortString(argo).equals(sortString(argoExpected)) == false) { - assertEquals(argoExpected, argo, "XmiArgo: Generated GraphML is not ok"); - } + assertXMIEqual(argo, argoExpected); + } + private void assertXMIEqual(final String actual, final String expected) { + // XMI is XML, so we can just use the xmlunit diffbuilder + // Compare elements with the same xmi ID + // checkForSimilar required to ignore order + Diff diff = DiffBuilder.compare(Input.fromString(actual)).withTest(Input.fromString(expected)) + .ignoreWhitespace().ignoreComments().checkForSimilar() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAttributes("xmi.id"))).build(); + + if (diff.hasDifferences()) { + assertTrue(false, diff.fullDescription()); + } } private String removeVersion(String xmi) { return xmi.replaceFirst("\\.*\\", ""); } - private String sortString(String s) { - final Map map = new TreeMap<>(); - for (int i = 0; i < s.length(); i++) { - final char ch = s.charAt(i); - // We ignore non writable characters - if (ch <= ' ') - continue; - - AtomicInteger count = map.get(ch); - if (count == null) - map.put(ch, new AtomicInteger(1)); - else - count.addAndGet(1); - } - return map.toString(); - } private String getLocalFolder() { return "test/" + getPackageName().replace(".", "/");