Skip to content

Commit f3c90f0

Browse files
author
Justin Lu
committed
8306711: Improve diagnosis of IntlTest framework
Reviewed-by: naoto, lancea
1 parent b827ce8 commit f3c90f0

File tree

2 files changed

+117
-103
lines changed

2 files changed

+117
-103
lines changed

test/jdk/java/text/Normalizer/ICUBasicTest.java

+56-30
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import sun.text.Normalizer;
4242
import jdk.internal.icu.text.NormalizerBase;
4343

44+
import java.util.HexFormat;
45+
4446
import static java.text.Normalizer.Form.*;
4547

4648
public class ICUBasicTest extends IntlTest {
@@ -149,7 +151,8 @@ public void TestCombiningMarks() {
149151

150152
if (!expected.equals(result)) {
151153
errln("Reordering of combining marks failed. Expected: " +
152-
toHexString(expected) + " Got: "+ toHexString(result));
154+
HexFormat.of().withDelimiter(" ").formatHex(expected.getBytes())
155+
+ " Got: "+ HexFormat.of().withDelimiter(" ").formatHex(result.getBytes()));
153156
}
154157
}
155158

@@ -191,16 +194,22 @@ public void TestVerisign() throws Exception {
191194

192195
String result = NormalizerBase.normalize(input, NFD);
193196
if (!result.equals(output)) {
194-
errln("FAIL input: " + toHexString(input) + "\n" +
195-
" decompose: " + toHexString(result) + "\n" +
196-
" expected: " + toHexString(output));
197+
errln("FAIL input: " + HexFormat.of().withDelimiter(" ")
198+
.formatHex(input.getBytes()) + "\n" +
199+
" decompose: " + HexFormat.of().withDelimiter(" ")
200+
.formatHex(result.getBytes()) + "\n" +
201+
" expected: " + HexFormat.of().withDelimiter(" ")
202+
.formatHex(output.getBytes()));
197203
}
198204

199205
result = NormalizerBase.normalize(input, NFC);
200206
if (!result.equals(output)) {
201-
errln("FAIL input: " + toHexString(input) + "\n" +
202-
" compose: " + toHexString(result) + "\n" +
203-
" expected: " + toHexString(output));
207+
errln("FAIL input: " + HexFormat.of().withDelimiter(" ")
208+
.formatHex(input.getBytes()) + "\n" +
209+
" compose: " + HexFormat.of().withDelimiter(" ")
210+
.formatHex(output.getBytes()) + "\n" +
211+
" expected: " + HexFormat.of().withDelimiter(" ")
212+
.formatHex(output.getBytes()));
204213
}
205214
}
206215
}
@@ -231,21 +240,27 @@ public void TestZeroIndex() throws Exception {
231240
String exp = DATA[i+1];
232241

233242
if (b.equals(exp)) {
234-
logln("Ok: " + toHexString(a) + " x COMPOSE_COMPAT => " +
235-
toHexString(b));
243+
logln("Ok: " + HexFormat.of().withDelimiter(" ")
244+
.formatHex(a.getBytes()) + " x COMPOSE_COMPAT => " +
245+
HexFormat.of().withDelimiter(" ")
246+
.formatHex(b.getBytes()));
236247
} else {
237-
errln("FAIL: " + toHexString(a) + " x COMPOSE_COMPAT => " +
238-
toHexString(b) + ", expect " + toHexString(exp));
248+
errln("FAIL: " + HexFormat.of().withDelimiter(" ")
249+
.formatHex(b.getBytes()) + " x COMPOSE_COMPAT => " +
250+
HexFormat.of().withDelimiter(" ")
251+
.formatHex(a.getBytes()) + ", expect " +
252+
HexFormat.of().withDelimiter(" ")
253+
.formatHex(exp.getBytes()));
239254
}
240255

241256
a = NormalizerBase.normalize(b, NFD);
242257
exp = DATA[i+2];
243258
if (a.equals(exp)) {
244-
logln("Ok: " + toHexString(b) + " x DECOMP => " +
245-
toHexString(a));
259+
logln("Ok: " + HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x DECOMP => " +
260+
HexFormat.of().withDelimiter(" ").formatHex(a.getBytes()));
246261
} else {
247-
errln("FAIL: " + toHexString(b) + " x DECOMP => " +
248-
toHexString(a) + ", expect " + toHexString(exp));
262+
errln("FAIL: " + HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x DECOMP => " +
263+
HexFormat.of().withDelimiter(" ").formatHex(a.getBytes()) + ", expect " + HexFormat.of().withDelimiter(" ").formatHex(exp.getBytes()));
249264
}
250265
}
251266
}
@@ -382,25 +397,33 @@ private void checkCompositionExclusion_320(String s) throws Exception {
382397
String c = NormalizerBase.normalize(b, NFC);
383398

384399
if (c.equals(a)) {
385-
errln("FAIL: " + toHexString(a) + " x DECOMP_COMPAT => " +
386-
toHexString(b) + " x COMPOSE => " +
387-
toHexString(c) + " for the latest Unicode");
400+
errln("FAIL: " + HexFormat.of().withDelimiter(" ")
401+
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
402+
HexFormat.of().withDelimiter(" ")
403+
.formatHex(b.getBytes()) + " x COMPOSE => " +
404+
HexFormat.of().withDelimiter(" ")
405+
.formatHex(c.getBytes()) + " for the latest Unicode");
388406
} else if (verbose) {
389-
logln("Ok: " + toHexString(a) + " x DECOMP_COMPAT => " +
390-
toHexString(b) + " x COMPOSE => " +
391-
toHexString(c) + " for the latest Unicode");
407+
logln("Ok: " + HexFormat.of().withDelimiter(" ")
408+
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
409+
HexFormat.of().withDelimiter(" ")
410+
.formatHex(b.getBytes()) + " x COMPOSE => " +
411+
HexFormat.of().withDelimiter(" ")
412+
.formatHex(c.getBytes()) + " for the latest Unicode");
392413
}
393414

394415
b = NormalizerBase.normalize(a, NFKD, Normalizer.UNICODE_3_2);
395416
c = NormalizerBase.normalize(b, NFC, Normalizer.UNICODE_3_2);
396417
if (c.equals(a)) {
397-
errln("FAIL: " + toHexString(a) + " x DECOMP_COMPAT => " +
398-
toHexString(b) + " x COMPOSE => " +
399-
toHexString(c) + " for Unicode 3.2.0");
418+
errln("FAIL: " + HexFormat.of().withDelimiter(" ")
419+
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
420+
HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x COMPOSE => " +
421+
HexFormat.of().withDelimiter(" ").formatHex(c.getBytes()) + " for Unicode 3.2.0");
400422
} else if (verbose) {
401-
logln("Ok: " + toHexString(a) + " x DECOMP_COMPAT => " +
402-
toHexString(b) + " x COMPOSE => " +
403-
toHexString(c) + " for Unicode 3.2.0");
423+
logln("Ok: " + HexFormat.of().withDelimiter(" ")
424+
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
425+
HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x COMPOSE => " +
426+
HexFormat.of().withDelimiter(" ").formatHex(c.getBytes()) + " for Unicode 3.2.0");
404427
}
405428
}
406429

