Skip to content

Commit

Permalink
8306711: Improve diagnosis of IntlTest framework
Browse files Browse the repository at this point in the history
Reviewed-by: naoto, lancea
  • Loading branch information
Justin Lu committed Apr 28, 2023
1 parent b827ce8 commit f3c90f0
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 103 deletions.
86 changes: 56 additions & 30 deletions test/jdk/java/text/Normalizer/ICUBasicTest.java
Expand Up @@ -41,6 +41,8 @@
import sun.text.Normalizer;
import jdk.internal.icu.text.NormalizerBase;

import java.util.HexFormat;

import static java.text.Normalizer.Form.*;

public class ICUBasicTest extends IntlTest {
Expand Down Expand Up @@ -149,7 +151,8 @@ public void TestCombiningMarks() {

if (!expected.equals(result)) {
errln("Reordering of combining marks failed. Expected: " +
toHexString(expected) + " Got: "+ toHexString(result));
HexFormat.of().withDelimiter(" ").formatHex(expected.getBytes())
+ " Got: "+ HexFormat.of().withDelimiter(" ").formatHex(result.getBytes()));
}
}

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

String result = NormalizerBase.normalize(input, NFD);
if (!result.equals(output)) {
errln("FAIL input: " + toHexString(input) + "\n" +
" decompose: " + toHexString(result) + "\n" +
" expected: " + toHexString(output));
errln("FAIL input: " + HexFormat.of().withDelimiter(" ")
.formatHex(input.getBytes()) + "\n" +
" decompose: " + HexFormat.of().withDelimiter(" ")
.formatHex(result.getBytes()) + "\n" +
" expected: " + HexFormat.of().withDelimiter(" ")
.formatHex(output.getBytes()));
}

result = NormalizerBase.normalize(input, NFC);
if (!result.equals(output)) {
errln("FAIL input: " + toHexString(input) + "\n" +
" compose: " + toHexString(result) + "\n" +
" expected: " + toHexString(output));
errln("FAIL input: " + HexFormat.of().withDelimiter(" ")
.formatHex(input.getBytes()) + "\n" +
" compose: " + HexFormat.of().withDelimiter(" ")
.formatHex(output.getBytes()) + "\n" +
" expected: " + HexFormat.of().withDelimiter(" ")
.formatHex(output.getBytes()));
}
}
}
Expand Down Expand Up @@ -231,21 +240,27 @@ public void TestZeroIndex() throws Exception {
String exp = DATA[i+1];

if (b.equals(exp)) {
logln("Ok: " + toHexString(a) + " x COMPOSE_COMPAT => " +
toHexString(b));
logln("Ok: " + HexFormat.of().withDelimiter(" ")
.formatHex(a.getBytes()) + " x COMPOSE_COMPAT => " +
HexFormat.of().withDelimiter(" ")
.formatHex(b.getBytes()));
} else {
errln("FAIL: " + toHexString(a) + " x COMPOSE_COMPAT => " +
toHexString(b) + ", expect " + toHexString(exp));
errln("FAIL: " + HexFormat.of().withDelimiter(" ")
.formatHex(b.getBytes()) + " x COMPOSE_COMPAT => " +
HexFormat.of().withDelimiter(" ")
.formatHex(a.getBytes()) + ", expect " +
HexFormat.of().withDelimiter(" ")
.formatHex(exp.getBytes()));
}

a = NormalizerBase.normalize(b, NFD);
exp = DATA[i+2];
if (a.equals(exp)) {
logln("Ok: " + toHexString(b) + " x DECOMP => " +
toHexString(a));
logln("Ok: " + HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x DECOMP => " +
HexFormat.of().withDelimiter(" ").formatHex(a.getBytes()));
} else {
errln("FAIL: " + toHexString(b) + " x DECOMP => " +
toHexString(a) + ", expect " + toHexString(exp));
errln("FAIL: " + HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x DECOMP => " +
HexFormat.of().withDelimiter(" ").formatHex(a.getBytes()) + ", expect " + HexFormat.of().withDelimiter(" ").formatHex(exp.getBytes()));
}
}
}
Expand Down Expand Up @@ -382,25 +397,33 @@ private void checkCompositionExclusion_320(String s) throws Exception {
String c = NormalizerBase.normalize(b, NFC);

if (c.equals(a)) {
errln("FAIL: " + toHexString(a) + " x DECOMP_COMPAT => " +
toHexString(b) + " x COMPOSE => " +
toHexString(c) + " for the latest Unicode");
errln("FAIL: " + HexFormat.of().withDelimiter(" ")
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
HexFormat.of().withDelimiter(" ")
.formatHex(b.getBytes()) + " x COMPOSE => " +
HexFormat.of().withDelimiter(" ")
.formatHex(c.getBytes()) + " for the latest Unicode");
} else if (verbose) {
logln("Ok: " + toHexString(a) + " x DECOMP_COMPAT => " +
toHexString(b) + " x COMPOSE => " +
toHexString(c) + " for the latest Unicode");
logln("Ok: " + HexFormat.of().withDelimiter(" ")
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
HexFormat.of().withDelimiter(" ")
.formatHex(b.getBytes()) + " x COMPOSE => " +
HexFormat.of().withDelimiter(" ")
.formatHex(c.getBytes()) + " for the latest Unicode");
}

b = NormalizerBase.normalize(a, NFKD, Normalizer.UNICODE_3_2);
c = NormalizerBase.normalize(b, NFC, Normalizer.UNICODE_3_2);
if (c.equals(a)) {
errln("FAIL: " + toHexString(a) + " x DECOMP_COMPAT => " +
toHexString(b) + " x COMPOSE => " +
toHexString(c) + " for Unicode 3.2.0");
errln("FAIL: " + HexFormat.of().withDelimiter(" ")
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x COMPOSE => " +
HexFormat.of().withDelimiter(" ").formatHex(c.getBytes()) + " for Unicode 3.2.0");
} else if (verbose) {
logln("Ok: " + toHexString(a) + " x DECOMP_COMPAT => " +
toHexString(b) + " x COMPOSE => " +
toHexString(c) + " for Unicode 3.2.0");
logln("Ok: " + HexFormat.of().withDelimiter(" ")
.formatHex(a.getBytes()) + " x DECOMP_COMPAT => " +
HexFormat.of().withDelimiter(" ").formatHex(b.getBytes()) + " x COMPOSE => " +
HexFormat.of().withDelimiter(" ").formatHex(c.getBytes()) + " for Unicode 3.2.0");
}
}

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

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

