diff --git a/.hgtags b/.hgtags index f54925473b1..3ef3763073a 100644 --- a/.hgtags +++ b/.hgtags @@ -386,3 +386,4 @@ d273dfe9a126d3bffe92072547fef2cd1361b0eb jdk-9+138 9aadd2163b568d76f8969ad2fb404a63733da359 jdk-9+141 df0e03e3ca0ed1307793017dfc1a054c8726131c jdk-9+142 d62173b931bf5b6bffc6e80a9060bb2e8b8efc75 jdk-9+143 +31f5023200d42185b70c4c00ba5672391e4642d0 jdk-9+144 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 846b6a11335..27933595820 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -386,3 +386,4 @@ a5815c6098a241d3a1df64d22b84b3524e4a77df jdk-9+140 f64afae7f1a5608e438585bbf0bc23785e69cba0 jdk-9+141 2b3e5caafe3594ea507c37675c4d3086f415dc64 jdk-9+142 1fc62b1c629fb80fdaa639d3b59452a184f0d705 jdk-9+143 +8d337fd6333e28c48aa87880144b840aad82baaf jdk-9+144 diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index eb912119e70..6a0eb9f8e3e 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -942,7 +942,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], # Little endian machine uses ELFv2 ABI. $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power8 -mtune=power8" fi elif test "x$OPENJDK_$1_CPU" = xs390x; then if test "x$OPENJDK_$1_OS" = xlinux; then diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 131556f50ad..238387046d6 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -5093,7 +5093,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1478524503 +DATE_WHEN_GENERATED=1479120453 ############################################################################### # @@ -50124,7 +50124,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA # Little endian machine uses ELFv2 ABI. JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" + JVM_CFLAGS="$JVM_CFLAGS -mcpu=power8 -mtune=power8" fi elif test "x$OPENJDK_TARGET_CPU" = xs390x; then if test "x$OPENJDK_TARGET_OS" = xlinux; then @@ -50948,7 +50948,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA # Little endian machine uses ELFv2 ABI. OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power8 -mtune=power8" fi elif test "x$OPENJDK_BUILD_CPU" = xs390x; then if test "x$OPENJDK_BUILD_OS" = xlinux; then diff --git a/common/bin/compare.sh b/common/bin/compare.sh index 21c9051e426..ba60485ea53 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -372,7 +372,7 @@ compare_general_files() { $CAT $OTHER_DIR/$f | eval "$HTML_FILTER" > $OTHER_FILE & $CAT $THIS_DIR/$f | eval "$HTML_FILTER" > $THIS_FILE & wait - elif [ "$f" = "./lib/classlist" ]; then + elif [[ "$f" = *"/lib/classlist" ]]; then # The classlist files may have some lines in random order OTHER_FILE=$WORK_DIR/$f.other THIS_FILE=$WORK_DIR/$f.this @@ -642,69 +642,18 @@ compare_bin_file() { if [ "$OPENJDK_TARGET_OS" = "windows" ]; then unset _NT_SYMBOL_PATH - # On windows we need to unzip the debug symbols, if present - OTHER_FILE_BASE=${OTHER_FILE/.dll/} - OTHER_FILE_BASE=${OTHER_FILE_BASE/.exe/} - OTHER_FILE_BASE=${OTHER_FILE_BASE/.cpl/} - DIZ_NAME=$(basename $OTHER_FILE_BASE).diz - # Some .exe files have the same name as a .dll file. Make sure the exe - # files get the right debug symbols. - if [ "$NAME" = "java.exe" ] \ - && [ -f "$OTHER/support/native/java.base/java_objs/java.diz" ]; then - OTHER_DIZ_FILE="$OTHER/support/native/java.base/java_objs/java.diz" - elif [ "$NAME" = "jimage.exe" ] \ - && [ -f "$OTHER/support/native/jdk.jlink/jimage_objs/jimage.diz" ]; then - OTHER_DIZ_FILE="$OTHER/support/modules_cmds/jdk.jlink/jimage.diz" - elif [ "$NAME" = "javacpl.exe" ] \ - && [ -f "$OTHER/support/native/jdk.plugin/javacpl/javacpl.diz" ]; then - OTHER_DIZ_FILE="$OTHER/support/modules_cmds/jdk.deploy.controlpanel/javacpl.diz" - elif [ -f "${OTHER_FILE_BASE}.diz" ]; then - OTHER_DIZ_FILE=${OTHER_FILE_BASE}.diz - else - # Some files, jli.dll, appears twice in the image but only one of - # them has a diz file next to it. - OTHER_DIZ_FILE="$($FIND $OTHER_DIR -name $DIZ_NAME | $SED 1q)" - if [ ! -f "$OTHER_DIZ_FILE" ]; then - # As a last resort, look for diz file in the whole build output - # dir. - OTHER_DIZ_FILE="$($FIND $OTHER -name $DIZ_NAME | $SED 1q)" - fi - fi - if [ -n "$OTHER_DIZ_FILE" ]; then - $MKDIR -p $FILE_WORK_DIR/other - (cd $FILE_WORK_DIR/other ; $UNARCHIVE -o $OTHER_DIZ_FILE) - export _NT_SYMBOL_PATH="$FILE_WORK_DIR/other" - fi - - THIS_FILE_BASE=${THIS_FILE/.dll/} - THIS_FILE_BASE=${THIS_FILE_BASE/.exe/} - THIS_FILE_BASE=${THIS_FILE_BASE/.cpl/} - # Some .exe files have the same name as a .dll file. Make sure the exe - # files get the right debug symbols. - if [ "$NAME" = "java.exe" ] \ - && [ -f "$THIS/support/native/java.base/java_objs/java.diz" ]; then - THIS_DIZ_FILE="$THIS/support/native/java.base/java_objs/java.diz" - elif [ "$NAME" = "jimage.exe" ] \ - && [ -f "$THIS/support/native/jdk.jlink/jimage_objs/jimage.diz" ]; then - THIS_DIZ_FILE="$THIS/support/modules_cmds/jdk.jlink/jimage.diz" - elif [ "$NAME" = "javacpl.exe" ] \ - && [ -f "$THIS/support/native/jdk.plugin/javacpl/javacpl.diz" ]; then - THIS_DIZ_FILE="$THIS/support/modules_cmds/jdk.deploy.controlpanel/javacpl.diz" - elif [ -f "${THIS_FILE_BASE}.diz" ]; then - THIS_DIZ_FILE=${THIS_FILE/.dll/}.diz - else - THIS_DIZ_FILE="$($FIND $THIS_DIR -name $DIZ_NAME | $SED 1q)" - if [ ! -f "$THIS_DIZ_FILE" ]; then - # As a last resort, look for diz file in the whole build output - # dir. - THIS_DIZ_FILE="$($FIND $THIS -name $DIZ_NAME | $SED 1q)" - fi - fi - if [ -n "$THIS_DIZ_FILE" ]; then - $MKDIR -p $FILE_WORK_DIR/this - (cd $FILE_WORK_DIR/this ; $UNARCHIVE -o $THIS_DIZ_FILE) - export _NT_SYMBOL_PATH="$_NT_SYMBOL_PATH;$FILE_WORK_DIR/this" + if [ "$(uname -o)" = "Cygwin" ]; then + THIS=$(cygpath -msa $THIS) + OTHER=$(cygpath -msa $OTHER) fi + # Build an _NT_SYMBOL_PATH that contains all known locations for + # pdb files. + PDB_DIRS="$(ls -d \ + {$OTHER,$THIS}/support/modules_{cmds,libs}/{*,*/*} \ + {$OTHER,$THIS}/support/demos/image/jvmti/*/lib \ + {$OTHER,$THIS}/support/native/java.base/java_objs \ + )" + export _NT_SYMBOL_PATH="$(echo $PDB_DIRS | tr ' ' ';')" fi if [ -z "$SKIP_BIN_DIFF" ]; then diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index a4c4278299a..5042cdcc104 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -431,6 +431,8 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then ACCEPTED_JARZIP_CONTENTS=" /modules_libs/java.security.jgss/w2k_lsa_auth.diz + /modules_libs/java.security.jgss/w2k_lsa_auth.pdb + /modules_libs/java.security.jgss/w2k_lsa_auth.map /modules_libs/java.security.jgss/w2k_lsa_auth.dll " diff --git a/corba/.hgtags b/corba/.hgtags index c96fdd40202..7ec4e1bd79d 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -386,3 +386,4 @@ aa053a3faf266c12b4fd5272da431a3e08e4a3e3 jdk-9+136 b32f998da32b488ec7c4e9dbb3c750841b48e74d jdk-9+141 408c9c621938ca028e20bced0459f815de47eba8 jdk-9+142 6211236ef15ec796806357608b1dd1b70c258ece jdk-9+143 +d4f1dae174098e799c48948e866054c52e11a186 jdk-9+144 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 4ff5566b655..5ab3bfa0769 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -546,3 +546,4 @@ fec31089c2ef5a12dd64f401b0bf2e00f56ee0d0 jdk-9+140 160a00bc6ed0af1fdf8418fc65e6bddbbc0c536d jdk-9+141 7b48d63dfd6b8e2657288de3d7b1f153dee02d7e jdk-9+142 d87d5d430c42342f0320ca7f5cbe0cbd1f9d62ba jdk-9+143 +6187b582d02aee38341dc8ce4011906e9b364e9f jdk-9+144 diff --git a/jaxp/.hgtags b/jaxp/.hgtags index addee1762c9..900943ec381 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -386,3 +386,4 @@ a8d5fe567ae72b4931040e59dd4478363f9004f5 jdk-9+137 037c095ba0c345edbeaaab52fda913a76c3930c0 jdk-9+141 bdafa0cc34a97a2f8db4847a4efd34b407943591 jdk-9+142 ce81d03ad7320dca3d673374c1a33bc0efd9136a jdk-9+143 +99be33734ff62b75116b1202d49a4d4e1bda4226 jdk-9+144 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 790219ed5e4..5d90ddab9df 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -389,3 +389,4 @@ ab1d78d395d4cb8be426ff181211da1a4085cf01 jdk-9+134 b2c18f755228d1d19a86cd7d5fa1abb6b1495dfb jdk-9+141 59101416d90160cfcb4f45dfbccaec15e2c27a29 jdk-9+142 1c988e708a06257119d54d8a57e99e3b0f37ff18 jdk-9+143 +92523c51d6a48b0a83912ba3cc43bc57b8159c2a jdk-9+144 diff --git a/jdk/.hgtags b/jdk/.hgtags index d39ded9908c..766e790c648 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -387,3 +387,4 @@ e93b7ea559759f036c9f69fd2ddaf47bb4e98385 jdk-9+140 6ce43dd8e954b452f330dd7a412df5107f7e1923 jdk-9+142 8dbc8594f9d5149bf1c22221272284609408227a jdk-9+143 efa71dc820eb8bd5a6c9f2f66f39c383ac3ee99d jdk-9+144 +99b7853cfbd8227c4441de4b6119c10742556840 jdk-9+145 diff --git a/jdk/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java b/jdk/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java index e6a2b584d96..f34274eed99 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java +++ b/jdk/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -118,7 +118,7 @@ class EPollArrayWrapper { // file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at // least) then the update is stored in a map. private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE]; - private Map eventsHigh; + private final Map eventsHigh = new HashMap<>(); // Used by release and updateRegistrations to track whether a file // descriptor is registered with epoll. @@ -133,10 +133,6 @@ class EPollArrayWrapper { int allocationSize = NUM_EPOLLEVENTS * SIZE_EPOLLEVENT; pollArray = new AllocatedNativeObject(allocationSize, true); pollArrayAddress = pollArray.address(); - - // eventHigh needed when using file descriptors > 64k - if (OPEN_MAX > MAX_UPDATE_ARRAY_SIZE) - eventsHigh = new HashMap<>(); } void initInterrupt(int fd0, int fd1) { diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index 725d237aff6..36d458720c0 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -2704,9 +2704,6 @@ public final class Class implements java.io.Serializable, * Reflection support. */ - // Caches for certain reflective results - private static boolean useCaches = true; - // reflection data that might get invalidated when JVM TI RedefineClasses() is called private static class ReflectionData { volatile Field[] declaredFields; @@ -2739,8 +2736,7 @@ public final class Class implements java.io.Serializable, SoftReference> reflectionData = this.reflectionData; int classRedefinedCount = this.classRedefinedCount; ReflectionData rd; - if (useCaches && - reflectionData != null && + if (reflectionData != null && (rd = reflectionData.get()) != null && rd.redefinedCount == classRedefinedCount) { return rd; @@ -2752,8 +2748,6 @@ public final class Class implements java.io.Serializable, private ReflectionData newReflectionData(SoftReference> oldReflectionData, int classRedefinedCount) { - if (!useCaches) return null; - while (true) { ReflectionData rd = new ReflectionData<>(classRedefinedCount); // try to CAS it... @@ -2819,7 +2813,6 @@ public final class Class implements java.io.Serializable, // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyField. private Field[] privateGetDeclaredFields(boolean publicOnly) { - checkInitted(); Field[] res; ReflectionData rd = reflectionData(); if (rd != null) { @@ -2842,7 +2835,6 @@ public final class Class implements java.io.Serializable, // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyField. private Field[] privateGetPublicFields(Set> traversedInterfaces) { - checkInitted(); Field[] res; ReflectionData rd = reflectionData(); if (rd != null) { @@ -2902,7 +2894,6 @@ public final class Class implements java.io.Serializable, // objects must NOT be propagated to the outside world, but must // instead be copied via ReflectionFactory.copyConstructor. private Constructor[] privateGetDeclaredConstructors(boolean publicOnly) { - checkInitted(); Constructor[] res; ReflectionData rd = reflectionData(); if (rd != null) { @@ -2937,7 +2928,6 @@ public final class Class implements java.io.Serializable, // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyMethod. private Method[] privateGetDeclaredMethods(boolean publicOnly) { - checkInitted(); Method[] res; ReflectionData rd = reflectionData(); if (rd != null) { @@ -3134,7 +3124,6 @@ public final class Class implements java.io.Serializable, // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyMethod. private Method[] privateGetPublicMethods() { - checkInitted(); Method[] res; ReflectionData rd = reflectionData(); if (rd != null) { @@ -3445,7 +3434,7 @@ public final class Class implements java.io.Serializable, * @since 1.4 */ public boolean desiredAssertionStatus() { - ClassLoader loader = getClassLoader(); + ClassLoader loader = getClassLoader0(); // If the loader is null this is a system class, so ask the VM if (loader == null) return desiredAssertionStatus0(this); @@ -3490,39 +3479,6 @@ public final class Class implements java.io.Serializable, } private static ReflectionFactory reflectionFactory; - // To be able to query system properties as soon as they're available - private static boolean initted = false; - private static void checkInitted() { - if (initted) return; - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - // Tests to ensure the system properties table is fully - // initialized. This is needed because reflection code is - // called very early in the initialization process (before - // command-line arguments have been parsed and therefore - // these user-settable properties installed.) We assume that - // if System.out is non-null then the System class has been - // fully initialized and that the bulk of the startup code - // has been run. - - if (System.out == null) { - // java.lang.System not yet fully initialized - return null; - } - - // Doesn't use Boolean.getBoolean to avoid class init. - String val = - System.getProperty("sun.reflect.noCaches"); - if (val != null && val.equals("true")) { - useCaches = false; - } - - initted = true; - return null; - } - }); - } - /** * Returns the elements of this enum class or null if this * Class object does not represent an enum type. diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java index 395e80ca6b0..cec436690b9 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -80,7 +80,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; default : throw newInternalError("unexpected xtype: " + xtype); } } catch (Throwable t) { - throw newInternalError(t); + throw uncaughtException(t); } } @@ -188,7 +188,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; case D_TYPE: return (double) speciesData().getters[i].invokeBasic(this); } } catch (Throwable ex) { - throw newInternalError(ex); + throw uncaughtException(ex); } throw new InternalError("unexpected type: " + speciesData().typeChars+"."+i); } @@ -408,18 +408,14 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; */ static boolean speciesDataCachePopulated() { Class rootCls = BoundMethodHandle.class; - try { - for (Class c : rootCls.getDeclaredClasses()) { - if (rootCls.isAssignableFrom(c)) { - final Class cbmh = c.asSubclass(BoundMethodHandle.class); - SpeciesData d = Factory.getSpeciesDataFromConcreteBMHClass(cbmh); - assert(d != null) : cbmh.getName(); - assert(d.clazz == cbmh); - assert(CACHE.get(d.typeChars) == d); - } + for (Class c : rootCls.getDeclaredClasses()) { + if (rootCls.isAssignableFrom(c)) { + final Class cbmh = c.asSubclass(BoundMethodHandle.class); + SpeciesData d = Factory.getSpeciesDataFromConcreteBMHClass(cbmh); + assert(d != null) : cbmh.getName(); + assert(d.clazz == cbmh); + assert(CACHE.get(d.typeChars) == d); } - } catch (Throwable e) { - throw newInternalError(e); } return true; } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java index df245e661e9..c24f94951f0 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -272,7 +272,7 @@ public class CallSite { MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget); } - // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite: + // this implements the upcall from the JVM, MethodHandleNatives.linkCallSite: static CallSite makeSite(MethodHandle bootstrapMethod, // Callee information: String name, MethodType type, @@ -293,59 +293,72 @@ public class CallSite { Object[] argv = (Object[]) info; maybeReBoxElements(argv); switch (argv.length) { - case 0: - binding = bootstrapMethod.invoke(caller, name, type); - break; - case 1: - binding = bootstrapMethod.invoke(caller, name, type, - argv[0]); - break; - case 2: - binding = bootstrapMethod.invoke(caller, name, type, - argv[0], argv[1]); - break; - case 3: - binding = bootstrapMethod.invoke(caller, name, type, - argv[0], argv[1], argv[2]); - break; - case 4: - binding = bootstrapMethod.invoke(caller, name, type, - argv[0], argv[1], argv[2], argv[3]); - break; - case 5: - binding = bootstrapMethod.invoke(caller, name, type, - argv[0], argv[1], argv[2], argv[3], argv[4]); - break; - case 6: - binding = bootstrapMethod.invoke(caller, name, type, - argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); - break; - default: - final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type) - if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY) - throw new BootstrapMethodError("too many bootstrap method arguments"); - MethodType bsmType = bootstrapMethod.type(); - MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length); - MethodHandle typedBSM = bootstrapMethod.asType(invocationType); - MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT); - binding = spreader.invokeExact(typedBSM, (Object)caller, (Object)name, (Object)type, argv); + case 0: + binding = bootstrapMethod.invoke(caller, name, type); + break; + case 1: + binding = bootstrapMethod.invoke(caller, name, type, + argv[0]); + break; + case 2: + binding = bootstrapMethod.invoke(caller, name, type, + argv[0], argv[1]); + break; + case 3: + binding = bootstrapMethod.invoke(caller, name, type, + argv[0], argv[1], argv[2]); + break; + case 4: + binding = bootstrapMethod.invoke(caller, name, type, + argv[0], argv[1], argv[2], argv[3]); + break; + case 5: + binding = bootstrapMethod.invoke(caller, name, type, + argv[0], argv[1], argv[2], argv[3], argv[4]); + break; + case 6: + binding = bootstrapMethod.invoke(caller, name, type, + argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + break; + default: + final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type) + if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY) + throw new BootstrapMethodError("too many bootstrap method arguments"); + MethodType bsmType = bootstrapMethod.type(); + MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length); + MethodHandle typedBSM = bootstrapMethod.asType(invocationType); + MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT); + binding = spreader.invokeExact(typedBSM, (Object) caller, (Object) name, (Object) type, argv); } } - //System.out.println("BSM for "+name+type+" => "+binding); if (binding instanceof CallSite) { site = (CallSite) binding; - } else { + } else { + // See the "Linking Exceptions" section for the invokedynamic + // instruction in JVMS 6.5. + // Throws a runtime exception defining the cause that is then + // in the "catch (Throwable ex)" a few lines below wrapped in + // BootstrapMethodError throw new ClassCastException("bootstrap method failed to produce a CallSite"); } - if (!site.getTarget().type().equals(type)) + if (!site.getTarget().type().equals(type)) { + // See the "Linking Exceptions" section for the invokedynamic + // instruction in JVMS 6.5. + // Throws a runtime exception defining the cause that is then + // in the "catch (Throwable ex)" a few lines below wrapped in + // BootstrapMethodError throw wrongTargetType(site.getTarget(), type); + } + } catch (Error e) { + // Pass through an Error, including BootstrapMethodError, any other + // form of linkage error, such as IllegalAccessError if the bootstrap + // method is inaccessible, or say ThreadDeath/OutOfMemoryError + // See the "Linking Exceptions" section for the invokedynamic + // instruction in JVMS 6.5. + throw e; } catch (Throwable ex) { - BootstrapMethodError bex; - if (ex instanceof BootstrapMethodError) - bex = (BootstrapMethodError) ex; - else - bex = new BootstrapMethodError("call site initialization exception", ex); - throw bex; + // Wrap anything else in BootstrapMethodError + throw new BootstrapMethodError("call site initialization exception", ex); } return site; } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index ea6236aa2d9..d903d488211 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -1021,7 +1021,7 @@ class InvokerBytecodeGenerator { try { emptyArray = name.function.resolvedHandle().invoke(); } catch (Throwable ex) { - throw newInternalError(ex); + throw uncaughtException(ex); } assert(java.lang.reflect.Array.getLength(emptyArray) == 0); assert(emptyArray.getClass() == rtype); // exact typing diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index bcc825bcf15..96b0a944800 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -855,7 +855,11 @@ class LambdaForm { System.out.println("LambdaForm compilation failed: " + this); bge.printStackTrace(System.out); } - } catch (Error | Exception e) { + } catch (Error e) { + // Pass through any error + throw e; + } catch (Exception e) { + // Wrap any exception throw newInternalError(this.toString(), e); } } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 13a3e0a990e..6265b874175 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -957,7 +957,7 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray if (!fail) return needType; // elicit an error: this.asType(needType); - throw newInternalError("should not return", null); + throw newInternalError("should not return"); } private void spreadArrayChecks(Class arrayType, int arrayLength) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index b364a3e5ace..1065b8d1482 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -379,11 +379,13 @@ class MethodHandleNatives { name, fixMethodType(callerClass, type), appendixResult); } } + } catch (Error e) { + // Pass through an Error, including say StackOverflowError or + // OutOfMemoryError + throw e; } catch (Throwable ex) { - if (ex instanceof LinkageError) - throw (LinkageError) ex; - else - throw new LinkageError(ex.getMessage(), ex); + // Wrap anything else in LinkageError + throw new LinkageError(ex.getMessage(), ex); } throw new LinkageError("no such method "+defc.getName()+"."+name+type); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index 22408f1b55a..f05cdda8166 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -107,10 +107,10 @@ import java.util.Properties; /*non-public*/ static InternalError newInternalError(String message) { return new InternalError(message); } - /*non-public*/ static InternalError newInternalError(String message, Throwable cause) { + /*non-public*/ static InternalError newInternalError(String message, Exception cause) { return new InternalError(message, cause); } - /*non-public*/ static InternalError newInternalError(Throwable cause) { + /*non-public*/ static InternalError newInternalError(Exception cause) { return new InternalError(cause); } /*non-public*/ static RuntimeException newIllegalStateException(String message) { @@ -132,7 +132,7 @@ import java.util.Properties; /*non-public*/ static Error uncaughtException(Throwable ex) { if (ex instanceof Error) throw (Error) ex; if (ex instanceof RuntimeException) throw (RuntimeException) ex; - throw newInternalError("uncaught exception", ex); + throw new InternalError("uncaught exception", ex); } private static String message(String message, Object obj) { if (obj != null) message = message + ": " + obj; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 4b336f4c6b1..6c94fb3eb36 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -723,6 +723,9 @@ public final class StringConcatFactory { default: throw new StringConcatException("Concatenation strategy " + STRATEGY + " is not implemented"); } + } catch (Error | StringConcatException e) { + // Pass through any error or existing StringConcatException + throw e; } catch (Throwable t) { throw new StringConcatException("Generator failed", t); } @@ -1092,9 +1095,9 @@ public final class StringConcatFactory { UNSAFE.ensureClassInitialized(innerClass); dumpIfEnabled(innerClass.getName(), classBytes); return Lookup.IMPL_LOOKUP.findStatic(innerClass, METHOD_NAME, args); - } catch (Throwable e) { + } catch (Exception e) { dumpIfEnabled(className + "$$FAILED", classBytes); - throw new StringConcatException("Error while spinning the class", e); + throw new StringConcatException("Exception while spinning the class", e); } } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java b/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java index a6d8e41c48c..ba1d84a8911 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -84,20 +84,21 @@ * * Invocation is as if by * {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}. - * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass). + * The returned result must be a {@link java.lang.invoke.CallSite CallSite} + * (or a subclass), otherwise a + * {@link java.lang.BootstrapMethodError BootstrapMethodError} is thrown. * The type of the call site's target must be exactly equal to the type * derived from the dynamic call site's type descriptor and passed to - * the bootstrap method. - * The call site then becomes permanently linked to the dynamic call site. + * the bootstrap method, otherwise a {@code BootstrapMethodError} is thrown. + * On success the call site then becomes permanently linked to the dynamic call + * site. *

- * As documented in the JVM specification, all failures arising from - * the linkage of a dynamic call site are reported - * by a {@link java.lang.BootstrapMethodError BootstrapMethodError}, - * which is thrown as the abnormal termination of the dynamic call - * site execution. - * If this happens, the same error will the thrown for all subsequent - * attempts to execute the dynamic call site. - * + * If an exception, {@code E} say, occurs when linking the call site then the + * linkage fails and terminates abnormally. {@code E} is rethrown if the type of + * {@code E} is {@code Error} or a subclass, otherwise a + * {@code BootstrapMethodError} that wraps {@code E} is thrown. + * If this happens, the same {@code Error} or subclass will the thrown for all + * subsequent attempts to execute the dynamic call site. *

timing of linkage

* A dynamic call site is linked just before its first execution. * The bootstrap method call implementing the linkage occurs within diff --git a/jdk/src/java.base/share/classes/java/net/Authenticator.java b/jdk/src/java.base/share/classes/java/net/Authenticator.java index 8b59db010f3..81a87c79987 100644 --- a/jdk/src/java.base/share/classes/java/net/Authenticator.java +++ b/jdk/src/java.base/share/classes/java/net/Authenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -130,6 +130,35 @@ class Authenticator { theAuthenticator = a; } + /** + * Gets the default authenticator. + * First, if there is a security manager, its {@code checkPermission} + * method is called with a + * {@code NetPermission("requestPasswordAuthentication")} permission. + * This may result in a java.lang.SecurityException. + * Then the default authenticator, if set, is returned. + * Otherwise, {@code null} is returned. + * + * @return The default authenticator, if set, {@code null} otherwise. + * + * @throws SecurityException + * if a security manager exists and its + * {@code checkPermission} method doesn't allow + * requesting password authentication. + * @since 9 + * @see SecurityManager#checkPermission + * @see java.net.NetPermission + */ + public static Authenticator getDefault() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + NetPermission requestPermission + = new NetPermission("requestPasswordAuthentication"); + sm.checkPermission(requestPermission); + } + return theAuthenticator; + } + /** * Ask the authenticator that has been registered with the system * for a password. diff --git a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java index 1f614d250f2..ecb12785591 100644 --- a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java +++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java @@ -32,6 +32,7 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import jdk.internal.misc.JavaSecurityAccess; import jdk.internal.misc.JavaSecurityProtectionDomainAccess; @@ -524,7 +525,7 @@ public class ProtectionDomain { // have some side effects so this manual // comparison is sufficient. if (pdpName.equals(pp.getName()) && - pdpActions.equals(pp.getActions())) { + Objects.equals(pdpActions, pp.getActions())) { plVector.remove(i); break; } diff --git a/jdk/src/java.base/share/classes/java/security/SecureRandom.java b/jdk/src/java.base/share/classes/java/security/SecureRandom.java index 8449613ba66..12b60f688e0 100644 --- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java +++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java @@ -120,6 +120,24 @@ import sun.security.util.Debug; * gathered, for example, if the entropy source is /dev/random on various * Unix-like operating systems. * + *

Thread safety

+ * {@code SecureRandom} objects are safe for use by multiple concurrent threads. + * + * @implSpec + * A {@code SecureRandom} service provider can advertise that it is thread-safe + * by setting the service + * provider attribute "ThreadSafe" to "true" when registering the provider. + * Otherwise, this class will instead synchronize access to the following + * methods of the {@code SecureRandomSpi} implementation: + *
    + *
  • {@link SecureRandomSpi#engineSetSeed(byte[])} + *
  • {@link SecureRandomSpi#engineNextBytes(byte[])} + *
  • {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)} + *
  • {@link SecureRandomSpi#engineGenerateSeed(int)} + *
  • {@link SecureRandomSpi#engineReseed(SecureRandomParameters)} + *
+ * * @see java.security.SecureRandomSpi * @see java.util.Random * @@ -150,6 +168,14 @@ public class SecureRandom extends java.util.Random { */ private SecureRandomSpi secureRandomSpi = null; + /** + * Thread safety. + * + * @serial + * @since 9 + */ + private final boolean threadSafe; + /* * The algorithm name of null if unknown. * @@ -189,6 +215,16 @@ public class SecureRandom extends java.util.Random { */ super(0); getDefaultPRNG(false, null); + this.threadSafe = getThreadSafe(); + } + + private boolean getThreadSafe() { + if (provider == null || algorithm == null) { + return false; + } else { + return Boolean.parseBoolean(provider.getProperty( + "SecureRandom." + algorithm + " ThreadSafe", "false")); + } } /** @@ -217,6 +253,7 @@ public class SecureRandom extends java.util.Random { public SecureRandom(byte[] seed) { super(0); getDefaultPRNG(true, seed); + this.threadSafe = getThreadSafe(); } private void getDefaultPRNG(boolean setSeed, byte[] seed) { @@ -269,6 +306,7 @@ public class SecureRandom extends java.util.Random { this.secureRandomSpi = secureRandomSpi; this.provider = provider; this.algorithm = algorithm; + this.threadSafe = getThreadSafe(); if (!skipDebug && pdebug != null) { pdebug.println("SecureRandom." + algorithm + @@ -653,8 +691,14 @@ public class SecureRandom extends java.util.Random { * * @see #getSeed */ - public synchronized void setSeed(byte[] seed) { - secureRandomSpi.engineSetSeed(seed); + public void setSeed(byte[] seed) { + if (threadSafe) { + secureRandomSpi.engineSetSeed(seed); + } else { + synchronized (this) { + secureRandomSpi.engineSetSeed(seed); + } + } } /** @@ -679,7 +723,7 @@ public class SecureRandom extends java.util.Random { * yet been initialized at that point. */ if (seed != 0) { - this.secureRandomSpi.engineSetSeed(longToByteArray(seed)); + setSeed(longToByteArray(seed)); } } @@ -690,7 +734,13 @@ public class SecureRandom extends java.util.Random { */ @Override public void nextBytes(byte[] bytes) { - secureRandomSpi.engineNextBytes(bytes); + if (threadSafe) { + secureRandomSpi.engineNextBytes(bytes); + } else { + synchronized (this) { + secureRandomSpi.engineNextBytes(bytes); + } + } } /** @@ -707,12 +757,19 @@ public class SecureRandom extends java.util.Random { * * @since 9 */ - public synchronized void nextBytes( - byte[] bytes, SecureRandomParameters params) { + public void nextBytes(byte[] bytes, SecureRandomParameters params) { if (params == null) { throw new IllegalArgumentException("params cannot be null"); } - secureRandomSpi.engineNextBytes(Objects.requireNonNull(bytes), params); + if (threadSafe) { + secureRandomSpi.engineNextBytes( + Objects.requireNonNull(bytes), params); + } else { + synchronized (this) { + secureRandomSpi.engineNextBytes( + Objects.requireNonNull(bytes), params); + } + } } /** @@ -756,6 +813,7 @@ public class SecureRandom extends java.util.Random { * * @param numBytes the number of seed bytes to generate. * + * @throws IllegalArgumentException if {@code numBytes} is negative * @return the seed bytes. * * @see #setSeed @@ -782,7 +840,13 @@ public class SecureRandom extends java.util.Random { if (numBytes < 0) { throw new IllegalArgumentException("numBytes cannot be negative"); } - return secureRandomSpi.engineGenerateSeed(numBytes); + if (threadSafe) { + return secureRandomSpi.engineGenerateSeed(numBytes); + } else { + synchronized (this) { + return secureRandomSpi.engineGenerateSeed(numBytes); + } + } } /** @@ -917,8 +981,14 @@ public class SecureRandom extends java.util.Random { * * @since 9 */ - public synchronized void reseed() { - secureRandomSpi.engineReseed(null); + public void reseed() { + if (threadSafe) { + secureRandomSpi.engineReseed(null); + } else { + synchronized (this) { + secureRandomSpi.engineReseed(null); + } + } } /** @@ -937,11 +1007,17 @@ public class SecureRandom extends java.util.Random { * * @since 9 */ - public synchronized void reseed(SecureRandomParameters params) { + public void reseed(SecureRandomParameters params) { if (params == null) { throw new IllegalArgumentException("params cannot be null"); } - secureRandomSpi.engineReseed(params); + if (threadSafe) { + secureRandomSpi.engineReseed(params); + } else { + synchronized (this) { + secureRandomSpi.engineReseed(params); + } + } } // Declare serialVersionUID to be compatible with JDK1.1 diff --git a/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java b/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java index 9aa24f57bc8..65a0ce0164d 100644 --- a/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java +++ b/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java @@ -58,6 +58,26 @@ package java.security; * a {@code SecureRandomParameters} argument will never * return an instance of this implementation. The * {@link #engineGetParameters()} method must return {@code null}. + *

+ * See {@link SecureRandom} for additional details on thread safety. By + * default, a {@code SecureRandomSpi} implementation is considered to be + * not safe for use by multiple concurrent threads and {@code SecureRandom} + * will synchronize access to each of the applicable engine methods + * (see {@link SecureRandom} for the list of methods). However, if a + * {@code SecureRandomSpi} implementation is thread-safe, the + * service provider attribute "ThreadSafe" should be set to "true" during + * its registration, as follows: + *

+ * put("SecureRandom.AlgName ThreadSafe", "true");
+ *
+ * or + *
+ * putService(new Service(this, "SecureRandom", "AlgName", className,
+ *          null, Map.of("ThreadSafe", "true")));
+ *
+ * {@code SecureRandom} will call the applicable engine methods + * without any synchronization. * * @since 1.2 */ diff --git a/jdk/src/java.base/share/classes/java/time/ZoneId.java b/jdk/src/java.base/share/classes/java/time/ZoneId.java index 5087888da4f..d3aa95b6443 100644 --- a/jdk/src/java.base/share/classes/java/time/ZoneId.java +++ b/jdk/src/java.base/share/classes/java/time/ZoneId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -76,6 +76,7 @@ import java.time.temporal.UnsupportedTemporalTypeException; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesException; import java.time.zone.ZoneRulesProvider; +import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -284,7 +285,7 @@ public abstract class ZoneId implements Serializable { * @return a modifiable copy of the set of zone IDs, not null */ public static Set getAvailableZoneIds() { - return ZoneRulesProvider.getAvailableZoneIds(); + return new HashSet(ZoneRulesProvider.getAvailableZoneIds()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java b/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java index 811bd5b2ee1..0faec561724 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -302,14 +302,10 @@ final class DateTimePrintContext { * @throws DateTimeException if the field is not available and the section is not optional */ Long getValue(TemporalField field) { - try { - return temporal.getLong(field); - } catch (DateTimeException ex) { - if (optional > 0) { - return null; - } - throw ex; + if (optional > 0 && !temporal.isSupported(field)) { + return null; } + return temporal.getLong(field); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java b/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java index 8e91eae0bbd..4014c23c083 100644 --- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java +++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -77,6 +77,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.Collections; /** * Provider of time-zone rules to the system. @@ -137,6 +138,11 @@ public abstract class ZoneRulesProvider { */ private static final ConcurrentMap ZONES = new ConcurrentHashMap<>(512, 0.75f, 2); + /** + * The zone ID data + */ + private static volatile Set ZONE_IDS; + static { // if the property java.time.zone.DefaultZoneRulesProvider is // set then its value is the class name of the default provider @@ -194,10 +200,10 @@ public abstract class ZoneRulesProvider { *

* These IDs are the string form of a {@link ZoneId}. * - * @return a modifiable copy of the set of zone IDs, not null + * @return the unmodifiable set of zone IDs, not null */ public static Set getAvailableZoneIds() { - return new HashSet<>(ZONES.keySet()); + return ZONE_IDS; } /** @@ -303,7 +309,7 @@ public abstract class ZoneRulesProvider { * @param provider the provider to register, not null * @throws ZoneRulesException if unable to complete the registration */ - private static void registerProvider0(ZoneRulesProvider provider) { + private static synchronized void registerProvider0(ZoneRulesProvider provider) { for (String zoneId : provider.provideZoneIds()) { Objects.requireNonNull(zoneId, "zoneId"); ZoneRulesProvider old = ZONES.putIfAbsent(zoneId, provider); @@ -313,6 +319,8 @@ public abstract class ZoneRulesProvider { ", currently loading from provider: " + provider); } } + Set combinedSet = new HashSet(ZONES.keySet()); + ZONE_IDS = Collections.unmodifiableSet(combinedSet); } /** diff --git a/jdk/src/java.base/share/classes/java/util/BitSet.java b/jdk/src/java.base/share/classes/java/util/BitSet.java index f65035f0601..4e35b34ae9f 100644 --- a/jdk/src/java.base/share/classes/java/util/BitSet.java +++ b/jdk/src/java.base/share/classes/java/util/BitSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, 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 @@ -29,6 +29,7 @@ import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.LongBuffer; +import java.util.function.IntConsumer; import java.util.stream.IntStream; import java.util.stream.StreamSupport; @@ -1217,32 +1218,156 @@ public class BitSet implements Cloneable, java.io.Serializable { * @since 1.8 */ public IntStream stream() { - class BitSetIterator implements PrimitiveIterator.OfInt { - int next = nextSetBit(0); + class BitSetSpliterator implements Spliterator.OfInt { + private int index; // current bit index for a set bit + private int fence; // -1 until used; then one past last bit index + private int est; // size estimate + private boolean root; // true if root and not split + // root == true then size estimate is accurate + // index == -1 or index >= fence if fully traversed + // Special case when the max bit set is Integer.MAX_VALUE - @Override - public boolean hasNext() { - return next != -1; + BitSetSpliterator(int origin, int fence, int est, boolean root) { + this.index = origin; + this.fence = fence; + this.est = est; + this.root = root; + } + + private int getFence() { + int hi; + if ((hi = fence) < 0) { + // Round up fence to maximum cardinality for allocated words + // This is sufficient and cheap for sequential access + // When splitting this value is lowered + hi = fence = (wordsInUse >= wordIndex(Integer.MAX_VALUE)) + ? Integer.MAX_VALUE + : wordsInUse << ADDRESS_BITS_PER_WORD; + est = cardinality(); + index = nextSetBit(0); + } + return hi; } @Override - public int nextInt() { - if (next != -1) { - int ret = next; - next = (next == Integer.MAX_VALUE) ? -1 : nextSetBit(next+1); - return ret; - } else { - throw new NoSuchElementException(); + public boolean tryAdvance(IntConsumer action) { + Objects.requireNonNull(action); + + int hi = getFence(); + int i = index; + if (i < 0 || i >= hi) { + // Check if there is a final bit set for Integer.MAX_VALUE + if (i == Integer.MAX_VALUE && hi == Integer.MAX_VALUE) { + index = -1; + action.accept(Integer.MAX_VALUE); + return true; + } + return false; + } + + index = nextSetBit(i + 1, wordIndex(hi - 1)); + action.accept(i); + return true; + } + + @Override + public void forEachRemaining(IntConsumer action) { + Objects.requireNonNull(action); + + int hi = getFence(); + int i = index; + int v = wordIndex(hi - 1); + index = -1; + while (i >= 0 && i < hi) { + action.accept(i); + i = nextSetBit(i + 1, v); + } + // Check if there is a final bit set for Integer.MAX_VALUE + if (i == Integer.MAX_VALUE && hi == Integer.MAX_VALUE) { + action.accept(Integer.MAX_VALUE); } } - } - return StreamSupport.intStream( - () -> Spliterators.spliterator( - new BitSetIterator(), cardinality(), - Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED), - Spliterator.SIZED | Spliterator.SUBSIZED | - Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED, - false); + @Override + public OfInt trySplit() { + int hi = getFence(); + int lo = index; + if (lo < 0) { + return null; + } + + // Lower the fence to be the upper bound of last bit set + // The index is the first bit set, thus this spliterator + // covers one bit and cannot be split, or two or more + // bits + hi = fence = (hi < Integer.MAX_VALUE || !get(Integer.MAX_VALUE)) + ? previousSetBit(hi - 1) + 1 + : Integer.MAX_VALUE; + + // Find the mid point + int mid = (lo + hi) >>> 1; + if (lo >= mid) { + return null; + } + + // Raise the index of this spliterator to be the next set bit + // from the mid point + index = nextSetBit(mid, wordIndex(hi - 1)); + root = false; + + // Don't lower the fence (mid point) of the returned spliterator, + // traversal or further splitting will do that work + return new BitSetSpliterator(lo, mid, est >>>= 1, false); + } + + @Override + public long estimateSize() { + getFence(); // force init + return est; + } + + @Override + public int characteristics() { + // Only sized when root and not split + return (root ? Spliterator.SIZED : 0) | + Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED; + } + + @Override + public Comparator getComparator() { + return null; + } + } + return StreamSupport.intStream(new BitSetSpliterator(0, -1, 0, true), false); } + + /** + * Returns the index of the first bit that is set to {@code true} + * that occurs on or after the specified starting index and up to and + * including the specified word index + * If no such bit exists then {@code -1} is returned. + * + * @param fromIndex the index to start checking from (inclusive) + * @param toWordIndex the last word index to check (inclusive) + * @return the index of the next set bit, or {@code -1} if there + * is no such bit + */ + private int nextSetBit(int fromIndex, int toWordIndex) { + int u = wordIndex(fromIndex); + // Check if out of bounds + if (u > toWordIndex) + return -1; + + long word = words[u] & (WORD_MASK << fromIndex); + + while (true) { + if (word != 0) + return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word); + // Check if out of bounds + if (++u > toWordIndex) + return -1; + word = words[u]; + } + } + } diff --git a/jdk/src/java.base/share/classes/java/util/stream/Stream.java b/jdk/src/java.base/share/classes/java/util/stream/Stream.java index 1ec21ed2b57..225664042a6 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java @@ -1327,7 +1327,7 @@ public interface Stream extends BaseStream> { * @param s the {@code Supplier} of generated elements * @return a new infinite sequential unordered {@code Stream} */ - public static Stream generate(Supplier s) { + public static Stream generate(Supplier s) { Objects.requireNonNull(s); return StreamSupport.stream( new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false); diff --git a/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java b/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java index 8236255d5ef..4606ce30306 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java +++ b/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java @@ -1346,9 +1346,9 @@ class StreamSpliterators { } static final class OfRef extends InfiniteSupplyingSpliterator { - final Supplier s; + final Supplier s; - OfRef(long size, Supplier s) { + OfRef(long size, Supplier s) { super(size); this.s = s; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java index 7ed01991bb1..64492508dc0 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java @@ -72,13 +72,13 @@ public class ClassLoaders { // If neither is specified then default to -cp // If -cp is not specified and -m is specified, the value of // java.class.path is an empty string, then no class path. - URLClassPath ucp = null; + URLClassPath ucp = new URLClassPath(new URL[0]); String mainMid = System.getProperty("jdk.module.main"); String cp = System.getProperty("java.class.path"); if (cp == null) cp = ""; if (mainMid == null || cp.length() > 0) - ucp = toURLClassPath(cp); + addClassPathToUCP(cp, ucp); // create the class loaders BOOT_LOADER = new BootClassLoader(bcp); diff --git a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java index 45e781b9b4a..c5d87287a17 100644 --- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -462,6 +462,8 @@ public final class LauncherHelper { * This method: * 1. Loads the main class from the module or class path * 2. Checks the public static void main method. + * 3. If the main class extends FX Application then call on FXHelper to + * perform the launch. * * @param printToStderr if set, all output will be routed to stderr * @param mode LaunchMode as determined by the arguments passed on the @@ -479,11 +481,23 @@ public final class LauncherHelper { Class mainClass = (mode == LM_MODULE) ? loadModuleMainClass(what) : loadMainClass(mode, what); - validateMainClass(mainClass); + // record the real main class for UI purposes + // neither method above can return null, they will abort() + appClass = mainClass; - // record main class if not already set - if (appClass == null) - appClass = mainClass; + /* + * Check if FXHelper can launch it using the FX launcher. In an FX app, + * the main class may or may not have a main method, so do this before + * validating the main class. + */ + if (JAVAFX_FXHELPER_CLASS_NAME_SUFFIX.equals(mainClass.getName()) || + doesExtendFXApplication(mainClass)) { + // Will abort() if there are problems with FX runtime + FXHelper.setFXLaunchParameters(what, mode); + mainClass = FXHelper.class; + } + + validateMainClass(mainClass); return mainClass; } @@ -530,7 +544,6 @@ public final class LauncherHelper { String cn = Normalizer.normalize(mainClass, Normalizer.Form.NFC); c = Class.forName(m, cn); - } if (c == null) { abort(null, "java.launcher.module.error2", mainClass, mainModule); @@ -542,8 +555,6 @@ public final class LauncherHelper { /** * Loads the main class from the class path (LM_CLASS or LM_JAR). - * If the main class extends FX Application then call on FXHelper to - * determine the main class to launch. */ private static Class loadMainClass(int mode, String what) { // get the class name @@ -570,7 +581,7 @@ public final class LauncherHelper { if (System.getProperty("os.name", "").contains("OS X") && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) { try { - // On Mac OS X since all names with diacretic symbols are + // On Mac OS X since all names with diacritical marks are // given as decomposed it is possible that main class name // comes incorrectly from the command line and we have // to re-compose it @@ -583,21 +594,6 @@ public final class LauncherHelper { abort(cnfe, "java.launcher.cls.error1", cn); } } - - // record the main class - appClass = mainClass; - - /* - * Check if FXHelper can launch it using the FX launcher. In an FX app, - * the main class may or may not have a main method, so do this before - * validating the main class. - */ - if (JAVAFX_FXHELPER_CLASS_NAME_SUFFIX.equals(mainClass.getName()) || - doesExtendFXApplication(mainClass)) { - // Will abort() if there are problems with FX runtime - FXHelper.setFXLaunchParameters(what, mode); - return FXHelper.class; - } return mainClass; } @@ -773,9 +769,15 @@ public final class LauncherHelper { * java -cp somedir FXClass N/A LM_CLASS "LM_CLASS" * java -jar fxapp.jar Present LM_JAR "LM_JAR" * java -jar fxapp.jar Not Present LM_JAR "LM_JAR" + * java -m module/class [1] N/A LM_MODULE "LM_MODULE" + * java -m module N/A LM_MODULE "LM_MODULE" + * + * [1] - JavaFX-Application-Class is ignored when modular args are used, even + * if present in a modular jar */ private static final String JAVAFX_LAUNCH_MODE_CLASS = "LM_CLASS"; private static final String JAVAFX_LAUNCH_MODE_JAR = "LM_JAR"; + private static final String JAVAFX_LAUNCH_MODE_MODULE = "LM_MODULE"; /* * FX application launcher and launch method, so we can launch @@ -835,6 +837,9 @@ public final class LauncherHelper { case LM_JAR: fxLaunchMode = JAVAFX_LAUNCH_MODE_JAR; break; + case LM_MODULE: + fxLaunchMode = JAVAFX_LAUNCH_MODE_MODULE; + break; default: // should not have gotten this far... throw new InternalError(mode + ": Unknown launch mode"); diff --git a/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java b/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java index ea090fa6898..31164695ecc 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java @@ -96,25 +96,32 @@ final class SunEntries { if (nativeAvailable && useNativePRNG) { map.put("SecureRandom.NativePRNG", "sun.security.provider.NativePRNG"); + map.put("SecureRandom.NativePRNG ThreadSafe", "true"); } map.put("SecureRandom.DRBG", "sun.security.provider.DRBG"); + map.put("SecureRandom.DRBG ThreadSafe", "true"); map.put("SecureRandom.SHA1PRNG", "sun.security.provider.SecureRandom"); + + map.put("SecureRandom.SHA1PRNG ThreadSafe", "true"); if (nativeAvailable && !useNativePRNG) { map.put("SecureRandom.NativePRNG", "sun.security.provider.NativePRNG"); + map.put("SecureRandom.NativePRNG ThreadSafe", "true"); } if (NativePRNG.Blocking.isAvailable()) { map.put("SecureRandom.NativePRNGBlocking", "sun.security.provider.NativePRNG$Blocking"); + map.put("SecureRandom.NativePRNGBlocking ThreadSafe", "true"); } if (NativePRNG.NonBlocking.isAvailable()) { map.put("SecureRandom.NativePRNGNonBlocking", "sun.security.provider.NativePRNG$NonBlocking"); + map.put("SecureRandom.NativePRNGNonBlocking ThreadSafe", "true"); } /* @@ -329,6 +336,7 @@ final class SunEntries { map.put("AlgorithmParameters.DSA ImplementedIn", "Software"); map.put("KeyFactory.DSA ImplementedIn", "Software"); map.put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); + map.put("SecureRandom.DRBG ImplementedIn", "Software"); map.put("CertificateFactory.X.509 ImplementedIn", "Software"); map.put("KeyStore.JKS ImplementedIn", "Software"); map.put("CertPathValidator.PKIX ImplementedIn", "Software"); diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java index 85e596cb6c3..5fba1666119 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java @@ -740,7 +740,7 @@ class RevocationChecker extends PKIXRevocationChecker { } response = OCSP.check(Collections.singletonList(certId), - responderURI, issuerInfo, responderCert, params.date(), + responderURI, issuerInfo, responderCert, null, ocspExtensions); } } catch (IOException e) { diff --git a/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java b/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java index 60edcc85d60..e260dd44ac0 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java +++ b/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java @@ -58,7 +58,7 @@ public class AnchorCertificates { try { cacerts = KeyStore.getInstance("JKS"); try (FileInputStream fis = new FileInputStream(f)) { - cacerts.load(fis, "changeit".toCharArray()); + cacerts.load(fis, null); certs = new HashSet<>(); Enumeration list = cacerts.aliases(); String alias; diff --git a/jdk/src/java.base/share/lib/security/default.policy b/jdk/src/java.base/share/lib/security/default.policy index 74c8463ea3c..de6e99a8f49 100644 --- a/jdk/src/java.base/share/lib/security/default.policy +++ b/jdk/src/java.base/share/lib/security/default.policy @@ -155,7 +155,6 @@ grant codeBase "jrt:/jdk.jsobject" { grant codeBase "jrt:/jdk.localedata" { permission java.lang.RuntimePermission "accessClassInPackage.sun.text.*"; permission java.lang.RuntimePermission "accessClassInPackage.sun.util.*"; - permission java.util.PropertyPermission "*", "read"; }; grant codeBase "jrt:/jdk.naming.dns" { diff --git a/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java b/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java index c859d337c69..edf758e8731 100644 --- a/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java +++ b/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -554,7 +554,7 @@ public class ThreadInfo { * @return an array of {@code StackTraceElement} objects of the thread. */ public StackTraceElement[] getStackTrace() { - return stackTrace; + return stackTrace.clone(); } /** @@ -868,7 +868,7 @@ public class ThreadInfo { * @since 1.6 */ public MonitorInfo[] getLockedMonitors() { - return lockedMonitors; + return lockedMonitors.clone(); } /** @@ -885,7 +885,7 @@ public class ThreadInfo { * @since 1.6 */ public LockInfo[] getLockedSynchronizers() { - return lockedSynchronizers; + return lockedSynchronizers.clone(); } private static final StackTraceElement[] NO_STACK_TRACE = diff --git a/jdk/src/java.management/share/classes/javax/management/MXBean.java b/jdk/src/java.management/share/classes/javax/management/MXBean.java index 8784a5fbaf8..ca5402effda 100644 --- a/jdk/src/java.management/share/classes/javax/management/MXBean.java +++ b/jdk/src/java.management/share/classes/javax/management/MXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -916,14 +916,14 @@ public interface ModuleMXBean {

  • Otherwise, J is not reconstructible.

  • -

    When only {@code @java.beans.ConstructorProperties} is present then - rule 2 is not applicable to subset Profiles of Java SE that do not include - the {@code java.beans} package. When targeting a runtime that does - not include the {@code java.beans} package, and where there is a mismatch - between the compile-time and runtime environment whereby J is - compiled with a public constructor and the {@code ConstructorProperties} - annotation, then J is not reconstructible unless another rule - applies.

    +

    Rule 2 is not applicable when {@code java.beans.ConstructorProperties} + is not visible (e.g. when the java.desktop module is not readable or when + the runtime image does not contain the java.desktop module). When + targeting a runtime that does not include the {@code java.beans} package, + and where there is a mismatch between the compile-time and runtime + environment whereby J is compiled with a public constructor + and the {@code ConstructorProperties} annotation, then J is + not reconstructible unless another rule applies.

    Here are examples showing different ways to code a type {@code NamedNumber} that consists of an {@code int} and a {@code diff --git a/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java b/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java index b0e4d44a540..595a6bf48f5 100644 --- a/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java +++ b/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -102,7 +102,13 @@ class VMManagementImpl implements VMManagement { } public boolean isGcNotificationSupported() { - return gcNotificationSupport; + boolean isSupported = true; + try { + Class.forName("com.sun.management.GarbageCollectorMXBean"); + } catch (ClassNotFoundException x) { + isSupported = false; + } + return isSupported; } public boolean isRemoteDiagnosticCommandsSupported() { diff --git a/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c b/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c index 51136856536..38a5b6af0cc 100644 --- a/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c +++ b/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -96,13 +96,6 @@ Java_sun_management_VMManagementImpl_initOptionalSupportFields value = mos.isRemoteDiagnosticCommandsSupported; setStaticBooleanField(env, cls, "remoteDiagnosticCommandsSupport", value); - - if ((jmm_version > JMM_VERSION_1_2) || - (jmm_version == JMM_VERSION_1_2 && ((jmm_version&0xFF) >= 1))) { - setStaticBooleanField(env, cls, "gcNotificationSupport", JNI_TRUE); - } else { - setStaticBooleanField(env, cls, "gcNotificationSupport", JNI_FALSE); - } } JNIEXPORT jobjectArray JNICALL diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java index 70165388eef..b7fbf801e86 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java @@ -33,6 +33,8 @@ import java.security.InvalidParameterException; import java.security.ProviderException; import java.util.HashMap; import java.util.Arrays; +import java.util.Map; + import static sun.security.util.SecurityConstants.PROVIDER_VER; /** @@ -133,8 +135,11 @@ public final class SunMSCAPI extends Provider { /* * Secure random */ + HashMap srattrs = new HashMap<>(1); + srattrs.put("ThreadSafe", "true"); putService(new ProviderService(p, "SecureRandom", - "Windows-PRNG", "sun.security.mscapi.PRNG")); + "Windows-PRNG", "sun.security.mscapi.PRNG", + null, srattrs)); /* * Key store diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java index 98b5e21ea2c..a9b6de30d82 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -987,7 +987,8 @@ public final class SunPKCS11 extends AuthProvider { P11Service(Token token, String type, String algorithm, String className, String[] al, long mechanism) { - super(token.provider, type, algorithm, className, toList(al), null); + super(token.provider, type, algorithm, className, toList(al), + type.equals(SR) ? Map.of("ThreadSafe", "true") : null); this.token = token; this.mechanism = mechanism & 0xFFFFFFFFL; } diff --git a/jdk/src/jdk.jdi/share/native/libdt_shmem/SharedMemoryConnection.c b/jdk/src/jdk.jdi/share/native/libdt_shmem/SharedMemoryConnection.c index 5936b5a0dc8..e28efe63128 100644 --- a/jdk/src/jdk.jdi/share/native/libdt_shmem/SharedMemoryConnection.c +++ b/jdk/src/jdk.jdi/share/native/libdt_shmem/SharedMemoryConnection.c @@ -174,9 +174,20 @@ byteArrayToPacket(JNIEnv *env, jbyteArray b, jdwpPacket *str) * Get the packet header */ (*env)->GetByteArrayRegion(env, b, 0, sizeof(pktHeader), pktHeader); + if ((*env)->ExceptionOccurred(env)) { + /* b shorter than sizeof(pktHeader) */ + return; + } total_length = (int)pktHeader[3] | ((int)pktHeader[2] << 8) | ((int)pktHeader[1] << 16) | ((int)pktHeader[0] << 24); + + if (total_length < sizeof(pktHeader)) { + throwException(env, "java/lang/IllegalArgumentException", + "JDWP header is incorrect"); + return; + } + /* * The id field is in big endian (also errorCode field in the case * of reply packets). @@ -195,9 +206,9 @@ byteArrayToPacket(JNIEnv *env, jbyteArray b, jdwpPacket *str) } /* - * The length of the JDWP packet is 11 + data + * The length of the JDWP packet is sizeof(pktHeader) + data */ - data_length = total_length - 11; + data_length = total_length - sizeof(pktHeader); if (data_length == 0) { data = NULL; @@ -209,7 +220,7 @@ byteArrayToPacket(JNIEnv *env, jbyteArray b, jdwpPacket *str) return; } - (*env)->GetByteArrayRegion(env, b, 11, /*sizeof(CmdPacket)+4*/ data_length, data); + (*env)->GetByteArrayRegion(env, b, sizeof(pktHeader), /*sizeof(CmdPacket)+4*/ data_length, data); if ((*env)->ExceptionOccurred(env)) { free(data); return; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 06d86a7653a..344b920a8bf 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -32,6 +32,7 @@ import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.PathMatcher; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.MissingResourceException; @@ -190,19 +191,12 @@ class JImageTask { if (options.help) { if (unhandled.isEmpty()) { log.println(TASK_HELPER.getMessage("main.usage", PROGNAME)); - - for (Option o : RECOGNIZED_OPTIONS) { - String name = o.aliases()[0]; - - if (name.startsWith("--")) { - name = name.substring(2); - } else if (name.startsWith("-")) { - name = name.substring(1); - } - - log.println(TASK_HELPER.getMessage("main.opt." + name)); - } - + Arrays.asList(RECOGNIZED_OPTIONS).stream() + .filter(option -> !option.isHidden()) + .sorted() + .forEach(option -> { + log.println(TASK_HELPER.getMessage(option.resourceName())); + }); log.println(TASK_HELPER.getMessage("main.opt.footer")); } else { try { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties index 24bffe3e1a5..13faa3b40e4 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties @@ -60,36 +60,36 @@ error.prefix=Error: warn.prefix=Warning: main.opt.dir=\ -\ --dir Target directory for extract directive +\ --dir Target directory for extract directive main.opt.include=\ -\ --include Pattern list for filtering entries. - -main.opt.footer=\ -\n\ -\For options requiring a , the value will be a comma\ -\ separated list of elements each using one the following forms:\n\ -\ \n\ -\ glob:\n\ -\ regex:\n\ -\ @ where filename is the name of a file containing patterns to be\ -\ used, one pattern per line\n\ - +\ --include Pattern list for filtering entries. main.opt.full-version=\ -\ --full-version Print full version information +\ --full-version Print full version information main.opt.help=\ \ -h, --help Print usage message main.opt.verbose=\ -\ --verbose Listing prints entry size and offset attributes +\ --verbose Listing prints entry size and offset\n\ +\ attributes main.opt.version=\ -\ --version Print version information +\ --version Print version information main.command.files=\ -\ @ Read options from file +\ @ Read options from file + +main.opt.footer=\ +\n\ +\For options requiring a , the value will be a comma separated\n\ +\list of elements each using one the following forms:\n\ +\ \n\ +\ glob:\n\ +\ regex: + + err.not.a.task=task must be one of : {0} err.missing.arg=no value given for {0} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java index 615b7a8349c..6ad2f8dfe42 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java @@ -27,6 +27,7 @@ package jdk.tools.jlink.internal; import java.lang.reflect.Layer; import java.nio.ByteOrder; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -278,6 +279,13 @@ public final class Jlink { */ public void build(JlinkConfiguration config, PluginsConfiguration pluginsConfig) { Objects.requireNonNull(config); + if (pluginsConfig == null) { + pluginsConfig = new PluginsConfiguration(); + } + + // add all auto-enabled plugins from boot layer + pluginsConfig = addAutoEnabledPlugins(pluginsConfig); + try { JlinkTask.createImage(config, pluginsConfig); } catch (Exception ex) { @@ -285,6 +293,19 @@ public final class Jlink { } } + private PluginsConfiguration addAutoEnabledPlugins(PluginsConfiguration pluginsConfig) { + List plugins = new ArrayList<>(pluginsConfig.getPlugins()); + List bootPlugins = PluginRepository.getPlugins(Layer.boot()); + for (Plugin bp : bootPlugins) { + if (Utils.isAutoEnabled(bp)) { + bp.configure(Collections.emptyMap()); + plugins.add(bp); + } + } + return new PluginsConfiguration(plugins, pluginsConfig.getImageBuilder(), + pluginsConfig.getLastSorterPluginName()); + } + /** * Post process the image with a plugin configuration. * diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index bf7e9e03e55..01876ee5b56 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -134,7 +134,7 @@ public class JlinkTask { }, true, "--full-version"), new Option(false, (task, opt, arg) -> { task.options.ignoreSigning = true; - }, true, "--ignore-signing-information"),}; + }, "--ignore-signing-information"),}; private static final String PROGNAME = "jlink"; private final OptionsValues options = new OptionsValues(); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java index 083bf048724..e9b5d885039 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java @@ -46,8 +46,8 @@ import java.util.Map.Entry; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; +import java.util.stream.Stream; -import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin; import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.Plugin.Category; @@ -90,8 +90,7 @@ public final class TaskHelper { public boolean showUsage; } - public static class Option { - + public static class Option implements Comparable { public interface Processing { void process(T task, String opt, String arg) throws BadArgs; @@ -100,17 +99,34 @@ public final class TaskHelper { final boolean hasArg; final Processing processing; final boolean hidden; - final String[] aliases; + final String name; + final String shortname; + + public Option(boolean hasArg, Processing processing, boolean hidden, String name, String shortname) { + if (!name.startsWith("--")) { + throw new RuntimeException("option name missing --, " + name); + } + if (!shortname.isEmpty() && !shortname.startsWith("-")) { + throw new RuntimeException("short name missing -, " + shortname); + } - public Option(boolean hasArg, Processing processing, boolean hidden, String... aliases) { this.hasArg = hasArg; this.processing = processing; - this.aliases = aliases; this.hidden = hidden; + this.name = name; + this.shortname = shortname; } - public Option(boolean hasArg, Processing processing, String... aliases) { - this(hasArg, processing, false, aliases); + public Option(boolean hasArg, Processing processing, String name, String shortname) { + this(hasArg, processing, false, name, shortname); + } + + public Option(boolean hasArg, Processing processing, boolean hidden, String name) { + this(hasArg, processing, hidden, name, ""); + } + + public Option(boolean hasArg, Processing processing, String name) { + this(hasArg, processing, false, name, ""); } public boolean isHidden() { @@ -118,16 +134,10 @@ public final class TaskHelper { } public boolean matches(String opt) { - for (String a : aliases) { - if (a.equals(opt)) { - return true; - } else if (opt.startsWith("--") - && (hasArg && opt.startsWith(a + "="))) { - return true; - } - } - return false; - } + return opt.equals(name) || + opt.equals(shortname) || + hasArg && opt.startsWith("--") && opt.startsWith(name + "="); + } public boolean ignoreRest() { return false; @@ -137,28 +147,54 @@ public final class TaskHelper { processing.process(task, opt, arg); } - public String[] aliases() { - return aliases; + public String getName() { + return name; + } + + public String resourceName() { + return resourcePrefix() + name.substring(2); + } + + public String getShortname() { + return shortname; + } + + public String resourcePrefix() { + return "main.opt."; + } + + @Override + public int compareTo(Object object) { + if (!(object instanceof Option)) { + throw new RuntimeException("comparing non-Option"); + } + + Option option = (Option)object; + + return name.compareTo(option.name); + } + + } + + private static class PluginOption extends Option { + public PluginOption(boolean hasArg, + Processing processing, boolean hidden, String name, String shortname) { + super(hasArg, processing, hidden, name, shortname); + } + + public PluginOption(boolean hasArg, + Processing processing, boolean hidden, String name) { + super(hasArg, processing, hidden, name, ""); + } + + public String resourcePrefix() { + return "plugin.opt."; } } - private static class PlugOption extends Option { - - public PlugOption(boolean hasArg, - Processing processing, boolean hidden, String... aliases) { - super(hasArg, processing, hidden, aliases); - } - - public PlugOption(boolean hasArg, - Processing processing, String... aliases) { - super(hasArg, processing, aliases); - } - } - - private final class PluginsOptions { + private final class PluginsHelper { private static final String PLUGINS_PATH = "--plugin-module-path"; - private static final String POST_PROCESS = "--post-process-path"; private Layer pluginsLayer = Layer.boot(); private final List plugins; @@ -170,10 +206,10 @@ public final class TaskHelper { // Each such occurrence results in a Map of arguments. So, there could be multiple // args maps per plugin instance. private final Map>> pluginToMaps = new HashMap<>(); - private final List pluginsOptions = new ArrayList<>(); - private final List mainOptions = new ArrayList<>(); + private final List pluginsOptions = new ArrayList<>(); + private final List mainOptions = new ArrayList<>(); - private PluginsOptions(String pp) throws BadArgs { + private PluginsHelper(String pp) throws BadArgs { if (pp != null) { String[] dirs = pp.split(File.pathSeparator); @@ -193,13 +229,13 @@ public final class TaskHelper { addOrderedPluginOptions(plugin, optionsSeen); } } - mainOptions.add(new PlugOption(false, + mainOptions.add(new PluginOption(false, (task, opt, arg) -> { // This option is handled prior // to have the options parsed. }, - "--plugin-module-path")); - mainOptions.add(new PlugOption(true, (task, opt, arg) -> { + false, "--plugin-module-path")); + mainOptions.add(new PluginOption(true, (task, opt, arg) -> { for (Plugin plugin : plugins) { if (plugin.getName().equals(arg)) { pluginToMaps.remove(plugin); @@ -208,24 +244,24 @@ public final class TaskHelper { } throw newBadArgs("err.no.such.plugin", arg); }, - "--disable-plugin")); - mainOptions.add(new PlugOption(true, (task, opt, arg) -> { + false, "--disable-plugin")); + mainOptions.add(new PluginOption(true, (task, opt, arg) -> { Path path = Paths.get(arg); if (!Files.exists(path) || !Files.isDirectory(path)) { throw newBadArgs("err.image.must.exist", path); } existingImage = path.toAbsolutePath(); - }, true, POST_PROCESS)); - mainOptions.add(new PlugOption(true, + }, true, "--post-process-path")); + mainOptions.add(new PluginOption(true, (task, opt, arg) -> { lastSorter = arg; }, true, "--resources-last-sorter")); - mainOptions.add(new PlugOption(false, + mainOptions.add(new PluginOption(false, (task, opt, arg) -> { listPlugins = true; }, - "--list-plugins")); + false, "--list-plugins")); } private List> argListFor(Plugin plugin) { @@ -261,8 +297,8 @@ public final class TaskHelper { } optionsSeen.add(option); - PlugOption plugOption - = new PlugOption(plugin.hasArguments(), + PluginOption plugOption + = new PluginOption(plugin.hasArguments(), (task, opt, arg) -> { if (!Utils.isFunctional(plugin)) { throw newBadArgs("err.provider.not.functional", @@ -312,7 +348,7 @@ public final class TaskHelper { } } }, - "--" + option); + false, "--" + option); pluginsOptions.add(plugOption); if (Utils.isFunctional(plugin)) { @@ -322,44 +358,44 @@ public final class TaskHelper { if (plugin instanceof DefaultCompressPlugin) { plugOption - = new PlugOption(false, + = new PluginOption(false, (task, opt, arg) -> { Map m = addArgumentMap(plugin); m.put(DefaultCompressPlugin.NAME, DefaultCompressPlugin.LEVEL_2); - }, "-c"); + }, false, "--compress", "-c"); mainOptions.add(plugOption); } else if (plugin instanceof StripDebugPlugin) { plugOption - = new PlugOption(false, + = new PluginOption(false, (task, opt, arg) -> { addArgumentMap(plugin); - }, "-G"); + }, false, "--strip-debug", "-G"); mainOptions.add(plugOption); } else if (plugin instanceof ExcludeJmodSectionPlugin) { - plugOption = new PlugOption(false, (task, opt, arg) -> { + plugOption = new PluginOption(false, (task, opt, arg) -> { Map m = addArgumentMap(plugin); m.put(ExcludeJmodSectionPlugin.NAME, ExcludeJmodSectionPlugin.MAN_PAGES); - }, "--no-man-pages"); + }, false, "--no-man-pages"); mainOptions.add(plugOption); - plugOption = new PlugOption(false, (task, opt, arg) -> { + plugOption = new PluginOption(false, (task, opt, arg) -> { Map m = addArgumentMap(plugin); m.put(ExcludeJmodSectionPlugin.NAME, ExcludeJmodSectionPlugin.INCLUDE_HEADER_FILES); - }, "--no-header-files"); + }, false, "--no-header-files"); mainOptions.add(plugOption); } } } - private PlugOption getOption(String name) throws BadArgs { - for (PlugOption o : pluginsOptions) { + private PluginOption getOption(String name) throws BadArgs { + for (PluginOption o : pluginsOptions) { if (o.matches(name)) { return o; } } - for (PlugOption o : mainOptions) { + for (PluginOption o : mainOptions) { if (o.matches(name)) { return o; } @@ -461,7 +497,7 @@ public final class TaskHelper { private String getPluginsPath(String[] args) throws BadArgs { String pp = null; for (int i = 0; i < args.length; i++) { - if (args[i].equals(PluginsOptions.PLUGINS_PATH)) { + if (args[i].equals(PluginsHelper.PLUGINS_PATH)) { if (i == args.length - 1) { throw new BadArgs("err.no.plugins.path").showUsage(true); } else { @@ -498,13 +534,13 @@ public final class TaskHelper { // Must extract it prior to do any option analysis. // Required to interpret custom plugin options. // Unit tests can call Task multiple time in same JVM. - pluginOptions = new PluginsOptions(getPluginsPath(args)); + pluginOptions = new PluginsHelper(getPluginsPath(args)); // First extract plugins path if any String pp = null; List filteredArgs = new ArrayList<>(); for (int i = 0; i < args.length; i++) { - if (args[i].equals(PluginsOptions.PLUGINS_PATH)) { + if (args[i].equals(PluginsHelper.PLUGINS_PATH)) { if (i == args.length - 1) { throw new BadArgs("err.no.plugins.path").showUsage(true); } else { @@ -529,7 +565,7 @@ public final class TaskHelper { for (int i = 0; i < args.length; i++) { if (args[i].charAt(0) == '-') { String name = args[i]; - PlugOption pluginOption = null; + PluginOption pluginOption = null; Option option = getOption(name); if (option == null) { pluginOption = pluginOptions.getOption(name); @@ -585,32 +621,13 @@ public final class TaskHelper { } public void showHelp(String progName) { - showHelp(progName, true); - } - - private void showHelp(String progName, boolean showsImageBuilder) { log.println(bundleHelper.getMessage("main.usage", progName)); - for (Option o : options) { - String name = o.aliases[0].substring(1); // there must always be at least one name - name = name.charAt(0) == '-' ? name.substring(1) : name; - if (o.isHidden() || name.equals("h")) { - continue; - } - log.println(bundleHelper.getMessage("main.opt." + name)); - } - - for (Option o : pluginOptions.mainOptions) { - if (o.aliases[0].equals(PluginsOptions.POST_PROCESS) - && !showsImageBuilder) { - continue; - } - String name = o.aliases[0].substring(1); // there must always be at least one name - name = name.charAt(0) == '-' ? name.substring(1) : name; - if (o.isHidden()) { - continue; - } - log.println(bundleHelper.getMessage("plugin.opt." + name)); - } + Stream.concat(options.stream(), pluginOptions.mainOptions.stream()) + .filter(option -> !option.isHidden()) + .sorted() + .forEach(option -> { + log.println(bundleHelper.getMessage(option.resourceName())); + }); log.println(bundleHelper.getMessage("main.command.files")); } @@ -619,6 +636,7 @@ public final class TaskHelper { log.println("\n" + bundleHelper.getMessage("main.extended.help")); List pluginList = PluginRepository. getPlugins(pluginOptions.pluginsLayer); + for (Plugin plugin : Utils.getSortedPlugins(pluginList)) { showPlugin(plugin, log); } @@ -671,7 +689,7 @@ public final class TaskHelper { } } - private PluginsOptions pluginOptions; + private PluginsHelper pluginOptions; private PrintWriter log; private final ResourceBundleHelper bundleHelper; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java index 0d2adf63221..5b06d8135f2 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java @@ -118,8 +118,6 @@ public final class AppRuntimeImageBuilder { null)); } - plugins.add(Jlink.newPlugin("installed-modules", Collections.emptyMap(), null)); - // build the image Jlink.PluginsConfiguration pluginConfig = new Jlink.PluginsConfiguration( plugins, new DefaultImageBuilder(outputDir), null); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties index ac4a86293a6..a56c77be18d 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties @@ -24,46 +24,51 @@ # main.usage.summary=\ -Usage: {0} --module-path --add-modules --output \n\ -use --help for a list of possible options +Usage: {0} --module-path --add-modules --output\n\ +\ use --help for a list of possible options main.usage=\ -Usage: {0} --module-path --add-modules --output \n\ -\Possible options include: +Usage: {0} --module-path --add-modules --output +\ Possible options include: error.prefix=Error: warn.prefix=Warning: main.opt.help=\ -\ -h, --help Print this help message +\ -h, --help Print this help message main.opt.version=\ -\ --version Version information +\ --version Version information main.opt.module-path=\ -\ -p \n\ -\ --module-path Module path +\ -p, --module-path Module path main.opt.add-modules=\ -\ --add-modules [,...] Root modules to resolve +\ --add-modules [,...] Root modules to resolve main.opt.limit-modules=\ -\ --limit-modules [,...] Limit the universe of observable modules +\ --limit-modules [,...] Limit the universe of observable\n\ +\ modules main.opt.output=\ -\ --output Location of output path +\ --output Location of output path main.command.files=\ -\ @ Read options from file +\ @ Read options from file main.opt.endian=\ -\ --endian Byte order of generated jimage (default:native) +\ --endian Byte order of generated jimage\n\ +\ (default:native) main.opt.save-opts=\ -\ --save-opts Save jlink options in the given file +\ --save-opts Save jlink options in the given file main.opt.ignore-signing-information=\ -\ --ignore-signing-information Ignore signing information in modular JARs +\ --ignore-signing-information Suppress a fatal error when signed\n\ +\ modular JARs are linked in the image.\n\ +\ The signature related files of the\n\ +\ signed modular JARs are not copied to\n\ +\ the runtime image. main.msg.bug=\ An exception has occurred in jlink. \ @@ -75,13 +80,13 @@ main.extended.help=\ \List of available plugins: main.extended.help.footer=\ -\For options requiring a , the value will be a comma\ -\ separated list of elements each using one the following forms:\n\ +\For options requiring a , the value will be a comma separated\n\ +\list of elements each using one the following forms:\n\ \ \n\ \ glob:\n\ \ regex:\n\ -\ @ where filename is the name of a file containing patterns to be\ -\ used, one pattern per line\n\ +\ @ where filename is the name of a file containing patterns to be\n\ +\ used, one pattern per line\n\ \n\ @@ -110,6 +115,6 @@ err.bom.generation=bom file generation failed: {0} err.not.modular.format=selected module {0} ({1}) not in jmod or modular JAR format err.signing=signed modular JAR {0} is currently not supported,\ \ use --ignore-signing-information to suppress error -warn.signing=signed modular JAR {0} is currently not supported +warn.signing=WARNING: signed modular JAR {0} is currently not supported warn.invalid.arg=invalid classname or pathname not exist: {0} warn.split.package=package {0} defined in {1} {2} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties index 3fcda64dcda..52e4529bc09 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties @@ -132,32 +132,33 @@ plugin.plugins.header=\ List of available plugin options: plugin.opt.list-plugins=\ -\ --list-plugins List available plugins +\ --list-plugins List available plugins plugin.opt.post-process-path=\ -\ --post-process-path Post process an existing image +\ --post-process-path Post process an existing image plugin.opt.resources-last-sorter=\ -\ --resources-last-sorter The last plugin allowed to sort resources +\ --resources-last-sorter The last plugin allowed to sort\n\ +\ resources plugin.opt.plugin-module-path=\ -\ --plugin-module-path Custom plugin module path +\ --plugin-module-path Custom plugin module path plugin.opt.disable-plugin=\ -\ --disable-plugin Disable the plugin mentioned +\ --disable-plugin Disable the plugin mentioned -plugin.opt.c=\ -\ -c, --compress=<0|1|2> Enable compression of resources\ -\n More details in --list-plugins option +plugin.opt.compress=\ +\ -c, --compress=<0|1|2> Enable compression of resources\n\ +\ More details in --list-plugins option -plugin.opt.G=\ -\ -G, --strip-debug Strip debug information +plugin.opt.strip-debug=\ +\ -G, --strip-debug Strip debug information plugin.opt.no-man-pages=\ -\ --no-man-pages Exclude man pages +\ --no-man-pages Exclude man pages plugin.opt.no-header-files=\ -\ --no-header-files Exclude include header files +\ --no-header-files Exclude include header files main.plugin.name=\ \Plugin Name diff --git a/jdk/test/Makefile b/jdk/test/Makefile index 6958d9abb58..d417600da79 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -55,7 +55,7 @@ TEE = tee UNAME = uname UNIQ = uniq WC = wc -ZIP = zip +ZIPEXE = zip # Get OS name from uname (Cygwin inexplicably adds _NT-5.1) UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_) @@ -143,7 +143,8 @@ ifneq ($(FAILURE_HANDLER_DIR), ) -timeoutHandlerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \ -observerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \ -timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler \ - -observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver + -observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver \ + -timeoutHandlerTimeout:0 ifeq ($(UNAME_S), CYGWIN) JTREG_FAILURE_HANDLER_OPTIONS += -J-Djava.library.path="$(FAILURE_HANDLER_DIR_MIXED)" endif @@ -161,7 +162,7 @@ endif ZIP_UP_RESULTS = ( $(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)` \ && $(CD) $(ABS_TEST_OUTPUT_DIR) \ && $(CHMOD) -R a+r . \ - && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . ) + && $(ZIPEXE) -q -r $(ARCHIVE_BUNDLE) . ) # important results files SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport/text/summary.txt") diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index df850721454..b252d116521 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -124,6 +124,7 @@ java/beans/Introspector/8132566/OverrideUserDefPropertyInfoTest.java 8132565 gen # jdk_lang java/lang/StringCoding/CheckEncodings.sh 7008363 generic-all +java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java 8169639 windows-all ############################################################################ @@ -135,7 +136,7 @@ java/lang/instrument/RetransformBigClass.sh 8065756 generic- java/lang/instrument/BootClassPath/BootClassPathTest.sh 8072130 macosx-all java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all -java/lang/management/MemoryMXBean/PendingAllGC.sh 8158760 generic-all +java/lang/management/MemoryMXBean/PendingAllGC.sh 8158837 generic-all ############################################################################ @@ -252,10 +253,14 @@ sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8157338 generic- # core_tools -tools/pack200/CommandLineTests.java 7143279,8059906 generic-all +tools/pack200/CommandLineTests.java 8059906 generic-all tools/launcher/FXLauncherTest.java 8068049 linux-all,macosx-all +tools/jimage/JImageExtractTest.java 8169713 generic-all +tools/jimage/JImageListTest.java 8169713 generic-all +tools/jimage/JImageVerifyTest.java 8169713 generic-all + ############################################################################ # jdk_jdi @@ -292,16 +297,6 @@ java/util/BitSet/BitSetStreamTest.java 8079538 generic- sun/tools/jcmd/TestJcmdSanity.java 8031482 windows-all -sun/tools/jhsdb/BasicLauncherTest.java 8160376 macosx-all - -sun/tools/jhsdb/HeapDumpTest.java 8160376 macosx-all - -sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java 8160376 macosx-all - -sun/tools/jps/TestJpsJar.java 8165500 generic-all - -sun/tools/jps/TestJpsJarRelative.java 6456333 generic-all - sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java 8057732 generic-all demo/jvmti/compiledMethodLoad/CompiledMethodLoadTest.java 8151899 generic-all diff --git a/jdk/test/com/sun/jndi/dns/CheckAccess.java b/jdk/test/com/sun/jndi/dns/CheckAccess.java index 265d99e8ea5..723ee28a983 100644 --- a/jdk/test/com/sun/jndi/dns/CheckAccess.java +++ b/jdk/test/com/sun/jndi/dns/CheckAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, 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 @@ -24,11 +24,13 @@ /* * @test * @bug 6657619 + * @modules jdk.naming.dns * @summary DnsContext.debug is public static mutable (findbugs) * @author Vincent Ryan */ -import java.lang.reflect.*; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; /* * Check that the 'debug' class member is no longer publicly accessible. diff --git a/jdk/test/com/sun/jndi/dns/Test6991580.java b/jdk/test/com/sun/jndi/dns/Test6991580.java index b06f78a23de..b8763bbbd0b 100644 --- a/jdk/test/com/sun/jndi/dns/Test6991580.java +++ b/jdk/test/com/sun/jndi/dns/Test6991580.java @@ -30,13 +30,14 @@ import java.awt.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -/** +/* * @test * @bug 6991580 8080108 8133035 * @requires os.family != "windows" * @summary IPv6 Nameservers in resolv.conf throws NumberFormatException - * @modules jdk.naming.dns/com.sun.jndi.dns - * @build IPv6NameserverPlatformParsingTest + * @modules java.desktop + * jdk.naming.dns/com.sun.jndi.dns + * @compile --add-modules jdk.naming.dns IPv6NameserverPlatformParsingTest.java * @run main/manual Test6991580 */ diff --git a/jdk/test/com/sun/jndi/ldap/TEST.properties b/jdk/test/com/sun/jndi/ldap/TEST.properties new file mode 100644 index 00000000000..88ac1ce7ea8 --- /dev/null +++ b/jdk/test/com/sun/jndi/ldap/TEST.properties @@ -0,0 +1 @@ +modules = java.naming diff --git a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java index 5709c2b5ca8..74f57678ac8 100644 --- a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java +++ b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -28,6 +28,7 @@ * successfully. * @modules java.rmi/sun.rmi.registry java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport java.rmi/sun.rmi.transport.tcp + * jdk.naming.rmi * @library ../../../../../../java/rmi/testlibrary * @build TestLibrary * @run main UnbindIdempotent @@ -49,8 +50,10 @@ public class UnbindIdempotent { try { rctx = (Context)ictx.lookup("rmi://localhost:" + Integer.toString(registryPort)); + System.out.println("Got context: " + rctx.getClass()); } catch (NamingException e) { // Unable to set up for test. + System.err.println("WARNING: The test skipped due to NamingException: " + e); return; } diff --git a/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java b/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java index 10d10f40903..d5df6a34135 100644 --- a/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java +++ b/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -72,22 +72,9 @@ public class GarbageCollectionNotificationContentTest { public static void main(String[] args) throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - final Boolean isNotificationSupported = AccessController.doPrivileged (new PrivilegedAction() { - public Boolean run() { - try { - Class cl = Class.forName("sun.management.VMManagementImpl"); - Field f = cl.getDeclaredField("gcNotificationSupport"); - f.setAccessible(true); - return f.getBoolean(null); - } catch(ClassNotFoundException e) { - return false; - } catch(NoSuchFieldException e) { - return false; - } catch(IllegalAccessException e) { - return false; - } - } - }); + final boolean isNotificationSupported = + sun.management.ManagementFactoryHelper.getVMManagement().isGcNotificationSupported(); + if(!isNotificationSupported) { System.out.println("GC Notification not supported by the JVM, test skipped"); return; diff --git a/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java b/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java index 3bbfea44193..5c42827eb4d 100644 --- a/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java +++ b/jdk/test/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -71,22 +71,9 @@ public class GarbageCollectionNotificationTest { public static void main(String[] args) throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - final Boolean isNotificationSupported = AccessController.doPrivileged (new PrivilegedAction() { - public Boolean run() { - try { - Class cl = Class.forName("sun.management.VMManagementImpl"); - Field f = cl.getDeclaredField("gcNotificationSupport"); - f.setAccessible(true); - return f.getBoolean(null); - } catch(ClassNotFoundException e) { - return false; - } catch(NoSuchFieldException e) { - return false; - } catch(IllegalAccessException e) { - return false; - } - } - }); + final boolean isNotificationSupported = + sun.management.ManagementFactoryHelper.getVMManagement().isGcNotificationSupported(); + if(!isNotificationSupported) { System.out.println("GC Notification not supported by the JVM, test skipped"); return; diff --git a/jdk/test/com/sun/nio/sctp/TEST.properties b/jdk/test/com/sun/nio/sctp/TEST.properties new file mode 100644 index 00000000000..3989427b278 --- /dev/null +++ b/jdk/test/com/sun/nio/sctp/TEST.properties @@ -0,0 +1,2 @@ +modules = jdk.sctp + diff --git a/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.java b/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.java new file mode 100644 index 00000000000..78c5e615330 --- /dev/null +++ b/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8169909 + * @library src /lib/testlibrary + * @build test/* + * @run shell AppendToClassPathModuleTest.sh + * @run main AppendToClassPathModuleTest + */ + +import java.util.Map; +import static jdk.testlibrary.ProcessTools.*; + +/** + * Launch a modular test with no class path and no CLASSPATH set. + * The java agent appends to the "hidden" directory to the class path + * at runtime. + */ +public class AppendToClassPathModuleTest { + public static void main(String... args) throws Throwable { + String modulepath = System.getProperty("test.module.path"); + ProcessBuilder pb = + createJavaProcessBuilder("-javaagent:Agent.jar", + "--module-path", modulepath, + "-m", "test/jdk.test.Main"); + + // remove CLASSPATH environment variable + Map env = pb.environment(); + String value = env.remove("CLASSPATH"); + + int exitCode = executeCommand(pb).getExitValue(); + if (exitCode != 0) { + throw new RuntimeException("Test failed: " + exitCode); + } + } + +} diff --git a/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.sh b/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.sh new file mode 100644 index 00000000000..5937acba058 --- /dev/null +++ b/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# +# Copyright (c) 2016, 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTSRC=${TESTSRC}" + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTJAVA=${TESTJAVA}" + +if [ "${COMPILEJAVA}" = "" ] +then + COMPILEJAVA="${TESTJAVA}" +fi +echo "COMPILEJAVA=${COMPILEJAVA}" + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +echo "TESTCLASSES=${TESTCLASSES}" + +mkdir -p hidden +${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ + -d hidden ${TESTSRC}/../ExampleForClassPath.java + +mkdir -p classes +${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ + -d classes ${TESTSRC}/../InstrumentationHandoff.java + +echo "Manifest-Version: 1.0" > Agent.mf +echo "Class-Path: hidden/" >> Agent.mf +echo "Premain-Class: InstrumentationHandoff" >> Agent.mf + +${TESTJAVA}/bin/jar ${TESTTOOLVMOPTS} cvfm Agent.jar \ + Agent.mf -C classes InstrumentationHandoff.class diff --git a/jdk/test/java/lang/instrument/modules/src/test/jdk/test/Main.java b/jdk/test/java/lang/instrument/modules/src/test/jdk/test/Main.java new file mode 100644 index 00000000000..94b05e41712 --- /dev/null +++ b/jdk/test/java/lang/instrument/modules/src/test/jdk/test/Main.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test; + +/** + * Launched by AppendToClassPathModuleTest. + */ +public class Main { + public static void main(String... args) throws Exception { + // "java.class.path" system property is expected to be empty. + String value = System.getProperty("java.class.path"); + if (!value.isEmpty()) { + throw new RuntimeException("Non-empty java.class.path=" + value); + } + + // load the "hidden" class that should be loaded by the system loader + Class c = Class.forName("ExampleForClassPath"); + if (c.getClassLoader() != ClassLoader.getSystemClassLoader()) { + throw new RuntimeException(c + " loaderd by " + c.getClassLoader()); + } + } +} diff --git a/jdk/test/java/lang/instrument/modules/src/test/module-info.java b/jdk/test/java/lang/instrument/modules/src/test/module-info.java new file mode 100644 index 00000000000..92ea019a3eb --- /dev/null +++ b/jdk/test/java/lang/instrument/modules/src/test/module-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module test { +} diff --git a/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java b/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java index 011ae7f43a5..c3d60b0374d 100644 --- a/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java +++ b/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -37,18 +37,11 @@ public class InvokeSeveralWays { failures++; } catch (InvocationTargetException e) { Throwable c = e.getCause(); - if (BootstrapMethodError.class.isInstance(c)) { - c = c.getCause(); - if (expected.isInstance(c)) - System.out.println("EXPECTED: " + expected.getName() + ", "+ c); - else { - failures++; - System.out.println("FAIL: Unexpected wrapped exception " + c); - e.printStackTrace(System.out); - } - } else { + if (expected.isInstance(c)) + System.out.println("EXPECTED: " + expected.getName() + ", "+ c); + else { failures++; - System.out.println("FAIL: Exception from MethodHandle invocation not wrapped in BootstrapMethodError " + c); + System.out.println("FAIL: Unexpected wrapped exception " + c); e.printStackTrace(System.out); } } catch (Throwable e) { @@ -80,19 +73,14 @@ public class InvokeSeveralWays { Invoker.invoke(); System.out.println("FAIL: No exception throw, probably failed to load modified bytecodes for MethodSupplier"); failures++; - } catch (BootstrapMethodError e) { - Throwable c = e.getCause(); - if (expected.isInstance(c)) - System.out.println("EXPECTED: " + expected.getName() + ", "+ c); + } catch (Throwable e) { + if (expected.isInstance(e)) + System.out.println("EXPECTED: " + expected.getName() + ", "+ e); else { failures++; - System.out.println("FAIL: Unexpected exception has been caught " + c); + System.out.println("FAIL: Unexpected exception has been caught " + e); e.printStackTrace(System.out); } - } catch (Throwable e) { - failures++; - System.out.println("FAIL: Exception from MethodHandle invocation not wrapped in BootstrapMethodError " + e); - e.printStackTrace(System.out); } System.out.println(); try { diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/order/MethodOrder.java b/jdk/test/java/lang/management/ManagementFactory/DefaultManagementProviderTest.java similarity index 63% rename from langtools/test/jdk/javadoc/doclet/testOrdering/order/MethodOrder.java rename to jdk/test/java/lang/management/ManagementFactory/DefaultManagementProviderTest.java index d04ceb07c4a..70c41098eb3 100644 --- a/langtools/test/jdk/javadoc/doclet/testOrdering/order/MethodOrder.java +++ b/jdk/test/java/lang/management/ManagementFactory/DefaultManagementProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -21,32 +21,18 @@ * questions. */ -package order; - -/** - * This class ensures the method detail section contains the methods - * in the order as it appears in the source. - * @author kumasrin +/* + * @test + * @bug 8151099 + * @summary Verify platform MXBeans initialized properly with java.management + * module only. No other management provider + * @run main/othervm --limit-modules=java.management DefaultManagementProviderTest */ -public class MethodOrder { - /** - * Method d. - * Second line. - */ - public void d(){} - /** - * Method b. - * Second line. - */ - public void b() {} - /** - * Method c. - * Second line. - */ - public void c() {} - /** - * Method a. - * Second line. - */ - public void a() {} +import java.lang.management.ManagementFactory; + +public class DefaultManagementProviderTest { + public static void main(String[] argv) { + ManagementFactory.getPlatformMBeanServer(); + System.out.println("Test case passed"); + } } diff --git a/jdk/test/java/net/Authenticator/GetAuthenticatorTest.java b/jdk/test/java/net/Authenticator/GetAuthenticatorTest.java new file mode 100644 index 00000000000..d36236ba32f --- /dev/null +++ b/jdk/test/java/net/Authenticator/GetAuthenticatorTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.ref.Reference; +import java.net.Authenticator; +import java.net.NetPermission; +import java.net.PasswordAuthentication; +import java.security.AccessControlException; + +/** + * @test + * @bug 8169068 + * @summary Basic test for Authenticator.getDefault() + * @run main/othervm GetAuthenticatorTest + */ +public class GetAuthenticatorTest { + + static final class MyAuthenticator extends Authenticator { + + MyAuthenticator () { + super (); + } + + @Override + public PasswordAuthentication getPasswordAuthentication () { + System.out.println ("Auth called"); + return (new PasswordAuthentication ("user", + "passwordNotCheckedAnyway".toCharArray())); + } + + } + + public static void main (String args[]) throws Exception { + Authenticator defaultAuth = Authenticator.getDefault(); + if (defaultAuth != null) { + throw new RuntimeException("Unexpected authenticator: null expected"); + } + MyAuthenticator auth = new MyAuthenticator(); + Authenticator.setDefault(auth); + defaultAuth = Authenticator.getDefault(); + if (defaultAuth != auth) { + throw new RuntimeException("Unexpected authenticator: auth expected"); + } + System.setSecurityManager(new SecurityManager()); + try { + defaultAuth = Authenticator.getDefault(); + throw new RuntimeException("Expected security exception not raised"); + } catch (AccessControlException s) { + System.out.println("Got expected exception: " + s); + if (!s.getPermission().equals(new NetPermission("requestPasswordAuthentication"))) { + throw new RuntimeException("Unexpected permission check: " + s.getPermission()); + } + } + System.out.println("Test passed with default authenticator " + + defaultAuth); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index e12ab09c32b..f98fca05391 100644 --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -219,7 +219,8 @@ public class Basic { throw new RuntimeException("ExecutionException expected"); } catch (ExecutionException x) { if (!(x.getCause() instanceof ClosedChannelException)) - throw new RuntimeException("Cause of ClosedChannelException expected"); + throw new RuntimeException("Cause of ClosedChannelException expected", + x.getCause()); } final AtomicReference connectException = new AtomicReference<>(); ch.connect(server.address(), (Void)null, new CompletionHandler() { @@ -233,7 +234,8 @@ public class Basic { Thread.sleep(100); } if (!(connectException.get() instanceof ClosedChannelException)) - throw new RuntimeException("ClosedChannelException expected"); + throw new RuntimeException("ClosedChannelException expected", + connectException.get()); } // test that failure to connect closes the channel @@ -353,7 +355,8 @@ public class Basic { Thread.sleep(100); } if (!(writeException.get() instanceof AsynchronousCloseException)) - throw new RuntimeException("AsynchronousCloseException expected"); + throw new RuntimeException("AsynchronousCloseException expected", + writeException.get()); } } @@ -460,7 +463,8 @@ public class Basic { throw new RuntimeException("ExecutionException expected"); } catch (ExecutionException x) { if (!(x.getCause() instanceof ClosedChannelException)) - throw new RuntimeException("Cause of ClosedChannelException expected"); + throw new RuntimeException("Cause of ClosedChannelException expected", + x.getCause()); } } } @@ -630,7 +634,8 @@ public class Basic { throw new RuntimeException("ExecutionException expected"); } catch (ExecutionException x) { if (!(x.getCause() instanceof ClosedChannelException)) - throw new RuntimeException("Cause of ClosedChannelException expected"); + throw new RuntimeException("Cause of ClosedChannelException expected", + x.getCause()); } } } @@ -738,7 +743,8 @@ public class Basic { throw new RuntimeException("ClosedChannelException expected"); } catch (ExecutionException x) { if (!(x.getCause() instanceof ClosedChannelException)) - throw new RuntimeException("ClosedChannelException expected"); + throw new RuntimeException("ClosedChannelException expected", + x.getCause()); } } } @@ -776,7 +782,8 @@ public class Basic { Thread.sleep(100); } if (!(readException.get() instanceof InterruptedByTimeoutException)) - throw new RuntimeException("InterruptedByTimeoutException expected"); + throw new RuntimeException("InterruptedByTimeoutException expected", + readException.get()); // after a timeout then further reading should throw unspecified runtime exception boolean exceptionThrown = false; @@ -813,7 +820,8 @@ public class Basic { Thread.sleep(100); } if (!(writeException.get() instanceof InterruptedByTimeoutException)) - throw new RuntimeException("InterruptedByTimeoutException expected"); + throw new RuntimeException("InterruptedByTimeoutException expected", + writeException.get()); // after a timeout then further writing should throw unspecified runtime exception boolean exceptionThrown = false; diff --git a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy index cdf9ca15fae..4ca2dd3fbbd 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy @@ -4,4 +4,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.rmi.server.useDynamicProxies=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy index ca4b8e244d9..ce485f61343 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy @@ -3,4 +3,7 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; + permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy index 53ed1f0bd93..586dd8efc1b 100644 --- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy @@ -4,4 +4,6 @@ grant { permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy index ca4b8e244d9..ce485f61343 100644 --- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy @@ -3,4 +3,7 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; + permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/rmid.security.policy index c488914b790..69c222e3e63 100644 --- a/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/rmid.security.policy @@ -1,4 +1,6 @@ grant { permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy index ca4b8e244d9..ce485f61343 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy @@ -3,4 +3,7 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; + permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy index 0471fc80946..3e6ac7893f0 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy @@ -3,4 +3,7 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; + permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy index b1f98628cf8..30b4e537750 100644 --- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy @@ -4,4 +4,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Ddummyname=dummyvalue"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy index ca4b8e244d9..fd9ccf3da7b 100644 --- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy +++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy @@ -3,4 +3,6 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission java.lang.RuntimePermission "selectorProvider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; }; diff --git a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java index 1675a7275c8..3e7798c687c 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java +++ b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -33,8 +33,9 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp + * java.base/sun.nio.ch * @build TestLibrary RMID ActivationLibrary - * ActivateMe ModifyDescriptor_Stub + * ActivateMe ModifyDescriptor_Stub RMIDSelectorProvider * @run main/othervm/policy=security.policy/timeout=240 ModifyDescriptor */ diff --git a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/rmid.security.policy b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/rmid.security.policy index f2d3e2c7795..a352c07a92b 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/rmid.security.policy +++ b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/rmid.security.policy @@ -3,4 +3,9 @@ grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; permission com.sun.rmi.rmid.ExecOptionPermission "-Dtest.message=hello"; permission com.sun.rmi.rmid.ExecOptionPermission "-Dtest.message=hello, again"; + permission java.lang.RuntimePermission "selectorProvider"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; + permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept"; }; diff --git a/jdk/test/java/rmi/testlibrary/RMID.java b/jdk/test/java/rmi/testlibrary/RMID.java index f83225f4d43..07628fb2358 100644 --- a/jdk/test/java/rmi/testlibrary/RMID.java +++ b/jdk/test/java/rmi/testlibrary/RMID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -25,6 +25,7 @@ import java.io.*; import java.rmi.*; import java.rmi.activation.*; import java.rmi.registry.*; +import java.time.LocalTime; import java.util.concurrent.TimeoutException; /** @@ -44,6 +45,15 @@ public class RMID extends JavaVM { private static final long STARTTIME_MS = 15_000L; private static final long POLLTIME_MS = 100L; + // when restart rmid, it may take more time than usual because of + // "port in use" by a possible interloper (check JDK-8168975), + // so need to set a longer timeout for restart. + private static long restartTimeout; + // Same reason to inheritedChannel in RMIDSelectorProvider. + // Put it here rather than in RMIDSelectorProvider to adjust + // both timeout values together. + private static long inheritedChannelTimeout; + private static final String SYSTEM_NAME = ActivationSystem.class.getName(); // "java.rmi.activation.ActivationSystem" @@ -73,7 +83,8 @@ public class RMID extends JavaVM { } /** make test options and arguments */ - private static String makeOptions(int port, boolean debugExec) { + private static String makeOptions(int port, boolean debugExec, + boolean enableSelectorProvider) { String options = " -Dsun.rmi.server.activation.debugExec=" + debugExec; @@ -98,12 +109,24 @@ public class RMID extends JavaVM { // to avoid spurious timeouts on slow machines. options += " -Dsun.rmi.activation.execTimeout=60000"; - if (port == 0) { + // It's important to set handshakeTimeout to small value, for example + // 5 sec (default is 60 sec) to avoid wasting too much time when + // calling lookupSystem(port) in restart(), because + // 1. If use default value of this option, it will take about 2 minutes + // to finish lookupSystem(port) in 2 loops in restart(); + // 2. If set this option as 5 sec then lookupSystem(port) will return + // very quickly. + options += " -Dsun.rmi.transport.tcp.handshakeTimeout=5000"; + + if (port == 0 || enableSelectorProvider) { // Ephemeral port, so have the rmid child process create the // server socket channel and report its port number, over stdin. options += " -classpath " + TestParams.testClassPath; options += " --add-exports=java.base/sun.nio.ch=ALL-UNNAMED"; options += " -Djava.nio.channels.spi.SelectorProvider=RMIDSelectorProvider"; + options += " -Dtest.java.rmi.testlibrary.RMIDSelectorProvider.port=" + port; + options += " -Dtest.java.rmi.testlibrary.RMIDSelectorProvider.timeout=" + + inheritedChannelTimeout; // Disable redirection of System.err to /tmp options += " -Dsun.rmi.server.activation.disableErrRedirect=true"; @@ -112,6 +135,10 @@ public class RMID extends JavaVM { return options; } + private static String makeArgs() { + return makeArgs(false, 0); + } + private static String makeArgs(boolean includePortArg, int port) { String propagateManager = null; @@ -183,7 +210,7 @@ public class RMID extends JavaVM { boolean debugExec, boolean includePortArg, int port) { - String options = makeOptions(port, debugExec); + String options = makeOptions(port, debugExec, false); String args = makeArgs(includePortArg, port); RMID rmid = new RMID("sun.rmi.server.Activation", options, args, out, err, port); @@ -193,14 +220,14 @@ public class RMID extends JavaVM { } public static RMID createRMIDOnEphemeralPort() { - return createRMID(System.out, System.err, true, true, 0); + return createRMID(System.out, System.err, true, false, 0); } public static RMID createRMIDOnEphemeralPort(OutputStream out, OutputStream err, boolean debugExec) { - return createRMID(out, err, debugExec, true, 0); + return createRMID(out, err, debugExec, false, 0); } @@ -213,6 +240,9 @@ public class RMID extends JavaVM { { super(classname, options, args, out, err); this.port = port; + long waitTime = (long)(240_000 * TestLibrary.getTimeoutFactor()); + restartTimeout = (long)(waitTime * 0.9); + inheritedChannelTimeout = (long)(waitTime * 0.8); } /** @@ -280,11 +310,11 @@ public class RMID extends JavaVM { // if rmid is already running, then the test will fail with // a well recognized exception (port already in use...). - mesg("Starting rmid on port " + port + "."); + mesg("Starting rmid on port " + port + ", at " + LocalTime.now()); int p = super.startAndGetPort(); if (p != -1) port = p; - mesg("Started rmid on port " + port + "."); + mesg("Started rmid on port " + port + ", at " + LocalTime.now()); // int slopFactor = 1; // try { @@ -318,6 +348,7 @@ public class RMID extends JavaVM { // The rmid process is alive; check to see whether // it responds to a remote call. + mesg("looking up activation system, at " + LocalTime.now()); if (lookupSystem(port) != null) { /* * We need to set the java.rmi.activation.port value as the @@ -328,10 +359,11 @@ public class RMID extends JavaVM { */ System.setProperty("java.rmi.activation.port", Integer.toString(port)); mesg("Started successfully after " + - (System.currentTimeMillis() - startTime) + "ms."); + (System.currentTimeMillis() - startTime) + "ms, at " + LocalTime.now()); return; } + mesg("after fail to looking up activation system, at " + LocalTime.now()); if (System.currentTimeMillis() > deadline) { TestLibrary.bomb("Failed to start rmid, giving up after " + (System.currentTimeMillis() - startTime) + "ms.", null); @@ -347,9 +379,10 @@ public class RMID extends JavaVM { */ public void restart() throws IOException { destroy(); - options = makeOptions(port, true); - args = makeArgs(true, port); - start(); + options = makeOptions(port, true, true); + args = makeArgs(); + + start(restartTimeout); } /** diff --git a/jdk/test/java/rmi/testlibrary/RMIDSelectorProvider.java b/jdk/test/java/rmi/testlibrary/RMIDSelectorProvider.java index 4b9f09264d7..d837ebce6fc 100644 --- a/jdk/test/java/rmi/testlibrary/RMIDSelectorProvider.java +++ b/jdk/test/java/rmi/testlibrary/RMIDSelectorProvider.java @@ -22,6 +22,7 @@ */ import java.io.*; +import java.net.BindException; import java.net.InetSocketAddress; import java.net.ProtocolFamily; import java.nio.channels.Channel; @@ -31,6 +32,7 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.AbstractSelector; import java.nio.channels.spi.SelectorProvider; +import java.time.LocalTime; import static java.net.StandardSocketOptions.SO_REUSEADDR; import static java.net.StandardSocketOptions.SO_REUSEPORT; @@ -98,7 +100,37 @@ public class RMIDSelectorProvider extends SelectorProvider { channel.setOption(SO_REUSEPORT, true); } - channel.bind(new InetSocketAddress(0)); + // when it comes here, these properties should have been set with + // a valid value, but assign a default value anyway. + long timeout = Long.getLong( + "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", + 200_000); + long deadline = System.currentTimeMillis() + timeout; + int port = Integer.getInteger( + "test.java.rmi.testlibrary.RMIDSelectorProvider.port", 0); + while (true) { + try { + channel.bind(new InetSocketAddress(port)); + break; + } catch (BindException ex) { + System.out.format("RMIDSelectorProvider: " + + "failed to bind to port %d due to \"%s\", at %s%n", + port, ex.getMessage(), LocalTime.now()); + } + if (System.currentTimeMillis() > deadline) { + System.out.format("RMIDSelectorProvider: " + + "fail to bind to port %d after trying for " + + "%d seconds, exiting rmid process, at %s%n", + port, timeout/1000, LocalTime.now()); + channel.close(); + // can not start rmid on specific port, + // there is no need to continue run rmid. + System.exit(1); + } + try { + Thread.sleep(1000); + } catch(InterruptedException ignore) { } + } System.out.println(RMID.EPHEMERAL_MSG + channel.socket().getLocalPort()); } diff --git a/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java b/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java index 6fce16108f1..e8688ec8250 100644 --- a/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java +++ b/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -53,7 +53,7 @@ import java.rmi.server.UnicastRemoteObject; public class ReuseDefaultPort implements Remote { - private static final int PORT = TestLibrary.getUnusedRandomPort(); + private static int rmiPort = 0; private ReuseDefaultPort() { } @@ -64,7 +64,7 @@ public class ReuseDefaultPort implements Remote { Remote stub = UnicastRemoteObject.exportObject(impl, 0); System.err.println("- exported object: " + stub); try { - Registry registry = LocateRegistry.createRegistry(PORT); + Registry registry = LocateRegistry.createRegistry(rmiPort); System.err.println("- exported registry: " + registry); System.err.println("TEST PASSED"); } finally { @@ -77,13 +77,15 @@ public class ReuseDefaultPort implements Remote { RMISocketFactory.getDefaultSocketFactory(); SF() { } public Socket createSocket(String host, int port) throws IOException { + System.err.format("in SF::createSocket: %s, %d%n", host, port); return defaultFactory.createSocket(host, port); } public ServerSocket createServerSocket(int port) throws IOException { - if (port == 0) { - port = PORT; - } - return defaultFactory.createServerSocket(port); + System.err.format("in SF::createServerSocket: %d%n", port); + ServerSocket server = defaultFactory.createServerSocket(port); + rmiPort = server.getLocalPort(); + System.err.println("rmiPort: " + rmiPort); + return server; } } } diff --git a/jdk/test/java/security/ProtectionDomain/NullGetActions.java b/jdk/test/java/security/ProtectionDomain/NullGetActions.java new file mode 100644 index 00000000000..4986395d5f9 --- /dev/null +++ b/jdk/test/java/security/ProtectionDomain/NullGetActions.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8043252 + * @summary Debug of access control is obfuscated - NullPointerException in + * ProtectionDomain + * @run main/othervm/java.security.policy=NullGetActions.policy NullGetActions + */ + +import java.net.*; +import java.security.*; + +public class NullGetActions { + + public static void main(String[] args) throws Exception { + Permissions permset = new Permissions(); + permset.add(new EvilPermission("java.let.me.do.stuff")); + + Policy.getPolicy(); + ProtectionDomain protDom = new ProtectionDomain( + new CodeSource(new URL("http://bar"), + (java.security.cert.Certificate[])null), permset, + null, null); + + System.out.println("Protection Domain:\n" + protDom); + } + + public static class EvilPermission extends Permission { + public EvilPermission(String name) { + super(name); + } + + @Override + public String getActions() { + return null; + } + + @Override + public boolean equals(Object obj) { + return (obj == this); + } + + @Override + public int hashCode() { + return 42; + } + + @Override + public boolean implies(Permission permission) { + return false; + } + } +} diff --git a/jdk/test/java/security/ProtectionDomain/NullGetActions.policy b/jdk/test/java/security/ProtectionDomain/NullGetActions.policy new file mode 100644 index 00000000000..87c88439050 --- /dev/null +++ b/jdk/test/java/security/ProtectionDomain/NullGetActions.policy @@ -0,0 +1,3 @@ +grant { + permission java.security.SecurityPermission "getPolicy"; +}; diff --git a/jdk/test/java/security/SecureRandom/NoSync.java b/jdk/test/java/security/SecureRandom/NoSync.java new file mode 100644 index 00000000000..032833c4a7f --- /dev/null +++ b/jdk/test/java/security/SecureRandom/NoSync.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.util.Date; +import java.util.concurrent.atomic.AtomicBoolean; + +/* + * @test + * @bug 7004967 + * @run main/othervm NoSync + * @summary SecureRandom should be more explicit about threading + */ +public class NoSync { + public static void main(String[] args) throws Exception { + for (Provider p : Security.getProviders()) { + for (Provider.Service s : p.getServices()) { + if (s.getType().equals("SecureRandom") && + !s.getAlgorithm().contains("Block")) { + test(SecureRandom.getInstance(s.getAlgorithm(), p)); + } + } + } + Security.setProperty("securerandom.drbg.config", "HMAC_DRBG"); + test(SecureRandom.getInstance("DRBG")); + Security.setProperty("securerandom.drbg.config", "CTR_DRBG"); + test(SecureRandom.getInstance("DRBG")); + } + + static void test(SecureRandom sr) throws Exception { + test(sr, 20, 3000); + // All out-of-box impl should have the ThreadSafe attribute + String attr = sr.getProvider().getProperty("SecureRandom." + + sr.getAlgorithm() + " ThreadSafe"); + if (!"true".equals(attr)) { + throw new Exception("Not ThreadSafe: " + attr); + } + } + + public static void test(SecureRandom sr, int tnum, int rnum) + throws Exception { + + System.out.println(sr); + System.out.println(sr.getAlgorithm() + " " + sr.getProvider().getName()); + + System.out.println(new Date()); + boolean reseed = sr.getParameters() != null; + Thread[] threads = new Thread[tnum]; + AtomicBoolean failed = new AtomicBoolean(false); + Thread.UncaughtExceptionHandler h = (t, e) -> { + failed.set(true); + e.printStackTrace(); + }; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread() { + @Override + public void run() { + for (int j = 0; j < rnum; j++) { + sr.nextBytes(new byte[j%100+100]); + sr.setSeed((long)j); + if (reseed) { + sr.reseed(); + } + } + } + }; + threads[i].setUncaughtExceptionHandler(h); + threads[i].start(); + } + for (int i = 0; i < threads.length; i++) { + threads[i].join(); + } + System.out.println(new Date()); + System.out.println(); + if (failed.get()) { + throw new RuntimeException("Failed"); + } + } +} diff --git a/jdk/test/java/security/SecureRandom/ThreadSafe.java b/jdk/test/java/security/SecureRandom/ThreadSafe.java new file mode 100644 index 00000000000..fda344b199f --- /dev/null +++ b/jdk/test/java/security/SecureRandom/ThreadSafe.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.Provider; +import java.security.SecureRandom; +import java.security.SecureRandomSpi; +import java.util.Map; + +/* + * @test + * @bug 7004967 + * @summary SecureRandom should be more explicit about threading + */ +public class ThreadSafe { + public static void main(String[] args) throws Exception { + Provider p = new P(); + NoSync.test(SecureRandom.getInstance("S1", p), 5, 5); + try { + NoSync.test(SecureRandom.getInstance("S2", p), 5, 5); + throw new Exception("Failed"); + } catch (RuntimeException re) { + // Good + } + NoSync.test(SecureRandom.getInstance("S3", p), 5, 5); + try { + NoSync.test(SecureRandom.getInstance("S4", p), 5, 5); + throw new Exception("Failed"); + } catch (RuntimeException re) { + // Good + } + } + + public static class P extends Provider { + public P() { + + super("P", 1.0d, "Haha"); + + // Good. No attribute. + put("SecureRandom.S1", S.class.getName()); + + // Bad. Boasting ThreadSafe but isn't + put("SecureRandom.S2", S.class.getName()); + put("SecureRandom.S2 ThreadSafe", "true"); + + // Good. No attribute. + putService(new Service(this, "SecureRandom", "S3", + S.class.getName(), null, null)); + + // Bad. Boasting ThreadSafe but isn't + putService(new Service(this, "SecureRandom", "S4", + S.class.getName(), null, Map.of("ThreadSafe", "true"))); + } + } + + // This implementation is not itself thread safe. + public static class S extends SecureRandomSpi { + @java.lang.Override + protected void engineSetSeed(byte[] seed) { + return; + } + + private volatile boolean inCall = false; + @Override + protected void engineNextBytes(byte[] bytes) { + if (inCall) { + throw new RuntimeException("IN CALL"); + } + inCall = true; + try { + Thread.sleep(100); + } catch (Exception e) { + // OK + } + inCall = false; + } + + @Override + protected byte[] engineGenerateSeed(int numBytes) { + return new byte[numBytes]; + } + } +} diff --git a/jdk/test/java/text/testlib/IntlTest.java b/jdk/test/java/text/testlib/IntlTest.java index d8ae8572f30..9dfb5a45193 100644 --- a/jdk/test/java/text/testlib/IntlTest.java +++ b/jdk/test/java/text/testlib/IntlTest.java @@ -89,6 +89,9 @@ public abstract class IntlTest { case "-nothrow": nothrow = true; break; + case "-exitcode": + exitCode = true; + break; default: Method m = testMethods.get(arg); if (m == null) { @@ -138,7 +141,12 @@ public abstract class IntlTest { } } if (nothrow) { - System.exit(errorCount); + if (exitCode) { + System.exit(errorCount); + } + if (errorCount > 0) { + throw new IllegalArgumentException("encountered " + errorCount + " errors"); + } } } @@ -243,7 +251,7 @@ public abstract class IntlTest { */ void usage() { System.out.println(getClass().getName() + - ": [-verbose] [-nothrow] [-prompt] [test names]"); + ": [-verbose] [-nothrow] [-exitcode] [-prompt] [test names]"); System.out.println(" Available test names:"); for (String methodName : testMethods.keySet()) { @@ -254,7 +262,7 @@ public abstract class IntlTest { private boolean prompt; private boolean nothrow; protected boolean verbose; - + private boolean exitCode; private PrintWriter log; private int indentLevel; private boolean needLineFeed; diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 1aa39d1d406..7429f013060 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -594,7 +594,7 @@ public class TCKDateTimeFormatterBuilder { @Test(dataProvider = "formatGenericTimeZonePatterns") public void test_appendZoneText_formatGenericTimeZonePatterns(String pattern, String input, String expected) { ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of(input)); - DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern); + DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern, Locale.US); assertEquals(zdt.format(df), expected); } @@ -641,7 +641,7 @@ public class TCKDateTimeFormatterBuilder { @Test(dataProvider = "formatNonGenericTimeZonePatterns_1") public void test_appendZoneText_parseNonGenricTimeZonePatterns_1(String pattern, LocalDateTime ldt, String expected) { ZoneId zId = ZoneId.of("America/Los_Angeles"); - DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(); + DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(Locale.US); ZonedDateTime zdt = ZonedDateTime.of(ldt, zId); String actual = df.format(zdt); assertEquals(actual, expected); @@ -668,7 +668,7 @@ public class TCKDateTimeFormatterBuilder { @Test(dataProvider = "formatNonGenericTimeZonePatterns_2") public void test_appendZoneText_parseNonGenricTimeZonePatterns_2(String pattern, LocalDateTime ldt, String expected) { ZoneId zId = ZoneId.of("America/Los_Angeles"); - DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern).withZone(zId); + DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern, Locale.US).withZone(zId); String actual = df.format(ldt); assertEquals(actual, expected); } diff --git a/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java b/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java index a30424f4572..f51bb396f50 100644 --- a/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java +++ b/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -91,10 +91,11 @@ public class TCKZoneRulesProvider { public void test_getAvailableGroupIds() { Set zoneIds = ZoneRulesProvider.getAvailableZoneIds(); assertEquals(zoneIds.contains("Europe/London"), true); - zoneIds.clear(); - assertEquals(zoneIds.size(), 0); - Set zoneIds2 = ZoneRulesProvider.getAvailableZoneIds(); - assertEquals(zoneIds2.contains("Europe/London"), true); + } + + @Test(expectedExceptions=UnsupportedOperationException.class) + public void test_getAvailableGroupIds_modifyZoneId() { + ZoneRulesProvider.getAvailableZoneIds().clear(); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/util/BitSet/BitSetStreamTest.java b/jdk/test/java/util/BitSet/BitSetStreamTest.java index d4e2d8d4919..87f9f05a753 100644 --- a/jdk/test/java/util/BitSet/BitSetStreamTest.java +++ b/jdk/test/java/util/BitSet/BitSetStreamTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -60,25 +60,6 @@ public class BitSetStreamTest { public int getAsInt() { int s = n1; n1 = n2; n2 = s + n1; return s; } } - private static final Object[][] testcases = new Object[][] { - { "none", IntStream.empty() }, - { "index 0", IntStream.of(0) }, - { "index 255", IntStream.of(255) }, - { "every bit", IntStream.range(0, 255) }, - { "step 2", IntStream.range(0, 255).map(f -> f * 2) }, - { "step 3", IntStream.range(0, 255).map(f -> f * 3) }, - { "step 5", IntStream.range(0, 255).map(f -> f * 5) }, - { "step 7", IntStream.range(0, 255).map(f -> f * 7) }, - { "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000) }, - { "max int", IntStream.of(Integer.MAX_VALUE) }, - { "25 fibs", IntStream.generate(new Fibs()).limit(25) } - }; - - @DataProvider(name = "cases") - public static Object[][] produceCases() { - return testcases; - } - @Test public void testFibs() { Fibs f = new Fibs(); @@ -93,22 +74,46 @@ public class BitSetStreamTest { assertEquals(987, Fibs.fibs(16)); } + + @DataProvider(name = "cases") + public static Object[][] produceCases() { + return new Object[][] { + { "none", IntStream.empty() }, + { "index 0", IntStream.of(0) }, + { "index 255", IntStream.of(255) }, + { "index 0 and 255", IntStream.of(0, 255) }, + { "index Integer.MAX_VALUE", IntStream.of(Integer.MAX_VALUE) }, + { "index Integer.MAX_VALUE - 1", IntStream.of(Integer.MAX_VALUE - 1) }, + { "index 0 and Integer.MAX_VALUE", IntStream.of(0, Integer.MAX_VALUE) }, + { "every bit", IntStream.range(0, 255) }, + { "step 2", IntStream.range(0, 255).map(f -> f * 2) }, + { "step 3", IntStream.range(0, 255).map(f -> f * 3) }, + { "step 5", IntStream.range(0, 255).map(f -> f * 5) }, + { "step 7", IntStream.range(0, 255).map(f -> f * 7) }, + { "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000) }, + { "25 fibs", IntStream.generate(new Fibs()).limit(25) } + }; + } + @Test(dataProvider = "cases") public void testBitsetStream(String name, IntStream data) { - BitSet bs = new BitSet(); - long setBits = data.distinct() - .peek(i -> bs.set(i)) - .count(); + BitSet bs = data.collect(BitSet::new, BitSet::set, BitSet::or); - assertEquals(bs.cardinality(), setBits); - assertEquals(bs.cardinality(), bs.stream().reduce(0, (s, i) -> s+1)); + assertEquals(bs.cardinality(), bs.stream().count()); + + int[] indexHolder = new int[] { -1 }; + bs.stream().forEach(i -> { + int ei = indexHolder[0]; + indexHolder[0] = bs.nextSetBit(ei + 1); + assertEquals(i, indexHolder[0]); + }); PrimitiveIterator.OfInt it = bs.stream().iterator(); - for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { assertTrue(it.hasNext()); assertEquals(it.nextInt(), i); if (i == Integer.MAX_VALUE) - break; // or (i+1) would overflow + break; // or (i + 1) would overflow } assertFalse(it.hasNext()); } @@ -123,16 +128,20 @@ public class BitSetStreamTest { for (int seed : seeds) { final Random random = new Random(seed); random.nextBytes(bytes); - final BitSet bitSet = BitSet.valueOf(bytes); - final int cardinality = bitSet.cardinality(); - final IntStream stream = bitSet.stream(); - final int[] array = stream.toArray(); - assertEquals(array.length, cardinality); - int nextSetBit = -1; - for (int i=0; i < cardinality; i++) { - nextSetBit = bitSet.nextSetBit(nextSetBit + 1); - assertEquals(array[i], nextSetBit); - } + + BitSet bitSet = BitSet.valueOf(bytes); + testBitSetContents(bitSet, bitSet.stream().toArray()); + testBitSetContents(bitSet, bitSet.stream().parallel().toArray()); + } + } + + void testBitSetContents(BitSet bitSet, int[] array) { + int cardinality = bitSet.cardinality(); + assertEquals(array.length, cardinality); + int nextSetBit = -1; + for (int i = 0; i < cardinality; i++) { + nextSetBit = bitSet.nextSetBit(nextSetBit + 1); + assertEquals(array[i], nextSetBit); } } } diff --git a/jdk/test/java/util/Calendar/Bug4766302.java b/jdk/test/java/util/Calendar/Bug4766302.java index 42df92b7e16..cd27e009ea2 100644 --- a/jdk/test/java/util/Calendar/Bug4766302.java +++ b/jdk/test/java/util/Calendar/Bug4766302.java @@ -29,9 +29,11 @@ import java.util.GregorianCalendar; +@SuppressWarnings("serial") public class Bug4766302 { static class MyCalendar extends GregorianCalendar { + boolean isTimeStillSet() { return isTimeSet; } diff --git a/jdk/test/java/util/Calendar/Bug4958050.java b/jdk/test/java/util/Calendar/Bug4958050.java index dfd627cda6f..2b2e6e4ff43 100644 --- a/jdk/test/java/util/Calendar/Bug4958050.java +++ b/jdk/test/java/util/Calendar/Bug4958050.java @@ -29,9 +29,11 @@ import java.util.Locale; import java.util.TimeZone; + import static java.util.Calendar.*; public class Bug4958050 { + static int errorCount = 0; public static void main(String[] args) { @@ -41,87 +43,87 @@ public class Bug4958050 { System.out.println("Time zone = " + cal.getTimeZone().getID()); // Test the week fields - int[] weekFields = { WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH }; + int[] weekFields = {WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH}; for (int i = 0; i < weekFields.length; i++) { int field = weekFields[i]; // add() cal.clear(); - cal.set(1919, DECEMBER, 14-7, 23, 50, 00); + cal.set(1919, DECEMBER, 14 - 7, 23, 50, 00); cal.add(weekFields[i], +1); if (!cal.checkDate(1919, DECEMBER, 14)) { - error("1919/12/07: add("+cal.getFieldName(weekFields[i])+", +1)\n" - + cal.getMessage()+" " + cal.toDateTimeString()); + error("1919/12/07: add(" + Koyomi.getFieldName(weekFields[i]) + ", +1)\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); - cal.set(1930, JUNE, 21-7); + cal.set(1930, JUNE, 21 - 7); cal.add(weekFields[i], +1); if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { - error("1930/6/14: add("+cal.getFieldName(weekFields[i])+", +1)\n" - + cal.getMessage()+" " + cal.toDateTimeString()); + error("1930/6/14: add(" + Koyomi.getFieldName(weekFields[i]) + ", +1)\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } // roll() cal.clear(); - cal.set(1919, DECEMBER, 14-7, 23, 50, 00); + cal.set(1919, DECEMBER, 14 - 7, 23, 50, 00); cal.roll(weekFields[i], +1); if (!cal.checkDate(1919, DECEMBER, 14)) { - error("1919/12/07: roll("+cal.getFieldName(weekFields[i])+", +1)\n" - + cal.getMessage()+" " + cal.toDateTimeString()); + error("1919/12/07: roll(" + Koyomi.getFieldName(weekFields[i]) + ", +1)\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); - cal.set(1930, JUNE, 21-7); + cal.set(1930, JUNE, 21 - 7); cal.roll(weekFields[i], +1); if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { - error("1930/6/14: roll("+cal.getFieldName(weekFields[i])+", +1)\n" - + cal.getMessage()+" " + cal.toDateTimeString()); + error("1930/6/14: roll(" + Koyomi.getFieldName(weekFields[i]) + ", +1)\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } } // Test the day fields - int[] dayFields = { DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK }; + int[] dayFields = {DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK}; for (int i = 0; i < dayFields.length; i++) { int field = dayFields[i]; // add() cal.clear(); - cal.set(1919, DECEMBER, 14-1, 23, 50, 00); + cal.set(1919, DECEMBER, 14 - 1, 23, 50, 00); cal.add(field, +1); if (!cal.checkDate(1919, DECEMBER, 14)) { - error("1919/12/13: add("+cal.getFieldName(field)+", +1)\n" - + cal.getMessage()+" " + cal.toDateTimeString()); + error("1919/12/13: add(" + Koyomi.getFieldName(field) + ", +1)\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); cal.set(1919, DECEMBER, 14, 00, 00, 00); cal.add(field, -1); if (!cal.checkDate(1919, DECEMBER, 13)) { - error("1919/12/14: add("+cal.getFieldName(field)+", -1)\n" - + cal.getMessage()+" " + cal.toDateTimeString()); + error("1919/12/14: add(" + Koyomi.getFieldName(field) + ", -1)\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); - cal.set(1930, JUNE, 21-1); + cal.set(1930, JUNE, 21 - 1); cal.add(field, +1); if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { - error("1930/6/20: add("+cal.getFieldName(field)+", +1)\n" - + cal.getMessage() + cal.toDateTimeString()); + error("1930/6/20: add(" + Koyomi.getFieldName(field) + ", +1)\n" + + cal.getMessage() + cal.toDateTimeString()); } cal.clear(); cal.set(1930, JUNE, 21, 01, 00, 00); cal.add(field, -1); if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) { - error("1930/6/21: add("+cal.getFieldName(field)+", -1)\n" - + cal.getMessage()+" " + cal.toDateTimeString()); + error("1930/6/21: add(" + Koyomi.getFieldName(field) + ", -1)\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } // roll() cal.clear(); - cal.set(1930, JUNE, 21-1); + cal.set(1930, JUNE, 21 - 1); int amount = +1; if (field == DAY_OF_WEEK) { amount += 700; } cal.roll(field, amount); if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { - error("1930/6/20: roll("+cal.getFieldName(field)+", +"+amount+")\n" - + cal.getMessage() + " " + cal.toDateTimeString()); + error("1930/6/20: roll(" + Koyomi.getFieldName(field) + ", +" + amount + ")\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); cal.set(1930, JUNE, 21, 01, 00, 00); @@ -131,93 +133,93 @@ public class Bug4958050 { } cal.roll(field, amount); if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) { - error("1930/6/21: roll("+cal.getFieldName(field)+", "+amount+")\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + error("1930/6/21: roll(" + Koyomi.getFieldName(field) + ", " + amount + ")\n" + + cal.getMessage() + " " + cal.toDateTimeString()); } } // Test the AM_PM field // add() cal.clear(); - cal.set(1919, DECEMBER, 14-1, 23, 50, 00); + cal.set(1919, DECEMBER, 14 - 1, 23, 50, 00); cal.add(AM_PM, +1); if (!cal.checkDate(1919, DECEMBER, 14) - || !cal.checkFieldValue(AM_PM, AM)) { + || !cal.checkFieldValue(AM_PM, AM)) { error("1919/12/13: add(AM_PM, +1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); - cal.set(1930, JUNE, 21-1, 12, 00, 00); + cal.set(1930, JUNE, 21 - 1, 12, 00, 00); cal.add(AM_PM, +1); if (!cal.checkDate(1930, JUNE, 21) - || !cal.checkFieldValue(AM_PM, AM)) { + || !cal.checkFieldValue(AM_PM, AM)) { error("1930/6/20: add(AM_PM, +1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); - cal.set(1930, JUNE, 21-2, 12, 00, 00); + cal.set(1930, JUNE, 21 - 2, 12, 00, 00); cal.add(AM_PM, +3); if (!cal.checkDate(1930, JUNE, 21) - || !cal.checkFieldValue(AM_PM, AM)) { + || !cal.checkFieldValue(AM_PM, AM)) { error("1930/6/10: add(AM_PM, +3)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); cal.set(1919, DECEMBER, 14, 11, 50, 00); cal.add(AM_PM, -1); - if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23, 50, 00, 000) - || !cal.checkFieldValue(AM_PM, PM)) { + if (!cal.checkDateTime(1919, DECEMBER, 14 - 1, 23, 50, 00, 000) + || !cal.checkFieldValue(AM_PM, PM)) { error("1919/12/14 11:50:00: add(AM_PM, -1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); cal.set(1930, JUNE, 21, 01, 00, 00); cal.add(AM_PM, -1); - if (!cal.checkDateTime(1930, JUNE, 21-1, 01+12, 00, 00, 000) - || !cal.checkFieldValue(AM_PM, PM)) { + if (!cal.checkDateTime(1930, JUNE, 21 - 1, 01 + 12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, PM)) { error("1930/6/20: add(AM_PM, -1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); cal.set(1930, JUNE, 21, 01, 00, 00); cal.add(AM_PM, -3); - if (!cal.checkDateTime(1930, JUNE, 21-2, 01+12, 00, 00, 000) - || !cal.checkFieldValue(AM_PM, PM)) { + if (!cal.checkDateTime(1930, JUNE, 21 - 2, 01 + 12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, PM)) { error("1930/6/10: add(AM_PM, -3)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } // roll() (should NOT change the date) cal.clear(); - cal.set(1919, DECEMBER, 14-1, 23, 50, 00); + cal.set(1919, DECEMBER, 14 - 1, 23, 50, 00); cal.roll(AM_PM, +1); - if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23-12, 50, 00, 000) - || !cal.checkFieldValue(AM_PM, AM)) { + if (!cal.checkDateTime(1919, DECEMBER, 14 - 1, 23 - 12, 50, 00, 000) + || !cal.checkFieldValue(AM_PM, AM)) { error("1919/12/13: roll(AM_PM, +1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); - cal.set(1930, JUNE, 21-1, 12, 00, 00); + cal.set(1930, JUNE, 21 - 1, 12, 00, 00); cal.roll(AM_PM, +1); - if (!cal.checkDateTime(1930, JUNE, 21-1, 12-12, 00, 00, 000) - || !cal.checkFieldValue(AM_PM, AM)) { + if (!cal.checkDateTime(1930, JUNE, 21 - 1, 12 - 12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, AM)) { error("1930/6/20: roll(AM_PM, +1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } cal.clear(); - cal.set(1930, JUNE, 21-2, 12, 00, 00); + cal.set(1930, JUNE, 21 - 2, 12, 00, 00); cal.roll(AM_PM, +3); - if (!cal.checkDateTime(1930, JUNE, 21-2, 12-12, 00, 00, 000) - || !cal.checkFieldValue(AM_PM, AM)) { + if (!cal.checkDateTime(1930, JUNE, 21 - 2, 12 - 12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, AM)) { error("1930/6/10: roll(AM_PM, +3)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } // Test the HOUR_OF_DAY field @@ -227,7 +229,7 @@ public class Bug4958050 { cal.add(HOUR_OF_DAY, +1); if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { error("1930/6/20 23:00:00: add(HOUR_OF_DAY, +1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } // roll() (should NOT change the date) @@ -236,7 +238,7 @@ public class Bug4958050 { cal.roll(HOUR_OF_DAY, +1); if (!cal.checkDateTime(1930, JUNE, 20, 00, 00, 00, 000)) { error("1930/6/20 23:00:00: roll(HOUR_OF_DAY, +1)\n" - + cal.getMessage()+" "+cal.toDateTimeString()); + + cal.getMessage() + " " + cal.toDateTimeString()); } checkErrors(); diff --git a/jdk/test/java/util/Calendar/CalendarRegression.java b/jdk/test/java/util/Calendar/CalendarRegression.java index 2852fae33f6..8a1ebcc4544 100644 --- a/jdk/test/java/util/Calendar/CalendarRegression.java +++ b/jdk/test/java/util/Calendar/CalendarRegression.java @@ -34,11 +34,24 @@ * @library /java/text/testlib * @run main CalendarRegression */ +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.SimpleTimeZone; +import java.util.TimeZone; -import java.lang.reflect.*; -import java.io.*; -import java.util.*; -import java.text.*; +import static java.util.Calendar.*; public class CalendarRegression extends IntlTest { @@ -47,99 +60,101 @@ public class CalendarRegression extends IntlTest { } /* - Synopsis: java.sql.Timestamp constructor works wrong on Windows 95 + Synopsis: java.sql.Timestamp constructor works wrong on Windows 95 - ==== Here is the test ==== - public static void main (String args[]) { - java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700); - logln("expected=1901-04-05 05:08:13.1234567"); - logln(" result="+t); - } + ==== Here is the test ==== + public static void main (String args[]) { + java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700); + logln("expected=1901-04-05 05:08:13.1234567"); + logln(" result="+t); + } - ==== Here is the output of the test on Solaris or NT ==== - expected=1901-04-05 05:08:13.1234567 - result=1901-04-05 05:08:13.1234567 - - ==== Here is the output of the test on Windows95 ==== - expected=1901-04-05 05:08:13.1234567 - result=1901-04-05 06:08:13.1234567 - */ + ==== Here is the output of the test on Solaris or NT ==== + expected=1901-04-05 05:08:13.1234567 + result=1901-04-05 05:08:13.1234567 + ==== Here is the output of the test on Windows95 ==== + expected=1901-04-05 05:08:13.1234567 + result=1901-04-05 06:08:13.1234567 + */ public void Test4031502() { // This bug actually occurs on Windows NT as well, and doesn't // require the host zone to be set; it can be set in Java. String[] ids = TimeZone.getAvailableIDs(); boolean bad = false; - for (int i=0; i max) + } + if (dow < min || dow > max) { errln("FAIL: Day of week " + dow + " out of range"); - if (dow != Calendar.SUNDAY) + } + if (dow != SUNDAY) { errln("FAIL: Day of week should be SUNDAY Got " + dow); + } } + @SuppressWarnings("deprecation") public void Test4071385() { Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(98, Calendar.JUNE, 24)); - cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field + cal.setTime(new Date(98, JUNE, 24)); + cal.set(MONTH, NOVEMBER); // change a field logln(cal.getTime().toString()); - if (!cal.getTime().equals(new Date(98, Calendar.NOVEMBER, 24))) + if (!cal.getTime().equals(new Date(98, NOVEMBER, 24))) { errln("Fail"); + } } public void Test4073929() { GregorianCalendar foo1 = new GregorianCalendar(1997, 8, 27); - foo1.add(Calendar.DAY_OF_MONTH, +1); - int testyear = foo1.get(Calendar.YEAR); - int testmonth = foo1.get(Calendar.MONTH); - int testday = foo1.get(Calendar.DAY_OF_MONTH); - if (testyear != 1997 || - testmonth != 8 || - testday != 28) + foo1.add(DAY_OF_MONTH, +1); + int testyear = foo1.get(YEAR); + int testmonth = foo1.get(MONTH); + int testday = foo1.get(DAY_OF_MONTH); + if (testyear != 1997 + || testmonth != 8 + || testday != 28) { errln("Fail: Calendar not initialized"); + } } public void Test4083167() { @@ -322,27 +346,26 @@ public class CalendarRegression extends IntlTest { Date firstDate = new Date(); Calendar cal = new GregorianCalendar(); cal.setTime(firstDate); - long firstMillisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L + - cal.get(Calendar.MINUTE) * 60000L + - cal.get(Calendar.SECOND) * 1000L + - cal.get(Calendar.MILLISECOND); + long firstMillisInDay = cal.get(HOUR_OF_DAY) * 3600000L + + cal.get(MINUTE) * 60000L + + cal.get(SECOND) * 1000L + + cal.get(MILLISECOND); logln("Current time: " + firstDate.toString()); - for (int validity=0; validity<30; validity++) { - Date lastDate = new Date(firstDate.getTime() + - (long)validity*1000*24*60*60); + for (int validity = 0; validity < 30; validity++) { + Date lastDate = new Date(firstDate.getTime() + + (long) validity * 1000 * 24 * 60 * 60); cal.setTime(lastDate); - long millisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L + - cal.get(Calendar.MINUTE) * 60000L + - cal.get(Calendar.SECOND) * 1000L + - cal.get(Calendar.MILLISECOND); + long millisInDay = cal.get(HOUR_OF_DAY) * 3600000L + + cal.get(MINUTE) * 60000L + + cal.get(SECOND) * 1000L + + cal.get(MILLISECOND); if (firstMillisInDay != millisInDay) { errln("Day has shifted " + lastDate); } } - } - finally { + } finally { TimeZone.setDefault(saveZone); } } @@ -359,61 +382,60 @@ public class CalendarRegression extends IntlTest { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); date = new SimpleDateFormat("zzzz"); - Calendar cal=Calendar.getInstance(); - cal.set(1997,Calendar.SEPTEMBER,30); - Date now=cal.getTime(); + Calendar cal = Calendar.getInstance(); + cal.set(1997, SEPTEMBER, 30); + Date now = cal.getTime(); String formattedDate = date.format(now); if (!formattedDate.equals(summerTime)) { errln("Wrong display name \"" + formattedDate - + "\" for <" + now + ">"); + + "\" for <" + now + ">"); } - int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + int weekOfYear = cal.get(WEEK_OF_YEAR); if (weekOfYear != 40) { errln("Wrong week-of-year " + weekOfYear - + " for <" + now + ">"); + + " for <" + now + ">"); } - cal.set(1996,Calendar.DECEMBER,31); - now=cal.getTime(); + cal.set(1996, DECEMBER, 31); + now = cal.getTime(); formattedDate = date.format(now); if (!formattedDate.equals(standardTime)) { errln("Wrong display name \"" + formattedDate - + "\" for <" + now + ">"); + + "\" for <" + now + ">"); } - weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + weekOfYear = cal.get(WEEK_OF_YEAR); if (weekOfYear != 1) { errln("Wrong week-of-year " + weekOfYear - + " for <" + now + ">"); + + " for <" + now + ">"); } - cal.set(1997,Calendar.JANUARY,1); - now=cal.getTime(); + cal.set(1997, JANUARY, 1); + now = cal.getTime(); formattedDate = date.format(now); if (!formattedDate.equals(standardTime)) { errln("Wrong display name \"" + formattedDate - + "\" for <" + now + ">"); + + "\" for <" + now + ">"); } - weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + weekOfYear = cal.get(WEEK_OF_YEAR); if (weekOfYear != 1) { errln("Wrong week-of-year " + weekOfYear - + " for <" + now + ">"); + + " for <" + now + ">"); } - cal.set(1997,Calendar.JANUARY,8); - now=cal.getTime(); + cal.set(1997, JANUARY, 8); + now = cal.getTime(); formattedDate = date.format(now); if (!formattedDate.equals(standardTime)) { errln("Wrong display name \"" + formattedDate - + "\" for <" + now + ">"); + + "\" for <" + now + ">"); } - weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + weekOfYear = cal.get(WEEK_OF_YEAR); if (weekOfYear != 2) { errln("Wrong week-of-year " + weekOfYear - + " for <" + now + ">"); + + " for <" + now + ">"); } - } - finally { + } finally { Locale.setDefault(saveLocale); TimeZone.setDefault(saveZone); } @@ -428,9 +450,9 @@ public class CalendarRegression extends IntlTest { cal1.set( Calendar.MINUTE, 20 ); cal1.set( Calendar.SECOND, 40 ); */ - logln( " Cal1 = " + cal1.getTime().getTime() ); - logln( " Cal1 time in ms = " + cal1.get(Calendar.MILLISECOND) ); - for( int k = 0; k < 100 ; k++ ); + logln(" Cal1 = " + cal1.getTime().getTime()); + logln(" Cal1 time in ms = " + cal1.get(MILLISECOND)); + for (int k = 0; k < 100; k++); GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40); /*cal2.set( Calendar.YEAR, 1997 ); @@ -440,17 +462,19 @@ public class CalendarRegression extends IntlTest { cal2.set( Calendar.MINUTE, 20 ); cal2.set( Calendar.SECOND, 40 ); */ - logln( " Cal2 = " + cal2.getTime().getTime() ); - logln( " Cal2 time in ms = " + cal2.get(Calendar.MILLISECOND) ); - if( !cal1.equals( cal2 ) ) + logln(" Cal2 = " + cal2.getTime().getTime()); + logln(" Cal2 time in ms = " + cal2.get(MILLISECOND)); + if (!cal1.equals(cal2)) { errln("Fail: Milliseconds randomized"); + } } public void Test4095407() { - GregorianCalendar a = new GregorianCalendar(1997,Calendar.NOVEMBER, 13); - int dow = a.get(Calendar.DAY_OF_WEEK); - if (dow != Calendar.THURSDAY) + GregorianCalendar a = new GregorianCalendar(1997, NOVEMBER, 13); + int dow = a.get(DAY_OF_WEEK); + if (dow != THURSDAY) { errln("Fail: Want THURSDAY Got " + dow); + } } public void Test4096231() { @@ -461,72 +485,74 @@ public class CalendarRegression extends IntlTest { Calendar cal1 = new GregorianCalendar(PST); cal1.setTime(new Date(880698639000L)); int p; - logln("PST 1 is: " + (p=cal1.get(cal1.HOUR_OF_DAY))); + logln("PST 1 is: " + (p = cal1.get(HOUR_OF_DAY))); cal1.setTimeZone(GMT); // Issue 1: Changing the timezone doesn't change the // represented time. - int h1,h2; - logln("GMT 1 is: " + (h1=cal1.get(cal1.HOUR_OF_DAY))); + int h1, h2; + logln("GMT 1 is: " + (h1 = cal1.get(HOUR_OF_DAY))); cal1.setTime(new Date(880698639000L)); - logln("GMT 2 is: " + (h2=cal1.get(cal1.HOUR_OF_DAY))); + logln("GMT 2 is: " + (h2 = cal1.get(HOUR_OF_DAY))); // Note: This test had a bug in it. It wanted h1!=h2, when // what was meant was h1!=p. Fixed this concurrent with fix // to 4177484. - if (p == h1 || h1 != h2) + if (p == h1 || h1 != h2) { errln("Fail: Hour same in different zones"); + } Calendar cal2 = new GregorianCalendar(GMT); Calendar cal3 = new GregorianCalendar(PST); - cal2.set(Calendar.MILLISECOND, 0); - cal3.set(Calendar.MILLISECOND, 0); + cal2.set(MILLISECOND, 0); + cal3.set(MILLISECOND, 0); - cal2.set(cal1.get(cal1.YEAR), - cal1.get(cal1.MONTH), - cal1.get(cal1.DAY_OF_MONTH), - cal1.get(cal1.HOUR_OF_DAY), - cal1.get(cal1.MINUTE), - cal1.get(cal1.SECOND)); + cal2.set(cal1.get(YEAR), + cal1.get(MONTH), + cal1.get(DAY_OF_MONTH), + cal1.get(HOUR_OF_DAY), + cal1.get(MINUTE), + cal1.get(SECOND)); - long t1,t2,t3,t4; - logln("RGMT 1 is: " + (t1=cal2.getTime().getTime())); + long t1, t2, t3, t4; + logln("RGMT 1 is: " + (t1 = cal2.getTime().getTime())); cal3.set(year, month, day, hr, min, sec); - logln("RPST 1 is: " + (t2=cal3.getTime().getTime())); + logln("RPST 1 is: " + (t2 = cal3.getTime().getTime())); cal3.setTimeZone(GMT); - logln("RGMT 2 is: " + (t3=cal3.getTime().getTime())); - cal3.set(cal1.get(cal1.YEAR), - cal1.get(cal1.MONTH), - cal1.get(cal1.DAY_OF_MONTH), - cal1.get(cal1.HOUR_OF_DAY), - cal1.get(cal1.MINUTE), - cal1.get(cal1.SECOND)); + logln("RGMT 2 is: " + (t3 = cal3.getTime().getTime())); + cal3.set(cal1.get(YEAR), + cal1.get(MONTH), + cal1.get(DAY_OF_MONTH), + cal1.get(HOUR_OF_DAY), + cal1.get(MINUTE), + cal1.get(SECOND)); // Issue 2: Calendar continues to use the timezone in its // constructor for set() conversions, regardless // of calls to setTimeZone() - logln("RGMT 3 is: " + (t4=cal3.getTime().getTime())); - if (t1 == t2 || - t1 != t4 || - t2 != t3) + logln("RGMT 3 is: " + (t4 = cal3.getTime().getTime())); + if (t1 == t2 + || t1 != t4 + || t2 != t3) { errln("Fail: Calendar zone behavior faulty"); + } } public void Test4096539() { - int[] y = {31,28,31,30,31,30,31,31,30,31,30,31}; + int[] y = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - for (int x=0;x<12;x++) { - GregorianCalendar gc = new - GregorianCalendar(1997,x,y[x]); - int m1,m2; - log((m1=gc.get(Calendar.MONTH)+1)+"/"+ - gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)+ - " + 1mo = "); + for (int x = 0; x < 12; x++) { + GregorianCalendar gc = new GregorianCalendar(1997, x, y[x]); + int m1, m2; + log((m1 = gc.get(MONTH) + 1) + "/" + + gc.get(DATE) + "/" + gc.get(YEAR) + + " + 1mo = "); - gc.add(Calendar.MONTH, 1); - logln((m2=gc.get(Calendar.MONTH)+1)+"/"+ - gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR) - ); + gc.add(MONTH, 1); + logln((m2 = gc.get(MONTH) + 1) + "/" + + gc.get(DATE) + "/" + gc.get(YEAR) + ); int m = (m1 % 12) + 1; - if (m2 != m) + if (m2 != m) { errln("Fail: Want " + m + " Got " + m2); + } } } @@ -538,13 +564,14 @@ public class CalendarRegression extends IntlTest { return; } - GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance(); - cal.set(Calendar.YEAR, 1997); - cal.set(Calendar.DAY_OF_YEAR, 1); + GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance(); + cal.set(YEAR, 1997); + cal.set(DAY_OF_YEAR, 1); Date d = cal.getTime(); // Should be Jan 1 logln(d.toString()); - if (cal.get(Calendar.DAY_OF_YEAR) != 1) + if (cal.get(DAY_OF_YEAR) != 1) { errln("Fail: DAY_OF_YEAR not set"); + } } public void Test4103271() { @@ -555,28 +582,28 @@ public class CalendarRegression extends IntlTest { } SimpleDateFormat sdf = new SimpleDateFormat(); - int numYears=40, startYear=1997, numDays=15; + int numYears = 40, startYear = 1997, numDays = 15; String output, testDesc; - GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance(); + GregorianCalendar testCal = (GregorianCalendar) Calendar.getInstance(); testCal.clear(); sdf.setCalendar(testCal); sdf.applyPattern("d MMM yyyy"); boolean fail = false; - for (int firstDay=1; firstDay<=2; firstDay++) { - for (int minDays=1; minDays<=7; minDays++) { + for (int firstDay = 1; firstDay <= 2; firstDay++) { + for (int minDays = 1; minDays <= 7; minDays++) { testCal.setMinimalDaysInFirstWeek(minDays); testCal.setFirstDayOfWeek(firstDay); testDesc = ("Test" + String.valueOf(firstDay) + String.valueOf(minDays)); - logln(testDesc + " => 1st day of week=" + - String.valueOf(firstDay) + - ", minimum days in first week=" + - String.valueOf(minDays)); - for (int j=startYear; j<=startYear+numYears; j++) { - testCal.set(j,11,25); - for(int i=0; i 1st day of week=" + + String.valueOf(firstDay) + + ", minimum days in first week=" + + String.valueOf(minDays)); + for (int j = startYear; j <= startYear + numYears; j++) { + testCal.set(j, 11, 25); + for (int i = 0; i < numDays; i++) { + testCal.add(DATE, 1); String calWOY; - int actWOY = testCal.get(Calendar.WEEK_OF_YEAR); + int actWOY = testCal.get(WEEK_OF_YEAR); if (actWOY < 1 || actWOY > 53) { Date d = testCal.getTime(); calWOY = String.valueOf(actWOY); @@ -592,20 +619,19 @@ public class CalendarRegression extends IntlTest { int[] DATA = { 3, 52, 52, 52, 52, 52, 52, 52, - 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 4, 52, 52, 52, 52, 52, 52, 52, - 53, 53, 53, 53, 53, 53, 53, - 1, 1, 1, 1, 1, 1, 1, - }; - testCal.setFirstDayOfWeek(Calendar.SUNDAY); - for (int j=0; j " + testCal.getTime()); + if (ADDROLL[i] == ADD) { + testCal.add(WEEK_OF_YEAR, amount); + } else { + testCal.roll(WEEK_OF_YEAR, amount); + } + log((ADDROLL[i] == ADD ? "add(WOY," : "roll(WOY,") + + amount + ")\t " + before + + "\n\t\t => " + testCal.getTime()); if (!after.equals(testCal.getTime())) { logln("\tFAIL\n\t\texp: " + after); fail = true; - } else + } else { logln(" OK"); + } testCal.setTime(after); - if (ADDROLL[i] == ADD) - testCal.add(Calendar.WEEK_OF_YEAR, -amount); - else - testCal.roll(Calendar.WEEK_OF_YEAR, -amount); - log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") + - (-amount) + ") " + after + - "\n\t\t => " + testCal.getTime()); + if (ADDROLL[i] == ADD) { + testCal.add(WEEK_OF_YEAR, -amount); + } else { + testCal.roll(WEEK_OF_YEAR, -amount); + } + log((ADDROLL[i] == ADD ? "add(WOY," : "roll(WOY,") + + (-amount) + ") " + after + + "\n\t\t => " + testCal.getTime()); if (!before.equals(testCal.getTime())) { logln("\tFAIL\n\t\texp: " + before); fail = true; + } else { + logln("\tOK"); } - else logln("\tOK"); } if (fail) { @@ -719,63 +749,68 @@ public class CalendarRegression extends IntlTest { public void Test4106136() { Locale saveLocale = Locale.getDefault(); try { - Locale[] locales = { Locale.CHINESE, Locale.CHINA }; - for (int i=0; i maxYear) { - errln("Failed for "+DATES[i].getTime()+" ms: year=" + - year + ", maxYear=" + maxYear); + errln("Failed for " + DATES[i].getTime() + " ms: year=" + + year + ", maxYear=" + maxYear); } } } @@ -1068,28 +1104,29 @@ public class CalendarRegression extends IntlTest { "SECOND", "MILLISECOND", "ZONE_OFFSET", - "DST_OFFSET" - }; + "DST_OFFSET"}; GregorianCalendar calendar = new GregorianCalendar(); calendar.setLenient(false); - Date date = new Date(1996-1900, Calendar.JANUARY, 3); // Arbitrary date - for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + @SuppressWarnings("deprecation") + Date date = new Date(1996 - 1900, JANUARY, 3); // Arbitrary date + for (int field = 0; field < FIELD_COUNT; field++) { calendar.setTime(date); // Note: In the bug report, getActualMaximum() was called instead // of getMaximum() -- this was an error. The validation code doesn't // use getActualMaximum(), since that's too costly. int max = calendar.getMaximum(field); - int value = max+1; + int value = max + 1; calendar.set(field, value); try { calendar.getTime(); // Force time computation // We expect an exception to be thrown. If we fall through // to the next line, then we have a bug. - errln("Test failed with field " + fieldName[field] + - ", date before: " + date + - ", date after: " + calendar.getTime() + - ", value: " + value + " (max = " + max +")"); - } catch (IllegalArgumentException e) {} + errln("Test failed with field " + fieldName[field] + + ", date before: " + date + + ", date after: " + calendar.getTime() + + ", value: " + value + " (max = " + max + ")"); + } catch (IllegalArgumentException e) { + } } } @@ -1099,19 +1136,19 @@ public class CalendarRegression extends IntlTest { * CANNOT REPRODUCE THIS BUG */ public void Test4149677() { - TimeZone[] zones = { TimeZone.getTimeZone("GMT"), - TimeZone.getTimeZone("PST"), - TimeZone.getTimeZone("EAT") }; - for (int i=0; i0) logln("---"); + for (int i = 0; i < 5; ++i) { + if (i > 0) { + logln("---"); + } cal.clear(); - cal.set(1998, Calendar.APRIL, 5, i, 0); + cal.set(1998, APRIL, 5, i, 0); d = cal.getTime(); String s0 = d.toString(); logln("0 " + i + ": " + s0); cal.clear(); - cal.set(1998, Calendar.APRIL, 4, i+24, 0); + cal.set(1998, APRIL, 4, i + 24, 0); d = cal.getTime(); String sPlus = d.toString(); logln("+ " + i + ": " + sPlus); cal.clear(); - cal.set(1998, Calendar.APRIL, 6, i-24, 0); + cal.set(1998, APRIL, 6, i - 24, 0); d = cal.getTime(); String sMinus = d.toString(); logln("- " + i + ": " + sMinus); @@ -1164,8 +1203,7 @@ public class CalendarRegression extends IntlTest { errln("Fail: All three lines must match"); } } - } - finally { + } finally { TimeZone.setDefault(savedTz); } } @@ -1174,14 +1212,14 @@ public class CalendarRegression extends IntlTest { * Adding 12 months behaves differently from adding 1 year */ public void Test4165343() { - GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29); + GregorianCalendar calendar = new GregorianCalendar(1996, FEBRUARY, 29); Date start = calendar.getTime(); logln("init date: " + start); - calendar.add(Calendar.MONTH, 12); + calendar.add(MONTH, 12); Date date1 = calendar.getTime(); logln("after adding 12 months: " + date1); calendar.setTime(start); - calendar.add(Calendar.YEAR, 1); + calendar.add(YEAR, 1); Date date2 = calendar.getTime(); logln("after adding one year : " + date2); if (date1.equals(date2)) { @@ -1196,34 +1234,34 @@ public class CalendarRegression extends IntlTest { */ public void Test4166109() { /* Test month: - * - * March 1998 - * Su Mo Tu We Th Fr Sa - * 1 2 3 4 5 6 7 - * 8 9 10 11 12 13 14 - * 15 16 17 18 19 20 21 - * 22 23 24 25 26 27 28 - * 29 30 31 + * + * March 1998 + * Su Mo Tu We Th Fr Sa + * 1 2 3 4 5 6 7 + * 8 9 10 11 12 13 14 + * 15 16 17 18 19 20 21 + * 22 23 24 25 26 27 28 + * 29 30 31 */ boolean passed = true; - int field = Calendar.WEEK_OF_MONTH; + int field = WEEK_OF_MONTH; GregorianCalendar calendar = new GregorianCalendar(Locale.US); - calendar.set(1998, Calendar.MARCH, 1); + calendar.set(1998, MARCH, 1); calendar.setMinimalDaysInFirstWeek(1); logln("Date: " + calendar.getTime()); - int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH); + int firstInMonth = calendar.get(DAY_OF_MONTH); - for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) { + for (int firstInWeek = SUNDAY; firstInWeek <= SATURDAY; firstInWeek++) { calendar.setFirstDayOfWeek(firstInWeek); int returned = calendar.getActualMaximum(field); - int expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7; + int expected = (31 + ((firstInMonth - firstInWeek + 7) % 7) + 6) / 7; - logln("First day of week = " + firstInWeek + - " getActualMaximum(WEEK_OF_MONTH) = " + returned + - " expected = " + expected + - ((returned == expected) ? " ok" : " FAIL")); + logln("First day of week = " + firstInWeek + + " getActualMaximum(WEEK_OF_MONTH) = " + returned + + " expected = " + expected + + ((returned == expected) ? " ok" : " FAIL")); if (returned != expected) { passed = false; @@ -1242,19 +1280,19 @@ public class CalendarRegression extends IntlTest { * changed. See 4928615. */ public void Test4167060() { - int field = Calendar.YEAR; + int field = YEAR; DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G", - Locale.US); + Locale.US); int[][] dates = { // year, month, day of month - { 100, Calendar.NOVEMBER, 1 }, - { -99 /*100BC*/, Calendar.JANUARY, 1 }, - { 1996, Calendar.FEBRUARY, 29 }}; + {100, NOVEMBER, 1}, + {-99 /*100BC*/, JANUARY, 1}, + {1996, FEBRUARY, 29}}; - String[] id = { "Hybrid", "Gregorian", "Julian" }; + String[] id = {"Hybrid", "Gregorian", "Julian"}; - for (int k=0; k<3; ++k) { + for (int k = 0; k < 3; ++k) { logln("--- " + id[k] + " ---"); for (int j = 0; j < dates.length; ++j) { @@ -1265,7 +1303,7 @@ public class CalendarRegression extends IntlTest { calendar.setGregorianChange(new Date(Long.MAX_VALUE)); } calendar.set(dates[j][0], dates[j][1], dates[j][2]); - format.setCalendar((Calendar)calendar.clone()); + format.setCalendar((Calendar) calendar.clone()); Date dateBefore = calendar.getTime(); @@ -1273,7 +1311,7 @@ public class CalendarRegression extends IntlTest { logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime())); logln("date before: " + format.format(dateBefore)); - int years[] = {2000, maxYear-1, maxYear, maxYear+1}; + int[] years = {2000, maxYear - 1, maxYear, maxYear + 1}; for (int i = 0; i < years.length; i++) { boolean valid = years[i] <= maxYear; @@ -1282,8 +1320,8 @@ public class CalendarRegression extends IntlTest { int newYear = calendar.get(field); calendar.setTime(dateBefore); // restore calendar for next use - logln(" Year " + years[i] + (valid? " ok " : " bad") + - " => " + format.format(dateAfter)); + logln(" Year " + years[i] + (valid ? " ok " : " bad") + + " => " + format.format(dateAfter)); if (valid && newYear != years[i]) { errln(" FAIL: " + newYear + " should be valid; date, month and time shouldn't change"); } else if (!valid && newYear == years[i]) { @@ -1305,18 +1343,16 @@ public class CalendarRegression extends IntlTest { return; } - int fieldsList[][] = { - { 1997, Calendar.FEBRUARY, 1, 10, 45, 15, 900 }, - { 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 }, + int[][] fieldsList = { + {1997, FEBRUARY, 1, 10, 45, 15, 900}, + {1999, DECEMBER, 22, 23, 59, 59, 999}, // test case for 4960642 with default cutover - { 1582, Calendar.OCTOBER, 4, 23, 59, 59, 999 }, - }; + {1582, OCTOBER, 4, 23, 59, 59, 999}}; String[] fieldNames = { "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", - "ZONE_OFFSET", "DST_OFFSET" - }; + "ZONE_OFFSET", "DST_OFFSET"}; Locale savedLocale = Locale.getDefault(); Locale.setDefault(Locale.US); @@ -1326,25 +1362,25 @@ public class CalendarRegression extends IntlTest { GregorianCalendar cal = new GregorianCalendar(); cal.setTime(new Date(0)); - cal.roll(Calendar.HOUR, 0x7F000000); - cal.roll(Calendar.HOUR, -0x7F000000); + cal.roll(HOUR, 0x7F000000); + cal.roll(HOUR, -0x7F000000); if (cal.getTime().getTime() != 0) { - errln("Hour rolling broken. expected 0, got "+cal.getTime().getTime()); + errln("Hour rolling broken. expected 0, got " + cal.getTime().getTime()); } - for (int op=0; op<2; ++op) { - logln("Testing GregorianCalendar " + (op==0 ? "add" : "roll")); + for (int op = 0; op < 2; ++op) { + logln("Testing GregorianCalendar " + (op == 0 ? "add" : "roll")); - for (int field=0; field < Calendar.FIELD_COUNT; ++field) { - if (field != Calendar.ZONE_OFFSET && - field != Calendar.DST_OFFSET) { - for (int j=0; j " + - cal.get(Calendar.YEAR) + - "/" + (cal.get(Calendar.MONTH) + 1) + - "/" + cal.get(Calendar.DATE) + - " " + cal.get(Calendar.HOUR_OF_DAY) + - ":" + cal.get(Calendar.MINUTE) + - ":" + cal.get(Calendar.SECOND) + - "." + cal.get(Calendar.MILLISECOND) + - " d=" + delta); + errln((op == 0 ? "add(" : "roll(") + + fieldNames[field] + ", " + + (i < limit ? "+" : "-") + "1) => " + + cal.get(YEAR) + + "/" + (cal.get(MONTH) + 1) + + "/" + cal.get(DATE) + + " " + cal.get(HOUR_OF_DAY) + + ":" + cal.get(MINUTE) + + ":" + cal.get(SECOND) + + "." + cal.get(MILLISECOND) + + " d=" + delta); } } } } } } - } - finally { + } finally { Locale.setDefault(savedLocale); } } @@ -1425,14 +1460,14 @@ public class CalendarRegression extends IntlTest { public void Test4174361() { GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29); - calendar.add(Calendar.MONTH, 10); + calendar.add(MONTH, 10); Date date1 = calendar.getTime(); - int d1 = calendar.get(Calendar.DAY_OF_MONTH); + int d1 = calendar.get(DAY_OF_MONTH); calendar = new GregorianCalendar(1996, 1, 29); - calendar.add(Calendar.MONTH, 11); + calendar.add(MONTH, 11); Date date2 = calendar.getTime(); - int d2 = calendar.get(Calendar.DAY_OF_MONTH); + int d2 = calendar.get(DAY_OF_MONTH); if (d1 != d2) { errln("adding months to Feb 29 broken"); @@ -1449,9 +1484,9 @@ public class CalendarRegression extends IntlTest { Calendar cal = Calendar.getInstance(PST, Locale.US); cal.clear(); cal.set(1999, 3, 21, 15, 5, 0); // Arbitrary - int h1 = cal.get(Calendar.HOUR_OF_DAY); + int h1 = cal.get(HOUR_OF_DAY); cal.setTimeZone(EST); - int h2 = cal.get(Calendar.HOUR_OF_DAY); + int h2 = cal.get(HOUR_OF_DAY); if (h1 == h2) { errln("FAIL: Fields not updated after setTimeZone"); } @@ -1460,7 +1495,7 @@ public class CalendarRegression extends IntlTest { // getTime() returns zone-independent time in ms. cal.clear(); cal.setTimeZone(PST); - cal.set(Calendar.HOUR_OF_DAY, 10); + cal.set(HOUR_OF_DAY, 10); Date pst10 = cal.getTime(); cal.setTimeZone(EST); Date est10 = cal.getTime(); @@ -1474,28 +1509,27 @@ public class CalendarRegression extends IntlTest { */ public void Test4197699() { GregorianCalendar cal = new GregorianCalendar(); - cal.setFirstDayOfWeek(Calendar.MONDAY); + cal.setFirstDayOfWeek(MONDAY); cal.setMinimalDaysInFirstWeek(4); DateFormat fmt = new SimpleDateFormat("E dd MMM yyyy 'DOY='D 'WOY='w"); fmt.setCalendar(cal); int[] DATA = { - 2000, Calendar.JANUARY, 1, 52, - 2001, Calendar.DECEMBER, 31, 1, - }; + 2000, JANUARY, 1, 52, + 2001, DECEMBER, 31, 1}; - for (int i=0; i " + actual + - ", want " + DATA[i+1]); + if (!actual.equals(DATA[i + 1])) { + errln("FAIL: Sunday " + DATA[i] + + " of Jan 1997 -> " + actual + + ", want " + DATA[i + 1]); } } } - public void Test4288792() throws Exception - { + public void Test4288792() throws Exception { TimeZone savedTZ = TimeZone.getDefault(); TimeZone.setDefault(TimeZone.getTimeZone("GMT")); GregorianCalendar cal = new GregorianCalendar(); @@ -1631,45 +1664,44 @@ public class CalendarRegression extends IntlTest { for (int i = 1900; i < 2100; i++) { for (int j1 = 1; j1 <= 7; j1++) { // Loop for MinimalDaysInFirstWeek: 1..7 - for (int j = Calendar.SUNDAY; j <= Calendar.SATURDAY; j++) { + for (int j = SUNDAY; j <= SATURDAY; j++) { // Loop for FirstDayOfWeek: SUNDAY..SATURDAY cal.clear(); cal.setMinimalDaysInFirstWeek(j1); cal.setFirstDayOfWeek(j); - cal.set(Calendar.YEAR, i); - int maxWeek = cal.getActualMaximum(Calendar.WEEK_OF_YEAR); - cal.set(Calendar.WEEK_OF_YEAR, maxWeek); - cal.set(Calendar.DAY_OF_WEEK, j); + cal.set(YEAR, i); + int maxWeek = cal.getActualMaximum(WEEK_OF_YEAR); + cal.set(WEEK_OF_YEAR, maxWeek); + cal.set(DAY_OF_WEEK, j); for (int k = 1; k < 7; k++) { - cal.add(Calendar.DATE, 1); - int WOY = cal.get(Calendar.WEEK_OF_YEAR); + cal.add(DATE, 1); + int WOY = cal.get(WEEK_OF_YEAR); if (WOY != maxWeek) { errln(cal.getTime() + ",got=" + WOY - + ",expected=" + maxWeek - + ",min=" + j1 + ",first=" + j); + + ",expected=" + maxWeek + + ",min=" + j1 + ",first=" + j); } } - cal.add(Calendar.DATE, 1); - int WOY = cal.get(Calendar.WEEK_OF_YEAR); + cal.add(DATE, 1); + int WOY = cal.get(WEEK_OF_YEAR); if (WOY != 1) { errln(cal.getTime() + ",got=" + WOY - + ",expected=1,min=" + j1 + ",first" + j); + + ",expected=1,min=" + j1 + ",first" + j); } } } } - } - finally { + } finally { TimeZone.setDefault(savedTZ); } } public void Test4328747() throws Exception { - Calendar c = (Calendar)Calendar.getInstance(Locale.US); + Calendar c = Calendar.getInstance(Locale.US); c.clear(); - c.set(1966,0,1); // 1 jan 1966 + c.set(1966, 0, 1); // 1 jan 1966 // serialize ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -1679,16 +1711,16 @@ public class CalendarRegression extends IntlTest { // deserialize ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); - Calendar result = (Calendar)t.readObject(); + Calendar result = (Calendar) t.readObject(); // let recalculate fields with the same UTC time result.setTime(result.getTime()); // Bug gives 1965 11 19 - if ((result.get(c.YEAR) != 1966) || (result.get(c.MONTH) != 0) - || (result.get(c.DATE) != 1)) { + if ((result.get(YEAR) != 1966) || (result.get(MONTH) != 0) + || (result.get(DATE) != 1)) { errln("deserialized Calendar returned wrong date field(s): " - + result.get(c.YEAR) + "/" + result.get(c.MONTH) + "/" + result.get(c.DATE) - + ", expected 1966/0/1"); + + result.get(YEAR) + "/" + result.get(MONTH) + "/" + result.get(DATE) + + ", expected 1966/0/1"); } } @@ -1700,13 +1732,13 @@ public class CalendarRegression extends IntlTest { TimeZone savedTimeZone = TimeZone.getDefault(); try { boolean pass = true; - String[] IDs = new String[] {"Undefined", "PST", "US/Pacific", - "GMT+3:00", "GMT-01:30"}; + String[] IDs = new String[]{"Undefined", "PST", "US/Pacific", + "GMT+3:00", "GMT-01:30"}; for (int i = 0; i < IDs.length; i++) { TimeZone tz = TimeZone.getTimeZone(IDs[i]); TimeZone.setDefault(tz); - Calendar c = (Calendar)Calendar.getInstance(); + Calendar c = Calendar.getInstance(); // serialize ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -1719,26 +1751,20 @@ public class CalendarRegression extends IntlTest { if (!c.equals(t.readObject())) { pass = false; - logln("Calendar instance which uses TimeZone <" + - IDs[i] + "> is incorrectly serialized/deserialized."); + logln("Calendar instance which uses TimeZone <" + + IDs[i] + "> is incorrectly serialized/deserialized."); } else { - logln("Calendar instance which uses TimeZone <" + - IDs[i] + "> is correctly serialized/deserialized."); + logln("Calendar instance which uses TimeZone <" + + IDs[i] + "> is correctly serialized/deserialized."); } } if (!pass) { errln("Fail: Calendar serialization/equality bug"); } - } - catch (IOException e) { + } catch (IOException | ClassNotFoundException e) { errln("Fail: " + e); e.printStackTrace(); - } - catch (ClassNotFoundException e) { - errln("Fail: " + e); - e.printStackTrace(); - } - finally { + } finally { TimeZone.setDefault(savedTimeZone); } } @@ -1747,12 +1773,12 @@ public class CalendarRegression extends IntlTest { * 4546637: Incorrect WEEK_OF_MONTH after changing First Day Of Week */ public void Test4546637() { - GregorianCalendar day = new GregorianCalendar (2001, Calendar.NOVEMBER, 04); + GregorianCalendar day = new GregorianCalendar(2001, NOVEMBER, 04); day.setMinimalDaysInFirstWeek(1); - int wom = day.get(Calendar.WEEK_OF_MONTH); + int wom = day.get(WEEK_OF_MONTH); - day.setFirstDayOfWeek(Calendar.MONDAY); - if (day.get(Calendar.WEEK_OF_MONTH) != 1) { + day.setFirstDayOfWeek(MONDAY); + if (day.get(WEEK_OF_MONTH) != 1) { errln("Fail: 2001/11/4 must be the first week of the month."); } } @@ -1761,14 +1787,14 @@ public class CalendarRegression extends IntlTest { * 4623997: GregorianCalendar returns bad WEEK_OF_YEAR */ public void Test4623997() { - GregorianCalendar cal = new GregorianCalendar(2000, GregorianCalendar.JANUARY, 1); + GregorianCalendar cal = new GregorianCalendar(2000, JANUARY, 1); - int dow = cal.get(GregorianCalendar.DAY_OF_WEEK); + int dow = cal.get(DAY_OF_WEEK); - cal.setFirstDayOfWeek(GregorianCalendar.MONDAY); + cal.setFirstDayOfWeek(MONDAY); cal.setMinimalDaysInFirstWeek(4); - if (cal.get(GregorianCalendar.WEEK_OF_YEAR) != 52) { + if (cal.get(WEEK_OF_YEAR) != 52) { errln("Fail: 2000/1/1 must be the 52nd week of the year."); } } @@ -1800,9 +1826,9 @@ public class CalendarRegression extends IntlTest { } t = calendar.getTime(); - calendar.set(Calendar.DAY_OF_MONTH, 33); + calendar.set(DAY_OF_MONTH, 33); t = calendar.getTime(); - calendar.set(Calendar.DAY_OF_MONTH, 0); + calendar.set(DAY_OF_MONTH, 0); s = df.format(calendar.getTime()); if (!expected.equals(s)) { errln("DAY_OF_MONTH w/o ZONE_OFFSET: expected: " + expected + ", got: " + s); @@ -1815,10 +1841,10 @@ public class CalendarRegression extends IntlTest { throw new RuntimeException("Unexpected parse exception", e); } t = calendar.getTime(); - calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); - calendar.set(Calendar.DAY_OF_MONTH, 33); + calendar.set(ZONE_OFFSET, calendar.get(ZONE_OFFSET)); + calendar.set(DAY_OF_MONTH, 33); t = calendar.getTime(); - calendar.set(Calendar.DAY_OF_MONTH, 0); + calendar.set(DAY_OF_MONTH, 0); s = df.format(calendar.getTime()); if (!expected.equals(s)) { errln("DAY_OF_MONTH: expected: " + expected + ", got: " + s); @@ -1834,11 +1860,11 @@ public class CalendarRegression extends IntlTest { throw new RuntimeException("Unexpected parse exception", e); } t = calendar.getTime(); - calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); + calendar.set(ZONE_OFFSET, calendar.get(ZONE_OFFSET)); // jump to the next year - calendar.set(Calendar.WEEK_OF_YEAR, 100); + calendar.set(WEEK_OF_YEAR, 100); t = calendar.getTime(); - calendar.set(Calendar.WEEK_OF_YEAR, 0); + calendar.set(WEEK_OF_YEAR, 0); s = df.format(calendar.getTime()); if (!expected.equals(s)) { errln("WEEK_OF_YEAR: expected: " + expected + ", got: " + s); @@ -1846,11 +1872,11 @@ public class CalendarRegression extends IntlTest { // change the state back calendar.clear(); calendar.setTime(initialDate); - calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); + calendar.set(ZONE_OFFSET, calendar.get(ZONE_OFFSET)); // jump to next month - calendar.set(Calendar.WEEK_OF_MONTH, 7); + calendar.set(WEEK_OF_MONTH, 7); t = calendar.getTime(); - calendar.set(Calendar.WEEK_OF_MONTH, 0); + calendar.set(WEEK_OF_MONTH, 0); s = df.format(calendar.getTime()); if (!expected.equals(s)) { errln("WEEK_OF_MONTH: expected: " + expected + ", got: " + s); @@ -1870,10 +1896,10 @@ public class CalendarRegression extends IntlTest { } t = calendar.getTime(); // time should be 22:59:59. - calendar.set(Calendar.MINUTE, 61); + calendar.set(MINUTE, 61); // time should be 23:01:59. t = calendar.getTime(); - calendar.set(Calendar.MINUTE, -1); + calendar.set(MINUTE, -1); // time should be back to 22:59:59. s = df.format(calendar.getTime()); if (!expected.equals(s)) { @@ -1896,15 +1922,15 @@ public class CalendarRegression extends IntlTest { Calendar cal = Calendar.getInstance(); cal.setTime(new Date(1029814211523L)); - cal.set(Calendar.YEAR, 2001); + cal.set(YEAR, 2001); Date t = cal.getTime(); - cal.set(Calendar.MONTH, Calendar.JANUARY); + cal.set(MONTH, JANUARY); t = cal.getTime(); - cal.set(Calendar.DAY_OF_MONTH, 8); + cal.set(DAY_OF_MONTH, 8); t = cal.getTime(); - cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + cal.set(DAY_OF_WEEK, MONDAY); DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); String expected = "2001/01/08"; String s = df.format(cal.getTime()); @@ -1923,9 +1949,9 @@ public class CalendarRegression extends IntlTest { */ public void Test4683492() { Calendar cal = new GregorianCalendar(2002, 3, 29, 10, 0, 0); - cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY); - cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1); - cal.set(Calendar.MONTH, 12); + cal.set(DAY_OF_WEEK, FRIDAY); + cal.set(DAY_OF_WEEK_IN_MONTH, -1); + cal.set(MONTH, 12); DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); String expected = "2003/01/31"; String s = df.format(cal.getTime()); @@ -1940,31 +1966,31 @@ public class CalendarRegression extends IntlTest { public void Test4080631() { Calendar cal = Calendar.getInstance(); int h1 = cal.hashCode(); - cal.add(cal.SECOND, +1); + cal.add(SECOND, +1); int h2 = cal.hashCode(); Calendar cal2 = (Calendar) cal.clone(); - cal.add(cal.MILLISECOND, +1); + cal.add(MILLISECOND, +1); int h3 = cal.hashCode(); - logln("hash code: h1="+h1+", h2="+h2+", h3="+h3); + logln("hash code: h1=" + h1 + ", h2=" + h2 + ", h3=" + h3); if (h1 == h2 || h1 == h3 || h2 == h3) { - errln("hash code is poor: hashCode="+h1); + errln("hash code is poor: hashCode=" + h1); } h2 = cal2.hashCode(); - cal.add(cal.MILLISECOND, -1); + cal.add(MILLISECOND, -1); int h4 = cal.hashCode(); - logln("hash code: h2="+h2+", h4="+h4); + logln("hash code: h2=" + h2 + ", h4=" + h4); if (cal.equals(cal2) && h2 != h4) { - errln("broken hash code: h2="+h2+", h4="+h4); + errln("broken hash code: h2=" + h2 + ", h4=" + h4); } int x = cal.getFirstDayOfWeek() + 3; - if (x > cal.SATURDAY) { + if (x > SATURDAY) { x -= 7; } cal.setFirstDayOfWeek(x); int h5 = cal.hashCode(); - logln("hash code: h4="+h4+", h5="+h5); + logln("hash code: h4=" + h4 + ", h5=" + h5); if (h4 == h5) { - errln("has code is poor with first day of week param: hashCode="+h4); + errln("has code is poor with first day of week param: hashCode=" + h4); } } @@ -1991,8 +2017,7 @@ public class CalendarRegression extends IntlTest { errln("Wrong BCE and/or CE values"); } } - */ - + */ /** * 4167995: GregorianCalendar.setGregorianChange() not to spec */ @@ -2000,42 +2025,42 @@ public class CalendarRegression extends IntlTest { Koyomi gc = new Koyomi(TimeZone.getTimeZone("GMT")); logln("Hybrid: min date"); gc.setTime(new Date(Long.MIN_VALUE)); - if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY) - || !gc.checkFieldValue(gc.ERA, gc.BC)) { + if (!gc.checkDate(292269055, DECEMBER, 2, SUNDAY) + || !gc.checkFieldValue(ERA, GregorianCalendar.BC)) { errln(gc.getMessage()); } logln("Hybrid: max date"); gc.setTime(new Date(Long.MAX_VALUE)); - if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY) - || !gc.checkFieldValue(gc.ERA, gc.AD)) { + if (!gc.checkDate(292278994, AUGUST, 17, SUNDAY) + || !gc.checkFieldValue(ERA, GregorianCalendar.AD)) { errln(gc.getMessage()); } gc.setGregorianChange(new Date(Long.MIN_VALUE)); logln("Gregorian: min date"); gc.setTime(new Date(Long.MIN_VALUE)); - if (!gc.checkDate(292275056, gc.MAY, 16, gc.SUNDAY) - || !gc.checkFieldValue(gc.ERA, gc.BC)) { + if (!gc.checkDate(292275056, MAY, 16, SUNDAY) + || !gc.checkFieldValue(ERA, GregorianCalendar.BC)) { errln(gc.getMessage()); } logln("Gregorian: max date"); gc.setTime(new Date(Long.MAX_VALUE)); - if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY) - || !gc.checkFieldValue(gc.ERA, gc.AD)) { + if (!gc.checkDate(292278994, AUGUST, 17, SUNDAY) + || !gc.checkFieldValue(ERA, GregorianCalendar.AD)) { errln(gc.getMessage()); } gc.setGregorianChange(new Date(Long.MAX_VALUE)); logln("Julian: min date"); gc.setTime(new Date(Long.MIN_VALUE)); - if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY) - || !gc.checkFieldValue(gc.ERA, gc.BC)) { + if (!gc.checkDate(292269055, DECEMBER, 2, SUNDAY) + || !gc.checkFieldValue(ERA, GregorianCalendar.BC)) { errln(gc.getMessage()); } logln("Julian: max date"); gc.setTime(new Date(Long.MAX_VALUE)); - if (!gc.checkDate(292272993, gc.JANUARY, 4, gc.SUNDAY) - || !gc.checkFieldValue(gc.ERA, gc.AD)) { + if (!gc.checkDate(292272993, JANUARY, 4, SUNDAY) + || !gc.checkFieldValue(ERA, GregorianCalendar.AD)) { errln(gc.getMessage()); } } @@ -2046,13 +2071,13 @@ public class CalendarRegression extends IntlTest { public void Test4340146() { Koyomi cal = new Koyomi(); cal.clear(); - cal.set(2003, cal.OCTOBER, 32); + cal.set(2003, OCTOBER, 32); cal.equals(new Koyomi()); - if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) { + if (!cal.checkInternalDate(2003, OCTOBER, 32)) { errln(cal.getMessage()); } new Koyomi().equals(cal); - if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) { + if (!cal.checkInternalDate(2003, OCTOBER, 32)) { errln(cal.getMessage()); } } @@ -2065,10 +2090,10 @@ public class CalendarRegression extends IntlTest { // throw IllegalArgumentException. Koyomi cal = new Koyomi(TimeZone.getTimeZone("Pacific/Kiritimati")); cal.setLenient(false); - cal.set(2003, cal.OCTOBER, 10); + cal.set(2003, OCTOBER, 10); cal.getTime(); cal.setTimeZone(TimeZone.getTimeZone("Pacific/Tongatapu")); - cal.set(2003, cal.OCTOBER, 10); + cal.set(2003, OCTOBER, 10); cal.getTime(); } @@ -2077,10 +2102,10 @@ public class CalendarRegression extends IntlTest { */ public void Test4652815() { Koyomi cal = new Koyomi(Locale.US); - testRoll(cal, 2003, cal.SEPTEMBER, 29); - testRoll(cal, 2003, cal.DECEMBER, 24); - testRoll(cal, 1582, cal.DECEMBER, 19); - testRoll(cal, 1582, cal.DECEMBER, 20); + testRoll(cal, 2003, SEPTEMBER, 29); + testRoll(cal, 2003, DECEMBER, 24); + testRoll(cal, 1582, DECEMBER, 19); + testRoll(cal, 1582, DECEMBER, 20); } private void testRoll(Koyomi cal, int year, int month, int dayOfMonth) { @@ -2089,15 +2114,15 @@ public class CalendarRegression extends IntlTest { cal.getTime(); // normalize fields logln("Roll backwards from " + cal.toDateString()); for (int i = 0; i < 1000; i++) { - cal.roll(cal.WEEK_OF_YEAR, -i); - if (!cal.checkFieldValue(cal.YEAR, year)) { + cal.roll(WEEK_OF_YEAR, -i); + if (!cal.checkFieldValue(YEAR, year)) { errln(cal.getMessage()); } } logln("Roll forewards from " + cal.toDateString()); for (int i = 0; i < 1000; i++) { - cal.roll(cal.WEEK_OF_YEAR, +i); - if (!cal.checkFieldValue(cal.YEAR, year)) { + cal.roll(WEEK_OF_YEAR, +i); + if (!cal.checkFieldValue(YEAR, year)) { errln(cal.getMessage()); } } @@ -2110,20 +2135,20 @@ public class CalendarRegression extends IntlTest { Koyomi cal = new Koyomi(Locale.US); cal.clear(); logln("BCE 9-2-28 (leap year) roll DAY_OF_MONTH++ twice"); - cal.set(cal.ERA, cal.BC); - cal.set(9, cal.FEBRUARY, 28); - if (cal.getActualMaximum(cal.DAY_OF_YEAR) != 366) { + cal.set(ERA, GregorianCalendar.BC); + cal.set(9, FEBRUARY, 28); + if (cal.getActualMaximum(DAY_OF_YEAR) != 366) { errln(" wrong actual max of DAY_OF_YEAR: got " - + cal.getActualMaximum(cal.DAY_OF_YEAR) + " expected " + 366); + + cal.getActualMaximum(DAY_OF_YEAR) + " expected " + 366); } - cal.roll(cal.DAY_OF_MONTH, +1); - if (!cal.checkFieldValue(cal.ERA, cal.BC) - || !cal.checkDate(9, cal.FEBRUARY, 29)) { + cal.roll(DAY_OF_MONTH, +1); + if (!cal.checkFieldValue(ERA, GregorianCalendar.BC) + || !cal.checkDate(9, FEBRUARY, 29)) { errln(cal.getMessage()); } - cal.roll(cal.DAY_OF_MONTH, +1); - if (!cal.checkFieldValue(cal.ERA, cal.BC) - || !cal.checkDate(9, cal.FEBRUARY, 1)) { + cal.roll(DAY_OF_MONTH, +1); + if (!cal.checkFieldValue(ERA, GregorianCalendar.BC) + || !cal.checkDate(9, FEBRUARY, 1)) { errln(cal.getMessage()); } } @@ -2135,11 +2160,11 @@ public class CalendarRegression extends IntlTest { logln("1999/(Feb+12)/1 should be normalized to 2000/Feb/1 for getActualMaximum"); Koyomi cal = new Koyomi(Locale.US); cal.clear(); - cal.set(1999, cal.FEBRUARY + 12, 1); - if (!cal.checkActualMaximum(cal.DAY_OF_YEAR, 366)) { + cal.set(1999, FEBRUARY + 12, 1); + if (!cal.checkActualMaximum(DAY_OF_YEAR, 366)) { errln(cal.getMessage()); } - if (!cal.checkActualMaximum(cal.DAY_OF_MONTH, 29)) { + if (!cal.checkActualMaximum(DAY_OF_MONTH, 29)) { errln(cal.getMessage()); } } @@ -2150,36 +2175,36 @@ public class CalendarRegression extends IntlTest { public void Test4936355() { Koyomi cal = new Koyomi(TimeZone.getTimeZone("GMT")); cal.clear(); - cal.set(1970, cal.JANUARY, 1); - checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MAX_VALUE, - (long)Integer.MAX_VALUE * 60 * 60 * 1000); + cal.set(1970, JANUARY, 1); + checkTimeCalculation(cal, HOUR_OF_DAY, Integer.MAX_VALUE, + (long) Integer.MAX_VALUE * 60 * 60 * 1000); cal.clear(); - cal.set(1970, cal.JANUARY, 1); - checkTimeCalculation(cal, cal.HOUR, Integer.MAX_VALUE, - (long)Integer.MAX_VALUE * 60 * 60 * 1000); + cal.set(1970, JANUARY, 1); + checkTimeCalculation(cal, HOUR, Integer.MAX_VALUE, + (long) Integer.MAX_VALUE * 60 * 60 * 1000); cal.clear(); - cal.set(1970, cal.JANUARY, 1); - checkTimeCalculation(cal, cal.MINUTE, Integer.MAX_VALUE, - (long)Integer.MAX_VALUE * 60 * 1000); + cal.set(1970, JANUARY, 1); + checkTimeCalculation(cal, MINUTE, Integer.MAX_VALUE, + (long) Integer.MAX_VALUE * 60 * 1000); cal.clear(); // Make sure to use Gregorian dates (before and after the // set() call) for testing - cal.set(250000, cal.JANUARY, 1); - checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MIN_VALUE, - (long)Integer.MIN_VALUE * 60 * 60 * 1000); + cal.set(250000, JANUARY, 1); + checkTimeCalculation(cal, HOUR_OF_DAY, Integer.MIN_VALUE, + (long) Integer.MIN_VALUE * 60 * 60 * 1000); cal.clear(); - cal.set(250000, cal.JANUARY, 1); - checkTimeCalculation(cal, cal.HOUR, Integer.MIN_VALUE, - (long)Integer.MIN_VALUE * 60 * 60 * 1000); + cal.set(250000, JANUARY, 1); + checkTimeCalculation(cal, HOUR, Integer.MIN_VALUE, + (long) Integer.MIN_VALUE * 60 * 60 * 1000); cal.clear(); - cal.set(250000, cal.JANUARY, 1); - checkTimeCalculation(cal, cal.MINUTE, Integer.MIN_VALUE, - (long)Integer.MIN_VALUE * 60 * 1000); + cal.set(250000, JANUARY, 1); + checkTimeCalculation(cal, MINUTE, Integer.MIN_VALUE, + (long) Integer.MIN_VALUE * 60 * 1000); } private void checkTimeCalculation(Koyomi cal, int field, int value, long expectedDelta) { @@ -2189,7 +2214,7 @@ public class CalendarRegression extends IntlTest { if ((time + expectedDelta) != time2) { String s = value == Integer.MAX_VALUE ? "Integer.MAX_VALUE" : "Integer.MIN_VALUE"; errln("set(" + Koyomi.getFieldName(field) + ", " + s + ") failed." + " got " + time2 - + ", expected " + (time+expectedDelta)); + + ", expected " + (time + expectedDelta)); } } @@ -2204,8 +2229,8 @@ public class CalendarRegression extends IntlTest { cal2.clear(); cal2.setLenient(false); - cal1.set(2003, Calendar.OCTOBER, 31); - cal2.set(2003, Calendar.OCTOBER, 31); + cal1.set(2003, OCTOBER, 31); + cal2.set(2003, OCTOBER, 31); try { if (cal1.equals(cal2)) { errln("lenient and non-lenient shouldn't be equal. (2003/10/31)"); @@ -2217,8 +2242,8 @@ public class CalendarRegression extends IntlTest { errln("equals threw IllegalArugumentException with non-lenient"); } - cal1.set(2003, Calendar.OCTOBER, 32); - cal2.set(2003, Calendar.OCTOBER, 32); + cal1.set(2003, OCTOBER, 32); + cal2.set(2003, OCTOBER, 32); try { if (cal1.equals(cal2)) { errln("lenient and non-lenient shouldn't be equal. (2003/10/32)"); @@ -2246,17 +2271,17 @@ public class CalendarRegression extends IntlTest { * 4738710: API: Calendar comparison methods should be improved */ public void Test4738710() { - Calendar cal0 = new GregorianCalendar(2003, Calendar.SEPTEMBER, 30); - Comparable cal1 = new GregorianCalendar(2003, Calendar.OCTOBER, 1); - Calendar cal2 = new GregorianCalendar(2003, Calendar.OCTOBER, 2); + Calendar cal0 = new GregorianCalendar(2003, SEPTEMBER, 30); + Comparable cal1 = new GregorianCalendar(2003, OCTOBER, 1); + Calendar cal2 = new GregorianCalendar(2003, OCTOBER, 2); if (!(cal1.compareTo(cal0) > 0)) { errln("!(cal1 > cal0)"); } if (!(cal1.compareTo(cal2) < 0)) { errln("!(cal1 < cal2)"); } - if (cal1.compareTo(new GregorianCalendar(2003, Calendar.OCTOBER, 1)) != 0) { - errln("cal1 != new GregorianCalendar(2003, Calendar.OCTOBER, 1)"); + if (cal1.compareTo(new GregorianCalendar(2003, OCTOBER, 1)) != 0) { + errln("cal1 != new GregorianCalendar(2003, OCTOBER, 1)"); } if (cal0.after(cal2)) { @@ -2266,10 +2291,10 @@ public class CalendarRegression extends IntlTest { errln("cal2 shouldn't be before cal0"); } - if (cal0.after(new Integer(0))) { + if (cal0.after(0)) { errln("cal0.after() returned true with an Integer."); } - if (cal0.before(new Integer(0))) { + if (cal0.before(0)) { errln("cal0.before() returned true with an Integer."); } if (cal0.after(null)) { @@ -2283,34 +2308,35 @@ public class CalendarRegression extends IntlTest { /** * 4633646: Setting WEEK_OF_MONTH to 1 results in incorrect date */ + @SuppressWarnings("deprecation") public void Test4633646() { Koyomi cal = new Koyomi(Locale.US); - cal.setTime(new Date(2002-1900, 1-1, 28)); + cal.setTime(new Date(2002 - 1900, 1 - 1, 28)); sub4633646(cal); cal.setLenient(false); - cal.setTime(new Date(2002-1900, 1-1, 28)); + cal.setTime(new Date(2002 - 1900, 1 - 1, 28)); sub4633646(cal); cal = new Koyomi(Locale.US); cal.clear(); - cal.set(2002, cal.JANUARY, 28); + cal.set(2002, JANUARY, 28); sub4633646(cal); cal.clear(); cal.setLenient(false); - cal.set(2002, cal.JANUARY, 28); + cal.set(2002, JANUARY, 28); sub4633646(cal); } void sub4633646(Koyomi cal) { cal.getTime(); - cal.set(cal.WEEK_OF_MONTH, 1); + cal.set(WEEK_OF_MONTH, 1); if (cal.isLenient()) { - if (!cal.checkDate(2001, cal.DECEMBER, 31)) { + if (!cal.checkDate(2001, DECEMBER, 31)) { errln(cal.getMessage()); } - if (!cal.checkFieldValue(cal.WEEK_OF_MONTH, 6)) { + if (!cal.checkFieldValue(WEEK_OF_MONTH, 6)) { errln(cal.getMessage()); } } else { @@ -2329,29 +2355,29 @@ public class CalendarRegression extends IntlTest { public void Test4846659() { Koyomi cal = new Koyomi(); cal.clear(); - cal.set(2003, cal.OCTOBER, 31, 10, 30, 30); + cal.set(2003, OCTOBER, 31, 10, 30, 30); cal.getTime(); // Test roll() - cal.roll(cal.AM_PM, +1); // should turn to PM - if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) { + cal.roll(AM_PM, +1); // should turn to PM + if (!cal.checkFieldValue(HOUR_OF_DAY, 10 + 12)) { errln("roll: AM_PM didn't change to PM"); } cal.clear(); - cal.set(2003, cal.OCTOBER, 31, 10, 30, 30); + cal.set(2003, OCTOBER, 31, 10, 30, 30); cal.getTime(); // Test set() - cal.set(cal.AM_PM, cal.PM); // should turn to PM - if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) { + cal.set(AM_PM, PM); // should turn to PM + if (!cal.checkFieldValue(HOUR_OF_DAY, 10 + 12)) { errln("set: AM_PM didn't change to PM"); } cal.clear(); - cal.set(2003, cal.OCTOBER, 31, 10, 30, 30); + cal.set(2003, OCTOBER, 31, 10, 30, 30); cal.getTime(); - cal.set(cal.AM_PM, cal.PM); - cal.set(cal.HOUR, 9); - if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 9+12)) { + cal.set(AM_PM, PM); + cal.set(HOUR, 9); + if (!cal.checkFieldValue(HOUR_OF_DAY, 9 + 12)) { errln("set: both AM_PM and HOUT didn't change to PM"); } } @@ -2370,15 +2396,15 @@ public class CalendarRegression extends IntlTest { // 29 30 cal.clear(); // 6/1 to 6/7 should be the 1st week of June. - cal.set(2003, cal.JUNE, 2); + cal.set(2003, JUNE, 2); cal.getTime(); // Let cal calculate time. - cal.setFirstDayOfWeek(cal.MONDAY); + cal.setFirstDayOfWeek(MONDAY); // Now 6/2 to 6/8 should be the 2nd week of June. Sunday of // that week is 6/8. - logln("1: " +cal.get(cal.WEEK_OF_MONTH)+", "+cal.get(cal.DAY_OF_MONTH)); - cal.set(cal.DAY_OF_WEEK, cal.SUNDAY); + logln("1: " + cal.get(WEEK_OF_MONTH) + ", " + cal.get(DAY_OF_MONTH)); + cal.set(DAY_OF_WEEK, SUNDAY); logln("1st Sunday of June 2003 with FirstDayOfWeek=MONDAY"); - if (!cal.checkDate(2003, cal.JUNE, 8)) { + if (!cal.checkDate(2003, JUNE, 8)) { errln(cal.getMessage()); } } @@ -2387,7 +2413,7 @@ public class CalendarRegression extends IntlTest { * 4973919: Inconsistent GregorianCalendar hashCode before and after serialization */ public void Test4966499() throws Exception { - GregorianCalendar date1 = new GregorianCalendar(2004, Calendar.JANUARY, 7); + GregorianCalendar date1 = new GregorianCalendar(2004, JANUARY, 7); // Serialize date1 ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -2399,15 +2425,15 @@ public class CalendarRegression extends IntlTest { // Deserialize it ByteArrayInputStream bais = new ByteArrayInputStream(buffer); ObjectInputStream ois = new ObjectInputStream(bais); - GregorianCalendar date2 = (GregorianCalendar)ois.readObject(); + GregorianCalendar date2 = (GregorianCalendar) ois.readObject(); if (!date1.equals(date2)) { errln("date1.equals(date2) != true"); } if (date1.hashCode() != date2.hashCode()) { errln("inconsistent hashCode() value (before=0x" - +Integer.toHexString(date1.hashCode())+ - ", after=0x"+Integer.toHexString(date2.hashCode())+")"); + + Integer.toHexString(date1.hashCode()) + + ", after=0x" + Integer.toHexString(date2.hashCode()) + ")"); } } @@ -2468,29 +2494,26 @@ public class CalendarRegression extends IntlTest { TimeZone savedZone = TimeZone.getDefault(); TimeZone.setDefault(TimeZone.getTimeZone("GMT")); try { - Map data = new HashMap(); - data.put(getGregorianDate(999, Calendar.OCTOBER, 1), Boolean.FALSE); - data.put(getGregorianDate(1000, Calendar.JANUARY, 1), Boolean.FALSE); - data.put(getGregorianDate(1000, Calendar.FEBRUARY, 1), Boolean.FALSE); - data.put(getGregorianDate(1000, Calendar.FEBRUARY, 28), Boolean.FALSE); - data.put(getGregorianDate(1000, Calendar.MARCH, 1), Boolean.TRUE); - data.put(getGregorianDate(1001, Calendar.JANUARY, 1), Boolean.TRUE); - data.put(getGregorianDate(1001, Calendar.JANUARY, 6), Boolean.TRUE); - data.put(getGregorianDate(1001, Calendar.MARCH, 1), Boolean.TRUE); + Map data = new HashMap<>(); + data.put(getGregorianDate(999, OCTOBER, 1), Boolean.FALSE); + data.put(getGregorianDate(1000, JANUARY, 1), Boolean.FALSE); + data.put(getGregorianDate(1000, FEBRUARY, 1), Boolean.FALSE); + data.put(getGregorianDate(1000, FEBRUARY, 28), Boolean.FALSE); + data.put(getGregorianDate(1000, MARCH, 1), Boolean.TRUE); + data.put(getGregorianDate(1001, JANUARY, 1), Boolean.TRUE); + data.put(getGregorianDate(1001, JANUARY, 6), Boolean.TRUE); + data.put(getGregorianDate(1001, MARCH, 1), Boolean.TRUE); - Iterator itr = data.keySet().iterator(); - while (itr.hasNext()) { - Date d = itr.next(); - boolean expected = data.get(d).booleanValue(); + data.keySet().forEach(d -> { + boolean expected = data.get(d); GregorianCalendar cal = new GregorianCalendar(); cal.setGregorianChange(d); if (cal.isLeapYear(1000) != expected) { - errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) + - " with cutover date (Julian) " + d); + errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) + + " with cutover date (Julian) " + d); } - } - } - finally { + }); + } finally { TimeZone.setDefault(savedZone); } } @@ -2511,15 +2534,15 @@ public class CalendarRegression extends IntlTest { */ public void Test5006864() { GregorianCalendar cal = new GregorianCalendar(); - int min = cal.getMinimum(cal.DAY_OF_WEEK_IN_MONTH); + int min = cal.getMinimum(DAY_OF_WEEK_IN_MONTH); if (min != 1) { errln("GregorianCalendar.getMinimum(DAY_OF_WEEK_IN_MONTH) returned " - + min + ", expected 1."); + + min + ", expected 1."); } - min = cal.getGreatestMinimum(cal.DAY_OF_WEEK_IN_MONTH); + min = cal.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH); if (min != 1) { errln("GregorianCalendar.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH) returned " - + min + ", expected 1."); + + min + ", expected 1."); } } } diff --git a/jdk/test/java/util/Calendar/CalendarTest.java b/jdk/test/java/util/Calendar/CalendarTest.java index b04bb03a1fc..d9ce67196af 100644 --- a/jdk/test/java/util/Calendar/CalendarTest.java +++ b/jdk/test/java/util/Calendar/CalendarTest.java @@ -30,12 +30,25 @@ * @key randomness */ -import java.util.*; -import java.text.*; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.SimpleTimeZone; +import java.util.TimeZone; + +import static java.util.Calendar.*; public class CalendarTest extends IntlTest { - static final int ONE_DAY = 24*60*60*1000; + + static final int ONE_DAY = 24 * 60 * 60 * 1000; static final int EPOCH_JULIAN = 2440588; public static void main(String argv[]) throws Exception { @@ -64,32 +77,31 @@ public class CalendarTest extends IntlTest { Changeover +6 days: 1582/10/21 dow=5 Changeover +7 days: 1582/10/22 dow=6 */ - int MON[] = { 9, 9, 9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 }; - int DOM[] = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 }; - int DOW[] = { 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6 }; + int[] MON = { 9, 9, 9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 }; + int[] DOM = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 }; + int[] DOW = { 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6 }; // ^ <-Changeover Fri Oct 15 1582 - try { TimeZone.setDefault(TimeZone.getTimeZone("GMT")); - Date co = new Date(1582-1900, Calendar.OCTOBER, 15); + @SuppressWarnings("deprecation") + Date co = new Date(1582 - 1900, OCTOBER, 15); GregorianCalendar cal = new GregorianCalendar(); int j = 0; for (int i = -7; i <= 7; ++i, ++j) { - Date d = new Date(co.getTime() + i*ONE_DAY); + Date d = new Date(co.getTime() + i * ONE_DAY); cal.setTime(d); - int y = cal.get(Calendar.YEAR); - int mon = cal.get(Calendar.MONTH)+1-Calendar.JANUARY; - int dom = cal.get(Calendar.DATE); - int dow = cal.get(Calendar.DAY_OF_WEEK); + int y = cal.get(YEAR); + int mon = cal.get(MONTH) + 1 - JANUARY; + int dom = cal.get(DATE); + int dow = cal.get(DAY_OF_WEEK); - logln("Changeover " + (i>=0?"+":"") + i + - " days: " + y + "/" + mon + "/" + dom + " dow=" + dow); + logln("Changeover " + (i >= 0 ? "+" : "") + i + + " days: " + y + "/" + mon + "/" + dom + " dow=" + dow); if (y != 1582 || mon != MON[j] || dom != DOM[j] || dow != DOW[j]) { errln(" Fail: Above line is wrong"); } } - } - finally { + } finally { TimeZone.setDefault(savedZone); } } @@ -99,22 +111,22 @@ public class CalendarTest extends IntlTest { * of this test, we don't care about timezones and week data * (first day of week, minimal days in first week). */ + @SuppressWarnings("deprecation") public void TestMapping() { TimeZone saveZone = TimeZone.getDefault(); int[] DATA = { - // Julian# Year Month DOM JULIAN:Year, Month, DOM - 2440588, 1970, Calendar.JANUARY, 1, 1969, Calendar.DECEMBER, 19, - 2415080, 1900, Calendar.MARCH, 1, 1900, Calendar.FEBRUARY, 17, - 2451604, 2000, Calendar.FEBRUARY, 29, 2000, Calendar.FEBRUARY, 16, - 2452269, 2001, Calendar.DECEMBER, 25, 2001, Calendar.DECEMBER, 12, - 2416526, 1904, Calendar.FEBRUARY, 15, 1904, Calendar.FEBRUARY, 2, - 2416656, 1904, Calendar.JUNE, 24, 1904, Calendar.JUNE, 11, - 1721426, 1, Calendar.JANUARY, 1, 1, Calendar.JANUARY, 3, - 2000000, 763, Calendar.SEPTEMBER, 18, 763, Calendar.SEPTEMBER, 14, - 4000000, 6239, Calendar.JULY, 12, 6239, Calendar.MAY, 28, - 8000000, 17191, Calendar.FEBRUARY, 26, 17190, Calendar.OCTOBER, 22, - 10000000, 22666, Calendar.DECEMBER, 20, 22666, Calendar.JULY, 5, - }; + // Julian# Year Month DOM JULIAN:Year Month, DOM + 2440588, 1970, JANUARY, 1, 1969, DECEMBER, 19, + 2415080, 1900, MARCH, 1, 1900, FEBRUARY, 17, + 2451604, 2000, FEBRUARY, 29, 2000, FEBRUARY, 16, + 2452269, 2001, DECEMBER, 25, 2001, DECEMBER, 12, + 2416526, 1904, FEBRUARY, 15, 1904, FEBRUARY, 2, + 2416656, 1904, JUNE, 24, 1904, JUNE, 11, + 1721426, 1, JANUARY, 1, 1, JANUARY, 3, + 2000000, 763, SEPTEMBER, 18, 763, SEPTEMBER, 14, + 4000000, 6239, JULY, 12, 6239, MAY, 28, + 8000000, 17191, FEBRUARY, 26, 17190, OCTOBER, 22, + 10000000, 22666, DECEMBER, 20, 22666, JULY, 5}; try { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); @@ -123,11 +135,11 @@ public class CalendarTest extends IntlTest { GregorianCalendar cal = new GregorianCalendar(); for (int i = 0; i < DATA.length; i += 7) { int julian = DATA[i]; - int year = DATA[i+1]; - int month = DATA[i+2]; - int dom = DATA[i+3]; + int year = DATA[i + 1]; + int month = DATA[i + 2]; + int dom = DATA[i + 3]; int year2, month2, dom2; - long millis = ((long)julian - EPOCH_JULIAN) * ONE_DAY; + long millis = ((long) julian - EPOCH_JULIAN) * ONE_DAY; String s; // Test Gregorian computation @@ -137,56 +149,55 @@ public class CalendarTest extends IntlTest { long calMillis = cal.getTime().getTime(); long delta = calMillis - millis; cal.setTime(new Date(millis)); - year2 = cal.get(Calendar.YEAR); - month2 = cal.get(Calendar.MONTH); - dom2 = cal.get(Calendar.DAY_OF_MONTH); - s = "G " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom + - " => " + calMillis + - " (" + ((float)delta/ONE_DAY) + " day delta) => " + - year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2; - if (delta != 0 || year != year2 || month != month2 || - dom != dom2) { + year2 = cal.get(YEAR); + month2 = cal.get(MONTH); + dom2 = cal.get(DAY_OF_MONTH); + s = "G " + year + "-" + (month + 1 - JANUARY) + "-" + dom + + " => " + calMillis + + " (" + ((float) delta / ONE_DAY) + " day delta) => " + + year2 + "-" + (month2 + 1 - JANUARY) + "-" + dom2; + if (delta != 0 || year != year2 || month != month2 + || dom != dom2) { errln(s + " FAIL"); } else { logln(s); } // Test Julian computation - year = DATA[i+4]; - month = DATA[i+5]; - dom = DATA[i+6]; + year = DATA[i + 4]; + month = DATA[i + 5]; + dom = DATA[i + 6]; cal.setGregorianChange(PURE_JULIAN); cal.clear(); cal.set(year, month, dom); calMillis = cal.getTime().getTime(); delta = calMillis - millis; cal.setTime(new Date(millis)); - year2 = cal.get(Calendar.YEAR); - month2 = cal.get(Calendar.MONTH); - dom2 = cal.get(Calendar.DAY_OF_MONTH); - s = "J " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom + - " => " + calMillis + - " (" + ((float)delta/ONE_DAY) + " day delta) => " + - year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2; - if (delta != 0 || year != year2 || month != month2 || - dom != dom2) { + year2 = cal.get(YEAR); + month2 = cal.get(MONTH); + dom2 = cal.get(DAY_OF_MONTH); + s = "J " + year + "-" + (month + 1 - JANUARY) + "-" + dom + + " => " + calMillis + + " (" + ((float) delta / ONE_DAY) + " day delta) => " + + year2 + "-" + (month2 + 1 - JANUARY) + "-" + dom2; + if (delta != 0 || year != year2 || month != month2 + || dom != dom2) { errln(s + " FAIL"); } else { logln(s); } } - cal.setGregorianChange(new Date(1582-1900, Calendar.OCTOBER, 15)); - auxMapping(cal, 1582, Calendar.OCTOBER, 4); - auxMapping(cal, 1582, Calendar.OCTOBER, 15); - auxMapping(cal, 1582, Calendar.OCTOBER, 16); - for (int y = 800; y < 3000; y += 1+(int)100*Math.random()) { - for (int m = Calendar.JANUARY; m <= Calendar.DECEMBER; ++m) { + cal.setGregorianChange(new Date(1582 - 1900, OCTOBER, 15)); + auxMapping(cal, 1582, OCTOBER, 4); + auxMapping(cal, 1582, OCTOBER, 15); + auxMapping(cal, 1582, OCTOBER, 16); + for (int y = 800; y < 3000; y += 1 + 100 * Math.random()) { + for (int m = JANUARY; m <= DECEMBER; ++m) { auxMapping(cal, y, m, 15); } } - } - finally { + } finally { TimeZone.setDefault(saveZone); } } @@ -195,14 +206,16 @@ public class CalendarTest extends IntlTest { cal.set(y, m, d); long millis = cal.getTime().getTime(); cal.setTime(new Date(millis)); - int year2 = cal.get(Calendar.YEAR); - int month2 = cal.get(Calendar.MONTH); - int dom2 = cal.get(Calendar.DAY_OF_MONTH); - if (y != year2 || m != month2 || dom2 != d) - errln("Round-trip failure: " + y + "-" + (m+1) + "-"+d+" =>ms=> " + - year2 + "-" + (month2+1) + "-" + dom2); + int year2 = cal.get(YEAR); + int month2 = cal.get(MONTH); + int dom2 = cal.get(DAY_OF_MONTH); + if (y != year2 || m != month2 || dom2 != d) { + errln("Round-trip failure: " + y + "-" + (m + 1) + "-" + d + " =>ms=> " + + year2 + "-" + (month2 + 1) + "-" + dom2); + } } + @SuppressWarnings("deprecation") public void TestGenericAPI() { Locale locale = Locale.getDefault(); if (!TestUtils.usesGregorianCalendar(locale)) { @@ -211,76 +224,95 @@ public class CalendarTest extends IntlTest { } String str; - - Date when = new Date(90, Calendar.APRIL, 15); + Date when = new Date(90, APRIL, 15); String tzid = "TestZone"; int tzoffset = 123400; SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid); - Calendar cal = (Calendar)Calendar.getInstance((SimpleTimeZone)zone.clone()); + Calendar cal = Calendar.getInstance((SimpleTimeZone) zone.clone()); - if (!zone.equals(cal.getTimeZone())) errln("FAIL: Calendar.getTimeZone failed"); + if (!zone.equals(cal.getTimeZone())) { + errln("FAIL: Calendar.getTimeZone failed"); + } Calendar cal2 = Calendar.getInstance(cal.getTimeZone()); cal.setTime(when); cal2.setTime(when); - if (!(cal.equals(cal2))) errln("FAIL: Calendar.operator== failed"); + if (!(cal.equals(cal2))) { + errln("FAIL: Calendar.operator== failed"); + } // if ((*cal != *cal2)) errln("FAIL: Calendar.operator!= failed"); - if (!cal.equals(cal2) || - cal.before(cal2) || - cal.after(cal2)) errln("FAIL: equals/before/after failed"); + if (!cal.equals(cal2) + || cal.before(cal2) + || cal.after(cal2)) { + errln("FAIL: equals/before/after failed"); + } cal2.setTime(new Date(when.getTime() + 1000)); - if (cal.equals(cal2) || - cal2.before(cal) || - cal.after(cal2)) errln("FAIL: equals/before/after failed"); + if (cal.equals(cal2) + || cal2.before(cal) + || cal.after(cal2)) { + errln("FAIL: equals/before/after failed"); + } - cal.roll(Calendar.SECOND, true); - if (!cal.equals(cal2) || - cal.before(cal2) || - cal.after(cal2)) errln("FAIL: equals/before/after failed"); + cal.roll(SECOND, true); + if (!cal.equals(cal2) + || cal.before(cal2) + || cal.after(cal2)) { + errln("FAIL: equals/before/after failed"); + } // Roll back to January - cal.roll(Calendar.MONTH, (int)(1 + Calendar.DECEMBER - cal.get(Calendar.MONTH))); - if (cal.equals(cal2) || - cal2.before(cal) || - cal.after(cal2)) errln("FAIL: equals/before/after failed"); + cal.roll(MONTH, 1 + DECEMBER - cal.get(MONTH)); + if (cal.equals(cal2) + || cal2.before(cal) + || cal.after(cal2)) { + errln("FAIL: equals/before/after failed"); + } // C++ only /* TimeZone z = cal.orphanTimeZone(); - if (z.getID(str) != tzid || - z.getRawOffset() != tzoffset) - errln("FAIL: orphanTimeZone failed"); - */ - + if (z.getID(str) != tzid || + z.getRawOffset() != tzoffset) + errln("FAIL: orphanTimeZone failed"); + */ for (int i = 0; i < 2; ++i) { - boolean lenient = ( i > 0 ); + boolean lenient = (i > 0); cal.setLenient(lenient); - if (lenient != cal.isLenient()) errln("FAIL: setLenient/isLenient failed"); + if (lenient != cal.isLenient()) { + errln("FAIL: setLenient/isLenient failed"); + } // Later: Check for lenient behavior } int i; - for (i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) { + for (i = SUNDAY; i <= SATURDAY; ++i) { cal.setFirstDayOfWeek(i); - if (cal.getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed"); + if (cal.getFirstDayOfWeek() != i) { + errln("FAIL: set/getFirstDayOfWeek failed"); + } } for (i = 0; i <= 7; ++i) { cal.setMinimalDaysInFirstWeek(i); - if (cal.getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed"); + if (cal.getMinimalDaysInFirstWeek() != i) { + errln("FAIL: set/getFirstDayOfWeek failed"); + } } - for (i = 0; i < Calendar.FIELD_COUNT; ++i) { - if (cal.getMinimum(i) != cal.getGreatestMinimum(i)) + for (i = 0; i < FIELD_COUNT; ++i) { + if (cal.getMinimum(i) != cal.getGreatestMinimum(i)) { errln("FAIL: getMinimum doesn't match getGreatestMinimum for field " + i); - if (cal.getLeastMaximum(i) > cal.getMaximum(i)) + } + if (cal.getLeastMaximum(i) > cal.getMaximum(i)) { errln("FAIL: getLeastMaximum larger than getMaximum for field " + i); - if (cal.getMinimum(i) >= cal.getMaximum(i)) + } + if (cal.getMinimum(i) >= cal.getMaximum(i)) { errln("FAIL: getMinimum not less than getMaximum for field " + i); + } } cal.setTimeZone(TimeZone.getDefault()); @@ -306,30 +338,36 @@ public class CalendarTest extends IntlTest { } cal.getTime(); - for (i = 0; i < Calendar.FIELD_COUNT; ++i) { - switch(i) { - case Calendar.YEAR: case Calendar.MONTH: case Calendar.DATE: - case Calendar.HOUR_OF_DAY: case Calendar.MINUTE: case Calendar.SECOND: - if (!cal.isSet(i)) - errln("FAIL: !Calendar.isSet test failed: " + calendarFieldNames[i]); - break; - default: - if (cal.isSet(i)) - errln("FAIL: Calendar.isSet test failed: " + calendarFieldNames[i]); + for (i = 0; i < FIELD_COUNT; ++i) { + switch (i) { + case YEAR: + case MONTH: + case DATE: + case HOUR_OF_DAY: + case MINUTE: + case SECOND: + if (!cal.isSet(i)) { + errln("FAIL: !Calendar.isSet test failed: " + calendarFieldNames[i]); + } + break; + default: + if (cal.isSet(i)) { + errln("FAIL: Calendar.isSet test failed: " + calendarFieldNames[i]); + } } cal.clear(i); - if (cal.isSet(i)) errln("FAIL: Calendar.clear/isSet failed"); + if (cal.isSet(i)) { + errln("FAIL: Calendar.clear/isSet failed"); + } } // delete cal; // delete cal2; - Locale[] loc = Calendar.getAvailableLocales(); long count = loc.length; if (count < 1 || loc == null) { errln("FAIL: getAvailableLocales failed"); - } - else { + } else { for (i = 0; i < count; ++i) { cal = Calendar.getInstance(loc[i]); // delete cal; @@ -358,13 +396,15 @@ public class CalendarTest extends IntlTest { // delete gc; gc = new GregorianCalendar(1998, 10, 14, 21, 43); - if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43).getTime()) + if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43).getTime()) { errln("FAIL: new GregorianCalendar(ymdhm) failed"); + } // delete gc; gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55); - if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43, 55).getTime()) + if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43, 55).getTime()) { errln("FAIL: new GregorianCalendar(ymdhms) failed"); + } // C++ only: // GregorianCalendar gc2 = new GregorianCalendar(Locale.ENGLISH); @@ -378,19 +418,20 @@ public class CalendarTest extends IntlTest { public void TestRog() { GregorianCalendar gc = new GregorianCalendar(); - int year = 1997, month = Calendar.APRIL, date = 1; + int year = 1997, month = APRIL, date = 1; gc.set(year, month, date); // April 1, 1997 - gc.set(Calendar.HOUR_OF_DAY, 23); - gc.set(Calendar.MINUTE, 0); - gc.set(Calendar.SECOND, 0); - gc.set(Calendar.MILLISECOND, 0); + gc.set(HOUR_OF_DAY, 23); + gc.set(MINUTE, 0); + gc.set(SECOND, 0); + gc.set(MILLISECOND, 0); - for (int i = 0; i < 9; i++, gc.add(Calendar.DATE, 1)) { - if (gc.get(Calendar.YEAR) != year || - gc.get(Calendar.MONTH) != month || - gc.get(Calendar.DATE) != (date + i)) + for (int i = 0; i < 9; i++, gc.add(DATE, 1)) { + if (gc.get(YEAR) != year + || gc.get(MONTH) != month + || gc.get(DATE) != (date + i)) { errln("FAIL: Date " + gc.getTime() + " wrong"); + } } } @@ -402,162 +443,172 @@ public class CalendarTest extends IntlTest { void dowTest(boolean lenient) { GregorianCalendar cal = new GregorianCalendar(); - cal.set(1997, Calendar.AUGUST, 12); // Wednesday + cal.set(1997, AUGUST, 12); // Wednesday cal.getTime(); // Force update cal.setLenient(lenient); - cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996 - int dow = cal.get(Calendar.DAY_OF_WEEK); - int min = cal.getMinimum(Calendar.DAY_OF_WEEK); - int max = cal.getMaximum(Calendar.DAY_OF_WEEK); - if (dow < min || dow > max) errln("FAIL: Day of week " + dow + " out of range"); - if (dow != Calendar.SUNDAY) { + cal.set(1996, DECEMBER, 1); // Set the date to be December 1, 1996 + int dow = cal.get(DAY_OF_WEEK); + int min = cal.getMinimum(DAY_OF_WEEK); + int max = cal.getMaximum(DAY_OF_WEEK); + if (dow < min || dow > max) { + errln("FAIL: Day of week " + dow + " out of range"); + } + if (dow != SUNDAY) { errln("FAIL2: Day of week should be SUNDAY; is " + dow + ": " + cal.getTime()); } - if (min != Calendar.SUNDAY || max != Calendar.SATURDAY) errln("FAIL: Min/max bad"); + if (min != SUNDAY || max != SATURDAY) { + errln("FAIL: Min/max bad"); + } } // Verify that the clone method produces distinct objects with no // unintentionally shared fields. public void TestClonesUnique908() { Calendar c = Calendar.getInstance(); - Calendar d = (Calendar)c.clone(); - c.set(Calendar.MILLISECOND, 123); - d.set(Calendar.MILLISECOND, 456); - if (c.get(Calendar.MILLISECOND) != 123 || - d.get(Calendar.MILLISECOND) != 456) { + Calendar d = (Calendar) c.clone(); + c.set(MILLISECOND, 123); + d.set(MILLISECOND, 456); + if (c.get(MILLISECOND) != 123 + || d.get(MILLISECOND) != 456) { errln("FAIL: Clones share fields"); } } // Verify effect of Gregorian cutoff value + @SuppressWarnings("deprecation") public void TestGregorianChange768() { boolean b; GregorianCalendar c = new GregorianCalendar(); logln("With cutoff " + c.getGregorianChange()); - logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800))); + logln(" isLeapYear(1800) = " + (b = c.isLeapYear(1800))); logln(" (should be FALSE)"); - if (b != false) errln("FAIL"); + if (b != false) { + errln("FAIL"); + } c.setGregorianChange(new Date(0, 0, 1)); // Jan 1 1900 logln("With cutoff " + c.getGregorianChange()); - logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800))); + logln(" isLeapYear(1800) = " + (b = c.isLeapYear(1800))); logln(" (should be TRUE)"); - if (b != true) errln("FAIL"); + if (b != true) { + errln("FAIL"); + } } // Test the correct behavior of the disambiguation algorithm. public void TestDisambiguation765() throws Exception { - Locale savedLocale = Locale.getDefault(); - try { - Locale.setDefault(Locale.US); - Calendar c = Calendar.getInstance(); - c.setLenient(false); - - c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.MONTH, Calendar.JUNE); - c.set(Calendar.DATE, 3); - - verify765("1997 third day of June = ", c, 1997, Calendar.JUNE, 3); - - c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.MONTH, Calendar.JUNE); - c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1); - verify765("1997 first Tuesday in June = ", c, 1997, Calendar.JUNE, 3); - - c.setLenient(true); // for 4944795 - c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.MONTH, Calendar.JUNE); - c.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1); - verify765("1997 last Tuesday in June = ", c, 1997, Calendar.JUNE, 24); - - c.setLenient(false); - IllegalArgumentException e = null; + Locale savedLocale = Locale.getDefault(); try { + Locale.setDefault(Locale.US); + Calendar c = Calendar.getInstance(); + c.setLenient(false); + c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.MONTH, Calendar.JUNE); - c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 0); - c.getTime(); - } - catch (IllegalArgumentException ex) { - e = ex; - } - verify765("1997 zero-th Tuesday in June = ", e); + c.set(YEAR, 1997); + c.set(MONTH, JUNE); + c.set(DATE, 3); - c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.MONTH, Calendar.JUNE); - c.set(Calendar.WEEK_OF_MONTH, 1); - verify765("1997 Tuesday in week 1 of June = ", c, 1997, Calendar.JUNE, 3); + verify765("1997 third day of June = ", c, 1997, JUNE, 3); - c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.MONTH, Calendar.JUNE); - c.set(Calendar.WEEK_OF_MONTH, 4); - verify765("1997 Tuesday in week 4 of June = ", c, 1997, Calendar.JUNE, 24); - - try { c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.MONTH, Calendar.JUNE); - c.set(Calendar.WEEK_OF_MONTH, 1); - verify765("1997 Tuesday in week 0 of June = ", c, 1997, Calendar.JUNE, 3); - } - catch (IllegalArgumentException ex) { - errln("FAIL: Exception seen: " + ex.getMessage()); - // ex.printStackTrace(log); - } + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(MONTH, JUNE); + c.set(DAY_OF_WEEK_IN_MONTH, 1); + verify765("1997 first Tuesday in June = ", c, 1997, JUNE, 3); - c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.WEEK_OF_YEAR, 2); - verify765("1997 Tuesday in week 2 of year = ", c, 1997, Calendar.JANUARY, 7); - - c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.WEEK_OF_YEAR, 10); - verify765("1997 Tuesday in week 10 of year = ", c, 1997, Calendar.MARCH, 4); - - try { + c.setLenient(true); // for 4944795 c.clear(); - c.set(Calendar.YEAR, 1997); - c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); - c.set(Calendar.WEEK_OF_YEAR, 0); - verify765("1997 Tuesday in week 0 of year = ", c, 1996, Calendar.DECEMBER, 24); - throw new Exception("Fail: WEEK_OF_YEAR 0 should be illegal"); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(MONTH, JUNE); + c.set(DAY_OF_WEEK_IN_MONTH, -1); + verify765("1997 last Tuesday in June = ", c, 1997, JUNE, 24); + + c.setLenient(false); + IllegalArgumentException e = null; + try { + c.clear(); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(MONTH, JUNE); + c.set(DAY_OF_WEEK_IN_MONTH, 0); + c.getTime(); + } catch (IllegalArgumentException ex) { + e = ex; + } + verify765("1997 zero-th Tuesday in June = ", e); + + c.clear(); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(MONTH, JUNE); + c.set(WEEK_OF_MONTH, 1); + verify765("1997 Tuesday in week 1 of June = ", c, 1997, JUNE, 3); + + c.clear(); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(MONTH, JUNE); + c.set(WEEK_OF_MONTH, 4); + verify765("1997 Tuesday in week 4 of June = ", c, 1997, JUNE, 24); + + try { + c.clear(); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(MONTH, JUNE); + c.set(WEEK_OF_MONTH, 1); + verify765("1997 Tuesday in week 0 of June = ", c, 1997, JUNE, 3); + } catch (IllegalArgumentException ex) { + errln("FAIL: Exception seen: " + ex.getMessage()); + // ex.printStackTrace(log); + } + + c.clear(); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(WEEK_OF_YEAR, 2); + verify765("1997 Tuesday in week 2 of year = ", c, 1997, JANUARY, 7); + + c.clear(); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(WEEK_OF_YEAR, 10); + verify765("1997 Tuesday in week 10 of year = ", c, 1997, MARCH, 4); + + try { + c.clear(); + c.set(YEAR, 1997); + c.set(DAY_OF_WEEK, TUESDAY); + c.set(WEEK_OF_YEAR, 0); + verify765("1997 Tuesday in week 0 of year = ", c, 1996, DECEMBER, 24); + throw new Exception("Fail: WEEK_OF_YEAR 0 should be illegal"); + } catch (IllegalArgumentException ex) { + } + } finally { + Locale.setDefault(savedLocale); } - catch (IllegalArgumentException ex) {} - } - finally { - Locale.setDefault(savedLocale); - } } + void verify765(String msg, Calendar c, int year, int month, int day) { - if (c.get(Calendar.YEAR) == year && - c.get(Calendar.MONTH) == month && - c.get(Calendar.DATE) == day) { + if (c.get(YEAR) == year + && c.get(MONTH) == month + && c.get(DATE) == day) { logln("PASS: " + msg + c.getTime()); - } - else { - errln("FAIL: " + msg + c.getTime() + - "; expected " + - year + "/" + (month+1) + "/" + day); + } else { + errln("FAIL: " + msg + c.getTime() + + "; expected " + + year + "/" + (month + 1) + "/" + day); } } + // Called when e expected to be non-null void verify765(String msg, IllegalArgumentException e) { - if (e == null) errln("FAIL: No IllegalArgumentException for " + msg); - else logln("PASS: " + msg + "IllegalArgument as expected"); + if (e == null) { + errln("FAIL: No IllegalArgumentException for " + msg); + } else { + logln("PASS: " + msg + "IllegalArgument as expected"); + } } // Test the behavior of GMT vs. local time @@ -588,106 +639,112 @@ public class CalendarTest extends IntlTest { Date date; Calendar gmtcal = Calendar.getInstance(); gmtcal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca")); - gmtcal.set(yr, mo-1, dt, hr, mn, sc); - gmtcal.set(Calendar.MILLISECOND, 0); + gmtcal.set(yr, mo - 1, dt, hr, mn, sc); + gmtcal.set(MILLISECOND, 0); date = gmtcal.getTime(); - logln("date = "+date); + logln("date = " + date); Calendar cal = Calendar.getInstance(); cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); cal.setTime(date); - int offset = cal.getTimeZone().getOffset(cal.get(Calendar.ERA), - cal.get(Calendar.YEAR), - cal.get(Calendar.MONTH), - cal.get(Calendar.DATE), - cal.get(Calendar.DAY_OF_WEEK), - cal.get(Calendar.MILLISECOND)); + int offset = cal.getTimeZone().getOffset(cal.get(ERA), + cal.get(YEAR), + cal.get(MONTH), + cal.get(DATE), + cal.get(DAY_OF_WEEK), + cal.get(MILLISECOND)); - logln("offset for "+date+"= "+(offset/1000/60/60.0) + "hr"); + logln("offset for " + date + "= " + (offset / 1000 / 60 / 60.0) + "hr"); - int utc = ((cal.get(Calendar.HOUR_OF_DAY) * 60 + - cal.get(Calendar.MINUTE)) * 60 + - cal.get(Calendar.SECOND)) * 1000 + - cal.get(Calendar.MILLISECOND) - offset; + int utc = ((cal.get(HOUR_OF_DAY) * 60 + + cal.get(MINUTE)) * 60 + + cal.get(SECOND)) * 1000 + + cal.get(MILLISECOND) - offset; int expected = ((hr * 60 + mn) * 60 + sc) * 1000; - if (utc != expected) - errln("FAIL: Discrepancy of " + - (utc - expected) + " millis = " + - ((utc-expected)/1000/60/60.0) + " hr"); + if (utc != expected) { + errln("FAIL: Discrepancy of " + + (utc - expected) + " millis = " + + ((utc - expected) / 1000 / 60 / 60.0) + " hr"); + } } // Verify that add and set work regardless of the order in which // they are called. public void TestAddSetOrder621() { + @SuppressWarnings("deprecation") Date d = new Date(97, 4, 14, 13, 23, 45); - Calendar cal = Calendar.getInstance (); - cal.setTime (d); - cal.add (Calendar.DATE, -5); - cal.set (Calendar.HOUR_OF_DAY, 0); - cal.set (Calendar.MINUTE, 0); - cal.set (Calendar.SECOND, 0); + Calendar cal = Calendar.getInstance(); + cal.setTime(d); + cal.add(DATE, -5); + cal.set(HOUR_OF_DAY, 0); + cal.set(MINUTE, 0); + cal.set(SECOND, 0); // ma feb 03 00:00:00 GMT+00:00 1997 - String s = cal.getTime ().toString (); + String s = cal.getTime().toString(); - cal = Calendar.getInstance (); - cal.setTime (d); - cal.set (Calendar.HOUR_OF_DAY, 0); - cal.set (Calendar.MINUTE, 0); - cal.set (Calendar.SECOND, 0); - cal.add (Calendar.DATE, -5); + cal = Calendar.getInstance(); + cal.setTime(d); + cal.set(HOUR_OF_DAY, 0); + cal.set(MINUTE, 0); + cal.set(SECOND, 0); + cal.add(DATE, -5); // ma feb 03 13:11:06 GMT+00:00 1997 - String s2 = cal.getTime ().toString (); + String s2 = cal.getTime().toString(); - if (s.equals(s2)) + if (s.equals(s2)) { logln("Pass: " + s + " == " + s2); - else + } else { errln("FAIL: " + s + " != " + s2); + } } // Verify that add works. public void TestAdd520() { - int y = 1997, m = Calendar.FEBRUARY, d = 1; - GregorianCalendar temp = new GregorianCalendar( y, m, d ); + int y = 1997, m = FEBRUARY, d = 1; + GregorianCalendar temp = new GregorianCalendar(y, m, d); check520(temp, y, m, d); - temp.add( temp.YEAR, 1 ); + temp.add(YEAR, 1); y++; check520(temp, y, m, d); - temp.add( temp.MONTH, 1 ); + temp.add(MONTH, 1); m++; check520(temp, y, m, d); - temp.add( temp.DATE, 1 ); + temp.add(DATE, 1); d++; check520(temp, y, m, d); - temp.add( temp.DATE, 2 ); + temp.add(DATE, 2); d += 2; check520(temp, y, m, d); - temp.add( temp.DATE, 28 ); - d = 1; ++m; + temp.add(DATE, 28); + d = 1; + ++m; check520(temp, y, m, d); } + void check520(Calendar c, int y, int m, int d) { - if (c.get(Calendar.YEAR) != y || - c.get(Calendar.MONTH) != m || - c.get(Calendar.DATE) != d) { - errln("FAILURE: Expected YEAR/MONTH/DATE of " + - y + "/" + (m+1) + "/" + d + - "; got " + - c.get(Calendar.YEAR) + "/" + - (c.get(Calendar.MONTH)+1) + "/" + - c.get(Calendar.DATE)); + if (c.get(YEAR) != y + || c.get(MONTH) != m + || c.get(DATE) != d) { + errln("FAILURE: Expected YEAR/MONTH/DATE of " + + y + "/" + (m + 1) + "/" + d + + "; got " + + c.get(YEAR) + "/" + + (c.get(MONTH) + 1) + "/" + + c.get(DATE)); + } else { + logln("Confirmed: " + + y + "/" + (m + 1) + "/" + d); } - else logln("Confirmed: " + - y + "/" + (m+1) + "/" + d); } // Verify that setting fields works. This test fails when an exception is thrown. @@ -697,18 +754,18 @@ public class CalendarTest extends IntlTest { GregorianCalendar g2 = new GregorianCalendar(); // At this point UTC value is set, various fields are not. // Now set to noon. - g2.set(Calendar.HOUR, 12); - g2.set(Calendar.MINUTE, 0); - g2.set(Calendar.SECOND, 0); + g2.set(HOUR, 12); + g2.set(MINUTE, 0); + g2.set(SECOND, 0); // At this point the object thinks UTC is NOT set, but fields are set. // The following line will result in IllegalArgumentException because // it thinks the YEAR is set and it is NOT. - if (g2.equals(g)) + if (g2.equals(g)) { logln("Same"); - else + } else { logln("Different"); - } - catch (IllegalArgumentException e) { + } + } catch (IllegalArgumentException e) { errln("Unexpected exception seen: " + e); } } @@ -729,28 +786,28 @@ public class CalendarTest extends IntlTest { FileInputStream in = new FileInputStream(FILENAME); ObjectInputStream t = new ObjectInputStream(in); - String pre = (String)t.readObject(); - Calendar c = (Calendar)t.readObject(); - String post = (String)t.readObject(); + String pre = (String) t.readObject(); + Calendar c = (Calendar) t.readObject(); + String post = (String) t.readObject(); in.close(); - ok = pre.equals(PREFIX) && - post.equals(POSTFIX) && - cal.equals(c); + ok = pre.equals(PREFIX) + && post.equals(POSTFIX) + && cal.equals(c); File fl = new File(FILENAME); fl.delete(); - } - catch (IOException e) { + } catch (IOException e) { errln("FAIL: Exception received:"); // e.printStackTrace(log); - } - catch (ClassNotFoundException e) { + } catch (ClassNotFoundException e) { errln("FAIL: Exception received:"); // e.printStackTrace(log); } - if (!ok) errln("Serialization of Calendar object failed."); + if (!ok) { + errln("Serialization of Calendar object failed."); + } } static final String PREFIX = "abc"; static final String POSTFIX = "def"; @@ -758,14 +815,16 @@ public class CalendarTest extends IntlTest { // Try to zero out the seconds field public void TestSecondsZero121() { - Calendar cal = new GregorianCalendar(); + Calendar cal = new GregorianCalendar(); // Initialize with current date/time cal.setTime(new Date()); // Round down to minute - cal.set(Calendar.SECOND, 0); - Date d = cal.getTime(); + cal.set(SECOND, 0); + Date d = cal.getTime(); String s = d.toString(); - if (s.indexOf(":00 ") < 0) errln("Expected to see :00 in " + s); + if (s.indexOf(":00 ") < 0) { + errln("Expected to see :00 in " + s); + } } // Try various sequences of add, set, and get method calls. @@ -777,15 +836,17 @@ public class CalendarTest extends IntlTest { // - Addition uses millis which are still *now* // { - Calendar calendar = new GregorianCalendar( ) ; - calendar.set( 1993, Calendar.JANUARY, 4 ) ; - logln( "1A) " + value( calendar ) ) ; - calendar.add( Calendar.DATE, 1 ) ; + Calendar calendar = new GregorianCalendar(); + calendar.set(1993, JANUARY, 4); + logln("1A) " + value(calendar)); + calendar.add(DATE, 1); String v = value(calendar); - logln( "1B) " + v ); - logln( "--) 1993/0/5" ) ; - if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + - "; saw " + v); + logln("1B) " + v); + logln("--) 1993/0/5"); + if (!v.equals(EXPECTED_0610)) { + errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } } // @@ -793,16 +854,17 @@ public class CalendarTest extends IntlTest { // - Upon initialization calendar fields set, millis = 0 // - Addition uses millis which are still 1970, 0, 1 // - { - Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ; - logln( "2A) " + value( calendar ) ) ; - calendar.add( Calendar.DATE, 1 ) ; + Calendar calendar = new GregorianCalendar(1993, JANUARY, 4); + logln("2A) " + value(calendar)); + calendar.add(DATE, 1); String v = value(calendar); - logln( "2B) " + v ); - logln( "--) 1993/0/5" ) ; - if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + - "; saw " + v); + logln("2B) " + v); + logln("--) 1993/0/5"); + if (!v.equals(EXPECTED_0610)) { + errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } } // @@ -811,102 +873,99 @@ public class CalendarTest extends IntlTest { // - getTime( ) is called which forces the millis to be set // - Addition uses millis which are correct // - { - Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ; - logln( "3A) " + value( calendar ) ) ; - calendar.getTime( ) ; - calendar.add( Calendar.DATE, 1 ) ; + Calendar calendar = new GregorianCalendar(1993, JANUARY, 4); + logln("3A) " + value(calendar)); + calendar.getTime(); + calendar.add(DATE, 1); String v = value(calendar); - logln( "3B) " + v ) ; - logln( "--) 1993/0/5" ) ; - if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + - "; saw " + v); + logln("3B) " + v); + logln("--) 1993/0/5"); + if (!v.equals(EXPECTED_0610)) { + errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } } } - static String value( Calendar calendar ) { - return( calendar.get( Calendar.YEAR ) + "/" + - calendar.get( Calendar.MONTH ) + "/" + - calendar.get( Calendar.DATE ) ) ; + static String value(Calendar calendar) { + return (calendar.get(YEAR) + "/" + + calendar.get(MONTH) + "/" + + calendar.get(DATE)); } static String EXPECTED_0610 = "1993/0/5"; // Test that certain fields on a certain date are as expected. public void TestFields060() { int year = 1997; - int month = java.util.Calendar.OCTOBER; //october + int month = OCTOBER; //october int dDate = 22; //DAYOFWEEK should return 3 for Wednesday GregorianCalendar calendar = null; - calendar = new GregorianCalendar( year, month, dDate); - for (int i = 0; i < EXPECTED_FIELDS.length; ) { + calendar = new GregorianCalendar(year, month, dDate); + for (int i = 0; i < EXPECTED_FIELDS.length;) { int field = EXPECTED_FIELDS[i++]; int expected = EXPECTED_FIELDS[i++]; if (calendar.get(field) != expected) { - errln("Expected field " + field + " to have value " + expected + - "; received " + calendar.get(field) + " instead"); + errln("Expected field " + field + " to have value " + expected + + "; received " + calendar.get(field) + " instead"); } } } - static int EXPECTED_FIELDS[] = { - Calendar.YEAR, 1997, - Calendar.MONTH, Calendar.OCTOBER, - Calendar.DAY_OF_MONTH, 22, - Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY, - Calendar.DAY_OF_WEEK_IN_MONTH, 4, - Calendar.DAY_OF_YEAR, 295 - }; + static int[] EXPECTED_FIELDS = { + YEAR, 1997, + MONTH, OCTOBER, + DAY_OF_MONTH, 22, + DAY_OF_WEEK, WEDNESDAY, + DAY_OF_WEEK_IN_MONTH, 4, + DAY_OF_YEAR, 295}; static final String[] calendarFieldNames = { - /* 0 */ "ERA", - /* 1 */ "YEAR", - /* 2 */ "MONTH", - /* 3 */ "WEEK_OF_YEAR", - /* 4 */ "WEEK_OF_MONTH", - /* 5 */ "DAY_OF_MONTH", - /* 6 */ "DAY_OF_YEAR", - /* 7 */ "DAY_OF_WEEK", - /* 8 */ "DAY_OF_WEEK_IN_MONTH", - /* 9 */ "AM_PM", - /* 10 */ "HOUR", - /* 11 */ "HOUR_OF_DAY", - /* 12 */ "MINUTE", - /* 13 */ "SECOND", - /* 14 */ "MILLISECOND", - /* 15 */ "ZONE_OFFSET", - /* 16 */ "DST_OFFSET" - }; + /* 0 */ "ERA", + /* 1 */ "YEAR", + /* 2 */ "MONTH", + /* 3 */ "WEEK_OF_YEAR", + /* 4 */ "WEEK_OF_MONTH", + /* 5 */ "DAY_OF_MONTH", + /* 6 */ "DAY_OF_YEAR", + /* 7 */ "DAY_OF_WEEK", + /* 8 */ "DAY_OF_WEEK_IN_MONTH", + /* 9 */ "AM_PM", + /* 10 */ "HOUR", + /* 11 */ "HOUR_OF_DAY", + /* 12 */ "MINUTE", + /* 13 */ "SECOND", + /* 14 */ "MILLISECOND", + /* 15 */ "ZONE_OFFSET", + /* 16 */ "DST_OFFSET"}; // Verify that the fields are as expected (mostly zero) at the epoch start. // Note that we adjust for the default timezone to get most things to zero. public void TestEpochStartFields() { String[][] lt = { - {"en", "US", "US/Pacific"}, /* First day = 1, Minimum day = 1 */ - {"en", "US", "America/Anchorage"}, /* First day = 1, Minimum day = 1 */ - {"en", "TO", "Pacific/Tongatapu"}, /* First day = 1, Minimum day = 1 */ - {"en", "MH", "Pacific/Majuro"}, /* First day = 1, Minimum day = 1 */ - {"ja", "JP", "Asia/Tokyo"}, /* First day = 1, Minimum day = 1 */ - {"iw", "IL", "Asia/Jerusalem"}, /* First day = 1, Minimum day = 1 */ - {"hi", "IN", "Asia/Jakarta"}, /* First day = 1, Minimum day = 1 */ - {"en", "GB", "Europe/London"}, /* First day = 2, Minimum day = 1 */ - {"en", "GB", "GMT"}, /* First day = 2, Minimum day = 1 */ - {"de", "DE", "Europe/Berlin"}, /* First day = 2, Minimum day = 4 */ - {"ar", "EG", "Africa/Cairo"}, /* First day = 7, Minimum day = 1 */ - }; + {"en", "US", "US/Pacific"}, /* First day = 1, Minimum day = 1 */ + {"en", "US", "America/Anchorage"}, /* First day = 1, Minimum day = 1 */ + {"en", "TO", "Pacific/Tongatapu"}, /* First day = 1, Minimum day = 1 */ + {"en", "MH", "Pacific/Majuro"}, /* First day = 1, Minimum day = 1 */ + {"ja", "JP", "Asia/Tokyo"}, /* First day = 1, Minimum day = 1 */ + {"iw", "IL", "Asia/Jerusalem"}, /* First day = 1, Minimum day = 1 */ + {"hi", "IN", "Asia/Jakarta"}, /* First day = 1, Minimum day = 1 */ + {"en", "GB", "Europe/London"}, /* First day = 2, Minimum day = 1 */ + {"en", "GB", "GMT"}, /* First day = 2, Minimum day = 1 */ + {"de", "DE", "Europe/Berlin"}, /* First day = 2, Minimum day = 4 */ + {"ar", "EG", "Africa/Cairo"}}; /* First day = 7, Minimum day = 1 */ int[][] goldenData = { - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, -28800000, 0}, - {1, 1969, 11, 1, 5, 31, 365, 4, 5, 1, 11, 23, 0, 0, 0, -36000000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 46800000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 43200000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 32400000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 25200000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 1, 1, 0, 0, 0, 3600000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 3600000, 0}, - {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0}, - }; + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, -28800000, 0}, + {1, 1969, 11, 1, 5, 31, 365, 4, 5, 1, 11, 23, 0, 0, 0, -36000000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 46800000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 43200000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 32400000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 25200000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 1, 1, 0, 0, 0, 3600000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 3600000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0}}; Locale savedLocale = Locale.getDefault(); TimeZone savedTimeZone = TimeZone.getDefault(); @@ -927,19 +986,18 @@ public class CalendarTest extends IntlTest { boolean err = false; for (int i = 0; i < calendarFieldNames.length; ++i) { if ((val = c.get(i)) != EPOCH_FIELDS[i]) { - errln("Wrong value: " + val + - " for field(" + calendarFieldNames[i] + - "), expected: " + EPOCH_FIELDS[i]); + errln("Wrong value: " + val + + " for field(" + calendarFieldNames[i] + + "), expected: " + EPOCH_FIELDS[i]); err = true; } } if (err) { - errln("Failed: \n\tDate=" + d + "\n\tTimeZone=" + z + - "\n\tLocale=" + l + "\n\tCalendar=" + c); + errln("Failed: \n\tDate=" + d + "\n\tTimeZone=" + z + + "\n\tLocale=" + l + "\n\tCalendar=" + c); } } - } - finally { + } finally { Locale.setDefault(savedLocale); TimeZone.setDefault(savedTimeZone); } @@ -948,125 +1006,146 @@ public class CalendarTest extends IntlTest { // Verify that as you add days to the calendar (e.g., 24 day periods), // the day of the week shifts in the expected pattern. public void TestDOWProgression() { - Calendar cal = - new GregorianCalendar(1972, Calendar.OCTOBER, 26); + Calendar cal + = new GregorianCalendar(1972, OCTOBER, 26); marchByDelta(cal, 24); // Last parameter must be != 0 modulo 7 } // Supply a delta which is not a multiple of 7. void marchByDelta(Calendar cal, int delta) { - Calendar cur = (Calendar)cal.clone(); - int initialDOW = cur.get(Calendar.DAY_OF_WEEK); + Calendar cur = (Calendar) cal.clone(); + int initialDOW = cur.get(DAY_OF_WEEK); int DOW, newDOW = initialDOW; do { DOW = newDOW; logln("DOW = " + DOW + " " + cur.getTime()); - cur.add(Calendar.DAY_OF_WEEK, delta); - newDOW = cur.get(Calendar.DAY_OF_WEEK); + cur.add(DAY_OF_WEEK, delta); + newDOW = cur.get(DAY_OF_WEEK); int expectedDOW = 1 + (DOW + delta - 1) % 7; if (newDOW != expectedDOW) { - errln("Day of week should be " + expectedDOW + - " instead of " + newDOW + " on " + cur.getTime()); + errln("Day of week should be " + expectedDOW + + " instead of " + newDOW + " on " + cur.getTime()); return; } - } - while (newDOW != initialDOW); + } while (newDOW != initialDOW); } public void TestActualMinMax() { - Calendar cal = new GregorianCalendar(1967, Calendar.MARCH, 10); - cal.setFirstDayOfWeek(Calendar.SUNDAY); + Calendar cal = new GregorianCalendar(1967, MARCH, 10); + cal.setFirstDayOfWeek(SUNDAY); cal.setMinimalDaysInFirstWeek(3); - if (cal.getActualMinimum(Calendar.DAY_OF_MONTH) != 1) - errln("Actual minimum date for 3/10/1967 should have been 1; got " + - cal.getActualMinimum(Calendar.DAY_OF_MONTH)); - if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 31) - errln("Actual maximum date for 3/10/1967 should have been 31; got " + - cal.getActualMaximum(Calendar.DAY_OF_MONTH)); + if (cal.getActualMinimum(DAY_OF_MONTH) != 1) { + errln("Actual minimum date for 3/10/1967 should have been 1; got " + + cal.getActualMinimum(DAY_OF_MONTH)); + } + if (cal.getActualMaximum(DAY_OF_MONTH) != 31) { + errln("Actual maximum date for 3/10/1967 should have been 31; got " + + cal.getActualMaximum(DAY_OF_MONTH)); + } - cal.set(Calendar.MONTH, Calendar.FEBRUARY); - if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 28) - errln("Actual maximum date for 2/10/1967 should have been 28; got " + - cal.getActualMaximum(Calendar.DAY_OF_MONTH)); - if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 365) - errln("Number of days in 1967 should have been 365; got " + - cal.getActualMaximum(Calendar.DAY_OF_YEAR)); + cal.set(MONTH, FEBRUARY); + if (cal.getActualMaximum(DAY_OF_MONTH) != 28) { + errln("Actual maximum date for 2/10/1967 should have been 28; got " + + cal.getActualMaximum(DAY_OF_MONTH)); + } + if (cal.getActualMaximum(DAY_OF_YEAR) != 365) { + errln("Number of days in 1967 should have been 365; got " + + cal.getActualMaximum(DAY_OF_YEAR)); + } - cal.set(Calendar.YEAR, 1968); - if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 29) - errln("Actual maximum date for 2/10/1968 should have been 29; got " + - cal.getActualMaximum(Calendar.DAY_OF_MONTH)); - if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 366) - errln("Number of days in 1968 should have been 366; got " + - cal.getActualMaximum(Calendar.DAY_OF_YEAR)); + cal.set(YEAR, 1968); + if (cal.getActualMaximum(DAY_OF_MONTH) != 29) { + errln("Actual maximum date for 2/10/1968 should have been 29; got " + + cal.getActualMaximum(DAY_OF_MONTH)); + } + if (cal.getActualMaximum(DAY_OF_YEAR) != 366) { + errln("Number of days in 1968 should have been 366; got " + + cal.getActualMaximum(DAY_OF_YEAR)); + } // Using week settings of SUNDAY/3 (see above) - if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 52) - errln("Number of weeks in 1968 should have been 52; got " + - cal.getActualMaximum(Calendar.WEEK_OF_YEAR)); + if (cal.getActualMaximum(WEEK_OF_YEAR) != 52) { + errln("Number of weeks in 1968 should have been 52; got " + + cal.getActualMaximum(WEEK_OF_YEAR)); + } - cal.set(Calendar.YEAR, 1976); + cal.set(YEAR, 1976); // Using week settings of SUNDAY/3 (see above) - if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 53) - errln("Number of weeks in 1976 should have been 53; got " + - cal.getActualMaximum(Calendar.WEEK_OF_YEAR)); + if (cal.getActualMaximum(WEEK_OF_YEAR) != 53) { + errln("Number of weeks in 1976 should have been 53; got " + + cal.getActualMaximum(WEEK_OF_YEAR)); + } } public void TestRoll() { - Calendar cal = new GregorianCalendar(1997, Calendar.JANUARY, 31); + Calendar cal = new GregorianCalendar(1997, JANUARY, 31); - int[] dayValues = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 }; + int[] dayValues = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31}; for (int i = 0; i < dayValues.length; i++) { - Calendar cal2 = (Calendar)cal.clone(); - cal2.roll(Calendar.MONTH, i); - if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues[i]) + Calendar cal2 = (Calendar) cal.clone(); + cal2.roll(MONTH, i); + if (cal2.get(DAY_OF_MONTH) != dayValues[i]) { errln("Rolling the month in 1/31/1997 up by " + i + " should have yielded " - + ((i + 1) % 12) + "/" + dayValues[i] + "/1997, but actually yielded " - + ((i + 1) % 12) + "/" + cal2.get(Calendar.DAY_OF_MONTH) + "/1997."); + + ((i + 1) % 12) + "/" + dayValues[i] + "/1997, but actually yielded " + + ((i + 1) % 12) + "/" + cal2.get(DAY_OF_MONTH) + "/1997."); + } } - cal.set(1996, Calendar.FEBRUARY, 29); + cal.set(1996, FEBRUARY, 29); - int[] monthValues = { 1, 2, 2, 2, 1, 2, 2, 2, 1, 2 }; - int[] dayValues2 = { 29, 1, 1, 1, 29, 1, 1, 1, 29, 1 }; + int[] monthValues = {1, 2, 2, 2, 1, 2, 2, 2, 1, 2}; + int[] dayValues2 = {29, 1, 1, 1, 29, 1, 1, 1, 29, 1}; for (int i = 0; i < dayValues2.length; i++) { - Calendar cal2 = (Calendar)cal.clone(); - cal2.roll(Calendar.YEAR, i); - if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues2[i] || cal2.get(Calendar.MONTH) - != monthValues[i]) + Calendar cal2 = (Calendar) cal.clone(); + cal2.roll(YEAR, i); + if (cal2.get(DAY_OF_MONTH) != dayValues2[i] || cal2.get(MONTH) + != monthValues[i]) { errln("Rolling the year in 2/29/1996 up by " + i + " should have yielded " - + (monthValues[i] + 1) + "/" + dayValues2[i] + "/" - + (1996 + i) + ", but actually yielded " - + (cal2.get(Calendar.MONTH) + 1) + "/" + - cal2.get(Calendar.DAY_OF_MONTH) + "/" + (1996 + i) + "."); + + (monthValues[i] + 1) + "/" + dayValues2[i] + "/" + + (1996 + i) + ", but actually yielded " + + (cal2.get(MONTH) + 1) + "/" + + cal2.get(DAY_OF_MONTH) + "/" + (1996 + i) + "."); + } } // Test rolling hour of day - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.roll(Calendar.HOUR_OF_DAY, -2); - int f = cal.get(Calendar.HOUR_OF_DAY); - if (f != 22) errln("Rolling HOUR_OF_DAY=0 delta=-2 gave " + f + " Wanted 22"); - cal.roll(Calendar.HOUR_OF_DAY, 5); - f = cal.get(Calendar.HOUR_OF_DAY); - if (f != 3) errln("Rolling HOUR_OF_DAY=22 delta=5 gave " + f + " Wanted 3"); - cal.roll(Calendar.HOUR_OF_DAY, 21); - f = cal.get(Calendar.HOUR_OF_DAY); - if (f != 0) errln("Rolling HOUR_OF_DAY=3 delta=21 gave " + f + " Wanted 0"); + cal.set(HOUR_OF_DAY, 0); + cal.roll(HOUR_OF_DAY, -2); + int f = cal.get(HOUR_OF_DAY); + if (f != 22) { + errln("Rolling HOUR_OF_DAY=0 delta=-2 gave " + f + " Wanted 22"); + } + cal.roll(HOUR_OF_DAY, 5); + f = cal.get(HOUR_OF_DAY); + if (f != 3) { + errln("Rolling HOUR_OF_DAY=22 delta=5 gave " + f + " Wanted 3"); + } + cal.roll(HOUR_OF_DAY, 21); + f = cal.get(HOUR_OF_DAY); + if (f != 0) { + errln("Rolling HOUR_OF_DAY=3 delta=21 gave " + f + " Wanted 0"); + } // Test rolling hour - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.roll(Calendar.HOUR, -2); - f = cal.get(Calendar.HOUR); - if (f != 10) errln("Rolling HOUR=0 delta=-2 gave " + f + " Wanted 10"); - cal.roll(Calendar.HOUR, 5); - f = cal.get(Calendar.HOUR); - if (f != 3) errln("Rolling HOUR=10 delta=5 gave " + f + " Wanted 3"); - cal.roll(Calendar.HOUR, 9); - f = cal.get(Calendar.HOUR); - if (f != 0) errln("Rolling HOUR=3 delta=9 gave " + f + " Wanted 0"); + cal.set(HOUR_OF_DAY, 0); + cal.roll(HOUR, -2); + f = cal.get(HOUR); + if (f != 10) { + errln("Rolling HOUR=0 delta=-2 gave " + f + " Wanted 10"); + } + cal.roll(HOUR, 5); + f = cal.get(HOUR); + if (f != 3) { + errln("Rolling HOUR=10 delta=5 gave " + f + " Wanted 3"); + } + cal.roll(HOUR, 9); + f = cal.get(HOUR); + if (f != 0) { + errln("Rolling HOUR=3 delta=9 gave " + f + " Wanted 0"); + } } /* @@ -1081,19 +1160,18 @@ public class CalendarTest extends IntlTest { TimeZone.setDefault(TimeZone.getTimeZone("PST")); Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, 2001); - cal.set(Calendar.MONTH, Calendar.OCTOBER); - cal.set(Calendar.WEEK_OF_YEAR, 4); - cal.set(Calendar.DAY_OF_WEEK, 2); + cal.set(YEAR, 2001); + cal.set(MONTH, OCTOBER); + cal.set(WEEK_OF_YEAR, 4); + cal.set(DAY_OF_WEEK, 2); - if (cal.get(Calendar.YEAR) != 2001 || - cal.get(Calendar.MONTH) != Calendar.JANUARY || - cal.get(Calendar.DATE) != 22 || - cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) { + if (cal.get(YEAR) != 2001 + || cal.get(MONTH) != JANUARY + || cal.get(DATE) != 22 + || cal.get(DAY_OF_WEEK) != MONDAY) { errln("Failed : got " + cal.getTime() + ", expected Mon Jan 22, 2001"); } - } - finally { + } finally { Locale.setDefault(savedLocale); TimeZone.setDefault(savedTimeZone); } diff --git a/jdk/test/java/util/Calendar/CalendarTypeTest.java b/jdk/test/java/util/Calendar/CalendarTypeTest.java index ce36cd656b3..41bb87e7421 100644 --- a/jdk/test/java/util/Calendar/CalendarTypeTest.java +++ b/jdk/test/java/util/Calendar/CalendarTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -27,9 +27,13 @@ * @summary Unit test for calendar types */ -import java.util.*; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.Set; public class CalendarTypeTest { + // Calendar types supported in JRE static Locale[] locales = new Locale[] { Locale.US, @@ -37,23 +41,20 @@ public class CalendarTypeTest { new Locale("th", "TH"), Locale.forLanguageTag("en-US-u-ca-buddhist"), new Locale("ja", "JP", "JP"), - Locale.forLanguageTag("en-US-u-ca-japanese"), - }; + Locale.forLanguageTag("en-US-u-ca-japanese")}; static final String[] TYPES = new String[] { "gregory", "buddhist", - "japanese", - }; + "japanese"}; static final String[] ALIASES = new String[] { "gregorian", - "iso8601", - }; + "iso8601"}; public static void main(String[] args) { for (int i = 0; i < locales.length; i++) { Calendar cal = Calendar.getInstance(locales[i]); String type = cal.getCalendarType(); - checkValue("bad calendar type", type, TYPES[i/2]); + checkValue("bad calendar type", type, TYPES[i / 2]); } GregorianCalendar gcal = new GregorianCalendar(); @@ -88,10 +89,13 @@ public class CalendarTypeTest { } } + @SuppressWarnings("serial") private static class Gregorian extends GregorianCalendar { } + @SuppressWarnings("serial") private static class Koyomi extends Calendar { + @Override protected void computeTime() { throw new UnsupportedOperationException("Not supported yet."); diff --git a/jdk/test/java/util/Calendar/FieldStateTest.java b/jdk/test/java/util/Calendar/FieldStateTest.java index caa6f219a24..34ab9e8076d 100644 --- a/jdk/test/java/util/Calendar/FieldStateTest.java +++ b/jdk/test/java/util/Calendar/FieldStateTest.java @@ -144,8 +144,11 @@ public class FieldStateTest extends IntlTest { } logln("Set day of week to SUNDAY and date to 2003/10/31. " - + "Then, getTime and set week of year to 43."); - cal.setTime(new Date(2003-1990, OCTOBER, 31)); + + "Then, getTime and set week of year to 43."); + + @SuppressWarnings("deprecation") + Date d = new Date(2003 - 1990, OCTOBER, 31); + cal.setTime(d); cal.set(DAY_OF_WEEK, SUNDAY); cal.set(2003, OCTOBER, 31); // 2003/10/31 is Friday. cal.set(ZONE_OFFSET, 0); @@ -166,8 +169,8 @@ public class FieldStateTest extends IntlTest { * 4916815: REGRESSION: Problem with java.util.Calendar VM 1.4.2-b28 */ public void Test4916815() { - logln("Set date to 2003/9/26 (Fri). Roll to Aug and back to Sep. "+ - "Set dayofweek to Sunday which should be 2003/9/21."); + logln("Set date to 2003/9/26 (Fri). Roll to Aug and back to Sep. " + + "Set dayofweek to Sunday which should be 2003/9/21."); Koyomi cal = new Koyomi(); cal.clear(); // 2003/9/26 (Fri) @@ -192,17 +195,17 @@ public class FieldStateTest extends IntlTest { cal.clear(); cal.set(YEAR, 2004); cal.set(WEEK_OF_YEAR, 1); - checkDate(cal, SUNDAY, 2003, DECEMBER, 28); - checkDate(cal, MONDAY, 2003, DECEMBER, 29); - checkDate(cal, TUESDAY, 2003, DECEMBER, 30); + checkDate(cal, SUNDAY, 2003, DECEMBER, 28); + checkDate(cal, MONDAY, 2003, DECEMBER, 29); + checkDate(cal, TUESDAY, 2003, DECEMBER, 30); checkDate(cal, WEDNESDAY, 2003, DECEMBER, 31); - checkDate(cal, THURSDAY, 2004, JANUARY, 1); - checkDate(cal, FRIDAY, 2004, JANUARY, 2); - checkDate(cal, SATURDAY, 2004, JANUARY, 3); + checkDate(cal, THURSDAY, 2004, JANUARY, 1); + checkDate(cal, FRIDAY, 2004, JANUARY, 2); + checkDate(cal, SATURDAY, 2004, JANUARY, 3); } private void checkDate(Koyomi cal, int dayOfWeek, - int expectedYear, int expectedMonth, int expectedDayOfMonth) { + int expectedYear, int expectedMonth, int expectedDayOfMonth) { cal.set(DAY_OF_WEEK, dayOfWeek); cal.getTime(); if (!cal.checkInternalDate(expectedYear, expectedMonth, expectedDayOfMonth, dayOfWeek)) { diff --git a/jdk/test/java/util/Calendar/GregorianCutoverTest.java b/jdk/test/java/util/Calendar/GregorianCutoverTest.java index bd743ae19f6..a9b840a95b1 100644 --- a/jdk/test/java/util/Calendar/GregorianCutoverTest.java +++ b/jdk/test/java/util/Calendar/GregorianCutoverTest.java @@ -76,7 +76,9 @@ public class GregorianCutoverTest extends IntlTest { checkContinuity(cal, WEEK_OF_YEAR); // Use large date (year >= 50000) - cal.setGregorianChange(new Date(50000-1900, JANUARY, 20)); + @SuppressWarnings("deprecation") + Date d = new Date(50000 - 1900, JANUARY, 20); + cal.setGregorianChange(d); cal.set(49998, JANUARY, 1); checkContinuity(cal, DAY_OF_YEAR); checkContinuity(cal, WEEK_OF_YEAR); @@ -124,7 +126,9 @@ public class GregorianCutoverTest extends IntlTest { // should handle the gap between 1969/12/22 (Julian) to 1970/1/5 (Gregorian) logln("Cutover date is 1970/1/5"); - cal.setGregorianChange(new Date(1970-1900, JANUARY, 5)); + @SuppressWarnings("deprecation") + Date d1 = new Date(1970 - 1900, JANUARY, 5); + cal.setGregorianChange(d1); cal.set(ERA, AD); cal.set(YEAR, 1970); logln(" Set DAY_OF_YEAR to the 28th day of 1970"); @@ -203,16 +207,17 @@ public class GregorianCutoverTest extends IntlTest { public void Test4928615() { Koyomi cal = new Koyomi(); logln("Today is 2003/10/1 Gregorian."); - Date x = new Date(2003-1900, 10-1, 1); + @SuppressWarnings("deprecation") + Date x = new Date(2003 - 1900, 10 - 1, 1); cal.setTime(x); logln(" Changing the cutover date to yesterday..."); - cal.setGregorianChange(new Date(x.getTime() - (24*3600*1000))); + cal.setGregorianChange(new Date(x.getTime() - (24 * 3600 * 1000))); if (!cal.checkDate(2003, OCTOBER, 1)) { errln(" " + cal.getMessage()); } logln(" Changing the cutover date to tomorrow..."); - cal.setGregorianChange(new Date(x.getTime() + (24*3600*1000))); + cal.setGregorianChange(new Date(x.getTime() + (24 * 3600 * 1000))); if (!cal.checkDate(2003, SEPTEMBER, 18)) { errln(" " + cal.getMessage()); } @@ -225,11 +230,11 @@ public class GregorianCutoverTest extends IntlTest { Koyomi cal = new Koyomi(); Koyomi cal2 = (Koyomi) cal.clone(); logln("getLeastMaximum should handle cutover year.\n" - +" default cutover date"); - if (!cal.checkLeastMaximum(DAY_OF_YEAR, 365-10)) { + + " default cutover date"); + if (!cal.checkLeastMaximum(DAY_OF_YEAR, 365 - 10)) { errln(" " + cal.getMessage()); } - if (!cal.checkLeastMaximum(WEEK_OF_YEAR, 52-((10+6)/7))) { + if (!cal.checkLeastMaximum(WEEK_OF_YEAR, 52 - ((10 + 6) / 7))) { errln(" " + cal.getMessage()); } // Corrected for 4956232 @@ -261,7 +266,9 @@ public class GregorianCutoverTest extends IntlTest { cal = new Koyomi(); logln("Change the cutover date to 1970/1/5."); - cal.setGregorianChange(new Date(1970-1900, 0, 5)); + @SuppressWarnings("deprecation") + Date d = new Date(1970 - 1900, 0, 5); + cal.setGregorianChange(d); if (!cal.checkLeastMaximum(DAY_OF_YEAR, 356)) { errln(" " + cal.getMessage()); } @@ -287,15 +294,15 @@ public class GregorianCutoverTest extends IntlTest { int hour = 13865672; Koyomi gc1 = new Koyomi(); gc1.clear(); - gc1.set(1, gc1.JANUARY, 1, 0, 0, 0); - gc1.set(gc1.HOUR_OF_DAY, hour); - if (!gc1.checkDate(1582, gc1.OCTOBER, 4)) { + gc1.set(1, JANUARY, 1, 0, 0, 0); + gc1.set(HOUR_OF_DAY, hour); + if (!gc1.checkDate(1582, OCTOBER, 4)) { errln("test case 1: " + gc1.getMessage()); } gc1.clear(); - gc1.set(1, gc1.JANUARY, 1, 0, 0, 0); - gc1.set(gc1.HOUR_OF_DAY, hour + 24); - if (!gc1.checkDate(1582, gc1.OCTOBER, 15)) { + gc1.set(1, JANUARY, 1, 0, 0, 0); + gc1.set(HOUR_OF_DAY, hour + 24); + if (!gc1.checkDate(1582, OCTOBER, 15)) { errln("test case 2: " + gc1.getMessage()); } } diff --git a/jdk/test/java/util/Calendar/JavatimeTest.java b/jdk/test/java/util/Calendar/JavatimeTest.java index 7af6e9d4c03..8f32801a307 100644 --- a/jdk/test/java/util/Calendar/JavatimeTest.java +++ b/jdk/test/java/util/Calendar/JavatimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -28,16 +28,16 @@ * @key randomness */ -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Random; -import java.util.TimeZone; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.ZoneId; import java.time.ZoneOffset; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Random; +import java.util.TimeZone; public class JavatimeTest { @@ -46,10 +46,11 @@ public class JavatimeTest { public static void main(String[] args) throws Throwable { int N = 10000; + @SuppressWarnings("deprecation") long t1970 = new java.util.Date(70, 0, 01).getTime(); Random r = new Random(); for (int i = 0; i < N; i++) { - int days = r.nextInt(50) * 365 + r.nextInt(365); + int days = r.nextInt(50) * 365 + r.nextInt(365); long secs = t1970 + days * 86400 + r.nextInt(86400); int nanos = r.nextInt(NANOS_PER_SECOND); int nanos_ms = nanos / 1000000 * 1000000; // millis precision @@ -61,15 +62,15 @@ public class JavatimeTest { ///////////// java.util.Date ///////////////////////// Date jud = new java.util.Date(millis); Instant inst0 = jud.toInstant(); - if (jud.getTime() != inst0.toEpochMilli() || - !jud.equals(Date.from(inst0))) { + if (jud.getTime() != inst0.toEpochMilli() + || !jud.equals(Date.from(inst0))) { System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); throw new RuntimeException("FAILED: j.u.d -> instant -> j.u.d"); } // roundtrip only with millis precision Date jud0 = Date.from(inst_ms); - if (jud0.getTime() != inst_ms.toEpochMilli() || - !inst_ms.equals(jud0.toInstant())) { + if (jud0.getTime() != inst_ms.toEpochMilli() + || !inst_ms.equals(jud0.toInstant())) { System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); throw new RuntimeException("FAILED: instant -> j.u.d -> instant"); } @@ -82,8 +83,8 @@ public class JavatimeTest { cal.setMinimalDaysInFirstWeek(4); cal.setTimeInMillis(millis); ZonedDateTime zdt0 = cal.toZonedDateTime(); - if (cal.getTimeInMillis() != zdt0.toInstant().toEpochMilli() || - !cal.equals(GregorianCalendar.from(zdt0))) { + if (cal.getTimeInMillis() != zdt0.toInstant().toEpochMilli() + || !cal.equals(GregorianCalendar.from(zdt0))) { System.out.println("cal:" + cal); System.out.println("zdt:" + zdt0); System.out.println("calNew:" + GregorianCalendar.from(zdt0)); @@ -97,8 +98,8 @@ public class JavatimeTest { } ZonedDateTime zdt = ZonedDateTime.of(ldt_ms, ZoneId.systemDefault()); GregorianCalendar cal0 = GregorianCalendar.from(zdt); - if (zdt.toInstant().toEpochMilli() != cal0.getTimeInMillis() || - !zdt.equals(GregorianCalendar.from(zdt).toZonedDateTime())) { + if (zdt.toInstant().toEpochMilli() != cal0.getTimeInMillis() + || !zdt.equals(GregorianCalendar.from(zdt).toZonedDateTime())) { System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); throw new RuntimeException("FAILED: zdt -> gcal -> zdt"); } @@ -107,12 +108,12 @@ public class JavatimeTest { ///////////// java.util.TimeZone ///////////////////////// for (String zidStr : TimeZone.getAvailableIDs()) { // TBD: tzdt intergration - if (zidStr.startsWith("SystemV") || - zidStr.contains("Riyadh8") || - zidStr.equals("US/Pacific-New") || - zidStr.equals("EST") || - zidStr.equals("HST") || - zidStr.equals("MST")) { + if (zidStr.startsWith("SystemV") + || zidStr.contains("Riyadh8") + || zidStr.equals("US/Pacific-New") + || zidStr.equals("EST") + || zidStr.equals("HST") + || zidStr.equals("MST")) { continue; } ZoneId zid = ZoneId.of(zidStr, ZoneId.SHORT_IDS); @@ -121,9 +122,9 @@ public class JavatimeTest { } TimeZone tz = TimeZone.getTimeZone(zidStr); // no round-trip for alias and "GMT" - if (!tz.equals(TimeZone.getTimeZone(tz.toZoneId())) && - !ZoneId.SHORT_IDS.containsKey(zidStr) && - !zidStr.startsWith("GMT")) { + if (!tz.equals(TimeZone.getTimeZone(tz.toZoneId())) + && !ZoneId.SHORT_IDS.containsKey(zidStr) + && !zidStr.startsWith("GMT")) { throw new RuntimeException("FAILED: tz -> zid -> tz :" + zidStr); } } diff --git a/jdk/test/java/util/Calendar/Koyomi.java b/jdk/test/java/util/Calendar/Koyomi.java index 8eec03b5de4..90f2eda0867 100644 --- a/jdk/test/java/util/Calendar/Koyomi.java +++ b/jdk/test/java/util/Calendar/Koyomi.java @@ -21,8 +21,6 @@ * questions. */ -import static java.util.Calendar.*; - import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; @@ -30,7 +28,9 @@ import java.util.TimeZone; /** * GregorianCalendar subclass for testing. */ +@SuppressWarnings("serial") public class Koyomi extends GregorianCalendar { + static final String[] FIELD_NAMES = { "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", @@ -78,7 +78,7 @@ public class Koyomi extends GregorianCalendar { StringBuilder sb = new StringBuilder(); sb.append(internalGet(ERA) == 0 ? "BCE " : ""); sb.append(internalGet(YEAR)).append('-'); - sb.append(internalGet(MONTH)+1).append('-'); + sb.append(internalGet(MONTH) + 1).append('-'); sb.append(internalGet(DAY_OF_MONTH)); return sb.toString(); } @@ -98,7 +98,7 @@ public class Koyomi extends GregorianCalendar { sb.append(ms); int offset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); offset /= 60000; - offset = (offset/60) * 100 + (offset%60); + offset = (offset / 60) * 100 + (offset % 60); if (offset >= 0) { sb.append('+'); } else { @@ -187,8 +187,8 @@ public class Koyomi extends GregorianCalendar { boolean checkActualMaximum(int field, int expectedValue) { int val; if ((val = getActualMaximum(field)) != expectedValue) { - appendMessage("getActualMaximum("+FIELD_NAMES[field]+"): got " + val - + " expected " + expectedValue); + appendMessage("getActualMaximum(" + FIELD_NAMES[field] + "): got " + val + + " expected " + expectedValue); } return getStatus(); } @@ -196,8 +196,8 @@ public class Koyomi extends GregorianCalendar { boolean checkLeastMaximum(int field, int expectedValue) { int val; if ((val = getLeastMaximum(field)) != expectedValue) { - appendMessage("getLeastMaximum("+FIELD_NAMES[field]+"): got " + val - + " expected " + expectedValue); + appendMessage("getLeastMaximum(" + FIELD_NAMES[field] + "): got " + val + + " expected " + expectedValue); } return getStatus(); } @@ -205,8 +205,8 @@ public class Koyomi extends GregorianCalendar { boolean checkActualMinimum(int field, int expectedValue) { int val; if ((val = getActualMinimum(field)) != expectedValue) { - appendMessage("getActualMinimum("+FIELD_NAMES[field]+"): got " + val - + " expected " + expectedValue); + appendMessage("getActualMinimum(" + FIELD_NAMES[field] + "): got " + val + + " expected " + expectedValue); } return getStatus(); } @@ -214,8 +214,8 @@ public class Koyomi extends GregorianCalendar { boolean checkGreatestMinimum(int field, int expectedValue) { int val; if ((val = getGreatestMinimum(field)) != expectedValue) { - appendMessage("getGreatestMinimum("+FIELD_NAMES[field]+"): got " + val - + " expected " + expectedValue); + appendMessage("getGreatestMinimum(" + FIELD_NAMES[field] + "): got " + val + + " expected " + expectedValue); } return getStatus(); } @@ -238,7 +238,7 @@ public class Koyomi extends GregorianCalendar { } boolean checkDateTime(int year, int month, int dayOfMonth, - int hourOfDay, int minute, int second, int ms) { + int hourOfDay, int minute, int second, int ms) { initTest(); checkFieldValue(YEAR, year); checkFieldValue(MONTH, month); @@ -270,8 +270,8 @@ public class Koyomi extends GregorianCalendar { boolean checkFieldValue(int field, int expectedValue) { int val; if ((val = get(field)) != expectedValue) { - appendMessage("get(" + FIELD_NAMES[field] + "): got " + val + - ", expected " + expectedValue + "; "); + appendMessage("get(" + FIELD_NAMES[field] + "): got " + val + + ", expected " + expectedValue + "; "); return false; } return true; @@ -280,8 +280,8 @@ public class Koyomi extends GregorianCalendar { boolean checkInternalFieldValue(int field, int expectedValue) { int val; if ((val = internalGet(field)) != expectedValue) { - appendMessage("internalGet(" + FIELD_NAMES[field] + "): got " + val + - ", expected " + expectedValue + "; "); + appendMessage("internalGet(" + FIELD_NAMES[field] + "): got " + val + + ", expected " + expectedValue + "; "); return false; } return true; diff --git a/jdk/test/java/util/Calendar/NonLenientTest.java b/jdk/test/java/util/Calendar/NonLenientTest.java index 6c42c594932..357cf0e95c0 100644 --- a/jdk/test/java/util/Calendar/NonLenientTest.java +++ b/jdk/test/java/util/Calendar/NonLenientTest.java @@ -28,7 +28,10 @@ * @library /java/text/testlib */ -import java.util.*; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; import static java.util.Calendar.*; @@ -129,7 +132,6 @@ public class NonLenientTest extends IntlTest { validate(cal, "6th Sunday in Jan 2003"); } - /** * 4726030: GregorianCalendar doesn't check invalid dates in non-lenient */ @@ -146,34 +148,34 @@ public class NonLenientTest extends IntlTest { */ public void Test4147269() { Koyomi calendar = getNonLenient(); - Date date = (new GregorianCalendar(1996,0,3)).getTime(); + Date date = (new GregorianCalendar(1996, 0, 3)).getTime(); - for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + for (int field = 0; field < FIELD_COUNT; field++) { calendar.setTime(date); int max = calendar.getActualMaximum(field); - int value = max+1; + int value = max + 1; calendar.set(field, value); try { calendar.computeTime(); // call method under test - errln("Test failed with field " + calendar.getFieldName(field) - + "\n\tdate before: " + date - + "\n\tdate after: " + calendar.getTime() - + "\n\tvalue: " + value + " (max = " + max +")"); + errln("Test failed with field " + Koyomi.getFieldName(field) + + "\n\tdate before: " + date + + "\n\tdate after: " + calendar.getTime() + + "\n\tvalue: " + value + " (max = " + max + ")"); } catch (IllegalArgumentException e) { } } - for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + for (int field = 0; field < FIELD_COUNT; field++) { calendar.setTime(date); int min = calendar.getActualMinimum(field); - int value = min-1; + int value = min - 1; calendar.set(field, value); try { calendar.computeTime(); // call method under test - errln("Test failed with field " + calendar.getFieldName(field) - + "\n\tdate before: " + date - + "\n\tdate after: " + calendar.getTime() - + "\n\tvalue: " + value + " (min = " + min +")"); + errln("Test failed with field " + Koyomi.getFieldName(field) + + "\n\tdate before: " + date + + "\n\tdate after: " + calendar.getTime() + + "\n\tvalue: " + value + " (min = " + min + ")"); } catch (IllegalArgumentException e) { } } @@ -194,17 +196,17 @@ public class NonLenientTest extends IntlTest { // In non-lenient, calendar field values that have beeb set by // user shouldn't be modified. int[] afterFields = cal.getFields(); - for (int i = 0; i < Calendar.FIELD_COUNT; i++) { + for (int i = 0; i < FIELD_COUNT; i++) { if (cal.isSet(i) && originalFields[i] != afterFields[i]) { - errln(" complete() modified fields[" + cal.getFieldName(i) + "] got " - + afterFields[i] + ", expected " + originalFields[i]); + errln(" complete() modified fields[" + Koyomi.getFieldName(i) + "] got " + + afterFields[i] + ", expected " + originalFields[i]); } } // In non-lenient, set state of fields shouldn't be modified. int afterSetFields = cal.getSetStateFields(); if (setFields != afterSetFields) { errln(" complate() modified set states: before 0x" + toHex(setFields) - + ", after 0x"+ toHex(afterSetFields)); + + ", after 0x" + toHex(afterSetFields)); } } diff --git a/jdk/test/java/util/Calendar/ZoneOffsets.java b/jdk/test/java/util/Calendar/ZoneOffsets.java index 147df337497..a0ddfde625c 100644 --- a/jdk/test/java/util/Calendar/ZoneOffsets.java +++ b/jdk/test/java/util/Calendar/ZoneOffsets.java @@ -28,12 +28,20 @@ * taken into account for time calculations. */ -import java.util.*; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + import static java.util.GregorianCalendar.*; public class ZoneOffsets { + // This TimeZone always returns the dstOffset value. + @SuppressWarnings("serial") private static class TestTimeZone extends TimeZone { + private int gmtOffset; private int dstOffset; @@ -44,7 +52,7 @@ public class ZoneOffsets { } public int getOffset(int era, int year, int month, int day, - int dayOfWeek, int milliseconds) { + int dayOfWeek, int milliseconds) { return gmtOffset + dstOffset; } @@ -80,22 +88,20 @@ public class ZoneOffsets { private static Locale[] locales = { Locale.getDefault(), new Locale("th", "TH"), - new Locale("ja", "JP", "JP"), - }; + new Locale("ja", "JP", "JP")}; private static final int HOUR = 60 * 60 * 1000; private static int[][] offsets = { - { 0, 0 }, - { 0, HOUR }, - { 0, 2 * HOUR }, - { -8 * HOUR, 0 }, - { -8 * HOUR, HOUR }, - { -8 * HOUR, 2 * HOUR }, - { 9 * HOUR, 0 }, - { 9 * HOUR, HOUR }, - { 9 * HOUR, 2 * HOUR }, - }; + {0, 0}, + {0, HOUR}, + {0, 2 * HOUR}, + {-8 * HOUR, 0}, + {-8 * HOUR, HOUR}, + {-8 * HOUR, 2 * HOUR}, + {9 * HOUR, 0}, + {9 * HOUR, HOUR}, + {9 * HOUR, 2 * HOUR}}; public static void main(String[] args) { for (int l = 0; l < locales.length; l++) { @@ -121,17 +127,17 @@ public class ZoneOffsets { private static void test(Locale loc, int gmtOffset, int dstOffset) { TimeZone tz1 = new TestTimeZone(gmtOffset, - "GMT" + (gmtOffset/HOUR) + "." + (dstOffset/HOUR), - dstOffset); + "GMT" + (gmtOffset / HOUR) + "." + (dstOffset / HOUR), + dstOffset); int someDifferentOffset = gmtOffset + 2 * HOUR; TimeZone tz2 = new TestTimeZone(someDifferentOffset, - "GMT"+ (someDifferentOffset/HOUR) + "." + (dstOffset/HOUR), - dstOffset); + "GMT" + (someDifferentOffset / HOUR) + "." + (dstOffset / HOUR), + dstOffset); int someDifferentDSTOffset = dstOffset == 2 * HOUR ? HOUR : dstOffset + HOUR; TimeZone tz3 = new TestTimeZone(gmtOffset, - "GMT"+ (gmtOffset/HOUR) + "." + (someDifferentDSTOffset/HOUR), - someDifferentDSTOffset); + "GMT" + (gmtOffset / HOUR) + "." + (someDifferentDSTOffset / HOUR), + someDifferentDSTOffset); // cal1 is the base line. Calendar cal1 = Calendar.getInstance(tz1, loc); @@ -225,7 +231,7 @@ public class ZoneOffsets { private static void error(String msg, Locale loc, Calendar cal2, int gmtOffset, int dstOffset, long t1) { System.err.println(cal2); throw new RuntimeException(msg + ": Locale=" + loc - + ", gmtOffset=" + gmtOffset + ", dstOffset=" + dstOffset - + ", cal1 time=" + t1 + ", cal2 time=" + cal2.getTime().getTime()); + + ", gmtOffset=" + gmtOffset + ", dstOffset=" + dstOffset + + ", cal1 time=" + t1 + ", cal2 time=" + cal2.getTime().getTime()); } } diff --git a/jdk/test/java/util/Calendar/bug4372743.java b/jdk/test/java/util/Calendar/bug4372743.java index 1800ebc002a..6d380e523e2 100644 --- a/jdk/test/java/util/Calendar/bug4372743.java +++ b/jdk/test/java/util/Calendar/bug4372743.java @@ -28,9 +28,8 @@ * @library /java/text/testlib */ -import java.io.*; -import java.util.*; -import java.text.*; +import java.util.GregorianCalendar; +import java.util.TimeZone; import static java.util.GregorianCalendar.*; @@ -41,51 +40,50 @@ public class bug4372743 extends IntlTest { } private int[][] data = { - {AD, 2, MARCH}, - {AD, 2, FEBRUARY}, - {AD, 2, JANUARY}, - {AD, 1, DECEMBER}, - {AD, 1, NOVEMBER}, - {AD, 1, OCTOBER}, - {AD, 1, SEPTEMBER}, - {AD, 1, AUGUST}, - {AD, 1, JULY}, - {AD, 1, JUNE}, - {AD, 1, MAY}, - {AD, 1, APRIL}, - {AD, 1, MARCH}, - {AD, 1, FEBRUARY}, - {AD, 1, JANUARY}, - {BC, 1, DECEMBER}, - {BC, 1, NOVEMBER}, - {BC, 1, OCTOBER}, - {BC, 1, SEPTEMBER}, - {BC, 1, AUGUST}, - {BC, 1, JULY}, - {BC, 1, JUNE}, - {BC, 1, MAY}, - {BC, 1, APRIL}, - {BC, 1, MARCH}, - {BC, 1, FEBRUARY}, - {BC, 1, JANUARY}, - {BC, 2, DECEMBER}, - {BC, 2, NOVEMBER}, - {BC, 2, OCTOBER}, - }; + {AD, 2, MARCH}, + {AD, 2, FEBRUARY}, + {AD, 2, JANUARY}, + {AD, 1, DECEMBER}, + {AD, 1, NOVEMBER}, + {AD, 1, OCTOBER}, + {AD, 1, SEPTEMBER}, + {AD, 1, AUGUST}, + {AD, 1, JULY}, + {AD, 1, JUNE}, + {AD, 1, MAY}, + {AD, 1, APRIL}, + {AD, 1, MARCH}, + {AD, 1, FEBRUARY}, + {AD, 1, JANUARY}, + {BC, 1, DECEMBER}, + {BC, 1, NOVEMBER}, + {BC, 1, OCTOBER}, + {BC, 1, SEPTEMBER}, + {BC, 1, AUGUST}, + {BC, 1, JULY}, + {BC, 1, JUNE}, + {BC, 1, MAY}, + {BC, 1, APRIL}, + {BC, 1, MARCH}, + {BC, 1, FEBRUARY}, + {BC, 1, JANUARY}, + {BC, 2, DECEMBER}, + {BC, 2, NOVEMBER}, + {BC, 2, OCTOBER}}; private int tablesize = data.length; private void check(GregorianCalendar gc, int index) { if (gc.get(ERA) != data[index][ERA]) { - errln("Invalid era :" + gc.get(ERA) + - ", expected :" + data[index][ERA]); + errln("Invalid era :" + gc.get(ERA) + + ", expected :" + data[index][ERA]); } if (gc.get(YEAR) != data[index][YEAR]) { - errln("Invalid year :" + gc.get(YEAR) + - ", expected :" + data[index][YEAR]); + errln("Invalid year :" + gc.get(YEAR) + + ", expected :" + data[index][YEAR]); } if (gc.get(MONTH) != data[index][MONTH]) { - errln("Invalid month :" + gc.get(MONTH) + - ", expected :" + data[index][MONTH]); + errln("Invalid month :" + gc.get(MONTH) + + ", expected :" + data[index][MONTH]); } } @@ -97,36 +95,35 @@ public class bug4372743 extends IntlTest { TimeZone.setDefault(TimeZone.getTimeZone("PST")); /* Set March 3, A.D. 2 */ - gc = new GregorianCalendar(2, MARCH, 3); + gc = new GregorianCalendar(2, MARCH, 3); for (int i = 0; i < tablesize; i++) { check(gc, i); - gc.add(gc.MONTH, -1); + gc.add(MONTH, -1); } /* Again, Set March 3, A.D. 2 */ - gc = new GregorianCalendar(2, MARCH, 3); - for (int i = 0; i < tablesize; i+=7) { + gc = new GregorianCalendar(2, MARCH, 3); + for (int i = 0; i < tablesize; i += 7) { check(gc, i); - gc.add(gc.MONTH, -7); + gc.add(MONTH, -7); } /* Set March 10, 2 B.C. */ - gc = new GregorianCalendar(2, OCTOBER, 10); - gc.add(gc.YEAR, -3); - for (int i = tablesize -1; i >= 0; i--) { + gc = new GregorianCalendar(2, OCTOBER, 10); + gc.add(YEAR, -3); + for (int i = tablesize - 1; i >= 0; i--) { check(gc, i); - gc.add(gc.MONTH, 1); + gc.add(MONTH, 1); } /* Again, Set March 10, 2 B.C. */ - gc = new GregorianCalendar(2, OCTOBER, 10); - gc.add(gc.YEAR, -3); - for (int i = tablesize -1; i >= 0; i-=8) { + gc = new GregorianCalendar(2, OCTOBER, 10); + gc.add(YEAR, -3); + for (int i = tablesize - 1; i >= 0; i -= 8) { check(gc, i); - gc.add(gc.MONTH, 8); + gc.add(MONTH, 8); } - } - finally { + } finally { TimeZone.setDefault(saveZone); } } diff --git a/jdk/test/java/util/Calendar/bug4401223.java b/jdk/test/java/util/Calendar/bug4401223.java index fbd9e29a8f6..3123181e1a1 100644 --- a/jdk/test/java/util/Calendar/bug4401223.java +++ b/jdk/test/java/util/Calendar/bug4401223.java @@ -28,7 +28,10 @@ * @library /java/text/testlib */ -import java.util.*; +import java.util.Date; +import java.util.GregorianCalendar; + +import static java.util.GregorianCalendar.*; public class bug4401223 extends IntlTest { @@ -37,11 +40,12 @@ public class bug4401223 extends IntlTest { String s = null; try { - Date date = new Date(2000-1900, Calendar.FEBRUARY, 29); + @SuppressWarnings("deprecation") + Date date = new Date(2000 - 1900, FEBRUARY, 29); GregorianCalendar gc = new GregorianCalendar(); gc.setTime(date); gc.setLenient(false); - gc.set(Calendar.YEAR, 2001); + gc.set(YEAR, 2001); s = "02/29/00 & set(YEAR,2001) = " + gc.getTime().toString(); } catch (Exception ex) { status++; @@ -59,16 +63,17 @@ public class bug4401223 extends IntlTest { String s = null; try { - Date date = new Date(2000-1900, Calendar.DECEMBER, 31); + @SuppressWarnings("deprecation") + Date date = new Date(2000 - 1900, DECEMBER, 31); GregorianCalendar gc = new GregorianCalendar(); gc.setTime(date); gc.setLenient(false); - gc.set(Calendar.YEAR, 2001); + gc.set(YEAR, 2001); - if (gc.get(Calendar.YEAR) != 2001 || - gc.get(Calendar.MONTH) != Calendar.DECEMBER || - gc.get(Calendar.DATE) != 31 || - gc.get(Calendar.DAY_OF_YEAR) != 365) { + if (gc.get(YEAR) != 2001 + || gc.get(MONTH) != DECEMBER + || gc.get(DATE) != 31 + || gc.get(DAY_OF_YEAR) != 365) { status++; s = "Wrong Date : 12/31/00 & set(YEAR,2001) ---> " + gc.getTime().toString(); } else { diff --git a/jdk/test/java/util/Calendar/bug4514831.java b/jdk/test/java/util/Calendar/bug4514831.java index 9d635e26167..f0c34a8aa2a 100644 --- a/jdk/test/java/util/Calendar/bug4514831.java +++ b/jdk/test/java/util/Calendar/bug4514831.java @@ -27,7 +27,12 @@ * @summary Confirm that GregorianCalendar.roll() works properly during transition from Daylight Saving Time to Standard Time. */ -import java.util.*; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + +import static java.util.GregorianCalendar.*; + public class bug4514831 { @@ -36,52 +41,52 @@ public class bug4514831 { TimeZone savedTimeZone = TimeZone.getDefault(); boolean err = false; - String golden_data1 ="27-28 28-29 29-30 30-31 31-1 1-2 2-3 "; - String golden_data2 ="27-28 28-29 29-30 30-31 31-25 25-26 26-27 "; - String golden_data3 ="1-8 8-15 15-22 22-29 29-1 1-8 8-15 "; + String golden_data1 = "27-28 28-29 29-30 30-31 31-1 1-2 2-3 "; + String golden_data2 = "27-28 28-29 29-30 30-31 31-25 25-26 26-27 "; + String golden_data3 = "1-8 8-15 15-22 22-29 29-1 1-8 8-15 "; try { Locale.setDefault(Locale.US); TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific")); String test_roll = ""; - GregorianCalendar c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27); - for (int i=0; i < 7; i++) { - test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-"; - c_roll.roll(c_roll.DAY_OF_YEAR, true); - test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " "; + GregorianCalendar c_roll = new GregorianCalendar(2001, OCTOBER, 27); + for (int i = 0; i < 7; i++) { + test_roll += c_roll.get(DAY_OF_MONTH) + "-"; + c_roll.roll(DAY_OF_YEAR, true); + test_roll += c_roll.get(DAY_OF_MONTH) + " "; } if (!test_roll.equals(golden_data1)) { err = true; - System.err.println("Wrong roll(DAY_OF_YEAR) transition: got "+ - test_roll + "expected " + golden_data1); + System.err.println("Wrong roll(DAY_OF_YEAR) transition: got " + + test_roll + "expected " + golden_data1); } test_roll = ""; - c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27); - c_roll.setFirstDayOfWeek(Calendar.THURSDAY); - for (int i=0; i < 7; i++) { - test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-"; - c_roll.roll(c_roll.DAY_OF_WEEK, true); - test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " "; + c_roll = new GregorianCalendar(2001, OCTOBER, 27); + c_roll.setFirstDayOfWeek(THURSDAY); + for (int i = 0; i < 7; i++) { + test_roll += c_roll.get(DAY_OF_MONTH) + "-"; + c_roll.roll(DAY_OF_WEEK, true); + test_roll += c_roll.get(DAY_OF_MONTH) + " "; } if (!test_roll.equals(golden_data2)) { err = true; - System.err.println("Wrong roll(DAY_OF_WEEK) transition: got "+ - test_roll + "expected " + golden_data2); + System.err.println("Wrong roll(DAY_OF_WEEK) transition: got " + + test_roll + "expected " + golden_data2); } test_roll = ""; - c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 1); - for (int i=0; i < 7; i++) { - test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-"; - c_roll.roll(c_roll.DAY_OF_WEEK_IN_MONTH, true); - test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " "; + c_roll = new GregorianCalendar(2001, OCTOBER, 1); + for (int i = 0; i < 7; i++) { + test_roll += c_roll.get(DAY_OF_MONTH) + "-"; + c_roll.roll(DAY_OF_WEEK_IN_MONTH, true); + test_roll += c_roll.get(DAY_OF_MONTH) + " "; } if (!test_roll.equals(golden_data3)) { err = true; - System.err.println("Wrong roll(DAY_OF_WEEK_IN_MONTH) transition: got "+ - test_roll + "expected " + golden_data3); + System.err.println("Wrong roll(DAY_OF_WEEK_IN_MONTH) transition: got " + + test_roll + "expected " + golden_data3); } } finally { Locale.setDefault(savedLocale); diff --git a/jdk/test/java/util/Date/Bug4955000.java b/jdk/test/java/util/Date/Bug4955000.java index c94b23868ca..4339f848f58 100644 --- a/jdk/test/java/util/Date/Bug4955000.java +++ b/jdk/test/java/util/Date/Bug4955000.java @@ -28,11 +28,15 @@ * same date/time. Both are new implementations in 1.5. */ -import java.util.*; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + import static java.util.GregorianCalendar.*; @SuppressWarnings("deprecation") public class Bug4955000 { + // Tests for Date.UTC(), derived from JCK // Date.miscTests.Date1025 and Date2015 public static void main(String[] args) { @@ -51,17 +55,17 @@ public class Bug4955000 { }; for (int i = 0; i < years1.length; i++) { gc.clear(); - gc.set(years1[i], gc.JANUARY, 1); + gc.set(years1[i], JANUARY, 1); long t = gc.getTimeInMillis(); - long utc = Date.UTC(years1[i] - 1900, 1-1, 1, - 0, 0, 0); // Jan 1 00:00:00 + long utc = Date.UTC(years1[i] - 1900, 1 - 1, 1, + 0, 0, 0); // Jan 1 00:00:00 if (t != utc) { - throw new RuntimeException("t (" + t + ") != utc (" + utc +")"); + throw new RuntimeException("t (" + t + ") != utc (" + utc + ")"); } } // Date2015 - int years[] = { + int[] years = { gc.getGreatestMinimum(YEAR), gc.getGreatestMinimum(YEAR) + 1, -1, @@ -71,47 +75,47 @@ public class Bug4955000 { gc.getLeastMaximum(YEAR) }; - int months[] = { + int[] months = { gc.getMinimum(MONTH), gc.getMinimum(MONTH) + 1, gc.getMaximum(MONTH) - 1, gc.getMaximum(MONTH) }; - int dates[] = { + int[] dates = { gc.getMinimum(DAY_OF_MONTH), gc.getMinimum(DAY_OF_MONTH) + 1, gc.getMaximum(DAY_OF_MONTH) - 1, gc.getMaximum(DAY_OF_MONTH) }; - int hs[] = { + int[] hs = { gc.getMinimum(HOUR), gc.getMinimum(HOUR) + 1, gc.getMaximum(HOUR) - 1, gc.getMaximum(HOUR) }; - int ms[] = { + int[] ms = { gc.getMinimum(MINUTE), gc.getMinimum(MINUTE) + 1, gc.getMaximum(MINUTE) - 1, gc.getMaximum(MINUTE) }; - int ss[] = { + int[] ss = { gc.getMinimum(SECOND), gc.getMinimum(SECOND) + 1, gc.getMaximum(SECOND) - 1, gc.getMaximum(SECOND) }; - for(int i = 0; i < years.length; i++) { - for(int j = 0; j < months.length; j++) { - for(int k = 0; k < dates.length; k++) { - for(int m = 0; m < hs.length; m++) { - for(int n = 0; n < ms.length; n++) { - for(int p = 0; p < ss.length; p++) { + for (int i = 0; i < years.length; i++) { + for (int j = 0; j < months.length; j++) { + for (int k = 0; k < dates.length; k++) { + for (int m = 0; m < hs.length; m++) { + for (int n = 0; n < ms.length; n++) { + for (int p = 0; p < ss.length; p++) { int year = years[i] - 1900; int month = months[j]; int date = dates[k]; @@ -120,7 +124,7 @@ public class Bug4955000 { int seconds = ss[p]; long result = Date.UTC(year, month, date, - hours, minutes, seconds); + hours, minutes, seconds); gc.clear(); gc.set(year + 1900, month, date, hours, minutes, seconds); @@ -129,7 +133,7 @@ public class Bug4955000 { if (expected != result) { throw new RuntimeException("expected (" + expected - + ") != result (" + result +")"); + + ") != result (" + result + ")"); } } } diff --git a/jdk/test/java/util/Locale/Bug4175998Test.java b/jdk/test/java/util/Locale/Bug4175998Test.java index e890ae9e667..a5ad1dd3abd 100644 --- a/jdk/test/java/util/Locale/Bug4175998Test.java +++ b/jdk/test/java/util/Locale/Bug4175998Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -24,6 +24,7 @@ /* * @test * @summary test ISO639-2 language codes + * @library /java/text/testlib * @compile -encoding ascii Bug4175998Test.java * @run main Bug4175998Test * @bug 4175998 @@ -43,14 +44,13 @@ */ import java.util.*; -import java.io.*; /** * Bug4175998Test verifies that the following bug has been fixed: * Bug 4175998 - The java.util.Locale.getISO3Language() returns wrong result for a locale with * language code 'ta'(Tamil). */ -public class Bug4175998Test extends LocaleTestFmwk { +public class Bug4175998Test extends IntlTest { public static void main(String[] args) throws Exception { new Bug4175998Test().run(args); //generateTables(); //uncomment this to regenerate data tables diff --git a/jdk/test/java/util/Locale/Bug4184873Test.java b/jdk/test/java/util/Locale/Bug4184873Test.java index 478a67fbf8b..3dadf1fe3a9 100644 --- a/jdk/test/java/util/Locale/Bug4184873Test.java +++ b/jdk/test/java/util/Locale/Bug4184873Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -23,6 +23,7 @@ /* @test @summary test that locale invariants are preserved across serialization + @library /java/text/testlib @run main Bug4184873Test @bug 4184873 */ @@ -63,7 +64,7 @@ import java.io.*; /** * A Locale can never contain the following language codes: he, yi or id. */ -public class Bug4184873Test extends LocaleTestFmwk { +public class Bug4184873Test extends IntlTest { public static void main(String[] args) throws Exception { if (args.length == 1 && args[0].equals("prepTest")) { prepTest(); diff --git a/jdk/test/java/util/Locale/Bug8001562.java b/jdk/test/java/util/Locale/Bug8001562.java index 1a18ac58a97..be53600a84d 100644 --- a/jdk/test/java/util/Locale/Bug8001562.java +++ b/jdk/test/java/util/Locale/Bug8001562.java @@ -30,37 +30,46 @@ * @run main Bug8001562 */ -import java.text.*; -import java.util.*; +import java.text.BreakIterator; +import java.text.Collator; +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; public class Bug8001562 { - static final String[] jdk7availTags = { - "ar", "ar-AE", "ar-BH", "ar-DZ", "ar-EG", "ar-IQ", "ar-JO", "ar-KW", - "ar-LB", "ar-LY", "ar-MA", "ar-OM", "ar-QA", "ar-SA", "ar-SD", "ar-SY", - "ar-TN", "ar-YE", "be", "be-BY", "bg", "bg-BG", "ca", "ca-ES", "cs", - "cs-CZ", "da", "da-DK", "de", "de-AT", "de-CH", "de-DE", "de-LU", "el", - "el-CY", "el-GR", "en", "en-AU", "en-CA", "en-GB", "en-IE", "en-IN", - "en-MT", "en-NZ", "en-PH", "en-SG", "en-US", "en-ZA", "es", "es-AR", - "es-BO", "es-CL", "es-CO", "es-CR", "es-DO", "es-EC", "es-ES", "es-GT", - "es-HN", "es-MX", "es-NI", "es-PA", "es-PE", "es-PR", "es-PY", "es-SV", - "es-US", "es-UY", "es-VE", "et", "et-EE", "fi", "fi-FI", "fr", "fr-BE", - "fr-CA", "fr-CH", "fr-FR", "fr-LU", "ga", "ga-IE", "he", "he-IL", - "hi-IN", "hr", "hr-HR", "hu", "hu-HU", "id", "id-ID", "is", "is-IS", - "it", "it-CH", "it-IT", "ja", "ja-JP", - "ja-JP-u-ca-japanese-x-lvariant-JP", "ko", "ko-KR", "lt", "lt-LT", "lv", - "lv-LV", "mk", "mk-MK", "ms", "ms-MY", "mt", "mt-MT", "nl", "nl-BE", - "nl-NL", "no", "no-NO", "no-NO-x-lvariant-NY", "pl", "pl-PL", "pt", - "pt-BR", "pt-PT", "ro", "ro-RO", "ru", "ru-RU", "sk", "sk-SK", "sl", - "sl-SI", "sq", "sq-AL", "sr", "sr-BA", "sr-CS", "sr-Latn", "sr-Latn-BA", - "sr-Latn-ME", "sr-Latn-RS", "sr-ME", "sr-RS", "sv", "sv-SE", "th", - "th-TH", "th-TH-u-nu-thai-x-lvariant-TH", "tr", "tr-TR", "uk", "uk-UA", - "vi", "vi-VN", "zh", "zh-CN", "zh-HK", "zh-SG", "zh-TW", }; - static List jdk7availLocs = new ArrayList<>(); + static final List jdk7availTags = List.of( + "ar", "ar-AE", "ar-BH", "ar-DZ", "ar-EG", "ar-IQ", "ar-JO", "ar-KW", + "ar-LB", "ar-LY", "ar-MA", "ar-OM", "ar-QA", "ar-SA", "ar-SD", "ar-SY", + "ar-TN", "ar-YE", "be", "be-BY", "bg", "bg-BG", "ca", "ca-ES", "cs", + "cs-CZ", "da", "da-DK", "de", "de-AT", "de-CH", "de-DE", "de-LU", "el", + "el-CY", "el-GR", "en", "en-AU", "en-CA", "en-GB", "en-IE", "en-IN", + "en-MT", "en-NZ", "en-PH", "en-SG", "en-US", "en-ZA", "es", "es-AR", + "es-BO", "es-CL", "es-CO", "es-CR", "es-DO", "es-EC", "es-ES", "es-GT", + "es-HN", "es-MX", "es-NI", "es-PA", "es-PE", "es-PR", "es-PY", "es-SV", + "es-US", "es-UY", "es-VE", "et", "et-EE", "fi", "fi-FI", "fr", "fr-BE", + "fr-CA", "fr-CH", "fr-FR", "fr-LU", "ga", "ga-IE", "he", "he-IL", + "hi-IN", "hr", "hr-HR", "hu", "hu-HU", "id", "id-ID", "is", "is-IS", + "it", "it-CH", "it-IT", "ja", "ja-JP", + "ja-JP-u-ca-japanese-x-lvariant-JP", "ko", "ko-KR", "lt", "lt-LT", "lv", + "lv-LV", "mk", "mk-MK", "ms", "ms-MY", "mt", "mt-MT", "nl", "nl-BE", + "nl-NL", "no", "no-NO", "no-NO-x-lvariant-NY", "pl", "pl-PL", "pt", + "pt-BR", "pt-PT", "ro", "ro-RO", "ru", "ru-RU", "sk", "sk-SK", "sl", + "sl-SI", "sq", "sq-AL", "sr", "sr-BA", "sr-CS", "sr-Latn", "sr-Latn-BA", + "sr-Latn-ME", "sr-Latn-RS", "sr-ME", "sr-RS", "sv", "sv-SE", "th", + "th-TH", "th-TH-u-nu-thai-x-lvariant-TH", "tr", "tr-TR", "uk", "uk-UA", + "vi", "vi-VN", "zh", "zh-CN", "zh-HK", "zh-SG", "zh-TW"); + static List jdk7availLocs; + static { - for (String locStr : jdk7availTags) { - jdk7availLocs.add(Locale.forLanguageTag(locStr)); - } + jdk7availLocs = jdk7availTags.stream() + .map(Locale::forLanguageTag) + .collect(Collectors.toList()); } public static void main(String[] args) { @@ -86,13 +95,13 @@ public class Bug8001562 { diffLocale(Locale.class, avail); } - static void diffLocale(Class c, List locs) { + static void diffLocale(Class c, List locs) { String diff = ""; System.out.printf("Only in target locales (%s.getAvailableLocales()): ", c.getSimpleName()); for (Locale l : locs) { if (!jdk7availLocs.contains(l)) { - diff += "\""+l.toLanguageTag()+"\", "; + diff += "\"" + l.toLanguageTag() + "\", "; } } System.out.println(diff); @@ -101,7 +110,7 @@ public class Bug8001562 { System.out.printf("Only in JDK7 (%s.getAvailableLocales()): ", c.getSimpleName()); for (Locale l : jdk7availLocs) { if (!locs.contains(l)) { - diff += "\""+l.toLanguageTag()+"\", "; + diff += "\"" + l.toLanguageTag() + "\", "; } } System.out.println(diff); diff --git a/jdk/test/java/util/Locale/HashCodeTest.java b/jdk/test/java/util/Locale/HashCodeTest.java index 8163ca03dc3..a911515274f 100644 --- a/jdk/test/java/util/Locale/HashCodeTest.java +++ b/jdk/test/java/util/Locale/HashCodeTest.java @@ -27,14 +27,17 @@ * @modules jdk.localedata */ -import java.util.*; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; public class HashCodeTest { + public static void main(String[] args) { Locale[] locales = Locale.getAvailableLocales(); int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; - Map map = new HashMap(locales.length); + Map map = new HashMap<>(locales.length); int conflicts = 0; for (int i = 0; i < locales.length; i++) { @@ -42,19 +45,19 @@ public class HashCodeTest { int hc = loc.hashCode(); min = Math.min(hc, min); max = Math.max(hc, max); - Integer key = new Integer(hc); + Integer key = hc; if (map.containsKey(key)) { conflicts++; - System.out.println("conflict: " + (Locale) map.get(key) + ", " + loc); + System.out.println("conflict: " + map.get(key) + ", " + loc); } else { map.put(key, loc); } } - System.out.println(locales.length+" locales: conflicts="+conflicts - +", min="+min+", max="+max +", diff="+(max-min)); + System.out.println(locales.length + " locales: conflicts=" + conflicts + + ", min=" + min + ", max=" + max + ", diff=" + (max - min)); if (conflicts >= (locales.length / 10)) { throw new RuntimeException("too many conflicts: " + conflicts - + " per " + locales.length + " locales"); + + " per " + locales.length + " locales"); } } } diff --git a/jdk/test/java/util/Locale/LocaleEnhanceTest.java b/jdk/test/java/util/Locale/LocaleEnhanceTest.java index a4a2f1106fc..c30804d3a15 100644 --- a/jdk/test/java/util/Locale/LocaleEnhanceTest.java +++ b/jdk/test/java/util/Locale/LocaleEnhanceTest.java @@ -46,11 +46,12 @@ import java.util.Set; * @bug 6875847 6992272 7002320 7015500 7023613 7032820 7033504 7004603 * 7044019 8008577 * @summary test API changes to Locale + * @library /java/text/testlib * @modules jdk.localedata * @compile LocaleEnhanceTest.java * @run main/othervm -Djava.locale.providers=JRE,SPI -esa LocaleEnhanceTest */ -public class LocaleEnhanceTest extends LocaleTestFmwk { +public class LocaleEnhanceTest extends IntlTest { public static void main(String[] args) throws Exception { List argList = new ArrayList(); diff --git a/jdk/test/java/util/Locale/LocaleTest.java b/jdk/test/java/util/Locale/LocaleTest.java index 90510ce2fda..33fd411863a 100644 --- a/jdk/test/java/util/Locale/LocaleTest.java +++ b/jdk/test/java/util/Locale/LocaleTest.java @@ -27,6 +27,7 @@ * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549 * 6786276 7066203 7085757 8008577 8030696 * @summary test Locales + * @library /java/text/testlib * @modules jdk.localedata * @run main/othervm -Djava.locale.providers=JRE,SPI LocaleTest */ @@ -63,16 +64,25 @@ * */ -import java.text.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OptionalDataException; +import java.io.StreamCorruptedException; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; -import java.util.Date; -import java.util.Calendar; -import java.io.*; -public class LocaleTest extends LocaleTestFmwk { +public class LocaleTest extends IntlTest { public LocaleTest() { } @@ -186,18 +196,22 @@ public class LocaleTest extends LocaleTestFmwk { Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]); logln("Testing " + testLocale + "..."); - if (!testLocale.getLanguage().equals(dataTable[LANG][i])) + if (!testLocale.getLanguage().equals(dataTable[LANG][i])) { errln(" Language code mismatch: " + testLocale.getLanguage() + " versus " - + dataTable[LANG][i]); - if (!testLocale.getCountry().equals(dataTable[CTRY][i])) + + dataTable[LANG][i]); + } + if (!testLocale.getCountry().equals(dataTable[CTRY][i])) { errln(" Country code mismatch: " + testLocale.getCountry() + " versus " - + dataTable[CTRY][i]); - if (!testLocale.getVariant().equals(dataTable[VAR][i])) + + dataTable[CTRY][i]); + } + if (!testLocale.getVariant().equals(dataTable[VAR][i])) { errln(" Variant code mismatch: " + testLocale.getVariant() + " versus " - + dataTable[VAR][i]); - if (!testLocale.toString().equals(dataTable[NAME][i])) + + dataTable[VAR][i]); + } + if (!testLocale.toString().equals(dataTable[NAME][i])) { errln(" Locale name mismatch: " + testLocale.toString() + " versus " - + dataTable[NAME][i]); + + dataTable[NAME][i]); + } } logln("Same thing without variant codes..."); @@ -205,31 +219,37 @@ public class LocaleTest extends LocaleTestFmwk { Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i]); logln("Testing " + testLocale + "..."); - if (!testLocale.getLanguage().equals(dataTable[LANG][i])) + if (!testLocale.getLanguage().equals(dataTable[LANG][i])) { errln(" Language code mismatch: " + testLocale.getLanguage() + " versus " - + dataTable[LANG][i]); - if (!testLocale.getCountry().equals(dataTable[CTRY][i])) + + dataTable[LANG][i]); + } + if (!testLocale.getCountry().equals(dataTable[CTRY][i])) { errln(" Country code mismatch: " + testLocale.getCountry() + " versus " - + dataTable[CTRY][i]); - if (!testLocale.getVariant().equals("")) + + dataTable[CTRY][i]); + } + if (!testLocale.getVariant().equals("")) { errln(" Variant code mismatch: " + testLocale.getVariant() + " versus \"\""); + } } } public void TestSimpleResourceInfo() { for (int i = 0; i <= MAX_LOCALES; i++) { - if (dataTable[LANG][i].equals("xx")) + if (dataTable[LANG][i].equals("xx")) { continue; + } Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]); logln("Testing " + testLocale + "..."); - if (!testLocale.getISO3Language().equals(dataTable[LANG3][i])) + if (!testLocale.getISO3Language().equals(dataTable[LANG3][i])) { errln(" ISO-3 language code mismatch: " + testLocale.getISO3Language() - + " versus " + dataTable[LANG3][i]); - if (!testLocale.getISO3Country().equals(dataTable[CTRY3][i])) + + " versus " + dataTable[LANG3][i]); + } + if (!testLocale.getISO3Country().equals(dataTable[CTRY3][i])) { errln(" ISO-3 country code mismatch: " + testLocale.getISO3Country() - + " versus " + dataTable[CTRY3][i]); + + " versus " + dataTable[CTRY3][i]); + } /* // getLCID() is currently private if (!String.valueOf(testLocale.getLCID()).equals(dataTable[LCID][i])) @@ -246,11 +266,11 @@ public class LocaleTest extends LocaleTestFmwk { * @bug 4052440 Stop falling back to the default locale. */ public void TestDisplayNames() { - Locale saveDefault = Locale.getDefault(); - Locale english = new Locale("en", "US"); - Locale french = new Locale("fr", "FR"); - Locale croatian = new Locale("hr", "HR"); - Locale greek = new Locale("el", "GR"); + Locale saveDefault = Locale.getDefault(); + Locale english = new Locale("en", "US"); + Locale french = new Locale("fr", "FR"); + Locale croatian = new Locale("hr", "HR"); + Locale greek = new Locale("el", "GR"); Locale.setDefault(english); logln("With default = en_US..."); @@ -282,97 +302,116 @@ public class LocaleTest extends LocaleTestFmwk { } private void doTestDisplayNames(Locale inLocale, int compareIndex, boolean defaultIsFrench) { - if (defaultIsFrench && !Locale.getDefault().getLanguage().equals("fr")) - errln("Default locale should be French, but it's really " + Locale.getDefault().getLanguage()); - else if (!defaultIsFrench && !Locale.getDefault().getLanguage().equals("en")) - errln("Default locale should be English, but it's really " + Locale.getDefault().getLanguage()); + String language = Locale.getDefault().getLanguage(); + + if (defaultIsFrench && !language.equals("fr")) { + errln("Default locale should be French, but it's really " + language); + } else if (!defaultIsFrench && !language.equals("en")) { + errln("Default locale should be English, but it's really " + language); + } for (int i = 0; i <= MAX_LOCALES; i++) { Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]); logln(" Testing " + testLocale + "..."); - String testLang; - String testCtry; - String testVar; - String testName; + String testLang; + String testCtry; + String testVar; + String testName; if (inLocale == null) { testLang = testLocale.getDisplayLanguage(); testCtry = testLocale.getDisplayCountry(); testVar = testLocale.getDisplayVariant(); testName = testLocale.getDisplayName(); - } - else { + } else { testLang = testLocale.getDisplayLanguage(inLocale); testCtry = testLocale.getDisplayCountry(inLocale); testVar = testLocale.getDisplayVariant(inLocale); testName = testLocale.getDisplayName(inLocale); } - String expectedLang; - String expectedCtry; - String expectedVar; - String expectedName; + String expectedLang; + String expectedCtry; + String expectedVar; + String expectedName; expectedLang = dataTable[compareIndex][i]; - if (expectedLang.equals("") && defaultIsFrench) + if (expectedLang.equals("") && defaultIsFrench) { expectedLang = dataTable[DLANG_EN][i]; - if (expectedLang.equals("")) + } + if (expectedLang.equals("")) { expectedLang = dataTable[DLANG_ROOT][i]; + } expectedCtry = dataTable[compareIndex + 1][i]; - if (expectedCtry.equals("") && defaultIsFrench) + if (expectedCtry.equals("") && defaultIsFrench) { expectedCtry = dataTable[DCTRY_EN][i]; - if (expectedCtry.equals("")) + } + if (expectedCtry.equals("")) { expectedCtry = dataTable[DCTRY_ROOT][i]; + } expectedVar = dataTable[compareIndex + 2][i]; - if (expectedVar.equals("") && defaultIsFrench) + if (expectedVar.equals("") && defaultIsFrench) { expectedVar = dataTable[DVAR_EN][i]; - if (expectedVar.equals("")) + } + if (expectedVar.equals("")) { expectedVar = dataTable[DVAR_ROOT][i]; + } expectedName = dataTable[compareIndex + 3][i]; - if (expectedName.equals("") && defaultIsFrench) + if (expectedName.equals("") && defaultIsFrench) { expectedName = dataTable[DNAME_EN][i]; - if (expectedName.equals("")) + } + if (expectedName.equals("")) { expectedName = dataTable[DNAME_ROOT][i]; + } - if (!testLang.equals(expectedLang)) + if (!testLang.equals(expectedLang)) { errln("Display language mismatch: " + testLang + " versus " + expectedLang); - if (!testCtry.equals(expectedCtry)) + } + if (!testCtry.equals(expectedCtry)) { errln("Display country mismatch: " + testCtry + " versus " + expectedCtry); - if (!testVar.equals(expectedVar)) + } + if (!testVar.equals(expectedVar)) { errln("Display variant mismatch: " + testVar + " versus " + expectedVar); - if (!testName.equals(expectedName)) + } + if (!testName.equals(expectedName)) { errln("Display name mismatch: " + testName + " versus " + expectedName); + } } } public void TestSimpleObjectStuff() { - Locale test1 = new Locale("aa", "AA"); - Locale test2 = new Locale("aa", "AA"); - Locale test3 = (Locale)test1.clone(); - Locale test4 = new Locale("zz", "ZZ"); + Locale test1 = new Locale("aa", "AA"); + Locale test2 = new Locale("aa", "AA"); + Locale test3 = (Locale) test1.clone(); + Locale test4 = new Locale("zz", "ZZ"); - if (test1 == test2 || test1 == test3 || test1 == test4 || test2 == test3) + if (test1 == test2 || test1 == test3 || test1 == test4 || test2 == test3) { errln("Some of the test variables point to the same locale!"); + } - if (test3 == null) + if (test3 == null) { errln("clone() failed to produce a valid object!"); + } - if (!test1.equals(test2) || !test1.equals(test3) || !test2.equals(test3)) + if (!test1.equals(test2) || !test1.equals(test3) || !test2.equals(test3)) { errln("clone() or equals() failed: objects that should compare equal don't"); + } - if (test1.equals(test4) || test2.equals(test4) || test3.equals(test4)) + if (test1.equals(test4) || test2.equals(test4) || test3.equals(test4)) { errln("equals() failed: objects that shouldn't compare equal do"); + } int hash1 = test1.hashCode(); int hash2 = test2.hashCode(); int hash3 = test3.hashCode(); - if (hash1 != hash2 || hash1 != hash3 || hash2 != hash3) + if (hash1 != hash2 || hash1 != hash3 || hash2 != hash3) { errln("hashCode() failed: objects that should have the same hash code don't"); + } } /** @@ -385,22 +424,22 @@ public class LocaleTest extends LocaleTestFmwk { try { result = test.getISO3Language(); - } - catch (MissingResourceException e) { + } catch (MissingResourceException e) { gotException = true; } - if (!gotException) + if (!gotException) { errln("getISO3Language() on xx_YY returned " + result + " instead of throwing an exception"); + } gotException = false; try { result = test.getISO3Country(); - } - catch (MissingResourceException e) { + } catch (MissingResourceException e) { gotException = true; } - if (!gotException) + if (!gotException) { errln("getISO3Country() on xx_YY returned " + result + " instead of throwing an exception"); + } } /** @@ -416,53 +455,65 @@ public class LocaleTest extends LocaleTestFmwk { // all lower case for the language codes, all upper case for the country codes) // 4) Is each list in sorted order? String[] test = Locale.getISOLanguages(); - String[] spotCheck1 = { "en", "es", "fr", "de", "it", "ja", "ko", "zh", "th", - "he", "id", "iu", "ug", "yi", "za" }; + String[] spotCheck1 = {"en", "es", "fr", "de", "it", "ja", "ko", "zh", "th", + "he", "id", "iu", "ug", "yi", "za"}; - if (test.length != 188) + if (test.length != 188) { errln("Expected getISOLanguages() to return 188 languages; it returned " + test.length); - else { + } else { for (int i = 0; i < spotCheck1.length; i++) { int j; - for (j = 0; j < test.length; j++) - if (test[j].equals(spotCheck1[i])) + for (j = 0; j < test.length; j++) { + if (test[j].equals(spotCheck1[i])) { break; - if (j == test.length || !test[j].equals(spotCheck1[i])) + } + } + if (j == test.length || !test[j].equals(spotCheck1[i])) { errln("Couldn't find " + spotCheck1[i] + " in language list."); + } } } for (int i = 0; i < test.length; i++) { - if (!test[i].equals(test[i].toLowerCase())) + if (!test[i].equals(test[i].toLowerCase())) { errln(test[i] + " is not all lower case."); - if (test[i].length() != 2) + } + if (test[i].length() != 2) { errln(test[i] + " is not two characters long."); - if (i > 0 && test[i].compareTo(test[i - 1]) <= 0) + } + if (i > 0 && test[i].compareTo(test[i - 1]) <= 0) { errln(test[i] + " appears in an out-of-order position in the list."); + } } test = Locale.getISOCountries(); - String[] spotCheck2 = { "US", "CA", "GB", "FR", "DE", "IT", "JP", "KR", "CN", "TW", "TH" }; + String[] spotCheck2 = {"US", "CA", "GB", "FR", "DE", "IT", "JP", "KR", "CN", "TW", "TH"}; - if (test.length != 250) + if (test.length != 250) { errln("Expected getISOCountries to return 250 countries; it returned " + test.length); - else { + } else { for (int i = 0; i < spotCheck2.length; i++) { int j; - for (j = 0; j < test.length; j++) - if (test[j].equals(spotCheck2[i])) + for (j = 0; j < test.length; j++) { + if (test[j].equals(spotCheck2[i])) { break; - if (j == test.length || !test[j].equals(spotCheck2[i])) + } + } + if (j == test.length || !test[j].equals(spotCheck2[i])) { errln("Couldn't find " + spotCheck2[i] + " in country list."); + } } } for (int i = 0; i < test.length; i++) { - if (!test[i].equals(test[i].toUpperCase())) + if (!test[i].equals(test[i].toUpperCase())) { errln(test[i] + " is not all upper case."); - if (test[i].length() != 2) + } + if (test[i].length() != 2) { errln(test[i] + " is not two characters long."); - if (i > 0 && test[i].compareTo(test[i - 1]) <= 0) + } + if (i > 0 && test[i].compareTo(test[i - 1]) <= 0) { errln(test[i] + " appears in an out-of-order position in the list."); + } } } @@ -475,14 +526,16 @@ public class LocaleTest extends LocaleTestFmwk { test = Locale.getISOCountries(); test[0] = "SUCKER!!!"; test = Locale.getISOCountries(); - if (test[0].equals("SUCKER!!!")) + if (test[0].equals("SUCKER!!!")) { errln("Changed internal country code list!"); + } test = Locale.getISOLanguages(); test[0] = "HAHAHAHA!!!"; test = Locale.getISOLanguages(); - if (test[0].equals("HAHAHAHA!!!")) // Fixed typo + if (test[0].equals("HAHAHAHA!!!")) { // Fixed typo errln("Changes internal language code list!"); + } } /** @@ -490,12 +543,13 @@ public class LocaleTest extends LocaleTestFmwk { */ public void TestGetAvailableLocales() { Locale[] locales = Locale.getAvailableLocales(); - if (locales == null || locales.length == 0) + if (locales == null || locales.length == 0) { errln("Locale.getAvailableLocales() returned no installed locales!"); - else { + } else { logln("Locale.getAvailableLocales() returned a list of " + locales.length + " locales."); - for (int i = 0; i < locales.length; i++) + for (int i = 0; i < locales.length; i++) { logln(locales[i].toString()); + } } } @@ -505,8 +559,9 @@ public class LocaleTest extends LocaleTestFmwk { public void TestBug4135316() { Locale[] locales1 = Locale.getAvailableLocales(); Locale[] locales2 = Locale.getAvailableLocales(); - if (locales1 == locales2) + if (locales1 == locales2) { errln("Locale.getAvailableLocales() doesn't clone its internal storage!"); + } } /** @@ -548,8 +603,7 @@ test commented out pending API-change approval * @bug 4110613 */ public void TestSerialization() throws ClassNotFoundException, OptionalDataException, - IOException, StreamCorruptedException - { + IOException, StreamCorruptedException { ObjectOutputStream ostream; ByteArrayOutputStream obstream; byte[] bytes = null; @@ -565,10 +619,11 @@ test commented out pending API-change approval ObjectInputStream istream = new ObjectInputStream(new ByteArrayInputStream(bytes)); - Locale test2 = (Locale)(istream.readObject()); + Locale test2 = (Locale) (istream.readObject()); - if (!test1.equals(test2) || test1.hashCode() != test2.hashCode()) + if (!test1.equals(test2) || test1.hashCode() != test2.hashCode()) { errln("Locale failed to deserialize correctly."); + } } /** @@ -579,15 +634,16 @@ test commented out pending API-change approval // fallback behavior, combination of language and country names to form locale // names, and other stuff like that. This test just checks specific language // and country codes to make sure we have the correct names for them. - String[] languageCodes = { "he", "id", "iu", "ug", "yi", "za" }; - String[] languageNames = { "Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish", - "Zhuang" }; + String[] languageCodes = {"he", "id", "iu", "ug", "yi", "za"}; + String[] languageNames = {"Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish", + "Zhuang"}; for (int i = 0; i < languageCodes.length; i++) { String test = (new Locale(languageCodes[i], "", "")).getDisplayLanguage(Locale.US); - if (!test.equals(languageNames[i])) - errln("Got wrong display name for " + languageCodes[i] + ": Expected \"" + - languageNames[i] + "\", got \"" + test + "\"."); + if (!test.equals(languageNames[i])) { + errln("Got wrong display name for " + languageCodes[i] + ": Expected \"" + + languageNames[i] + "\", got \"" + test + "\"."); + } } } @@ -597,24 +653,26 @@ test commented out pending API-change approval public void TestUninstalledISO3Names() { // This test checks to make sure getISO3Language and getISO3Country work right // even for locales that are not installed. - String[] iso2Languages = { "am", "ba", "fy", "mr", "rn", "ss", "tw", "zu" }; - String[] iso3Languages = { "amh", "bak", "fry", "mar", "run", "ssw", "twi", "zul" }; + String[] iso2Languages = {"am", "ba", "fy", "mr", "rn", "ss", "tw", "zu"}; + String[] iso3Languages = {"amh", "bak", "fry", "mar", "run", "ssw", "twi", "zul"}; for (int i = 0; i < iso2Languages.length; i++) { String test = (new Locale(iso2Languages[i], "", "")).getISO3Language(); - if (!test.equals(iso3Languages[i])) - errln("Got wrong ISO3 code for " + iso2Languages[i] + ": Expected \"" + - iso3Languages[i] + "\", got \"" + test + "\"."); + if (!test.equals(iso3Languages[i])) { + errln("Got wrong ISO3 code for " + iso2Languages[i] + ": Expected \"" + + iso3Languages[i] + "\", got \"" + test + "\"."); + } } - String[] iso2Countries = { "AF", "BW", "KZ", "MO", "MN", "SB", "TC", "ZW" }; - String[] iso3Countries = { "AFG", "BWA", "KAZ", "MAC", "MNG", "SLB", "TCA", "ZWE" }; + String[] iso2Countries = {"AF", "BW", "KZ", "MO", "MN", "SB", "TC", "ZW"}; + String[] iso3Countries = {"AFG", "BWA", "KAZ", "MAC", "MNG", "SLB", "TCA", "ZWE"}; for (int i = 0; i < iso2Countries.length; i++) { String test = (new Locale("", iso2Countries[i], "")).getISO3Country(); - if (!test.equals(iso3Countries[i])) - errln("Got wrong ISO3 code for " + iso2Countries[i] + ": Expected \"" + - iso3Countries[i] + "\", got \"" + test + "\"."); + if (!test.equals(iso3Countries[i])) { + errln("Got wrong ISO3 code for " + iso2Countries[i] + ": Expected \"" + + iso3Countries[i] + "\", got \"" + test + "\"."); + } } } @@ -629,15 +687,18 @@ test commented out pending API-change approval Locale indonesianOld = new Locale("in", "", ""); Locale indonesianNew = new Locale("id", "", ""); - if (!hebrewNew.getLanguage().equals("iw")) - errln("Got back wrong language code for Hebrew: expected \"iw\", got \"" + - hebrewNew.getLanguage() + "\""); - if (!yiddishNew.getLanguage().equals("ji")) - errln("Got back wrong language code for Yiddish: expected \"ji\", got \"" + - yiddishNew.getLanguage() + "\""); - if (!indonesianNew.getLanguage().equals("in")) - errln("Got back wrong language code for Indonesian: expected \"in\", got \"" + - indonesianNew.getLanguage() + "\""); + if (!hebrewNew.getLanguage().equals("iw")) { + errln("Got back wrong language code for Hebrew: expected \"iw\", got \"" + + hebrewNew.getLanguage() + "\""); + } + if (!yiddishNew.getLanguage().equals("ji")) { + errln("Got back wrong language code for Yiddish: expected \"ji\", got \"" + + yiddishNew.getLanguage() + "\""); + } + if (!indonesianNew.getLanguage().equals("in")) { + errln("Got back wrong language code for Indonesian: expected \"in\", got \"" + + indonesianNew.getLanguage() + "\""); + } } /** @@ -703,25 +764,28 @@ test commented out pending API-change approval for (int i = 0; i < localesToTest.length; i++) { String name = localesToTest[i].getDisplayName(Locale.US); logln(name); - if (!name.equals(englishDisplayNames[i])) + if (!name.equals(englishDisplayNames[i])) { errln("Lookup in English failed: expected \"" + englishDisplayNames[i] - + "\", got \"" + name + "\""); + + "\", got \"" + name + "\""); + } } for (int i = 0; i < localesToTest.length; i++) { String name = localesToTest[i].getDisplayName(new Locale("es", "ES")); logln(name); - if (!name.equals(spanishDisplayNames[i])) + if (!name.equals(spanishDisplayNames[i])) { errln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i] - + "\", got \"" + name + "\""); + + "\", got \"" + name + "\""); + } } for (int i = 0; i < localesToTest.length; i++) { String name = localesToTest[i].getDisplayName(Locale.FRANCE); logln(name); - if (!name.equals(frenchDisplayNames[i])) + if (!name.equals(frenchDisplayNames[i])) { errln("Lookup in French failed: expected \"" + frenchDisplayNames[i] - + "\", got \"" + name + "\""); + + "\", got \"" + name + "\""); + } } // restore the default locale for other tests @@ -737,15 +801,16 @@ test commented out pending API-change approval boolean gotException = false; try { Locale.setDefault(null); - } - catch (NullPointerException e) { + } catch (NullPointerException e) { // all other exception types propagate through here back to the test harness gotException = true; } - if (Locale.getDefault() == null) + if (Locale.getDefault() == null) { errln("Locale.getDefault() allowed us to set default to NULL!"); - if (!gotException) + } + if (!gotException) { errln("Trying to set default locale to NULL didn't throw exception!"); + } } /** @@ -754,14 +819,16 @@ test commented out pending API-change approval * get the LocaleDataTest working again. */ public void TestThaiCurrencyFormat() { - DecimalFormat thaiCurrency = (DecimalFormat)NumberFormat.getCurrencyInstance( - new Locale("th", "TH")); - if (!thaiCurrency.getPositivePrefix().equals("\u0e3f")) - errln("Thai currency prefix wrong: expected \"\u0e3f\", got \"" + - thaiCurrency.getPositivePrefix() + "\""); - if (!thaiCurrency.getPositiveSuffix().equals("")) - errln("Thai currency suffix wrong: expected \"\", got \"" + - thaiCurrency.getPositiveSuffix() + "\""); + DecimalFormat thaiCurrency = (DecimalFormat) NumberFormat.getCurrencyInstance( + new Locale("th", "TH")); + if (!thaiCurrency.getPositivePrefix().equals("\u0e3f")) { + errln("Thai currency prefix wrong: expected \"\u0e3f\", got \"" + + thaiCurrency.getPositivePrefix() + "\""); + } + if (!thaiCurrency.getPositiveSuffix().equals("")) { + errln("Thai currency suffix wrong: expected \"\", got \"" + + thaiCurrency.getPositiveSuffix() + "\""); + } } /** @@ -778,26 +845,25 @@ test commented out pending API-change approval * iterate through all locales. */ public void TestEuroSupport() { - final String EURO_VARIANT = "EURO"; + final String EURO_VARIANT = "EURO"; final String EURO_CURRENCY = "\u20AC"; // Look for this string in formatted Euro currency Locale[] locales = NumberFormat.getAvailableLocales(); - for (int i=0; i= 0) { NumberFormat nf = NumberFormat.getCurrencyInstance(loc); String pos = nf.format(271828.182845); String neg = nf.format(-271828.182845); - if (pos.indexOf(EURO_CURRENCY) >= 0 && - neg.indexOf(EURO_CURRENCY) >= 0) { - logln("Ok: " + loc.toString() + - ": " + pos + " / " + neg); - } - else { - errln("Fail: " + loc.toString() + - " formats without " + EURO_CURRENCY + - ": " + pos + " / " + neg + - "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***"); + if (pos.indexOf(EURO_CURRENCY) >= 0 + && neg.indexOf(EURO_CURRENCY) >= 0) { + logln("Ok: " + loc.toString() + + ": " + pos + " / " + neg); + } else { + errln("Fail: " + loc.toString() + + " formats without " + EURO_CURRENCY + + ": " + pos + " / " + neg + + "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***"); } } } @@ -811,15 +877,15 @@ test commented out pending API-change approval Object[] DATA = { new Locale("xx", "", ""), "xx", new Locale("", "YY", ""), "_YY", - new Locale("", "", "ZZ"), "", + new Locale("", "", "ZZ"), "", new Locale("xx", "YY", ""), "xx_YY", new Locale("xx", "", "ZZ"), "xx__ZZ", new Locale("", "YY", "ZZ"), "_YY_ZZ", new Locale("xx", "YY", "ZZ"), "xx_YY_ZZ", }; - for (int i=0; i" + loc); } @@ -832,9 +898,9 @@ test commented out pending API-change approval * end to test the whole pipe. */ public void Test4105828() { - Locale[] LOC = { Locale.CHINESE, new Locale("zh", "CN", ""), - new Locale("zh", "TW", ""), new Locale("zh", "HK", "") }; - for (int i=0; i= 0) + if (str.indexOf('\u0151') < 0 || str.indexOf('\u00F4') >= 0) { errln("Fail: Monday in Hungarian is wrong"); + } } /** @@ -894,9 +962,10 @@ test commented out pending API-change approval try { String result = locale.getISO3Country(); - errln("ERROR: getISO3Country() returns: " + result + - " for locale '" + locale + "' rather than exception" ); - } catch(MissingResourceException e) { } + errln("ERROR: getISO3Country() returns: " + result + + " for locale '" + locale + "' rather than exception"); + } catch (MissingResourceException e) { + } } /** @@ -912,8 +981,8 @@ test commented out pending API-change approval String result = locale.getISO3Language(); if (!result.equals("aaa")) { - errln("ERROR: getISO3Language() returns: " + result + - " for locale '" + locale + "' rather than returning it as is" ); + errln("ERROR: getISO3Language() returns: " + result + + " for locale '" + locale + "' rather than returning it as is"); } // Try an invalid two letter language code, and check whether it @@ -923,36 +992,39 @@ test commented out pending API-change approval try { result = locale.getISO3Language(); - errln("ERROR: getISO3Language() returns: " + result + - " for locale '" + locale + "' rather than exception" ); - } catch(MissingResourceException e) { } + errln("ERROR: getISO3Language() returns: " + result + + " for locale '" + locale + "' rather than exception"); + } catch (MissingResourceException e) { + } } /* * @bug 4147552 4778440 8030696 */ public void Test4147552() { - Locale[] locales = { new Locale("no", "NO"), new Locale("no", "NO", "B"), - new Locale("no", "NO", "NY"), new Locale("nb", "NO"), - new Locale("nn", "NO") }; - String[] englishDisplayNames = { "Norwegian (Norway)", - "Norwegian (Norway,Bokm\u00e5l)", - "Norwegian (Norway,Nynorsk)", - "Norwegian Bokm\u00e5l (Norway)", - "Norwegian Nynorsk (Norway)" }; - String[] norwegianDisplayNames = { "norsk (Norge)", - "norsk (Norge,bokm\u00e5l)", "norsk (Noreg,nynorsk)", - "bokm\u00e5l (Norge)", "nynorsk (Noreg)" }; + Locale[] locales = {new Locale("no", "NO"), new Locale("no", "NO", "B"), + new Locale("no", "NO", "NY"), new Locale("nb", "NO"), + new Locale("nn", "NO")}; + String[] englishDisplayNames = {"Norwegian (Norway)", + "Norwegian (Norway,Bokm\u00e5l)", + "Norwegian (Norway,Nynorsk)", + "Norwegian Bokm\u00e5l (Norway)", + "Norwegian Nynorsk (Norway)"}; + String[] norwegianDisplayNames = {"norsk (Norge)", + "norsk (Norge,bokm\u00e5l)", "norsk (Noreg,nynorsk)", + "bokm\u00e5l (Norge)", "nynorsk (Noreg)"}; for (int i = 0; i < locales.length; i++) { Locale loc = locales[i]; - if (!loc.getDisplayName(Locale.US).equals(englishDisplayNames[i])) - errln("English display-name mismatch: expected " + - englishDisplayNames[i] + ", got " + loc.getDisplayName()); - if (!loc.getDisplayName(loc).equals(norwegianDisplayNames[i])) - errln("Norwegian display-name mismatch: expected " + - norwegianDisplayNames[i] + ", got " + - loc.getDisplayName(loc)); + if (!loc.getDisplayName(Locale.US).equals(englishDisplayNames[i])) { + errln("English display-name mismatch: expected " + + englishDisplayNames[i] + ", got " + loc.getDisplayName()); + } + if (!loc.getDisplayName(loc).equals(norwegianDisplayNames[i])) { + errln("Norwegian display-name mismatch: expected " + + norwegianDisplayNames[i] + ", got " + + loc.getDisplayName(loc)); + } } } @@ -961,21 +1033,24 @@ test commented out pending API-change approval */ public void Test8030696() { List av = Arrays.asList(Locale.getAvailableLocales()); - if (!av.contains(new Locale("nb", "NO")) || - !av.contains(new Locale("nn", "NO"))) { - errln("\"nb-NO\" and/or \"nn-NO\" locale(s) not returned from getAvailableLocales()."); + if (!av.contains(new Locale("nb", "NO")) + || !av.contains(new Locale("nn", "NO"))) { + errln("\"nb-NO\" and/or \"nn-NO\" locale(s) not returned from getAvailableLocales()."); } } static String escapeUnicode(String s) { StringBuffer buf = new StringBuffer(); - for (int i=0; i= 0x20 && c <= 0x7F) buf.append(c); - else { + if (c >= 0x20 && c <= 0x7F) { + buf.append(c); + } else { buf.append("\\u"); String h = "000" + Integer.toHexString(c); - if (h.length() > 4) h = h.substring(h.length() - 4); + if (h.length() > 4) { + h = h.substring(h.length() - 4); + } buf.append(h); } } diff --git a/jdk/test/java/util/Locale/LocaleTestFmwk.java b/jdk/test/java/util/Locale/LocaleTestFmwk.java deleted file mode 100644 index 68532d4d31d..00000000000 --- a/jdk/test/java/util/Locale/LocaleTestFmwk.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 2010, 2013, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * - * - * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved - * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved - * - * Portions copyright (c) 2007 Sun Microsystems, Inc. - * All Rights Reserved. - * - * The original version of this source code and documentation - * is copyrighted and owned by Taligent, Inc., a wholly-owned - * subsidiary of IBM. These materials are provided under terms - * of a License Agreement between Taligent and Sun. This technology - * is protected by multiple US and International patents. - * - * This notice and attribution to Taligent may not be removed. - * Taligent is a registered trademark of Taligent, Inc. - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for NON-COMMERCIAL purposes and without - * fee is hereby granted provided that this copyright notice - * appears in all copies. Please refer to the file "copyright.html" - * for further important copyright and licensing information. - * - * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF - * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. - * - */ - -import java.lang.reflect.*; -import java.util.Hashtable; -import java.util.Enumeration; -import java.util.Vector; -import java.io.*; -import java.text.*; - -/** - * LocaleTestFmwk is a base class for tests that can be run conveniently from - * the command line as well as under the Java test harness. - *

    - * Sub-classes implement a set of methods named Test. Each - * of these methods performs some test. Test methods should indicate - * errors by calling either err or errln. This will increment the - * errorCount field and may optionally print a message to the log. - * Debugging information may also be added to the log via the log - * and logln methods. These methods will add their arguments to the - * log only if the test is being run in verbose mode. - */ -public class LocaleTestFmwk { - //------------------------------------------------------------------------ - // Everything below here is boilerplate code that makes it possible - // to add a new test by simply adding a function to an existing class - //------------------------------------------------------------------------ - - protected LocaleTestFmwk() { - // Create a hashtable containing all the test methods. - testMethods = new Hashtable(); - Method[] methods = getClass().getDeclaredMethods(); - for( int i=0; i 0) { - throw new IllegalArgumentException("encountered " + errorCount + " errors"); - } - } - } - - /** - * Adds given string to the log if we are in verbose mode. - */ - protected void log( String message ) { - if( verbose ) { - indent(indentLevel + 1); - log.print( message ); - } - } - - protected void logln( String message ) { - log(message + System.getProperty("line.separator")); - } - - /** - * Report an error - */ - protected void err( String message ) { - errorCount++; - indent(indentLevel + 1); - log.print( message ); - log.flush(); - - if (!nothrow) { - throw new RuntimeException(message); - } - } - - protected void errln( String message ) { - err(message + System.getProperty("line.separator")); - } - - - protected void writeTestName(String testName) { - indent(indentLevel); - log.print(testName); - log.flush(); - needLineFeed = true; - } - - protected void writeTestResult(int count) { - if (!needLineFeed) { - indent(indentLevel); - log.print("}"); - } - needLineFeed = false; - - if (count != 0) - log.println(" FAILED"); - else - log.println(" Passed"); - } - - private final void indent(int distance) { - if (needLineFeed) { - log.println(" {"); - needLineFeed = false; - } - log.print(spaces.substring(0, distance * 2)); - } - - /** - * Print a usage message for this test class. - */ - void usage() { - System.out.println(getClass().getName() + - ": [-verbose] [-nothrow] [-exitcode] [-prompt] [test names]"); - - System.out.println("test names:"); - Enumeration methodNames = testMethods.keys(); - while( methodNames.hasMoreElements() ) { - System.out.println("\t" + methodNames.nextElement() ); - } - } - - private boolean prompt = false; - private boolean nothrow = false; - private boolean exitcode = false; - protected boolean verbose = false; - - private PrintWriter log; - private int indentLevel = 0; - private boolean needLineFeed = false; - private int errorCount = 0; - - private Hashtable testMethods; - private final String spaces = " "; -} diff --git a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java index a8d6a9c6471..474204384a8 100644 --- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java +++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java @@ -25,7 +25,7 @@ * @test * @summary Spliterator traversing and splitting tests * @run testng SpliteratorTraversingAndSplittingTest - * @bug 8020016 8071477 + * @bug 8020016 8071477 8072784 8169838 */ import org.testng.annotations.DataProvider; @@ -37,6 +37,7 @@ import java.util.AbstractSet; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -80,7 +81,9 @@ import java.util.function.IntConsumer; import java.util.function.LongConsumer; import java.util.function.Supplier; import java.util.function.UnaryOperator; +import java.util.stream.IntStream; +import static java.util.stream.Collectors.toList; import static org.testng.Assert.*; import static org.testng.Assert.assertEquals; @@ -883,6 +886,30 @@ public class SpliteratorTraversingAndSplittingTest { cdb.add("new StringBuffer(\"%s\")", StringBuffer::new); } + + Object[][] bitStreamTestcases = new Object[][] { + { "none", IntStream.empty().toArray() }, + { "index 0", IntStream.of(0).toArray() }, + { "index 255", IntStream.of(255).toArray() }, + { "index 0 and 255", IntStream.of(0, 255).toArray() }, + { "every bit", IntStream.range(0, 255).toArray() }, + { "step 2", IntStream.range(0, 255).map(f -> f * 2).toArray() }, + { "step 3", IntStream.range(0, 255).map(f -> f * 3).toArray() }, + { "step 5", IntStream.range(0, 255).map(f -> f * 5).toArray() }, + { "step 7", IntStream.range(0, 255).map(f -> f * 7).toArray() }, + { "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000).toArray() }, + }; + for (Object[] tc : bitStreamTestcases) { + String description = (String)tc[0]; + int[] exp = (int[])tc[1]; + SpliteratorOfIntDataBuilder db = new SpliteratorOfIntDataBuilder( + data, IntStream.of(exp).boxed().collect(toList())); + + db.add("BitSet.stream.spliterator() {" + description + "}", () -> + IntStream.of(exp).collect(BitSet::new, BitSet::set, BitSet::or). + stream().spliterator() + ); + } return spliteratorOfIntDataProvider = data.toArray(new Object[0][]); } diff --git a/jdk/test/javax/net/ssl/templates/SSLSocketSample.java b/jdk/test/javax/net/ssl/templates/SSLSocketSample.java deleted file mode 100644 index 38a082a041e..00000000000 --- a/jdk/test/javax/net/ssl/templates/SSLSocketSample.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// Please run in othervm mode. SunJSSE does not support dynamic system -// properties, no way to re-use system properties in samevm/agentvm mode. - -/* - * @test - * @bug 8161106 - * @summary Improve SSLSocket test template - * @run main/othervm SSLSocketSample - */ - -import java.io.*; -import javax.net.ssl.*; -import java.net.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Template to help speed your client/server tests. - */ -public final class SSLSocketSample { - - /* - * ============================================================= - * Set the various variables needed for the tests, then - * specify what tests to run on each side. - */ - - /* - * Should we run the client or server in a separate thread? - * Both sides can throw exceptions, but do you have a preference - * as to which side should be the main thread. - */ - private static final boolean separateServerThread = false; - - /* - * Where do we find the keystores? - */ - private static final String pathToStores = "../etc"; - private static final String keyStoreFile = "keystore"; - private static final String trustStoreFile = "truststore"; - private static final String passwd = "passphrase"; - - /* - * Turn on SSL debugging? - */ - private static final boolean debug = false; - - /* - * Is the server ready to serve? - */ - private static final CountDownLatch serverCondition = new CountDownLatch(1); - - /* - * Is the client ready to handshake? - */ - private static final CountDownLatch clientCondition = new CountDownLatch(1); - - /* - * What's the server port? Use any free port by default - */ - private volatile int serverPort = 0; - - /* - * If the client or server is doing some kind of object creation - * that the other side depends on, and that thread prematurely - * exits, you may experience a hang. The test harness will - * terminate all hung threads after its timeout has expired, - * currently 3 minutes by default, but you might try to be - * smart about it.... - */ - - /* - * Define the server side of the test. - */ - void doServerSide() throws Exception { - SSLServerSocket sslServerSocket; - - // kick start the server side service - SSLServerSocketFactory sslssf = - (SSLServerSocketFactory)SSLServerSocketFactory.getDefault(); - sslServerSocket = - (SSLServerSocket)sslssf.createServerSocket(serverPort); - - serverPort = sslServerSocket.getLocalPort(); - - // Signal the client, the server is ready to accept connection. - serverCondition.countDown(); - - - // Try to accept a connection in 30 seconds. - SSLSocket sslSocket; - try { - sslServerSocket.setSoTimeout(30000); - sslSocket = (SSLSocket)sslServerSocket.accept(); - } catch (SocketTimeoutException ste) { - sslServerSocket.close(); - - // Ignore the test case if no connection within 30 seconds. - System.out.println( - "No incoming client connection in 30 seconds. " + - "Ignore in server side."); - return; - } - - // handle the connection - try { - // Is it the expected client connection? - // - // Naughty test cases or third party routines may try to - // connection to this server port unintentionally. In - // order to mitigate the impact of unexpected client - // connections and avoid intermittent failure, it should - // be checked that the accepted connection is really linked - // to the expected client. - boolean clientIsReady = - clientCondition.await(30L, TimeUnit.SECONDS); - - if (clientIsReady) { - // Run the application in server side. - runServerApplication(sslSocket); - } else { // Otherwise, ignore - // We don't actually care about plain socket connections - // for TLS communication testing generally. Just ignore - // the test if the accepted connection is not linked to - // the expected client or the client connection timeout - // in 30 seconds. - System.out.println( - "The client is not the expected one or timeout. " + - "Ignore in server side."); - } - } finally { - sslSocket.close(); - sslServerSocket.close(); - } - } - - /* - * Define the server side application of the test for the specified socket. - */ - void runServerApplication(SSLSocket socket) throws Exception { - // here comes the test logic - InputStream sslIS = socket.getInputStream(); - OutputStream sslOS = socket.getOutputStream(); - - sslIS.read(); - sslOS.write(85); - sslOS.flush(); - } - - /* - * Define the client side of the test. - */ - void doClientSide() throws Exception { - - // Wait for server to get started. - // - // The server side takes care of the issue if the server cannot - // get started in 90 seconds. The client side would just ignore - // the test case if the serer is not ready. - boolean serverIsReady = - serverCondition.await(90L, TimeUnit.SECONDS); - if (!serverIsReady) { - System.out.println( - "The server is not ready yet in 90 seconds. " + - "Ignore in client side."); - return; - } - - SSLSocketFactory sslsf = - (SSLSocketFactory)SSLSocketFactory.getDefault(); - try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { - try { - sslSocket.connect( - new InetSocketAddress("localhost", serverPort), 15000); - } catch (IOException ioe) { - // The server side may be impacted by naughty test cases or - // third party routines, and cannot accept connections. - // - // Just ignore the test if the connection cannot be - // established. - System.out.println( - "Cannot make a connection in 15 seconds. " + - "Ignore in client side."); - return; - } - - // OK, here the client and server get connected. - - // Signal the server, the client is ready to communicate. - clientCondition.countDown(); - - // There is still a chance in theory that the server thread may - // wait client-ready timeout and then quit. The chance should - // be really rare so we don't consider it until it becomes a - // real problem. - - // Run the application in client side. - runClientApplication(sslSocket); - } - } - - /* - * Define the server side application of the test for the specified socket. - */ - void runClientApplication(SSLSocket socket) throws Exception { - InputStream sslIS = socket.getInputStream(); - OutputStream sslOS = socket.getOutputStream(); - - sslOS.write(280); - sslOS.flush(); - sslIS.read(); - } - - /* - * ============================================================= - * The remainder is just support stuff - */ - - private volatile Exception serverException = null; - private volatile Exception clientException = null; - - public static void main(String[] args) throws Exception { - String keyFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + keyStoreFile; - String trustFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + trustStoreFile; - - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", passwd); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", passwd); - - if (debug) { - System.setProperty("javax.net.debug", "all"); - } - - /* - * Start the tests. - */ - new SSLSocketSample(); - } - - private Thread clientThread = null; - private Thread serverThread = null; - - /* - * Primary constructor, used to drive remainder of the test. - * - * Fork off the other side, then do your work. - */ - SSLSocketSample() throws Exception { - Exception startException = null; - try { - if (separateServerThread) { - startServer(true); - startClient(false); - } else { - startClient(true); - startServer(false); - } - } catch (Exception e) { - startException = e; - } - - /* - * Wait for other side to close down. - */ - if (separateServerThread) { - if (serverThread != null) { - serverThread.join(); - } - } else { - if (clientThread != null) { - clientThread.join(); - } - } - - /* - * When we get here, the test is pretty much over. - * Which side threw the error? - */ - Exception local; - Exception remote; - - if (separateServerThread) { - remote = serverException; - local = clientException; - } else { - remote = clientException; - local = serverException; - } - - Exception exception = null; - - /* - * Check various exception conditions. - */ - if ((local != null) && (remote != null)) { - // If both failed, return the curthread's exception. - local.initCause(remote); - exception = local; - } else if (local != null) { - exception = local; - } else if (remote != null) { - exception = remote; - } else if (startException != null) { - exception = startException; - } - - /* - * If there was an exception *AND* a startException, - * output it. - */ - if (exception != null) { - if (exception != startException && startException != null) { - exception.addSuppressed(startException); - } - throw exception; - } - - // Fall-through: no exception to throw! - } - - void startServer(boolean newThread) throws Exception { - if (newThread) { - serverThread = new Thread() { - @Override - public void run() { - try { - doServerSide(); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - System.out.println("Server died: " + e); - serverException = e; - } - } - }; - serverThread.start(); - } else { - try { - doServerSide(); - } catch (Exception e) { - System.out.println("Server failed: " + e); - serverException = e; - } - } - } - - void startClient(boolean newThread) throws Exception { - if (newThread) { - clientThread = new Thread() { - @Override - public void run() { - try { - doClientSide(); - } catch (Exception e) { - /* - * Our client thread just died. - */ - System.out.println("Client died: " + e); - clientException = e; - } - } - }; - clientThread.start(); - } else { - try { - doClientSide(); - } catch (Exception e) { - System.out.println("Client failed: " + e); - clientException = e; - } - } - } -} diff --git a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java index 12dfcaacae5..9b4c65536d2 100644 --- a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java @@ -21,251 +21,561 @@ * questions. */ -// SunJSSE does not support dynamic system properties, no way to re-use -// system properties in samevm/agentvm mode. +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.SocketTimeoutException; +import java.security.KeyStore; +import java.security.Security; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +/** + * This class defines a framework for JSSE tests. + * + * Please run in othervm mode. SunJSSE does not support dynamic system + * properties, no way to re-use system properties in samevm/agentvm mode. + */ /* * @test * @bug 1234567 - * @summary Use this template to help speed your client/server tests. + * @summary Use this class for JSSE tests * @run main/othervm SSLSocketTemplate * @author Brad Wetmore */ -import java.io.*; -import javax.net.ssl.*; - public class SSLSocketTemplate { + public static final String TEST_SRC = System.getProperty("test.src", "."); + /* - * ============================================================= - * Set the various variables needed for the tests, then - * specify what tests to run on each side. + * Where do we find the keystores? */ + public static final String PATH_TO_STORES = "../etc"; + public static final String KEY_STORE_FILE = "keystore"; + public static final String TRUST_STORE_FILE = "truststore"; + public static final String PASSWORD = "passphrase"; + + public static final int FREE_PORT = 0; + + // in seconds + public static final long CLIENT_SIGNAL_TIMEOUT = 30L; + public static final long SERVER_SIGNAL_TIMEOUT = 90L; + + // in millis + public static final int CLIENT_TIMEOUT = 15000; + public static final int SERVER_TIMEOUT = 30000; /* * Should we run the client or server in a separate thread? * Both sides can throw exceptions, but do you have a preference * as to which side should be the main thread. */ - static boolean separateServerThread = false; + private boolean separateServerThread = false; /* - * Where do we find the keystores? + * What's the server port? Use any free port by default */ - static String pathToStores = "../etc"; - static String keyStoreFile = "keystore"; - static String trustStoreFile = "truststore"; - static String passwd = "passphrase"; + private volatile int serverPort; + + private volatile Exception serverException; + private volatile Exception clientException; + + private Thread clientThread; + private Thread serverThread; + + private Peer serverPeer; + private Peer clientPeer; + + private Application serverApplication; + private Application clientApplication; + + private SSLContext context; /* * Is the server ready to serve? */ - volatile static boolean serverReady = false; + private final CountDownLatch serverReadyCondition = new CountDownLatch(1); /* - * Turn on SSL debugging? + * Is the client ready to handshake? */ - static boolean debug = false; + private final CountDownLatch clientReadyCondition = new CountDownLatch(1); /* - * If the client or server is doing some kind of object creation - * that the other side depends on, and that thread prematurely - * exits, you may experience a hang. The test harness will - * terminate all hung threads after its timeout has expired, - * currently 3 minutes by default, but you might try to be - * smart about it.... + * Is the server done? + */ + private final CountDownLatch serverDoneCondition = new CountDownLatch(1); + + /* + * Is the client done? + */ + private final CountDownLatch clientDoneCondition = new CountDownLatch(1); + + /* + * Public API. + */ + + public static interface Peer { + void run(SSLSocketTemplate test) throws Exception; + } + + public static interface Application { + void run(SSLSocket socket, SSLSocketTemplate test) throws Exception; + } + + public static void debug() { + debug("ssl"); + } + + public static void debug(String mode) { + System.setProperty("javax.net.debug", mode); + } + + public static void setup(String keyFilename, String trustFilename, + String password) { + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", password); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", password); + } + + public static void setup() throws Exception { + String keyFilename = TEST_SRC + "/" + PATH_TO_STORES + "/" + + KEY_STORE_FILE; + String trustFilename = TEST_SRC + "/" + PATH_TO_STORES + "/" + + TRUST_STORE_FILE; + + setup(keyFilename, trustFilename, PASSWORD); + } + + public static void print(String message, Throwable... errors) { + synchronized (System.out) { + System.out.println(message); + for (Throwable e : errors) { + e.printStackTrace(System.out); + } + } + } + + public static KeyStore loadJksKeyStore(String filename, String password) + throws Exception { + + return loadKeyStore(filename, password, "JKS"); + } + + public static KeyStore loadKeyStore(String filename, String password, + String type) throws Exception { + + KeyStore keystore = KeyStore.getInstance(type); + FileInputStream fis = new FileInputStream(filename); + try { + keystore.load(fis, password.toCharArray()); + } finally { + fis.close(); + } + return keystore; + } + + // Try to accept a connection in 30 seconds. + public static SSLSocket accept(SSLServerSocket sslServerSocket) + throws IOException { + + return accept(sslServerSocket, SERVER_TIMEOUT); + } + + public static SSLSocket accept(SSLServerSocket sslServerSocket, int timeout) + throws IOException { + + try { + sslServerSocket.setSoTimeout(timeout); + return (SSLSocket) sslServerSocket.accept(); + } catch (SocketTimeoutException ste) { + print("Warning: ", ste); + return null; + } + } + + public SSLSocketTemplate setSeparateServerThread( + boolean separateServerThread) { + + this.separateServerThread = separateServerThread; + return this; + } + + public SSLSocketTemplate setServerPort(int serverPort) { + this.serverPort = serverPort; + return this; + } + + public int getServerPort() { + return serverPort; + } + + public SSLSocketTemplate setSSLContext(SSLContext context) { + this.context = context; + return this; + } + + public SSLContext getSSLContext() { + return context; + } + + public SSLServerSocketFactory getSSLServerSocketFactory() { + if (context != null) { + return context.getServerSocketFactory(); + } + + return (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + } + + public SSLSocketFactory getSSLSocketFactory() { + if (context != null) { + return context.getSocketFactory(); + } + + return (SSLSocketFactory) SSLSocketFactory.getDefault(); + } + + public void signalServerReady() { + serverReadyCondition.countDown(); + } + + public void signalServerDone() { + serverDoneCondition.countDown(); + } + + public boolean waitForClientSignal(long timeout, TimeUnit unit) + throws InterruptedException { + + return clientReadyCondition.await(timeout, unit); + } + + public boolean waitForClientSignal() throws InterruptedException { + return waitForClientSignal(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); + } + + public boolean waitForClientDone(long timeout, TimeUnit unit) + throws InterruptedException { + + return clientDoneCondition.await(timeout, unit); + } + + public boolean waitForClientDone() throws InterruptedException { + return waitForClientDone(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); + } + + public void signalClientReady() { + clientReadyCondition.countDown(); + } + + public void signalClientDone() { + clientDoneCondition.countDown(); + } + + public boolean waitForServerSignal(long timeout, TimeUnit unit) + throws InterruptedException { + + return serverReadyCondition.await(timeout, unit); + } + + public boolean waitForServerSignal() throws InterruptedException { + return waitForServerSignal(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); + } + + public boolean waitForServerDone(long timeout, TimeUnit unit) + throws InterruptedException { + + return serverDoneCondition.await(timeout, unit); + } + + public boolean waitForServerDone() throws InterruptedException { + return waitForServerDone(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); + } + + public SSLSocketTemplate setServerPeer(Peer serverPeer) { + this.serverPeer = serverPeer; + return this; + } + + public Peer getServerPeer() { + return serverPeer; + } + + public SSLSocketTemplate setServerApplication( + Application serverApplication) { + + this.serverApplication = serverApplication; + return this; + } + + public Application getServerApplication() { + return serverApplication; + } + + public SSLSocketTemplate setClientPeer(Peer clientPeer) { + this.clientPeer = clientPeer; + return this; + } + + public Peer getClientPeer() { + return clientPeer; + } + + public SSLSocketTemplate setClientApplication( + Application clientApplication) { + + this.clientApplication = clientApplication; + return this; + } + + public Application getClientApplication() { + return clientApplication; + } + + public void runTest() throws Exception { + if (separateServerThread) { + startServer(true, this); + startClient(false, this); + serverThread.join(); + } else { + startClient(true, this); + startServer(false, this); + clientThread.join(); + } + + if (clientException != null || serverException != null) { + throw new RuntimeException("Test failed"); + } + } + + public SSLSocketTemplate() { + serverPeer = new Peer() { + + @Override + public void run(SSLSocketTemplate test) throws Exception { + doServerSide(test); + } + }; + + clientPeer = new Peer() { + + @Override + public void run(SSLSocketTemplate test) throws Exception { + doClientSide(test); + } + }; + + serverApplication = new Application() { + + @Override + public void run(SSLSocket socket, SSLSocketTemplate test) + throws Exception { + + runServerApplication(socket); + } + + }; + + clientApplication = new Application() { + + @Override + public void run(SSLSocket socket, SSLSocketTemplate test) + throws Exception { + + runClientApplication(socket); + } + }; + } + + public static void main(String args[]) throws Exception { + // reset the security property to make sure that the algorithms + // and keys used in this test are not disabled. + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + // MD5 is used in this test case, don't disable MD5 algorithm. + Security.setProperty( + "jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024"); + + setup(); + + new SSLSocketTemplate().runTest(); + } + + /* + * Private part. */ /* * Define the server side of the test. - * - * If the server prematurely exits, serverReady will be set to true - * to avoid infinite hangs. */ - void doServerSide() throws Exception { - SSLServerSocketFactory sslssf = - (SSLServerSocketFactory)SSLServerSocketFactory.getDefault(); - try (SSLServerSocket sslServerSocket = - (SSLServerSocket)sslssf.createServerSocket(serverPort)) { + private static void doServerSide(SSLSocketTemplate test) throws Exception { + SSLServerSocket sslServerSocket; - serverPort = sslServerSocket.getLocalPort(); + // kick start the server side service + SSLServerSocketFactory sslssf = test.getSSLServerSocketFactory(); + sslServerSocket = (SSLServerSocket)sslssf.createServerSocket(FREE_PORT); - /* - * Signal Client, we're ready for his connect. - */ - serverReady = true; + test.setServerPort(sslServerSocket.getLocalPort()); + print("Server is listening on port " + test.getServerPort()); - try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); + // Signal the client, the server is ready to accept connection. + test.signalServerReady(); - sslIS.read(); - sslOS.write(85); - sslOS.flush(); - } + // Try to accept a connection in 30 seconds. + SSLSocket sslSocket = accept(sslServerSocket); + if (sslSocket == null) { + // Ignore the test case if no connection within 30 seconds. + print("No incoming client connection in 30 seconds. " + + "Ignore in server side."); + return; } + print("Server accepted connection"); + + // handle the connection + try { + // Is it the expected client connection? + // + // Naughty test cases or third party routines may try to + // connection to this server port unintentionally. In + // order to mitigate the impact of unexpected client + // connections and avoid intermittent failure, it should + // be checked that the accepted connection is really linked + // to the expected client. + boolean clientIsReady = test.waitForClientSignal(); + + if (clientIsReady) { + // Run the application in server side. + print("Run server application"); + test.getServerApplication().run(sslSocket, test); + } else { // Otherwise, ignore + // We don't actually care about plain socket connections + // for TLS communication testing generally. Just ignore + // the test if the accepted connection is not linked to + // the expected client or the client connection timeout + // in 30 seconds. + print("The client is not the expected one or timeout. " + + "Ignore in server side."); + } + } finally { + sslSocket.close(); + sslServerSocket.close(); + } + + test.signalServerDone(); + } + + /* + * Define the server side application of the test for the specified socket. + */ + private static void runServerApplication(SSLSocket socket) + throws Exception { + + // here comes the test logic + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); } /* * Define the client side of the test. - * - * If the server prematurely exits, serverReady will be set to true - * to avoid infinite hangs. */ - void doClientSide() throws Exception { + private static void doClientSide(SSLSocketTemplate test) throws Exception { - /* - * Wait for server to get started. - */ - while (!serverReady) { - Thread.sleep(50); + // Wait for server to get started. + // + // The server side takes care of the issue if the server cannot + // get started in 90 seconds. The client side would just ignore + // the test case if the serer is not ready. + boolean serverIsReady = test.waitForServerSignal(); + if (!serverIsReady) { + print("The server is not ready yet in 90 seconds. " + + "Ignore in client side."); + return; } - SSLSocketFactory sslsf = - (SSLSocketFactory)SSLSocketFactory.getDefault(); - try (SSLSocket sslSocket = - (SSLSocket)sslsf.createSocket("localhost", serverPort)) { - - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); - - sslOS.write(280); - sslOS.flush(); - sslIS.read(); - } - } - - /* - * ============================================================= - * The remainder is just support stuff - */ - - // use any free port by default - volatile int serverPort = 0; - - volatile Exception serverException = null; - volatile Exception clientException = null; - - public static void main(String[] args) throws Exception { - String keyFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + keyStoreFile; - String trustFilename = - System.getProperty("test.src", ".") + "/" + pathToStores + - "/" + trustStoreFile; - - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", passwd); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", passwd); - - if (debug) { - System.setProperty("javax.net.debug", "all"); - } - - /* - * Start the tests. - */ - new SSLSocketTemplate(); - } - - Thread clientThread = null; - Thread serverThread = null; - - /* - * Primary constructor, used to drive remainder of the test. - * - * Fork off the other side, then do your work. - */ - SSLSocketTemplate() throws Exception { - Exception startException = null; + SSLSocketFactory sslsf = test.getSSLSocketFactory(); + SSLSocket sslSocket = (SSLSocket)sslsf.createSocket(); try { - if (separateServerThread) { - startServer(true); - startClient(false); - } else { - startClient(true); - startServer(false); + try { + sslSocket.connect( + new InetSocketAddress("localhost", + test.getServerPort()), CLIENT_TIMEOUT); + print("Client connected to server"); + } catch (IOException ioe) { + // The server side may be impacted by naughty test cases or + // third party routines, and cannot accept connections. + // + // Just ignore the test if the connection cannot be + // established. + print("Cannot make a connection in 15 seconds. " + + "Ignore in client side.", ioe); + return; } - } catch (Exception e) { - startException = e; + + // OK, here the client and server get connected. + + // Signal the server, the client is ready to communicate. + test.signalClientReady(); + + // There is still a chance in theory that the server thread may + // wait client-ready timeout and then quit. The chance should + // be really rare so we don't consider it until it becomes a + // real problem. + + // Run the application in client side. + print("Run client application"); + test.getClientApplication().run(sslSocket, test); + } finally { + sslSocket.close(); } - /* - * Wait for other side to close down. - */ - if (separateServerThread) { - if (serverThread != null) { - serverThread.join(); - } - } else { - if (clientThread != null) { - clientThread.join(); - } - } - - /* - * When we get here, the test is pretty much over. - * Which side threw the error? - */ - Exception local; - Exception remote; - - if (separateServerThread) { - remote = serverException; - local = clientException; - } else { - remote = clientException; - local = serverException; - } - - Exception exception = null; - - /* - * Check various exception conditions. - */ - if ((local != null) && (remote != null)) { - // If both failed, return the curthread's exception. - local.initCause(remote); - exception = local; - } else if (local != null) { - exception = local; - } else if (remote != null) { - exception = remote; - } else if (startException != null) { - exception = startException; - } - - /* - * If there was an exception *AND* a startException, - * output it. - */ - if (exception != null) { - if (exception != startException && startException != null) { - exception.addSuppressed(startException); - } - throw exception; - } - - // Fall-through: no exception to throw! + test.signalClientDone(); } - void startServer(boolean newThread) throws Exception { + /* + * Define the client side application of the test for the specified socket. + */ + private static void runClientApplication(SSLSocket socket) + throws Exception { + + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + } + + private void startServer(boolean newThread, SSLSocketTemplate test) + throws Exception { + if (newThread) { serverThread = new Thread() { + @Override public void run() { try { - doServerSide(); + serverPeer.run(test); } catch (Exception e) { /* * Our server thread just died. * * Release the client, if not active already... */ - System.err.println("Server died..."); - serverReady = true; + print("Server died ...", e); serverException = e; } } @@ -273,27 +583,29 @@ public class SSLSocketTemplate { serverThread.start(); } else { try { - doServerSide(); + serverPeer.run(test); } catch (Exception e) { + print("Server failed ...", e); serverException = e; - } finally { - serverReady = true; } } } - void startClient(boolean newThread) throws Exception { + private void startClient(boolean newThread, SSLSocketTemplate test) + throws Exception { + if (newThread) { clientThread = new Thread() { + @Override public void run() { try { - doClientSide(); + clientPeer.run(test); } catch (Exception e) { /* * Our client thread just died. */ - System.err.println("Client died..."); + print("Client died ...", e); clientException = e; } } @@ -301,8 +613,9 @@ public class SSLSocketTemplate { clientThread.start(); } else { try { - doClientSide(); + clientPeer.run(test); } catch (Exception e) { + print("Client failed ...", e); clientException = e; } } diff --git a/jdk/test/javax/net/ssl/templates/SSLTest.java b/jdk/test/javax/net/ssl/templates/SSLTest.java deleted file mode 100644 index 61ab7ae0a15..00000000000 --- a/jdk/test/javax/net/ssl/templates/SSLTest.java +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (c) 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.SocketTimeoutException; -import java.security.KeyStore; -import java.util.Arrays; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLServerSocket; -import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; - -/** - * Helper class for JSSE tests. - * - * Please run in othervm mode. SunJSSE does not support dynamic system - * properties, no way to re-use system properties in samevm/agentvm mode. - */ -public class SSLTest { - - public static final String TEST_SRC = System.getProperty("test.src", "."); - - /* - * Where do we find the keystores? - */ - public static final String PATH_TO_STORES = "../etc"; - public static final String KEY_STORE_FILE = "keystore"; - public static final String TRUST_STORE_FILE = "truststore"; - public static final String PASSWORD = "passphrase"; - - public static final int FREE_PORT = 0; - - // in seconds - public static final long CLIENT_SIGNAL_TIMEOUT = 30L; - public static final long SERVER_SIGNAL_TIMEOUT = 90L; - - // in millis - public static final int CLIENT_TIMEOUT = 15000; - public static final int SERVER_TIMEOUT = 30000; - - /* - * Should we run the client or server in a separate thread? - * Both sides can throw exceptions, but do you have a preference - * as to which side should be the main thread. - */ - private boolean separateServerThread = false; - - /* - * What's the server port? Use any free port by default - */ - private volatile int serverPort; - - private volatile Exception serverException; - private volatile Exception clientException; - - private Thread clientThread; - private Thread serverThread; - - private Peer serverPeer; - private Peer clientPeer; - - private Application serverApplication; - private Application clientApplication; - - private SSLContext context; - - /* - * Is the server ready to serve? - */ - private final CountDownLatch serverReadyCondition = new CountDownLatch(1); - - /* - * Is the client ready to handshake? - */ - private final CountDownLatch clientReadyCondition = new CountDownLatch(1); - - /* - * Is the server done? - */ - private final CountDownLatch serverDoneCondition = new CountDownLatch(1); - - /* - * Is the client done? - */ - private final CountDownLatch clientDoneCondition = new CountDownLatch(1); - - /* - * Public API. - */ - - public static interface Peer { - void run(SSLTest test) throws Exception; - } - - public static interface Application { - void run(SSLSocket socket, SSLTest test) throws Exception; - } - - public static void debug() { - debug("ssl"); - } - - public static void debug(String mode) { - System.setProperty("javax.net.debug", mode); - } - - public static void setup(String keyFilename, String trustFilename, - String password) { - - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", password); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", password); - } - - public static void setup() throws Exception { - String keyFilename = TEST_SRC + "/" + PATH_TO_STORES + "/" - + KEY_STORE_FILE; - String trustFilename = TEST_SRC + "/" + PATH_TO_STORES + "/" - + TRUST_STORE_FILE; - - setup(keyFilename, trustFilename, PASSWORD); - } - - public static void print(String message, Throwable... errors) { - synchronized (System.out) { - System.out.println(message); - Arrays.stream(errors).forEach(e -> e.printStackTrace(System.out)); - } - } - - public static KeyStore loadJksKeyStore(String filename, String password) - throws Exception { - - return loadKeyStore(filename, password, "JKS"); - } - - public static KeyStore loadKeyStore(String filename, String password, - String type) throws Exception { - - KeyStore keystore = KeyStore.getInstance(type); - try (FileInputStream fis = new FileInputStream(filename)) { - keystore.load(fis, password.toCharArray()); - } - return keystore; - } - - // Try to accept a connection in 30 seconds. - public static SSLSocket accept(SSLServerSocket sslServerSocket) - throws IOException { - - return accept(sslServerSocket, SERVER_TIMEOUT); - } - - public static SSLSocket accept(SSLServerSocket sslServerSocket, int timeout) - throws IOException { - - try { - sslServerSocket.setSoTimeout(timeout); - return (SSLSocket) sslServerSocket.accept(); - } catch (SocketTimeoutException ste) { - sslServerSocket.close(); - return null; - } - } - - public SSLTest setSeparateServerThread(boolean separateServerThread) { - this.separateServerThread = separateServerThread; - return this; - } - - public SSLTest setServerPort(int serverPort) { - this.serverPort = serverPort; - return this; - } - - public int getServerPort() { - return serverPort; - } - - public SSLTest setSSLContext(SSLContext context) { - this.context = context; - return this; - } - - public SSLContext getSSLContext() { - return context; - } - - public SSLServerSocketFactory getSSLServerSocketFactory() { - if (context != null) { - return context.getServerSocketFactory(); - } - - return (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); - } - - public SSLSocketFactory getSSLSocketFactory() { - if (context != null) { - return context.getSocketFactory(); - } - - return (SSLSocketFactory) SSLSocketFactory.getDefault(); - } - - public void signalServerReady() { - serverReadyCondition.countDown(); - } - - public void signalServerDone() { - serverDoneCondition.countDown(); - } - - public boolean waitForClientSignal(long timeout, TimeUnit unit) - throws InterruptedException { - - return clientReadyCondition.await(timeout, unit); - } - - public boolean waitForClientSignal() throws InterruptedException { - return waitForClientSignal(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); - } - - public boolean waitForClientDone(long timeout, TimeUnit unit) - throws InterruptedException { - - return clientDoneCondition.await(timeout, unit); - } - - public boolean waitForClientDone() throws InterruptedException { - return waitForClientDone(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); - } - - public void signalClientReady() { - clientReadyCondition.countDown(); - } - - public void signalClientDone() { - clientDoneCondition.countDown(); - } - - public boolean waitForServerSignal(long timeout, TimeUnit unit) - throws InterruptedException { - - return serverReadyCondition.await(timeout, unit); - } - - public boolean waitForServerSignal() throws InterruptedException { - return waitForServerSignal(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); - } - - public boolean waitForServerDone(long timeout, TimeUnit unit) - throws InterruptedException { - - return serverDoneCondition.await(timeout, unit); - } - - public boolean waitForServerDone() throws InterruptedException { - return waitForServerDone(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); - } - - public SSLTest setServerPeer(Peer serverPeer) { - this.serverPeer = serverPeer; - return this; - } - - public Peer getServerPeer() { - return serverPeer; - } - - public SSLTest setServerApplication(Application serverApplication) { - this.serverApplication = serverApplication; - return this; - } - - public Application getServerApplication() { - return serverApplication; - } - - public SSLTest setClientPeer(Peer clientPeer) { - this.clientPeer = clientPeer; - return this; - } - - public Peer getClientPeer() { - return clientPeer; - } - - public SSLTest setClientApplication(Application clientApplication) { - this.clientApplication = clientApplication; - return this; - } - - public Application getClientApplication() { - return clientApplication; - } - - public void runTest() throws Exception { - if (separateServerThread) { - startServer(true, this); - startClient(false, this); - serverThread.join(); - } else { - startClient(true, this); - startServer(false, this); - clientThread.join(); - } - - if (clientException != null || serverException != null) { - throw new RuntimeException("Test failed"); - } - } - - public SSLTest() { - serverPeer = (test) -> doServerSide(test); - clientPeer = (test) -> doClientSide(test); - serverApplication = (socket, test) -> runServerApplication(socket); - clientApplication = (socket, test) -> runClientApplication(socket); - } - - /* - * Private part. - */ - - - /* - * Define the server side of the test. - */ - private static void doServerSide(SSLTest test) throws Exception { - SSLServerSocket sslServerSocket; - - // kick start the server side service - SSLServerSocketFactory sslssf = test.getSSLServerSocketFactory(); - sslServerSocket = (SSLServerSocket)sslssf.createServerSocket(FREE_PORT); - - test.setServerPort(sslServerSocket.getLocalPort()); - print("Server is listening on port " + test.getServerPort()); - - // Signal the client, the server is ready to accept connection. - test.signalServerReady(); - - // Try to accept a connection in 30 seconds. - SSLSocket sslSocket = accept(sslServerSocket); - if (sslSocket == null) { - // Ignore the test case if no connection within 30 seconds. - print("No incoming client connection in 30 seconds. " - + "Ignore in server side."); - return; - } - print("Server accepted connection"); - - // handle the connection - try { - // Is it the expected client connection? - // - // Naughty test cases or third party routines may try to - // connection to this server port unintentionally. In - // order to mitigate the impact of unexpected client - // connections and avoid intermittent failure, it should - // be checked that the accepted connection is really linked - // to the expected client. - boolean clientIsReady = test.waitForClientSignal(); - - if (clientIsReady) { - // Run the application in server side. - print("Run server application"); - test.getServerApplication().run(sslSocket, test); - } else { // Otherwise, ignore - // We don't actually care about plain socket connections - // for TLS communication testing generally. Just ignore - // the test if the accepted connection is not linked to - // the expected client or the client connection timeout - // in 30 seconds. - print("The client is not the expected one or timeout. " - + "Ignore in server side."); - } - } finally { - sslSocket.close(); - sslServerSocket.close(); - } - - test.signalServerDone(); - } - - /* - * Define the server side application of the test for the specified socket. - */ - private static void runServerApplication(SSLSocket socket) - throws Exception { - - // here comes the test logic - InputStream sslIS = socket.getInputStream(); - OutputStream sslOS = socket.getOutputStream(); - - sslIS.read(); - sslOS.write(85); - sslOS.flush(); - } - - /* - * Define the client side of the test. - */ - private static void doClientSide(SSLTest test) throws Exception { - - // Wait for server to get started. - // - // The server side takes care of the issue if the server cannot - // get started in 90 seconds. The client side would just ignore - // the test case if the serer is not ready. - boolean serverIsReady = test.waitForServerSignal(); - if (!serverIsReady) { - print("The server is not ready yet in 90 seconds. " - + "Ignore in client side."); - return; - } - - SSLSocketFactory sslsf = test.getSSLSocketFactory(); - try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { - try { - sslSocket.connect( - new InetSocketAddress("localhost", - test.getServerPort()), CLIENT_TIMEOUT); - print("Client connected to server"); - } catch (IOException ioe) { - // The server side may be impacted by naughty test cases or - // third party routines, and cannot accept connections. - // - // Just ignore the test if the connection cannot be - // established. - print("Cannot make a connection in 15 seconds. " - + "Ignore in client side.", ioe); - return; - } - - // OK, here the client and server get connected. - - // Signal the server, the client is ready to communicate. - test.signalClientReady(); - - // There is still a chance in theory that the server thread may - // wait client-ready timeout and then quit. The chance should - // be really rare so we don't consider it until it becomes a - // real problem. - - // Run the application in client side. - print("Run client application"); - test.getClientApplication().run(sslSocket, test); - } - - test.signalClientDone(); - } - - /* - * Define the client side application of the test for the specified socket. - */ - private static void runClientApplication(SSLSocket socket) - throws Exception { - - InputStream sslIS = socket.getInputStream(); - OutputStream sslOS = socket.getOutputStream(); - - sslOS.write(280); - sslOS.flush(); - sslIS.read(); - } - - private void startServer(boolean newThread, SSLTest test) throws Exception { - if (newThread) { - serverThread = new Thread() { - @Override - public void run() { - try { - serverPeer.run(test); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - print("Server died ...", e); - serverException = e; - } - } - }; - serverThread.start(); - } else { - try { - serverPeer.run(test); - } catch (Exception e) { - print("Server failed ...", e); - serverException = e; - } - } - } - - private void startClient(boolean newThread, SSLTest test) throws Exception { - if (newThread) { - clientThread = new Thread() { - @Override - public void run() { - try { - clientPeer.run(test); - } catch (Exception e) { - /* - * Our client thread just died. - */ - print("Client died ...", e); - clientException = e; - } - } - }; - clientThread.start(); - } else { - try { - clientPeer.run(test); - } catch (Exception e) { - print("Client failed ...", e); - clientException = e; - } - } - } -} diff --git a/jdk/test/javax/rmi/PortableRemoteObject/8146975/RmiIiopReturnValueTest.java b/jdk/test/javax/rmi/PortableRemoteObject/8146975/RmiIiopReturnValueTest.java index 87f5d866507..38f2c519845 100644 --- a/jdk/test/javax/rmi/PortableRemoteObject/8146975/RmiIiopReturnValueTest.java +++ b/jdk/test/javax/rmi/PortableRemoteObject/8146975/RmiIiopReturnValueTest.java @@ -24,8 +24,11 @@ /* * @test * @bug 8146975 + * @key intermittent * @summary test RMI-IIOP with value object return * @modules java.corba + * java.naming + * java.rmi * @library /lib/testlibrary * @build jdk.testlibrary.* * @compile Test.java Test3.java Test4.java diff --git a/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java b/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java index 4d2d279c995..998a66ab954 100644 --- a/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java +++ b/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java @@ -27,6 +27,8 @@ * @summary test RMI-IIOP call with ConcurrentHashMap as an argument * @library /lib/testlibrary * @modules java.corba + * java.naming + * java.rmi * @build jdk.testlibrary.* * @compile Test.java HelloInterface.java HelloServer.java HelloClient.java * HelloImpl.java _HelloImpl_Tie.java _HelloInterface_Stub.java ConcurrentHashMapTest.java diff --git a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java index 4e4b8379bad..a2f3fb034fa 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java @@ -63,7 +63,7 @@ import static java.nio.charset.StandardCharsets.US_ASCII; * authentication proxy */ -public class ProxyAuthTest { +public class ProxyAuthTest extends SSLSocketTemplate { /* * Where do we find the keystores? */ @@ -96,13 +96,13 @@ public class ProxyAuthTest { expectSuccess = args[0].equals("succeed"); String keyFilename = - SSLTest.TEST_SRC + "/" + pathToStores + "/" + keyStoreFile; + TEST_SRC + "/" + pathToStores + "/" + keyStoreFile; String trustFilename = - SSLTest.TEST_SRC + "/" + pathToStores + "/" + trustStoreFile; + TEST_SRC + "/" + pathToStores + "/" + trustStoreFile; - SSLTest.setup(keyFilename, trustFilename, passwd); + setup(keyFilename, trustFilename, passwd); - new SSLTest() + new SSLSocketTemplate() .setServerApplication((socket, test) -> { DataOutputStream out = new DataOutputStream( socket.getOutputStream()); @@ -164,7 +164,7 @@ public class ProxyAuthTest { .runTest(); } - static void doClientSide(SSLTest test) throws IOException { + static void doClientSide(SSLSocketTemplate test) throws IOException { // Wait for server to get started. // diff --git a/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java index 8543f9dd904..8554885d9fe 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java @@ -45,20 +45,20 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; -public class ServerIdentityTest { +public class ServerIdentityTest extends SSLSocketTemplate { private static final String PASSWORD = "changeit"; public static void main(String[] args) throws Exception { final String keystore = args[0]; - String keystoreFilename = SSLTest.TEST_SRC + "/" + keystore; + String keystoreFilename = TEST_SRC + "/" + keystore; - SSLTest.setup(keystoreFilename, keystoreFilename, PASSWORD); + setup(keystoreFilename, keystoreFilename, PASSWORD); SSLContext context = SSLContext.getInstance("SSL"); KeyManager[] kms = new KeyManager[1]; - KeyStore ks = SSLTest.loadJksKeyStore(keystoreFilename, PASSWORD); + KeyStore ks = loadJksKeyStore(keystoreFilename, PASSWORD); KeyManager km = new MyKeyManager(ks, PASSWORD.toCharArray()); kms[0] = km; context.init(kms, null, null); @@ -70,7 +70,7 @@ public class ServerIdentityTest { */ System.out.println("Testing " + keystore); - new SSLTest() + new SSLSocketTemplate() .setSSLContext(context) .setServerApplication((socket, test) -> { BufferedWriter bw = new BufferedWriter( @@ -79,12 +79,12 @@ public class ServerIdentityTest { bw.flush(); Thread.sleep(2000); socket.getSession().invalidate(); - SSLTest.print("Server application is done"); + print("Server application is done"); }) .setClientPeer((test) -> { boolean serverIsReady = test.waitForServerSignal(); if (!serverIsReady) { - SSLTest.print( + print( "The server is not ready, ignore on client side."); return; } @@ -100,7 +100,7 @@ public class ServerIdentityTest { ((HttpURLConnection) url.openConnection()) .getInputStream().close(); - SSLTest.print("Client is done"); + print("Client is done"); }).runTest(); } } diff --git a/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java b/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java index f91e78f1a38..3171d874258 100644 --- a/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java +++ b/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java @@ -74,6 +74,13 @@ public class ReplayCacheTestProc { private static List reqs = new ArrayList<>(); private static String HOST = "localhost"; + private static final String SERVICE; + + static { + String tmp = System.getProperty("test.service"); + SERVICE = (tmp == null) ? "service" : tmp; + } + // Where should the rcache be saved. It seems KRB5RCACHEDIR is not // recognized on Solaris. Maybe version too low? I see 1.6. private static String cwd = @@ -322,12 +329,12 @@ public class ReplayCacheTestProc { // returns the service name private static String service(int p) { - return "service" + p + "/" + HOST; + return SERVICE + p + "/" + HOST; } // returns the dfl name for a service private static String dfl(int p) { - return "service" + p + (uid == -1 ? "" : ("_"+uid)); + return SERVICE + p + (uid == -1 ? "" : ("_"+uid)); } // generates an ap-req and save into reqs, returns the index @@ -454,8 +461,8 @@ public class ReplayCacheTestProc { actual = Boolean.valueOf(reply); csize = csize(r.service); - String label = String.format("%03d-CLIENT%d-SERVICE%d-%s-%s", - i, r.client, r.service, acceptor.debug(), actual); + String label = String.format("%03d-client%d-%s%d-%s-%s", + i, r.client, SERVICE, r.service, acceptor.debug(), actual); record(label, r); if (new File(cwd, dfl(r.service)).exists()) { diff --git a/jdk/test/sun/security/krb5/auto/rcache_usemd5.sh b/jdk/test/sun/security/krb5/auto/rcache_usemd5.sh index a48ebd1bfb8..0d9a7d7a129 100644 --- a/jdk/test/sun/security/krb5/auto/rcache_usemd5.sh +++ b/jdk/test/sun/security/krb5/auto/rcache_usemd5.sh @@ -24,7 +24,8 @@ # @test # @bug 8168518 # @library ../../../../java/security/testlibrary/ /test/lib -# @run main/othervm/timeout=300 -Djdk.krb5.rcache.useMD5=true ReplayCacheTestProc +# @run main/othervm/timeout=300 -Djdk.krb5.rcache.useMD5=true +# -Dtest.service=host ReplayCacheTestProc # @summary testing jdk.krb5.rcache.useMD5. This action is put in a separate # test so that ReplayCacheTestProc.java can be launched with special # test.* system properties easily. diff --git a/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java index a380342616d..bb134aa4224 100644 --- a/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java +++ b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java @@ -42,7 +42,7 @@ import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocket; -public class AnonCipherWithWantClientAuth { +public class AnonCipherWithWantClientAuth extends SSLSocketTemplate { /* * Where do we find the keystores? @@ -62,16 +62,16 @@ public class AnonCipherWithWantClientAuth { String trustFilename = System.getProperty("test.src", "./") + "/" + pathToStores + "/" + trustStoreFile; - SSLTest.setup(keyFilename, trustFilename, passwd); + setup(keyFilename, trustFilename, passwd); - new SSLTest() + new SSLSocketTemplate() .setServerPeer(test -> { SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket sslServerSocket = - (SSLServerSocket) sslssf.createServerSocket(SSLTest.FREE_PORT); + (SSLServerSocket) sslssf.createServerSocket(FREE_PORT); test.setServerPort(sslServerSocket.getLocalPort()); - SSLTest.print("Server is listening on port " + print("Server is listening on port " + test.getServerPort()); String ciphers[] = { @@ -85,14 +85,14 @@ public class AnonCipherWithWantClientAuth { test.signalServerReady(); // Try to accept a connection in 30 seconds. - SSLSocket sslSocket = SSLTest.accept(sslServerSocket); + SSLSocket sslSocket = accept(sslServerSocket); if (sslSocket == null) { // Ignore the test case if no connection within 30 seconds. - SSLTest.print("No incoming client connection in 30 seconds." + print("No incoming client connection in 30 seconds." + " Ignore in server side."); return; } - SSLTest.print("Server accepted connection"); + print("Server accepted connection"); // handle the connection try { @@ -108,7 +108,7 @@ public class AnonCipherWithWantClientAuth { if (clientIsReady) { // Run the application in server side. - SSLTest.print("Run server application"); + print("Run server application"); InputStream sslIS = sslSocket.getInputStream(); OutputStream sslOS = sslSocket.getOutputStream(); diff --git a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java index e2ac09bd9e6..9ba18ac0f05 100644 --- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java +++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java @@ -58,7 +58,7 @@ import sun.security.x509.X500Name; /* * @test - * @bug 6543842 6543440 6939248 8009636 8024302 8163304 + * @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 * @summary checking response of timestamp * @modules java.base/sun.security.pkcs * java.base/sun.security.timestamp @@ -349,6 +349,18 @@ public class TimestampCheck { .shouldMatch("MD5withRSA.*-sigalg.*risk"); checkWeak("weak.jar"); + signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5") + .shouldHaveExitValue(0); + checkHalfWeak("halfWeak.jar"); + + // sign with DSA key + signWithAliasAndTsa("sign1", "old.jar", "dsakey") + .shouldHaveExitValue(0); + // sign with RSAkeysize < 1024 + signWithAliasAndTsa("sign2", "sign1.jar", "weakkeysize") + .shouldHaveExitValue(0); + checkMultiple("sign2.jar"); + // When .SF or .RSA is missing or invalid checkMissingOrInvalidFiles("normal.jar"); } else { // Run as a standalone server @@ -447,6 +459,37 @@ public class TimestampCheck { .shouldMatch("SignatureException:.*Disabled"); } + static void checkHalfWeak(String file) throws Throwable { + verify(file) + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled.") + .shouldMatch("Re-run jarsigner with the -verbose option for more details"); + verify(file, "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled by") + .shouldMatch("Digest algorithm: .*weak") + .shouldNotMatch("Signature algorithm: .*weak") + .shouldNotMatch("Timestamp digest algorithm: .*weak") + .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak") + .shouldNotMatch("Timestamp signature algorithm: .*key.*weak"); + } + + static void checkMultiple(String file) throws Throwable { + verify(file) + .shouldHaveExitValue(0) + .shouldContain("jar verified"); + verify(file, "-verbose", "-certs") + .shouldHaveExitValue(0) + .shouldContain("jar verified") + .shouldMatch("X.509.*CN=dsakey") + .shouldNotMatch("X.509.*CN=weakkeysize") + .shouldMatch("Signed by .*CN=dsakey") + .shouldMatch("Signed by .*CN=weakkeysize") + .shouldMatch("Signature algorithm: .*key.*weak"); + } + static void checkTimestamp(String file, String policyId, String digestAlg) throws Exception { try (JarFile jf = new JarFile(file)) { @@ -480,11 +523,16 @@ public class TimestampCheck { */ static OutputAnalyzer sign(String path, String... extra) throws Throwable { + String alias = path.equals("badku") ? "badku" : "old"; + return signWithAliasAndTsa(path, "old.jar", alias, extra); + } + + static OutputAnalyzer signWithAliasAndTsa (String path, String jar, + String alias, String...extra) throws Throwable { which++; System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra)); List args = List.of("-J-Djava.security.egd=file:/dev/./urandom", - "-debug", "-signedjar", path + ".jar", "old.jar", - path.equals("badku") ? "badku" : "old"); + "-debug", "-signedjar", path + ".jar", jar, alias); args = new ArrayList<>(args); if (!path.equals("none") && !path.equals("badku")) { args.add("-tsa"); @@ -499,6 +547,8 @@ public class TimestampCheck { Files.deleteIfExists(Paths.get("tsks")); keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); keytool("-alias old -genkeypair -dname CN=old"); + keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey"); + keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize"); keytool("-alias badku -genkeypair -dname CN=badku"); keytool("-alias ts -genkeypair -dname CN=ts"); keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1"); @@ -507,6 +557,8 @@ public class TimestampCheck { keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3"); gencert("old"); + gencert("dsakey"); + gencert("weakkeysize"); gencert("badku", "-ext ku:critical=keyAgreement"); gencert("ts", "-ext eku:critical=ts"); gencert("tsweak", "-ext eku:critical=ts"); diff --git a/jdk/test/sun/tools/jps/JpsBase.java b/jdk/test/sun/tools/jps/JpsBase.java deleted file mode 100644 index 1b810f357bb..00000000000 --- a/jdk/test/sun/tools/jps/JpsBase.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2014, 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.File; -import java.net.URL; -import java.util.List; - -import jdk.testlibrary.OutputAnalyzer; -import jdk.testlibrary.ProcessTools; - -/** - * The base class for testing the jps utility. - * The test sequence is to start jps with different combinations of arguments - * and verify the output contains proper values. - */ -public final class JpsBase { - - /** - * The jps output should contain processes' names - * (except when jps is started in quite mode). - * The expected name of the test process is prepared here. - */ - - private static String getShortProcessName() { - URL url = JpsBase.class.getResource("JpsBase.class"); - boolean isJar = url.getProtocol().equals("jar"); - return (isJar) ? JpsBase.class.getSimpleName() + ".jar" : JpsBase.class.getSimpleName(); - } - - private static String getFullProcessName() { - URL url = JpsBase.class.getResource("JpsBase.class"); - boolean isJar = url.getProtocol().equals("jar"); - if (isJar) { - String urlPath = url.getPath(); - File jar = new File(urlPath.substring(urlPath.indexOf("file:") + 5, urlPath.indexOf("jar!") + 3)); - return jar.getAbsolutePath(); - } - - return JpsBase.class.getName(); - } - - private static boolean userDirSanityCheck(String fullProcessName) { - String userDir = System.getProperty("user.dir"); - if (!fullProcessName.startsWith(userDir)) { - System.err.printf("Test skipped. user.dir '%s' is not a prefix of '%s'\n", userDir, fullProcessName); - return false; - } - return true; - } - - public static void main(String[] args) throws Exception { - System.out.printf("INFO: user.dir: '%s''\n", System.getProperty("user.dir")); - long pid = ProcessTools.getProcessId(); - - List> combinations = JpsHelper.JpsArg.generateCombinations(); - for (List combination : combinations) { - OutputAnalyzer output = JpsHelper.jps(JpsHelper.JpsArg.asCmdArray(combination)); - output.shouldHaveExitValue(0); - - boolean isQuiet = false; - boolean isFull = false; - String pattern; - for (JpsHelper.JpsArg jpsArg : combination) { - switch (jpsArg) { - case q: - // If '-q' is specified output should contain only a list of local VM identifiers: - // 30673 - isQuiet = true; - JpsHelper.verifyJpsOutput(output, "^\\d+$"); - output.shouldContain(Long.toString(pid)); - break; - case l: - // If '-l' is specified output should contain the full package name for the application's main class - // or the full path name to the application's JAR file: - // 30673 /tmp/jtreg/jtreg-workdir/scratch/JpsBase.jar ... - isFull = true; - String fullProcessName = getFullProcessName(); - // Skip the test if user.dir is not a prefix of the current path - // It's possible if the test is run from symlinked dir or windows alias drive - if (userDirSanityCheck(fullProcessName)) { - pattern = "^" + pid + "\\s+" + replaceSpecialChars(fullProcessName) + ".*"; - output.shouldMatch(pattern); - } - break; - case m: - // If '-m' is specified output should contain the arguments passed to the main method: - // 30673 JpsBase monkey ... - for (String arg : args) { - pattern = "^" + pid + ".*" + replaceSpecialChars(arg) + ".*"; - output.shouldMatch(pattern); - } - break; - case v: - // If '-v' is specified output should contain VM arguments: - // 30673 JpsBase -Xmx512m -XX:+UseParallelGC -XX:Flags=/tmp/jtreg/jtreg-workdir/scratch/vmflags ... - for (String vmArg : JpsHelper.getVmArgs()) { - pattern = "^" + pid + ".*" + replaceSpecialChars(vmArg) + ".*"; - output.shouldMatch(pattern); - } - break; - case V: - // If '-V' is specified output should contain VM flags: - // 30673 JpsBase +DisableExplicitGC ... - pattern = "^" + pid + ".*" + replaceSpecialChars(JpsHelper.VM_FLAG) + ".*"; - output.shouldMatch(pattern); - break; - } - - if (isQuiet) { - break; - } - } - - if (!isQuiet) { - // Verify output line by line. - // Output should only contain lines with pids after the first line with pid. - JpsHelper.verifyJpsOutput(output, "^\\d+\\s+.*"); - if (!isFull) { - String shortProcessName = getShortProcessName(); - pattern = "^" + pid + "\\s+" + replaceSpecialChars(shortProcessName); - if (combination.isEmpty()) { - // If no arguments are specified output should only contain - // pid and process name - pattern += "$"; - } else { - pattern += ".*"; - } - output.shouldMatch(pattern); - } - } - } - } - - private static String replaceSpecialChars(String str) { - String tmp = str.replace("\\", "\\\\"); - tmp = tmp.replace("+", "\\+"); - tmp = tmp.replace(".", "\\."); - tmp = tmp.replace("\n", "\\\\n"); - tmp = tmp.replace("\r", "\\\\r"); - return tmp; - } - -} diff --git a/jdk/test/sun/tools/jps/JpsHelper.java b/jdk/test/sun/tools/jps/JpsHelper.java index 3078ea5a336..be9ad0733d5 100644 --- a/jdk/test/sun/tools/jps/JpsHelper.java +++ b/jdk/test/sun/tools/jps/JpsHelper.java @@ -204,44 +204,85 @@ public final class JpsHelper { "The ouput should contain all content of " + path.toAbsolutePath()); } - private static File getManifest(String className) throws IOException { - if (manifestFile == null) { - manifestFile = new File(className + ".mf"); - try (BufferedWriter output = new BufferedWriter(new FileWriter(manifestFile))) { - output.write("Main-Class: " + className + Utils.NEW_LINE); + public static void runJpsVariants(Long pid, String processName, String fullProcessName, String argument) throws Exception { + System.out.printf("INFO: user.dir: '%s''\n", System.getProperty("user.dir")); + List> combinations = JpsHelper.JpsArg.generateCombinations(); + for (List combination : combinations) { + OutputAnalyzer output = JpsHelper.jps(JpsHelper.JpsArg.asCmdArray(combination)); + output.shouldHaveExitValue(0); + + boolean isQuiet = false; + boolean isFull = false; + String pattern; + for (JpsHelper.JpsArg jpsArg : combination) { + switch (jpsArg) { + case q: + // If '-q' is specified output should contain only a list of local VM identifiers: + // 30673 + isQuiet = true; + JpsHelper.verifyJpsOutput(output, "^\\d+$"); + output.shouldContain(Long.toString(pid)); + break; + case l: + // If '-l' is specified output should contain the full package name for the application's main class + // or the full path name to the application's JAR file: + // 30673 /tmp/jtreg/jtreg-workdir/scratch/LingeredAppForJps.jar ... + isFull = true; + pattern = "^" + pid + "\\s+" + replaceSpecialChars(fullProcessName) + ".*"; + output.shouldMatch(pattern); + break; + case m: + // If '-m' is specified output should contain the arguments passed to the main method: + // 30673 LingeredAppForJps lockfilename ... + pattern = "^" + pid + ".*" + replaceSpecialChars(argument) + ".*"; + output.shouldMatch(pattern); + break; + case v: + // If '-v' is specified output should contain VM arguments: + // 30673 LingeredAppForJps -Xmx512m -XX:+UseParallelGC -XX:Flags=/tmp/jtreg/jtreg-workdir/scratch/vmflags ... + for (String vmArg : JpsHelper.getVmArgs()) { + pattern = "^" + pid + ".*" + replaceSpecialChars(vmArg) + ".*"; + output.shouldMatch(pattern); + } + break; + case V: + // If '-V' is specified output should contain VM flags: + // 30673 LingeredAppForJps +DisableExplicitGC ... + pattern = "^" + pid + ".*" + replaceSpecialChars(JpsHelper.VM_FLAG) + ".*"; + output.shouldMatch(pattern); + break; + } + + if (isQuiet) { + break; + } + } + + if (!isQuiet) { + // Verify output line by line. + // Output should only contain lines with pids after the first line with pid. + JpsHelper.verifyJpsOutput(output, "^\\d+\\s+.*"); + if (!isFull) { + pattern = "^" + pid + "\\s+" + replaceSpecialChars(processName); + if (combination.isEmpty()) { + // If no arguments are specified output should only contain + // pid and process name + pattern += "$"; + } else { + pattern += ".*"; + } + output.shouldMatch(pattern); + } } } - return manifestFile; } - /** - * Build a jar of test classes in runtime - */ - public static File buildJar(String className) throws Exception { - File jar = new File(className + ".jar"); - - List jarArgs = new ArrayList<>(); - jarArgs.add("-cfm"); - jarArgs.add(jar.getAbsolutePath()); - File manifestFile = getManifest(className); - jarArgs.add(manifestFile.getAbsolutePath()); - String testClassPath = System.getProperty("test.class.path", "?"); - for (String path : testClassPath.split(File.pathSeparator)) { - jarArgs.add("-C"); - jarArgs.add(path); - jarArgs.add("."); - } - - System.out.println("Running jar " + jarArgs.toString()); - sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); - if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) { - throw new Exception("jar failed: args=" + jarArgs.toString()); - } - - manifestFile.delete(); - jar.deleteOnExit(); - - return jar; + private static String replaceSpecialChars(String str) { + String tmp = str.replace("\\", "\\\\"); + tmp = tmp.replace("+", "\\+"); + tmp = tmp.replace(".", "\\."); + tmp = tmp.replace("\n", "\\\\n"); + tmp = tmp.replace("\r", "\\\\r"); + return tmp; } - } diff --git a/jdk/test/sun/tools/jps/LingeredApp.java b/jdk/test/sun/tools/jps/LingeredApp.java new file mode 100644 index 00000000000..b4aab24bc41 --- /dev/null +++ b/jdk/test/sun/tools/jps/LingeredApp.java @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2015, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * This is a framework to launch an app that could be synchronized with caller + * to make further attach actions reliable across supported platforms + + * Caller example: + * SmartTestApp a = SmartTestApp.startApp(cmd); + * // do something + * a.stopApp(); + * + * or fine grained control + * + * a = new SmartTestApp("MyLock.lck"); + * a.createLock(); + * a.runApp(); + * a.waitAppReady(); + * // do something + * a.deleteLock(); + * a.waitAppTerminate(); + * + * Then you can work with app output and process object + * + * output = a.getAppOutput(); + * process = a.getProcess(); + * + */ +public class LingeredApp { + + private static final long spinDelay = 1000; + + private long lockCreationTime; + private final ArrayList storedAppOutput; + + protected Process appProcess; + protected static final int appWaitTime = 100; + protected final String lockFileName; + + /* + * Drain child process output, store it into string array + */ + class InputGobbler extends Thread { + + InputStream is; + List astr; + + InputGobbler(InputStream is, List astr) { + this.is = is; + this.astr = astr; + } + + public void run() { + try { + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line = null; + while ((line = br.readLine()) != null) { + astr.add(line); + } + } catch (IOException ex) { + // pass + } + } + } + + /** + * Create LingeredApp object on caller side. Lock file have be a valid filename + * at writable location + * + * @param lockFileName - the name of lock file + */ + public LingeredApp(String lockFileName) { + this.lockFileName = lockFileName; + this.storedAppOutput = new ArrayList(); + } + + public LingeredApp() { + final String lockName = UUID.randomUUID().toString() + ".lck"; + this.lockFileName = lockName; + this.storedAppOutput = new ArrayList(); + } + + /** + * + * @return name of lock file + */ + public String getLockFileName() { + return this.lockFileName; + } + + /** + * + * @return name of testapp + */ + public String getAppName() { + return this.getClass().getName(); + } + + /** + * + * @return pid of java process running testapp + */ + public long getPid() { + if (appProcess == null) { + throw new RuntimeException("Process is not alive"); + } + return appProcess.getPid(); + } + + /** + * + * @return process object + */ + public Process getProcess() { + return appProcess; + } + + /** + * + * @return application output as string array. Empty array if application produced no output + */ + public List getAppOutput() { + if (appProcess.isAlive()) { + throw new RuntimeException("Process is still alive. Can't get its output."); + } + return storedAppOutput; + } + + /* Make sure all part of the app use the same method to get dates, + as different methods could produce different results + */ + private static long epoch() { + return new Date().getTime(); + } + + private static long lastModified(String fileName) throws IOException { + Path path = Paths.get(fileName); + BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class); + return attr.lastModifiedTime().toMillis(); + } + + private static void setLastModified(String fileName, long newTime) throws IOException { + Path path = Paths.get(fileName); + FileTime fileTime = FileTime.fromMillis(newTime); + Files.setLastModifiedTime(path, fileTime); + } + + /** + * create lock + * + * @throws IOException + */ + public void createLock() throws IOException { + Path path = Paths.get(lockFileName); + // Files.deleteIfExists(path); + Files.createFile(path); + lockCreationTime = lastModified(lockFileName); + } + + /** + * Delete lock + * + * @throws IOException + */ + public void deleteLock() throws IOException { + try { + Path path = Paths.get(lockFileName); + Files.delete(path); + } catch (NoSuchFileException ex) { + // Lock already deleted. Ignore error + } + } + + public void waitAppTerminate() { + while (true) { + try { + appProcess.waitFor(); + break; + } catch (InterruptedException ex) { + // pass + } + } + } + + /** + * The app touches the lock file when it's started + * wait while it happens. Caller have to delete lock on wait error. + * + * @param timeout + * @throws java.io.IOException + */ + public void waitAppReady(long timeout) throws IOException { + long here = epoch(); + while (true) { + long epoch = epoch(); + if (epoch - here > (timeout * 1000)) { + throw new IOException("App waiting timeout"); + } + + // Live process should touch lock file every second + long lm = lastModified(lockFileName); + if (lm > lockCreationTime) { + break; + } + + // Make sure process didn't already exit + if (!appProcess.isAlive()) { + throw new IOException("App exited unexpectedly with " + appProcess.exitValue()); + } + + try { + Thread.sleep(spinDelay); + } catch (InterruptedException ex) { + // pass + } + } + } + + /** + * Analyze an environment and prepare a command line to + * run the app, app name should be added explicitly + */ + public List runAppPrepare(List vmArguments) { + // We should always use testjava or throw an exception, + // so we can't use JDKToolFinder.getJDKTool("java"); + // that falls back to compile java on error + String jdkPath = System.getProperty("test.jdk"); + if (jdkPath == null) { + // we are not under jtreg, try env + Map env = System.getenv(); + jdkPath = env.get("TESTJAVA"); + } + + if (jdkPath == null) { + throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set"); + } + + String osname = System.getProperty("os.name"); + String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java"); + + List cmd = new ArrayList(); + cmd.add(javapath); + + + if (vmArguments == null) { + // Propagate test.vm.options to LingeredApp, filter out possible empty options + String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+"); + for (String s : testVmOpts) { + if (!s.equals("")) { + cmd.add(s); + } + } + } + else{ + // Lets user manage LingeredApp options + cmd.addAll(vmArguments); + } + + // Make sure we set correct classpath to run the app + cmd.add("-cp"); + String classpath = System.getProperty("test.class.path"); + cmd.add((classpath == null) ? "." : classpath); + + return cmd; + } + + /** + * Assemble command line to a printable string + */ + public void printCommandLine(List cmd) { + // A bit of verbosity + StringBuilder cmdLine = new StringBuilder(); + for (String strCmd : cmd) { + cmdLine.append("'").append(strCmd).append("' "); + } + + System.out.println("Command line: [" + cmdLine.toString() + "]"); + } + + public void startGobblerPipe() { + // Create pipe reader for process, and read stdin and stderr to array of strings + InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput); + gb.start(); + } + + /** + * Run the app. + * + * @param vmArguments + * @throws IOException + */ + public void runApp(List vmArguments) + throws IOException { + + List cmd = runAppPrepare(vmArguments); + + cmd.add(this.getAppName()); + cmd.add(lockFileName); + + printCommandLine(cmd); + + ProcessBuilder pb = new ProcessBuilder(cmd); + // we don't expect any error output but make sure we are not stuck on pipe + // pb.redirectErrorStream(false); + // ProcessBuilder.start can throw IOException + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + appProcess = pb.start(); + + startGobblerPipe(); + } + + /** + * Delete lock file that signals app to terminate, then + * wait until app is actually terminated. + * @throws IOException + */ + public void stopApp() throws IOException { + deleteLock(); + // The startApp() of the derived app can throw + // an exception before the LA actually starts + if (appProcess != null) { + waitAppTerminate(); + int exitcode = appProcess.exitValue(); + if (exitcode != 0) { + throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode); + } + } + } + + /** + * High level interface for test writers + */ + /** + * Factory method that creates LingeredApp object with ready to use application + * lock name is autogenerated + * @param cmd - vm options, could be null to auto add testvm.options + * @return LingeredApp object + * @throws IOException + */ + public static LingeredApp startApp(List cmd) throws IOException { + LingeredApp a = new LingeredApp(); + a.createLock(); + try { + a.runApp(cmd); + a.waitAppReady(appWaitTime); + } catch (Exception ex) { + a.deleteLock(); + throw ex; + } + + return a; + } + + /** + * Factory method that starts pre-created LingeredApp + * lock name is autogenerated + * @param cmd - vm options, could be null to auto add testvm.options + * @param theApp - app to start + * @return LingeredApp object + * @throws IOException + */ + + public static void startApp(List cmd, LingeredApp theApp) throws IOException { + theApp.createLock(); + try { + theApp.runApp(cmd); + theApp.waitAppReady(appWaitTime); + } catch (Exception ex) { + theApp.deleteLock(); + throw ex; + } + } + + public static LingeredApp startApp() throws IOException { + return startApp(null); + } + + public static void stopApp(LingeredApp app) throws IOException { + if (app != null) { + // LingeredApp can throw an exception during the intialization, + // make sure we don't have cascade NPE + app.stopApp(); + } + } + + /** + * LastModified time might not work correctly in some cases it might + * cause later failures + */ + + public static boolean isLastModifiedWorking() { + boolean sane = true; + try { + long lm = lastModified("."); + if (lm == 0) { + System.err.println("SANITY Warning! The lastModifiedTime() doesn't work on this system, it returns 0"); + sane = false; + } + + long now = epoch(); + if (lm > now) { + System.err.println("SANITY Warning! The Clock is wrong on this system lastModifiedTime() > getTime()"); + sane = false; + } + + setLastModified(".", epoch()); + long lm1 = lastModified("."); + if (lm1 <= lm) { + System.err.println("SANITY Warning! The setLastModified doesn't work on this system"); + sane = false; + } + } + catch(IOException e) { + System.err.println("SANITY Warning! IOException during sanity check " + e); + sane = false; + } + + return sane; + } + + /** + * This part is the application it self + */ + public static void main(String args[]) { + + if (args.length != 1) { + System.err.println("Lock file name is not specified"); + System.exit(7); + } + + String theLockFileName = args[0]; + + try { + Path path = Paths.get(theLockFileName); + + while (Files.exists(path)) { + // Touch the lock to indicate our readiness + setLastModified(theLockFileName, epoch()); + Thread.sleep(spinDelay); + } + } catch (NoSuchFileException ex) { + // Lock deleted while we are setting last modified time. + // Ignore error and lets the app exits + } catch (Exception ex) { + System.err.println("LingeredApp ERROR: " + ex); + // Leave exit_code = 1 to Java launcher + System.exit(3); + } + + System.exit(0); + } +} diff --git a/jdk/test/sun/tools/jps/LingeredAppForJps.java b/jdk/test/sun/tools/jps/LingeredAppForJps.java new file mode 100644 index 00000000000..f2407411b77 --- /dev/null +++ b/jdk/test/sun/tools/jps/LingeredAppForJps.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.net.URL; + +public class LingeredAppForJps extends LingeredApp { + + // Copy runApp logic here to be able to run an app from JarFile + public void runAppWithName(List vmArguments, String runName) + throws IOException { + + List cmd = runAppPrepare(vmArguments); + if (runName.endsWith(".jar")) { + cmd.add("-Xdiag"); + cmd.add("-jar"); + } + cmd.add(runName); + cmd.add(lockFileName); + + printCommandLine(cmd); + + ProcessBuilder pb = new ProcessBuilder(cmd); + // we don't expect any error output but make sure we are not stuck on pipe + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + appProcess = pb.start(); + startGobblerPipe(); + } + + public static LingeredApp startAppJar(List cmd, LingeredAppForJps app, File jar) throws IOException { + app.createLock(); + try { + app.runAppWithName(cmd, jar.getAbsolutePath()); + app.waitAppReady(appWaitTime); + } catch (Exception ex) { + app.deleteLock(); + throw ex; + } + + return app; + } + + /** + * The jps output should contain processes' names + * (except when jps is started in quite mode). + * The expected name of the test process is prepared here. + */ + public static String getProcessName() { + return LingeredAppForJps.class.getSimpleName(); + } + + public static String getProcessName(File jar) { + return jar.getName(); + } + + // full package name for the application's main class or the full path + // name to the application's JAR file: + + public static String getFullProcessName() { + return LingeredAppForJps.class.getCanonicalName(); + } + + public static String getFullProcessName(File jar) { + return jar.getAbsolutePath(); + } + + public static File buildJar() throws IOException { + String className = LingeredAppForJps.class.getName(); + File jar = new File(className + ".jar"); + String testClassPath = System.getProperty("test.class.path", "?"); + + File manifestFile = new File(className + ".mf"); + String nl = System.getProperty("line.separator"); + try (BufferedWriter output = new BufferedWriter(new FileWriter(manifestFile))) { + output.write("Main-Class: " + className + nl); + } + + List jarArgs = new ArrayList<>(); + jarArgs.add("-cfm"); + jarArgs.add(jar.getAbsolutePath()); + jarArgs.add(manifestFile.getAbsolutePath()); + + for (String path : testClassPath.split(File.pathSeparator)) { + String classFullName = path + File.separator + className + ".class"; + File f = new File(classFullName); + if (f.exists()) { + jarArgs.add("-C"); + jarArgs.add(path); + jarArgs.add("."); + System.out.println("INFO: scheduled to jar " + path); + break; + } + } + + System.out.println("Running jar " + jarArgs.toString()); + sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); + if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) { + throw new IOException("jar failed: args=" + jarArgs.toString()); + } + + manifestFile.delete(); + jar.deleteOnExit(); + + // Print content of jar file + System.out.println("Content of jar file" + jar.getAbsolutePath()); + + jarArgs = new ArrayList<>(); + jarArgs.add("-tvf"); + jarArgs.add(jar.getAbsolutePath()); + + jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); + if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) { + throw new IOException("jar failed: args=" + jarArgs.toString()); + } + + return jar; + } + + public static void main(String args[]) { + LingeredApp.main(args); + } + } diff --git a/jdk/test/sun/tools/jps/TestJps.java b/jdk/test/sun/tools/jps/TestJps.java new file mode 100644 index 00000000000..f8a84261c81 --- /dev/null +++ b/jdk/test/sun/tools/jps/TestJps.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /lib/testlibrary /test/lib + * @modules jdk.jartool/sun.tools.jar + * @build LingeredAppForJps + * @build LingeredApp + * @run main/othervm TestJps + */ + + /* + * Notes: + * @modules tag is ignored in driver mode, so need main/othervm + * + * Launching the process with relative path to an app jar file is not tested + * + * This test resides in default package, so correct appearance + * of the full package name actually is not tested. + */ + +import java.util.List; +import java.io.File; + +public class TestJps { + + public static void testJpsClass() throws Throwable { + LingeredApp app = new LingeredAppForJps(); + try { + LingeredApp.startApp(JpsHelper.getVmArgs(), app); + JpsHelper.runJpsVariants(app.getPid(), + LingeredAppForJps.getProcessName(), LingeredAppForJps.getFullProcessName(), app.getLockFileName()); + + } finally { + LingeredApp.stopApp(app); + } + } + + public static void testJpsJar() throws Throwable { + // Get any jar exception as early as possible + File jar = LingeredAppForJps.buildJar(); + + // Jar created go to the main test + LingeredAppForJps app = new LingeredAppForJps(); + try { + LingeredAppForJps.startAppJar(JpsHelper.getVmArgs(), app, jar); + JpsHelper.runJpsVariants(app.getPid(), + LingeredAppForJps.getProcessName(jar), LingeredAppForJps.getFullProcessName(jar), app.getLockFileName()); + } finally { + LingeredAppForJps.stopApp(app); + } + + } + + public static void main(String[] args) throws Throwable { + testJpsClass(); + testJpsJar(); + } +} diff --git a/jdk/test/sun/tools/jps/TestJpsClass.java b/jdk/test/sun/tools/jps/TestJpsClass.java deleted file mode 100644 index 7cde3ce57b8..00000000000 --- a/jdk/test/sun/tools/jps/TestJpsClass.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.ArrayList; -import java.util.List; - -import jdk.testlibrary.OutputAnalyzer; -import jdk.testlibrary.ProcessTools; - -/* - * @test - * @summary The test application will be started with java class: - * java JpsBase - * For all possible combinations of jps arguments a jps process - * will be started from within the test application. - * The output should contain proper values. - * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar - * java.management - * @build jdk.testlibrary.* JpsHelper JpsBase - * @run driver TestJpsClass - */ -public class TestJpsClass { - - public static void main(String[] args) throws Throwable { - String testJdk = System.getProperty("test.jdk", "?"); - String testSrc = System.getProperty("test.src", "?"); - String testClassPath = System.getProperty("test.class.path", "?"); - - List cmd = new ArrayList<>(); - cmd.addAll(JpsHelper.getVmArgs()); - cmd.add("-Dtest.jdk=" + testJdk); - cmd.add("-Dtest.src=" + testSrc); - cmd.add("-cp"); - cmd.add(testClassPath); - cmd.add("JpsBase"); - cmd.add("monkey"); - - ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd.toArray(new String[cmd.size()])); - OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); - System.out.println(output.getOutput()); - output.shouldHaveExitValue(0); - } - -} diff --git a/jdk/test/sun/tools/jps/TestJpsJar.java b/jdk/test/sun/tools/jps/TestJpsJar.java deleted file mode 100644 index 97d744ec85f..00000000000 --- a/jdk/test/sun/tools/jps/TestJpsJar.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2014, 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import jdk.testlibrary.OutputAnalyzer; -import jdk.testlibrary.ProcessTools; - -/* - * @test - * @summary The test application will be started with absolute jar: - * java -jar /tmp/jtreg/jtreg-workdir/scratch/JpsBase.jar - * For all possible combinations of jps arguments a jps process - * will be started from within the test application. - * The output should contain proper values. - * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar - * java.management - * @build JpsHelper JpsBase - * @run main/othervm TestJpsJar - */ -public class TestJpsJar { - - public static void main(String[] args) throws Throwable { - String testJdk = System.getProperty("test.jdk", "?"); - String testSrc = System.getProperty("test.src", "?"); - File jar = JpsHelper.buildJar("JpsBase"); - - List cmd = new ArrayList<>(); - cmd.addAll(JpsHelper.getVmArgs()); - cmd.add("-Dtest.jdk=" + testJdk); - cmd.add("-Dtest.src=" + testSrc); - cmd.add("-Duser.dir=" + System.getProperty("user.dir")); - cmd.add("-jar"); - cmd.add(jar.getAbsolutePath()); - cmd.add("monkey"); - - ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd.toArray(new String[cmd.size()])); - OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); - System.out.println(output.getOutput()); - output.shouldHaveExitValue(0); - } - -} diff --git a/jdk/test/sun/tools/jps/TestJpsJarRelative.java b/jdk/test/sun/tools/jps/TestJpsJarRelative.java deleted file mode 100644 index 12282959105..00000000000 --- a/jdk/test/sun/tools/jps/TestJpsJarRelative.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import jdk.testlibrary.OutputAnalyzer; -import jdk.testlibrary.ProcessTools; - -/* - * @test - * @summary The test application will be started with relative jar: - * java -jar ./JpsBase.jar - * For all possible combinations of jps arguments a jps process - * will be started from within the test application. - * The output should contain proper values. - * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar - * java.management - * @build jdk.testlibrary.* JpsHelper JpsBase - * @run main/othervm TestJpsJarRelative - */ -public class TestJpsJarRelative { - - public static void main(String[] args) throws Throwable { - String testJdk = System.getProperty("test.jdk", "?"); - String testSrc = System.getProperty("test.src", "?"); - File jar = JpsHelper.buildJar("JpsBase"); - - List cmd = new ArrayList<>(); - cmd.addAll(JpsHelper.getVmArgs()); - cmd.add("-Dtest.jdk=" + testJdk); - cmd.add("-Dtest.src=" + testSrc); - cmd.add("-jar"); - cmd.add("." + File.separator + jar.getName()); - cmd.add("monkey"); - - ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd.toArray(new String[cmd.size()])); - OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); - System.out.println(output.getOutput()); - output.shouldHaveExitValue(0); - } - -} diff --git a/jdk/test/sun/tools/jps/TestJpsSanity.java b/jdk/test/sun/tools/jps/TestJpsSanity.java index 47d15635961..fa1cf9e8c91 100644 --- a/jdk/test/sun/tools/jps/TestJpsSanity.java +++ b/jdk/test/sun/tools/jps/TestJpsSanity.java @@ -96,7 +96,7 @@ public class TestJpsSanity { } private static void testJpsUnknownHost() throws Exception { - String invalidHostName = "Oja781nh2ev7vcvbajdg-Sda1-C"; + String invalidHostName = "Oja781nh2ev7vcvbajdg-Sda1-C.invalid"; OutputAnalyzer output = JpsHelper.jps(invalidHostName); Asserts.assertNotEquals(output.getExitValue(), 0, "Exit code shouldn't be 0"); Asserts.assertFalse(output.getStderr().isEmpty(), "Error output should not be empty"); diff --git a/jdk/test/tools/jimage/JImageBasicsTest.java b/jdk/test/tools/jimage/JImageBasicsTest.java new file mode 100644 index 00000000000..adfc8106d89 --- /dev/null +++ b/jdk/test/tools/jimage/JImageBasicsTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests to verify jimage basic options, i.e. --version, -h + * @library /test/lib + * @modules jdk.jlink/jdk.tools.jimage + * @build jdk.test.lib.Asserts + * @run main JImageBasicsTest + */ + +import static jdk.test.lib.Asserts.assertTrue; + +public class JImageBasicsTest extends JImageCliTest { + + public void testVersion() { + jimage("--version") + .assertSuccess() + .resultChecker(r -> { + assertTrue(r.output.contains(System.getProperty("java.version")), "Contains java version."); + }); + } + + public void testFullVersion() { + jimage("--full-version") + .assertSuccess() + .resultChecker(r -> { + assertTrue(r.output.contains(System.getProperty("java.version")), "Contains java version."); + }); + } + + public void testHelp() { + jimage("--help") + .assertSuccess() + .resultChecker(r -> verifyHelpOutput(r.output)); + } + + public void testShortHelp() { + jimage("-h") + .assertSuccess() + .resultChecker(r -> verifyHelpOutput(r.output)); + } + + public void testUnknownAction() { + jimage("unknown") + .assertFailure() + .assertShowsError(); + } + + public void testUnknownOption() { + jimage("--unknown") + .assertFailure() + .assertShowsError(); + } + + private void verifyHelpOutput(String output) { + assertTrue(output.startsWith("Usage: jimage"), "Usage is printed."); + assertTrue(output.contains("extract"), "Option 'extract' is found."); + assertTrue(output.contains("info"), "Option 'info' is found."); + assertTrue(output.contains("list"), "Option 'list' is found."); + assertTrue(output.contains("verify"), "Option 'verify' is found."); + } + + public static void main(String[] args) throws Throwable { + new JImageBasicsTest().runTests(); + } +} + diff --git a/jdk/test/tools/jimage/JImageCliTest.java b/jdk/test/tools/jimage/JImageCliTest.java new file mode 100644 index 00000000000..da924d5ff94 --- /dev/null +++ b/jdk/test/tools/jimage/JImageCliTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.function.Consumer; +import java.util.regex.Pattern; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertTrue; +import static jdk.test.lib.Asserts.fail; + +/** + * This class is intended to be a base class for classes which are about to test + * command line interface of jimage. + */ +public class JImageCliTest { + + private String bootImagePath; + + public JImageCliTest() { + Path imagePath = Paths.get(System.getProperty("java.home"), "lib", "modules"); + if (Files.exists(imagePath)) { + this.bootImagePath = imagePath.toAbsolutePath().toString(); + } + } + + public void assertMatches(String regex, String output) { + Pattern pattern = Pattern.compile(regex); + if (!pattern.matcher(output).find()) { + fail(String.format("Expected to find a string match for [%s] in output \n[\n%s\n]\n.", + pattern, output)); + } + } + + /** + * Returns a path to a tested image to share it across tests. By default it returns a path to the boot image + * of tested JDK. This behavior can be redefined by descendants. + */ + public String getImagePath() { + return bootImagePath; + } + + /** + * Runs jimage task with the supplied arguments. + */ + protected static JImageResult jimage(String... args) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + System.out.println("jimage " + Arrays.asList(args)); + int exitCode = jdk.tools.jimage.Main.run(args, new PrintWriter(ps)); + return new JImageResult(exitCode, new String(baos.toByteArray(), UTF_8)); + } + + protected static class JImageResult { + final int exitCode; + final String output; + + JImageResult(int exitCode, String output) { + this.exitCode = exitCode; + this.output = output; + } + + JImageResult assertSuccess() { assertTrue(exitCode == 0, output); return this; } + JImageResult assertFailure() { assertFalse(exitCode == 0, output); return this; } + + // a helper to ensure the error output doesn't exhibit implementation details + JImageResult assertShowsError() { + assertTrue(output.contains("Error"), + String.format("Output contains error, output=[%s]\n", output)); + assertFalse(output.contains("Exception"), + String.format("Output doesn't contain a stacktrace, output=[%s]\n", output)); + return this; + } + + JImageResult resultChecker(Consumer r) { r.accept(this); return this; } + } + + protected final void runTests() throws Throwable { + if (getImagePath() != null) { + for (Method m : getClass().getDeclaredMethods()) { + if (m.getName().startsWith("test")) { + System.out.printf("Invoking %s\n", m.getName()); + m.invoke(this); + } + } + } else { + System.out.println("This is not an image build. Skipping."); + } + } + +} + diff --git a/jdk/test/tools/jimage/JImageExtractTest.java b/jdk/test/tools/jimage/JImageExtractTest.java new file mode 100644 index 00000000000..9c015471414 --- /dev/null +++ b/jdk/test/tools/jimage/JImageExtractTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests to verify jimage 'extract' action + * @library /test/lib + * @modules jdk.jlink/jdk.tools.jimage + * @build jdk.test.lib.Asserts + * @run main/othervm JImageExtractTest + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertTrue; + +public class JImageExtractTest extends JImageCliTest { + public void testExtract() throws IOException { + jimage("extract", getImagePath()) + .assertSuccess() + .resultChecker(r -> { + assertTrue(r.output.isEmpty(), "Output is not expected"); + }); + verifyExplodedImage(Paths.get(".")); + } + + public void testExtractHelp() { + for (String opt : Arrays.asList("-h", "--help")) { + jimage("extract", "--help") + .assertSuccess() + .resultChecker(r -> { + // extract - descriptive text + assertMatches("\\s+extract\\s+-\\s+.*", r.output); + }); + } + } + + public void testExtractToDir() throws IOException { + Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName()); + jimage("extract", "--dir", tmp.toString(), getImagePath()) + .assertSuccess() + .resultChecker(r -> { + assertTrue(r.output.isEmpty(), "Output is not expected"); + }); + verifyExplodedImage(tmp); + } + + public void testExtractNoImageSpecified() { + jimage("extract", "") + .assertFailure() + .assertShowsError(); + } + + public void testExtractNotAnImage() throws IOException { + Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_an_image"); + jimage("extract", tmp.toString()) + .assertFailure() + .assertShowsError(); + } + + public void testExtractNotExistingImage() throws IOException { + Path tmp = Paths.get(".", "not_existing_image"); + Files.deleteIfExists(tmp); + jimage("extract", tmp.toString()) + .assertFailure() + .assertShowsError(); + } + + public void testExtractToUnspecifiedDir() { + jimage("extract", "--dir", "--", getImagePath()) + .assertFailure() + .assertShowsError(); + } + + public void testExtractToNotExistingDir() throws IOException { + Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName()); + Files.delete(tmp); + jimage("extract", "--dir", tmp.toString(), getImagePath()) + .assertSuccess() + .resultChecker(r -> { + assertTrue(r.output.isEmpty(), "Output is not expected"); + }); + verifyExplodedImage(tmp); + } + + public void testExtractFromDir() { + Path imagePath = Paths.get(getImagePath()); + Path imageDirPath = imagePath.subpath(0, imagePath.getNameCount() - 1); + jimage("extract", imageDirPath.toString()) + .assertFailure() + .assertShowsError(); + } + + public void testExtractToDirBySymlink() throws IOException { + Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName()); + try { + Path symlink = Files.createSymbolicLink(Paths.get(".", "symlink"), tmp); + jimage("extract", "--dir", symlink.toString(), getImagePath()) + .assertSuccess() + .resultChecker(r -> { + assertTrue(r.output.isEmpty(), "Output is not expected"); + }); + verifyExplodedImage(tmp); + } catch (UnsupportedOperationException e) { + // symlinks are not supported + // nothing to test + } + } + + public void testExtractToReadOnlyDir() throws IOException { + Set perms = PosixFilePermissions.fromString("r-xr--r--"); + FileAttribute> atts = PosixFilePermissions.asFileAttribute(perms); + Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName(), atts); + jimage("extract", "--dir", tmp.toString(), getImagePath()) + .assertFailure() + .assertShowsError(); + } + + public void testExtractToNotEmptyDir() throws IOException { + Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName()); + Files.createFile(Paths.get(tmp.toString(), ".not_empty")); + jimage("extract", "--dir", tmp.toString(), getImagePath()) + .assertFailure() + .assertShowsError(); + } + + public void testExtractToFile() throws IOException { + Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_a_dir"); + jimage("extract", "--dir", tmp.toString(), getImagePath()) + .assertFailure() + .assertShowsError(); + } + + private void verifyExplodedImage(Path imagePath) throws IOException { + Set allModules = Files.walk(imagePath, 1).collect(Collectors.toSet()); + assertTrue(allModules.stream().anyMatch(p -> "java.base".equals(p.getFileName().toString())), + "Exploded image contains java.base module."); + + Set badModules = allModules.stream() + .filter(p -> !Files.exists(p.resolve("module-info.class"))) + .collect(Collectors.toSet()); + assertEquals(badModules, new HashSet() {{ add(imagePath); }}, + "There are no exploded modules with missing 'module-info.class'"); + } + + public static void main(String[] args) throws Throwable { + new JImageExtractTest().runTests(); + } +} + diff --git a/jdk/test/tools/jimage/JImageInfoTest.java b/jdk/test/tools/jimage/JImageInfoTest.java new file mode 100644 index 00000000000..45eaece46bb --- /dev/null +++ b/jdk/test/tools/jimage/JImageInfoTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests to verify jimage 'info' action + * @library /test/lib + * @modules jdk.jlink/jdk.tools.jimage + * @build jdk.test.lib.Asserts + * @run main JImageInfoTest + */ + +import java.util.Arrays; + +public class JImageInfoTest extends JImageCliTest { + public void testInfo() { + jimage("info", getImagePath()) + .assertSuccess() + .resultChecker(r -> { + assertMatches("(?m)^\\s+Major Version: +[1-9]\\d*$.*", r.output); + assertMatches("(?m)^\\s+Minor Version: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Flags: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Resource Count: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Table Length: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Offsets Size: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Redirects Size: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Locations Size: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Strings Size: +\\d+$.*", r.output); + assertMatches("(?m)^\\s+Index Size: +\\d+$.*", r.output); + }); + } + + public void testInfoHelp() { + for (String opt : Arrays.asList("-h", "--help")) { + jimage("info", opt) + .assertSuccess() + .resultChecker(r -> { + // info - descriptive text + assertMatches("\\s+info\\s+-\\s+.*", r.output); + }); + } + } + + public void testInfoUnknownOption() { + jimage("info", "--unknown") + .assertFailure() + .assertShowsError(); + } + + public static void main(String[] args) throws Throwable { + new JImageInfoTest().runTests(); + } +} + diff --git a/jdk/test/tools/jimage/JImageListTest.java b/jdk/test/tools/jimage/JImageListTest.java new file mode 100644 index 00000000000..e49e14e2ccb --- /dev/null +++ b/jdk/test/tools/jimage/JImageListTest.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests to verify jimage 'list' action + * @library /test/lib + * @modules jdk.jlink/jdk.tools.jimage + * @build jdk.test.lib.Asserts + * @run main JImageListTest + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertTrue; + +public class JImageListTest extends JImageCliTest { + public void testList() { + jimage("list", getImagePath()) + .assertSuccess() + .resultChecker(r -> { + String[] lines = r.output.split(System.lineSeparator()); + assertTrue(lines.length > 0, "Option --list has output."); + assertTrue(lines[0].startsWith("jimage: " + getImagePath()), + "Output should start with jimage path."); + + List modules = Stream.of(lines) + .filter(s -> s.startsWith("Module: ")) + .map(s -> s.substring(s.indexOf(':') + 1).trim()) + .collect(Collectors.toList()); + assertTrue(modules.size() > 0, "Image contains at least one module."); + assertTrue(modules.indexOf("java.base") > 0, "Module java.base found."); + }); + } + + public void testListHelp() { + for (String opt : Arrays.asList("-h", "--help")) { + jimage("list", opt) + .assertSuccess() + .resultChecker(r -> { + // list - descriptive text + assertMatches("\\s+list\\s+-\\s+.*", r.output); + }); + } + } + + public void testListVerbose() { + jimage("list", "--verbose", getImagePath()) + .assertSuccess() + .resultChecker(r -> { + assertMatches("Offset\\s+Size\\s+Compressed\\s+Entry", r.output); + + String[] lines = r.output.split("[" + System.lineSeparator() + "]+"); + assertTrue(lines.length > 0, "Option --list has output."); + assertTrue(lines[0].startsWith("jimage: " + getImagePath()), + "Output should start with jimage path."); + + List modules = Stream.of(lines) + .filter(s -> s.startsWith("Module: ")) + .map(s -> s.substring(s.indexOf(':') + 1).trim()) + .collect(Collectors.toList()); + assertTrue(modules.size() > 0, "Image contains at least one module."); + assertTrue(modules.indexOf("java.base") > 0, "Module java.base found."); + + Set entries = Stream.of(lines) + .filter(s -> { return !s.startsWith("Module: ") && !s.startsWith("Offset"); }) + // Offset \d+ Size \d+ Compressed \d+ Entry \.* + .filter(s -> !s.matches("\\s+\\d+\\s+\\d+\\s+\\d+\\s+.*")) + .collect(Collectors.toSet()); + assertEquals(entries, new HashSet<>() {{ add("jimage: " + getImagePath()); }}, + "All entries should be in format: Offset Size Compressed Entry"); + }); + } + + public void testListIncludeAllWithGlob() { + JImageResult listAll = jimage("list", getImagePath()).assertSuccess(); + JImageResult listAllGlob = jimage("list", "--include", "**", getImagePath()).assertSuccess(); + assertEquals(listAllGlob.output, listAll.output, "--include ** should produce the same output"); + } + + public void testListIncludeWithGlob() { + JImageResult listAll = jimage("list", getImagePath()).assertSuccess(); + Set expected = Stream.of(listAll.output.split("[" + System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> s.startsWith("java/util/zip")) + .collect(Collectors.toSet()); + + JImageResult listJavaUtil = jimage("list", "--include", "/java.base/java/util/zip/**", getImagePath()).assertSuccess(); + Set actual = Stream.of(listJavaUtil.output.split("[" + System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:")) + .collect(Collectors.toSet()); + assertEquals(actual, expected, "All java.util.zip classes are listed"); + } + + public void testListIncludeNoMatchWithGlob() { + JImageResult listNotMatching = jimage("list", "--include", "not_matching", getImagePath()).assertSuccess(); + Set entries = Stream.of(listNotMatching.output.split("["+ System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:")) + .collect(Collectors.toSet()); + assertEquals(entries, Collections.emptySet(), "No java.util classes are listed"); + } + + public void testListIncludeAllWithExplicitGlob() { + JImageResult listAll = jimage("list", getImagePath()).assertSuccess(); + JImageResult listAllGlob = jimage("list", "--include", "glob:**", getImagePath()).assertSuccess(); + assertEquals(listAllGlob.output, listAll.output, "--include glob:** should produce the same output"); + } + + public void testListIncludeAllWithRegex() { + JImageResult listAll = jimage("list", getImagePath()).assertSuccess(); + JImageResult listAllRegex = jimage("list", "--include", "regex:.*", getImagePath()).assertSuccess(); + assertEquals(listAllRegex.output, listAll.output, "--include regex:.* should produce the same output"); + } + + public void testListIncludeWithRegex() { + JImageResult listAll = jimage("list", getImagePath()).assertSuccess(); + Set expected = Stream.of(listAll.output.split("[" + System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> s.startsWith("java/text/")) + .collect(Collectors.toSet()); + assertFalse(expected.isEmpty(), "There should be classes from java.text package"); + + JImageResult listJavaText = jimage("list", "--include", "regex:/java.base/java/text/.*", getImagePath()).assertSuccess(); + Set actual = Stream.of(listJavaText.output.split("[" + System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:")) + .collect(Collectors.toSet()); + + assertEquals(actual, expected, "All java.text classes are listed"); + } + + public void testListIncludeNoMatchWithRegex() { + JImageResult listNotMatching = jimage("list", "--include", "regex:not_matching", + getImagePath()).assertSuccess(); + Set entries = Stream.of(listNotMatching.output.split("[" + System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:")) + .collect(Collectors.toSet()); + assertEquals(entries, Collections.emptySet(), "No classes are listed"); + } + + public void testListIncludeMultiplePatterns() throws IOException { + JImageResult listAll = jimage("list", getImagePath()).assertSuccess(); + Set expected = Stream.of(listAll.output.split("[" + System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> s.startsWith("java/time/") || s.startsWith("java/util/zip")) + .collect(Collectors.toSet()); + assertFalse(expected.isEmpty(), "There should be classes from java.time and java.io packages"); + + JImageResult listMatched = jimage("list", "--include", "glob:/java.base/java/time/**,regex:/java.base/java/util/zip/.*", + getImagePath()).assertSuccess(); + Set actual = Stream.of(listMatched.output.split("[" + System.lineSeparator() + "]+")) + .map(String::trim) + .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:")) + .collect(Collectors.toSet()); + + assertEquals(actual, expected, "All java.time and java.util.zip classes are listed"); + } + + public void testListNoImageSpecified() { + jimage("list", "") + .assertFailure() + .assertShowsError(); + } + + public void testListEmptyFile() throws IOException { + Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "empty_file"); + jimage("list", tmp.toString()) + .assertFailure() + .assertShowsError(); + } + + public void testListNotAnImage() throws IOException { + Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_an_image"); + Files.write(tmp, "This is not an image".getBytes()); + jimage("list", tmp.toString()) + .assertFailure() + .assertShowsError(); + } + + public void testListNotExistingImage() throws IOException { + Path tmp = Paths.get(".", "not_existing_image"); + Files.deleteIfExists(tmp); + jimage("list", tmp.toString()) + .assertFailure() + .assertShowsError(); + } + + public void testListWithUnknownOption() { + jimage("list", "--unknown") + .assertFailure() + .assertShowsError(); + } + + public static void main(String[] args) throws Throwable { + new JImageListTest().runTests(); + } +} + diff --git a/jdk/test/tools/jimage/JImageToolTest.java b/jdk/test/tools/jimage/JImageToolTest.java index da6cb9f740e..c508eba0cfc 100644 --- a/jdk/test/tools/jimage/JImageToolTest.java +++ b/jdk/test/tools/jimage/JImageToolTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -23,8 +23,8 @@ /* * @test * @library /lib/testlibrary - * @build jdk.testlibrary.* - * @summary Test to see if jimage tool extracts and recreates correctly. + * @build jdk.testlibrary.ProcessTools + * @summary Test to check if jimage tool exists and is working * @run main/timeout=360 JImageToolTest */ @@ -42,7 +42,7 @@ import jdk.testlibrary.ProcessTools; public class JImageToolTest { private static void jimage(String... jimageArgs) throws Exception { ArrayList args = new ArrayList<>(); - args.add("-ms8m"); + args.add("-ms64m"); args.add("jdk.tools.jimage.Main"); args.addAll(Arrays.asList(jimageArgs)); @@ -61,11 +61,7 @@ public class JImageToolTest { if (Files.exists(jimagePath) && Files.exists(modulesimagePath)) { String jimage = jimagePath.toAbsolutePath().toString(); - String bootimage = modulesimagePath.toAbsolutePath().toString(); - String extractDir = Paths.get(".", "extract").toAbsolutePath().toString(); - jimage("list", bootimage); - jimage("verify", bootimage); - jimage("extract", "--dir", extractDir, bootimage); + jimage("--version"); System.out.println("Test successful"); } else { System.out.println("Test skipped, not an images build"); diff --git a/jdk/test/tools/jimage/JImageVerifyTest.java b/jdk/test/tools/jimage/JImageVerifyTest.java new file mode 100644 index 00000000000..bb763c45704 --- /dev/null +++ b/jdk/test/tools/jimage/JImageVerifyTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests to verify jimage 'verify' action + * @library /test/lib + * @modules jdk.jlink/jdk.tools.jimage + * @build jdk.test.lib.Asserts + * @run main JImageVerifyTest + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +import static jdk.test.lib.Asserts.assertTrue; + +public class JImageVerifyTest extends JImageCliTest { + + public void testVerify() { + jimage("verify", getImagePath()) + .assertSuccess() + .resultChecker(r -> { + assertTrue(r.output.startsWith("jimage: " + getImagePath()), + "Contains verified image's path"); + }); + } + + public void testVerifyHelp() { + for (String opt : Arrays.asList("-h", "--help")) { + jimage("verify", opt) + .assertSuccess() + .resultChecker(r -> { + // verify - descriptive text + assertMatches("\\s+verify\\s+-\\s+.*", r.output); + }); + } + } + + public void testVerifyImageNotSpecified() { + jimage("verify", "") + .assertFailure() + .assertShowsError(); + } + + public void testVerifyNotAnImage() throws IOException { + Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_an_image"); + jimage("verify", tmp.toString()) + .assertFailure() + .assertShowsError(); + } + + public void testVerifyNotExistingImage() throws IOException { + Path tmp = Paths.get(".", "not_existing_image"); + Files.deleteIfExists(tmp); + jimage("verify", "") + .assertFailure() + .assertShowsError(); + } + + public void testVerifyWithUnknownOption() { + jimage("verify", "--unknown") + .assertFailure() + .assertShowsError(); + } + + public static void main(String[] args) throws Throwable { + new JImageVerifyTest().runTests(); + } + +} diff --git a/jdk/test/tools/jlink/JLinkSigningTest.java b/jdk/test/tools/jlink/JLinkSigningTest.java index 169d3904c41..34b4dbcbdaa 100644 --- a/jdk/test/tools/jlink/JLinkSigningTest.java +++ b/jdk/test/tools/jlink/JLinkSigningTest.java @@ -26,24 +26,31 @@ * @bug 8159393 * @summary Test signed jars involved in image creation * @modules java.base/jdk.internal.jimage - * jdk.jlink/jdk.tools.jlink.internal - * jdk.compiler/com.sun.tools.javac * java.base/sun.security.tools.keytool + * jdk.compiler/com.sun.tools.javac * jdk.jartool/sun.security.tools.jarsigner * jdk.jartool/sun.tools.jar + * jdk.jlink/jdk.tools.jlink.internal * @run main/othervm JLinkSigningTest */ import java.io.File; import java.io.IOException; -import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.spi.ToolProvider; public class JLinkSigningTest { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> new RuntimeException("jar tool not found")); + private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac") + .orElseThrow(() -> new RuntimeException("javac tool not found")); + private static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> new RuntimeException("jlink tool not found")); + static final String[] MODULE_INFO = { "module test {", "}", @@ -61,22 +68,29 @@ public class JLinkSigningTest { System.out.println(command + " " + String.join(" ", Arrays.asList(args))); } - static void javac(String[] args) { - report("javac", args); - com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main(); + static void jar(String[] args) { + report("jar", args); + JAR_TOOL.run(System.out, System.err, args); + } - if (javac.compile(args) != 0) { - throw new RuntimeException("javac failed"); + static void jarsigner(String[] args) { + report("jarsigner", args); + + try { + sun.security.tools.jarsigner.Main.main(args); + } catch (Exception ex) { + throw new RuntimeException("jarsigner not found"); } } - static void jar(String[] args) { - report("jar", args); - sun.tools.jar.Main jar = new sun.tools.jar.Main(System.out, System.err, "jar"); + static void javac(String[] args) { + report("javac", args); + JAVAC_TOOL.run(System.out, System.err, args); + } - if (!jar.run(args)) { - throw new RuntimeException("jar failed"); - } + static void jlink(String[] args) { + report("jlink", args); + JLINK_TOOL.run(System.out, System.err, args); } static void keytool(String[] args) { @@ -89,28 +103,6 @@ public class JLinkSigningTest { } } - static void jarsigner(String[] args) { - report("jarsigner", args); - - try { - sun.security.tools.jarsigner.Main.main(args); - } catch (Exception ex) { - throw new RuntimeException("jarsigner failed"); - } - } - - static void jlink(String[] args) { - report("jlink", args); - - try { - jdk.tools.jlink.internal.Main.run(new PrintWriter(System.out, true), - new PrintWriter(System.err, true), - args); - } catch (Exception ex) { - throw new RuntimeException("jlink failed"); - } - } - public static void main(String[] args) { final String JAVA_HOME = System.getProperty("java.home"); Path moduleInfoJavaPath = Paths.get("module-info.java"); diff --git a/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java b/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java index 72afcb06fc0..634a27fa95c 100644 --- a/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java +++ b/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java @@ -21,12 +21,14 @@ * questions. */ +import java.io.BufferedWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.spi.ToolProvider; import jdk.testlibrary.OutputAnalyzer; import org.testng.annotations.BeforeTest; @@ -42,6 +44,7 @@ import static jdk.testlibrary.ProcessTools.*; * @summary Test the default class path if -Djava.class.path is set * @library /lib/testlibrary * @modules jdk.compiler + * jdk.jartool * @build CompilerUtils jdk.testlibrary.* * @run testng JavaClassPathTest */ @@ -50,6 +53,7 @@ public class JavaClassPathTest { private static final Path SRC_DIR = Paths.get(System.getProperty("test.src"), "src"); private static final Path MODS_DIR = Paths.get("mods"); + private static final Path LIB_DIR = Paths.get("lib"); private static final String TEST_MODULE = "m"; private static final String TEST_MAIN = "jdk.test.Main"; @@ -66,27 +70,47 @@ public class JavaClassPathTest { Path res = Paths.get("jdk/test/res.properties"); Files.createFile(res); + + ToolProvider jartool = ToolProvider.findFirst("jar").orElseThrow( + () -> new RuntimeException("jar tool not found") + ); + + Path jarfile = LIB_DIR.resolve("m.jar"); + Files.createDirectories(LIB_DIR); + assertTrue(jartool.run(System.out, System.err, "cfe", + jarfile.toString(), TEST_MAIN, + file.toString()) == 0); + + Path manifest = LIB_DIR.resolve("manifest"); + try (BufferedWriter writer = Files.newBufferedWriter(manifest)) { + writer.write("CLASS-PATH: lib/m.jar"); + } + jarfile = LIB_DIR.resolve("m1.jar"); + assertTrue(jartool.run(System.out, System.err, "cfme", + jarfile.toString(), manifest.toString(), TEST_MAIN, + file.toString()) == 0); } @DataProvider(name = "classpath") public Object[][] classpath() { return new Object[][]{ // true indicates that class path default to current working directory - { "", true }, - { "-Djava.class.path", true }, - { "-Djava.class.path=", true }, - { "-Djava.class.path=.", true }, + { "", "." }, + { "-Djava.class.path", "." }, + { "-Djava.class.path=", "" }, + { "-Djava.class.path=.", "." }, }; } @Test(dataProvider = "classpath") - public void testUnnamedModule(String option, boolean expected) throws Throwable { + public void testUnnamedModule(String option, String expected) throws Throwable { List args = new ArrayList<>(); if (!option.isEmpty()) { args.add(option); } args.add(TEST_MAIN); - args.add(Boolean.toString(expected)); + args.add(Boolean.toString(true)); + args.add(expected); assertTrue(execute(args).getExitValue() == 0); } @@ -95,15 +119,14 @@ public class JavaClassPathTest { public Object[][] moduleAndClassPath() { return new Object[][]{ // true indicates that class path default to current working directory - { "", false }, - { "-Djava.class.path", false }, - { "-Djava.class.path=", false }, - { "-Djava.class.path=.", true }, + { "", "" }, + { "-Djava.class.path", "" }, + { "-Djava.class.path=", "" }, }; } @Test(dataProvider = "moduleAndClassPath") - public void testNamedModule(String option, boolean expected) throws Throwable { + public void testNamedModule(String option, String expected) throws Throwable { List args = new ArrayList<>(); if (!option.isEmpty()) { args.add(option); @@ -112,7 +135,61 @@ public class JavaClassPathTest { args.add(MODS_DIR.toString()); args.add("-m"); args.add(TEST_MODULE + "/" + TEST_MAIN); - args.add(Boolean.toString(expected)); + // not default to CWD + args.add(Boolean.toString(false)); + args.add(expected); + + + assertTrue(execute(args).getExitValue() == 0); + } + + @Test + public void testClassPath() throws Throwable { + List args = new ArrayList<>(); + args.add("-Djava.class.path=."); + args.add("--module-path"); + args.add(MODS_DIR.toString()); + args.add("-m"); + args.add(TEST_MODULE + "/" + TEST_MAIN); + args.add(Boolean.toString(true)); + args.add("."); + + assertTrue(execute(args).getExitValue() == 0); + } + + @Test + public void testJAR() throws Throwable { + String jarfile = LIB_DIR.resolve("m.jar").toString(); + List args = new ArrayList<>(); + args.add("-jar"); + args.add(jarfile); + args.add(Boolean.toString(false)); + args.add(jarfile); + + assertTrue(execute(args).getExitValue() == 0); + } + + /* + * Test CLASS-PATH attribute in manifest + */ + @Test + public void testClassPathAttribute() throws Throwable { + String jarfile = LIB_DIR.resolve("m1.jar").toString(); + + List args = new ArrayList<>(); + args.add("-jar"); + args.add(jarfile); + args.add(Boolean.toString(false)); + args.add(jarfile); + + assertTrue(execute(args).getExitValue() == 0); + + args.clear(); + args.add("-cp"); + args.add(jarfile); + args.add(TEST_MAIN); + args.add(Boolean.toString(false)); + args.add(jarfile); assertTrue(execute(args).getExitValue() == 0); } diff --git a/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java b/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java index 41e7cd8717d..8a6c671ae89 100644 --- a/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java +++ b/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java @@ -29,13 +29,14 @@ public class Main { static final String JAVA_CLASS_PATH = "java.class.path"; public static void main(String[] args) throws Exception { + boolean expected = args[0].equals("true"); + String cpath = args.length > 1 ? args[1] : ""; String value = System.getProperty(JAVA_CLASS_PATH); - if (value == null) { - throw new RuntimeException(JAVA_CLASS_PATH + " is expected non-null" + - " for compatibility"); + if (!value.equals(cpath)) { + throw new RuntimeException(JAVA_CLASS_PATH + "=" + value + + " expected=" + cpath); } - boolean expected = args[0].equals("true"); ClassLoader loader = ClassLoader.getSystemClassLoader(); URL url = loader.getResource("jdk/test/res.properties"); if ((expected && url == null) || (!expected && url != null)) { diff --git a/langtools/.hgtags b/langtools/.hgtags index cafeca2beaf..4205f71b3ec 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -386,3 +386,4 @@ dd56c243c199a540c9f1fbff4855f0934b32a9d0 jdk-9+137 296c875051187918f8f3f87e9432036d13013d39 jdk-9+141 d245e56f4a79a8a8d18bd143c08f079ee98ab638 jdk-9+142 6ef8a1453577832626b0efb7f70a3102b721ebbf jdk-9+143 +47871e348144bafddea0ede3a44299461e254a2d jdk-9+144 diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java index fbdb07ef248..5b7d30c80b0 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java @@ -137,12 +137,18 @@ public abstract class Scope { /** Returns true iff the given Symbol is in this scope or any outward scope. */ public boolean includes(final Symbol sym) { + return includes(sym, RECURSIVE); + } + + /** Returns true iff the given Symbol is in this scope, optionally checking outward scopes. + */ + public boolean includes(final Symbol sym, LookupKind lookupKind) { return getSymbolsByName(sym.name, new Filter() { @Override public boolean accepts(Symbol t) { return t == sym; } - }).iterator().hasNext(); + }, lookupKind).iterator().hasNext(); } /** Returns true iff this scope does not contain any Symbol. Does not inspect outward scopes. diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java index 40c9211b61d..202ca4e5dfe 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java @@ -383,7 +383,19 @@ public class Symtab { addRootPackageFor(unnamedModule); unnamedModule.enclosedPackages = unnamedModule.enclosedPackages.prepend(unnamedModule.unnamedPackage); - errModule = new ModuleSymbol(names.empty, null) { }; + errModule = new ModuleSymbol(names.empty, null) { + { + directives = List.nil(); + exports = List.nil(); + provides = List.nil(); + uses = List.nil(); + ModuleSymbol java_base = enterModule(names.java_base); + com.sun.tools.javac.code.Directive.RequiresDirective d = + new com.sun.tools.javac.code.Directive.RequiresDirective(java_base, + EnumSet.of(com.sun.tools.javac.code.Directive.RequiresFlag.MANDATED)); + requires = List.of(d); + } + }; addRootPackageFor(errModule); noModule = new ModuleSymbol(names.empty, null) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index 2850e2506f4..b52af6545d6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -293,8 +293,11 @@ public class Modules extends JCTree.Visitor { private void enterModule(JCCompilationUnit toplevel, ClassSymbol c, Set modules) { boolean isModuleInfo = toplevel.sourcefile.isNameCompatible("module-info", Kind.SOURCE); boolean isModuleDecl = toplevel.defs.nonEmpty() && toplevel.defs.head.hasTag(MODULEDEF); - if (isModuleInfo && isModuleDecl) { + if (isModuleDecl) { JCModuleDecl decl = (JCModuleDecl) toplevel.defs.head; + if (!isModuleInfo) { + log.error(decl.pos(), Errors.ModuleDeclSbInModuleInfoJava); + } Name name = TreeInfo.fullName(decl.qualId); ModuleSymbol sym; if (c != null) { @@ -330,9 +333,6 @@ public class Modules extends JCTree.Visitor { JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head; log.error(tree.pos(), Errors.ExpectedModule); } - } else if (isModuleDecl) { - JCTree tree = toplevel.defs.head; - log.error(tree.pos(), Errors.ModuleDeclSbInModuleInfoJava); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index c1e0964aaef..1416d2b8b9b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -62,6 +62,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.Kind.*; +import com.sun.tools.javac.code.Scope.LookupKind; import static com.sun.tools.javac.code.TypeTag.ARRAY; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.code.TypeTag.TYPEVAR; @@ -2186,7 +2187,11 @@ public class ClassReader { // Sometimes anonymous classes don't have an outer // instance, however, there is no reliable way to tell so // we never strip this$n - if (!currentOwner.name.isEmpty()) + // ditto for local classes. Local classes that have an enclosing method set + // won't pass the "hasOuterInstance" check above, but those that don't have an + // enclosing method (i.e. from initializers) will pass that check. + boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE); + if (!currentOwner.name.isEmpty() && !local) type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()), type.getReturnType(), type.getThrownTypes(), diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 756b0080bc2..7dd835f82fb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -35,6 +35,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -43,6 +44,7 @@ import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.TreeSet; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -200,31 +202,37 @@ public enum Option { // The standard file manager code knows to split apart the NULL-separated components. @Override public boolean process(OptionHelper helper, String option, String arg) { - if (!arg.contains("=")) { // could be more strict regeex, e.g. "(?i)[a-z0-9_.]+=.*" - helper.error(Errors.LocnInvalidArgForXpatch(arg)); + if (arg.isEmpty()) { + helper.error("err.no.value.for.option", option); + return true; + } else if (getPattern().matcher(arg).matches()) { + String prev = helper.get(PATCH_MODULE); + if (prev == null) { + super.process(helper, option, arg); + return false; + } else { + String argModulePackage = arg.substring(0, arg.indexOf('=')); + boolean isRepeated = Arrays.stream(prev.split("\0")) + .map(s -> s.substring(0, s.indexOf('='))) + .collect(Collectors.toSet()) + .contains(argModulePackage); + if (isRepeated) { + helper.error("err.repeated.value.for.patch.module", argModulePackage); + return true; + } else { + super.process(helper, option, prev + '\0' + arg); + return false; + } + } + } else { + helper.error("err.bad.value.for.option", option, arg); + return true; } + } - String previous = helper.get(this); - if (previous == null) { - return super.process(helper, option, arg); - } - - Map map = new LinkedHashMap<>(); - for (String s : previous.split("\0")) { - int sep = s.indexOf('='); - map.put(s.substring(0, sep), s.substring(sep + 1)); - } - - int sep = arg.indexOf('='); - map.put(arg.substring(0, sep), arg.substring(sep + 1)); - - StringBuilder sb = new StringBuilder(); - map.forEach((m, p) -> { - if (sb.length() > 0) - sb.append('\0'); - sb.append(m).append('=').append(p); - }); - return super.process(helper, option, sb.toString()); + @Override + public Pattern getPattern() { + return Pattern.compile("([^/]+)=(,*[^,].*)"); } }, diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties index faa6db19881..6acb5db137d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties @@ -361,6 +361,8 @@ javac.err.bad.value.for.option=\ bad value for {0} option: ''{1}'' javac.err.no.value.for.option=\ no value for {0} option +javac.err.repeated.value.for.patch.module=\ + --patch-module specified more than once for {0} ## messages diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index e7c5385d937..b671ed16c3b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -535,7 +535,7 @@ public abstract class AbstractMemberWriter { TypeElement superClass = utils.getSuperClass(typeElement); while (superClass != null) { - if (visibleMemberMap.hasMembersFor(superClass)) { + if (visibleMemberMap.hasMembers(superClass)) { liNav.addContent(getNavSummaryLink(superClass, true)); return; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java index d2607ba41b8..3485be66d24 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java @@ -135,8 +135,6 @@ public class ConfigurationImpl extends Configuration { */ public String docrootparent = ""; - public boolean sortedMethodDetails = false; - /** * True if command line option "-nohelp" is used. Default value is false. */ diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java index be59ef815c9..612c2e0db06 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java @@ -72,7 +72,7 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter VisibleMemberMap visibleMemberMap = new VisibleMemberMap( typeElement, VisibleMemberMap.Kind.CONSTRUCTORS, configuration); - SortedSet constructors = visibleMemberMap.getMembersFor(typeElement); + List constructors = visibleMemberMap.getMembers(typeElement); for (Element constructor : constructors) { if (utils.isProtected(constructor) || utils.isPrivate(constructor)) { setFoundNonPubConstructor(true); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java index ee0dba08fee..3bc2b1a1939 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java @@ -25,6 +25,15 @@ package jdk.javadoc.internal.doclets.toolkit.builders; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.lang.model.element.Element; + +import jdk.javadoc.internal.doclets.formats.html.ConfigurationImpl; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.DocletException; @@ -42,6 +51,7 @@ import jdk.javadoc.internal.doclets.toolkit.DocletException; */ public abstract class AbstractMemberBuilder extends AbstractBuilder { + public final Comparator comparator; /** * Construct a SubBuilder. * @param context a context object, providing information used in this run @@ -49,6 +59,7 @@ public abstract class AbstractMemberBuilder extends AbstractBuilder { */ public AbstractMemberBuilder(Context context) { super(context); + comparator = utils.makeGeneralPurposeComparator(); } /** @@ -83,4 +94,10 @@ public abstract class AbstractMemberBuilder extends AbstractBuilder { * @return true if this subbuilder has anything to document */ public abstract boolean hasMembersToDocument(); + + public SortedSet asSortedSet(Collection members) { + SortedSet out = new TreeSet<>(comparator); + out.addAll(members); + return out; + } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java index f8d020ab904..9026429b7c9 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java @@ -67,7 +67,7 @@ public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder { /** * The list of members being documented. */ - protected SortedSet members; + protected List members; /** * The index of the current member that is being documented at this point @@ -91,7 +91,7 @@ public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder { this.typeElement = typeElement; this.writer = writer; this.visibleMemberMap = new VisibleMemberMap(typeElement, memberType, configuration); - this.members = this.visibleMemberMap.getMembersFor(typeElement); + this.members = this.visibleMemberMap.getMembers(typeElement); } @@ -118,26 +118,6 @@ public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder { return "AnnotationTypeFieldDetails"; } - /** - * Returns a list of members that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param typeElement the TypeElement we want to check. - * @return a list of members that will be documented. - */ - public SortedSet members(TypeElement typeElement) { - return visibleMemberMap.getMembersFor(typeElement); - } - - /** - * Returns the visible member map for the members of this class. - * - * @return the visible member map for the members of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } /** * Returns whether or not there are members to document. @@ -145,7 +125,7 @@ public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder { */ @Override public boolean hasMembersToDocument() { - return members.size() > 0; + return !members.isEmpty(); } /** @@ -172,16 +152,19 @@ public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder { if (writer == null) { return; } - if (!members.isEmpty()) { + if (hasMembersToDocument()) { writer.addAnnotationFieldDetailsMarker(memberDetailsTree); - for (Element element : members) { - currentMember = element; + + Element lastElement = members.get(members.size() - 1); + for (Element member : members) { + currentMember = member; Content detailsTree = writer.getMemberTreeHeader(); writer.addAnnotationDetailsTreeHeader(typeElement, detailsTree); - Content annotationDocTree = writer.getAnnotationDocTreeHeader(element, detailsTree); + Content annotationDocTree = writer.getAnnotationDocTreeHeader(currentMember, + detailsTree); buildChildren(node, annotationDocTree); detailsTree.addContent(writer.getAnnotationDoc( - annotationDocTree, currentMember == members.last())); + annotationDocTree, currentMember == lastElement)); memberDetailsTree.addContent(writer.getAnnotationDetails(detailsTree)); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java index 8f4a678c585..412f723ef16 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java @@ -68,7 +68,7 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { /** * The list of members being documented. */ - protected SortedSet members; + protected List members; /** * The index of the current member that is being documented at this point @@ -82,6 +82,7 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { * @param context the build context. * @param typeElement the class whose members are being documented. * @param writer the doclet specific writer. + * @param memberType the kind of member this builder processes. */ protected AnnotationTypeRequiredMemberBuilder(Context context, TypeElement typeElement, @@ -91,7 +92,7 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { this.typeElement = typeElement; this.writer = writer; this.visibleMemberMap = new VisibleMemberMap(typeElement, memberType, configuration); - this.members = this.visibleMemberMap.getMembersFor(typeElement); + this.members = this.visibleMemberMap.getMembers(typeElement); } @@ -101,6 +102,7 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { * @param context the build context. * @param typeElement the class whose members are being documented. * @param writer the doclet specific writer. + * @return an instance of this object */ public static AnnotationTypeRequiredMemberBuilder getInstance( Context context, TypeElement typeElement, @@ -118,34 +120,13 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { return "AnnotationTypeRequiredMemberDetails"; } - /** - * Returns a list of members that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param typeElement the {@link TypeElement} we want to check. - * @return a list of members that will be documented. - */ - public SortedSet members(TypeElement typeElement) { - return visibleMemberMap.getMembersFor(typeElement); - } - - /** - * Returns the visible member map for the members of this class. - * - * @return the visible member map for the members of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - /** * Returns whether or not there are members to document. * @return whether or not there are members to document */ @Override public boolean hasMembersToDocument() { - return members.size() > 0; + return !members.isEmpty(); } /** @@ -165,24 +146,25 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { * * @param node the XML element that specifies which components to document * @param memberDetailsTree the content tree to which the documentation will be added + * @throws DocletException if an error occurs */ public void buildAnnotationTypeMember(XMLNode node, Content memberDetailsTree) throws DocletException { if (writer == null) { return; } - int size = members.size(); - if (size > 0) { + if (hasMembersToDocument()) { writer.addAnnotationDetailsMarker(memberDetailsTree); - for (Element element : members) { - currentMember = element; + Element lastMember = members.get((members.size() - 1)); + for (Element member : members) { + currentMember = member; Content detailsTree = writer.getMemberTreeHeader(); writer.addAnnotationDetailsTreeHeader(typeElement, detailsTree); Content annotationDocTree = writer.getAnnotationDocTreeHeader( - element, detailsTree); + currentMember, detailsTree); buildChildren(node, annotationDocTree); detailsTree.addContent(writer.getAnnotationDoc( - annotationDocTree, currentMember == members.last())); + annotationDocTree, currentMember == lastMember)); memberDetailsTree.addContent(writer.getAnnotationDetails(detailsTree)); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java index 45eea2bc5b9..75a01fa5c73 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java @@ -275,7 +275,7 @@ public class ConstantsSummaryBuilder extends AbstractBuilder { private boolean hasConstantField (TypeElement typeElement) { VisibleMemberMap visibleMemberMapFields = new VisibleMemberMap(typeElement, VisibleMemberMap.Kind.FIELDS, configuration); - SortedSet fields = visibleMemberMapFields.getLeafClassMembers(); + List fields = visibleMemberMapFields.getLeafMembers(); for (Element f : fields) { VariableElement field = (VariableElement)f; if (field.getConstantValue() != null) { @@ -350,21 +350,21 @@ public class ConstantsSummaryBuilder extends AbstractBuilder { } /** - * Return the list of visible constant fields for the given TypeElement. - * @return the list of visible constant fields for the given TypeElement. + * Returns a set of visible constant fields for the given type. + * @return the set of visible constant fields for the given type. */ protected SortedSet members() { - SortedSet list = visibleMemberMapFields.getLeafClassMembers(); - list.addAll(visibleMemberMapEnumConst.getLeafClassMembers()); - SortedSet inclList = + List members = visibleMemberMapFields.getLeafMembers(); + members.addAll(visibleMemberMapEnumConst.getLeafMembers()); + SortedSet includes = new TreeSet<>(utils.makeGeneralPurposeComparator()); - for (Element element : list) { + for (Element element : members) { VariableElement member = (VariableElement)element; if (member.getConstantValue() != null) { - inclList.add(member); + includes.add(member); } } - return inclList; + return includes; } } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java index 787ba257eb7..ee8076bb72f 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java @@ -59,7 +59,7 @@ public class ConstructorBuilder extends AbstractMemberBuilder { /** * The current constructor that is being documented at this point in time. */ - private ExecutableElement constructor; + private ExecutableElement currentConstructor; /** * The class whose constructors are being documented. @@ -79,7 +79,7 @@ public class ConstructorBuilder extends AbstractMemberBuilder { /** * The constructors being documented. */ - private final SortedSet constructors; + private final List constructors; /** * Construct a new ConstructorBuilder. @@ -99,7 +99,7 @@ public class ConstructorBuilder extends AbstractMemberBuilder { typeElement, VisibleMemberMap.Kind.CONSTRUCTORS, configuration); - constructors = visibleMemberMap.getMembersFor(typeElement); + constructors = visibleMemberMap.getMembers(typeElement); for (Element ctor : constructors) { if (utils.isProtected(ctor) || utils.isPrivate(ctor)) { writer.setFoundNonPubConstructor(true); @@ -136,18 +136,6 @@ public class ConstructorBuilder extends AbstractMemberBuilder { return !constructors.isEmpty(); } - /** - * Returns a list of constructors that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param typeElement the class - * @return a list of constructors that will be documented. - */ - public SortedSet members(TypeElement typeElement) { - return visibleMemberMap.getMembersFor(typeElement); - } - /** * Return the constructor writer for this builder. * @@ -168,17 +156,17 @@ public class ConstructorBuilder extends AbstractMemberBuilder { if (writer == null) { return; } - int size = constructors.size(); - if (size > 0) { + if (hasMembersToDocument()) { Content constructorDetailsTree = writer.getConstructorDetailsTreeHeader(typeElement, memberDetailsTree); - for (Element ctor : constructors) { - constructor = (ExecutableElement)ctor; - Content constructorDocTree = writer.getConstructorDocTreeHeader( - constructor, constructorDetailsTree); + + Element lastElement = constructors.get(constructors.size() - 1); + for (Element contructor : constructors) { + currentConstructor = (ExecutableElement)contructor; + Content constructorDocTree = writer.getConstructorDocTreeHeader(currentConstructor, constructorDetailsTree); buildChildren(node, constructorDocTree); constructorDetailsTree.addContent(writer.getConstructorDoc(constructorDocTree, - constructors.last().equals(constructor))); + currentConstructor == lastElement)); } memberDetailsTree.addContent( writer.getConstructorDetails(constructorDetailsTree)); @@ -192,7 +180,7 @@ public class ConstructorBuilder extends AbstractMemberBuilder { * @param constructorDocTree the content tree to which the documentation will be added */ public void buildSignature(XMLNode node, Content constructorDocTree) { - constructorDocTree.addContent(writer.getSignature(constructor)); + constructorDocTree.addContent(writer.getSignature(currentConstructor)); } /** @@ -202,7 +190,7 @@ public class ConstructorBuilder extends AbstractMemberBuilder { * @param constructorDocTree the content tree to which the documentation will be added */ public void buildDeprecationInfo(XMLNode node, Content constructorDocTree) { - writer.addDeprecated(constructor, constructorDocTree); + writer.addDeprecated(currentConstructor, constructorDocTree); } /** @@ -214,7 +202,7 @@ public class ConstructorBuilder extends AbstractMemberBuilder { */ public void buildConstructorComments(XMLNode node, Content constructorDocTree) { if (!configuration.nocomment) { - writer.addComments(constructor, constructorDocTree); + writer.addComments(currentConstructor, constructorDocTree); } } @@ -225,6 +213,6 @@ public class ConstructorBuilder extends AbstractMemberBuilder { * @param constructorDocTree the content tree to which the documentation will be added */ public void buildTagInfo(XMLNode node, Content constructorDocTree) { - writer.addTags(constructor, constructorDocTree); + writer.addTags(currentConstructor, constructorDocTree); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java index 47ac296c5e9..ddb6619225e 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java @@ -67,9 +67,9 @@ public class EnumConstantBuilder extends AbstractMemberBuilder { private final EnumConstantWriter writer; /** - * The list of enum constants being documented. + * The set of enum constants being documented. */ - private final SortedSet enumConstants; + private final List enumConstants; /** * The current enum constant that is being documented at this point @@ -94,7 +94,7 @@ public class EnumConstantBuilder extends AbstractMemberBuilder { typeElement, VisibleMemberMap.Kind.ENUM_CONSTANTS, configuration); - enumConstants = visibleMemberMap.getMembersFor(typeElement); + enumConstants = visibleMemberMap.getMembers(typeElement); } /** @@ -118,27 +118,6 @@ public class EnumConstantBuilder extends AbstractMemberBuilder { return "EnumConstantDetails"; } - /** - * Returns a list of enum constants that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param typeElement the {@link TypeElement} we want to check. - * @return a list of enum constants that will be documented. - */ - public SortedSet members(TypeElement typeElement) { - return visibleMemberMap.getMembersFor(typeElement); - } - - /** - * Returns the visible member map for the enum constants of this class. - * - * @return the visible member map for the enum constants of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - /** * Returns whether or not there are members to document. * @@ -146,7 +125,7 @@ public class EnumConstantBuilder extends AbstractMemberBuilder { */ @Override public boolean hasMembersToDocument() { - return enumConstants.size() > 0; + return !enumConstants.isEmpty(); } /** @@ -160,16 +139,17 @@ public class EnumConstantBuilder extends AbstractMemberBuilder { if (writer == null) { return; } - if (!enumConstants.isEmpty()) { + if (hasMembersToDocument()) { Content enumConstantsDetailsTree = writer.getEnumConstantsDetailsTreeHeader(typeElement, memberDetailsTree); - for (Element element : enumConstants) { - currentElement = (VariableElement)element; + Element lastElement = enumConstants.get(enumConstants.size() - 1); + for (Element enumConstant : enumConstants) { + currentElement = (VariableElement)enumConstant; Content enumConstantsTree = writer.getEnumConstantsTreeHeader(currentElement, enumConstantsDetailsTree); buildChildren(node, enumConstantsTree); enumConstantsDetailsTree.addContent(writer.getEnumConstants( - enumConstantsTree, currentElement.equals(enumConstants.last()))); + enumConstantsTree, currentElement == lastElement)); } memberDetailsTree.addContent( writer.getEnumConstantsDetails(enumConstantsDetailsTree)); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java index 09f6965f07f..ccb5671b9ab 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java @@ -69,7 +69,7 @@ public class FieldBuilder extends AbstractMemberBuilder { /** * The list of fields being documented. */ - private final SortedSet fields; + private final List fields; /** * The index of the current field that is being documented at this point @@ -95,7 +95,7 @@ public class FieldBuilder extends AbstractMemberBuilder { typeElement, VisibleMemberMap.Kind.FIELDS, configuration); - fields = visibleMemberMap.getLeafClassMembers(); + fields = visibleMemberMap.getLeafMembers(); } /** @@ -120,27 +120,6 @@ public class FieldBuilder extends AbstractMemberBuilder { return "FieldDetails"; } - /** - * Returns a list of fields that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param typeElement the {@link TypeElement} we want to check. - * @return a list of fields that will be documented. - */ - public SortedSet members(TypeElement typeElement) { - return visibleMemberMap.getMembersFor(typeElement); - } - - /** - * Returns the visible member map for the fields of this class. - * - * @return the visible member map for the fields of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - /** * Returns whether or not there are members to document. * @@ -164,12 +143,14 @@ public class FieldBuilder extends AbstractMemberBuilder { } if (!fields.isEmpty()) { Content fieldDetailsTree = writer.getFieldDetailsTreeHeader(typeElement, memberDetailsTree); + + Element lastElement = fields.get(fields.size() - 1); for (Element element : fields) { currentElement = (VariableElement)element; Content fieldDocTree = writer.getFieldDocTreeHeader(currentElement, fieldDetailsTree); buildChildren(node, fieldDocTree); fieldDetailsTree.addContent(writer.getFieldDoc( - fieldDocTree, currentElement.equals(fields.last()))); + fieldDocTree, currentElement == lastElement)); } memberDetailsTree.addContent( writer.getFieldDetails(fieldDetailsTree)); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java index 713fc028e7c..5534abd0bd3 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java @@ -182,7 +182,9 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { * @see VisibleMemberMap */ public SortedSet members(VisibleMemberMap.Kind type) { - return visibleMemberMaps.get(type).getLeafClassMembers(); + TreeSet out = new TreeSet<>(comparator); + out.addAll(visibleMemberMaps.get(type).getLeafMembers()); + return out; } /** @@ -336,7 +338,7 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { */ private void buildSummary(MemberSummaryWriter writer, VisibleMemberMap visibleMemberMap, LinkedList summaryTreeList) { - SortedSet members = visibleMemberMap.getLeafClassMembers(); + SortedSet members = asSortedSet(visibleMemberMap.getLeafMembers()); if (!members.isEmpty()) { List tableContents = new LinkedList<>(); int counter = 0; @@ -492,7 +494,7 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { if (inhclass == typeElement) { continue; } - SortedSet inhmembers = visibleMemberMap.getMembersFor(inhclass); + SortedSet inhmembers = asSortedSet(visibleMemberMap.getMembers(inhclass)); if (!inhmembers.isEmpty()) { Content inheritedTree = writer.getInheritedSummaryHeader(inhclass); Content linksTree = writer.getInheritedSummaryLinksTree(); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java index 7511bdad07d..ba0e88a287b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java @@ -78,7 +78,7 @@ public class MethodBuilder extends AbstractMemberBuilder { /** * The methods being documented. */ - private final SortedSet methods; + private final List methods; /** @@ -98,7 +98,7 @@ public class MethodBuilder extends AbstractMemberBuilder { typeElement, VisibleMemberMap.Kind.METHODS, configuration); - methods = visibleMemberMap.getLeafClassMembers(); + methods = visibleMemberMap.getLeafMembers(); } /** @@ -123,27 +123,6 @@ public class MethodBuilder extends AbstractMemberBuilder { return "MethodDetails"; } - /** - * Returns a list of methods that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param typeElement the {@link TypeElement} we want to check. - * @return a list of methods that will be documented. - */ - public SortedSet members(TypeElement typeElement) { - return visibleMemberMap.getMembersFor(typeElement); - } - - /** - * Returns the visible member map for the methods of this class. - * - * @return the visible member map for the methods of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - /** * {@inheritDoc} */ @@ -163,18 +142,17 @@ public class MethodBuilder extends AbstractMemberBuilder { if (writer == null) { return; } - if (!methods.isEmpty()) { + if (hasMembersToDocument()) { Content methodDetailsTree = writer.getMethodDetailsTreeHeader(typeElement, memberDetailsTree); - Set methodDetailSet = ((ConfigurationImpl)configuration).sortedMethodDetails - ? methods - : visibleMemberMap.getLeafClassMembersSourceOrder(); - for (Element e : methodDetailSet) { - currentMethod = (ExecutableElement) e; + + Element lastElement = methods.get(methods.size() - 1); + for (Element method : methods) { + currentMethod = (ExecutableElement)method; Content methodDocTree = writer.getMethodDocTreeHeader(currentMethod, methodDetailsTree); buildChildren(node, methodDocTree); methodDetailsTree.addContent(writer.getMethodDoc( - methodDocTree, currentMethod == methods.last())); + methodDocTree, currentMethod == lastElement)); } memberDetailsTree.addContent(writer.getMethodDetails(methodDetailsTree)); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java index 68af2e3447b..986924f61fb 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java @@ -69,7 +69,7 @@ public class PropertyBuilder extends AbstractMemberBuilder { /** * The list of properties being documented. */ - private final SortedSet properties; + private final List properties; /** * The index of the current property that is being documented at this point @@ -95,7 +95,7 @@ public class PropertyBuilder extends AbstractMemberBuilder { typeElement, VisibleMemberMap.Kind.PROPERTIES, configuration); - properties = visibleMemberMap.getMembersFor(typeElement); + properties = visibleMemberMap.getMembers(typeElement); } /** @@ -120,27 +120,6 @@ public class PropertyBuilder extends AbstractMemberBuilder { return "PropertyDetails"; } - /** - * Returns a list of properties that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param typeElement the {@link TypeElement} we want to check. - * @return a list of properties that will be documented. - */ - public SortedSet members(TypeElement typeElement) { - return visibleMemberMap.getMembersFor(typeElement); - } - - /** - * Returns the visible member map for the properties of this class. - * - * @return the visible member map for the properties of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - /** * Returns whether or not there are members to document. * @@ -162,17 +141,17 @@ public class PropertyBuilder extends AbstractMemberBuilder { if (writer == null) { return; } - int size = properties.size(); - if (size > 0) { + if (hasMembersToDocument()) { Content propertyDetailsTree = writer.getPropertyDetailsTreeHeader(typeElement, memberDetailsTree); - for (Element e : properties) { - currentProperty = (ExecutableElement) e; + Element lastElement = properties.get(properties.size() - 1); + for (Element property : properties) { + currentProperty = (ExecutableElement)property; Content propertyDocTree = writer.getPropertyDocTreeHeader(currentProperty, propertyDetailsTree); buildChildren(node, propertyDocTree); propertyDetailsTree.addContent(writer.getPropertyDoc( - propertyDocTree, currentProperty == properties.last())); + propertyDocTree, currentProperty == lastElement)); } memberDetailsTree.addContent( writer.getPropertyDetails(propertyDetailsTree)); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index e23cf65983a..7ba231bac15 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -25,7 +25,6 @@ package jdk.javadoc.internal.doclets.toolkit.util; -import java.io.IOException; import java.lang.annotation.Documented; import java.lang.ref.SoftReference; import java.text.CollationKey; @@ -77,9 +76,7 @@ import com.sun.source.util.DocTrees; import com.sun.source.util.TreePath; import jdk.javadoc.internal.doclets.toolkit.CommentUtils.DocCommentDuo; import jdk.javadoc.internal.doclets.toolkit.Configuration; -import jdk.javadoc.internal.doclets.toolkit.DocletException; import jdk.javadoc.internal.doclets.toolkit.Messages; -import jdk.javadoc.internal.doclets.toolkit.Resources; import jdk.javadoc.internal.doclets.toolkit.WorkArounds; import static javax.lang.model.element.ElementKind.*; @@ -258,14 +255,6 @@ public class Utils { return getEnclosingTypeElement(e) == null || isStatic(e); } - public boolean matches(Element e1, Element e2) { - if (isExecutableElement(e1) && isExecutableElement(e1)) { - return executableMembersEqual((ExecutableElement)e1, (ExecutableElement)e2); - } else { - return e1.getSimpleName().equals(e2.getSimpleName()); - } - } - /** * Copy doc-files directory and its contents from the source * package directory to the generated documentation directory. @@ -2161,6 +2150,13 @@ public class Utils { return convertToExecutableElement(getItems(e, false, METHOD)); } + public int getOrdinalValue(VariableElement member) { + if (member == null || member.getKind() != ENUM_CONSTANT) { + throw new IllegalArgumentException("must be an enum constant: " + member); + } + return member.getEnclosingElement().getEnclosedElements().indexOf(member); + } + public long getLineNumber(Element e) { TreePath path = getTreePath(e); if (path == null) { // maybe null if synthesized diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java index 6fbae159bf1..08e07514964 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java @@ -220,48 +220,36 @@ public class VisibleMemberMap { } /** - * Return the visible members of the class being mapped. Also append at the - * end of the list members that are inherited by inaccessible parents. We - * document these members in the child because the parent is not documented. + * Returns a list of visible enclosed members of the type being mapped. + * This list may also contain appended members, inherited by inaccessible + * super types. These members are documented in the subtype when the + * super type is not documented. * - * @param configuration the current configuration of the doclet. + * @return a list of visible enclosed members */ - public SortedSet getLeafClassMembers() { - SortedSet result = getMembersFor(typeElement); - result.addAll(getInheritedPackagePrivateMethods()); - return result; - } - public Set getLeafClassMembersSourceOrder() { - Set result = new LinkedHashSet<>(classMap.get(typeElement).members); + public List getLeafMembers() { + List result = new ArrayList<>(); + result.addAll(classMap.get(typeElement).members); result.addAll(getInheritedPackagePrivateMethods()); return result; } /** - * Retrn the list of members for the given class. + * Returns a list of enclosed members for the given type. * - * @param typeElement the class to retrieve the list of visible members for. + * @param typeElement the given type * - * @return the list of members for the given class. + * @return a list of enclosed members */ - public SortedSet getMembersFor(TypeElement typeElement) { - return asSortedSet(classMap.get(typeElement).members); + public List getMembers(TypeElement typeElement) { + return classMap.get(typeElement).members; } - public boolean hasMembersFor(TypeElement typeElement) { + public boolean hasMembers(TypeElement typeElement) { return !classMap.get(typeElement).members.isEmpty(); } - private SortedSet asSortedSet(Collection in) { - if (in == null) { - return Collections.emptySortedSet(); - } - TreeSet out = new TreeSet<>(comparator); - out.addAll(in); - return out; - } - private void fillMemberLevelMap(List list, String level) { for (Element element : list) { Object key = getMemberKey(element); @@ -318,9 +306,9 @@ public class VisibleMemberMap { private final TypeElement typeElement; /** - * List of inherited members from the mapping class. + * List of members from the mapping class. */ - private Set members = new LinkedHashSet<>(); + private List members = null; /** * Level/Depth of inheritance. @@ -379,23 +367,23 @@ public class VisibleMemberMap { * Adjust member-level-map, class-map. */ private void addMembers(TypeElement fromClass) { - List classMembers = getClassMembers(fromClass, true); - List incllist = new ArrayList<>(); - for (Element element : classMembers) { - if (!found(members, element)) { - if (memberIsVisible(element)) { - if (!isOverridden(element, level)) { - if (!utils.isHidden(element)) { - incllist.add(element); - } + List result = new ArrayList<>(); + for (Element element : getClassMembers(fromClass, true)) { + if (memberIsVisible(element)) { + if (!isOverridden(element, level)) { + if (!utils.isHidden(element)) { + result.add(element); } } } } - if (!incllist.isEmpty()) { + if (members != null) { + throw new AssertionError("members should not be null"); + } + members = Collections.unmodifiableList(result); + if (!members.isEmpty()) { noVisibleMembers = false; } - members.addAll(incllist); fillMemberLevelMap(getClassMembers(fromClass, false), level); } @@ -513,16 +501,6 @@ public class VisibleMemberMap { return targetMembers; } - private boolean found(Iterable list, Element elem) { - for (Element pgmelem : list) { - if (utils.matches(pgmelem, elem)) { - return true; - } - } - return false; - } - - /** * Is member overridden? The member is overridden if it is found in the * same level hierarchy e.g. member at level "11" overrides member at diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index c5b94f3500b..49cd9cdbff0 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -939,6 +939,17 @@ public class Start extends ToolOption.Helper { public void put(String name, String value) { compOpts.put(name, value); } + + @Override + public void remove(String name) { + compOpts.remove(name); + } + + @Override + public boolean handleFileManagerOption(com.sun.tools.javac.main.Option option, String value) { + fileManagerOpts.put(option, value); + return true; + } }; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java index 1949e684dd9..7f4ef90868b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java @@ -57,63 +57,56 @@ public enum ToolOption { BOOTCLASSPATH("-bootclasspath", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.BOOT_CLASS_PATH, arg); + Option.BOOT_CLASS_PATH.process(helper.getOptionHelper(), primaryName, arg); } }, CLASS_PATH("--class-path -classpath -cp", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.CLASS_PATH, arg); + Option.CLASS_PATH.process(helper.getOptionHelper(), primaryName, arg); } }, EXTDIRS("-extdirs", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.EXTDIRS, arg); + Option.EXTDIRS.process(helper.getOptionHelper(), primaryName, arg); } }, SOURCE_PATH("--source-path -sourcepath", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.SOURCE_PATH, arg); - } - }, - - SYSCLASSPATH("-sysclasspath", HIDDEN, true) { - @Override - public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.BOOT_CLASS_PATH, arg); + Option.SOURCE_PATH.process(helper.getOptionHelper(), primaryName, arg); } }, MODULE_SOURCE_PATH("--module-source-path", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.MODULE_SOURCE_PATH, arg); + Option.MODULE_SOURCE_PATH.process(helper.getOptionHelper(), primaryName, arg); } }, UPGRADE_MODULE_PATH("--upgrade-module-path", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.UPGRADE_MODULE_PATH, arg); + Option.UPGRADE_MODULE_PATH.process(helper.getOptionHelper(), primaryName, arg); } }, SYSTEM("--system", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.SYSTEM, arg); + Option.SYSTEM.process(helper.getOptionHelper(), primaryName, arg); } }, MODULE_PATH("--module-path -p", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.MODULE_PATH, arg); + Option.MODULE_PATH.process(helper.getOptionHelper(), primaryName, arg); } }, @@ -141,7 +134,7 @@ public enum ToolOption { ENCODING("-encoding", STANDARD, true) { @Override public void process(Helper helper, String arg) { - helper.setFileManagerOpt(Option.ENCODING, arg); + Option.ENCODING.process(helper.getOptionHelper(), primaryName, arg); } }, @@ -290,14 +283,6 @@ public enum ToolOption { // ----- output control options ----- - PROMPT("-prompt", HIDDEN) { - @Override - public void process(Helper helper) { - helper.compOpts.put("-prompt", "-prompt"); - helper.promptOnError = true; - } - }, - QUIET("-quiet", STANDARD) { @Override public void process(Helper helper) { diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java index 02d6bc6ea9b..44159653d95 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java @@ -89,6 +89,7 @@ public class JdepsConfiguration implements AutoCloseable { List classpaths, List initialArchives, boolean allDefaultModules, + boolean allSystemModules, Runtime.Version version) throws IOException { @@ -107,6 +108,11 @@ public class JdepsConfiguration implements AutoCloseable { roots.isEmpty() || allDefaultModules) { mods.addAll(systemModulePath.defaultSystemRoots()); } + if (allSystemModules) { + systemModulePath.findAll().stream() + .map(mref -> mref.descriptor().name()) + .forEach(mods::add); + } this.configuration = Configuration.empty() .resolveRequires(finder, ModuleFinder.of(), mods); @@ -488,6 +494,7 @@ public class JdepsConfiguration implements AutoCloseable { ModuleFinder appModulePath; boolean addAllApplicationModules; boolean addAllDefaultModules; + boolean addAllSystemModules; Runtime.Version version; public Builder() { @@ -533,8 +540,7 @@ public class JdepsConfiguration implements AutoCloseable { * Include all system modules and modules found on modulepath */ public Builder allModules() { - systemModulePath.moduleNames() - .forEach(this.rootModules::add); + this.addAllSystemModules = true; this.addAllApplicationModules = true; return this; } @@ -588,6 +594,7 @@ public class JdepsConfiguration implements AutoCloseable { classPaths, initialArchives, addAllDefaultModules, + addAllSystemModules, version); } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java index dca3f476d3c..3ed77929c9c 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java @@ -25,8 +25,10 @@ package com.sun.tools.jdeps; +import com.sun.tools.jdeps.Analyzer.Type; import static com.sun.tools.jdeps.Analyzer.Type.*; import static com.sun.tools.jdeps.JdepsWriter.*; +import static java.util.stream.Collectors.*; import java.io.IOException; import java.io.PrintWriter; @@ -111,6 +113,10 @@ class JdepsTask { this.aliases = aliases; } + Option(boolean hasArg, CommandOption cmd) { + this(hasArg, cmd.names()); + } + boolean isHidden() { return false; } @@ -144,25 +150,46 @@ class JdepsTask { } } + enum CommandOption { + ANALYZE_DEPS(""), + GENERATE_DOT_FILE("-dotoutput", "--dot-output"), + GENERATE_MODULE_INFO("--generate-module-info"), + LIST_DEPS("--list-deps"), + LIST_REDUCED_DEPS("--list-reduced-deps"), + CHECK_MODULES("--check"); + + private final String[] names; + CommandOption(String... names) { + this.names = names; + } + + String[] names() { + return names; + } + + @Override + public String toString() { + return names[0]; + } + } + static Option[] recognizedOptions = { new Option(false, "-h", "-?", "-help", "--help") { void process(JdepsTask task, String opt, String arg) { task.options.help = true; } }, - new Option(true, "-dotoutput", "--dot-output") { + new Option(true, CommandOption.GENERATE_DOT_FILE) { void process(JdepsTask task, String opt, String arg) throws BadArgs { - Path p = Paths.get(arg); - if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) { - throw new BadArgs("err.invalid.path", arg); + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); } - task.options.dotOutputDir = Paths.get(arg);; + task.command = task.genDotFile(Paths.get(arg)); } }, new Option(false, "-s", "-summary") { void process(JdepsTask task, String opt, String arg) { task.options.showSummary = true; - task.options.verbose = SUMMARY; } }, new Option(false, "-v", "-verbose", @@ -196,35 +223,48 @@ class JdepsTask { task.options.apiOnly = true; } }, - new Option(true, "--check") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - Set mods = Set.of(arg.split(",")); - task.options.checkModuleDeps = mods; - task.options.addmods.addAll(mods); - } - }, - new Option(true, "--generate-module-info") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - Path p = Paths.get(arg); - if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) { - throw new BadArgs("err.invalid.path", arg); - } - task.options.genModuleInfo = Paths.get(arg); - } - }, + new Option(false, "-jdkinternals", "--jdk-internals") { void process(JdepsTask task, String opt, String arg) { task.options.findJDKInternals = true; - task.options.verbose = CLASS; if (task.options.includePattern == null) { task.options.includePattern = Pattern.compile(".*"); } } }, - new Option(false, "--list-deps", "--list-reduced-deps") { - void process(JdepsTask task, String opt, String arg) { - task.options.showModulesAddExports = true; - task.options.reduced = opt.equals("--list-reduced-deps"); + + new Option(true, CommandOption.CHECK_MODULES) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + Set mods = Set.of(arg.split(",")); + task.options.addmods.addAll(mods); + task.command = task.checkModuleDeps(mods); + } + }, + new Option(true, CommandOption.GENERATE_MODULE_INFO) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + task.command = task.genModuleInfo(Paths.get(arg)); + } + }, + new Option(false, CommandOption.LIST_DEPS) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + task.command = task.listModuleDeps(false); + } + }, + new Option(false, CommandOption.LIST_REDUCED_DEPS) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + task.command = task.listModuleDeps(true); } }, @@ -419,6 +459,7 @@ class JdepsTask { private final Options options = new Options(); private final List inputArgs = new ArrayList<>(); + private Command command; private PrintWriter log; void setLog(PrintWriter out) { log = out; @@ -445,55 +486,30 @@ class JdepsTask { if (options.version || options.fullVersion) { showVersion(options.fullVersion); } + if (options.help || options.version || options.fullVersion) { + return EXIT_OK; + } + if (!inputArgs.isEmpty() && options.rootModule != null) { reportError("err.invalid.arg.for.option", "-m"); } - if (inputArgs.isEmpty() && options.addmods.isEmpty() && options.includePattern == null - && options.includeSystemModulePattern == null && options.checkModuleDeps == null) { - if (options.help || options.version || options.fullVersion) { - return EXIT_OK; - } else { - showHelp(); - return EXIT_CMDERR; - } - } - if (options.genModuleInfo != null) { - if (options.dotOutputDir != null || options.classpath != null || options.hasFilter()) { - showHelp(); - return EXIT_CMDERR; - } - } if (options.numFilters() > 1) { reportError("err.invalid.filters"); return EXIT_CMDERR; } - if (options.inverse && options.depth != 1) { - reportError("err.invalid.inverse.option", "-R"); - return EXIT_CMDERR; + // default command to analyze dependences + if (command == null) { + command = analyzeDeps(); } - - if (options.inverse && options.numFilters() == 0) { - reportError("err.invalid.filters"); - return EXIT_CMDERR; - } - - if ((options.findJDKInternals) && (options.hasFilter() || options.showSummary)) { - showHelp(); - return EXIT_CMDERR; - } - if (options.showSummary && options.verbose != SUMMARY) { - showHelp(); - return EXIT_CMDERR; - } - if (options.checkModuleDeps != null && !inputArgs.isEmpty()) { - reportError("err.invalid.module.option", inputArgs, "--check"); + if (!command.checkOptions()) { return EXIT_CMDERR; } boolean ok = run(); return ok ? EXIT_OK : EXIT_ERROR; + } catch (BadArgs|UncheckedBadArgs e) { reportError(e.getKey(), e.getArgs()); if (e.showUsage()) { @@ -515,13 +531,14 @@ class JdepsTask { } boolean run() throws IOException { - try (JdepsConfiguration config = buildConfig()) { + try (JdepsConfiguration config = buildConfig(command.allModules())) { // detect split packages - config.splitPackages().entrySet().stream() + config.splitPackages().entrySet() + .stream() .sorted(Map.Entry.comparingByKey()) .forEach(e -> System.out.format("split package: %s %s%n", e.getKey(), - e.getValue().toString())); + e.getValue().toString())); // check if any module specified in --require is missing Stream.concat(options.addmods.stream(), options.requires.stream()) @@ -529,38 +546,11 @@ class JdepsTask { .forEach(mn -> config.findModule(mn).orElseThrow(() -> new UncheckedBadArgs(new BadArgs("err.module.not.found", mn)))); - // --generate-module-info - if (options.genModuleInfo != null) { - return genModuleInfo(config); - } - - // --check - if (options.checkModuleDeps != null) { - return new ModuleAnalyzer(config, log, options.checkModuleDeps).run(); - } - - if (options.showModulesAddExports) { - return new ModuleExportsAnalyzer(config, - dependencyFilter(config), - options.reduced, - log).run(); - } - - if (options.dotOutputDir != null && - (options.verbose == SUMMARY || options.verbose == MODULE) && - !options.addmods.isEmpty() && inputArgs.isEmpty()) { - return new ModuleAnalyzer(config, log).genDotFiles(options.dotOutputDir); - } - - if (options.inverse) { - return analyzeInverseDeps(config); - } else { - return analyzeDeps(config); - } + return command.run(config); } } - private JdepsConfiguration buildConfig() throws IOException { + private JdepsConfiguration buildConfig(boolean allModules) throws IOException { JdepsConfiguration.Builder builder = new JdepsConfiguration.Builder(options.systemModulePath); @@ -568,7 +558,7 @@ class JdepsTask { .appModulePath(options.modulePath) .addmods(options.addmods); - if (options.checkModuleDeps != null || options.showModulesAddExports) { + if (allModules) { // check all system modules in the image builder.allModules(); } @@ -592,148 +582,421 @@ class JdepsTask { return builder.build(); } - private boolean analyzeDeps(JdepsConfiguration config) throws IOException { - // output result - final JdepsWriter writer; - if (options.dotOutputDir != null) { - writer = new DotFileWriter(options.dotOutputDir, - options.verbose, - options.showProfile, - options.showModule, - options.showLabel); - } else { - writer = new SimpleWriter(log, - options.verbose, - options.showProfile, - options.showModule); - } + // ---- factory methods to create a Command - // analyze the dependencies - DepsAnalyzer analyzer = new DepsAnalyzer(config, - dependencyFilter(config), - writer, - options.verbose, - options.apiOnly); - - boolean ok = analyzer.run(options.compileTimeView, options.depth); - - // print skipped entries, if any - if (!options.nowarning) { - analyzer.archives() - .forEach(archive -> archive.reader() - .skippedEntries().stream() - .forEach(name -> warning("warn.skipped.entry", name))); - } - - if (options.findJDKInternals && !options.nowarning) { - Map jdkInternals = new TreeMap<>(); - Set deps = analyzer.dependences(); - // find the ones with replacement - deps.forEach(cn -> replacementFor(cn).ifPresent( - repl -> jdkInternals.put(cn, repl)) - ); - - if (!deps.isEmpty()) { - log.println(); - warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url")); - } - - if (!jdkInternals.isEmpty()) { - log.println(); - log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement"); - log.format("%-40s %s%n", "----------------", "---------------------"); - jdkInternals.entrySet().stream() - .forEach(e -> { - String key = e.getKey(); - String[] lines = e.getValue().split("\\n"); - for (String s : lines) { - log.format("%-40s %s%n", key, s); - key = ""; - } - }); - } - } - return ok; + private AnalyzeDeps analyzeDeps() throws BadArgs { + return options.inverse ? new InverseAnalyzeDeps() + : new AnalyzeDeps(); } - private boolean analyzeInverseDeps(JdepsConfiguration config) throws IOException { - JdepsWriter writer = new SimpleWriter(log, - options.verbose, - options.showProfile, - options.showModule); - - InverseDepsAnalyzer analyzer = new InverseDepsAnalyzer(config, - dependencyFilter(config), - writer, - options.verbose, - options.apiOnly); - boolean ok = analyzer.run(); - - log.println(); - if (!options.requires.isEmpty()) - log.format("Inverse transitive dependences on %s%n", options.requires); - else - log.format("Inverse transitive dependences matching %s%n", - options.regex != null - ? options.regex.toString() - : "packages " + options.packageNames); - - analyzer.inverseDependences().stream() - .sorted(Comparator.comparing(this::sortPath)) - .forEach(path -> log.println(path.stream() - .map(Archive::getName) - .collect(Collectors.joining(" <- ")))); - return ok; + private GenDotFile genDotFile(Path dir) throws BadArgs { + if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) { + throw new BadArgs("err.invalid.path", dir.toString()); + } + return new GenDotFile(dir); } - private String sortPath(Deque path) { - return path.peekFirst().getName(); + private GenModuleInfo genModuleInfo(Path dir) throws BadArgs { + if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) { + throw new BadArgs("err.invalid.path", dir.toString()); + } + return new GenModuleInfo(dir); } - private boolean genModuleInfo(JdepsConfiguration config) throws IOException { - // check if any JAR file contains unnamed package - for (String arg : inputArgs) { - try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) { - Optional classInUnnamedPackage = - reader.entries().stream() - .filter(n -> n.endsWith(".class")) - .filter(cn -> toPackageName(cn).isEmpty()) - .findFirst(); + private ListModuleDeps listModuleDeps(boolean reduced) throws BadArgs { + return reduced ? new ListReducedDeps() + : new ListModuleDeps(); + } - if (classInUnnamedPackage.isPresent()) { - if (classInUnnamedPackage.get().equals("module-info.class")) { - reportError("err.genmoduleinfo.not.jarfile", arg); - } else { - reportError("err.genmoduleinfo.unnamed.package", arg); - } + private CheckModuleDeps checkModuleDeps(Set mods) throws BadArgs { + return new CheckModuleDeps(mods); + } + + abstract class Command { + final CommandOption option; + protected Command(CommandOption option) { + this.option = option; + } + /** + * Returns true if the command-line options are all valid; + * otherwise, returns false. + */ + abstract boolean checkOptions(); + + /** + * Do analysis + */ + abstract boolean run(JdepsConfiguration config) throws IOException; + + /** + * Includes all modules on system module path and application module path + */ + boolean allModules() { + return false; + } + + @Override + public String toString() { + return option.toString(); + } + } + + + /** + * Analyze dependences + */ + class AnalyzeDeps extends Command { + JdepsWriter writer; + AnalyzeDeps() { + this(CommandOption.ANALYZE_DEPS); + } + + AnalyzeDeps(CommandOption option) { + super(option); + } + + @Override + boolean checkOptions() { + if (options.findJDKInternals) { + // cannot set any filter, -verbose and -summary option + if (options.showSummary || options.verbose != null) { + reportError("err.invalid.options", "-summary or -verbose", + "-jdkinternals"); + return false; + } + if (options.hasFilter()) { + reportError("err.invalid.options", "--package, --regex, --require", + "-jdkinternals"); return false; } } + if (options.showSummary) { + // -summary cannot use with -verbose option + if (options.verbose != null) { + reportError("err.invalid.options", "-v, -verbose", "-s, -summary"); + return false; + } + } + if (inputArgs.isEmpty() && !options.hasSourcePath()) { + showHelp(); + return false; + } + return true; } - ModuleInfoBuilder builder - = new ModuleInfoBuilder(config, inputArgs, options.genModuleInfo); - boolean ok = builder.run(); + /* + * Default is to show package-level dependencies + */ + Type getAnalyzerType() { + if (options.showSummary) + return Type.SUMMARY; - if (!ok && !options.nowarning) { - log.println("ERROR: missing dependencies"); - builder.visitMissingDeps( - new Analyzer.Visitor() { - @Override - public void visitDependence(String origin, Archive originArchive, - String target, Archive targetArchive) { - if (builder.notFound(targetArchive)) - log.format(" %-50s -> %-50s %s%n", - origin, target, targetArchive.getName()); - } - }); + if (options.findJDKInternals) + return Type.CLASS; + + // default to package-level verbose + return options.verbose != null ? options.verbose : PACKAGE; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + Type type = getAnalyzerType(); + // default to package-level verbose + JdepsWriter writer = new SimpleWriter(log, + type, + options.showProfile, + options.showModule); + + return run(config, writer, type); + } + + boolean run(JdepsConfiguration config, JdepsWriter writer, Type type) throws IOException { + + + // analyze the dependencies + DepsAnalyzer analyzer = new DepsAnalyzer(config, + dependencyFilter(config), + writer, + type, + options.apiOnly); + + boolean ok = analyzer.run(options.compileTimeView, options.depth); + + // print skipped entries, if any + if (!options.nowarning) { + analyzer.archives() + .forEach(archive -> archive.reader() + .skippedEntries().stream() + .forEach(name -> warning("warn.skipped.entry", name))); + } + + if (options.findJDKInternals && !options.nowarning) { + Map jdkInternals = new TreeMap<>(); + Set deps = analyzer.dependences(); + // find the ones with replacement + deps.forEach(cn -> replacementFor(cn).ifPresent( + repl -> jdkInternals.put(cn, repl)) + ); + + if (!deps.isEmpty()) { + log.println(); + warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url")); + } + + if (!jdkInternals.isEmpty()) { + log.println(); + log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement"); + log.format("%-40s %s%n", "----------------", "---------------------"); + jdkInternals.entrySet().stream() + .forEach(e -> { + String key = e.getKey(); + String[] lines = e.getValue().split("\\n"); + for (String s : lines) { + log.format("%-40s %s%n", key, s); + key = ""; + } + }); + } + } + return ok; } - return ok; } - private String toPackageName(String name) { - int i = name.lastIndexOf('/'); - return i > 0 ? name.replace('/', '.').substring(0, i) : ""; + + class InverseAnalyzeDeps extends AnalyzeDeps { + InverseAnalyzeDeps() { + } + + @Override + boolean checkOptions() { + if (options.depth != 1) { + reportError("err.invalid.options", "-R", "--inverse"); + return false; + } + + if (options.numFilters() == 0) { + reportError("err.filter.not.specified"); + return false; + } + + if (!super.checkOptions()) { + return false; + } + + return true; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + Type type = getAnalyzerType(); + + InverseDepsAnalyzer analyzer = + new InverseDepsAnalyzer(config, + dependencyFilter(config), + writer, + type, + options.apiOnly); + boolean ok = analyzer.run(); + + log.println(); + if (!options.requires.isEmpty()) + log.format("Inverse transitive dependences on %s%n", options.requires); + else + log.format("Inverse transitive dependences matching %s%n", + options.regex != null + ? options.regex.toString() + : "packages " + options.packageNames); + + analyzer.inverseDependences().stream() + .sorted(Comparator.comparing(this::sortPath)) + .forEach(path -> log.println(path.stream() + .map(Archive::getName) + .collect(joining(" <- ")))); + return ok; + } + + private String sortPath(Deque path) { + return path.peekFirst().getName(); + } + } + + + class GenModuleInfo extends Command { + final Path dir; + GenModuleInfo(Path dir) { + super(CommandOption.GENERATE_MODULE_INFO); + this.dir = dir; + } + + @Override + boolean checkOptions() { + if (options.classpath != null) { + reportError("err.invalid.options", "-classpath", + option); + return false; + } + if (options.hasFilter()) { + reportError("err.invalid.options", "--package, --regex, --require", + option); + return false; + } + return true; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + // check if any JAR file contains unnamed package + for (String arg : inputArgs) { + try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) { + Optional classInUnnamedPackage = + reader.entries().stream() + .filter(n -> n.endsWith(".class")) + .filter(cn -> toPackageName(cn).isEmpty()) + .findFirst(); + + if (classInUnnamedPackage.isPresent()) { + if (classInUnnamedPackage.get().equals("module-info.class")) { + reportError("err.genmoduleinfo.not.jarfile", arg); + } else { + reportError("err.genmoduleinfo.unnamed.package", arg); + } + return false; + } + } + } + + ModuleInfoBuilder builder + = new ModuleInfoBuilder(config, inputArgs, dir); + boolean ok = builder.run(); + + if (!ok && !options.nowarning) { + log.println("ERROR: missing dependencies"); + builder.visitMissingDeps( + new Analyzer.Visitor() { + @Override + public void visitDependence(String origin, Archive originArchive, + String target, Archive targetArchive) { + if (builder.notFound(targetArchive)) + log.format(" %-50s -> %-50s %s%n", + origin, target, targetArchive.getName()); + } + }); + } + return ok; + } + + private String toPackageName(String name) { + int i = name.lastIndexOf('/'); + return i > 0 ? name.replace('/', '.').substring(0, i) : ""; + } + } + + class CheckModuleDeps extends Command { + final Set modules; + CheckModuleDeps(Set mods) { + super(CommandOption.CHECK_MODULES); + this.modules = mods; + } + + @Override + boolean checkOptions() { + if (!inputArgs.isEmpty()) { + reportError("err.invalid.options", inputArgs, "--check"); + return false; + } + return true; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + if (!config.initialArchives().isEmpty()) { + String list = config.initialArchives().stream() + .map(Archive::getPathName).collect(joining(" ")); + throw new UncheckedBadArgs(new BadArgs("err.invalid.options", + list, "--check")); + } + return new ModuleAnalyzer(config, log, modules).run(); + } + + public boolean allModules() { + return true; + } + } + + class ListReducedDeps extends ListModuleDeps { + ListReducedDeps() { + super(CommandOption.LIST_REDUCED_DEPS, true); + } + } + + class ListModuleDeps extends Command { + final boolean reduced; + ListModuleDeps() { + this(CommandOption.LIST_DEPS, false); + } + ListModuleDeps(CommandOption option, boolean reduced) { + super(option); + this.reduced = reduced; + } + + @Override + boolean checkOptions() { + if (options.showSummary || options.verbose != null) { + reportError("err.invalid.options", "-summary or -verbose", + option); + return false; + } + if (options.findJDKInternals) { + reportError("err.invalid.options", "-jdkinternals", + option); + return false; + } + if (inputArgs.isEmpty() && !options.hasSourcePath()) { + showHelp(); + return false; + } + return true; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + return new ModuleExportsAnalyzer(config, + dependencyFilter(config), + reduced, + log).run(); + } + + @Override + boolean allModules() { + return true; + } + } + + + class GenDotFile extends AnalyzeDeps { + final Path dotOutputDir; + GenDotFile(Path dotOutputDir) { + super(CommandOption.GENERATE_DOT_FILE); + + this.dotOutputDir = dotOutputDir; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + if ((options.showSummary || options.verbose == MODULE) && + !options.addmods.isEmpty() && inputArgs.isEmpty()) { + // print module descriptor + return new ModuleAnalyzer(config, log).genDotFiles(dotOutputDir); + } + + Type type = getAnalyzerType(); + JdepsWriter writer = new DotFileWriter(dotOutputDir, + type, + options.showProfile, + options.showModule, + options.showLabel); + return run(config, writer, type); + } } /** @@ -875,14 +1138,11 @@ class JdepsTask { boolean showLabel; boolean findJDKInternals; boolean nowarning = false; - // default is to show package-level dependencies - // and filter references from same package - Analyzer.Type verbose = PACKAGE; + Analyzer.Type verbose; + // default filter references from same package boolean filterSamePackage = true; boolean filterSameArchive = false; Pattern filterRegex; - Path dotOutputDir; - Path genModuleInfo; String classpath; int depth = 1; Set requires = new HashSet<>(); @@ -892,15 +1152,17 @@ class JdepsTask { Pattern includeSystemModulePattern; boolean inverse = false; boolean compileTimeView = false; - Set checkModuleDeps; String systemModulePath = System.getProperty("java.home"); String upgradeModulePath; String modulePath; String rootModule; Set addmods = new HashSet<>(); Runtime.Version multiRelease; - boolean showModulesAddExports; - boolean reduced; + + boolean hasSourcePath() { + return !addmods.isEmpty() || includePattern != null || + includeSystemModulePattern != null; + } boolean hasFilter() { return numFilters() > 0; diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java index 810498b6718..f00394a05a3 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java @@ -81,7 +81,7 @@ class Module extends Archive { * Returns module name */ public String name() { - return descriptor.name(); + return descriptor != null ? descriptor.name() : getName(); } public boolean isNamed() { diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java index c5a5a971158..9c0d65cfc1a 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java @@ -70,14 +70,6 @@ public class ModuleAnalyzer { public ModuleAnalyzer(JdepsConfiguration config, PrintWriter log, Set names) { - - if (!config.initialArchives().isEmpty()) { - String list = config.initialArchives().stream() - .map(Archive::getPathName).collect(joining(" ")); - throw new JdepsTask.UncheckedBadArgs(new BadArgs("err.invalid.module.option", - list, "--check")); - } - this.configuration = config; this.log = log; diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java index 79847e6d6ec..8d7b82094a1 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static com.sun.tools.jdeps.Analyzer.NOT_FOUND; @@ -140,20 +141,34 @@ public class ModuleExportsAnalyzer extends DepsAnalyzer { Set modules = builder.build().adjacentNodes(root); // if reduced is set, apply transition reduction - Set reducedSet = reduced ? builder.reduced().adjacentNodes(root) - : modules; + Set reducedSet; + if (reduced) { + Set nodes = builder.reduced().adjacentNodes(root); + if (nodes.size() == 1) { + // java.base only + reducedSet = nodes; + } else { + // java.base is mandated and can be excluded from the reduced graph + reducedSet = nodes.stream() + .filter(m -> !"java.base".equals(m.name()) || + jdkinternals.containsKey("java.base")) + .collect(Collectors.toSet()); + } + } else { + reducedSet = modules; + } modules.stream() .sorted(Comparator.comparing(Module::name)) .forEach(m -> { - if (jdkinternals.containsKey(m)) { - jdkinternals.get(m).stream() - .sorted() - .forEach(pn -> writer.format(" %s/%s%n", m, pn)); - } else if (reducedSet.contains(m)){ - // if the transition reduction is applied, show the reduced graph - writer.format(" %s%n", m); - } + if (jdkinternals.containsKey(m)) { + jdkinternals.get(m).stream() + .sorted() + .forEach(pn -> writer.format(" %s/%s%n", m, pn)); + } else if (reducedSet.contains(m)){ + // if the transition reduction is applied, show the reduced graph + writer.format(" %s%n", m); + } }); } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties index 8bff48b92dc..4189ae86745 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties @@ -151,7 +151,9 @@ main.opt.jdkinternals=\ main.opt.list-deps=\ \ --list-deps Lists the dependences and use of JDK internal\n\ -\ APIs.\n\ +\ APIs. + +main.opt.list-reduced-deps=\ \ --list-reduced-deps Same as --list-deps with not listing\n\ \ the implied reads edges from the module graph\n\ \ If module M1 depends on M2 and M3,\n\ @@ -171,6 +173,7 @@ main.opt.multi-release=\ \ multi-release jar files. should\n\ \ be integer >= 9 or base. +err.command.set={0} and {1} options are specified. err.unknown.option=unknown option: {0} err.missing.arg=no value given for {0} err.invalid.arg.for.option=invalid argument for option: {0} @@ -180,11 +183,10 @@ err.genmoduleinfo.unnamed.package={0} contains an unnamed package that is not al err.profiles.msg=No profile information err.exception.message={0} err.invalid.path=invalid path: {0} -err.invalid.module.option=Cannot set {0} with {1} option. -err.invalid.filters=Only one of --package (-p), --regex (-e), --require option can be set +err.invalid.options={0} cannot be used with {1} option err.module.not.found=module not found: {0} err.root.module.not.set=root module set empty -err.invalid.inverse.option={0} cannot be used with --inverse option +err.filter.not.specified=--package (-p), --regex (-e), --require option must be specified err.multirelease.option.exists={0} is not a multi-release jar file, but the --multi-release option is set err.multirelease.option.notfound={0} is a multi-release jar file, but the --multi-release option is not set err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index 16e9f65bd0c..a99a1fc5579 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -57,7 +57,6 @@ import jdk.internal.jline.TerminalFactory; import jdk.internal.jline.TerminalSupport; import jdk.internal.jline.WindowsTerminal; import jdk.internal.jline.console.ConsoleReader; -import jdk.internal.jline.console.CursorBuffer; import jdk.internal.jline.console.KeyMap; import jdk.internal.jline.console.UserInterruptException; import jdk.internal.jline.console.completer.Completer; @@ -581,26 +580,55 @@ class ConsoleIOContext extends IOContext { private static final FixComputer[] FIX_COMPUTERS = new FixComputer[] { new FixComputer('v', false) { //compute "Introduce variable" Fix: + private void performToVar(ConsoleReader in, String type) throws IOException { + in.redrawLine(); + in.setCursorPosition(0); + in.putString(type + " = "); + in.setCursorPosition(in.getCursorBuffer().cursor - 3); + in.flush(); + } + @Override public FixResult compute(JShellTool repl, String code, int cursor) { String type = repl.analysis.analyzeType(code, cursor); if (type == null) { return new FixResult(Collections.emptyList(), null); } - return new FixResult(Collections.singletonList(new Fix() { + List fixes = new ArrayList<>(); + fixes.add(new Fix() { @Override public String displayName() { return repl.messageFormat("jshell.console.create.variable"); } + @Override public void perform(ConsoleReader in) throws IOException { - in.redrawLine(); - in.setCursorPosition(0); - in.putString(type + " = "); - in.setCursorPosition(in.getCursorBuffer().cursor - 3); - in.flush(); + performToVar(in, type); } - }), null); + }); + int idx = type.lastIndexOf("."); + if (idx > 0) { + String stype = type.substring(idx + 1); + QualifiedNames res = repl.analysis.listQualifiedNames(stype, stype.length()); + if (res.isUpToDate() && res.getNames().contains(type) + && !res.isResolvable()) { + fixes.add(new Fix() { + @Override + public String displayName() { + return "import: " + type + ". " + + repl.messageFormat("jshell.console.create.variable"); + } + + @Override + public void perform(ConsoleReader in) throws IOException { + repl.state.eval("import " + type + ";"); + in.println("Imported: " + type); + performToVar(in, stype); + } + }); + } + } + return new FixResult(fixes, null); } }, new FixComputer('i', true) { //compute "Add import" Fixes: @@ -614,6 +642,7 @@ class ConsoleIOContext extends IOContext { public String displayName() { return "import: " + fqn; } + @Override public void perform(ConsoleReader in) throws IOException { repl.state.eval("import " + fqn + ";"); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java index 45114ac03a6..ee266a30c17 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java @@ -29,6 +29,7 @@ import java.io.InputStream; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.OutputStream; +import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; @@ -111,7 +112,7 @@ public class JdiDefaultExecutionControl extends JdiExecutionControl { */ private static ExecutionControl create(ExecutionEnv env, boolean isLaunch, String host) throws IOException { - try (final ServerSocket listener = new ServerSocket(0)) { + try (final ServerSocket listener = new ServerSocket(0, 1, InetAddress.getLoopbackAddress())) { // timeout after 60 seconds listener.setSoTimeout(60000); int port = listener.getLocalPort(); diff --git a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java index cc8af164a63..bb9c951876b 100644 --- a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java +++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363 + * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363 8167967 * @summary Test of the JavaFX doclet features. * @author jvalenta * @library ../lib @@ -163,10 +163,7 @@ public class TestJavaFX extends JavadocTester { "pkg2"); checkExit(Exit.OK); checkOutput("pkg2/Test.html", true, - "

  • \n" - + "\n" - + "\n" - + "

    Property Detail

    \n" + "

    Property Detail

    \n" + "\n" + "\n" + "\n" @@ -176,27 +173,27 @@ public class TestJavaFX extends JavadocTester { + "
    public java.lang.Object betaProperty
    \n" + "
  • \n" + "\n" - + "\n" + + "\n" + "\n" + "\n" + "
      \n" + "
    • \n" + + "

      gamma

      \n" + + "
      public final java.util.List<java.lang.String> gammaProperty
      \n" + + "
    • \n" + + "
    \n" + + "\n" + + "\n" + + "\n" + + "
      \n" + + "
    • \n" + "

      delta

      \n" + "
      public final java.util.List<"
                       + "java.util.Set<? super java.lang.Object>> deltaProperty
      \n" + "
    • \n" + "
    \n" - + "\n" - + "\n" - + "\n" - + "
      \n" - + "
    • \n" - + "

      gamma

      \n" - + "
      public final java.util.List<"
      -                + "java.lang.String> gammaProperty
      \n" + "
    • \n" - + "
    \n" - + ""); + + ""); } /* diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java index 9ffac254c93..19626d84d10 100644 --- a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java @@ -23,9 +23,8 @@ /* * @test - * @bug 8039410 8042601 8042829 8049393 8050031 8155061 8155995 + * @bug 8039410 8042601 8042829 8049393 8050031 8155061 8155995 8167967 * @summary test to determine if members are ordered correctly - * @author ksrini * @library ../lib/ * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build JavadocTester @@ -51,492 +50,640 @@ public class TestOrdering extends JavadocTester { @Test void testUnnamedPackagesForClassUse() { - javadoc("-d", "out", - "-sourcepath", testSrc, - "-use", - testSrc("C.java"), testSrc("UsedInC.java")); - checkExit(Exit.OK); - checkExecutableMemberOrdering("class-use/UsedInC.html"); + new UnnamedPackageForClassUseTest(this).run(); } @Test void testNamedPackagesForClassUse() { - javadoc("-d", "out-1", - "-sourcepath", testSrc, - "-use", - "pkg1"); - checkExit(Exit.OK); - checkClassUseOrdering("pkg1/class-use/UsedClass.html"); - checkOrder("pkg1/class-use/UsedClass.html", expectedClassUseMethodOrdering); - checkOrder("pkg1/class-use/UsedClass.html", expectedClassUseWithTypeParams); - checkOrder("pkg1/class-use/UsedClass.html", expectedInnerClassContructors); - checkOrder("pkg1/ImplementsOrdering.html", expectedImplementsOrdering); - checkOrder("pkg1/OverrideOrdering.html", expectedOverrideOrdering); - checkOrder("allclasses-noframe.html", expectedAllClasses); - checkOrder("allclasses-frame.html", expectedAllClasses); + new NamedPackagesForClassUseTest(this).run(); } - enum ListOrder { NONE, REVERSE, SHUFFLE }; - /* - * By default we do not shuffle the input list, in order to keep the list deterministic, - * and the test predictable. However, we can turn on the stress mode, by setting the following - * property if required. - */ - static final ListOrder STRESS_MODE = Boolean.getBoolean("TestOrder.STRESS") - ? ListOrder.SHUFFLE - : ListOrder.REVERSE; - - /* - * Controls the number of sibling packages, pkg0, pkg1, pkg2, ..... - */ - static final int MAX_PACKAGES = 4; - - /* - * Controls the number of children packages, pkg0, pkg0.pkg, pkg0.pkg.pkg, ..... - * Note: having too long a depth (> 256 chars on Windows), will likely lead to - * cause problems with automated build and test systems. - */ - static final int MAX_SUBPACKAGES_DEPTH = 4; @Test void testIndexOrdering() throws IOException { - final String clsname = "Add"; - List cmdArgs = new ArrayList(); - cmdArgs.add("-d"); - cmdArgs.add("out-2"); - cmdArgs.add("-sourcepath"); - cmdArgs.add("src"); - cmdArgs.add("-package"); - System.out.println("STRESS_MODE: " + STRESS_MODE); - emitFile(null, clsname, STRESS_MODE); - for (int width = 0 ; width < MAX_PACKAGES ; width++) { - String wpkgname = "add" + width; - String dpkgname = wpkgname; - emitFile(wpkgname, clsname, ListOrder.NONE); // list as-is - cmdArgs.add(wpkgname); - for (int depth = 1 ; depth < MAX_SUBPACKAGES_DEPTH ; depth++) { - dpkgname = dpkgname + ".add"; - emitFile(dpkgname, clsname, STRESS_MODE); - cmdArgs.add(dpkgname); - } - } - File srcDir = new File(new File("."), "src"); - cmdArgs.add(new File(srcDir, clsname + ".java").getPath()); - javadoc(cmdArgs.toArray(new String[cmdArgs.size()])); - checkExit(Exit.OK); - checkOrder("index-all.html", composeTestVectors()); - checkOrder("add0/add/package-tree.html", expectedPackageTreeOrdering); - checkOrder("overview-tree.html", expectedOverviewOrdering); - checkOrder("overview-frame.html", expectedOverviewFrameOrdering); + new IndexOrderingTest(this).run(); } @Test void testIndexTypeClustering() { - javadoc("-d", "out-3", - "-sourcepath", testSrc("src-2"), - "-use", - "a", - "b", - "e", - "something"); - checkOrder("index-all.html", typeTestVectors); - checkExit(Exit.OK); + new IndexTypeClusteringTest(this).run(); } @Test - void testMethodDetailOrdering() { - javadoc("-d", "out-4", - "-sourcepath", testSrc(new File(".").getPath()), - "order" - ); - checkOrder("order/MethodOrder.html", methodSourceOrderVectors); - checkExit(Exit.OK); + void testTypeElementMemberOrdering() { + new TypeElementMemberOrderingTest(this).run(); } - String[] methodSourceOrderVectors = { - "
    public void d()
    \n" + - "
    Method d.\n" + - " Second line.
    ", - "
    public void b()
    \n" + - "
    Method b.\n" + - " Second line.
    ", - "
    public void c()
    \n" + - "
    Method c.\n" + - " Second line.
    ", - "
    public void a()
    \n" + - "
    Method a.\n" + - " Second line.
    " - }; + static class UnnamedPackageForClassUseTest { + final JavadocTester tester; - String[] typeTestVectors = { - "something - package something", - "something - Class in", - "something - Enum in", - "something - Interface in", - "something - Annotation Type in", - "something - Variable in class", - "something() - Constructor", - "something() - Method in class a. - Method in class a. - Method in class something. testList = new ArrayList<>(); - - testList.addAll(Arrays.asList(expectedPackageOrdering)); - for (String x : expectedEnumOrdering) { - testList.add(x.replace("REPLACE_ME", "<Unnamed>")); - for (int i = 0; i < MAX_PACKAGES; i++) { - String wpkg = "add" + i; - testList.add(wpkg + "/" + x.replace("REPLACE_ME", - wpkg)); - String dpkg = wpkg; - for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) { - dpkg = dpkg + "/" + "add"; - testList.add(dpkg + "/" + x.replace("REPLACE_ME", - pathToPackage(dpkg))); - } - } + UnnamedPackageForClassUseTest(JavadocTester tester) { + this.tester = tester; } - testList.addAll(Arrays.asList(expectedFieldOrdering)); - - for (String x : expectedMethodOrdering) { - testList.add(x); - for (int i = 0; i < MAX_PACKAGES; i++) { - String wpkg = "add" + i; - testList.add(wpkg + "/" + x); - String dpkg = wpkg; - for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) { - dpkg = dpkg + "/" + "add"; - testList.add(dpkg + "/" + x); - } - } + void run() { + tester.javadoc("-d", "out", + "-sourcepath", testSrc, + "-use", + tester.testSrc("C.java"), tester.testSrc("UsedInC.java")); + tester.checkExit(Exit.OK); + checkExecutableMemberOrdering("class-use/UsedInC.html"); } - return testList.toArray(new String[testList.size()]); - } - - void checkExecutableMemberOrdering(String usePage) { - String contents = readFile(usePage); - // check constructors - checking("constructors"); - int idx1 = contents.indexOf("C.html#C-UsedInC"); - int idx2 = contents.indexOf("C.html#C-UsedInC-int"); - int idx3 = contents.indexOf("C.html#C-UsedInC-java.lang.String"); - if (idx1 == -1 || idx2 == -1 || idx3 == -1) { - failed("ctor strings not found"); - } else if (idx1 > idx2 || idx2 > idx3 || idx1 > idx3) { - failed("ctor strings are out of order"); - } else - passed("ctor strings are in order"); - - // check methods - checking("methods"); - idx1 = contents.indexOf("C.html#ymethod-int"); - idx2 = contents.indexOf("C.html#ymethod-java.lang.String"); - if (idx1 == -1 || idx2 == -1) { - failed("#ymethod strings not found"); - } else if (idx1 > idx2) { - failed("#ymethod strings are out of order"); - } else - passed("Executable Member Ordering: OK"); - } - - void checkClassUseOrdering(String usePage) { - checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#zfield"); - checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#fieldInC#ITERATION#"); - checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#zmethod-pkg1.UsedClass"); - checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#methodInC#ITERATION#"); - } - - void checkClassUseOrdering(String usePage, String searchString) { - String contents = readFile(usePage); - int lastidx = 0; - System.out.println("testing for " + searchString); - for (int i = 1; i < 5; i++) { - String s = searchString.replaceAll("#ITERATION#", Integer.toString(i)); - checking(s); - int idx = contents.indexOf(s); - if (idx < lastidx) { - failed(s + ", member ordering error, last:" + lastidx + ", got:" + idx); + void checkExecutableMemberOrdering(String usePage) { + String contents = tester.readFile(usePage); + // check constructors + tester.checking("constructors"); + int idx1 = contents.indexOf("C.html#C-UsedInC"); + int idx2 = contents.indexOf("C.html#C-UsedInC-int"); + int idx3 = contents.indexOf("C.html#C-UsedInC-java.lang.String"); + if (idx1 == -1 || idx2 == -1 || idx3 == -1) { + tester.failed("ctor strings not found"); + } else if (idx1 > idx2 || idx2 > idx3 || idx1 > idx3) { + tester.failed("ctor strings are out of order"); } else { - passed("\tlast: " + lastidx + " got:" + idx); + tester.passed("ctor strings are in order"); + } + + // check methods + tester.checking("methods"); + idx1 = contents.indexOf("C.html#ymethod-int"); + idx2 = contents.indexOf("C.html#ymethod-java.lang.String"); + if (idx1 == -1 || idx2 == -1) { + tester.failed("#ymethod strings not found"); + } else if (idx1 > idx2) { + tester.failed("#ymethod strings are out of order"); + } else { + tester.passed("Executable Member Ordering: OK"); } - lastidx = idx; } } - static String[] contents = { - "public add ADDADD;", - "public add AddAdd;", - "public add addadd;", - "public enum add {add, ADD, addd, ADDD};", - "public enum ADD {ADD, add, addd, ADDD};", - "public void add(){}", - "public void add(double d){}", - "public void add(int i, float f){}", - "public void add(float f, int i){}", - "public void add(double d, byte b){}", - "public Double add(Double d) {return (double) 22/7;}", - "public double add(double d1, double d2) {return d1 + d2;}", - "public double add(double d1, Double d2) {return d1 + d2;}", - "public Float add(float f) {return (float) 22/7;}", - "public void add(int i){}", - "public int add(Integer i) {return 0;}" - }; + static class NamedPackagesForClassUseTest { + final JavadocTester tester; - void emitFile(String pkgname, String clsname, ListOrder order) throws IOException { - File srcDir = new File("src"); - File outDir = pkgname == null - ? srcDir - : new File(srcDir, pkgname.replace(".", File.separator)); - File outFile = new File(outDir, clsname + ".java"); - outDir.mkdirs(); - List scratch = new ArrayList<>(Arrays.asList(contents)); - switch (order) { - case SHUFFLE: - Collections.shuffle(scratch); - break; - case REVERSE: - Collections.reverse(scratch); - break; - default: + NamedPackagesForClassUseTest(JavadocTester tester) { + this.tester = tester; + } + + public void run() { + tester.javadoc("-d", "out-1", + "-sourcepath", tester.testSrc, + "-use", + "pkg1"); + tester.checkExit(Exit.OK); + + checkClassUseOrdering("pkg1/class-use/UsedClass.html"); + + tester.checkOrder("pkg1/class-use/UsedClass.html", + "../../pkg1/MethodOrder.html#m--", + "../../pkg1/MethodOrder.html#m-byte:A-", + "../../pkg1/MethodOrder.html#m-double-", + "../../pkg1/MethodOrder.html#m-double-double-", + "../../pkg1/MethodOrder.html#m-double-java.lang.Double-", + "../../pkg1/MethodOrder.html#m-int-", + "../../pkg1/MethodOrder.html#m-int-int-", + "../../pkg1/MethodOrder.html#m-int-java.lang.Integer-", + "../../pkg1/MethodOrder.html#m-long-", + "../../pkg1/MethodOrder.html#m-long-long-", + "../../pkg1/MethodOrder.html#m-long-java.lang.Long-", + "../../pkg1/MethodOrder.html#m-long-java.lang.Long...-", + "../../pkg1/MethodOrder.html#m-java.lang.Double-", + "../../pkg1/MethodOrder.html#m-java.lang.Double-double-", + "../../pkg1/MethodOrder.html#m-java.lang.Double-java.lang.Double-", + "../../pkg1/MethodOrder.html#m-java.lang.Integer-", + "../../pkg1/MethodOrder.html#m-java.lang.Integer-int-", + "../../pkg1/MethodOrder.html#m-java.lang.Integer-java.lang.Integer-", + "../../pkg1/MethodOrder.html#m-java.lang.Object:A-", + "../../pkg1/MethodOrder.html#m-java.util.ArrayList-", + "../../pkg1/MethodOrder.html#m-java.util.Collection-", + "../../pkg1/MethodOrder.html#m-java.util.List-"); + + tester.checkOrder("pkg1/class-use/UsedClass.html", + "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-", + "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass-", + "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass:A-", + "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-java.lang.String-"); + + tester.checkOrder("pkg1/class-use/UsedClass.html", + "../../pkg1/A.html#A-pkg1.UsedClass-", + "../../pkg1/B.A.html#A-pkg1.UsedClass-", + "../../pkg1/B.html#B-pkg1.UsedClass-", + "../../pkg1/A.C.html#C-pkg1.UsedClass-java.lang.Object:A-", + "../../pkg1/A.C.html#C-pkg1.UsedClass-java.util.Collection-", + "../../pkg1/A.C.html#C-pkg1.UsedClass-java.util.List-"); + + tester.checkOrder("pkg1/ImplementsOrdering.html", + "
    close in interface java.lang.AutoCloseable
    ", + "
    close in interface java.nio.channels.Channel
    ", + "
    close in interface java.io.Closeable
    "); + + tester.checkOrder("pkg1/OverrideOrdering.html", + "
    iterator in interface java.util.Collection<", + "
    iterator in interface java.lang.Iterable<"); + + tester.checkOrder("allclasses-noframe.html", + "pkg1/A.html\" title=\"class in pkg1", + "pkg1/A.C.html\" title=\"class in pkg1", + "pkg1/B.html\" title=\"class in pkg1", + "pkg1/B.A.html\" title=\"class in pkg1", + "pkg1/C1.html\" title=\"class in pkg1", + "pkg1/C2.html\" title=\"class in pkg1", + "pkg1/C3.html\" title=\"class in pkg1", + "pkg1/C4.html\" title=\"class in pkg1", + "pkg1/ImplementsOrdering.html\" title=\"interface in pkg1", + "pkg1/MethodOrder.html\" title=\"class in pkg1", + "pkg1/OverrideOrdering.html\" title=\"class in pkg1", + "pkg1/UsedClass.html\" title=\"class in pkg1"); + + tester.checkOrder("allclasses-frame.html", + "pkg1/A.html\" title=\"class in pkg1", + "pkg1/A.C.html\" title=\"class in pkg1", + "pkg1/B.html\" title=\"class in pkg1", + "pkg1/B.A.html\" title=\"class in pkg1", + "pkg1/C1.html\" title=\"class in pkg1", + "pkg1/C2.html\" title=\"class in pkg1", + "pkg1/C3.html\" title=\"class in pkg1", + "pkg1/C4.html\" title=\"class in pkg1", + "pkg1/ImplementsOrdering.html\" title=\"interface in pkg1", + "pkg1/MethodOrder.html\" title=\"class in pkg1", + "pkg1/OverrideOrdering.html\" title=\"class in pkg1", + "pkg1/UsedClass.html\" title=\"class in pkg1"); + } + + void checkClassUseOrdering(String usePage) { + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#zfield"); + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#fieldInC#ITERATION#"); + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#zmethod-pkg1.UsedClass"); + checkClassUseOrdering(usePage, "pkg1/C#ITERATION#.html#methodInC#ITERATION#"); + } + + void checkClassUseOrdering(String usePage, String searchString) { + String contents = tester.readFile(usePage); + int lastidx = 0; + System.out.println("testing for " + searchString); + for (int i = 1; i < 5; i++) { + String s = searchString.replaceAll("#ITERATION#", Integer.toString(i)); + tester.checking(s); + int idx = contents.indexOf(s); + if (idx < lastidx) { + tester.failed(s + ", member ordering error, last:" + lastidx + ", got:" + idx); + } else { + tester.passed("\tlast: " + lastidx + " got:" + idx); + } + lastidx = idx; + } + } + } + + static class IndexOrderingTest { + private final JavadocTester tester; + + IndexOrderingTest(JavadocTester tester) { + this.tester = tester; + } + + enum ListOrder { + NONE, REVERSE, SHUFFLE + }; + + /* + * By default we do not shuffle the input list, in order to keep the list deterministic, + * and the test predictable. However, we can turn on the stress mode, by setting the following + * property if required. + */ + static final ListOrder STRESS_MODE = Boolean.getBoolean("TestOrder.STRESS") + ? ListOrder.SHUFFLE + : ListOrder.REVERSE; + + /* + * Controls the number of children packages, pkg0, pkg0.pkg, pkg0.pkg.pkg, ..... + * Note: having too long a depth (> 256 chars on Windows), will likely lead to + * cause problems with automated build and test systems. + */ + static final int MAX_SUBPACKAGES_DEPTH = 4; + + /* + * Controls the number of sibling packages, pkg0, pkg1, pkg2, ..... + */ + static final int MAX_PACKAGES = 4; + + static String[] contents = { + "public add ADDADD;", + "public add AddAdd;", + "public add addadd;", + "public enum add {add, ADD, addd, ADDD};", + "public enum ADD {ADD, add, addd, ADDD};", + "public void add(){}", + "public void add(double d){}", + "public void add(int i, float f){}", + "public void add(float f, int i){}", + "public void add(double d, byte b){}", + "public Double add(Double d) {return (double) 22/7;}", + "public double add(double d1, double d2) {return d1 + d2;}", + "public double add(double d1, Double d2) {return d1 + d2;}", + "public Float add(float f) {return (float) 22/7;}", + "public void add(int i){}", + "public int add(Integer i) {return 0;}" + }; + + static String expectedEnumOrdering[] = { + "Add.add.html\" title=\"enum in REPLACE_ME\"", + "Add.ADD.html\" title=\"enum in REPLACE_ME\"" + }; + + static String expectedFieldOrdering[] = { + "Add.html#addadd\"", + "add0/add/add/add/Add.html#addadd\"", + "add0/add/add/Add.html#addadd\"", + "add0/add/Add.html#addadd\"", + "add0/Add.html#addadd\"", + "add1/add/add/add/Add.html#addadd\"", + "add1/add/add/Add.html#addadd\"", + "add1/add/Add.html#addadd\"", + "add1/Add.html#addadd\"", + "add2/add/add/add/Add.html#addadd\"", + "add2/add/add/Add.html#addadd\"", + "add2/add/Add.html#addadd\"", + "add2/Add.html#addadd\"", + "add3/add/add/add/Add.html#addadd\"", + "add3/add/add/Add.html#addadd\"", + "add3/add/Add.html#addadd\"", + "add3/Add.html#addadd\"", + "Add.html#AddAdd\"", + "add0/add/add/add/Add.html#AddAdd\"", + "add0/add/add/Add.html#AddAdd\"", + "add0/add/Add.html#AddAdd\"", + "add0/Add.html#AddAdd\"", + "add1/add/add/add/Add.html#AddAdd\"", + "add1/add/add/Add.html#AddAdd\"", + "add1/add/Add.html#AddAdd\"", + "add1/Add.html#AddAdd\"", + "add2/add/add/add/Add.html#AddAdd\"", + "add2/add/add/Add.html#AddAdd\"", + "add2/add/Add.html#AddAdd\"", + "add2/Add.html#AddAdd\"", + "add3/add/add/add/Add.html#AddAdd\"", + "add3/add/add/Add.html#AddAdd\"", + "add3/add/Add.html#AddAdd\"", + "add3/Add.html#AddAdd\"", + "Add.html#ADDADD\"", + "add0/add/add/add/Add.html#ADDADD\"", + "add0/add/add/Add.html#ADDADD\"", + "add0/add/Add.html#ADDADD\"", + "add0/Add.html#ADDADD\"", + "add1/add/add/add/Add.html#ADDADD\"", + "add1/add/add/Add.html#ADDADD\"", + "add1/add/Add.html#ADDADD\"", + "add1/Add.html#ADDADD\"", + "add2/add/add/add/Add.html#ADDADD\"", + "add2/add/add/Add.html#ADDADD\"", + "add2/add/Add.html#ADDADD\"", + "add2/Add.html#ADDADD\"", + "add3/add/add/add/Add.html#ADDADD\"", + "add3/add/add/Add.html#ADDADD\"", + "add3/add/Add.html#ADDADD\"", + "add3/Add.html#ADDADD\"" + }; + + static String expectedMethodOrdering[] = { + "Add.html#add--", + "Add.html#add-double-", + "Add.html#add-double-byte-", + "Add.html#add-double-double-", + "Add.html#add-double-java.lang.Double-", + "Add.html#add-float-", + "Add.html#add-float-int-", + "Add.html#add-int-", + "Add.html#add-int-float-", + "Add.html#add-java.lang.Double-", + "Add.html#add-java.lang.Integer-" + }; + + static String expectedPackageOrdering[] = { + "\"add0/package-summary.html\">add0 - package add0", + "\"add0/add/package-summary.html\">add0.add - package add0.add", + "\"add0/add/add/package-summary.html\">add0.add.add - package add0.add.add", + "\"add0/add/add/add/package-summary.html\">add0.add.add.add - package add0.add.add.add", + "\"add1/package-summary.html\">add1 - package add1", + "\"add1/add/package-summary.html\">add1.add - package add1.add", + "\"add1/add/add/package-summary.html\">add1.add.add - package add1.add.add", + "\"add1/add/add/add/package-summary.html\">add1.add.add.add - package add1.add.add.add", + "\"add2/package-summary.html\">add2 - package add2", + "\"add2/add/package-summary.html\">add2.add - package add2.add", + "\"add2/add/add/package-summary.html\">add2.add.add - package add2.add.add", + "\"add2/add/add/add/package-summary.html\">add2.add.add.add - package add2.add.add.add", + "\"add3/package-summary.html\">add3 - package add3", + "\"add3/add/package-summary.html\">add3.add - package add3.add", + "\"add3/add/add/package-summary.html\">add3.add.add - package add3.add.add", + "\"add3/add/add/add/package-summary.html\">add3.add.add.add - package add3.add.add.add" + }; + + void run() throws IOException { + final String clsname = "Add"; + List cmdArgs = new ArrayList(); + cmdArgs.add("-d"); + cmdArgs.add("out-2"); + cmdArgs.add("-sourcepath"); + cmdArgs.add("src"); + cmdArgs.add("-package"); + System.out.println("STRESS_MODE: " + STRESS_MODE); + emitFile(null, clsname, STRESS_MODE); + for (int width = 0; width < MAX_PACKAGES; width++) { + String wpkgname = "add" + width; + String dpkgname = wpkgname; + emitFile(wpkgname, clsname, ListOrder.NONE); // list as-is + cmdArgs.add(wpkgname); + for (int depth = 1; depth < MAX_SUBPACKAGES_DEPTH; depth++) { + dpkgname = dpkgname + ".add"; + emitFile(dpkgname, clsname, STRESS_MODE); + cmdArgs.add(dpkgname); + } + } + File srcDir = new File(new File("."), "src"); + cmdArgs.add(new File(srcDir, clsname + ".java").getPath()); + tester.javadoc(cmdArgs.toArray(new String[cmdArgs.size()])); + tester.checkExit(Exit.OK); + tester.checkOrder("index-all.html", composeTestVectors()); + tester.checkOrder("add0/add/package-tree.html", + "", + ""); + tester.checkOrder("overview-tree.html", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ""); + + tester.checkOrder("overview-frame.html", + "<unnamed package>", + "add0", + "add0.add", + "add0.add.add", + "add0.add.add.add", + "add1", + "add1.add", + "add1.add.add", + "add1.add.add.add", + "add2", + "add2.add", + "add2.add.add", + "add2.add.add.add", + "add3", + "add3.add", + "add3.add.add", + "add3.add.add.add"); + } + + void emitFile(String pkgname, String clsname, ListOrder order) throws IOException { + File srcDir = new File("src"); + File outDir = pkgname == null + ? srcDir + : new File(srcDir, pkgname.replace(".", File.separator)); + File outFile = new File(outDir, clsname + ".java"); + outDir.mkdirs(); + List scratch = new ArrayList<>(Arrays.asList(contents)); + switch (order) { + case SHUFFLE: + Collections.shuffle(scratch); + break; + case REVERSE: + Collections.reverse(scratch); + break; + default: // leave list as-is + } + // insert the header + scratch.add(0, "public class " + clsname + " {"); + if (pkgname != null) { + scratch.add(0, "package " + pkgname + ";"); + } + // append the footer + scratch.add("}"); + Files.write(outFile.toPath(), scratch, CREATE, TRUNCATE_EXISTING); } - // insert the header - scratch.add(0, "public class " + clsname + " {"); - if (pkgname != null) { - scratch.add(0, "package " + pkgname + ";"); + + String[] composeTestVectors() { + List testList = new ArrayList<>(); + + testList.addAll(Arrays.asList(expectedPackageOrdering)); + for (String x : expectedEnumOrdering) { + testList.add(x.replace("REPLACE_ME", "<Unnamed>")); + for (int i = 0; i < MAX_PACKAGES; i++) { + String wpkg = "add" + i; + testList.add(wpkg + "/" + x.replace("REPLACE_ME", + wpkg)); + String dpkg = wpkg; + for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) { + dpkg = dpkg + "/" + "add"; + testList.add(dpkg + "/" + x.replace("REPLACE_ME", pathToPackage(dpkg))); + } + } + } + + testList.addAll(Arrays.asList(expectedFieldOrdering)); + + for (String x : expectedMethodOrdering) { + testList.add(x); + for (int i = 0; i < MAX_PACKAGES; i++) { + String wpkg = "add" + i; + testList.add(wpkg + "/" + x); + String dpkg = wpkg; + for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) { + dpkg = dpkg + "/" + "add"; + testList.add(dpkg + "/" + x); + } + } + } + + return testList.toArray(new String[testList.size()]); + } + + String pathToPackage(String in) { + return in.replace("/", "."); } - // append the footer - scratch.add("}"); - Files.write(outFile.toPath(), scratch, CREATE, TRUNCATE_EXISTING); } - String pathToPackage(String in) { - return in.replace("/", "."); + static class IndexTypeClusteringTest { + + private final JavadocTester tester; + + IndexTypeClusteringTest(JavadocTester tester) { + this.tester = tester; + } + + void run() { + tester.javadoc("-d", "out-3", + "-sourcepath", tester.testSrc("src-2"), + "-use", + "a", + "b", + "e", + "something"); + + tester.checkExit(Exit.OK); + + tester.checkOrder("index-all.html", + "something - package something", + "something - Class in", + "something - Enum in", + "something - Interface in", + "something - Annotation Type in", + "something - Variable in class", + "something() - Constructor", + "something() - Method in class a. - Method in class a. - Method in class something.add0 - package add0", - "\"add0/add/package-summary.html\">add0.add - package add0.add", - "\"add0/add/add/package-summary.html\">add0.add.add - package add0.add.add", - "\"add0/add/add/add/package-summary.html\">add0.add.add.add - package add0.add.add.add", - "\"add1/package-summary.html\">add1 - package add1", - "\"add1/add/package-summary.html\">add1.add - package add1.add", - "\"add1/add/add/package-summary.html\">add1.add.add - package add1.add.add", - "\"add1/add/add/add/package-summary.html\">add1.add.add.add - package add1.add.add.add", - "\"add2/package-summary.html\">add2 - package add2", - "\"add2/add/package-summary.html\">add2.add - package add2.add", - "\"add2/add/add/package-summary.html\">add2.add.add - package add2.add.add", - "\"add2/add/add/add/package-summary.html\">add2.add.add.add - package add2.add.add.add", - "\"add3/package-summary.html\">add3 - package add3", - "\"add3/add/package-summary.html\">add3.add - package add3.add", - "\"add3/add/add/package-summary.html\">add3.add.add - package add3.add.add", - "\"add3/add/add/add/package-summary.html\">add3.add.add.add - package add3.add.add.add" - }; + tester.checkOrder("pkg5/AnnoFieldTest.html", + "

    Field Detail

    ", + "
    static final int one
    ", + "
    static final int two
    ", + "
    static final int three
    ", + "
    static final int four
    "); - final String expectedMethodOrdering[] = { - "Add.html#add--", - "Add.html#add-double-", - "Add.html#add-double-byte-", - "Add.html#add-double-double-", - "Add.html#add-double-java.lang.Double-", - "Add.html#add-float-", - "Add.html#add-float-int-", - "Add.html#add-int-", - "Add.html#add-int-float-", - "Add.html#add-java.lang.Double-", - "Add.html#add-java.lang.Integer-" - }; + tester.checkOrder("pkg5/AnnoOptionalTest.html", + "

    Optional Element Summary

    ", + "four", + "one", + "three", + "two", + "

    Element Detail

    ", + "

    one

    ", + "

    two

    ", + "

    three

    ", + "

    four

    "); - final String expectedEnumOrdering[] = { - "Add.add.html\" title=\"enum in REPLACE_ME\"", - "Add.ADD.html\" title=\"enum in REPLACE_ME\"" - }; + tester.checkOrder("pkg5/AnnoRequiredTest.html", + "

    Required Element Summary

    ", + "four", + "one", + "three", + "two", + "

    Element Detail

    ", + "

    one

    ", + "

    two

    ", + "

    three

    ", + "

    four

    "); - final String expectedFieldOrdering[] = { - "Add.html#addadd\"", - "add0/add/add/add/Add.html#addadd\"", - "add0/add/add/Add.html#addadd\"", - "add0/add/Add.html#addadd\"", - "add0/Add.html#addadd\"", - "add1/add/add/add/Add.html#addadd\"", - "add1/add/add/Add.html#addadd\"", - "add1/add/Add.html#addadd\"", - "add1/Add.html#addadd\"", - "add2/add/add/add/Add.html#addadd\"", - "add2/add/add/Add.html#addadd\"", - "add2/add/Add.html#addadd\"", - "add2/Add.html#addadd\"", - "add3/add/add/add/Add.html#addadd\"", - "add3/add/add/Add.html#addadd\"", - "add3/add/Add.html#addadd\"", - "add3/Add.html#addadd\"", - "Add.html#AddAdd\"", - "add0/add/add/add/Add.html#AddAdd\"", - "add0/add/add/Add.html#AddAdd\"", - "add0/add/Add.html#AddAdd\"", - "add0/Add.html#AddAdd\"", - "add1/add/add/add/Add.html#AddAdd\"", - "add1/add/add/Add.html#AddAdd\"", - "add1/add/Add.html#AddAdd\"", - "add1/Add.html#AddAdd\"", - "add2/add/add/add/Add.html#AddAdd\"", - "add2/add/add/Add.html#AddAdd\"", - "add2/add/Add.html#AddAdd\"", - "add2/Add.html#AddAdd\"", - "add3/add/add/add/Add.html#AddAdd\"", - "add3/add/add/Add.html#AddAdd\"", - "add3/add/Add.html#AddAdd\"", - "add3/Add.html#AddAdd\"", - "Add.html#ADDADD\"", - "add0/add/add/add/Add.html#ADDADD\"", - "add0/add/add/Add.html#ADDADD\"", - "add0/add/Add.html#ADDADD\"", - "add0/Add.html#ADDADD\"", - "add1/add/add/add/Add.html#ADDADD\"", - "add1/add/add/Add.html#ADDADD\"", - "add1/add/Add.html#ADDADD\"", - "add1/Add.html#ADDADD\"", - "add2/add/add/add/Add.html#ADDADD\"", - "add2/add/add/Add.html#ADDADD\"", - "add2/add/Add.html#ADDADD\"", - "add2/Add.html#ADDADD\"", - "add3/add/add/add/Add.html#ADDADD\"", - "add3/add/add/Add.html#ADDADD\"", - "add3/add/Add.html#ADDADD\"", - "add3/Add.html#ADDADD\"" - }; + tester.checkOrder("pkg5/CtorTest.html", + "

    Constructor Summary

    ", + "Constructor Detail", + "", + "", + "", + ""); - final String expectedPackageTreeOrdering[] = { - "", - "" - }; + tester.checkOrder("pkg5/EnumTest.html", + "

    Enum Constant Summary

    ", + "
    FOUR", + "ONE", + "THREE", + "TWO", + "

    Enum Constant Detail

    ", + "

    ONE

    ", + "

    TWO

    ", + "

    THREE

    ", + "

    FOUR

    "); - final String expectedOverviewOrdering[] = { - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - }; + tester.checkOrder("pkg5/FieldTest.html", + "

    Field Summary

    ", + "
    four", + "one", + "three", + "two", + "

    Field Detail

    ", + "

    one

    ", + "

    two

    ", + "

    three

    ", + "

    four

    "); - final static String expectedOverviewFrameOrdering[] = { - "<unnamed package>", - "add0", - "add0.add", - "add0.add.add", - "add0.add.add.add", - "add1", - "add1.add", - "add1.add.add", - "add1.add.add.add", - "add2", - "add2.add", - "add2.add.add", - "add2.add.add.add", - "add3", - "add3.add", - "add3.add.add", - "add3.add.add.add" - }; + tester.checkOrder("pkg5/IntfTest.html", + "

    Method Summary

    ", + "four", + "one", + "three", + "two", + "

    Method Detail

    ", + "

    one

    ", + "

    two

    ", + "

    three

    ", + "

    four

    "); - final static String expectedImplementsOrdering[] = { - "
    close in interface java.lang.AutoCloseable
    ", - "
    close in interface java.nio.channels.Channel
    ", - "
    close in interface java.io.Closeable
    " - }; + tester.checkOrder("pkg5/MethodTest.html", + "

    Method Summary

    ", + "four", + "one", + "three", + "two", + "

    Method Detail

    ", + "

    one

    ", + "

    two

    ", + "

    three

    ", + "

    four

    "); - final static String expectedOverrideOrdering[] = { - "
    iterator in interface java.util.Collection<", - "
    iterator in interface java.lang.Iterable<" - }; + tester.checkOrder("pkg5/PropertyTest.html", + "

    Property Summary

    ", + "four", + "one", + "three", + "two", + "

    Property Detail

    ", + "

    oneProperty

    ", + "

    twoProperty

    ", + "

    threeProperty

    ", + "

    fourProperty

    "); + } + } } diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoFieldTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoFieldTest.java new file mode 100644 index 00000000000..53c0617f3ec --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoFieldTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public @interface AnnoFieldTest { + public int one = 1; + public int two = 2; + public int three = 3; + public int four = 4; +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoOptionalTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoOptionalTest.java new file mode 100644 index 00000000000..aba053a0476 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoOptionalTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public @interface AnnoOptionalTest { + int one() default 1; + int two() default 2; + int three() default 3; + int four() default 4; +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoRequiredTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoRequiredTest.java new file mode 100644 index 00000000000..f54a0e4af14 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/AnnoRequiredTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public @interface AnnoRequiredTest { + int one(); + int two(); + int three(); + int four(); +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/CtorTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/CtorTest.java new file mode 100644 index 00000000000..60bd64a49e8 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/CtorTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public class CtorTest { + public CtorTest(int one, int two, int three, int four) {} + public CtorTest(int one, int two, int three) {} + public CtorTest(int one, int two) {} + public CtorTest(int one) {} +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/EnumTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/EnumTest.java new file mode 100644 index 00000000000..ef1267f00a5 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/EnumTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public enum EnumTest { + ONE, + TWO, + THREE, + FOUR +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/FieldTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/FieldTest.java new file mode 100644 index 00000000000..66f876e0a85 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/FieldTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public class FieldTest { + public int one; + public int two; + public int three; + public int four; +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/IntfTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/IntfTest.java new file mode 100644 index 00000000000..959034ed16b --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/IntfTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public interface IntfTest { + void one(); + void two(); + void three(); + void four(); +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/MethodTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/MethodTest.java new file mode 100644 index 00000000000..9333b30c00d --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/MethodTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public class MethodTest { + public void one(){} + public void two(){} + public void three(){} + public void four(){} +} diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/PropertyTest.java b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/PropertyTest.java new file mode 100644 index 00000000000..b53752a1e1a --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/pkg5/PropertyTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg5; + +public class PropertyTest { + public int oneProperty() { return 1; } + public int twoProperty() { return 2; } + public int threeProperty() { return 3; } + public int fourProperty() { return 4; } +} diff --git a/langtools/test/jdk/javadoc/tool/modules/Modules.java b/langtools/test/jdk/javadoc/tool/modules/Modules.java index 41114ea5806..39f94b666bf 100644 --- a/langtools/test/jdk/javadoc/tool/modules/Modules.java +++ b/langtools/test/jdk/javadoc/tool/modules/Modules.java @@ -296,7 +296,7 @@ public class Modules extends ModuleTestBase { checkMembersSelected("pkg2.B.f"); } -// @Test @ignore JDK-8166379 + @Test public void testPatchModuleOption(Path base) throws Exception { Path src = base.resolve("src"); Path modulePath = base.resolve("modules"); diff --git a/langtools/test/tools/javac/modules/AnnotationProcessingWithModuleInfoInWrongPlace.java b/langtools/test/tools/javac/modules/AnnotationProcessingWithModuleInfoInWrongPlace.java new file mode 100644 index 00000000000..1a5e17842fd --- /dev/null +++ b/langtools/test/tools/javac/modules/AnnotationProcessingWithModuleInfoInWrongPlace.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8168312 + * @summary javac throws NPE if annotation processor is specified and module is declared in a file named arbitrarily + * @library /tools/lib + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @run main AnnotationProcessingWithModuleInfoInWrongPlace + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; + +import toolbox.JavacTask; +import toolbox.Task; + +public class AnnotationProcessingWithModuleInfoInWrongPlace extends ModuleTestBase { + + public static void main(String... args) throws Exception { + new AnnotationProcessingWithModuleInfoInWrongPlace().runTests(); + } + + @Test + public void testModuleInfoInWrongPlace(Path base) throws Exception { + Path moduleSrc = base.resolve("module-src"); + Path m = moduleSrc.resolve("m"); + + Path classes = base.resolve("classes"); + + Files.createDirectories(classes); + + tb.writeJavaFiles(m, "module m {}"); + + Path mi = m.resolve("module-info.java"); + Path f = m.resolve("F.java"); + + tb.moveFile(mi, f); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--module-source-path", moduleSrc.toString(), + "-processor", AP.class.getName()) + .outdir(classes) + .files(findJavaFiles(moduleSrc)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + + if (!log.contains("F.java:1:1: compiler.err.module.decl.sb.in.module-info.java")) + throw new AssertionError("Unexpected output: " + log); + } + + @SupportedAnnotationTypes("*") + public static final class AP extends AbstractProcessor { + + @Override + public boolean process(Set annot, RoundEnvironment env) { + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + } +} diff --git a/langtools/test/tools/javac/modules/PatchModulesTest.java b/langtools/test/tools/javac/modules/PatchModulesTest.java index bf481c596e4..648ba4901ac 100644 --- a/langtools/test/tools/javac/modules/PatchModulesTest.java +++ b/langtools/test/tools/javac/modules/PatchModulesTest.java @@ -91,12 +91,28 @@ public class PatchModulesTest extends ModuleTestBase { } @Test - public void testLastOneWins(Path base) throws Exception { + public void testDuplicates(Path base) throws Exception { test(asList("java.base=a", "java.compiler=b", "java.base=c"), - "{java.base=[c], java.compiler=[b]}"); + false, "--patch-module specified more than once for java.base"); + } + + @Test + public void testEmpty(Path base) throws Exception { + test(asList(""), + false, "no value for --patch-module option"); + } + + @Test + public void testInvalid(Path base) throws Exception { + test(asList("java.base/java.lang=."), + false, "bad value for --patch-module option: 'java.base/java.lang=.'"); } void test(List patches, String expect) throws Exception { + test(patches, true, expect); + } + + void test(List patches, boolean expectOK, String expect) throws Exception { JavacTool tool = (JavacTool) ToolProvider.getSystemJavaCompiler(); StringWriter sw = new StringWriter(); try (PrintWriter pw = new PrintWriter(sw)) { @@ -116,6 +132,17 @@ public class PatchModulesTest extends ModuleTestBase { Map patchMap = (Map) patchMapField.get(locations); String found = patchMap.toString(); + if (!found.equals(expect)) { + tb.out.println("Expect: " + expect); + tb.out.println("Found: " + found); + error("output not as expected"); + } + } catch (IllegalArgumentException e) { + if (expectOK) { + error("unexpected exception: " + e); + throw e; + } + String found = e.getMessage(); if (!found.equals(expect)) { tb.out.println("Expect: " + expect); tb.out.println("Found: " + found); diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.java b/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.java new file mode 100644 index 00000000000..9f8a3977305 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8166700 + * @summary Check that local classes originating in static initializer can be loaded properly. + * @modules jdk.compiler + * @build LocalTest$1Local LocalTest$2Local LocalTest$3Local LocalTest$4Local LocalTest$5Local LocalTest + * @compile LocalClassesModel.java + * @compile/process/ref=LocalClassesModel.out -processor LocalClassesModel LocalTest$1Local LocalTest$2Local LocalTest$3Local LocalTest$4Local LocalTest$5Local LocalTest + */ + +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.ElementFilter; + +@SupportedAnnotationTypes("*") +public class LocalClassesModel extends AbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement root : ElementFilter.typesIn(roundEnv.getRootElements())) { + System.out.println(processingEnv.getElementUtils().getBinaryName(root)); + for (ExecutableElement constr : ElementFilter.constructorsIn(root.getEnclosedElements())) { + System.out.print(" ("); + boolean first = true; + for (VariableElement param : constr.getParameters()) { + if (!first) { + System.out.print(", "); + } + first = false; + System.out.print(param.asType().toString()); + } + System.out.println(")"); + } + } + + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } +} \ No newline at end of file diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.out b/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.out new file mode 100644 index 00000000000..895193116f3 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.out @@ -0,0 +1,12 @@ +LocalTest$1Local + () +LocalTest$2Local + (LocalTest) +LocalTest$3Local + () +LocalTest$4Local + (LocalTest) +LocalTest$5Local + (LocalTest) +LocalTest + () diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$1Local.jcod b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$1Local.jcod new file mode 100644 index 00000000000..3ffaeecee84 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$1Local.jcod @@ -0,0 +1,77 @@ +class LocalTest$1Local { + 0xCAFEBABE; + 0; // minor version + 52; // version + [] { // Constant Pool + ; // first element is empty + Method #3 #12; // #1 + class #13; // #2 + class #16; // #3 + Utf8 ""; // #4 + Utf8 "()V"; // #5 + Utf8 "Code"; // #6 + Utf8 "LineNumberTable"; // #7 + Utf8 "SourceFile"; // #8 + Utf8 "LocalTest.java"; // #9 + Utf8 "EnclosingMethod"; // #10 + class #17; // #11 + NameAndType #4 #5; // #12 + Utf8 "LocalTest$1Local"; // #13 + Utf8 "Local"; // #14 + Utf8 "InnerClasses"; // #15 + Utf8 "java/lang/Object"; // #16 + Utf8 "LocalTest"; // #17 + } // Constant Pool + + 0x0020; // access + #2;// this_cpx + #3;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // fields + } // fields + + [] { // methods + { // Member + 0x0000; // access + #4; // name_cpx + #5; // sig_cpx + [] { // Attributes + Attr(#6) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2AB70001B1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#7) { // LineNumberTable + [] { // LineNumberTable + 0 3; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + Attr(#8) { // SourceFile + #9; + } // end SourceFile + ; + Attr(#10) { // EnclosingMethod + #11 #0; + } // end EnclosingMethod + ; + Attr(#15) { // InnerClasses + [] { // InnerClasses + #2 #0 #14 0; + } + } // end InnerClasses + } // Attributes +} // end class LocalTest$1Local diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$2Local.jcod b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$2Local.jcod new file mode 100644 index 00000000000..23808b81b1b --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$2Local.jcod @@ -0,0 +1,90 @@ +class LocalTest$2Local { + 0xCAFEBABE; + 0; // minor version + 52; // version + [] { // Constant Pool + ; // first element is empty + Field #3 #15; // #1 + Method #4 #16; // #2 + class #17; // #3 + class #20; // #4 + Utf8 "this$0"; // #5 + Utf8 "LLocalTest;"; // #6 + Utf8 ""; // #7 + Utf8 "(LLocalTest;)V"; // #8 + Utf8 "Code"; // #9 + Utf8 "LineNumberTable"; // #10 + Utf8 "SourceFile"; // #11 + Utf8 "LocalTest.java"; // #12 + Utf8 "EnclosingMethod"; // #13 + class #21; // #14 + NameAndType #5 #6; // #15 + NameAndType #7 #22; // #16 + Utf8 "LocalTest$2Local"; // #17 + Utf8 "Local"; // #18 + Utf8 "InnerClasses"; // #19 + Utf8 "java/lang/Object"; // #20 + Utf8 "LocalTest"; // #21 + Utf8 "()V"; // #22 + } // Constant Pool + + 0x0020; // access + #3;// this_cpx + #4;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // fields + { // Member + 0x1010; // access + #5; // name_cpx + #6; // sig_cpx + [] { // Attributes + } // Attributes + } // Member + } // fields + + [] { // methods + { // Member + 0x0000; // access + #7; // name_cpx + #8; // sig_cpx + [] { // Attributes + Attr(#9) { // Code + 2; // max_stack + 2; // max_locals + Bytes[]{ + 0x2A2BB500012AB700; + 0x02B1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#10) { // LineNumberTable + [] { // LineNumberTable + 0 6; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + Attr(#11) { // SourceFile + #12; + } // end SourceFile + ; + Attr(#13) { // EnclosingMethod + #14 #0; + } // end EnclosingMethod + ; + Attr(#19) { // InnerClasses + [] { // InnerClasses + #3 #0 #18 0; + } + } // end InnerClasses + } // Attributes +} // end class LocalTest$2Local diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$3Local.jcod b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$3Local.jcod new file mode 100644 index 00000000000..fd7d2681f2e --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$3Local.jcod @@ -0,0 +1,79 @@ +class LocalTest$3Local { + 0xCAFEBABE; + 0; // minor version + 52; // version + [] { // Constant Pool + ; // first element is empty + Method #3 #13; // #1 + class #14; // #2 + class #17; // #3 + Utf8 ""; // #4 + Utf8 "()V"; // #5 + Utf8 "Code"; // #6 + Utf8 "LineNumberTable"; // #7 + Utf8 "SourceFile"; // #8 + Utf8 "LocalTest.java"; // #9 + Utf8 "EnclosingMethod"; // #10 + class #18; // #11 + NameAndType #19 #5; // #12 + NameAndType #4 #5; // #13 + Utf8 "LocalTest$3Local"; // #14 + Utf8 "Local"; // #15 + Utf8 "InnerClasses"; // #16 + Utf8 "java/lang/Object"; // #17 + Utf8 "LocalTest"; // #18 + Utf8 "test1"; // #19 + } // Constant Pool + + 0x0020; // access + #2;// this_cpx + #3;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // fields + } // fields + + [] { // methods + { // Member + 0x0000; // access + #4; // name_cpx + #5; // sig_cpx + [] { // Attributes + Attr(#6) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2AB70001B1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#7) { // LineNumberTable + [] { // LineNumberTable + 0 9; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + Attr(#8) { // SourceFile + #9; + } // end SourceFile + ; + Attr(#10) { // EnclosingMethod + #11 #12; + } // end EnclosingMethod + ; + Attr(#16) { // InnerClasses + [] { // InnerClasses + #2 #0 #15 0; + } + } // end InnerClasses + } // Attributes +} // end class LocalTest$3Local diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$4Local.jcod b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$4Local.jcod new file mode 100644 index 00000000000..737dcb43c82 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$4Local.jcod @@ -0,0 +1,92 @@ +class LocalTest$4Local { + 0xCAFEBABE; + 0; // minor version + 52; // version + [] { // Constant Pool + ; // first element is empty + Field #3 #16; // #1 + Method #4 #17; // #2 + class #18; // #3 + class #21; // #4 + Utf8 "this$0"; // #5 + Utf8 "LLocalTest;"; // #6 + Utf8 ""; // #7 + Utf8 "(LLocalTest;)V"; // #8 + Utf8 "Code"; // #9 + Utf8 "LineNumberTable"; // #10 + Utf8 "SourceFile"; // #11 + Utf8 "LocalTest.java"; // #12 + Utf8 "EnclosingMethod"; // #13 + class #22; // #14 + NameAndType #23 #24; // #15 + NameAndType #5 #6; // #16 + NameAndType #7 #24; // #17 + Utf8 "LocalTest$4Local"; // #18 + Utf8 "Local"; // #19 + Utf8 "InnerClasses"; // #20 + Utf8 "java/lang/Object"; // #21 + Utf8 "LocalTest"; // #22 + Utf8 "test2"; // #23 + Utf8 "()V"; // #24 + } // Constant Pool + + 0x0020; // access + #3;// this_cpx + #4;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // fields + { // Member + 0x1010; // access + #5; // name_cpx + #6; // sig_cpx + [] { // Attributes + } // Attributes + } // Member + } // fields + + [] { // methods + { // Member + 0x0000; // access + #7; // name_cpx + #8; // sig_cpx + [] { // Attributes + Attr(#9) { // Code + 2; // max_stack + 2; // max_locals + Bytes[]{ + 0x2A2BB500012AB700; + 0x02B1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#10) { // LineNumberTable + [] { // LineNumberTable + 0 12; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + Attr(#11) { // SourceFile + #12; + } // end SourceFile + ; + Attr(#13) { // EnclosingMethod + #14 #15; + } // end EnclosingMethod + ; + Attr(#20) { // InnerClasses + [] { // InnerClasses + #3 #0 #19 0; + } + } // end InnerClasses + } // Attributes +} // end class LocalTest$4Local diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$5Local.jcod b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$5Local.jcod new file mode 100644 index 00000000000..f377dbec956 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest$5Local.jcod @@ -0,0 +1,90 @@ +class LocalTest$5Local { + 0xCAFEBABE; + 0; // minor version + 52; // version + [] { // Constant Pool + ; // first element is empty + Field #3 #16; // #1 + Method #4 #15; // #2 + class #17; // #3 + class #20; // #4 + Utf8 "this$0"; // #5 + Utf8 "LLocalTest;"; // #6 + Utf8 ""; // #7 + Utf8 "(LLocalTest;)V"; // #8 + Utf8 "Code"; // #9 + Utf8 "LineNumberTable"; // #10 + Utf8 "SourceFile"; // #11 + Utf8 "LocalTest.java"; // #12 + Utf8 "EnclosingMethod"; // #13 + class #21; // #14 + NameAndType #7 #22; // #15 + NameAndType #5 #6; // #16 + Utf8 "LocalTest$5Local"; // #17 + Utf8 "Local"; // #18 + Utf8 "InnerClasses"; // #19 + Utf8 "java/lang/Object"; // #20 + Utf8 "LocalTest"; // #21 + Utf8 "()V"; // #22 + } // Constant Pool + + 0x0020; // access + #3;// this_cpx + #4;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // fields + { // Member + 0x1010; // access + #5; // name_cpx + #6; // sig_cpx + [] { // Attributes + } // Attributes + } // Member + } // fields + + [] { // methods + { // Member + 0x0000; // access + #7; // name_cpx + #8; // sig_cpx + [] { // Attributes + Attr(#9) { // Code + 2; // max_stack + 2; // max_locals + Bytes[]{ + 0x2A2BB500012AB700; + 0x02B1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#10) { // LineNumberTable + [] { // LineNumberTable + 0 15; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + Attr(#11) { // SourceFile + #12; + } // end SourceFile + ; + Attr(#13) { // EnclosingMethod + #14 #15; + } // end EnclosingMethod + ; + Attr(#19) { // InnerClasses + [] { // InnerClasses + #3 #0 #18 0; + } + } // end InnerClasses + } // Attributes +} // end class LocalTest$5Local diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest.jcod b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest.jcod new file mode 100644 index 00000000000..7bde5b0329b --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest.jcod @@ -0,0 +1,160 @@ +class LocalTest { + 0xCAFEBABE; + 0; // minor version + 52; // version + [] { // Constant Pool + ; // first element is empty + Method #3 #20; // #1 + class #21; // #2 + class #22; // #3 + class #23; // #4 + Utf8 "Local"; // #5 + Utf8 "InnerClasses"; // #6 + class #24; // #7 + class #25; // #8 + class #26; // #9 + class #27; // #10 + Utf8 "test1"; // #11 + Utf8 "()V"; // #12 + Utf8 "Code"; // #13 + Utf8 "LineNumberTable"; // #14 + Utf8 "test2"; // #15 + Utf8 ""; // #16 + Utf8 ""; // #17 + Utf8 "SourceFile"; // #18 + Utf8 "LocalTest.java"; // #19 + NameAndType #16 #12; // #20 + Utf8 "LocalTest"; // #21 + Utf8 "java/lang/Object"; // #22 + Utf8 "LocalTest$5Local"; // #23 + Utf8 "LocalTest$4Local"; // #24 + Utf8 "LocalTest$3Local"; // #25 + Utf8 "LocalTest$2Local"; // #26 + Utf8 "LocalTest$1Local"; // #27 + } // Constant Pool + + 0x0021; // access + #2;// this_cpx + #3;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // fields + } // fields + + [] { // methods + { // Member + 0x0008; // access + #11; // name_cpx + #12; // sig_cpx + [] { // Attributes + Attr(#13) { // Code + 0; // max_stack + 0; // max_locals + Bytes[]{ + 0xB1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#14) { // LineNumberTable + [] { // LineNumberTable + 0 10; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member + 0x0000; // access + #15; // name_cpx + #12; // sig_cpx + [] { // Attributes + Attr(#13) { // Code + 0; // max_stack + 1; // max_locals + Bytes[]{ + 0xB1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#14) { // LineNumberTable + [] { // LineNumberTable + 0 13; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member + 0x0000; // access + #16; // name_cpx + #12; // sig_cpx + [] { // Attributes + Attr(#13) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2AB70001B1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#14) { // LineNumberTable + [] { // LineNumberTable + 0 14; + 4 16; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member + 0x0008; // access + #17; // name_cpx + #12; // sig_cpx + [] { // Attributes + Attr(#13) { // Code + 0; // max_stack + 0; // max_locals + Bytes[]{ + 0xB1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#14) { // LineNumberTable + [] { // LineNumberTable + 0 4; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + Attr(#18) { // SourceFile + #19; + } // end SourceFile + ; + Attr(#6) { // InnerClasses + [] { // InnerClasses + #4 #0 #5 0; + #7 #0 #5 0; + #8 #0 #5 0; + #9 #0 #5 0; + #10 #0 #5 0; + } + } // end InnerClasses + } // Attributes +} // end class LocalTest diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest.orign b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest.orign new file mode 100644 index 00000000000..7f56f2e4e68 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalTest.orign @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/**The jcod files are generated from this file, compiled by JDK 8 javac. + */ +public class LocalTest { + static { + class Local { } + } + { + class Local { } + } + static void test1() { + class Local { } + } + void test2() { + class Local { } + } + LocalTest() { + class Local { } + } +} + diff --git a/langtools/test/tools/jdeps/DotFileTest.java b/langtools/test/tools/jdeps/DotFileTest.java index 0dd4296776c..944d3a3694d 100644 --- a/langtools/test/tools/jdeps/DotFileTest.java +++ b/langtools/test/tools/jdeps/DotFileTest.java @@ -136,8 +136,6 @@ public class DotFileTest { // with -P option List argsWithDashP = new ArrayList<>(); - argsWithDashP.add("-dotoutput"); - argsWithDashP.add(dotoutput.toString()); argsWithDashP.add("-P"); argsWithDashP.addAll(args); @@ -162,8 +160,6 @@ public class DotFileTest { // with -P option List argsWithDashP = new ArrayList<>(); - argsWithDashP.add("-dotoutput"); - argsWithDashP.add(dotoutput.toString()); argsWithDashP.add("-P"); argsWithDashP.addAll(args); diff --git a/langtools/test/tools/jdeps/Options.java b/langtools/test/tools/jdeps/Options.java new file mode 100644 index 00000000000..40da51047c8 --- /dev/null +++ b/langtools/test/tools/jdeps/Options.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8168386 + * @summary Test option validation + * @modules jdk.jdeps + * @library lib + * @build JdepsRunner + * @run testng Options + */ + + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +public class Options { + private static final String TEST_CLASSES = System.getProperty("test.classes"); + + @DataProvider(name = "errors") + public Object[][] errors() { + return new Object[][]{ + { + new String[] { "-summary", "-v", TEST_CLASSES }, + "-v, -verbose cannot be used with -s, -summary option" + }, + { + new String[] { "-jdkinternal", "-summary", TEST_CLASSES }, + "-summary or -verbose cannot be used with -jdkinternals option" + }, + { + new String[] { "-jdkinternal", "-p", "java.lang", TEST_CLASSES }, + "--package, --regex, --require cannot be used with -jdkinternals option" + }, + { + new String[] { "--inverse", TEST_CLASSES }, + "--package (-p), --regex (-e), --require option must be specified" + }, + { + new String[] { "--inverse", "-R", TEST_CLASSES }, + "-R cannot be used with --inverse option" + }, + { + new String[] { "--generate-module-info", "dots", "-cp", TEST_CLASSES }, + "-classpath cannot be used with --generate-module-info option" + }, + { + new String[] { "--list-deps", "-summary", TEST_CLASSES }, + "--list-deps and --list-reduced-deps options are specified" + }, + { + new String[] { "--list-deps", "--list-reduced-deps", TEST_CLASSES }, + "--list-deps and --list-reduced-deps options are specified" + }, + }; + } + + @Test(dataProvider = "errors") + public void test(String[] options, String expected) { + jdepsError(options).outputContains(expected); + } + + + public static JdepsRunner jdepsError(String... args) { + JdepsRunner jdeps = new JdepsRunner(args); + assertTrue(jdeps.run(true) != 0); + return jdeps; + } +} diff --git a/langtools/test/tools/jdeps/lib/JdepsRunner.java b/langtools/test/tools/jdeps/lib/JdepsRunner.java index 5d93f2fbd5a..1161558beaa 100644 --- a/langtools/test/tools/jdeps/lib/JdepsRunner.java +++ b/langtools/test/tools/jdeps/lib/JdepsRunner.java @@ -75,7 +75,7 @@ public class JdepsRunner { } public boolean outputContains(String s) { - return stdout.toString().contains(s); + return stdout.toString().contains(s) || stderr.toString().contains(s); } public void printStdout(PrintStream stream) { diff --git a/langtools/test/tools/jdeps/listdeps/ListModuleDeps.java b/langtools/test/tools/jdeps/listdeps/ListModuleDeps.java index 1456fed1e19..9327565881a 100644 --- a/langtools/test/tools/jdeps/listdeps/ListModuleDeps.java +++ b/langtools/test/tools/jdeps/listdeps/ListModuleDeps.java @@ -24,7 +24,7 @@ /* * @test * @bug 8167057 - * @summary Tests split packages + * @summary Tests --list-deps and --list-reduced-deps options * @modules java.logging * java.xml * jdk.compiler @@ -53,6 +53,8 @@ public class ListModuleDeps { private static final Path CLASSES_DIR = Paths.get("classes"); private static final Path LIB_DIR = Paths.get("lib"); + private static final Path HI_CLASS = + CLASSES_DIR.resolve("hi").resolve("Hi.class"); private static final Path FOO_CLASS = CLASSES_DIR.resolve("z").resolve("Foo.class"); private static final Path BAR_CLASS = @@ -68,6 +70,9 @@ public class ListModuleDeps { // compile library assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "lib"), LIB_DIR)); + // simple program depends only on java.base + assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "hi"), CLASSES_DIR)); + // compile classes in unnamed module assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "z"), CLASSES_DIR, @@ -117,6 +122,11 @@ public class ListModuleDeps { } }, + { HI_CLASS, new String[] { + "java.base" + } + }, + { FOO_CLASS, new String[] { "java.base", "java.logging", @@ -155,9 +165,12 @@ public class ListModuleDeps { } }, + { HI_CLASS, new String[] { + "java.base" + } + }, { FOO_CLASS, new String[] { - "java.base", "java.sql", "unnamed module: lib" } diff --git a/langtools/test/tools/jdeps/listdeps/src/hi/Hi.java b/langtools/test/tools/jdeps/listdeps/src/hi/Hi.java new file mode 100644 index 00000000000..248ae724365 --- /dev/null +++ b/langtools/test/tools/jdeps/listdeps/src/hi/Hi.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hi; + +public class Hi { +} diff --git a/nashorn/.hgtags b/nashorn/.hgtags index edcfefd25c1..fc07f2de0a9 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -377,3 +377,4 @@ e3b11296395b39bfeb3364f26c2ef77fa652e300 jdk-9+139 a46b7d3867957a868a6cc8ee66c05079b883733a jdk-9+141 d3f5d7311a1aec3152b17d75046d5d298245a0b4 jdk-9+142 b4e57ead3fae4939b70dd345d1f6744a1dedfa21 jdk-9+143 +a7f21ee6ed30695a6de14e74035d2857a754f62b jdk-9+144 diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java index 974f56c7ccc..041ab612c34 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java @@ -384,7 +384,7 @@ final class IRTranslator extends SimpleNodeVisitor { final List catchTrees = new ArrayList<>(catchNodes.size()); for (final CatchNode catchNode : catchNodes) { catchTrees.add(new CatchTreeImpl(catchNode, - translateIdent(catchNode.getException()), + translateExpr(catchNode.getException()), (BlockTree) translateBlock(catchNode.getBody()), translateExpr(catchNode.getExceptionCondition()))); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java index fdc828b50b1..3bb44b5aa13 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java @@ -462,7 +462,7 @@ final class AssignSymbols extends SimpleNodeVisitor implements Loggable { @Override public boolean enterCatchNode(final CatchNode catchNode) { - final IdentNode exception = catchNode.getException(); + final IdentNode exception = catchNode.getExceptionIdentifier(); final Block block = lc.getCurrentBlock(); start(catchNode); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java index f04f8959339..c4053bcf1e6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -3255,7 +3255,7 @@ final class CodeGenerator extends NodeOperatorVisitor origins = new LinkedList<>(); private Map types = Collections.emptyMap(); - void addOrigin(final JoinPredecessor originNode, final Map originTypes) { + void addOrigin(final JoinPredecessor originNode, final Map originTypes, final LocalVariableTypesCalculator calc) { origins.add(new JumpOrigin(originNode, originTypes)); - this.types = getUnionTypes(this.types, originTypes); + this.types = calc.getUnionTypes(this.types, originTypes); } } private enum LvarType { @@ -185,12 +186,15 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { } @SuppressWarnings("unchecked") - private static IdentityHashMap cloneMap(final Map map) { - return (IdentityHashMap)((IdentityHashMap)map).clone(); + private static HashMap cloneMap(final Map map) { + return (HashMap)((HashMap)map).clone(); } private LocalVariableConversion createConversion(final Symbol symbol, final LvarType branchLvarType, final Map joinLvarTypes, final LocalVariableConversion next) { + if (invalidatedSymbols.contains(symbol)) { + return next; + } final LvarType targetType = joinLvarTypes.get(symbol); assert targetType != null; if(targetType == branchLvarType) { @@ -208,7 +212,7 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { return new LocalVariableConversion(symbol, branchLvarType.type, targetType.type, next); } - private static Map getUnionTypes(final Map types1, final Map types2) { + private Map getUnionTypes(final Map types1, final Map types2) { if(types1 == types2 || types1.isEmpty()) { return types2; } else if(types2.isEmpty()) { @@ -261,6 +265,11 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { final LvarType type2 = types2.get(symbol); union.put(symbol, widestLvarType(type1, type2)); } + // If the two sets of symbols differ, there's a good chance that some of + // symbols only appearing in one of the sets are lexically invalidated, + // so we remove them from further consideration. + // This is not strictly necessary, just a working set size optimization. + union.keySet().removeAll(invalidatedSymbols); return union; } @@ -359,8 +368,6 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { if(t1.ordinal() < LvarType.INT.ordinal() || t2.ordinal() < LvarType.INT.ordinal()) { return LvarType.OBJECT; } - // NOTE: we allow "widening" of long to double even though it can lose precision. ECMAScript doesn't have an - // Int64 type anyway, so this loss of precision is actually more conformant to the specification... return LvarType.values()[Math.max(t1.ordinal(), t2.ordinal())]; } private final Compiler compiler; @@ -368,7 +375,10 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { // Local variable type mapping at the currently evaluated point. No map instance is ever modified; setLvarType() always // allocates a new map. Immutability of maps allows for cheap snapshots by just keeping the reference to the current // value. - private Map localVariableTypes = new IdentityHashMap<>(); + private Map localVariableTypes = Collections.emptyMap(); + // Set of symbols whose lexical scope has already ended. + private final Set invalidatedSymbols = new HashSet<>(); + // Stack for evaluated expression types. private final Deque typeStack = new ArrayDeque<>(); @@ -464,9 +474,19 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { @Override public boolean enterBlock(final Block block) { + boolean cloned = false; for(final Symbol symbol: block.getSymbols()) { - if(symbol.isBytecodeLocal() && getLocalVariableTypeOrNull(symbol) == null) { - setType(symbol, LvarType.UNDEFINED); + if(symbol.isBytecodeLocal()) { + if (getLocalVariableTypeOrNull(symbol) == null) { + if (!cloned) { + cloneOrNewLocalVariableTypes(); + cloned = true; + } + localVariableTypes.put(symbol, LvarType.UNDEFINED); + } + // In case we're repeating analysis of a lexical scope (e.g. it's in a loop), + // make sure all symbols lexically scoped by the block become valid again. + invalidatedSymbols.remove(symbol); } } return true; @@ -1033,7 +1053,7 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { joinOnLabel(catchLabel); for(final CatchNode catchNode: tryNode.getCatches()) { - final IdentNode exception = catchNode.getException(); + final IdentNode exception = catchNode.getExceptionIdentifier(); onAssignment(exception, LvarType.OBJECT); final Expression condition = catchNode.getExceptionCondition(); if(condition != null) { @@ -1046,15 +1066,11 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { // throw an exception. reachable = true; catchBody.accept(this); - final Symbol exceptionSymbol = exception.getSymbol(); if(reachable) { - localVariableTypes = cloneMap(localVariableTypes); - localVariableTypes.remove(exceptionSymbol); jumpToLabel(catchBody, endLabel); canExit = true; } - localVariableTypes = cloneMap(afterConditionTypes); - localVariableTypes.remove(exceptionSymbol); + localVariableTypes = afterConditionTypes; } // NOTE: if we had one or more conditional catch blocks with no unconditional catch block following them, then // there will be an unconditional rethrow, so the join point can never be reached from the last @@ -1204,7 +1220,7 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { } private void jumpToLabel(final JoinPredecessor jumpOrigin, final Label label, final Map types) { - getOrCreateJumpTarget(label).addOrigin(jumpOrigin, types); + getOrCreateJumpTarget(label).addOrigin(jumpOrigin, types, this); } @Override @@ -1226,16 +1242,18 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { boolean cloned = false; for(final Symbol symbol: block.getSymbols()) { - // Undefine the symbol outside the block - if(localVariableTypes.containsKey(symbol)) { - if(!cloned) { - localVariableTypes = cloneMap(localVariableTypes); - cloned = true; - } - localVariableTypes.remove(symbol); - } - if(symbol.hasSlot()) { + // Invalidate the symbol when its defining block ends + if (symbol.isBytecodeLocal()) { + if(localVariableTypes.containsKey(symbol)) { + if(!cloned) { + localVariableTypes = cloneMap(localVariableTypes); + cloned = true; + } + } + invalidateSymbol(symbol); + } + final SymbolConversions conversions = symbolConversions.get(symbol); if(conversions != null) { // Potentially make some currently dead types live if they're needed as a source of a type @@ -1605,10 +1623,19 @@ final class LocalVariableTypesCalculator extends SimpleNodeVisitor { } assert symbol.hasSlot(); assert !symbol.isGlobal(); - localVariableTypes = localVariableTypes.isEmpty() ? new IdentityHashMap() : cloneMap(localVariableTypes); + cloneOrNewLocalVariableTypes(); localVariableTypes.put(symbol, type); } + private void cloneOrNewLocalVariableTypes() { + localVariableTypes = localVariableTypes.isEmpty() ? new HashMap() : cloneMap(localVariableTypes); + } + + private void invalidateSymbol(final Symbol symbol) { + localVariableTypes.remove(symbol); + invalidatedSymbols.add(symbol); + } + /** * Set a flag in the symbol marking it as needing to be able to store a value of a particular type. Every symbol for * a local variable will be assigned between 1 and 6 local variable slots for storing all types it is known to need diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java index 81a05397c45..634b537f199 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java @@ -177,6 +177,15 @@ final class Lower extends NodeOperatorVisitor implements Lo return checkEval(callNode.setFunction(markerFunction(callNode.getFunction()))); } + @Override + public boolean enterCatchNode(final CatchNode catchNode) { + Expression exception = catchNode.getException(); + if ((exception != null) && !(exception instanceof IdentNode)) { + throwNotImplementedYet("es6.destructuring", exception); + } + return true; + } + @Override public Node leaveCatchNode(final CatchNode catchNode) { return addStatement(catchNode); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CatchNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CatchNode.java index 80ca3a509c9..9431f3b3acb 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CatchNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CatchNode.java @@ -35,8 +35,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor; public final class CatchNode extends Statement { private static final long serialVersionUID = 1L; - /** Exception identifier. */ - private final IdentNode exception; + /** Exception binding identifier or binding pattern. */ + private final Expression exception; /** Exception condition. */ private final Expression exceptionCondition; @@ -52,21 +52,27 @@ public final class CatchNode extends Statement { * @param lineNumber lineNumber * @param token token * @param finish finish - * @param exception variable name of exception + * @param exception variable name or pattern of exception * @param exceptionCondition exception condition * @param body catch body * @param isSyntheticRethrow true if this node is a synthetically generated rethrow node. */ - public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, + public CatchNode(final int lineNumber, final long token, final int finish, final Expression exception, final Expression exceptionCondition, final Block body, final boolean isSyntheticRethrow) { super(lineNumber, token, finish); - this.exception = exception == null ? null : exception.setIsInitializedHere(); + if (exception instanceof IdentNode) { + this.exception = ((IdentNode) exception).setIsInitializedHere(); + } else if ((exception instanceof LiteralNode.ArrayLiteralNode) || (exception instanceof ObjectNode)) { + this.exception = exception; + } else { + throw new IllegalArgumentException("invalid catch parameter"); + } this.exceptionCondition = exceptionCondition; - this.body = body; + this.body = body; this.isSyntheticRethrow = isSyntheticRethrow; } - private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition, + private CatchNode(final CatchNode catchNode, final Expression exception, final Expression exceptionCondition, final Block body, final boolean isSyntheticRethrow) { super(catchNode); this.exception = exception; @@ -83,11 +89,10 @@ public final class CatchNode extends Statement { public Node accept(final NodeVisitor visitor) { if (visitor.enterCatchNode(this)) { return visitor.leaveCatchNode( - setException((IdentNode)exception.accept(visitor)). - setExceptionCondition(exceptionCondition == null ? null : (Expression)exceptionCondition.accept(visitor)). - setBody((Block)body.accept(visitor))); + setException((Expression) exception.accept(visitor)). + setExceptionCondition(exceptionCondition == null ? null : (Expression) exceptionCondition.accept(visitor)). + setBody((Block) body.accept(visitor))); } - return this; } @@ -109,13 +114,24 @@ public final class CatchNode extends Statement { } /** - * Get the identifier representing the exception thrown - * @return the exception identifier + * Get the binding pattern representing the exception thrown + * + * @return the exception binding pattern */ - public IdentNode getException() { + public Expression getException() { return exception; } + /** + * Get the identifier representing the exception thrown + * + * @return the exception identifier + * @throws ClassCastException if exception set is not binding identifier + */ + public IdentNode getExceptionIdentifier() { + return (IdentNode) exception; + } + /** * Get the exception condition for this catch block * @return the exception condition @@ -146,13 +162,19 @@ public final class CatchNode extends Statement { /** * Resets the exception of a catch block - * @param exception new exception + * + * @param exception new exception which can be binding identifier or binding + * pattern * @return new catch node if changed, same otherwise */ - public CatchNode setException(final IdentNode exception) { + public CatchNode setException(final Expression exception) { if (this.exception == exception) { return this; } + /*check if exception is legitimate*/ + if (!((exception instanceof IdentNode) || (exception instanceof LiteralNode.ArrayLiteralNode) || (exception instanceof ObjectNode))) { + throw new IllegalArgumentException("invalid catch parameter"); + } return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java index bb8d61a5907..fccad1532aa 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java @@ -397,7 +397,7 @@ public final class PrintVisitor extends SimpleNodeVisitor { @Override public boolean enterVarNode(final VarNode varNode) { - sb.append("var "); + sb.append(varNode.isConst() ? "const " : varNode.isLet() ? "let " : "var "); varNode.getName().toString(sb, printTypes); printLocalVariableConversion(varNode.getName()); final Node init = varNode.getInit(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java index 3b43249cdc7..24518223439 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java @@ -102,19 +102,9 @@ public class Lexer extends Scanner { private int templateExpressionOpenBraces; - private static final String SPACETAB = " \t"; // ASCII space and tab - private static final String LFCR = "\n\r"; // line feed and carriage return (ctrl-m) - - private static final String JAVASCRIPT_WHITESPACE_EOL = - LFCR + + private static final String JAVASCRIPT_OTHER_WHITESPACE = "\u2028" + // line separator - "\u2029" // paragraph separator - ; - private static final String JAVASCRIPT_WHITESPACE = - SPACETAB + - JAVASCRIPT_WHITESPACE_EOL + - "\u000b" + // tabulation line - "\u000c" + // ff (ctrl-l) + "\u2029" + // paragraph separator "\u00a0" + // Latin-1 space "\u1680" + // Ogham space mark "\u180e" + // separator, Mongolian vowel @@ -384,7 +374,13 @@ public class Lexer extends Scanner { * @return true if valid JavaScript whitespace */ public static boolean isJSWhitespace(final char ch) { - return JAVASCRIPT_WHITESPACE.indexOf(ch) != -1; + return ch == ' ' // space + || ch >= '\t' && ch <= '\r' // 0x09..0x0d: tab, line feed, tabulation line, ff, carriage return + || ch >= 160 && isOtherJSWhitespace(ch); + } + + private static boolean isOtherJSWhitespace(final char ch) { + return JAVASCRIPT_OTHER_WHITESPACE.indexOf(ch) != -1; } /** @@ -393,7 +389,10 @@ public class Lexer extends Scanner { * @return true if valid JavaScript end of line */ public static boolean isJSEOL(final char ch) { - return JAVASCRIPT_WHITESPACE_EOL.indexOf(ch) != -1; + return ch == '\n' // line feed + || ch == '\r' // carriage return (ctrl-m) + || ch == '\u2028' // line separator + || ch == '\u2029'; // paragraph separator } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java index c609a0d18c7..fb4fd433b42 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java @@ -2619,13 +2619,23 @@ public class Parser extends AbstractParser implements Loggable { next(); expect(LPAREN); - // FIXME: ES6 catch parameter can be a BindingIdentifier or a BindingPattern - // We need to generalize this here! + // ES6 catch parameter can be a BindingIdentifier or a BindingPattern // http://www.ecma-international.org/ecma-262/6.0/ - final IdentNode exception = getIdent(); + final String contextString = "catch argument"; + final Expression exception = bindingIdentifierOrPattern(contextString); + final boolean isDestructuring = !(exception instanceof IdentNode); + if (isDestructuring) { + verifyDestructuringBindingPattern(exception, new Consumer() { + @Override + public void accept(final IdentNode identNode) { + verifyIdent(identNode, contextString); + } + }); + } else { + // ECMA 12.4.1 strict mode restrictions + verifyStrictIdent((IdentNode) exception, "catch argument"); + } - // ECMA 12.4.1 strict mode restrictions - verifyStrictIdent(exception, "catch argument"); // Nashorn extension: catch clause can have optional // condition. So, a single try can have more than one diff --git a/nashorn/test/script/basic/es6/JDK-8168373.js b/nashorn/test/script/basic/es6/JDK-8168373.js new file mode 100644 index 00000000000..af26e73533e --- /dev/null +++ b/nashorn/test/script/basic/es6/JDK-8168373.js @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8168373: don't emit conversions for symbols outside their lexical scope + * + * @test + * @run + * @option --language=es6 + */ + +function p() { return false } // "predicate" +function r(x) { return x } // "read" + +(function() { + try { // Try creates control flow edges from assignments into catch blocks. + // Lexically scoped, never read int variable (undefined at catch block) but still with a cf edge into catch block. + // Since it's never read, it's not written either (Nashorn optimizes some dead writes). + let x = 0; + if (p()) { throw {}; } // We need `p()` so this block doesn't get optimized away, for possibility of a `throw` + x = 0.0; // change the type of x to double + r(x); // read x otherwise it's optimized away + } catch (e) {} // under the bug, "throw" will try to widen unwritten int x to double for here and cause a verifier error +})() diff --git a/nashorn/test/script/basic/es6/destructuring.js b/nashorn/test/script/basic/es6/destructuring.js index a7f7a59de04..d2b2a1bd31e 100644 --- a/nashorn/test/script/basic/es6/destructuring.js +++ b/nashorn/test/script/basic/es6/destructuring.js @@ -62,4 +62,11 @@ check("(function({ x }) { return x; })()"); check("(function([x]) { return x; })()"); check("for (var [[x, y, z] = [4, 5, 6]] = [7, 8, 9]; iterCount < 1; ) ;"); check("for ([ arrow = () => {} ] of [[]]) ;"); +check("try { throw null;} catch({}) { }"); +check("try { throw {} } catch ({}) { }"); +check("try { throw [] } catch ([,]) { }"); +check("try { throw { w: [7, undefined, ] }} catch ({ w: [x, y, z] = [4, 5, 6] }) { }"); +check("try { throw { a: 2, b: 3} } catch ({a, b}) { }"); +check("try { throw [null] } catch ([[x]]) { }"); +check("try { throw { w: undefined } } catch ({ w: { x, y, z } = { x: 4, y: 5, z: 6 } }) { }"); diff --git a/nashorn/test/script/basic/es6/destructuring.js.EXPECTED b/nashorn/test/script/basic/es6/destructuring.js.EXPECTED index 65e2eda1dc9..54ecd96a3fa 100644 --- a/nashorn/test/script/basic/es6/destructuring.js.EXPECTED +++ b/nashorn/test/script/basic/es6/destructuring.js.EXPECTED @@ -70,3 +70,24 @@ for (var [[x, y, z] = [4, 5, 6]] = [7, 8, 9]; iterCount < 1; ) ; java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented for ([ arrow = () => {} ] of [[]]) ; ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:25 ES6 destructuring is not yet implemented +try { throw null;} catch({}) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:24 ES6 destructuring is not yet implemented +try { throw {} } catch ({}) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:24 ES6 destructuring is not yet implemented +try { throw [] } catch ([,]) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:44 ES6 destructuring is not yet implemented +try { throw { w: [7, undefined, ] }} catch ({ w: [x, y, z] = [4, 5, 6] }) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:35 ES6 destructuring is not yet implemented +try { throw { a: 2, b: 3} } catch ({a, b}) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:28 ES6 destructuring is not yet implemented +try { throw [null] } catch ([[x]]) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:38 ES6 destructuring is not yet implemented +try { throw { w: undefined } } catch ({ w: { x, y, z } = { x: 4, y: 5, z: 6 } }) { } + ^ diff --git a/nashorn/test/script/nosecurity/treeapi/destructuring_catch.js b/nashorn/test/script/nosecurity/treeapi/destructuring_catch.js new file mode 100644 index 00000000000..ff399fee444 --- /dev/null +++ b/nashorn/test/script/nosecurity/treeapi/destructuring_catch.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Tests to check representation of ES6 catch parameter as binding pattern. + * + * @test + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + +var code = <