@@ -572,15 +595,18 @@ private void staticTest(java.text.Normalizer.Form form,
572595
int outCol) throws Exception {
573596
for (int i = 0; i < tests.length; i++) {
574597
String input = tests[i][0];
575-
logln("Normalizing '" + input + "' (" + toHexString(input) + ")" );
598+
logln("Normalizing '" + input + "' (" + HexFormat.of()
599+
.withDelimiter(" ").formatHex(input.getBytes()) + ")" );
576600

577601
String expect =tests[i][outCol];
578602
String output = java.text.Normalizer.normalize(input, form);
579603

580604
if (!output.equals(expect)) {
581605
errln("FAIL: case " + i
582-
+ " expected '" + expect + "' (" + toHexString(expect) + ")"
583-
+ " but got '" + output + "' (" + toHexString(output) + ")"
606+
+ " expected '" + expect + "' (" + HexFormat.of()
607+
.withDelimiter(" ").formatHex(expect.getBytes()) + ")"
608+
+ " but got '" + output + "' (" + HexFormat.of()
609+
.withDelimiter(" ").formatHex(output.getBytes()) + ")"
584610
);
585611
}
586612
}

test/jdk/java/text/testlib/IntlTest.java

+61-73
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
2727
import java.lang.reflect.Method;
2828
import java.lang.reflect.Modifier;
2929
import java.util.ArrayList;
30+
import java.util.Comparator;
3031
import java.util.Map;
3132
import java.util.LinkedHashMap;
3233
import java.util.List;
@@ -49,10 +50,11 @@ public abstract class IntlTest {
4950
// Everything below here is boilerplate code that makes it possible
5051
// to add a new test by simply adding a method to an existing class.
5152
//------------------------------------------------------------------------
52-
5353
protected IntlTest() {
54+
Class<? extends IntlTest> testClass = getClass();
55+
testName = testClass.getCanonicalName();
5456
// Populate testMethods with all the test methods.
55-
Method[] methods = getClass().getDeclaredMethods();
57+
Method[] methods = testClass.getDeclaredMethods();
5658
for (Method method : methods) {
5759
if (Modifier.isPublic(method.getModifiers())
5860
&& method.getReturnType() == void.class
@@ -67,71 +69,34 @@ protected IntlTest() {
6769
}
6870
}
6971

70-
protected void run(String[] args) throws Exception
71-
{
72+
protected void run(String[] args) throws Exception {
7273
// Set up the log and reference streams. We use PrintWriters in order to
7374
// take advantage of character conversion. The JavaEsc converter will
7475
// convert Unicode outside the ASCII range to Java's \\uxxxx notation.
7576
log = new PrintWriter(System.out, true);
76-
77-
// Parse the test arguments. They can be either the flag
78-
// "-verbose" or names of test methods. Create a list of
79-
// tests to be run.
80-
List<Method> testsToRun = new ArrayList<>(args.length);
81-
for (String arg : args) {
82-
switch (arg) {
83-
case "-verbose":
84-
verbose = true;
85-
break;
86-
case "-prompt":
87-
prompt = true;
88-
break;
89-
case "-nothrow":
90-
nothrow = true;
91-
break;
92-
case "-exitcode":
93-
exitCode = true;
94-
break;
95-
default:
96-
Method m = testMethods.get(arg);
97-
if (m == null) {
98-
System.out.println("Method " + arg + ": not found");
99-
usage();
100-
return;
101-
}
102-
testsToRun.add(m);
103-
break;
104-
}
105-
}
106-
107-
// If no test method names were given explicitly, run them all.
108-
if (testsToRun.isEmpty()) {
109-
testsToRun.addAll(testMethods.values());
110-
}
111-
112-
System.out.println(getClass().getName() + " {");
77+
List<Method> testsToRun = configureTestsAndArgs(args);
78+
System.out.println(testName + " {");
11379
indentLevel++;
11480

11581
// Run the list of tests given in the test arguments
11682
for (Method testMethod : testsToRun) {
11783
int oldCount = errorCount;
118-
119-
writeTestName(testMethod.getName());
120-
84+
String testName = testMethod.getName();
85+
writeTestName(testName);
12186
try {
122-
testMethod.invoke(this, new Object[0]);
87+
testMethod.invoke(this);
12388
} catch (IllegalAccessException e) {
124-
errln("Can't acces test method " + testMethod.getName());
89+
errln("Can't access test method " + testName);
12590
} catch (InvocationTargetException e) {
126-
errln("Uncaught exception thrown in test method "
127-
+ testMethod.getName());
128-
e.getTargetException().printStackTrace(this.log);
91+
// Log exception first, that way if -nothrow is
92+
// not an arg, the original exception is still logged
93+
logExc(e);
94+
errln(String.format("$$$ Uncaught exception thrown in %s," +
95+
" see above for cause", testName));
12996
}
13097
writeTestResult(errorCount - oldCount);
13198
}
13299
indentLevel--;
133-
writeTestResult(errorCount);
134-
135100
if (prompt) {
136101
System.out.println("Hit RETURN to exit...");
137102
try {
@@ -140,14 +105,46 @@ protected void run(String[] args) throws Exception
140105
System.out.println("Exception: " + e.toString() + e.getMessage());
141106
}
142107
}
143-
if (nothrow) {
144-
if (exitCode) {
145-
System.exit(errorCount);
146-
}
147-
if (errorCount > 0) {
148-
throw new IllegalArgumentException("encountered " + errorCount + " errors");
108+
if (exitCode) {
109+
System.exit(errorCount);
110+
}
111+
if (errorCount > 0) {
112+
throw new RuntimeException(String.format(
113+
"$$$ %s FAILED with %s failures%n", testName, errorCount));
114+
} else {
115+
log.println(String.format("\t$$$ %s PASSED%n", testName));
116+
}
117+
}
118+
119+
private List<Method> configureTestsAndArgs(String[] args) {
120+
// Parse the test arguments. They can be either the flag
121+
// "-verbose" or names of test methods. Create a list of
122+
// tests to be run.
123+
List<Method> testsToRun = new ArrayList<>(args.length);
124+
for (String arg : args) {
125+
switch (arg) {
126+
case "-verbose" -> verbose = true;
127+
case "-prompt" -> prompt = true;
128+
case "-nothrow" -> nothrow = true;
129+
case "-exitcode" -> exitCode = true;
130+
default -> {
131+
Method m = testMethods.get(arg);
132+
if (m == null) {
133+
System.out.println("Method " + arg + ": not found");
134+
usage();
135+
return testsToRun;
136+
}
137+
testsToRun.add(m);
138+
}
149139
}
150140
}
141+
// If no test method names were given explicitly, run them all.
142+
if (testsToRun.isEmpty()) {
143+
testsToRun.addAll(testMethods.values());
144+
}
145+
// Arbitrarily sort the tests, so that they are run in the same order every time
146+
testsToRun.sort(Comparator.comparing(Method::getName));
147+
return testsToRun;
151148
}
152149

153150
/**
@@ -177,6 +174,11 @@ private void logImpl(String message, boolean newline) {
177174
}
178175
}
179176

177+
private void logExc(InvocationTargetException ite) {
178+
indent(indentLevel);
179+
ite.getTargetException().printStackTrace(this.log);
180+
}
181+
180182
protected void err(String message) {
181183
errImpl(message, false);
182184
}
@@ -224,20 +226,6 @@ protected void writeTestResult(int count) {
224226
}
225227
}
226228

227-
/*
228-
* Returns a spece-delimited hex String.
229-
*/
230-
protected static String toHexString(String s) {
231-
StringBuilder sb = new StringBuilder(" ");
232-
233-
for (int i = 0; i < s.length(); i++) {
234-
sb.append(Integer.toHexString(s.charAt(i)));
235-
sb.append(' ');
236-
}
237-
238-
return sb.toString();
239-
}
240-
241229
private void indent(int distance) {
242230
if (needLineFeed) {
243231
log.println(" {");
@@ -258,7 +246,7 @@ void usage() {
258246
System.out.println("\t" + methodName);
259247
}
260248
}
261-
249+
private final String testName;
262250
private boolean prompt;
263251
private boolean nothrow;
264252
protected boolean verbose;

0 commit comments

Comments
 (0)