diff --git a/.github/workflows/cli-build-instructions.yml b/.github/workflows/cli-build-instructions.yml index 7de8a45803..d107512ed0 100644 --- a/.github/workflows/cli-build-instructions.yml +++ b/.github/workflows/cli-build-instructions.yml @@ -90,7 +90,7 @@ jobs: # which makes little sense; but that is the purpose of the other job. # For smoke testing, generate only a couple of files. - name: Run some invariant tests - run: MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml test -am -pl unicodetools -Dtest=TestTestUnicodeInvariants#testUnicodeSetParsing -Dsurefire.failIfNoSpecifiedTests=false -DCLDR_DIR=$(cd ../cldr ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd Generated; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) + run: MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml test -am -pl unicodetools -Dtest=TestUnicodeSetParsing -Dsurefire.failIfNoSpecifiedTests=false -DCLDR_DIR=$(cd ../cldr ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd Generated; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -195,7 +195,7 @@ jobs: - name: Run most tests run: | cd unicodetools/mine/src - MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml test -Dtest=!TestTestUnicodeInvariants#testSecurityInvariants -DCLDR_DIR=$(cd ../../../cldr/mine/src ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd ../Generated ; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) -DEMIT_GITHUB_ERRORS -DENABLE_PROP_FILE_CACHE + MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml test -Dtest=!TestSecurityInvariants -DCLDR_DIR=$(cd ../../../cldr/mine/src ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd ../Generated ; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) -DEMIT_GITHUB_ERRORS -DENABLE_PROP_FILE_CACHE env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -438,7 +438,7 @@ jobs: then ERROR="::notice" else ERROR="::error" fi - MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml test -am -pl unicodetools -Dtest=TestTestUnicodeInvariants#testSecurityInvariants -DCLDR_DIR=$(cd ../../../cldr/mine/src ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd ../Generated ; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) -Dsurefire.failIfNoSpecifiedTests=false -DEMIT_GITHUB_ERRORS 2>&1 | sed "s/^::error/$ERROR/" + MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml test -am -pl unicodetools -Dtest=TestSecurityInvariants -DCLDR_DIR=$(cd ../../../cldr/mine/src ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd ../Generated ; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) -Dsurefire.failIfNoSpecifiedTests=false -DEMIT_GITHUB_ERRORS 2>&1 | sed "s/^::error/$ERROR/" STATUS=${PIPESTATUS[0]} if [[ ${REPERTOIRE_CHANGED:-0} -ne 0 ]] then exit 0 diff --git a/docs/build.md b/docs/build.md index 512e9f423f..870a159285 100644 --- a/docs/build.md +++ b/docs/build.md @@ -589,6 +589,7 @@ We no longer post files to FTP folders, nor publish individual files without con 1. Note that since 2022-May (Unicode 15) we have a `TestTestUnicodeInvariants` JUnit wrapper that runs `TestUnicodeInvariants` with default options, and which is one of our CI build bot tests. + 1. In 2026-May this got split into multiple classes for better granularity / more parallel testing. 1. The header of the result file explains the syntax of the tests. 1. Open that file and search for `**** START Test Failure`. 1. Each such point provides a dump of comparison information. diff --git a/docs/pipeline.md b/docs/pipeline.md index 98a656bdeb..141ee05f20 100644 --- a/docs/pipeline.md +++ b/docs/pipeline.md @@ -235,6 +235,6 @@ git commit -m GenerateEnums ### Run comparison tests eggrobin (Windows, in-source; replace $RMG_ISSUE by the RMG issue number, or define it as that number). ```powershell -mvn test -am -pl unicodetools "-DCLDR_DIR=$(gl|split-path -parent)\cldr\" "-DUNICODETOOLS_GEN_DIR=$(gl|split-path -parent)\unicodetools\Generated\" "-DUNICODETOOLS_REPO_DIR=$(gl|split-path -parent)\unicodetools\" "-Dtest=TestTestUnicodeInvariants#testAdditionComparisons" -Dsurefire.failIfNoSpecifiedTests=false -DtrimStackTrace=false "-DRMG_ISSUE=$RMG_ISSUE" +mvn test -am -pl unicodetools "-DCLDR_DIR=$(gl|split-path -parent)\cldr\" "-DUNICODETOOLS_GEN_DIR=$(gl|split-path -parent)\unicodetools\Generated\" "-DUNICODETOOLS_REPO_DIR=$(gl|split-path -parent)\unicodetools\" "-Dtest=TestAdditionComparisons" -Dsurefire.failIfNoSpecifiedTests=false -DtrimStackTrace=false "-DRMG_ISSUE=$RMG_ISSUE" ``` Results are in Generated\UnicodeTestResults-addition-comparisons-[RMG issue number].html. diff --git a/unicodetools/src/test/java/org/unicode/text/UCD/TestAdditionComparisons.java b/unicodetools/src/test/java/org/unicode/text/UCD/TestAdditionComparisons.java new file mode 100644 index 0000000000..f33d9a0156 --- /dev/null +++ b/unicodetools/src/test/java/org/unicode/text/UCD/TestAdditionComparisons.java @@ -0,0 +1,54 @@ +package org.unicode.text.UCD; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.IOException; +import org.junit.jupiter.api.Test; +import org.unicode.cldr.util.CldrUtility; + +public class TestAdditionComparisons { + @Test + void testAdditionComparisons() throws IOException { + final var directory = new File(getClass().getResource("AdditionComparisons").getPath()); + if (!directory.exists()) { + throw new IOException(directory.getAbsolutePath() + " does not exist"); + } + int rc = 0; + // Ideally, this would be a @ParameterizedTest, and we would use the Dtest parameter of the + // mvn command line to filter a specific test. + // Unfortunately, this does not appear to be possible with JUnit 5 and Surefire, see + // https://stackoverflow.com/questions/69198795/junit5-running-a-single-instance-of-parameterized-test, + // so we have one big test and we filter by hand. + final String rmgIssueFilter = CldrUtility.getProperty("RMG_ISSUE", null); + boolean matchedFilter = false; + for (var file : directory.listFiles()) { + final String filename = file.getName(); + if (!file.getName().endsWith(".txt")) { + continue; + } + final String nameWithoutExtension = filename.substring(0, filename.length() - 4); + if (rmgIssueFilter != null) { + if (nameWithoutExtension.equals(rmgIssueFilter)) { + matchedFilter = true; + } else { + continue; + } + } + final int errors = + TestUnicodeInvariants.testInvariants( + "AdditionComparisons/" + filename, + "addition-comparisons-" + nameWithoutExtension, + true); + if (errors != 0) { + System.err.println(errors + " errors in " + filename); + } + rc += errors; + } + if (rmgIssueFilter != null) { + assertTrue(matchedFilter, "Could not find test " + rmgIssueFilter + ".txt"); + } + assertEquals(0, rc, "TestUnicodeInvariants.testInvariants(addition-comparisons) failed"); + } +} diff --git a/unicodetools/src/test/java/org/unicode/text/UCD/TestMainUnicodeInvariants.java b/unicodetools/src/test/java/org/unicode/text/UCD/TestMainUnicodeInvariants.java new file mode 100644 index 0000000000..bd9a2d5470 --- /dev/null +++ b/unicodetools/src/test/java/org/unicode/text/UCD/TestMainUnicodeInvariants.java @@ -0,0 +1,35 @@ +package org.unicode.text.UCD; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.IOException; +import org.junit.jupiter.api.Test; +import org.unicode.text.utility.Settings; + +public class TestMainUnicodeInvariants { + @Test + void testSRC_UCD_DIR() { + assertAll( + "assert that no components of Settings.SRC_UCD_DIR are null", + () -> + assertNotNull( + Settings.UnicodeTools.UNICODETOOLS_RSRC_DIR, + "Settings.UnicodeTools.UNICODETOOLS_RSRC_DIR"), + () -> + assertNotNull( + Settings.UnicodeTools.UNICODETOOLS_DIR, + "Settings.UnicodeTools.UNICODETOOLS_DIR"), + () -> + assertNotNull( + Settings.UnicodeTools.UNICODETOOLS_REPO_DIR, + "Settings.UnicodeTools.UNICODETOOLS_REPO_DIR")); + } + + @Test + void testUnicodeInvariants() throws IOException { + int rc = TestUnicodeInvariants.testInvariants(null, null, true); + assertEquals(0, rc, "TestUnicodeInvariants.testInvariants(default) failed"); + } +} diff --git a/unicodetools/src/test/java/org/unicode/text/UCD/TestSecurityInvariants.java b/unicodetools/src/test/java/org/unicode/text/UCD/TestSecurityInvariants.java new file mode 100644 index 0000000000..6b3e2c9561 --- /dev/null +++ b/unicodetools/src/test/java/org/unicode/text/UCD/TestSecurityInvariants.java @@ -0,0 +1,15 @@ +package org.unicode.text.UCD; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import org.junit.jupiter.api.Test; + +public class TestSecurityInvariants { + @Test + void testSecurityInvariants() throws IOException { + int rc = + TestUnicodeInvariants.testInvariants("SecurityInvariantTest.txt", "security", true); + assertEquals(0, rc, "TestUnicodeInvariants.testInvariants(security) failed"); + } +} diff --git a/unicodetools/src/test/java/org/unicode/text/UCD/TestTestUnicodeInvariants.java b/unicodetools/src/test/java/org/unicode/text/UCD/TestTestUnicodeInvariants.java deleted file mode 100644 index 093f806c42..0000000000 --- a/unicodetools/src/test/java/org/unicode/text/UCD/TestTestUnicodeInvariants.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.unicode.text.UCD; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.text.ParseException; -import java.text.ParsePosition; -import org.junit.jupiter.api.Test; -import org.unicode.cldr.util.CldrUtility; -import org.unicode.text.UCD.TestUnicodeInvariants.BackwardParseException; -import org.unicode.text.utility.Settings; - -public class TestTestUnicodeInvariants { - @Test - void testSRC_UCD_DIR() { - assertAll( - "assert that no components of Settings.SRC_UCD_DIR are null", - () -> - assertNotNull( - Settings.UnicodeTools.UNICODETOOLS_RSRC_DIR, - "Settings.UnicodeTools.UNICODETOOLS_RSRC_DIR"), - () -> - assertNotNull( - Settings.UnicodeTools.UNICODETOOLS_DIR, - "Settings.UnicodeTools.UNICODETOOLS_DIR"), - () -> - assertNotNull( - Settings.UnicodeTools.UNICODETOOLS_REPO_DIR, - "Settings.UnicodeTools.UNICODETOOLS_REPO_DIR")); - } - - @Test - void testUnicodeInvariants() throws IOException { - int rc = TestUnicodeInvariants.testInvariants(null, null, true); - assertEquals(0, rc, "TestUnicodeInvariants.testInvariants(default) failed"); - } - - @Test - void testAdditionComparisons() throws IOException { - final var directory = new File(getClass().getResource("AdditionComparisons").getPath()); - if (!directory.exists()) { - throw new IOException(directory.getAbsolutePath() + " does not exist"); - } - int rc = 0; - // Ideally, this would be a @ParameterizedTest, and we would use the Dtest parameter of the - // mvn command line to filter a specific test. - // Unfortunately, this does not appear to be possible with JUnit 5 and Surefire, see - // https://stackoverflow.com/questions/69198795/junit5-running-a-single-instance-of-parameterized-test, - // so we have one big test and we filter by hand. - final String rmgIssueFilter = CldrUtility.getProperty("RMG_ISSUE", null); - boolean matchedFilter = false; - for (var file : directory.listFiles()) { - final String filename = file.getName(); - if (!file.getName().endsWith(".txt")) { - continue; - } - final String nameWithoutExtension = filename.substring(0, filename.length() - 4); - if (rmgIssueFilter != null) { - if (nameWithoutExtension.equals(rmgIssueFilter)) { - matchedFilter = true; - } else { - continue; - } - } - final int errors = - TestUnicodeInvariants.testInvariants( - "AdditionComparisons/" + filename, - "addition-comparisons-" + nameWithoutExtension, - true); - if (errors != 0) { - System.err.println(errors + " errors in " + filename); - } - rc += errors; - } - if (rmgIssueFilter != null) { - assertTrue(matchedFilter, "Could not find test " + rmgIssueFilter + ".txt"); - } - assertEquals(0, rc, "TestUnicodeInvariants.testInvariants(addition-comparisons) failed"); - } - - @Test - void testSecurityInvariants() throws IOException { - int rc = - TestUnicodeInvariants.testInvariants("SecurityInvariantTest.txt", "security", true); - assertEquals(0, rc, "TestUnicodeInvariants.testInvariants(security) failed"); - } - - @Test - void testUnicodeSetParsing() throws ParseException { - assertEquals( - 26, - TestUnicodeInvariants.parseUnicodeSet( - "TEST [\\N{LATIN SMALL LETTER A}-\\N{LATIN SMALL LETTER Z}]", - new ParsePosition(5)) - .size()); - ParseException thrown = - assertThrows( - ParseException.class, - () -> - TestUnicodeInvariants.parseUnicodeSet( - "TEST [\\N{MEOW}]", new ParsePosition(5))); - assertEquals("No character name nor name alias matches MEOW", thrown.getMessage()); - assertEquals("TEST [".length(), thrown.getErrorOffset()); - thrown = - assertThrows( - BackwardParseException.class, - () -> - TestUnicodeInvariants.parseUnicodeSet( - "TEST [[a-z]-\\N{LATIN SMALL LETTER Z}]", - new ParsePosition(5))); - assertEquals("Error: Set expected after operator", thrown.getMessage()); - assertEquals("TEST [[a-z]-.N{LATIN SMALL LETTER Z}".length(), thrown.getErrorOffset()); - } -} diff --git a/unicodetools/src/test/java/org/unicode/text/UCD/TestUnicodeSetParsing.java b/unicodetools/src/test/java/org/unicode/text/UCD/TestUnicodeSetParsing.java new file mode 100644 index 0000000000..fa48715dc8 --- /dev/null +++ b/unicodetools/src/test/java/org/unicode/text/UCD/TestUnicodeSetParsing.java @@ -0,0 +1,38 @@ +package org.unicode.text.UCD; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.text.ParseException; +import java.text.ParsePosition; +import org.junit.jupiter.api.Test; +import org.unicode.text.UCD.TestUnicodeInvariants.BackwardParseException; + +public class TestUnicodeSetParsing { + @Test + void testUnicodeSetParsing() throws ParseException { + assertEquals( + 26, + TestUnicodeInvariants.parseUnicodeSet( + "TEST [\\N{LATIN SMALL LETTER A}-\\N{LATIN SMALL LETTER Z}]", + new ParsePosition(5)) + .size()); + ParseException thrown = + assertThrows( + ParseException.class, + () -> + TestUnicodeInvariants.parseUnicodeSet( + "TEST [\\N{MEOW}]", new ParsePosition(5))); + assertEquals("No character name nor name alias matches MEOW", thrown.getMessage()); + assertEquals("TEST [".length(), thrown.getErrorOffset()); + thrown = + assertThrows( + BackwardParseException.class, + () -> + TestUnicodeInvariants.parseUnicodeSet( + "TEST [[a-z]-\\N{LATIN SMALL LETTER Z}]", + new ParsePosition(5))); + assertEquals("Error: Set expected after operator", thrown.getMessage()); + assertEquals("TEST [[a-z]-.N{LATIN SMALL LETTER Z}".length(), thrown.getErrorOffset()); + } +}