<i18n dev> [8]: diff patch for jdk test on a non US platform

Stuart Marks stuart.marks at oracle.com
Thu Oct 31 14:27:15 PDT 2013


Hi Francis,

Alan Bateman directed me to this patch since it includes changes to the RMI 
tests, which I maintain. I have a few comments on the changes to these tests.

> From: 	Francis ANDRE <francis.andre.kampbell at orange.fr>
>
> Following are a list of patch for making the jdk jtreg test suite happy with a
> WXP/Cygwin/VS2010 Franch platform. For most of them, the fix consists in adding
> Locale.setDefault(Locale.US); as the first statement in main.
>
> diff --git a/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java
> b/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java
> --- a/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java
> +++ b/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java
> @@ -238,7 +238,7 @@
>
>           public synchronized void notifyLine(String s)
>           {
> -            if (s != null && s.indexOf("rmid: debugExec") != -1)
> +            if (s != null && s.indexOf("rmid : debugExec") != -1)
>                   found = s;
>           }
>

This is somewhat odd. This section of the test is capturing the output of rmid 
and is scanning it for a particular string. Why would adding a space be 
necessary? It turns out that the debugExec lines emitted by rmid are localized:


$ cd jdk/src/share/classes/sun/rmi/server/resources
$ grep rmid.exec.command *_*.properties
rmid_de.properties:rmid.exec.command=rmid: debugExec: "{0}" wird ausgef\u00FChrt
rmid_es.properties:rmid.exec.command=rmid: debugExec: en ejecuci\u00F3n "{0}"
rmid_fr.properties:rmid.exec.command=rmid : debugExec : ex\u00E9cution de "{0}"
rmid_it.properties:rmid.exec.command=rmid: debugExec: esecuzione di "{0}" in corso
rmid_ja.properties:rmid.exec.command=rmid: debugExec: "{0}"\u3092\u5B9F\u884C\u4E2D
rmid_ko.properties:rmid.exec.command=rmid: debugExec: "{0}" \uC2E4\uD589 \uC911
rmid_pt_BR.properties:rmid.exec.command=rmid: debugExec: executando "{0}"
rmid_sv.properties:rmid.exec.command=rmid: debugExec: k\u00F6r "{0}"
rmid_zh_CN.properties:rmid.exec.command=rmid: debugExec: 
\u6B63\u5728\u8FD0\u884C "{0}"
rmid_zh_TW.properties:rmid.exec.command=rmid: debugExec: \u57F7\u884C "{0}"
$ grep -B 0 -A 1 rmid.exec.command rmid.properties
rmid.exec.command=\
	rmid: debugExec: running "{0}"


All locales except the French have no space between "rmid" and the trailing 
colon (":"). It appears that having the space before the colon is proper French 
usage (at least, the other French localizations all appear similar). But adding 
the space to the search string will fix the French locale but will break all the 
other locales.

Forcing the test to run in the US locale seems preferable to adding logic to 
deal with different localizations. Since these tests fork JVMs in subprocesses, 
it's probably necessary to do something special to make sure the sub-JVMs are in 
the US locale. This probably involves setting an environment variable or a 
system property. I'm sure others on this list can provide advice.