if (!output.equals(expect)) {
errln("FAIL: case " + i
+ " expected '" + expect + "' (" + toHexString(expect) + ")"
+ " but got '" + output + "' (" + toHexString(output) + ")"
+ " expected '" + expect + "' (" + HexFormat.of()
.withDelimiter(" ").formatHex(expect.getBytes()) + ")"
+ " but got '" + output + "' (" + HexFormat.of()
.withDelimiter(" ").formatHex(output.getBytes()) + ")"
);
}
}
Expand Down
134 changes: 61 additions & 73 deletions test/jdk/java/text/testlib/IntlTest.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -27,6 +27,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.List;
Expand All @@ -49,10 +50,11 @@ public abstract class IntlTest {
// Everything below here is boilerplate code that makes it possible
// to add a new test by simply adding a method to an existing class.
//------------------------------------------------------------------------

protected IntlTest() {
Class<? extends IntlTest> testClass = getClass();
testName = testClass.getCanonicalName();
// Populate testMethods with all the test methods.
Method[] methods = getClass().getDeclaredMethods();
Method[] methods = testClass.getDeclaredMethods();
for (Method method : methods) {
if (Modifier.isPublic(method.getModifiers())
&& method.getReturnType() == void.class
Expand All @@ -67,71 +69,34 @@ protected IntlTest() {
}
}

protected void run(String[] args) throws Exception
{
protected void run(String[] args) throws Exception {
// Set up the log and reference streams. We use PrintWriters in order to
// take advantage of character conversion. The JavaEsc converter will
// convert Unicode outside the ASCII range to Java's \\uxxxx notation.
log = new PrintWriter(System.out, true);

// Parse the test arguments. They can be either the flag
// "-verbose" or names of test methods. Create a list of
// tests to be run.
List<Method> testsToRun = new ArrayList<>(args.length);
for (String arg : args) {
switch (arg) {
case "-verbose":
verbose = true;
break;
case "-prompt":
prompt = true;
break;
case "-nothrow":
nothrow = true;
break;
case "-exitcode":
exitCode = true;
break;
default:
Method m = testMethods.get(arg);
if (m == null) {
System.out.println("Method " + arg + ": not found");
usage();
return;
}
testsToRun.add(m);
break;
}
}

// If no test method names were given explicitly, run them all.
if (testsToRun.isEmpty()) {
testsToRun.addAll(testMethods.values());
}

System.out.println(getClass().getName() + " {");
List<Method> testsToRun = configureTestsAndArgs(args);
System.out.println(testName + " {");
indentLevel++;

// Run the list of tests given in the test arguments
for (Method testMethod : testsToRun) {
int oldCount = errorCount;

writeTestName(testMethod.getName());

String testName = testMethod.getName();
writeTestName(testName);
try {
testMethod.invoke(this, new Object[0]);
testMethod.invoke(this);
} catch (IllegalAccessException e) {
errln("Can't acces test method " + testMethod.getName());
errln("Can't access test method " + testName);
} catch (InvocationTargetException e) {
errln("Uncaught exception thrown in test method "
+ testMethod.getName());
e.getTargetException().printStackTrace(this.log);
// Log exception first, that way if -nothrow is
// not an arg, the original exception is still logged
logExc(e);
errln(String.format("$$$ Uncaught exception thrown in %s," +
" see above for cause", testName));
}
writeTestResult(errorCount - oldCount);
}
indentLevel--;
writeTestResult(errorCount);

if (prompt) {
System.out.println("Hit RETURN to exit...");
try {
Expand All @@ -140,14 +105,46 @@ protected void run(String[] args) throws Exception
System.out.println("Exception: " + e.toString() + e.getMessage());
}
}
if (nothrow) {
if (exitCode) {
System.exit(errorCount);
}
if (errorCount > 0) {
throw new IllegalArgumentException("encountered " + errorCount + " errors");
if (exitCode) {
System.exit(errorCount);
}
if (errorCount > 0) {
throw new RuntimeException(String.format(
"$$$ %s FAILED with %s failures%n", testName, errorCount));
} else {
log.println(String.format("\t$$$ %s PASSED%n", testName));
}
}

private List<Method> configureTestsAndArgs(String[] args) {
// Parse the test arguments. They can be either the flag
// "-verbose" or names of test methods. Create a list of
// tests to be run.
List<Method> testsToRun = new ArrayList<>(args.length);
for (String arg : args) {
switch (arg) {
case "-verbose" -> verbose = true;
case "-prompt" -> prompt = true;
case "-nothrow" -> nothrow = true;
case "-exitcode" -> exitCode = true;
default -> {
Method m = testMethods.get(arg);
if (m == null) {
System.out.println("Method " + arg + ": not found");
usage();
return testsToRun;
}
testsToRun.add(m);
}
}
}
// If no test method names were given explicitly, run them all.
if (testsToRun.isEmpty()) {
testsToRun.addAll(testMethods.values());
}
// Arbitrarily sort the tests, so that they are run in the same order every time
testsToRun.sort(Comparator.comparing(Method::getName));
return testsToRun;
}

/**
Expand Down Expand Up @@ -177,6 +174,11 @@ private void logImpl(String message, boolean newline) {
}
}

private void logExc(InvocationTargetException ite) {
indent(indentLevel);
ite.getTargetException().printStackTrace(this.log);
}

protected void err(String message) {
errImpl(message, false);
}
Expand Down Expand Up @@ -224,20 +226,6 @@ protected void writeTestResult(int count) {
}
}

/*
* Returns a spece-delimited hex String.
*/
protected static String toHexString(String s) {
StringBuilder sb = new StringBuilder(" ");

for (int i = 0; i < s.length(); i++) {
sb.append(Integer.toHexString(s.charAt(i)));
sb.append(' ');
}

return sb.toString();
}

private void indent(int distance) {
if (needLineFeed) {
log.println(" {");
Expand All @@ -258,7 +246,7 @@ void usage() {
System.out.println("\t" + methodName);
}
}

private final String testName;
private boolean prompt;
private boolean nothrow;
protected boolean verbose;
Expand Down

1 comment on commit f3c90f0

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.