Skip to content

Commit 210204f

Browse files
authored
Show invariant test results in the diff (unicode-org#646)
1 parent 8cb8c74 commit 210204f

File tree

2 files changed

+103
-33
lines changed

2 files changed

+103
-33
lines changed

.github/workflows/cli-build-instructions.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ jobs:
170170
- name: Run command - Build and Test
171171
run: |
172172
cd unicodetools/mine/src
173-
MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml package -DCLDR_DIR=$(cd ../../../cldr/mine/src ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd ../Generated ; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) -DUVERSION=$CURRENT_UVERSION
173+
MAVEN_OPTS="-ea" mvn -s .github/workflows/mvn-settings.xml package -DCLDR_DIR=$(cd ../../../cldr/mine/src ; pwd) -DUNICODETOOLS_GEN_DIR=$(cd ../Generated ; pwd) -DUNICODETOOLS_REPO_DIR=$(pwd) -DUVERSION=$CURRENT_UVERSION -DEMIT_GITHUB_ERRORS
174174
env:
175175
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
176176

unicodetools/src/main/java/org/unicode/text/UCD/TestUnicodeInvariants.java

Lines changed: 102 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public class TestUnicodeInvariants {
4646
private static int showRangeLimit = 20;
4747
static boolean doHtml = true;
4848
public static final String DEFAULT_FILE = "UnicodeInvariantTest.txt";
49+
public static final HTMLTabber htmlTabber = new Tabber.HTMLTabber();
50+
public static final boolean EMIT_GITHUB_ERRORS =
51+
System.getProperty("EMIT_GITHUB_ERRORS") != null;
4952

5053
private static final int
5154
// HELP1 = 0,
@@ -171,8 +174,6 @@ public static int testInvariants(String inputFile, boolean doRange) throws IOExc
171174
out3.write('\uFEFF'); // BOM
172175
}
173176
try (final BufferedReader in = getInputReader(inputFile)) {
174-
final HTMLTabber tabber = new Tabber.HTMLTabber();
175-
176177
errorLister =
177178
new BagFormatter()
178179
.setMergeRanges(doRange)
@@ -183,7 +184,7 @@ public static int testInvariants(String inputFile, boolean doRange) throws IOExc
183184
.setFixName(toHTML);
184185
errorLister.setShowTotal(false);
185186
if (doHtml) {
186-
errorLister.setTabber(tabber);
187+
errorLister.setTabber(htmlTabber);
187188
}
188189

189190
showLister =
@@ -198,7 +199,7 @@ public static int testInvariants(String inputFile, boolean doRange) throws IOExc
198199
showLister.setValueSource(LATEST_PROPS.getProperty("script"));
199200
}
200201
if (doHtml) {
201-
showLister.setTabber(tabber);
202+
showLister.setTabber(htmlTabber);
202203
}
203204

204205
// symbolTable = new ChainedSymbolTable();
@@ -207,7 +208,7 @@ public static int testInvariants(String inputFile, boolean doRange) throws IOExc
207208
// ToolUnicodePropertySource.make(UCD.lastVersion).getSymbolTable("\u00D7"),
208209
//
209210
// ToolUnicodePropertySource.make(Default.ucdVersion()).getSymbolTable("")});
210-
while (true) {
211+
for (int lineNumber = 1; ; ++lineNumber) {
211212
String line = in.readLine();
212213
if (line == null) {
213214
break;
@@ -230,24 +231,24 @@ public static int testInvariants(String inputFile, boolean doRange) throws IOExc
230231
} else if (line.startsWith("Let")) {
231232
letLine(pp, line);
232233
} else if (line.startsWith("In")) {
233-
inLine(pp, line);
234+
inLine(pp, line, lineNumber);
234235
} else if (line.startsWith("ShowScript")) {
235236
showScript = true;
236237
} else if (line.startsWith("HideScript")) {
237238
showScript = false;
238239
} else if (line.startsWith("Map")) {
239-
testMapLine(line, pp);
240+
testMapLine(line, pp, lineNumber);
240241
} else if (line.startsWith("ShowMap")) {
241242
showMapLine(line, pp);
242243
} else if (line.startsWith("Show")) {
243244
showLine(line, pp);
244245
} else if (line.startsWith("EquivalencesOf")) {
245-
equivalencesLine(line, pp);
246+
equivalencesLine(line, pp, lineNumber);
246247
} else {
247-
testLine(line, pp);
248+
testLine(line, pp, lineNumber);
248249
}
249250
} catch (final Exception e) {
250-
parseErrorCount = parseError(parseErrorCount, line, e);
251+
parseErrorCount = parseError(parseErrorCount, line, e, lineNumber);
251252
continue;
252253
}
253254
}
@@ -276,7 +277,8 @@ static class PropertyComparison {
276277
UnicodeProperty property2;
277278
}
278279

279-
private static void equivalencesLine(String line, ParsePosition pp) throws ParseException {
280+
private static void equivalencesLine(String line, ParsePosition pp, int lineNumber)
281+
throws ParseException {
280282
pp.setIndex("EquivalencesOf".length());
281283
final UnicodeSet domain = new UnicodeSet(line, pp, symbolTable);
282284
final var leftProperty = CompoundProperty.of(LATEST_PROPS, line, pp);
@@ -435,16 +437,26 @@ private static void equivalencesLine(String line, ParsePosition pp) throws Parse
435437
++testFailureCount;
436438
printErrorLine("Test Failure", Side.START, testFailureCount);
437439
}
440+
final List<String> errorMessageLines = new ArrayList<>();
438441
if (counterexamples.isEmpty()) {
439-
println("There are no counterexamples to " + relationOperator + ".");
442+
errorMessageLines.add("There are no counterexamples to " + relationOperator + ".");
440443
} else {
441444
if (leftShouldImplyRight) {
442-
println("The implication ⇒ is " + leftImpliesRightCounterexamples.isEmpty() + ".");
445+
errorMessageLines.add(
446+
"The implication ⇒ is " + leftImpliesRightCounterexamples.isEmpty() + ".");
443447
}
444448
if (rightShouldImplyLeft) {
445-
println("The implication ⇐ is " + rightImpliesLeftCounterexamples.isEmpty() + ".");
449+
errorMessageLines.add(
450+
"The implication ⇐ is " + rightImpliesLeftCounterexamples.isEmpty() + ".");
446451
}
447452
}
453+
for (var errorLine : errorMessageLines) {
454+
println(errorLine);
455+
}
456+
errorMessageLines.addAll(counterexamples);
457+
if (failure) {
458+
reportTestFailure(lineNumber, String.join("\n", errorMessageLines).replace('\t', ' '));
459+
}
448460
out.println(failure ? "<table class='f'>" : "<table>");
449461
for (String counterexample : counterexamples) {
450462
out.println("<tr><td>");
@@ -457,7 +469,8 @@ private static void equivalencesLine(String line, ParsePosition pp) throws Parse
457469
}
458470
}
459471

460-
private static void inLine(ParsePosition pp, String line) throws ParseException {
472+
private static void inLine(ParsePosition pp, String line, int lineNumber)
473+
throws ParseException {
461474
pp.setIndex(2);
462475
final PropertyComparison propertyComparison = getPropertyComparison(pp, line);
463476
final UnicodeMap<String> failures = new UnicodeMap<>();
@@ -476,13 +489,23 @@ private static void inLine(ParsePosition pp, String line) throws ParseException
476489
if (failureCount != 0) {
477490
testFailureCount++;
478491
printErrorLine("Test Failure", Side.START, testFailureCount);
479-
println(
480-
"## Got unexpected "
492+
String errorMessage =
493+
"Got unexpected "
481494
+ (propertyComparison.shouldBeEqual ? "differences" : "equalities")
482495
+ ": "
483-
+ failureCount);
496+
+ failureCount;
497+
println("## " + errorMessage);
498+
484499
final UnicodeLabel failureProp = new UnicodeProperty.UnicodeMapProperty().set(failures);
485500
errorLister.setValueSource(failureProp);
501+
502+
var monoTable = new StringWriter();
503+
errorLister.setTabber(new Tabber.MonoTabber());
504+
errorLister.setLineSeparator("\n");
505+
errorLister.showSetNames(new PrintWriter(monoTable), failureSet);
506+
errorLister.setTabber(htmlTabber);
507+
reportTestFailure(lineNumber, errorMessage + "\n" + monoTable.toString());
508+
486509
if (doHtml) {
487510
out.println("<table class='f'>");
488511
}
@@ -710,7 +733,8 @@ private static void showMapLine(String line, ParsePosition pp) {
710733
showLister.setMergeRanges(doRange);
711734
}
712735

713-
private static void testLine(String line, ParsePosition pp) throws ParseException {
736+
private static void testLine(String line, ParsePosition pp, int lineNumber)
737+
throws ParseException {
714738
if (line.startsWith("Test")) {
715739
line = line.substring(4).trim();
716740
}
@@ -776,21 +800,24 @@ private static void testLine(String line, ParsePosition pp) throws ParseExceptio
776800
"In",
777801
rightSide,
778802
"But Not In",
779-
leftSide);
803+
leftSide,
804+
lineNumber);
780805
checkExpected(
781806
rightAndLeft,
782807
new UnicodeSet(rightSet).retainAll(leftSet),
783808
"In",
784809
rightSide,
785810
"And In",
786-
leftSide);
811+
leftSide,
812+
lineNumber);
787813
checkExpected(
788814
left_right,
789815
new UnicodeSet(leftSet).removeAll(rightSet),
790816
"In",
791817
leftSide,
792818
"But Not In",
793-
rightSide);
819+
rightSide,
820+
lineNumber);
794821
}
795822

796823
public static void checkRelation(ParsePosition pp, char relation) throws ParseException {
@@ -810,7 +837,8 @@ private static void checkExpected(
810837
String rightStatus,
811838
String rightSide,
812839
String leftStatus,
813-
String leftSide) {
840+
String leftSide,
841+
int lineNumber) {
814842
switch (expected) {
815843
case empty:
816844
if (segment.size() == 0) {
@@ -829,9 +857,22 @@ private static void checkExpected(
829857
}
830858
testFailureCount++;
831859
printErrorLine("Test Failure", Side.START, testFailureCount);
832-
println("## Expected " + expected + ", got: " + segment.size() + "\t" + segment.toString());
833-
println("## " + rightStatus + "\t" + rightSide);
834-
println("## " + leftStatus + "\t" + leftSide);
860+
final var errorMessageLines =
861+
new String[] {
862+
"Expected " + expected + ", got: " + segment.size() + "\t" + segment.toString(),
863+
rightStatus + "\t" + rightSide,
864+
leftStatus + "\t" + leftSide
865+
};
866+
var monoTable = new StringWriter();
867+
for (String line : errorMessageLines) {
868+
println("## " + line);
869+
}
870+
errorLister.setTabber(new Tabber.MonoTabber());
871+
errorLister.setLineSeparator("\n");
872+
errorLister.showSetNames(new PrintWriter(monoTable), segment);
873+
reportTestFailure(
874+
lineNumber, String.join("\n", errorMessageLines) + "\n" + monoTable.toString());
875+
errorLister.setTabber(htmlTabber);
835876
if (doHtml) {
836877
out.println("<table class='e'>");
837878
}
@@ -853,7 +894,8 @@ private static void checkExpected(
853894
getProperties(Settings.lastVersion),
854895
IndexUnicodeProperties.make(Settings.lastVersion)));
855896

856-
private static void testMapLine(String line, ParsePosition pp) throws ParseException {
897+
private static void testMapLine(String line, ParsePosition pp, int lineNumber)
898+
throws ParseException {
857899
char relation = 0;
858900
String rightSide = null;
859901
String leftSide = null;
@@ -915,21 +957,24 @@ private static void testMapLine(String line, ParsePosition pp) throws ParseExcep
915957
"In",
916958
rightSide,
917959
"But Not In",
918-
leftSide);
960+
leftSide,
961+
lineNumber);
919962
checkExpected(
920963
rightAndLeft,
921964
UnicodeMapParser.retainAll(new UnicodeMap<String>().putAll(rightSet), leftSet),
922965
"In",
923966
rightSide,
924967
"And In",
925-
leftSide);
968+
leftSide,
969+
lineNumber);
926970
checkExpected(
927971
left_right,
928972
UnicodeMapParser.removeAll(new UnicodeMap<String>().putAll(leftSet), rightSet),
929973
"In",
930974
leftSide,
931975
"But Not In",
932-
rightSide);
976+
rightSide,
977+
lineNumber);
933978
}
934979

935980
private static void checkExpected(
@@ -938,7 +983,8 @@ private static void checkExpected(
938983
String rightStatus,
939984
String rightSide,
940985
String leftStatus,
941-
String leftSide) {
986+
String leftSide,
987+
int lineNumber) {
942988
switch (expected) {
943989
case empty:
944990
if (segment.size() == 0) {
@@ -1015,7 +1061,7 @@ private static void showSet(ParsePosition pp, final String value) {
10151061
println();
10161062
}
10171063

1018-
private static int parseError(int parseErrorCount, String line, Exception e) {
1064+
private static int parseError(int parseErrorCount, String line, Exception e, int lineNumber) {
10191065
parseErrorCount++;
10201066
if (e instanceof ParseException) {
10211067
final int index = ((ParseException) e).getErrorOffset();
@@ -1029,7 +1075,9 @@ private static int parseError(int parseErrorCount, String line, Exception e) {
10291075
if (message != null) {
10301076
println("##" + message);
10311077
}
1078+
reportParseError(lineNumber, message);
10321079
e.printStackTrace(out);
1080+
10331081
out.println("</pre>");
10341082
printErrorLine("Parse Error", Side.END, parseErrorCount);
10351083
println();
@@ -1122,6 +1170,28 @@ private static void println() {
11221170
println("");
11231171
}
11241172

1173+
private static void reportParseError(int lineNumber, String message) {
1174+
reportError(lineNumber, "Parse error", message);
1175+
}
1176+
1177+
private static void reportTestFailure(int lineNumber, String message) {
1178+
reportError(lineNumber, "Invariant test failure", message);
1179+
}
1180+
1181+
private static void reportError(int lineNumber, String title, String message) {
1182+
if (EMIT_GITHUB_ERRORS) {
1183+
System.err.println(
1184+
"::error file=unicodetools/src/main/resources/org/unicode/text/UCD/"
1185+
+ DEFAULT_FILE
1186+
+ ",line="
1187+
+ lineNumber
1188+
+ ",title="
1189+
+ title
1190+
+ "::"
1191+
+ message.replace("%", "%25").replace("\n", "%0A"));
1192+
}
1193+
}
1194+
11251195
/** Should add to UnicodeSet */
11261196
public static String scan(UnicodeSet unicodeSet, String line, ParsePosition pp, boolean in) {
11271197
final int start = pp.getIndex();

0 commit comments

Comments
 (0)