> diff --git a/test/java/rmi/activation/checkusage/CheckUsage.java
> b/test/java/rmi/activation/checkusage/CheckUsage.java
> --- a/test/java/rmi/activation/checkusage/CheckUsage.java
> +++ b/test/java/rmi/activation/checkusage/CheckUsage.java
> @@ -31,12 +31,20 @@
>    */
>
>   import java.io.ByteArrayOutputStream;
> +import java.util.HashMap;
> +import java.util.Locale;
> +import java.util.Map;
>
>   /**
>    * Make sure that rmid prints out a correct usage statement when run with an
>    * incorrect command line.
>    */
>   public class CheckUsage {
> +    private static final Map<String, String> maps = new HashMap<String, String>();
> +    static {
> +        maps.put(Locale.ENGLISH.getDisplayLanguage(), "runtime flag");
> +        maps.put(Locale.FRENCH.getDisplayLanguage(), "indicateur d'exécution");
> +    }
>       public static void main(String[] args) {
>           try {
>               ByteArrayOutputStream berr = new ByteArrayOutputStream();
> @@ -54,8 +62,9 @@
>               String usage = new String(berr.toByteArray());
>
>               System.err.println("rmid usage: " + usage);
> -
> -            if (usage.indexOf("-J<runtime flag>") < 0) {
> +
> +            String jflag = "-J<" +
> maps.get(Locale.getDefault().getDisplayLanguage()) + ">";
> +            if (usage.indexOf(jflag) < 0) {
>                   TestLibrary.bomb("rmid has incorrect usage message");
>               } else {
>                   System.err.println("test passed");


This change looks like the start of a map that includes localized usage messages 
from various locales. If we were to expand this to other locales, eventually 
we'd end up duplicating all the localized usage messages into the test code. 
That seems pretty fragile.

As above, this is capturing the output of a subprocess, so it would seem better 
if the subprocess were forced into the US locale.

(In fact, this is kind of a stupid test anyway; all it does is make sure that a 
usage message gets emitted if an erroneous command-line option is provided. I've 
been thinking of removing it. It's certainly not worth adding extra logic to 
handle multiple locales.)

--

Do we even support running the test suite in different locales? We test on 
several platforms as it is; I don't think we'll want to have separate test runs 
for all eleven (or however many) different localizations.

I can see adding code (or test configuration properties or environment 
variables) to ensure that tests are run in the US locale, unless this is 
specifically overridden by the test. It doesn't seem appropriate to add 
locale-specific logic or data structures to the tests, though.

s'marks


> diff --git a/test/java/util/Formattable/StockName.java
> b/test/java/util/Formattable/StockName.java
> --- a/test/java/util/Formattable/StockName.java
> +++ b/test/java/util/Formattable/StockName.java
> @@ -33,83 +33,90 @@
>   import static java.util.FormattableFlags.*;
>
>   public class StockName implements Formattable {
> -    private String symbol, companyName, frenchCompanyName;
> +    private String symbol, companyName, frenchCompanyName;
>
> -    public StockName(String symbol, String companyName,
> -                     String frenchCompanyName)
> -    {
> -        this.symbol = symbol;
> -        this.companyName = companyName;
> -        this.frenchCompanyName = frenchCompanyName;
> -    }
> +    public StockName(String symbol, String companyName, String frenchCompanyName) {
> +        this.symbol = symbol;
> +        this.companyName = companyName;
> +        this.frenchCompanyName = frenchCompanyName;
> +    }
>
> -    public void formatTo(Formatter fmt, int f, int width, int precision){
> -        StringBuilder sb = new StringBuilder();
> +    public void formatTo(Formatter fmt, int f, int width, int precision){
> +        StringBuilder sb = new StringBuilder();
>
> -        // decide form of name
> -        String name = companyName;
> -        if (fmt.locale().equals(Locale.FRANCE))
> -            name = frenchCompanyName;
> -        boolean alternate = (f & ALTERNATE) == ALTERNATE;
> -        boolean usesymbol = alternate || (precision != -1 && precision < 10);
> -        String out = (usesymbol ? symbol : name);
> +        // decide form of name
> +        String name = companyName;
> +        if (fmt.locale().equals(Locale.FRANCE))
> +            name = frenchCompanyName;
> +        boolean alternate = (f & ALTERNATE) == ALTERNATE;
> +        boolean usesymbol = alternate || (precision != -1 && precision < 10);
> +        String out = (usesymbol ? symbol : name);
>
> -        // apply precision
> -        if (precision == -1 || out.length() < precision) {
> -            // write it all
> -            sb.append(out);
> -        } else {
> -            sb.append(out.substring(0, precision - 1)).append('*');
> -        }
> +        // apply precision
> +        if (precision == -1 || out.length() < precision) {
> +            // write it all
> +            sb.append(out);
> +        } else {
> +            sb.append(out.substring(0, precision - 1)).append('*');
> +        }
>
> -        // apply width and justification
> -        int len = sb.length();
> -        if (len < width)
> -            for (int i = 0; i < width - len; i++)
> -                if ((f & LEFT_JUSTIFY) == LEFT_JUSTIFY)
> -                    sb.append(' ');
> -                else
> -                    sb.insert(0, ' ');
> +        // apply width and justification
> +        int len = sb.length();
> +        if (len < width)
> +            for (int i = 0; i < width - len; i++)
> +                if ((f & LEFT_JUSTIFY) == LEFT_JUSTIFY)
> +                    sb.append(' ');
> +                else
> +                    sb.insert(0, ' ');
>
> -        fmt.format(sb.toString());
> -    }
> +        fmt.format(sb.toString());
> +    }
>
> -    public String toString() {
> -        return String.format("%s - %s", symbol, companyName);
> -    }
> +    public String toString() {
> +        return String.format("%s - %s", symbol, companyName);
> +    }
>
> -    public static void main(String [] args) {
> -        StockName sn = new StockName("HUGE", "Huge Fruit, Inc.",
> -                                     "Fruit Titanesque, Inc.");
> -        CharBuffer cb = CharBuffer.allocate(128);
> -        Formatter fmt = new Formatter(cb);
> +    public static void main(String[] args) {
> +        StockName sn = new StockName("HUGE", "Huge Fruit, Inc.",
> +                "Fruit Titanesque, Inc.");
> +        CharBuffer cb = CharBuffer.allocate(128);
> +        Formatter fmt = new Formatter(cb);
>
> -        fmt.format("%s", sn);            //   -> "Huge Fruit, Inc."
> -        test(cb, "Huge Fruit, Inc.");
> +        if (fmt.locale().equals(Locale.FRANCE)) {
> +            fmt.format("%s", sn); // -> "Fruit Titanesque, Inc."
> +            test(cb, "Fruit Titanesque, Inc.");
> +        } else {
> +            fmt.format("%s", sn); // -> "Huge Fruit, Inc."
> +            test(cb, "Huge Fruit, Inc.");
> +        }
> +        fmt.format("%s", sn.toString()); // -> "HUGE - Huge Fruit, Inc."
> +        test(cb, "HUGE - Huge Fruit, Inc.");
>
> -        fmt.format("%s", sn.toString()); //   -> "HUGE - Huge Fruit, Inc."
> -        test(cb, "HUGE - Huge Fruit, Inc.");
> +        fmt.format("%#s", sn); // -> "HUGE"
> +        test(cb, "HUGE");
>
> -        fmt.format("%#s", sn);           //   -> "HUGE"
> -        test(cb, "HUGE");
> +        fmt.format("%-10.8s", sn); // -> "HUGE      "
> +        test(cb, "HUGE      ");
>
> -        fmt.format("%-10.8s", sn);       //   -> "HUGE      "
> -        test(cb, "HUGE      ");
> +        if (fmt.locale().equals(Locale.FRANCE)) {
> +            fmt.format("%.12s", sn); // -> "Fruit Titan*"
> +            test(cb, "Fruit Titan*");
> +        } else {
> +            fmt.format("%.12s", sn); // -> "Huge Fruit,*"
> +            test(cb, "Huge Fruit,*");
> +        }
>
> -        fmt.format("%.12s", sn);         //   -> "Huge Fruit,*"
> -        test(cb, "Huge Fruit,*");
> +        fmt.format(Locale.FRANCE, "%25s", sn);
> +        // -> "   Fruit Titanesque, Inc."
> +        test(cb, "   Fruit Titanesque, Inc.");
> +    }
>
> -        fmt.format(Locale.FRANCE, "%25s", sn);
> -                                         //   -> "   Fruit Titanesque, Inc."
> -        test(cb, "   Fruit Titanesque, Inc.");
> -    }
> -
> -    private static void test(CharBuffer cb, String exp) {
> -        cb.limit(cb.position());
> -        cb.rewind();
> -        if (!cb.toString().equals(exp))
> -            throw new RuntimeException("expect: '" + exp + "'; got: '"
> -                                       + cb.toString() + "'");
> -        cb.clear();
> -    }
> +    private static void test(CharBuffer cb, String exp) {
> +        cb.limit(cb.position());
> +        cb.rewind();
> +        if (!cb.toString().equals(exp))
> +            throw new RuntimeException("expect: '" + exp + "'; got: '"
> +                    + cb.toString() + "'");
> +        cb.clear();
> +    }
>   }
> diff --git a/test/java/util/ResourceBundle/ResourceBundleTest.java
> b/test/java/util/ResourceBundle/ResourceBundleTest.java
> --- a/test/java/util/ResourceBundle/ResourceBundleTest.java
> +++ b/test/java/util/ResourceBundle/ResourceBundleTest.java
> @@ -67,6 +67,7 @@
>
>   public class ResourceBundleTest extends RBTestFmwk {
>       public static void main(String[] args) throws Exception {
> +        Locale.setDefault(Locale.US);
>           new ResourceBundleTest().run(args);
>       }
>
> diff --git
> a/test/java/util/ResourceBundle/getBaseBundleName/TestGetBaseBundleName.java
> b/test/java/util/ResourceBundle/getBaseBundleName/TestGetBaseBundleName.java
> --- a/test/java/util/ResourceBundle/getBaseBundleName/TestGetBaseBundleName.java
> +++ b/test/java/util/ResourceBundle/getBaseBundleName/TestGetBaseBundleName.java
> @@ -45,6 +45,7 @@
>       }
>
>       public static void main(String... args) throws Exception {
> +        Locale.setDefault(Locale.US);
>
>           Locale defaultLocale = Locale.getDefault();
>           System.out.println("Default locale is: " + defaultLocale);
> diff --git a/test/java/util/logging/LocalizedLevelName.java
> b/test/java/util/logging/LocalizedLevelName.java
> --- a/test/java/util/logging/LocalizedLevelName.java
> +++ b/test/java/util/logging/LocalizedLevelName.java
> @@ -49,6 +49,7 @@
>       };
>
>       public static void main(String args[]) throws Exception {
> +        Locale.setDefault(Locale.US);
>           Locale defaultLocale = Locale.getDefault();
>           for (int i=0; i<namesMap.length; i += 4) {
>               final String key = (String) namesMap[i];
> diff --git a/test/java/util/logging/SimpleFormatterFormat.java
> b/test/java/util/logging/SimpleFormatterFormat.java
> --- a/test/java/util/logging/SimpleFormatterFormat.java
> +++ b/test/java/util/logging/SimpleFormatterFormat.java
> @@ -30,6 +30,7 @@
>    */
>
>   import java.io.*;
> +import java.util.Locale;
>   import java.util.logging.*;
>   import java.util.regex.*;
>
> @@ -38,7 +39,8 @@
>       private static final String origFormat = System.getProperty(key);
>       private static final PrintStream err = System.err;
>       public static void main(String[] args) throws Exception {
> -        try {
> +       Locale.setDefault(Locale.US);
> +       try {
>               File dir = new File(System.getProperty("user.dir", "."));
>               File log = new File(dir, "simpleformat.txt");
>               java.nio.file.Files.deleteIfExists(log.toPath());
> diff --git a/test/sun/util/logging/SourceClassName.java
> b/test/sun/util/logging/SourceClassName.java
> --- a/test/sun/util/logging/SourceClassName.java
> +++ b/test/sun/util/logging/SourceClassName.java
> @@ -31,12 +31,14 @@
>    * @run main/othervm SourceClassName
>    */
>
> +import java.util.Locale;
>   import java.util.logging.*;
>   import java.io.*;
>   import sun.util.logging.PlatformLogger;
>
>   public class SourceClassName {
>       public static void main(String[] args) throws Exception {
> +        Locale.setDefault(Locale.US);
>           File dir = new File(System.getProperty("user.dir", "."));
>           File log = new File(dir, "testlog.txt");
>           PrintStream logps = new PrintStream(log);
>


More information about the i18n-dev mailing list