diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 75fcb5f4de4..cdd21c19b18 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -362,3 +362,4 @@ f900d5afd9c83a0df8f36161c27c5e4c86a66f4c jdk-9+111 e882bcdbdac436523f3d5681611d3118a3804ea7 jdk-9+117 047f95de8f918d8ff5e8cd2636a2abb5c3c8adb8 jdk-9+118 3463a3f14f0f0e8a68f29ac6405454f2fa2f598a jdk-9+119 +647e0142a5a52749db572b5e6638d561def6479e jdk-9+120 diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 0079a944dac..bb5491ba0b4 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -229,6 +229,7 @@ LIB_SETUP_LIBRARIES JDKOPT_DETECT_INTREE_EC JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER +JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST ############################################################################### # diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index ef4a2674e9f..e4c2dab06f9 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -650,6 +650,7 @@ TEST_JOBS JOBS MEMORY_SIZE NUM_CORES +ENABLE_GENERATE_CLASSLIST BUILD_FAILURE_HANDLER ENABLE_INTREE_EC STLPORT_LIB @@ -1226,6 +1227,7 @@ with_dxsdk with_dxsdk_lib with_dxsdk_include enable_jtreg_failure_handler +enable_generate_classlist with_num_cores with_memory_size with_jobs @@ -2005,6 +2007,10 @@ Optional Features: Default is auto, where the failure handler is built if all dependencies are present and otherwise just disabled. + --disable-generate-classlist + forces enabling or disabling of the generation of a + CDS classlist at build time. Default is to generate + it when either the server or client JVMs are built. --enable-sjavac use sjavac to do fast incremental compiles [disabled] --disable-javac-server disable javac server [enabled] @@ -4391,6 +4397,12 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # +################################################################################ +# +# Enable or disable generation of the classlist at build time +# + + # # Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -5080,7 +5092,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=1463732692 +DATE_WHEN_GENERATED=1464173584 ############################################################################### # @@ -64812,6 +64824,51 @@ $as_echo "yes, jtreg present" >&6; } + # Check whether --enable-generate-classlist was given. +if test "${enable_generate_classlist+set}" = set; then : + enableval=$enable_generate_classlist; +fi + + + # Check if it's likely that it's possible to generate the classlist. Depending + # on exact jvm configuration it could be possible anyway. + if [[ " $JVM_VARIANTS " =~ " server " ]] || [[ " $JVM_VARIANTS " =~ " client " ]] ; then + ENABLE_GENERATE_CLASSLIST_POSSIBLE="true" + else + ENABLE_GENERATE_CLASSLIST_POSSIBLE="false" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the CDS classlist generation should be enabled" >&5 +$as_echo_n "checking if the CDS classlist generation should be enabled... " >&6; } + if test "x$enable_generate_classlist" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5 +$as_echo "yes, forced" >&6; } + ENABLE_GENERATE_CLASSLIST="true" + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&5 +$as_echo "$as_me: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&2;} + fi + elif test "x$enable_generate_classlist" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5 +$as_echo "no, forced" >&6; } + ENABLE_GENERATE_CLASSLIST="false" + elif test "x$enable_generate_classlist" = "x"; then + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xtrue"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ENABLE_GENERATE_CLASSLIST="true" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ENABLE_GENERATE_CLASSLIST="false" + fi + else + as_fn_error $? "Invalid value for --enable-generate-classlist: $enable_generate_classlist" "$LINENO" 5 + fi + + + + ############################################################################### # # Configure parts of the build that only affect the build performance, diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 076b6cfaa09..4ae07928262 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -491,3 +491,46 @@ AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER], AC_SUBST(BUILD_FAILURE_HANDLER) ]) + +################################################################################ +# +# Enable or disable generation of the classlist at build time +# +AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST], +[ + AC_ARG_ENABLE([generate-classlist], [AS_HELP_STRING([--disable-generate-classlist], + [forces enabling or disabling of the generation of a CDS classlist at build time. + Default is to generate it when either the server or client JVMs are built.])]) + + # Check if it's likely that it's possible to generate the classlist. Depending + # on exact jvm configuration it could be possible anyway. + if HOTSPOT_CHECK_JVM_VARIANT(server) || HOTSPOT_CHECK_JVM_VARIANT(client); then + ENABLE_GENERATE_CLASSLIST_POSSIBLE="true" + else + ENABLE_GENERATE_CLASSLIST_POSSIBLE="false" + fi + + AC_MSG_CHECKING([if the CDS classlist generation should be enabled]) + if test "x$enable_generate_classlist" = "xyes"; then + AC_MSG_RESULT([yes, forced]) + ENABLE_GENERATE_CLASSLIST="true" + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then + AC_MSG_WARN([Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS]) + fi + elif test "x$enable_generate_classlist" = "xno"; then + AC_MSG_RESULT([no, forced]) + ENABLE_GENERATE_CLASSLIST="false" + elif test "x$enable_generate_classlist" = "x"; then + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xtrue"; then + AC_MSG_RESULT([yes]) + ENABLE_GENERATE_CLASSLIST="true" + else + AC_MSG_RESULT([no]) + ENABLE_GENERATE_CLASSLIST="false" + fi + else + AC_MSG_ERROR([Invalid value for --enable-generate-classlist: $enable_generate_classlist]) + fi + + AC_SUBST([ENABLE_GENERATE_CLASSLIST]) +]) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index cace1439818..a58639f2b8a 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -285,6 +285,8 @@ BUILD_HOTSPOT=@BUILD_HOTSPOT@ BUILD_FAILURE_HANDLER := @BUILD_FAILURE_HANDLER@ +ENABLE_GENERATE_CLASSLIST := @ENABLE_GENERATE_CLASSLIST@ + # The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep # it in sync. BOOT_JDK:=@BOOT_JDK@ diff --git a/corba/.hgtags b/corba/.hgtags index db59b1cf556..284ccf7a0d8 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -362,3 +362,4 @@ cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113 7a1b36bf2fe55a9a7732489ccdd326c910329a7e jdk-9+117 8c2c2d17f7ce92a31c9ccb44a122ec62f5a85ace jdk-9+118 daf533920b1266603b5cbdab31908d2a931c5361 jdk-9+119 +5943b791e131e79b969d4cea053aecda34801723 jdk-9+120 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 754ebb60e4b..c500fce7e12 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -522,3 +522,4 @@ b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114 88170d3642905b9e6cac03e8efcc976885a7e6da jdk-9+117 9b1075cac08dc836ec32e7b368415cbe3aceaf8c jdk-9+118 15f3fe264872766bcb205696198f0c1502420e17 jdk-9+119 +0be6f4f5d18671184e62583668cb1d783dffa128 jdk-9+120 diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 7de009b0cce..e447d080f2b 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -362,3 +362,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 46b57560cd06ebcdd21489250628ff5f9d9d8916 jdk-9+117 a8aa25fc6c5fda0ed7a93b8ffee62da326a752fc jdk-9+118 f92e8518bb34a9628b11e662bf7308561a55eb3b jdk-9+119 +ecbe72546137cd29cb73d4dcc81cc099e847d543 jdk-9+120 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 0fe31aa3ebc..b7d3abb35f7 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -365,3 +365,4 @@ b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114 58265b39fc74b932bda4d4f4649c530a89f55c4e jdk-9+117 6ba73d04589ccc0705a5d8ae5111b63632b6ad20 jdk-9+118 331a825f849afd2e5126c93c88e55bd9ef0c6b8f jdk-9+119 +ecd0d6a71c7ccf93584ba4dacdd4fa8455efd741 jdk-9+120 diff --git a/jdk/.hgtags b/jdk/.hgtags index b7e36c324d5..7ac8e6be416 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -362,3 +362,4 @@ baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116 4da0f73ce03aaf245b92cc040cc0ab0e3fa54dc2 jdk-9+117 e1eba5cfa5cc8c66d524396a05323dc93568730a jdk-9+118 bad3f8a33db271a6143ba6eac0c8bd5bbd942417 jdk-9+119 +b9a518bf72516954e57ac2f6e3ef21e13008f1cd jdk-9+120 diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index 693f5a87fb8..8bd1118c1ff 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -267,6 +267,7 @@ SUNWprivate_1.1 { Java_jdk_internal_misc_VM_geteuid; Java_jdk_internal_misc_VM_getgid; Java_jdk_internal_misc_VM_getegid; + Java_jdk_internal_misc_VM_getRuntimeArguments; Java_jdk_internal_misc_VM_initialize; Java_java_lang_reflect_Module_defineModule0; diff --git a/jdk/src/java.base/share/classes/java/lang/Boolean.java b/jdk/src/java.base/share/classes/java/lang/Boolean.java index eeda751719c..af7bad17a64 100644 --- a/jdk/src/java.base/share/classes/java/lang/Boolean.java +++ b/jdk/src/java.base/share/classes/java/lang/Boolean.java @@ -117,7 +117,9 @@ public final class Boolean implements java.io.Serializable, * Parses the string argument as a boolean. The {@code boolean} * returned represents the value {@code true} if the string argument * is not {@code null} and is equal, ignoring case, to the string - * {@code "true"}.

+ * {@code "true"}. + * Otherwise, a false value is returned, including for a null + * argument.

* Example: {@code Boolean.parseBoolean("True")} returns {@code true}.
* Example: {@code Boolean.parseBoolean("yes")} returns {@code false}. * @@ -165,6 +167,8 @@ public final class Boolean implements java.io.Serializable, * specified string. The {@code Boolean} returned represents a * true value if the string argument is not {@code null} * and is equal, ignoring case, to the string {@code "true"}. + * Otherwise, a false value is returned, including for a null + * argument. * * @param s a string. * @return the {@code Boolean} value represented by the string. @@ -241,14 +245,12 @@ public final class Boolean implements java.io.Serializable, /** * Returns {@code true} if and only if the system property named - * by the argument exists and is equal to the string {@code - * "true"}. (Beginning with version 1.0.2 of the Java™ - * platform, the test of this string is case insensitive.) A - * system property is accessible through {@code getProperty}, a - * method defined by the {@code System} class. - *

- * If there is no property with the specified name, or if the specified - * name is empty or null, then {@code false} is returned. + * by the argument exists and is equal to, ignoring case, the + * string {@code "true"}. + * A system property is accessible through {@code getProperty}, a + * method defined by the {@code System} class.

If there is no + * property with the specified name, or if the specified name is + * empty or null, then {@code false} is returned. * * @param name the system property name. * @return the {@code boolean} value of the system property. diff --git a/jdk/src/java.base/share/classes/java/lang/StackWalker.java b/jdk/src/java.base/share/classes/java/lang/StackWalker.java index aef9c729a92..247cd467a83 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java +++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java @@ -306,8 +306,9 @@ public final class StackWalker { return DEFAULT_WALKER; } - checkPermission(options); - return new StackWalker(toEnumSet(options)); + EnumSet

The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS + *

The constant {@link #TYPE_USE} corresponds to the type contexts in JLS * 4.11, as well as to two declaration contexts: type declarations (including * annotation type declarations) and type parameter declarations. * diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java index 1b77bfd8618..4d3d2bf15a0 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.nio.ByteBuffer; +import java.util.Objects; import java.util.Optional; @@ -163,9 +164,12 @@ public interface ModuleReader extends Closeable { * @param bb * The byte buffer to release * - * @implSpec The default implementation does nothing. + * @implSpec The default implementation doesn't do anything except check + * if the byte buffer is null. */ - default void release(ByteBuffer bb) { } + default void release(ByteBuffer bb) { + Objects.requireNonNull(bb); + } /** * Closes the module reader. Once closed then subsequent calls to locate or diff --git a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java index 77d5392821a..9dd6694267c 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java @@ -272,9 +272,9 @@ class SystemModuleFinder implements ModuleFinder { * if not found. */ private ImageLocation findImageLocation(String name) throws IOException { + Objects.requireNonNull(name); if (closed) throw new IOException("ModuleReader is closed"); - if (imageReader != null) { return imageReader.findLocation(module, name); } else { @@ -322,6 +322,7 @@ class SystemModuleFinder implements ModuleFinder { @Override public void release(ByteBuffer bb) { + Objects.requireNonNull(bb); ImageReader.releaseByteBuffer(bb); } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java index 34dae522d6f..6e220a5e43c 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java @@ -75,11 +75,12 @@ import sun.security.util.SecurityConstants; * *

A Java virtual machine has at least one non-empty layer, the {@link * #boot() boot} layer, that is created when the Java virtual machine is - * started. The system modules, including {@code java.base}, are in - * the boot layer. The modules in the boot layer are mapped to the bootstrap - * class loader and other class loaders that are built-in into the Java virtual - * machine. The boot layer will often be the {@link #parent() parent} when - * creating additional layers.

+ * started. The boot layer contains module {@code java.base} and is the only + * layer in the Java virtual machine with a module named "{@code java.base}". + * The modules in the boot layer are mapped to the bootstrap class loader and + * other class loaders that are + * built-in into the Java virtual machine. The boot layer will often be + * the {@link #parent() parent} when creating additional layers.

* *

As when creating a {@code Configuration}, * {@link ModuleDescriptor#isAutomatic() automatic} modules receive @@ -204,7 +205,8 @@ public final class Layer { * for this layer * @throws LayerInstantiationException * If all modules cannot be defined to the same class loader for any - * of the reasons listed above + * of the reasons listed above or the layer cannot be created because + * the configuration contains a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("createClassLoader")} or * {@code RuntimePermission("getClassLoader")} is denied by @@ -219,14 +221,13 @@ public final class Layer { checkCreateClassLoaderPermission(); checkGetClassLoaderPermission(); - Loader loader; try { - loader = new Loader(cf.modules(), parentLoader); + Loader loader = new Loader(cf.modules(), parentLoader); loader.initRemotePackageMap(cf, this); + return new Layer(cf, this, mn -> loader); } catch (IllegalArgumentException e) { throw new LayerInstantiationException(e.getMessage()); } - return new Layer(cf, this, mn -> loader); } @@ -266,6 +267,9 @@ public final class Layer { * @throws IllegalArgumentException * If the parent of the given configuration is not the configuration * for this layer + * @throws LayerInstantiationException + * If the layer cannot be created because the configuration contains + * a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("createClassLoader")} or * {@code RuntimePermission("getClassLoader")} is denied by @@ -281,7 +285,11 @@ public final class Layer { checkGetClassLoaderPermission(); LoaderPool pool = new LoaderPool(cf, this, parentLoader); - return new Layer(cf, this, pool::loaderFor); + try { + return new Layer(cf, this, pool::loaderFor); + } catch (IllegalArgumentException e) { + throw new LayerInstantiationException(e.getMessage()); + } } @@ -330,7 +338,8 @@ public final class Layer { * for this layer * @throws LayerInstantiationException * If creating the {@code Layer} fails for any of the reasons - * listed above + * listed above or the layer cannot be created because the + * configuration contains a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("getClassLoader")} is denied by * the security manager diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java index 59eb856f8fb..26e47245f38 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java @@ -513,7 +513,7 @@ public final class Module { * package {@code pn} to the given module. * *

This method has no effect if the package is already exported to the - * given module. If also has no effect if invoked on an unnamed module (as + * given module. It also has no effect if invoked on an unnamed module (as * unnamed modules export all packages).

* * @param pn @@ -866,7 +866,7 @@ public final class Module { URI uri = mref.location().orElse(null); Module m; - if (loader == null && name.equals("java.base")) { + if (loader == null && name.equals("java.base") && Layer.boot() == null) { m = Object.class.getModule(); } else { m = new Module(layer, loader, descriptor, uri); diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java index dce4300c77a..162daf9458c 100644 --- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java @@ -55,7 +55,7 @@ import java.util.Arrays; * object to the operation. In either case, eight rounding * modes are provided for the control of rounding. Using the * integer fields in this class (such as {@link #ROUND_HALF_UP}) to - * represent rounding mode is largely obsolete; the enumeration values + * represent rounding mode is deprecated; the enumeration values * of the {@code RoundingMode} {@code enum}, (such as {@link * RoundingMode#HALF_UP}) should be used instead. * @@ -93,7 +93,7 @@ import java.util.Arrays; *

In general the rounding modes and precision setting determine * how operations return results with a limited number of digits when * the exact result has more digits (perhaps infinitely many in the - * case of division) than the number of digits returned. + * case of division and square root) than the number of digits returned. * * First, the * total number of digits to return is specified by the @@ -196,18 +196,19 @@ import java.util.Arrays; * {@code BigDecimal} value; for example [19, 2] is the * {@code BigDecimal} numerically equal to 0.19 having a scale of 2. * - *

Note: care should be exercised if {@code BigDecimal} objects - * are used as keys in a {@link java.util.SortedMap SortedMap} or - * elements in a {@link java.util.SortedSet SortedSet} since - * {@code BigDecimal}'s natural ordering is inconsistent - * with equals. See {@link Comparable}, {@link - * java.util.SortedMap} or {@link java.util.SortedSet} for more - * information. * *

All methods and constructors for this class throw * {@code NullPointerException} when passed a {@code null} object * reference for any input parameter. * + * @apiNote Care should be exercised if {@code BigDecimal} objects + * are used as keys in a {@link java.util.SortedMap SortedMap} or + * elements in a {@link java.util.SortedSet SortedSet} since + * {@code BigDecimal}'s natural ordering is inconsistent + * with equals. See {@link Comparable}, {@link + * java.util.SortedMap} or {@link java.util.SortedSet} for more + * information. + * * @see BigInteger * @see MathContext * @see RoundingMode @@ -377,10 +378,10 @@ public class BigDecimal extends Number implements Comparable { * same sequence of characters as the {@link #BigDecimal(String)} * constructor, while allowing a sub-array to be specified. * - *

Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * within a character array, using this constructor is faster than * converting the {@code char} array to string and using the - * {@code BigDecimal(String)} constructor . + * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @param offset first character in the array to inspect. @@ -401,14 +402,14 @@ public class BigDecimal extends Number implements Comparable { * constructor, while allowing a sub-array to be specified and * with rounding according to the context settings. * - *

Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * within a character array, using this constructor is faster than * converting the {@code char} array to string and using the * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @param offset first character in the array to inspect. - * @param len number of characters to consider.. + * @param len number of characters to consider. * @param mc the context to use. * @throws ArithmeticException if the result is inexact but the * rounding mode is {@code UNNECESSARY}. @@ -679,10 +680,10 @@ public class BigDecimal extends Number implements Comparable { * same sequence of characters as the {@link #BigDecimal(String)} * constructor. * - *

Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * as a character array, using this constructor is faster than * converting the {@code char} array to string and using the - * {@code BigDecimal(String)} constructor . + * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @throws NumberFormatException if {@code in} is not a valid @@ -700,10 +701,10 @@ public class BigDecimal extends Number implements Comparable { * constructor and with rounding according to the context * settings. * - *

Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * as a character array, using this constructor is faster than * converting the {@code char} array to string and using the - * {@code BigDecimal(String)} constructor . + * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @param mc the context to use. @@ -805,7 +806,7 @@ public class BigDecimal extends Number implements Comparable { * "-0" [0,0] * * - *

Note: For values other than {@code float} and + * @apiNote For values other than {@code float} and * {@code double} NaN and ±Infinity, this constructor is * compatible with the values returned by {@link Float#toString} * and {@link Double#toString}. This is generally the preferred @@ -859,13 +860,13 @@ public class BigDecimal extends Number implements Comparable { * This is because 0.1 cannot be represented exactly as a * {@code double} (or, for that matter, as a binary fraction of * any finite length). Thus, the value that is being passed - * in to the constructor is not exactly equal to 0.1, + * in to the constructor is not exactly equal to 0.1, * appearances notwithstanding. * *

  • * The {@code String} constructor, on the other hand, is * perfectly predictable: writing {@code new BigDecimal("0.1")} - * creates a {@code BigDecimal} which is exactly equal to + * creates a {@code BigDecimal} which is exactly equal to * 0.1, as one would expect. Therefore, it is generally * recommended that the {@linkplain #BigDecimal(String) * String constructor} be used in preference to this one. @@ -1199,10 +1200,11 @@ public class BigDecimal extends Number implements Comparable { /** * Translates a {@code long} unscaled value and an - * {@code int} scale into a {@code BigDecimal}. This - * {@literal "static factory method"} is provided in preference to - * a ({@code long}, {@code int}) constructor because it - * allows for reuse of frequently used {@code BigDecimal} values.. + * {@code int} scale into a {@code BigDecimal}. + * + * @apiNote This static factory method is provided in preference + * to a ({@code long}, {@code int}) constructor because it allows + * for reuse of frequently used {@code BigDecimal} values. * * @param unscaledVal unscaled value of the {@code BigDecimal}. * @param scale scale of the {@code BigDecimal}. @@ -1222,10 +1224,11 @@ public class BigDecimal extends Number implements Comparable { /** * Translates a {@code long} value into a {@code BigDecimal} - * with a scale of zero. This {@literal "static factory method"} - * is provided in preference to a ({@code long}) constructor - * because it allows for reuse of frequently used - * {@code BigDecimal} values. + * with a scale of zero. + * + * @apiNote This static factory method is provided in preference + * to a ({@code long}) constructor because it allows for reuse of + * frequently used {@code BigDecimal} values. * * @param val value of the {@code BigDecimal}. * @return a {@code BigDecimal} whose value is {@code val}. @@ -1270,11 +1273,11 @@ public class BigDecimal extends Number implements Comparable { * the {@code double}'s canonical string representation provided * by the {@link Double#toString(double)} method. * - *

    Note: This is generally the preferred way to convert - * a {@code double} (or {@code float}) into a - * {@code BigDecimal}, as the value returned is equal to that - * resulting from constructing a {@code BigDecimal} from the - * result of using {@link Double#toString(double)}. + * @apiNote This is generally the preferred way to convert a + * {@code double} (or {@code float}) into a {@code BigDecimal}, as + * the value returned is equal to that resulting from constructing + * a {@code BigDecimal} from the result of using {@link + * Double#toString(double)}. * * @param val {@code double} to convert to a {@code BigDecimal}. * @return a {@code BigDecimal} whose value is equal to or approximately @@ -1896,7 +1899,7 @@ public class BigDecimal extends Number implements Comparable { * *

    The remainder is given by * {@code this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))}. - * Note that this is not the modulo operation (the result can be + * Note that this is not the modulo operation (the result can be * negative). * * @param divisor value by which this {@code BigDecimal} is to be divided. @@ -2037,6 +2040,7 @@ public class BigDecimal extends Number implements Comparable { * {@code (mc.getRoundingMode()==RoundingMode.UNNECESSARY}) and * the exact result cannot fit in {@code mc.getPrecision()} * digits. + * @see BigInteger#sqrt() * @since 9 */ public BigDecimal sqrt(MathContext mc) { @@ -2694,8 +2698,8 @@ public class BigDecimal extends Number implements Comparable { * in this case, the specified rounding mode is applied to the * division. * - *

    Note that since BigDecimal objects are immutable, calls of - * this method do not result in the original object being + * @apiNote Since BigDecimal objects are immutable, calls of + * this method do not result in the original object being * modified, contrary to the usual convention of having methods * named setX mutate field {@code X}. * Instead, {@code setScale} returns an object with the proper @@ -2727,8 +2731,8 @@ public class BigDecimal extends Number implements Comparable { * in this case, the specified rounding mode is applied to the * division. * - *

    Note that since BigDecimal objects are immutable, calls of - * this method do not result in the original object being + * @apiNote Since BigDecimal objects are immutable, calls of + * this method do not result in the original object being * modified, contrary to the usual convention of having methods * named setX mutate field {@code X}. * Instead, {@code setScale} returns an object with the proper @@ -2822,8 +2826,8 @@ public class BigDecimal extends Number implements Comparable { * versions of {@code setScale}, but saves the caller the trouble * of specifying a rounding mode in cases where it is irrelevant. * - *

    Note that since {@code BigDecimal} objects are immutable, - * calls of this method do not result in the original + * @apiNote Since {@code BigDecimal} objects are immutable, + * calls of this method do not result in the original * object being modified, contrary to the usual convention of * having methods named setX mutate field * {@code X}. Instead, {@code setScale} returns an @@ -3091,7 +3095,7 @@ public class BigDecimal extends Number implements Comparable { /** * Returns the hash code for this {@code BigDecimal}. Note that * two {@code BigDecimal} objects that are numerically equal but - * differ in scale (like 2.0 and 2.00) will generally not + * differ in scale (like 2.0 and 2.00) will generally not * have the same hash code. * * @return hash code for this {@code BigDecimal}. @@ -3342,7 +3346,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code BigInteger}. * This conversion is analogous to the * narrowing primitive conversion from {@code double} to - * {@code long} as defined in section 5.1.3 of + * {@code long} as defined in * The Java™ Language Specification: * any fractional part of this * {@code BigDecimal} will be discarded. Note that this @@ -3354,6 +3358,7 @@ public class BigDecimal extends Number implements Comparable { * {@link #toBigIntegerExact()} method. * * @return this {@code BigDecimal} converted to a {@code BigInteger}. + * @jls 5.1.3 Narrowing Primitive Conversion */ public BigInteger toBigInteger() { // force to an integer, quietly @@ -3379,7 +3384,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code long}. * This conversion is analogous to the * narrowing primitive conversion from {@code double} to - * {@code short} as defined in section 5.1.3 of + * {@code short} as defined in * The Java™ Language Specification: * any fractional part of this * {@code BigDecimal} will be discarded, and if the resulting @@ -3390,6 +3395,7 @@ public class BigDecimal extends Number implements Comparable { * as return a result with the opposite sign. * * @return this {@code BigDecimal} converted to a {@code long}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public long longValue(){ @@ -3448,7 +3454,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to an {@code int}. * This conversion is analogous to the * narrowing primitive conversion from {@code double} to - * {@code short} as defined in section 5.1.3 of + * {@code short} as defined in * The Java™ Language Specification: * any fractional part of this * {@code BigDecimal} will be discarded, and if the resulting @@ -3459,6 +3465,7 @@ public class BigDecimal extends Number implements Comparable { * value as well as return a result with the opposite sign. * * @return this {@code BigDecimal} converted to an {@code int}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public int intValue() { @@ -3531,7 +3538,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code float}. * This conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this {@code BigDecimal} has too great a * magnitude to represent as a {@code float}, it will be @@ -3542,6 +3549,7 @@ public class BigDecimal extends Number implements Comparable { * value. * * @return this {@code BigDecimal} converted to a {@code float}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public float floatValue(){ @@ -3575,7 +3583,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code double}. * This conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this {@code BigDecimal} has too great a * magnitude represent as a {@code double}, it will be @@ -3586,6 +3594,7 @@ public class BigDecimal extends Number implements Comparable { * value. * * @return this {@code BigDecimal} converted to a {@code double}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public double doubleValue(){ diff --git a/jdk/src/java.base/share/classes/java/math/BigInteger.java b/jdk/src/java.base/share/classes/java/math/BigInteger.java index c89aa09698d..b89939b5c1e 100644 --- a/jdk/src/java.base/share/classes/java/math/BigInteger.java +++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java @@ -116,6 +116,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; * +2{@code Integer.MAX_VALUE} (exclusive). * * @see BigDecimal + * @jls 4.2.2 Integer Operations * @author Josh Bloch * @author Michael McCloskey * @author Alan Eliasen @@ -126,7 +127,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; public class BigInteger extends Number implements Comparable { /** * The signum of this BigInteger: -1 for negative, 0 for zero, or - * 1 for positive. Note that the BigInteger zero must have + * 1 for positive. Note that the BigInteger zero must have * a signum of 0. This is necessary to ensures that there is exactly one * representation for each BigInteger value. */ @@ -710,7 +711,7 @@ public class BigInteger extends Number implements Comparable { * Constructs a randomly generated positive BigInteger that is probably * prime, with the specified bitLength. * - *

    It is recommended that the {@link #probablePrime probablePrime} + * @apiNote It is recommended that the {@link #probablePrime probablePrime} * method be used in preference to this constructor unless there * is a compelling need to specify a certainty. * @@ -1157,9 +1158,11 @@ public class BigInteger extends Number implements Comparable { /** * Returns a BigInteger whose value is equal to that of the - * specified {@code long}. This "static factory method" is - * provided in preference to a ({@code long}) constructor - * because it allows for reuse of frequently used BigIntegers. + * specified {@code long}. + * + * @apiNote This static factory method is provided in preference + * to a ({@code long}) constructor because it allows for reuse of + * frequently used BigIntegers. * * @param val value of the BigInteger to return. * @return a BigInteger with the specified value. @@ -3551,13 +3554,13 @@ public class BigInteger extends Number implements Comparable { /** * Returns the number of bits in the minimal two's-complement - * representation of this BigInteger, excluding a sign bit. + * representation of this BigInteger, excluding a sign bit. * For positive BigIntegers, this is equivalent to the number of bits in * the ordinary binary representation. (Computes * {@code (ceil(log2(this < 0 ? -this : this+1)))}.) * * @return number of bits in the minimal two's-complement - * representation of this BigInteger, excluding a sign bit. + * representation of this BigInteger, excluding a sign bit. */ public int bitLength() { int n = bitLengthPlusOne - 1; @@ -4034,7 +4037,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to an {@code int}. This * conversion is analogous to a * narrowing primitive conversion from {@code long} to - * {@code int} as defined in section 5.1.3 of + * {@code int} as defined in * The Java™ Language Specification: * if this BigInteger is too big to fit in an * {@code int}, only the low-order 32 bits are returned. @@ -4044,6 +4047,7 @@ public class BigInteger extends Number implements Comparable { * * @return this BigInteger converted to an {@code int}. * @see #intValueExact() + * @jls 5.1.3 Narrowing Primitive Conversion */ public int intValue() { int result = 0; @@ -4055,7 +4059,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to a {@code long}. This * conversion is analogous to a * narrowing primitive conversion from {@code long} to - * {@code int} as defined in section 5.1.3 of + * {@code int} as defined in * The Java™ Language Specification: * if this BigInteger is too big to fit in a * {@code long}, only the low-order 64 bits are returned. @@ -4065,6 +4069,7 @@ public class BigInteger extends Number implements Comparable { * * @return this BigInteger converted to a {@code long}. * @see #longValueExact() + * @jls 5.1.3 Narrowing Primitive Conversion */ public long longValue() { long result = 0; @@ -4078,7 +4083,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to a {@code float}. This * conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this BigInteger has too great a magnitude * to represent as a {@code float}, it will be converted to @@ -4088,6 +4093,7 @@ public class BigInteger extends Number implements Comparable { * information about the precision of the BigInteger value. * * @return this BigInteger converted to a {@code float}. + * @jls 5.1.3 Narrowing Primitive Conversion */ public float floatValue() { if (signum == 0) { @@ -4162,7 +4168,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to a {@code double}. This * conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this BigInteger has too great a magnitude * to represent as a {@code double}, it will be converted to @@ -4172,6 +4178,7 @@ public class BigInteger extends Number implements Comparable { * information about the precision of the BigInteger value. * * @return this BigInteger converted to a {@code double}. + * @jls 5.1.3 Narrowing Primitive Conversion */ public double doubleValue() { if (signum == 0) { diff --git a/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java b/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java index 6a3dcc76c7d..07f95ac56fb 100644 --- a/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java +++ b/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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,7 +23,10 @@ * questions. */ package java.net; + import java.io.IOException; +import static java.net.InetAddress.PREFER_IPV6_VALUE; +import static java.net.InetAddress.PREFER_SYSTEM_VALUE; /* * Package private implementation of InetAddressImpl for dual @@ -35,15 +38,23 @@ import java.io.IOException; * * @since 1.4 */ - class Inet6AddressImpl implements InetAddressImpl { - public native String getLocalHostName() throws UnknownHostException; - public native InetAddress[] - lookupAllHostAddr(String hostname) throws UnknownHostException; - public native String getHostByAddr(byte[] addr) throws UnknownHostException; - private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException; - public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException { + public native String getLocalHostName() throws UnknownHostException; + + public native InetAddress[] lookupAllHostAddr(String hostname) + throws UnknownHostException; + + public native String getHostByAddr(byte[] addr) throws UnknownHostException; + + private native boolean isReachable0(byte[] addr, int scope, int timeout, + byte[] inf, int ttl, int if_scope) + throws IOException; + + public boolean isReachable(InetAddress addr, int timeout, + NetworkInterface netif, int ttl) + throws IOException + { byte[] ifaddr = null; int scope = -1; int netif_scope = -1; @@ -79,7 +90,8 @@ class Inet6AddressImpl implements InetAddressImpl { public synchronized InetAddress anyLocalAddress() { if (anyLocalAddress == null) { - if (InetAddress.preferIPv6Address) { + if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || + InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) { anyLocalAddress = new Inet6Address(); anyLocalAddress.holder().hostName = "::"; } else { @@ -91,7 +103,8 @@ class Inet6AddressImpl implements InetAddressImpl { public synchronized InetAddress loopbackAddress() { if (loopbackAddress == null) { - if (InetAddress.preferIPv6Address) { + if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || + InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) { byte[] loopback = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; @@ -103,6 +116,6 @@ class Inet6AddressImpl implements InetAddressImpl { return loopbackAddress; } - private InetAddress anyLocalAddress; - private InetAddress loopbackAddress; + private InetAddress anyLocalAddress; + private InetAddress loopbackAddress; } diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index e45b590200a..33e70ea1b43 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -26,8 +26,6 @@ package java.net; import java.util.NavigableSet; -import java.util.Iterator; -import java.util.List; import java.util.ArrayList; import java.util.Objects; import java.util.Scanner; @@ -41,6 +39,7 @@ import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream.PutField; +import java.lang.annotation.Native; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentSkipListSet; @@ -193,6 +192,11 @@ import sun.net.util.IPAddressUtil; */ public class InetAddress implements java.io.Serializable { + + @Native static final int PREFER_IPV4_VALUE = 0; + @Native static final int PREFER_IPV6_VALUE = 1; + @Native static final int PREFER_SYSTEM_VALUE = 2; + /** * Specify the address family: Internet Protocol, Version 4 * @since 1.4 @@ -206,8 +210,7 @@ class InetAddress implements java.io.Serializable { static final int IPv6 = 2; /* Specify address family preference */ - static transient boolean preferIPv6Address = false; - + static transient final int preferIPv6Address; static class InetAddressHolder { /** @@ -293,8 +296,19 @@ class InetAddress implements java.io.Serializable { * Load net library into runtime, and perform initializations. */ static { - preferIPv6Address = java.security.AccessController.doPrivileged( - new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue(); + String str = java.security.AccessController.doPrivileged( + new GetPropertyAction("java.net.preferIPv6Addresses")); + if (str == null) { + preferIPv6Address = PREFER_IPV4_VALUE; + } else if (str.equalsIgnoreCase("true")) { + preferIPv6Address = PREFER_IPV6_VALUE; + } else if (str.equalsIgnoreCase("false")) { + preferIPv6Address = PREFER_IPV4_VALUE; + } else if (str.equalsIgnoreCase("system")) { + preferIPv6Address = PREFER_SYSTEM_VALUE; + } else { + preferIPv6Address = PREFER_IPV4_VALUE; + } AccessController.doPrivileged( new java.security.PrivilegedAction<>() { public Void run() { diff --git a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html index d8e8949fc32..76c82b5b81e 100644 --- a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -1,5 +1,5 @@ "ae" + // "z" --> "aeef" + // + String[][] test2 = { + { "< a & ae = a1 & aeef = z < b < e < f", "" }, + { "a", "1" }, + { "b", "1" }, + { "e", "2" }, + { "f", "4" }, + }; + verifyExpansion(test2); + } + + /* + * @bug 4157299 + */ + public void TestClearBuffers() throws ParseException { + RuleBasedCollator c = new RuleBasedCollator("< a < b < c & ab = d"); + CollationElementIterator i = c.getCollationElementIterator("abcd"); + int e0 = i.next(); // save the first collation element + i.setOffset(3); // go to the expanding character + i.next(); // but only use up half of it + i.setOffset(0); // go back to the beginning + int e = i.next(); // and get this one again + if (e != e0) { + errln("got " + Integer.toString(e, 16) + ", expected " + + Integer.toString(e0, 16)); + } + } + + //------------------------------------------------------------------------ + // Internal utilities + // + + private void backAndForth(CollationElementIterator iter) { + // Run through the iterator forwards and stick it into an array + int [] orders = getOrders(iter); + + // Now go through it backwards and make sure we get the same values + int index = orders.length; + int o; + + while ((o = iter.previous()) != CollationElementIterator.NULLORDER) { + if (o != orders[--index]) { + errln("Mismatch at index " + index + ": " + + orders[index] + " vs " + o); + break; + } + } + if (index != 0) { + errln("Didn't get back to beginning - index is " + index); + + iter.reset(); + err("next: "); + while ((o = iter.next()) != NULLORDER) { + err( Integer.toHexString(o) + " "); + } + errln(""); + + err("prev: "); + while ((o = iter.previous()) != NULLORDER) { + err( Integer.toHexString(o) + " "); + } + errln(""); + } + } + + /** + * Verify that getMaxExpansion works on a given set of collation rules + * + * The first row of the "tests" array contains the collation rules + * at index 0, and the string at index 1 is ignored. + * + * Subsequent rows of the array contain a character and a number, both + * represented as strings. The character's collation order is determined, + * and getMaxExpansion is called for that character. If its value is + * not equal to the specified number, an error results. + */ + private void verifyExpansion(String[][] tests) throws ParseException + { + RuleBasedCollator coll = new RuleBasedCollator(tests[0][0]); + CollationElementIterator iter = coll.getCollationElementIterator(""); + + for (int i = 1; i < tests.length; i++) { + // First get the collation key that the test string expands to + iter.setText(tests[i][0]); + + int order = iter.next(); + + if (order == NULLORDER || iter.next() != NULLORDER) { + iter.reset(); + errln("verifyExpansion: '" + tests[i][0] + + "' has multiple orders:" + orderString(iter)); + } + + int expansion = iter.getMaxExpansion(order); + int expect = new Integer(tests[i][1]).intValue(); + + if (expansion != expect) { + errln("expansion for '" + tests[i][0] + "' is wrong: " + + "expected " + expect + ", got " + expansion); + } + } + } + + /** + * Return an integer array containing all of the collation orders + * returned by calls to next on the specified iterator + */ + private int[] getOrders(CollationElementIterator iter) + { + int maxSize = 100; + int size = 0; + int[] orders = new int[maxSize]; + + int order; + while ((order = iter.next()) != NULLORDER) { + if (size == maxSize) { + maxSize *= 2; + int[] temp = new int[maxSize]; + System.arraycopy(orders, 0, temp, 0, size); + orders = temp; + } + orders[size++] = order; + } + + if (orders.length > size) { + int[] temp = new int[size]; + System.arraycopy(orders, 0, temp, 0, size); + orders = temp; + } + return orders; + }; + + /** + * Return a string containing all of the collation orders + * returned by calls to next on the specified iterator + */ + private String orderString(CollationElementIterator iter) { + StringBuffer buf = new StringBuffer(); + + int order; + while ((order = iter.next()) != NULLORDER) { + buf.append( Integer.toHexString(order) + " "); + } + return buf.toString(); + } + + static final private int NULLORDER = CollationElementIterator.NULLORDER; + RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US); + + String test1 = "What subset of all possible test cases?"; + String test2 = "has the highest probability of detecting"; +} diff --git a/jdk/test/java/text/Collator/JapaneseTest.java b/jdk/test/java/text/Collator/JapaneseTest.java new file mode 100644 index 00000000000..2bd5f6d0179 --- /dev/null +++ b/jdk/test/java/text/Collator/JapaneseTest.java @@ -0,0 +1,324 @@ +/* + * 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 + * 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 1.1 02/09/11 + * @bug 4176141 4655819 + * @summary Regression tests for Japanese Collation + */ + +import java.text.*; +import java.util.*; + +public class JapaneseTest { + + // NOTE: + // Golden data in this test case is locale data dependent and + // may need to be changed if the Japanese locale collation rules + // are changed. + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results1 = { + { -1, -1, -1}, + { -1, -1, -1}, + { -1, -1, -1}, + }; + static final String[][] compData1 = { + /* + * Data to verify '<' relationship in LocaleElements_ja.java + */ + {"\u3084", "\u30E6", + "Hiragana \"YA\"(0x3084) <---> Katakana \"YU\"(0x30E6)"}, + {"\u30E6", "\u3088", + "Katakana \"YU\"(0x30E6) <---> Hiragana \"YO\"(0x3088)"}, + {"\u00B1", "\u2260", + "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"}, + {"\u3011", "\u2260", + "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"}, + {"\u2260", "\u2103", + "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"}, + {"\u2260", "\u2606", + "Not Equal To(0x2260) <---> White Star(0x2606)"}, + {"\u30FD", "\u309E", + "Katakana Iteration Mark(0x30FD) <---> Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u3059\u309D", "\u3059\u309E", + "Hiragana \"SU\"(0x3059)Hiragana Iteration Mark(0x309D) <---> Hiragana \"SU\"(0x3059)Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u821E", "\u798F", + "CJK Unified Ideograph(0x821E) <---> CJK Unified Ideograph(0x798F)"}, + + /* + * Data to verify normalization + */ + {"\u2260", "\u225F", + "Not Equal To(0x2260) <---> Questioned Equal To(0x225F)"}, + {"\u226E", "\u2260", + "Not Less-than(0x226E) <---> Not Equal To(0x2260)"}, + {"\u226E", "\u226D", + "Not Less-than(0x226E) <---> Not Equivalent To(0x226D)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results2 = { + { 0, 0, 0}, + { -1, -1, -1}, + { -1, -1, -1}, + }; + static final String[][] compData2 = { + /* + * Data to verify ';' relationship in LocaleElements_ja.java + */ + {"\u3099", "\u309A", + "Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A)"}, + {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3068\u3099\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUTO\"(0x3053 0x3046 0x3068)Combining Katakana-Hiragana Voiced Sound Mark(0X3099)\"U\"(0x3046)"}, + {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3069\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUDOU\"(0x3053 0x3046 0x3069 0x3046)"}, + {"\u3053\u3046\u3069\u3046", "\u3054\u3046\u3068\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3069 0x3046) <---> Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046)"}, + {"\u3054\u3046\u3068\u3046", "\u3054\u3046\u3069\u3046", + "Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046) <---> Hiragana \"GOUDOU\"(0x3054 0x3046 0x3069 0x3046)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results3 = { + { 0, 0, 0}, + { 0, 0, 0}, + { -1, -1, -1}, + }; + static final String[][] compData3 = { + /* + * Data to verify ',' relationship in LocaleElements_ja.java + */ + {"\u3042", "\u3041", + "Hiragana \"A\"(0x3042) <---> Hiragana \"a\"(0x3041)"}, + {"\u3041", "\u30A2", + "Hiragana \"a\"(0x3041) <---> Katakana \"A\"(0x30A2)"}, + {"\u30A2", "\u30A1", + "Katakana \"A\"(0x30A2) <---> Katakana \"a\"(0x30A1)"}, + {"\u3094", "\u30F4", + "Hiragana \"VU\"(0x3094) <---> Katakana \"VU\"(0x30F4)"}, + {"\u3094", "\u30A6\u3099", + "Hiragana \"VU\"(0x3094) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u3046\u3099", "\u30F4", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"}, + {"\u3046\u3099", "\u30A6\u3099", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u30AB\u30A2", "\u30AB\u30FC", + "Katakana \"KAA\"(0x30AB 0x30A2) <---> Katakana \"KA-\"(0x30AB 0x30FC)"}, + {"\u30CB\u30A1\u30A2", "\u30CB\u30A1\u30FC", + "Katakana \"NyaA\"(0x30CB 0x30A1 0x30A2) <---> Katakana \"Nya-\"(0x30CB 0x30A1 0x30FC)"}, + {"\u30B3\u30AA\u30D2\u30A4", "\u30B3\u30FC\u30D2\u30FC", + "Katakana \"KOOHII\"(0x30B3 0x30AA 0x30D2 0x30A4) <---> Katakana \"KO-HI-\"(0x30B3 0x30FC 0x30D2 0x30FC)"}, + {"\u308A\u3088\u3046", "\u308A\u3087\u3046", + "Hiragana \"RIYOU\"(0x308A 0x3088 0x3046) <---> Hiragana \"Ryou\"(0x308A 0x3087 0x3046)"}, + {"\u3081\u3064\u304D", "\u3081\u3063\u304D", + "Hiragana \"METSUKI\"(0x3081 0x3064 0x304D) <---> Hiragana \"MEKKI\"(0x3081 0x3063 0x304D)"}, + {"\u3075\u3042\u3093", "\u30D5\u30A1\u30F3", + "Hiragana \"FUAN\"(0x3075 0x3042 0x3093) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"}, + {"\u3075\u3041\u3093", "\u30D5\u30A2\u30F3", + "Hiragana \"FUaN\"(0x3075 0x3041 0x3093) <---> Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3)"}, + {"\u30D5\u30A2\u30F3", "\u30D5\u30A1\u30F3", + "Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + */ + static final int[][] results4 = { + { 0, 0, 0}, + { 0, 0, 0}, + { 0, 0, 0}, + }; + static final String[][] compData4 = { + /* + * Data to verify Japanese normalization + */ + {"\u309E", "\u309D\u3099", + "Hiragana Voiced Iteration Mark(0x309E) <---> Hiragana Iteration Mark(0x309D)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u30FE", "\u30FD\u3099", + "Katakana Voiced Iteration Mark(0x30FE) <---> Katakana iteration mark(0x30FD)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u306F\u3099", "\u3070", + "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"BA\"(0x3070)"}, + {"\u306F\u309A", "\u3071", + "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A) <---> Hiragana \"PA\"(0x3071)"}, + {"\u30EF\u3099", "\u30F7", + "Katakana \"WA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VA\"(0x30F7)"}, + {"\u30F0\u3099", "\u30F8", + "Katakana \"WI\"(0x30F0)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VI\"(0x30F8)"}, + {"\u30F1\u3099", "\u30F9", + "Katakana \"WE\"(0x30F1)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VE\"(0x30F9)"}, + {"\u30F2\u3099", "\u30FA", + "Katakana \"WO\"(0x30F2)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VO\"(0x30FA)"}, + {"\u3046\u3099", "\u3094", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"VU\"(0x3094)"}, + {"\u30A6\u3099", "\u30F4", + "Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"}, + + // verify normalization + {"\u2260", "\u003D\u0338", + "Not Equal To(0x2260) <---> Equal(0x003D)Combining Long Solidus Overlay(0x0338)"}, + {"\u2262", "\u2261\u0338", + "Not Identical To(0x2262) <---> Identical To(0x2261)Combining Long Solidus Overlay(0x0338)"}, + {"\u226E", "\u003C\u0338", + "Not Less-than(0x226E) <---> Less-than Sign(0x003C)Combining Long Solidus Overlay(0x0338)"}, + + // Verify a character which has been added since Unicode 2.1.X. + {"\u798F", "\uFA1B", + "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + */ + static final int[][] results5 = { + { 1, 0, 0}, + { 1, 0, 0}, + { 1, 0, 0}, + }; + static final String[][] compData5 = { + /* + * Data to verify normalization + */ + {"\u226D", "\u224D\u0338", + "Not Equivalent To(0x226D) <---> Equivalent To(0x224D)Combining Long Solidus Overlay(0x0338)"}, + }; + + static final int[][] results6 = { + { 1, -1, -1}, + { 1, -1, -1}, + { 1, -1, -1}, + }; + static final String[][] compData6 = { + /* + * Data to verify normalization + */ + {"\u226D", "\u226C", + "Not Equivalent To(0x226D) <---> Between(0x226C)"}, + {"\u226D", "\u225F", + "Not Equivalent To(0x226D) <---> Questioned Equal To(0x225F)"}, + }; + + + /* + * The following data isn't used at the moment because iteration marks + * aren't supported now. + */ + static final String[][] compData0 = { + {"\u307F\u307F", "\u307F\u309D", + "Hiragana \"MIMI\"(0x307F 0x307F) <---> Hiragana \"MI\"(0x307F)Hiragana Iteration Mark(0x309D)"}, + {"\u3044\u3059\u305A", "\u3044\u3059\u309E", + "Hiragana \"ISUZU\"(0x3044 0x3059 0x305A) <---> Hiragana \"ISU\"(0x3044 0x3059)Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u30DF\u30DF", "\u30DF\u30FD", + "Katakana \"MIMI\"(0x30DF 0x30DF) <---> Katakana \"MI\"(0x30DF)Katakana Iteration Mark(0x30FD)"}, + {"\u30A4\u30B9\u30BA", "\u30A4\u30B9\u30FE", + "Katakana \"ISUZU\"(0x30A4 0x30B9 0x30BA) <---> Katakana \"ISU\"(0x30A4 0x30B9)Katakana Voiced Iteration Mark(0x30FE)"}, + }; + + + static final String[] decomp_name = { + "NO_DECOMP", "CANONICAL_DECOMP", "FULL_DECOMP" + }; + + static final String[] strength_name = { + "PRIMARY", "SECONDARY", "TERTIARY" + }; + + + Collator col = Collator.getInstance(Locale.JAPAN); + int result = 0; + + public static void main(String[] args) throws Exception { + new JapaneseTest().run(); + } + + public void run() { + // Use all available localse on the initial testing.... + // Locale[] locales = Locale.getAvailableLocales(); + Locale[] locales = { Locale.getDefault() }; + + for (int l = 0; l < locales.length; l++) { + Locale.setDefault(locales[l]); + + for (int decomp = 0; decomp < 3; decomp++) {// See decomp_name. + col.setDecomposition(decomp); + + for (int strength = 0; strength < 3; strength++) {// See strength_name. +// System.err.println("\n" + locales[l] + ": " + strength_name[strength] + " --- " + decomp_name[decomp]); + + col.setStrength(strength); + doCompare(compData1, results1[strength][decomp], strength, decomp); + doCompare(compData2, results2[strength][decomp], strength, decomp); + doCompare(compData3, results3[strength][decomp], strength, decomp); + doCompare(compData4, results4[strength][decomp], strength, decomp); + doCompare(compData5, results5[strength][decomp], strength, decomp); + doCompare(compData6, results6[strength][decomp], strength, decomp); + } + } + } + + /* Check result */ + if (result !=0) { + throw new RuntimeException("Unexpected results on Japanese collation."); + } + } + + void doCompare(String[][] s, int expectedValue, int strength, int decomp) { + int value; + for (int i=0; i < s.length; i++) { + if ((value = col.compare(s[i][0], s[i][1])) != expectedValue) { + result++; + System.err.println(strength_name[strength] + + ": compare() returned unexpected value.(" + + value + ") on " + decomp_name[decomp] + + " Expected(" + expectedValue + + ") for " + s[i][2]); + } + } + } +} diff --git a/jdk/test/java/text/Collator/KoreanTest.java b/jdk/test/java/text/Collator/KoreanTest.java new file mode 100644 index 00000000000..fd314ee13ed --- /dev/null +++ b/jdk/test/java/text/Collator/KoreanTest.java @@ -0,0 +1,142 @@ +/* + * 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 + * 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 1.1 02/09/12 + * @bug 4176141 4655819 + * @summary Regression tests for Korean Collation + */ + +import java.text.*; +import java.util.*; + +public class KoreanTest { + + // NOTE: + // Golden data in this test case is locale data dependent and + // may need to be changed if the Korean locale collation rules + // are changed. + + // And, CollationDecomp has been set to 0(NO_DECOMPOSITION) in + // LocaleElements_ko.java. + // This is very important to consider what is correct behavior in + // Korean Collator. Sometimes different from other locales. + + /* + * TERTIARY(default): s1 < s2, SECONDARY: s1 < s2, PRIMARY: s1 < s2 + */ + static final String[][] compData1 = { + /* + * Data to verify '<' relationship in LocaleElements_ja.java + */ + {"\uACE0\uC591\uC774", "\u732B", + "Hangul \"Cat\"(0xACE0 0xC591 0xC774) <---> Chinese Kanji \"Cat\"(0x732B)"}, + {"\u30FB", "\u2025", + "Katakana middle dot(0x30FB) <---> Two dot leader(0x2025)"}, + + {"\u00B1", "\u2260", + "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"}, + {"\u3011", "\u2260", + "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"}, + {"\u2260", "\u2103", + "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"}, + {"\u2260", "\u2606", + "Not Equal To(0x2260) <---> White Star(0x2606)"}, + + // Unlike other locales' Collator, compare() returns -1 because of + // NO_DECOMPOSITION. + /* above "assumption" is no longer true, now we do normalize ("decomposition") + for the pattern in ko locale, but exclude those hangul syllables, so the + test case below need to be excluded from tiger/1.5 + {"\u003D\u0338", "\u2260", + "Equal(0x003D)Combining Long Solidus Overlay(0x0338) <---> Not Equal To(0x2260)"}, + */ + }; + + /* + * TERTIARY(default): s1 = s2, SECONDARY: s1 = s2, PRIMARY: s1 = s2 + */ + static final String[][] compData2 = { + // Verify a character which has been added since Unicode 2.1.X. + {"\u798F", "\uFA1B", + "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"}, + + }; + + Collator col = Collator.getInstance(Locale.KOREA); + int result = 0; + + public static void main(String[] args) throws Exception { + new KoreanTest().run(); + } + + public void run() { + // + // Test for TERTIARY(default) + // + doCompare(compData1); + doEquals(compData2); + + // + // Test for SECONDARY + // + col.setStrength(Collator.SECONDARY); + doCompare(compData1); + doEquals(compData2); + + // + // Test for PRIMARY + // + col.setStrength(Collator.PRIMARY); + doCompare(compData1); + doEquals(compData2); + + if (result !=0) { + throw new RuntimeException("Unexpected results on Korean collation."); + } + } + + /* compare() should return -1 for each combination. */ + void doCompare(String[][] s) { + int value; + for (int i=0; i < s.length; i++) { + if ((value = col.compare(s[i][0], s[i][1])) > -1) { + result++; + System.err.println("TERTIARY: The first string should be less than the second string: " + + s[i][2] + " compare() returned " + value + "."); + } + } + } + + /* equals() should return true for each combination. */ + void doEquals(String[][] s) { + for (int i=0; i < s.length; i++) { + if (!col.equals(s[i][0], s[i][1])) { + result++; + System.err.println("TERTIARY: The first string should be equals to the second string: " + + s[i][2] + " compare() returned " + + col.compare(s[i][0], s[i][1] + ".")); + } + } + } +} diff --git a/jdk/test/java/text/Collator/MonkeyTest.java b/jdk/test/java/text/Collator/MonkeyTest.java new file mode 100644 index 00000000000..9539bf5f5ae --- /dev/null +++ b/jdk/test/java/text/Collator/MonkeyTest.java @@ -0,0 +1,149 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test Collation, Monkey style + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - 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. +*/ + +import java.io.IOException; +import java.util.Random; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.text.CollationKey; + +public class MonkeyTest extends CollatorTest +{ + public static void main(String[] args) throws Exception { + new MonkeyTest().run(args); + } + + public void report(String s, String t, int result, int revResult) + { + if (result == -1) + { + if (revResult != 1) + errln(" --> Test Failed"); + } + else if (result == 1) + { + if (revResult != -1) + errln(" --> Test Failed"); + } + else if (result == 0) + { + if (revResult != 0) + errln(" --> Test Failed"); + } + } + + public void TestCollationKey() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + CollationKey CollationKey1 = myCollator.getCollationKey(subs); + CollationKey CollationKey2 = myCollator.getCollationKey(subt); + int result = CollationKey1.compareTo(CollationKey2); // Tertiary + int revResult = CollationKey2.compareTo(CollationKey1); // Tertiary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.SECONDARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Secondary + revResult = CollationKey2.compareTo(CollationKey1); // Secondary + report(("CollationKey(" + subs + ")") , ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.PRIMARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Primary + revResult = CollationKey2.compareTo(CollationKey1); // Primary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + String addOne = subs + "\uE000"; + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(addOne); + result = CollationKey1.compareTo(CollationKey2); + if (result != -1) + errln("CollationKey(" + subs + ")" + ".LT." + "CollationKey(" + addOne + ") Failed."); + result = CollationKey2.compareTo(CollationKey1); + if (result != 1) + errln("CollationKey(" + addOne + ")" + ".GT." + "CollationKey(" + subs + ") Failed."); + } + private static int checkValue(int value) + { + value *= (value > 0) ? 1 : -1; + return value; + } + public void TestCompare() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + int result = myCollator.compare(subs, subt); // Tertiary + int revResult = myCollator.compare(subt, subs); // Tertiary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.SECONDARY); + result = myCollator.compare(subs, subt); // Secondary + revResult = myCollator.compare(subt, subs); // Secondary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.PRIMARY); + result = myCollator.compare(subs, subt); // Primary + revResult = myCollator.compare(subt, subs); // Primary + report(subs, subt, result, revResult); + String addOne = subs + "\uE000"; + result = myCollator.compare(subs, addOne); + if (result != -1) + errln("Test : " + subs + " .LT. " + addOne + " Failed."); + result = myCollator.compare(addOne, subs); + if (result != 1) + errln("Test : " + addOne + " .GE. " + subs + " Failed."); + } + private static Collator myCollator = Collator.getInstance(); +} diff --git a/jdk/test/java/text/Collator/Regression.java b/jdk/test/java/text/Collator/Regression.java new file mode 100644 index 00000000000..958ce29c524 --- /dev/null +++ b/jdk/test/java/text/Collator/Regression.java @@ -0,0 +1,940 @@ +/* + * 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 + * 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 4048446 4051866 4053636 4054238 4054734 4054736 4058613 4059820 4060154 + * 4062418 4065540 4066189 4066696 4076676 4078588 4079231 4081866 4087241 + * 4087243 4092260 4095316 4101940 4103436 4114076 4114077 4124632 4132736 + * 4133509 4139572 4141640 4179126 4179686 4244884 4663220 + * @library /java/text/testlib + * @summary Regression tests for Collation and associated classes + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - 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. +*/ + +import java.text.*; +import java.util.Locale; +import java.util.Vector; + + +public class Regression extends CollatorTest { + + public static void main(String[] args) throws Exception { + new Regression().run(args); + } + + // CollationElementIterator.reset() doesn't work + // + public void Test4048446() { + CollationElementIterator i1 = en_us.getCollationElementIterator(test1); + CollationElementIterator i2 = en_us.getCollationElementIterator(test1); + + while ( i1.next() != CollationElementIterator.NULLORDER ) { + } + i1.reset(); + + assertEqual(i1, i2); + } + + + // Collator -> rules -> Collator round-trip broken for expanding characters + // + public void Test4051866() throws ParseException { + // Build a collator containing expanding characters + RuleBasedCollator c1 = new RuleBasedCollator("< o " + +"& oe ,o\u3080" + +"& oe ,\u1530 ,O" + +"& OE ,O\u3080" + +"& OE ,\u1520" + +"< p ,P"); + + // Build another using the rules from the first + RuleBasedCollator c2 = new RuleBasedCollator(c1.getRules()); + + // Make sure they're the same + if (!c1.getRules().equals(c2.getRules())) { + errln("Rules are not equal"); + } + } + + // Collator thinks "black-bird" == "black" + // + public void Test4053636() { + if (en_us.equals("black-bird","black")) { + errln("black-bird == black"); + } + } + + + // CollationElementIterator will not work correctly if the associated + // Collator object's mode is changed + // + public void Test4054238() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + CollationElementIterator i1 = en_us.getCollationElementIterator(test3); + + c.setDecomposition(Collator.NO_DECOMPOSITION); + CollationElementIterator i2 = en_us.getCollationElementIterator(test3); + + // At this point, BOTH iterators should use NO_DECOMPOSITION, since the + // collator itself is in that mode + assertEqual(i1, i2); + } + + // Collator.IDENTICAL documented but not implemented + // + public void Test4054734() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + try { + c.setStrength(Collator.IDENTICAL); + } + catch (Exception e) { + errln("Caught " + e.toString() + " setting Collator.IDENTICAL"); + } + + String[] decomp = { + "\u0001", "<", "\u0002", + "\u0001", "=", "\u0001", + "A\u0001", ">", "~\u0002", // Ensure A and ~ are not compared bitwise + "\u00C0", "=", "A\u0300" // Decomp should make these equal + }; + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + compareArray(c, decomp); + + String[] nodecomp = { + "\u00C0", ">", "A\u0300" // A-grave vs. A combining-grave + }; + c.setDecomposition(Collator.NO_DECOMPOSITION); + compareArray(c, nodecomp); + } + + // Full Decomposition mode not implemented + // + public void Test4054736() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\uFB4f", "=", "\u05D0\u05DC", // Alef-Lamed vs. Alef, Lamed + }; + + compareArray(c, tests); + } + + // Collator.getInstance() causes an ArrayIndexOutofBoundsException for Korean + // + public void Test4058613() { + // Creating a default collator doesn't work when Korean is the default + // locale + + Locale oldDefault = Locale.getDefault(); + + Locale.setDefault( Locale.KOREAN ); + try { + Collator c = Collator.getInstance(); + + // Since the fix to this bug was to turn of decomposition for Korean collators, + // ensure that's what we got + if (c.getDecomposition() != Collator.NO_DECOMPOSITION) { + errln("Decomposition is not set to NO_DECOMPOSITION"); + } + } + finally { + Locale.setDefault(oldDefault); + } + } + + // RuleBasedCollator.getRules does not return the exact pattern as input + // for expanding character sequences + // + public void Test4059820() { + RuleBasedCollator c = null; + try { + c = new RuleBasedCollator("< a < b , c/a < d < z"); + } catch (ParseException e) { + errln("Exception building collator: " + e.toString()); + return; + } + if ( c.getRules().indexOf("c/a") == -1) { + errln("returned rules do not contain 'c/a'"); + } + } + + // MergeCollation::fixEntry broken for "& H < \u0131, \u0130, i, I" + // + public void Test4060154() { + RuleBasedCollator c = null; + try { + c = new RuleBasedCollator("< g, G < h, H < i, I < j, J" + + " & H < \u0131, \u0130, i, I" ); + } catch (ParseException e) { + errln("Exception building collator: " + e.toString()); + return; + } + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + + String[] tertiary = { + "A", "<", "B", + "H", "<", "\u0131", + "H", "<", "I", + "\u0131", "<", "\u0130", + "\u0130", "<", "i", + "\u0130", ">", "H", + }; + c.setStrength(Collator.TERTIARY); + compareArray(c, tertiary); + + String[] secondary = { + "H", "<", "I", + "\u0131", "=", "\u0130", + }; + c.setStrength(Collator.PRIMARY); + compareArray(c, secondary); + }; + + // Secondary/Tertiary comparison incorrect in French Secondary + // + public void Test4062418() throws ParseException { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "p\u00eache", "<", "p\u00e9ch\u00e9", // Comparing accents from end, p\u00e9ch\u00e9 is greater + }; + + compareArray(c, tests); + } + + // Collator.compare() method broken if either string contains spaces + // + public void Test4065540() { + if (en_us.compare("abcd e", "abcd f") == 0) { + errln("'abcd e' == 'abcd f'"); + } + } + + // Unicode characters need to be recursively decomposed to get the + // correct result. For example, + // u1EB1 -> \u0103 + \u0300 -> a + \u0306 + \u0300. + // + public void Test4066189() { + String test1 = "\u1EB1"; + String test2 = "a\u0306\u0300"; + + RuleBasedCollator c1 = (RuleBasedCollator) en_us.clone(); + c1.setDecomposition(Collator.FULL_DECOMPOSITION); + CollationElementIterator i1 = en_us.getCollationElementIterator(test1); + + RuleBasedCollator c2 = (RuleBasedCollator) en_us.clone(); + c2.setDecomposition(Collator.NO_DECOMPOSITION); + CollationElementIterator i2 = en_us.getCollationElementIterator(test2); + + assertEqual(i1, i2); + } + + // French secondary collation checking at the end of compare iteration fails + // + public void Test4066696() { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "\u00e0", "<", "\u01fa", // a-grave < A-ring-acute + }; + + compareArray(c, tests); + } + + + // Bad canonicalization of same-class combining characters + // + public void Test4076676() { + // These combining characters are all in the same class, so they should not + // be reordered, and they should compare as unequal. + String s1 = "A\u0301\u0302\u0300"; + String s2 = "A\u0302\u0300\u0301"; + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + if (c.compare(s1,s2) == 0) { + errln("Same-class combining chars were reordered"); + } + } + + + // RuleBasedCollator.equals(null) throws NullPointerException + // + public void Test4079231() { + try { + if (en_us.equals(null)) { + errln("en_us.equals(null) returned true"); + } + } + catch (Exception e) { + errln("en_us.equals(null) threw " + e.toString()); + } + } + + // RuleBasedCollator breaks on "< a < bb" rule + // + public void Test4078588() throws ParseException { + RuleBasedCollator rbc=new RuleBasedCollator("< a < bb"); + + int result = rbc.compare("a","bb"); + + if (result != -1) { + errln("Compare(a,bb) returned " + result + "; expected -1"); + } + } + + // Combining characters in different classes not reordered properly. + // + public void Test4081866() throws ParseException { + // These combining characters are all in different classes, + // so they should be reordered and the strings should compare as equal. + String s1 = "A\u0300\u0316\u0327\u0315"; + String s2 = "A\u0327\u0316\u0315\u0300"; + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + // Now that the default collators are set to NO_DECOMPOSITION + // (as a result of fixing bug 4114077), we must set it explicitly + // when we're testing reordering behavior. -- lwerner, 5/5/98 + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + + if (c.compare(s1,s2) != 0) { + errln("Combining chars were not reordered"); + } + } + + // string comparison errors in Scandinavian collators + // + public void Test4087241() { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance( + new Locale("da", "DK")); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "\u007a", "<", "\u00e6", // z < ae + "a\u0308", "<", "a\u030a", // a-unlaut < a-ring + "Y", "<", "u\u0308", // Y < u-umlaut + }; + + compareArray(c, tests); + } + + // CollationKey takes ignorable strings into account when it shouldn't + // + public void Test4087243() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] tests = { + "123", "=", "123\u0001", // 1 2 3 = 1 2 3 ctrl-A + }; + + compareArray(c, tests); + } + + // Mu/micro conflict + // Micro symbol and greek lowercase letter Mu should sort identically + // + public void Test4092260() { + Collator c = Collator.getInstance(new Locale("el", "")); + + // will only be equal when FULL_DECOMPOSITION is used + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\u00B5", "=", "\u03BC", + }; + + compareArray(c, tests); + } + + void Test4095316() { + Collator c = Collator.getInstance(new Locale("el", "GR")); + c.setStrength(Collator.TERTIARY); + // javadocs for RuleBasedCollator clearly specify that characters containing compatability + // chars MUST use FULL_DECOMPOSITION to get accurate comparisons. + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\u03D4", "=", "\u03AB", + }; + + compareArray(c, tests); + } + + public void Test4101940() { + try { + RuleBasedCollator c = new RuleBasedCollator("< a < b"); + CollationElementIterator i = c.getCollationElementIterator(""); + i.reset(); + + if (i.next() != i.NULLORDER) { + errln("next did not return NULLORDER"); + } + } + catch (Exception e) { + errln("Caught " + e ); + } + } + + // Collator.compare not handling spaces properly + // + public void Test4103436() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] tests = { + "file", "<", "file access", + "file", "<", "fileaccess", + }; + + compareArray(c, tests); + } + + // Collation not Unicode conformant with Hangul syllables + // + public void Test4114076() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + // + // With Canonical decomposition, Hangul syllables should get decomposed + // into Jamo, but Jamo characters should not be decomposed into + // conjoining Jamo + // + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + String[] test1 = { + "\ud4db", "=", "\u1111\u1171\u11b6", + }; + compareArray(c, test1); + + // Full decomposition result should be the same as canonical decomposition + // for all hangul. + c.setDecomposition(Collator.FULL_DECOMPOSITION); + compareArray(c, test1); + + } + + + // Collator.getCollationKey was hanging on certain character sequences + // + public void Test4124632() throws Exception { + Collator coll = Collator.getInstance(Locale.JAPAN); + + try { + coll.getCollationKey("A\u0308bc"); + } catch (OutOfMemoryError e) { + errln("Ran out of memory -- probably an infinite loop"); + } + } + + // sort order of french words with multiple accents has errors + // + public void Test4132736() { + Collator c = Collator.getInstance(Locale.FRANCE); + + String[] test1 = { + "e\u0300e\u0301", "<", "e\u0301e\u0300", + "e\u0300\u0301", ">", "e\u0301\u0300", + }; + compareArray(c, test1); + } + + // The sorting using java.text.CollationKey is not in the exact order + // + public void Test4133509() { + String[] test1 = { + "Exception", "<", "ExceptionInInitializerError", + "Graphics", "<", "GraphicsEnvironment", + "String", "<", "StringBuffer", + }; + compareArray(en_us, test1); + } + + // Collation with decomposition off doesn't work for Europe + // + public void Test4114077() { + // Ensure that we get the same results with decomposition off + // as we do with it on.... + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] test1 = { + "\u00C0", "=", "A\u0300", // Should be equivalent + "p\u00eache", ">", "p\u00e9ch\u00e9", + "\u0204", "=", "E\u030F", + "\u01fa", "=", "A\u030a\u0301", // a-ring-acute -> a-ring, acute + // -> a, ring, acute + "A\u0300\u0316", "<", "A\u0316\u0300", // No reordering --> unequal + }; + c.setDecomposition(Collator.NO_DECOMPOSITION); + compareArray(c, test1); + + String[] test2 = { + "A\u0300\u0316", "=", "A\u0316\u0300", // Reordering --> equal + }; + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + compareArray(c, test2); + } + + // Support for Swedish gone in 1.1.6 (Can't create Swedish collator) + // + public void Test4141640() { + // + // Rather than just creating a Swedish collator, we might as well + // try to instantiate one for every locale available on the system + // in order to prevent this sort of bug from cropping up in the future + // + Locale[] locales = Collator.getAvailableLocales(); + + for (int i = 0; i < locales.length; i++) { + try { + Collator c = Collator.getInstance(locales[i]); + } catch (Exception e) { + errln("Caught " + e + " creating collator for " + locales[i]); + } + } + } + + // getCollationKey throws exception for spanish text + // Cannot reproduce this bug on 1.2, however it DOES fail on 1.1.6 + // + public void Test4139572() { + // + // Code pasted straight from the bug report + // + // create spanish locale and collator + Locale l = new Locale("es", "es"); + Collator col = Collator.getInstance(l); + + // this spanish phrase kills it! + col.getCollationKey("Nombre De Objeto"); + } + + // RuleBasedCollator doesn't use getCollationElementIterator internally + // + public void Test4146160() throws ParseException { + // + // Use a custom collator class whose getCollationElementIterator + // methods increment a count.... + // + My4146160Collator.count = 0; + new My4146160Collator().getCollationKey("1"); + if (My4146160Collator.count < 1) { + errln("getCollationElementIterator not called"); + } + + My4146160Collator.count = 0; + new My4146160Collator().compare("1", "2"); + if (My4146160Collator.count < 1) { + errln("getCollationElementIterator not called"); + } + } + + static class My4146160Collator extends RuleBasedCollator { + public My4146160Collator() throws ParseException { + super(Regression.en_us.getRules()); + } + + public CollationElementIterator getCollationElementIterator( + String text) { + count++; + return super.getCollationElementIterator(text); + } + public CollationElementIterator getCollationElementIterator( + CharacterIterator text) { + count++; + return super.getCollationElementIterator(text); + } + + public static int count = 0; + }; + + // CollationElementIterator.previous broken for expanding char sequences + // + public void Test4179686() throws ParseException { + + // Create a collator with a few expanding character sequences in it.... + RuleBasedCollator coll = new RuleBasedCollator(en_us.getRules() + + " & ae ; \u00e4 & AE ; \u00c4" + + " & oe ; \u00f6 & OE ; \u00d6" + + " & ue ; \u00fc & UE ; \u00dc"); + + String text = "T\u00f6ne"; // o-umlaut + + CollationElementIterator iter = coll.getCollationElementIterator(text); + Vector elements = new Vector(); + int elem; + + // Iterate forward and collect all of the elements into a Vector + while ((elem = iter.next()) != iter.NULLORDER) { + elements.addElement(new Integer(elem)); + } + + // Now iterate backward and make sure they're the same + int index = elements.size() - 1; + while ((elem = iter.previous()) != iter.NULLORDER) { + int expect = ((Integer)elements.elementAt(index)).intValue(); + + if (elem != expect) { + errln("Mismatch at index " + index + + ": got " + Integer.toString(elem,16) + + ", expected " + Integer.toString(expect,16)); + } + index--; + } + } + + public void Test4244884() throws ParseException { + RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US); + coll = new RuleBasedCollator(coll.getRules() + + " & C < ch , cH , Ch , CH < cat < crunchy"); + + String[] testStrings = new String[] { + "car", + "cave", + "clamp", + "cramp", + "czar", + "church", + "catalogue", + "crunchy", + "dog" + }; + + for (int i = 1; i < testStrings.length; i++) { + if (coll.compare(testStrings[i - 1], testStrings[i]) >= 0) { + errln("error: \"" + testStrings[i - 1] + + "\" is greater than or equal to \"" + testStrings[i] + + "\"."); + } + } + } + + public void Test4179216() throws ParseException { + // you can position a CollationElementIterator in the middle of + // a contracting character sequence, yielding a bogus collation + // element + RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US); + coll = new RuleBasedCollator(coll.getRules() + + " & C < ch , cH , Ch , CH < cat < crunchy"); + String testText = "church church catcatcher runcrunchynchy"; + CollationElementIterator iter = coll.getCollationElementIterator( + testText); + + // test that the "ch" combination works properly + iter.setOffset(4); + int elt4 = CollationElementIterator.primaryOrder(iter.next()); + + iter.reset(); + int elt0 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(5); + int elt5 = CollationElementIterator.primaryOrder(iter.next()); + + if (elt4 != elt0 || elt5 != elt0) + errln("The collation elements at positions 0 (" + elt0 + "), 4 (" + + elt4 + "), and 5 (" + elt5 + ") don't match."); + + // test that the "cat" combination works properly + iter.setOffset(14); + int elt14 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(15); + int elt15 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(16); + int elt16 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(17); + int elt17 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(18); + int elt18 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(19); + int elt19 = CollationElementIterator.primaryOrder(iter.next()); + + if (elt14 != elt15 || elt14 != elt16 || elt14 != elt17 + || elt14 != elt18 || elt14 != elt19) + errln("\"cat\" elements don't match: elt14 = " + elt14 + ", elt15 = " + + elt15 + ", elt16 = " + elt16 + ", elt17 = " + elt17 + + ", elt18 = " + elt18 + ", elt19 = " + elt19); + + // now generate a complete list of the collation elements, + // first using next() and then using setOffset(), and + // make sure both interfaces return the same set of elements + iter.reset(); + + int elt = iter.next(); + int count = 0; + while (elt != CollationElementIterator.NULLORDER) { + ++count; + elt = iter.next(); + } + + String[] nextElements = new String[count]; + String[] setOffsetElements = new String[count]; + int lastPos = 0; + + iter.reset(); + elt = iter.next(); + count = 0; + while (elt != CollationElementIterator.NULLORDER) { + nextElements[count++] = testText.substring(lastPos, iter.getOffset()); + lastPos = iter.getOffset(); + elt = iter.next(); + } + count = 0; + for (int i = 0; i < testText.length(); ) { + iter.setOffset(i); + lastPos = iter.getOffset(); + elt = iter.next(); + setOffsetElements[count++] = testText.substring(lastPos, iter.getOffset()); + i = iter.getOffset(); + } + for (int i = 0; i < nextElements.length; i++) { + if (nextElements[i].equals(setOffsetElements[i])) { + logln(nextElements[i]); + } else { + errln("Error: next() yielded " + nextElements[i] + ", but setOffset() yielded " + + setOffsetElements[i]); + } + } + } + + public void Test4216006() throws Exception { + // rule parser barfs on "<\u00e0=a\u0300", and on other cases + // where the same token (after normalization) appears twice in a row + boolean caughtException = false; + try { + RuleBasedCollator dummy = new RuleBasedCollator("\u00e0= 0) { + errln("List out of order at element #" + i + ": " + + prettify(sortedList[i]) + " >= " + + prettify(sortedList[i + 1])); + } + } + } + + // CollationElementIterator set doesn't work propertly with next/prev + public void Test4663220() { + RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(Locale.US); + CharacterIterator stringIter = new StringCharacterIterator("fox"); + CollationElementIterator iter = collator.getCollationElementIterator(stringIter); + + int[] elements_next = new int[3]; + logln("calling next:"); + for (int i = 0; i < 3; ++i) { + logln("[" + i + "] " + (elements_next[i] = iter.next())); + } + + int[] elements_fwd = new int[3]; + logln("calling set/next:"); + for (int i = 0; i < 3; ++i) { + iter.setOffset(i); + logln("[" + i + "] " + (elements_fwd[i] = iter.next())); + } + + for (int i = 0; i < 3; ++i) { + if (elements_next[i] != elements_fwd[i]) { + errln("mismatch at position " + i + + ": " + elements_next[i] + + " != " + elements_fwd[i]); + } + } + } + + //------------------------------------------------------------------------ + // Internal utilities + // + private void compareArray(Collator c, String[] tests) { + for (int i = 0; i < tests.length; i += 3) { + + int expect = 0; + if (tests[i+1].equals("<")) { + expect = -1; + } else if (tests[i+1].equals(">")) { + expect = 1; + } else if (tests[i+1].equals("=")) { + expect = 0; + } else { + expect = Integer.decode(tests[i+1]).intValue(); + } + + int result = c.compare(tests[i], tests[i+2]); + if (sign(result) != sign(expect)) + { + errln( i/3 + ": compare(" + prettify(tests[i]) + + " , " + prettify(tests[i+2]) + + ") got " + result + "; expected " + expect); + } + else + { + // Collator.compare worked OK; now try the collation keys + CollationKey k1 = c.getCollationKey(tests[i]); + CollationKey k2 = c.getCollationKey(tests[i+2]); + + result = k1.compareTo(k2); + if (sign(result) != sign(expect)) { + errln( i/3 + ": key(" + prettify(tests[i]) + + ").compareTo(key(" + prettify(tests[i+2]) + + ")) got " + result + "; expected " + expect); + + errln(" " + prettify(k1) + " vs. " + prettify(k2)); + } + } + } + } + + private static final int sign(int i) { + if (i < 0) return -1; + if (i > 0) return 1; + return 0; + } + + + static RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US); + + String test1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?"; + String test2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?"; + String test3 = "a\u00FCbeck Gr\u00F6\u00DFe L\u00FCbeck"; +} diff --git a/jdk/test/java/text/Collator/SpanishTest.java b/jdk/test/java/text/Collator/SpanishTest.java new file mode 100644 index 00000000000..fab4ef0d66b --- /dev/null +++ b/jdk/test/java/text/Collator/SpanishTest.java @@ -0,0 +1,106 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test Spanish Collation + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - 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. +*/ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class SpanishTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new SpanishTest().run(args); + } + + /* + * TestPrimary() + */ + private static final String[] primarySourceData = { + "alias", + "acHc", + "acc", + "Hello" + }; + + private static final String[] primaryTargetData = { + "allias", + "aCHc", + "aCHc", + "hellO" + }; + + private static final int[] primaryResults = { + -1, 0, -1, 0 + }; + + /* + * TestTertiary() + */ + private static final String[] tertiarySourceData = { + "alias", + "Elliot", + "Hello", + "acHc", + "acc" + }; + + private static final String[] tertiaryTargetData = { + "allias", + "Emiot", + "hellO", + "aCHc", + "aCHc" + }; + + private static final int[] tertiaryResults = { + -1, -1, 1, -1, -1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("es", "ES", "")); +} diff --git a/jdk/test/java/text/Collator/SurrogatesTest.java b/jdk/test/java/text/Collator/SurrogatesTest.java new file mode 100644 index 00000000000..87df904e882 --- /dev/null +++ b/jdk/test/java/text/Collator/SurrogatesTest.java @@ -0,0 +1,117 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test Supplementary Character Collation + */ + +import java.text.Collator; +import java.text.RuleBasedCollator; + +// Quick dummy program for printing out test results +public class SurrogatesTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new SurrogatesTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "A\ud800\udc04BCD" + }; + + private static final String[] primaryTargetData = { + "A\ud800\udc05BCD" + }; + + private static final int[] primaryResults = { + 0 + }; + + /* + * Data for TestTertiary() + */ + private static final String[] tertiarySourceData = { + "ABCD", + "ABCD", + "A\ud800\udc00CD", + "WXYZ", + "WXYZ", + "AFEM", + "FGM", + "BB", + "BB" + }; + + private static final String[] tertiaryTargetData = { + "A\ud800\udc00CD", + "AB\ud800\udc00D", + "A\ud800\udc01CD", + "W\ud800\udc0aYZ", + "W\ud800\udc0bYZ", + "A\ud800\udc08M", + "\ud800\udc08M", + "\ud800\udc04\ud800\udc02", + "\ud800\udc04\ud800\udc05" + }; + + private static final int[] tertiaryResults = { + -1, 1, 1, 1, -1, -1, -1, -1, 1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private Collator getCollator() { + RuleBasedCollator base = (RuleBasedCollator)Collator.getInstance(); + String rule = base.getRules(); + try { + return new RuleBasedCollator(rule + + "&B < \ud800\udc01 < \ud800\udc00" + + ", \ud800\udc02, \ud800\udc03" + + "; \ud800\udc04, \ud800\udc05" + + "< \ud800\udc06 < \ud800\udc07" + + "&FE < \ud800\udc08" + + "&PE, \ud800\udc09" + + "&Z < \ud800\udc0a < \ud800\udc0b < \ud800\udc0c" + + "&\ud800\udc0a < x, X" + + "&A < \ud800\udc04\ud800\udc05"); + } catch (Exception e) { + errln("Failed to create new RulebasedCollator object"); + return null; + } + } + + private Collator myCollation = getCollator(); +} diff --git a/jdk/test/java/text/Collator/Test4401726.java b/jdk/test/java/text/Collator/Test4401726.java new file mode 100644 index 00000000000..6f9e9ed945e --- /dev/null +++ b/jdk/test/java/text/Collator/Test4401726.java @@ -0,0 +1,98 @@ +/* + * 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 + * 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 4401726 + * @author John O'Conner + * @library /java/text/testlib + * @summary Regression tests for Collation and associated classes + */ + + +import java.text.*; +import java.util.Locale; +import java.util.Vector; + +public class Test4401726 extends CollatorTest { + + public static void main(String[] args) throws Exception { + new Test4401726().run(args); + } + + public void TestSetOffSet() { + + int[] expected = {0, -1, 65536}; + int[] actual = new int[expected.length]; + + try { + String rule = "< a, A < d; D"; + + RuleBasedCollator rbc = new RuleBasedCollator(rule); + String str = "aD"; + CollationElementIterator iterator = + rbc.getCollationElementIterator(str); + + iterator.setOffset(0); + actual[0] = iterator.getOffset(); + actual[1] = iterator.previous(); + iterator.setOffset(0); + actual[2] = iterator.next(); + + if (compareArray(expected, actual) == false) { + errln("Failed."); + } + + str = "a"; + iterator = rbc.getCollationElementIterator(str); + iterator.setOffset(0); + actual[0] = iterator.getOffset(); + actual[1] = iterator.previous(); + iterator.setOffset(0); + actual[2] = iterator.next(); + + if (compareArray(expected, actual) == false) { + errln("Failed."); + } + + } catch (ParseException e) { + errln("Unexpected ParseException: " + e); + } + + + } + + boolean compareArray(int[] expected, int[] actual) { + boolean retVal = false; + if (expected.length == actual.length) { + int errors = 0; + for(int x=0; x< expected.length; ++x) { + if (expected[x] != actual[x]) { + ++errors; + } + } + if (errors == 0) retVal = true; + } + return retVal; + } +} diff --git a/jdk/test/java/text/Collator/ThaiTest.java b/jdk/test/java/text/Collator/ThaiTest.java new file mode 100644 index 00000000000..7d643446434 --- /dev/null +++ b/jdk/test/java/text/Collator/ThaiTest.java @@ -0,0 +1,156 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test Thai Collation + */ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * + * This software is the proprietary information of Oracle. + * Use is subject to license terms. + * + */ + +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; + +public class ThaiTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new ThaiTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "\u0e01\u0e01", + "\u0e07\u0e42\u0e01\u0e49", + "\u0e10\u0e34\u0e19", + "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32", + "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22", + "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22", + "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30", + "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07", + "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c", + "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07", + "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25", + "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c", + "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21", + "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19", + "\u0e2a\u0e49\u0e28\u0e36\u0e01", + "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27", + "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19", + "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19", + "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19", + "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07", + "\u0e2a\u0e49\u0e44\u0e01\u0e48", + "\u0e2b", + "\u0e2b\u0e0b\u0e2d\u0e07", + "\u0e2b\u0e19", + "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32", + "\u0e2b\u0e21", + "\u0e2b\u0e21\u0e17\u0e2d\u0e07", + "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14", + "\u0e2b\u0e21\u0e49", + "\u0e2b\u0e23\u0e13\u0e22\u0e4c", + "\u0e2b\u0e25", + "\u0e2b\u0e25\u0e19\u0e49\u0e33", + "\u0e2b\u0e25\u0e48", + "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19", + "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b", + "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07", + "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a", + "\u0e2b\u0e49", + "\u0e2d", + "\u0e2d\u0e49", + "\u0e2e\u0e42\u0e25", + "\u0e2e\u0e44\u0e1f", + "\u0e2e\u0e49" + }; + + private static final String[] primaryTargetData = { + "\u0e01\u0e01", + "\u0e07\u0e42\u0e01\u0e49", + "\u0e10\u0e34\u0e19", + "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32", + "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22", + "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22", + "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30", + "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07", + "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c", + "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07", + "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25", + "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c", + "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21", + "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19", + "\u0e2a\u0e49\u0e28\u0e36\u0e01", + "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27", + "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19", + "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19", + "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19", + "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07", + "\u0e2a\u0e49\u0e44\u0e01\u0e48", + "\u0e2b", + "\u0e2b\u0e0b\u0e2d\u0e07", + "\u0e2b\u0e19", + "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32", + "\u0e2b\u0e21", + "\u0e2b\u0e21\u0e17\u0e2d\u0e07", + "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14", + "\u0e2b\u0e21\u0e49", + "\u0e2b\u0e23\u0e13\u0e22\u0e4c", + "\u0e2b\u0e25", + "\u0e2b\u0e25\u0e19\u0e49\u0e33", + "\u0e2b\u0e25\u0e48", + "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19", + "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b", + "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07", + "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a", + "\u0e2b\u0e49", + "\u0e2d", + "\u0e2d\u0e49", + "\u0e2e\u0e42\u0e25", + "\u0e2e\u0e44\u0e1f", + "\u0e2e\u0e49" + }; + + private static final int[] primaryResults = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("th")); +} diff --git a/jdk/test/java/text/Collator/TurkishTest.java b/jdk/test/java/text/Collator/TurkishTest.java new file mode 100644 index 00000000000..f83ef228e06 --- /dev/null +++ b/jdk/test/java/text/Collator/TurkishTest.java @@ -0,0 +1,118 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test Turkish Collation + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - 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. +*/ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class TurkishTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new TurkishTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "\u00FCoid", + "vo\u0131d", + "idea", + "Idea", + "\u0130dea" + }; + + private static final String[] primaryTargetData = { + "void", + "void", + "Idea", + "\u0130dea", + "\u0131dea" + }; + + private static final int[] primaryResults = { + -1, -1, 1, -1, 1 + }; + + /* + * Data for TestTertiary() + */ + private static final String[] tertiarySourceData = { + "s\u0327", + "v\u00E4t", + "old", + "\u00FCoid", + "h\u011Ealt", + "stres\u015E", + "vo\u0131d", + "idea", + "idea", + "\u0131dea" + }; + + private static final String tertiaryTargetData[] = { + "u\u0308", + "vbt", + "\u00D6ay", + "void", + "halt", + "\u015Etre\u015Es", + "void", + "Idea", + "\u0130dea", + "Idea" + }; + + private static final int[] tertiaryResults = { + -1, -1, -1, -1, 1, -1, -1, 1, -1, -1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("tr", "TR", "")); +} diff --git a/jdk/test/java/text/Collator/VietnameseTest.java b/jdk/test/java/text/Collator/VietnameseTest.java new file mode 100644 index 00000000000..faa4921073c --- /dev/null +++ b/jdk/test/java/text/Collator/VietnameseTest.java @@ -0,0 +1,364 @@ +/* + * 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 + * 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 4932968 5015215 + * @library /java/text/testlib + * @summary test Vietnamese Collation + */ + +/* + ******************************************************************************* + * (C) Copyright IBM Corp. 1996-2003 - All Rights Reserved * + * * + * The original version of this source code and documentation is copyrighted * + * and owned by IBM, These materials are provided under terms of a License * + * Agreement between IBM and Sun. This technology is protected by multiple * + * US and International patents. This notice and attribution to IBM may not * + * to removed. * + ******************************************************************************* + */ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class VietnameseTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new VietnameseTest().run(args); + } + + private final static String testPS[] = { + "a", + "a", + "\u00c2", + "Cz", + "d", + "e", + "e", + "\u1ec7", + "gz", + "i", + "kz", + "nz", + "nh", + "o", + "o", + "\u01a0", + "pz", + "tz", + "tr", + "u", + "u", + "y" + }; + + private final static String testPT[] = { + "\u00e0", + "\u0102", + "\u0102", + "Ch", + "\u0110", + "\u0111", + "\u1eb9", + "\u1eb9", + "gi", + "\u0128", + "kh", + "ng", + "ng", + "\u00f2", + "\u00f4", + "\u00f4", + "ph", + "th", + "th", + "\u1ee5", + "\u01b0", + "\u1ef4" + }; + + private final static int testPR[] = { + 0, + -1, + 1, + 1, + -1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 0, + -1, + 1, + 1, + 1, + 1, + 0, + -1, + 0 + }; + + private final static String testT[] = { + "a", + "A", + "\u00e0", + "\u00c0", + "\u1ea3", + "\u1ea2", + "\u00e3", + "\u00c3", + "\u00e1", + "\u00c1", + "\u1ea1", + "\u1ea0", + "\u0103", + "\u0102", + "\u1eb1", + "\u1eb0", + "\u1eb3", + "\u1eb2", + "\u1eb5", + "\u1eb4", + "\u1eaf", + "\u1eae", + "\u1eb7", + "\u1eb6", + "\u00e2", + "\u00c2", + "\u1ea7", + "\u1ea6", + "\u1ea9", + "\u1ea8", + "\u1eab", + "\u1eaa", + "\u1ea5", + "\u1ea4", + "\u1ead", + "\u1eac", + "b", + "B", + "c", + "C", + "ch", + "Ch", + "CH", + "d", + "D", + "\u0111", + "\u0110", + "e", + "E", + "\u00e8", + "\u00c8", + "\u1ebb", + "\u1eba", + "\u1ebd", + "\u1ebc", + "\u00e9", + "\u00c9", + "\u1eb9", + "\u1eb8", + "\u00ea", + "\u00ca", + "\u1ec1", + "\u1ec0", + "\u1ec3", + "\u1ec2", + "\u1ec5", + "\u1ec4", + "\u1ebf", + "\u1ebe", + "\u1ec7", + "\u1ec6", + "f", + "F", + "g", + "G", + "gi", + "Gi", + "GI", + "gz", + "h", + "H", + "i", + "I", + "\u00ec", + "\u00cc", + "\u1ec9", + "\u1ec8", + "\u0129", + "\u0128", + "\u00ed", + "\u00cd", + "\u1ecb", + "\u1eca", + "j", + "J", + "k", + "K", + "kh", + "Kh", + "KH", + "kz", + "l", + "L", + "m", + "M", + "n", + "N", + "ng", + "Ng", + "NG", + "ngz", + "nh", + "Nh", + "NH", + "nz", + "o", + "O", + "\u00f2", + "\u00d2", + "\u1ecf", + "\u1ece", + "\u00f5", + "\u00d5", + "\u00f3", + "\u00d3", + "\u1ecd", + "\u1ecc", + "\u00f4", + "\u00d4", + "\u1ed3", + "\u1ed2", + "\u1ed5", + "\u1ed4", + "\u1ed7", + "\u1ed6", + "\u1ed1", + "\u1ed0", + "\u1ed9", + "\u1ed8", + "\u01a1", + "\u01a0", + "\u1edd", + "\u1edc", + "\u1edf", + "\u1ede", + "\u1ee1", + "\u1ee0", + "\u1edb", + "\u1eda", + "\u1ee3", + "\u1ee2", + "p", + "P", + "ph", + "Ph", + "PH", + "pz", + "q", + "Q", + "r", + "R", + "s", + "S", + "t", + "T", + "th", + "Th", + "TH", + "thz", + "tr", + "Tr", + "TR", + "tz", + "u", + "U", + "\u00f9", + "\u00d9", + "\u1ee7", + "\u1ee6", + "\u0169", + "\u0168", + "\u00fa", + "\u00da", + "\u1ee5", + "\u1ee4", + "\u01b0", + "\u01af", + "\u1eeb", + "\u1eea", + "\u1eed", + "\u1eec", + "\u1eef", + "\u1eee", + "\u1ee9", + "\u1ee8", + "\u1ef1", + "\u1ef0", + "v", + "V", + "w", + "W", + "x", + "X", + "y", + "Y", + "\u1ef3", + "\u1ef2", + "\u1ef7", + "\u1ef6", + "\u1ef9", + "\u1ef8", + "\u00fd", + "\u00dd", + "\u1ef5", + "\u1ef4", + "z", + "Z" + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, testPS, testPT, testPR); + } + + public void TestTertiary() { + int testLength = testT.length; + + myCollation.setStrength(Collator.TERTIARY); + for (int i = 0; i < testLength - 1; i++) { + for (int j = i+1; j < testLength; j++) { + doTest(myCollation, testT[i], testT[j], -1); + } + } + } + + private final Collator myCollation = Collator.getInstance(new Locale("vi", "VN")); +} diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt new file mode 100644 index 00000000000..23c4e4607fc --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt @@ -0,0 +1,44 @@ +# +# Copyright (c) 1999, 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. +# + +# Hex dump of a serialized ChiceFormat for Bug4185732Test. + +aced0005737200166a6176612e746578742e43686f696365466f726d617418e9 +c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61 +76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400 +025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3 +bf137d07e803000b5a000c67726f7570696e67557365644200116d6178467261 +6374696f6e4469676974734200106d6178496e74656765724469676974734900 +156d6178696d756d4672616374696f6e4469676974734900146d6178696d756d +496e74656765724469676974734200116d696e4672616374696f6e4469676974 +734200106d696e496e74656765724469676974734900156d696e696d756d4672 +616374696f6e4469676974734900146d696e696d756d496e7465676572446967 +6974735a00107061727365496e74656765724f6e6c7949001573657269616c56 +657273696f6e4f6e53747265616d787200106a6176612e746578742e466f726d +6174fbd8bc12e90f184302000078700103280000000300000028000100000000 +00000001000000000178757200135b4c6a6176612e6c616e672e537472696e67 +3badd256e7e91d7b470200007870000000067400034d6f6e7400035475657400 +0357656474000454687572740003467269740003536174757200025b443ea68c +14ab635a1e0200007870000000073ff000000000000040000000000000004008 +000000000000401000000000000040140000000000004018000000000000401c +000000000000 diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java new file mode 100644 index 00000000000..06c5dea1f53 --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1999, 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 4185732 + * @library /java/text/testlib + * @build Bug4185732Test IntlTest HexDumpReader + * @run main Bug4185732Test + * @summary test that ChoiceFormat invariants are preserved across serialization + */ +/* + * + * + * (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.util.*; +import java.io.*; +import java.text.ChoiceFormat; + +/** + * A Locale can never contains language codes of he, yi or id. + */ +public class Bug4185732Test extends IntlTest { + public static void main(String[] args) throws Exception { + if (args.length == 1 && args[0].equals("prepTest")) { + prepTest(); + } else { + new Bug4185732Test().run(args); + } + } + + public void testIt() throws Exception { + try { + final ObjectInputStream in + = new ObjectInputStream(HexDumpReader.getStreamFromHexDump("Bug4185732.ser.txt")); + final ChoiceFormat loc = (ChoiceFormat)in.readObject(); + if (loc.getFormats().length != loc.getLimits().length) { + errln("ChoiceFormat did not properly check stream"); + } else { + //for some reason, the data file was VALID. This test + //requires a corrupt data file the format and limit + //arrays are of different length. + errln("Test data file was not properly created"); + } + } catch (InvalidObjectException e) { + //this is what we want to have happen + } catch (Exception e) { + errln(e.toString()); + } + } + + /** + * Create a data file for this test. The data file must be corrupted by hand. + */ + private static void prepTest() { + try { + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream("Bug4185732.ser")); + final double[] limits = {1,2,3,4,5,6,7}; + final String[] formats = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}; + final ChoiceFormat fmt = new ChoiceFormat(limits, formats); + out.writeObject(fmt); + out.close(); + System.out.println("You must invalidate the output file before running the test"); + System.out.println("by modifying the length of one of the array"); + } catch (Exception e) { + System.out.println(e); + } + } +} diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java b/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java new file mode 100644 index 00000000000..d211bb6976e --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java @@ -0,0 +1,69 @@ +/* + * 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 + * 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 4387255 + * @summary Verifies that ChoiceFormat can handle large numbers of choices + */ + +import java.text.ChoiceFormat; + +public class Bug4387255 { + + private static final double[] doubles = { + 0, 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, 32, 33, 34, 35}; + + private static final String[] strings = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", + "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", + "U", "V", "W", "X", "Y", "Z"}; + + private static final String pattern = + "0#0|1#1|2#2|3#3|4#4|5#5|6#6|7#7|8#8|9#9" + + "|10#A|11#B|12#C|13#D|14#E|15#F|16#G|17#H|18#I|19#J" + + "|20#K|21#L|22#M|23#N|24#O|25#P|26#Q|27#R|28#S|29#T" + + "|30#U|31#V|32#W|33#X|34#Y|35#Z"; + + public static void main(String[] args) throws Exception { + ChoiceFormat choiceFormat1 = new ChoiceFormat(doubles, strings); + ChoiceFormat choiceFormat2 = new ChoiceFormat(pattern); + if (!choiceFormat1.equals(choiceFormat2)) { + System.out.println("choiceFormat1: " + choiceFormat1.toPattern()); + System.out.println("choiceFormat2: " + choiceFormat2.toPattern()); + throw new RuntimeException(); + } + + for (int i = 0; i < doubles.length; i++) { + String result = choiceFormat2.format(doubles[i]); + if (!result.equals(strings[i])) { + throw new RuntimeException("Wrong format result - expected " + + strings[i] + ", got " + result); + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4322313.java b/jdk/test/java/text/Format/DateFormat/Bug4322313.java new file mode 100644 index 00000000000..19987022664 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4322313.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2001, 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 4322313 4833268 6302990 6304305 + * @library /java/text/testlib + * @summary Make sure that new implementation for + * SimpleDateFormat.parse('z' or 'Z') and format('z' or 'Z') work correctly. + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +public class Bug4322313 extends IntlTest { + + public void Test4322313() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + boolean err = false; + long mpm = 60 * 1000; /* Milliseconds per a minute */ + + Locale[] locs = {Locale.US, Locale.JAPAN, Locale.UK, new Locale("ar")}; + + String[] formats = { + "z", + "Z", + }; + + Object[][] valids = { + /* given ID offset format('z'), ('Z') index */ + {"GMT+03:04", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(9)}, + {"GMT+13:42", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(9)}, + {"GMT+00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, + {"GMT+1:11", new Long(-71 * mpm), "GMT+01:11", "+0111", new Integer(8)}, + {"GMT +13:42", new Long(0), "GMT", "+0000", new Integer(3)}, + {" GMT", new Long(0), "GMT", "+0000", new Integer(4)}, + {"+0304", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(5)}, + {"+1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(5)}, + {"+0000", new Long(0), "GMT+00:00", "+0000", new Integer(5)}, + {" +1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(6)}, + /* ISO-LATIN-1 digits */ + {"GMT+\u0030\u0031:\u0032\u0033", new Long(-83 * mpm), "GMT+01:23", "+0123", new Integer(9)}, + + /* In fact, this test case is skipped because TimeZone class can't + * recognize TimeZone IDs like "+00234" or "-00234". + */ + {"+00234", new Long(-23 * mpm), "GMT+00:23", "+0023", new Integer(5)}, + + {"GMT-03:04", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(9)}, + {"GMT-13:42", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(9)}, + {"GMT-00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, + {"GMT-1:11", new Long(71 * mpm), "GMT-01:11", "-0111", new Integer(8)}, + {"GMT -13:42", new Long(0), "GMT", "+0000", new Integer(3)}, + {"-0304", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(5)}, + {"-1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(5)}, + {" -1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(6)}, + /* ISO-LATIN-1 digits */ + {"GMT-\u0030\u0031:\u0032\u0033", new Long(83 * mpm), "GMT-01:23", "-0123", new Integer(9)}, + /* In fact, this test case is skipped because TimeZone class can't + * recognize TimeZone IDs like "+00234" or "-00234". + */ + {"-00234", new Long(23 * mpm), "GMT+00:23", "-0023", new Integer(5)}, + }; + + Object[][] invalids = { + /* given ID error index */ + {"GMT+8", new Integer(5)}, + {"GMT+18", new Integer(6)}, + {"GMT+208", new Integer(6)}, + {"GMT+0304", new Integer(6)}, + {"GMT+42195", new Integer(5)}, + {"GMT+5:8", new Integer(7)}, + {"GMT+23:60", new Integer(8)}, + {"GMT+11:1", new Integer(8)}, + {"GMT+24:13", new Integer(5)}, + {"GMT+421:950", new Integer(5)}, + {"GMT+0a:0A", new Integer(5)}, + {"GMT+ 13:42", new Integer(4)}, + {"GMT+13 :42", new Integer(6)}, + {"GMT+13: 42", new Integer(7)}, + {"GMT+-13:42", new Integer(4)}, + {"G M T", new Integer(0)}, + {"+8", new Integer(2)}, + {"+18", new Integer(3)}, + {"+208", new Integer(4)}, + {"+2360", new Integer(4)}, + {"+2413", new Integer(2)}, + {"+42195", new Integer(2)}, + {"+0AbC", new Integer(2)}, + {"+ 1342", new Integer(1)}, + {"+-1342", new Integer(1)}, + {"1342", new Integer(0)}, + /* Arabic-Indic digits */ + {"GMT+\u0660\u0661:\u0662\u0663", new Integer(4)}, + /* Extended Arabic-Indic digits */ + {"GMT+\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, + /* Devanagari digits */ + {"GMT+\u0966\u0967:\u0968\u0969", new Integer(4)}, + /* Fullwidth digits */ + {"GMT+\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, + + {"GMT-8", new Integer(5)}, + {"GMT-18", new Integer(6)}, + {"GMT-208", new Integer(6)}, + {"GMT-0304", new Integer(6)}, + {"GMT-42195", new Integer(5)}, + {"GMT-5:8", new Integer(7)}, + {"GMT-23:60", new Integer(8)}, + {"GMT-11:1", new Integer(8)}, + {"GMT-24:13", new Integer(5)}, + {"GMT-421:950", new Integer(5)}, + {"GMT-0a:0A", new Integer(5)}, + {"GMT- 13:42", new Integer(4)}, + {"GMT-13 :42", new Integer(6)}, + {"GMT-13: 42", new Integer(7)}, + {"GMT-+13:42", new Integer(4)}, + {"-8", new Integer(2)}, + {"-18", new Integer(3)}, + {"-208", new Integer(4)}, + {"-2360", new Integer(4)}, + {"-2413", new Integer(2)}, + {"-42195", new Integer(2)}, + {"-0AbC", new Integer(2)}, + {"- 1342", new Integer(1)}, + {"--1342", new Integer(1)}, + {"-802", new Integer(2)}, + /* Arabic-Indic digits */ + {"GMT-\u0660\u0661:\u0662\u0663", new Integer(4)}, + /* Extended Arabic-Indic digits */ + {"GMT-\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, + /* Devanagari digits */ + {"GMT-\u0966\u0967:\u0968\u0969", new Integer(4)}, + /* Fullwidth digits */ + {"GMT-\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, + }; + + try { + for (int i=0; i < locs.length; i++) { + Locale.setDefault(locs[i]); + + for (int j=0; j < formats.length; j++) { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + SimpleDateFormat sdf = new SimpleDateFormat(formats[j]); + Date date; + + /* Okay case */ + for (int k=0; k < valids.length; k++) { + ParsePosition pos = new ParsePosition(0); + try { + date = sdf.parse((String)valids[k][0], pos); + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] Unexpected Exception occurred: " + e); + continue; + } + + int offset = pos.getIndex(); + if (offset != ((Integer)valids[k][4]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] invalid index: expected:" + valids[k][4] + + ", got:" + offset); + } + + if (date.getTime() != ((Long)valids[k][1]).longValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][1] + + ", got:" + date.getTime() + ", " + date); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][1] + + ", got:" + date.getTime() + ", " + date); +*/ + + try { + date = sdf.parse((String)valids[k][0]); + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] Unexpected Exception occurred: " + e); + continue; + } + + /* Since TimeZone.getTimeZone() don't treat + * "+00234" or "-00234" as a valid ID, skips. + */ + if (((String)valids[k][0]).length() == 6) { + continue; + } + + /* Since TimeZone.getTimeZone() don't recognize + * +hhmm/-hhmm format, add "GMT" as prefix. + */ + sdf.setTimeZone(TimeZone.getTimeZone( + (((((String)valids[k][0]).charAt(0) != 'G') ? + "GMT" : "") + valids[k][0]))); + StringBuffer s = new StringBuffer(); + sdf.format(date, s, new FieldPosition(0)); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + + String got = s.toString(); + String expected = (String)valids[k][2+j]; + if (!got.equals(expected) && + // special case to allow the difference between + // DateFormatSymbols.getZoneStrings() and + // TimeZone.getDisplayName() for "GMT+-00:00" + !(got.equals("GMT-00:00") && + expected.equals("GMT+00:00"))) { + err = true; + System.err.println("\tFormat Error [Locale=" + + Locale.getDefault() + ", " + + formats[j] + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][2+j] + + ", got:" + s + ", " + date); + } else { +/* + logln("\tFormat Okay [Locale=" + + Locale.getDefault() + ", " + + formats[j] + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][2+j] + + ", got:" + s + ", " + date); +*/ + } + } + } + + /* Error case 1 + * using SimpleDateFormat.parse(String, ParsePosition) + */ + for (int k=0; k < invalids.length; k++) { + ParsePosition pos = new ParsePosition(0); + try { + date = sdf.parse((String)invalids[k][0], pos); + if (date != null) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] expected:null , got:" + date); + } + int offset = pos.getErrorIndex(); + if (offset != ((Integer)invalids[k][1]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] incorrect offset. expected:" + + invalids[k][1] + ", got: " + offset); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] correct offset: " + offset); +*/ + } + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Unexpected Exception occurred: " + e); + } + } + + /* Error case 2 + * using DateFormat.parse(String) + */ + boolean correctParseException = false; + for (int k=0; k < invalids.length; k++) { + try { + date = sdf.parse((String)invalids[k][0]); + } + catch (ParseException e) { + correctParseException = true; + int offset = e.getErrorOffset(); + if (offset != ((Integer)invalids[k][1]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception occurred with an incorrect offset. expected:" + + invalids[k][1] + ", got: " + offset); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception occurred with an correct offset: " + + offset); +*/ + } + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Invalid exception occurred: " + e); + } + finally { + if (!correctParseException) { + err = true; + System.err.println("\tParse Error: [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception didn't occur."); + } + } + } + } + } + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + if (err) { + errln("SimpleDateFormat.parse()/format() test failed"); + } + } + } + + public static void main(String[] args) throws Exception { + new Bug4322313().run(args); + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4407042.java b/jdk/test/java/text/Format/DateFormat/Bug4407042.java new file mode 100644 index 00000000000..8cc557e5a97 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4407042.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001, 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 4407042 + * @summary Make sure that cloned SimpleDateFormat objects work + * independently in multiple threads. + * @run main Bug4407042 10 + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +// Usage: java Bug4407042 [duration] +public class Bug4407042 { + + static final String TIME_STRING = "2000/11/18 00:01:00"; + static final long UTC_LONG = 974534460000L; + static SimpleDateFormat masterFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + static boolean runrun = true; + static int duration = 100; + + void test() { + Locale locale = Locale.getDefault(); + if (locale.equals(new Locale("th", "TH")) || + locale.equals(new Locale("hi", "IN"))) { + return; + } + + masterFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); + DateParseThread d1 = new DateParseThread(); + DateFormatThread d2 = new DateFormatThread(); + d1.start(); + d2.start(); + int n = Thread.activeCount(); + boolean failed = false; + + for (int i = 0; i < duration; i++) { + try { + Thread.sleep(1000); + if (Thread.activeCount() != n) { + failed = true; + break; + } + } catch (InterruptedException e) { + } + } + runrun = false; + try { + d1.join(); + d2.join(); + } catch (InterruptedException e) { + } + if (failed) { + throw new RuntimeException("Failed"); + } + } + + synchronized static SimpleDateFormat getFormatter() { + return (SimpleDateFormat) masterFormat.clone(); + } + + static class DateParseThread extends Thread { + public void run() { + SimpleDateFormat sdf = getFormatter(); + Calendar cal = null; + + try { + int i = 0; + while (runrun) { + Date date =sdf.parse(TIME_STRING); + long t = date.getTime(); + i++; + if (t != UTC_LONG) { + throw new RuntimeException("Parse Error: " + i + + " (" + sdf.format(date) + ") " + t + + " != " + UTC_LONG); + } + } + } catch (ParseException e) { + e.printStackTrace(); + throw new RuntimeException("Parse Error"); + } + } + } + + static class DateFormatThread extends Thread { + public void run () { + SimpleDateFormat sdf = getFormatter(); + Calendar cal = null; + + int i = 0; + while (runrun) { + i++; + String s = sdf.format(new Date(UTC_LONG)); + if (!s.equals(TIME_STRING)) { + throw new RuntimeException("Format Error: " + i + " " + + s + " != " + TIME_STRING); + } + } + } + } + + public static void main (String[] args) { + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + new Bug4407042().test(); + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4736959.java b/jdk/test/java/text/Format/DateFormat/Bug4736959.java new file mode 100644 index 00000000000..cdb9cad20b4 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4736959.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002, 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 4736959 + * @summary Make sure to parse "PM" (only) and produce the correct value. + */ + +import java.text.*; +import java.util.*; + +public class Bug4736959 { + /** + * 4736959: JSpinner won't work for AM/PM field + */ + public static void main(String[] args) { + SimpleDateFormat f = new SimpleDateFormat("a", Locale.US); + + Date d1 = f.parse("AM", new ParsePosition(0)); + System.out.println("d1: " + d1); + if (d1.getHours() != 0) { + throw new RuntimeException("Parsing \"AM\": expected 0 (midnight), got " + + d1.getHours()); + } + Date d2 = f.parse("PM", new ParsePosition(0)); + System.out.println("d2: " + d2); + if (d2.getHours() != 12) { + throw new RuntimeException("Parsing \"PM\": expected 12 (noon), got " + + d2.getHours()); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4845901.java b/jdk/test/java/text/Format/DateFormat/Bug4845901.java new file mode 100644 index 00000000000..8ed8bd47648 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4845901.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004, 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 4845901 + * @summary Make sure that SimpleDateFormat.parse() can distinguish + * the same time zone abbreviation for standard and daylight saving + * time. + */ + +import java.util.*; +import java.text.SimpleDateFormat; + +public class Bug4845901 { + public static void main (String args[]) { + TimeZone savedTZ = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney")); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS z"); + try { + testParse(sdf, "2003.01.13 11:10:00.802 AEDT", 11); + testParse(sdf, "2003.06.12 11:10:00.802 AEST", 11); + testParse(sdf, "2004.12.24 10:10:00.002 AEDT", 10); + testParse(sdf, "2004.08.10 10:10:00.002 AEST", 10); + } finally { + TimeZone.setDefault(savedTZ); + } + } + + static void testParse(SimpleDateFormat sdf, String str, int expectedHour) { + try { + Date parsedDate = sdf.parse(str); + if (parsedDate.getHours() != expectedHour) { + throw new RuntimeException( + "parsed date has wrong hour: " + parsedDate.getHours() + + ", expected: " + expectedHour + + "\ngiven string: " + str + + "\nparsedDate = " + parsedDate); + } + } catch (java.text.ParseException e) { + throw new RuntimeException("parse exception", e); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug6251817.java b/jdk/test/java/text/Format/DateFormat/Bug6251817.java new file mode 100644 index 00000000000..b0dd7fc9c2c --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6251817.java @@ -0,0 +1,45 @@ +/* + * 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 + * 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 6251817 + * @summary Confirm that a typo was corrected. + */ + +import java.text.*; +import java.util.*; + +public class Bug6251817 { + + public static void main(String[] args) { + SimpleDateFormat sdf = new SimpleDateFormat("zzzz", Locale.US); + sdf.setTimeZone(TimeZone.getTimeZone("Australia/Lord_Howe")); + String got = sdf.format(new Date()); + + if (!got.equals("Lord Howe Standard Time") && + !got.equals("Lord Howe Daylight Time")) { + throw new RuntimeException("Timezone display name for Australia/Lord_Howe is incorrect. Got:" + got); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug6335238.java b/jdk/test/java/text/Format/DateFormat/Bug6335238.java new file mode 100644 index 00000000000..201a1af8f99 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6335238.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2006, 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 1.1 06/01/24 + * @bug 6335238 + * @summary Make sure that both the original and cloned SimpleDateFormat coexistindependently and don't cut off each other. + * @run main Bug6335238 10 + */ + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +// Usage: java Bug6335238 [duration] +public class Bug6335238 { + + static final long UTC_LONG = 974534460000L; + static final String TIME_STRING = "2000/11/18 00:01:00"; + static SimpleDateFormat masterSdf; + static int duration = 180; + static boolean stopped = false; + static boolean err = false; + + public static void main(String[] args) { + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + + TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific")); + Locale.setDefault(Locale.US); + + masterSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + + try { + // Once it is used, DecimalFormat becomes not thread-safe. + Date d = masterSdf.parse(TIME_STRING); + + new Bug6335238(); + } catch (Exception e) { + System.err.println(e); + err = true; + } finally { + TimeZone.setDefault(savedTimeZone); + Locale.setDefault(savedLocale); + + if (err) { + throw new RuntimeException("Failed: Multiple DateFormat instances didn't work correctly."); + } else { + System.out.println("Passed."); + } + } + } + + public Bug6335238() { + stopped = false; + + DateParseThread d1 = new DateParseThread(); + DateFormatThread d2 = new DateFormatThread(); + DateParseThread d3 = new DateParseThread(); + DateFormatThread d4 = new DateFormatThread(); + + d1.start(); + d2.start(); + d3.start(); + d4.start(); + + try { + Thread.sleep(duration * 1000); + } + catch (Exception e) { + System.err.println(e); + err = true; + } + + stopped = true; + } + + class DateFormatThread extends Thread { + + public void run() { + int i = 0; + + while (!stopped) { + SimpleDateFormat sdf; + synchronized (masterSdf) { + sdf = (SimpleDateFormat)masterSdf.clone(); + } + + i++; + String s = sdf.format(new Date(UTC_LONG)); + + if (!s.equals(TIME_STRING)) { + stopped = true; + err = true; + + throw new RuntimeException("Formatting Date Error: counter=" + + i + ", Got<" + s + "> != Expected<" + TIME_STRING + ">"); + } + } + } + } + + class DateParseThread extends Thread { + + public void run() { + int i = 0; + + while (!stopped) { + SimpleDateFormat sdf; + synchronized (masterSdf) { + sdf = (SimpleDateFormat)masterSdf.clone(); + } + + i++; + Date date; + try { + date = sdf.parse(TIME_STRING); + long t = date.getTime(); + + if (t != UTC_LONG) { + stopped = true; + err = true; + + throw new RuntimeException("Parsing Date Error: counter=" + + i + " Got:" + t + "<" + sdf.format(date) + + "> != " + UTC_LONG); + } + } + catch (ParseException e) { + stopped = true; + err = true; + + throw new RuntimeException(e); + } + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug6530336.java b/jdk/test/java/text/Format/DateFormat/Bug6530336.java new file mode 100644 index 00000000000..d01a96aba9e --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6530336.java @@ -0,0 +1,108 @@ +/* + * 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 + * 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 6530336 6537997 8008577 + * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug6530336 + */ + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class Bug6530336 { + + public static void main(String[] args) throws Exception { + Locale defaultLocale = Locale.getDefault(); + TimeZone defaultTimeZone = TimeZone.getDefault(); + + boolean err = false; + + try { + Locale locales[] = Locale.getAvailableLocales(); + Locale locale_Japan = new Locale("ja", "JP", "JP"); + TimeZone timezone_LA = TimeZone.getTimeZone("America/Los_Angeles"); + TimeZone.setDefault(timezone_LA); + + TimeZone timezones[] = { + TimeZone.getTimeZone("America/New_York"), + TimeZone.getTimeZone("America/Denver"), + }; + + String[] expected = { + "Sun Jul 15 12:00:00 PDT 2007", + "Sun Jul 15 14:00:00 PDT 2007", + }; + + Date[] dates = new Date[2]; + + for (int i = 0; i < locales.length; i++) { + if (locales[i].getLanguage().equals("th") || + locales[i].equals(locale_Japan)) { + continue; + } + + Locale.setDefault(locales[i]); + + for (int j = 0; j < timezones.length; j++) { + Calendar cal = Calendar.getInstance(timezones[j]); + cal.set(2007, 6, 15, 15, 0, 0); + dates[j] = cal.getTime(); + } + + SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); + + for (int j = 0; j < timezones.length; j++) { + sdf.setTimeZone(timezones[j]); + String date = sdf.format(dates[j]); + sdf.setTimeZone(timezone_LA); + String date_LA = sdf.parse(date).toString(); + + if (!expected[j].equals(date_LA)) { + System.err.println("Got wrong Pacific time (" + + date_LA + ") for (" + date + ") in " + locales[i] + + " in " + timezones[j] + + ".\nExpected=" + expected[j]); + err = true; + } + } + } + } + catch (Exception e) { + e.printStackTrace(); + err = true; + } + finally { + Locale.setDefault(defaultLocale); + TimeZone.setDefault(defaultTimeZone); + + if (err) { + throw new RuntimeException("Failed."); + } + } + } + +} diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java b/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java new file mode 100644 index 00000000000..d276aac088b --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java @@ -0,0 +1,1098 @@ +/* + * 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 + * 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.text.*; +import java.util.*; +import java.io.*; + +/** + * @test + * @bug 4029195 4052408 4056591 4059917 4060212 4061287 4065240 4071441 4073003 + * 4089106 4100302 4101483 4103340 4103341 4104136 4104522 4106807 4108407 + * 4134203 4138203 4148168 4151631 4151706 4153860 4162071 4182066 4209272 4210209 + * 4213086 4250359 4253490 4266432 4406615 4413980 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRegression + */ +public class DateFormatRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new DateFormatRegression().run(args); + } + + public void Test4029195() { + + Date today = new Date(); + + logln("today: " + today); + + SimpleDateFormat sdf = (SimpleDateFormat)SimpleDateFormat.getDateInstance(); + logln("pattern: " + sdf.toPattern()); + logln("today: " + sdf.format(today)); + + sdf.applyPattern("G yyyy DDD"); + String todayS = sdf.format(today); + logln("today: " + todayS); + try { + today = sdf.parse(todayS); + logln("today date: " + today); + } catch(Exception e) { + logln("Error reparsing date: " + e.getMessage()); + } + + try { + String rt = sdf.format(sdf.parse(todayS)); + logln("round trip: " + rt); + if (!rt.equals(todayS)) errln("Fail: Want " + todayS + " Got " + rt); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4052408() { + + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, + DateFormat.SHORT, Locale.US); + Date date = new Date(97, Calendar.MAY, 3, 8, 55); + String str; + logln(str = fmt.format(date)); + + if (!str.equals("5/3/97 8:55 AM")) + errln("Fail: Test broken; Want 5/3/97 8:55 AM Got " + str); + Hashtable expected = new Hashtable(); + expected.put(new Integer(DateFormat.MONTH_FIELD), "5"); + expected.put(new Integer(DateFormat.DATE_FIELD), "3"); + expected.put(new Integer(DateFormat.YEAR_FIELD), "97"); + expected.put(new Integer(DateFormat.HOUR1_FIELD), "8"); + expected.put(new Integer(DateFormat.MINUTE_FIELD), "55"); + expected.put(new Integer(DateFormat.AM_PM_FIELD), "AM"); + + StringBuffer buf = new StringBuffer(); + String fieldNames[] = { + "ERA_FIELD", + "YEAR_FIELD", + "MONTH_FIELD", + "DATE_FIELD", + "HOUR_OF_DAY1_FIELD", + "HOUR_OF_DAY0_FIELD", + "MINUTE_FIELD", + "SECOND_FIELD", + "MILLISECOND_FIELD", + "DAY_OF_WEEK_FIELD", + "DAY_OF_YEAR_FIELD", + "DAY_OF_WEEK_IN_MONTH_FIELD", + "WEEK_OF_YEAR_FIELD", + "WEEK_OF_MONTH_FIELD", + "AM_PM_FIELD", + "HOUR1_FIELD", + "HOUR0_FIELD", + "TIMEZONE_FIELD", + }; + boolean pass = true; + for (int i=0; i<=17; ++i) { + FieldPosition pos = new FieldPosition(i); + fmt.format(date, buf, pos); + char[] dst = new char[pos.getEndIndex() - pos.getBeginIndex()]; + buf.getChars(pos.getBeginIndex(), pos.getEndIndex(), dst, 0); + str = new String(dst); + log(i + ": " + fieldNames[i] + + ", \"" + str + "\", " + + pos.getBeginIndex() + ", " + + pos.getEndIndex()); + String exp = (String) expected.get(new Integer(i)); + if ((exp == null && str.length() == 0) || + str.equals(exp)) + logln(" ok"); + else { + logln(" expected " + exp); + pass = false; + } + } + if (!pass) errln("Fail: FieldPosition not set right by DateFormat"); + } + + /** + * Verify the function of the [s|g]et2DigitYearStart() API. + */ + public void Test4056591() { + try { + SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd", Locale.US); + Date start = new Date(1809-1900, Calendar.DECEMBER, 25); + fmt.set2DigitYearStart(start); + if (!fmt.get2DigitYearStart().equals(start)) + errln("get2DigitYearStart broken"); + Object[] DATA = { + "091225", new Date(1809-1900, Calendar.DECEMBER, 25), + "091224", new Date(1909-1900, Calendar.DECEMBER, 24), + "091226", new Date(1809-1900, Calendar.DECEMBER, 26), + "611225", new Date(1861-1900, Calendar.DECEMBER, 25), + }; + for (int i=0; i " + got + "; exp " + exp); + if (!got.equals(exp)) errln("set2DigitYearStart broken"); + } + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4059917() { + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + SimpleDateFormat fmt; + String myDate; + + fmt = new SimpleDateFormat( "yyyy/MM/dd" ); + myDate = "1997/01/01"; + aux917( fmt, myDate ); + + fmt = new SimpleDateFormat( "yyyyMMdd" ); + myDate = "19970101"; + aux917( fmt, myDate ); + } + + void aux917( SimpleDateFormat fmt, String str ) { + try { + logln( "==================" ); + logln( "testIt: pattern=" + fmt.toPattern() + + " string=" + str ); + + Object o; + o = fmt.parseObject( str ); + logln( "Parsed object: " + o ); + + String formatted = fmt.format( o ); + logln( "Formatted string: " + formatted ); + if (!formatted.equals(str)) errln("Fail: Want " + str + " Got " + formatted); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4060212() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + String dateString = "1995-040.05:01:29"; + + logln( "dateString= " + dateString ); + logln("Using yyyy-DDD.hh:mm:ss"); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-DDD.hh:mm:ss"); + ParsePosition pos = new ParsePosition(0); + Date myDate = formatter.parse( dateString, pos ); + String myString = DateFormat.getDateTimeInstance( DateFormat.FULL, + DateFormat.LONG).format( myDate ); + logln( myString ); + Calendar cal = new GregorianCalendar(); + cal.setTime(myDate); + if (cal.get(Calendar.DAY_OF_YEAR) != 40) + errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + + " Want 40"); + + logln("Using yyyy-ddd.hh:mm:ss"); + formatter = new SimpleDateFormat("yyyy-ddd.hh:mm:ss"); + pos = new ParsePosition(0); + myDate = formatter.parse( dateString, pos ); + myString = DateFormat.getDateTimeInstance( DateFormat.FULL, + DateFormat.LONG).format( myDate ); + logln( myString ); + cal.setTime(myDate); + if (cal.get(Calendar.DAY_OF_YEAR) != 40) + errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + + " Want 40"); + } + finally { + Locale.setDefault(savedLocale); + } + } + + public void Test4061287() { + SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy"); + try { + logln(df.parse("35/01/1971").toString()); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + df.setLenient(false); + boolean ok = false; + try { + logln(df.parse("35/01/1971").toString()); + } catch (ParseException e) {ok=true;} + if (!ok) errln("Fail: Lenient not working"); + } + + public void Test4065240() { + Date curDate; + DateFormat shortdate, fulldate; + String strShortDate, strFullDate; + Locale saveLocale = Locale.getDefault(); + TimeZone saveZone = TimeZone.getDefault(); + try { + Locale curLocale = new Locale("de","DE"); + Locale.setDefault(curLocale); + TimeZone.setDefault(TimeZone.getTimeZone("EST")); + curDate = new Date(98, 0, 1); + shortdate = DateFormat.getDateInstance(DateFormat.SHORT); + fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG + ); + strShortDate = new String("The current date (short form) is " + shortdate. + format(curDate)); + strFullDate = new String("The current date (long form) is " + fulldate.format(curDate)); + + logln(strShortDate); + logln(strFullDate); + + // UPDATE THIS AS ZONE NAME RESOURCE FOR in de_DE is updated + if (!strFullDate.endsWith("EST") + && !strFullDate.endsWith("GMT-05:00")) { + errln("Fail: Want GMT-05:00"); + } + } + finally { + Locale.setDefault(saveLocale); + TimeZone.setDefault(saveZone); + } + } + + /* + DateFormat.equals is too narrowly defined. As a result, MessageFormat + does not work correctly. DateFormat.equals needs to be written so + that the Calendar sub-object is not compared using Calendar.equals, + but rather compared for equivalency. This may necessitate adding a + (package private) method to Calendar to test for equivalency. + + Currently this bug breaks MessageFormat.toPattern + */ + public void Test4071441() { + DateFormat fmtA = DateFormat.getInstance(); + DateFormat fmtB = DateFormat.getInstance(); + Calendar calA = fmtA.getCalendar(); + Calendar calB = fmtB.getCalendar(); + Date epoch = new Date(0); + Date xmas = new Date(61, Calendar.DECEMBER, 25); + calA.setTime(epoch); + calB.setTime(epoch); + if (!calA.equals(calB)) + errln("Fail: Can't complete test; Calendar instances unequal"); + if (!fmtA.equals(fmtB)) + errln("Fail: DateFormat unequal when Calendars equal"); + calB.setTime(xmas); + if (calA.equals(calB)) + errln("Fail: Can't complete test; Calendar instances equal"); + if (!fmtA.equals(fmtB)) + errln("Fail: DateFormat unequal when Calendars equivalent"); + logln("DateFormat.equals ok"); + } + + /* The java.text.DateFormat.parse(String) method expects for the + US locale a string formatted according to mm/dd/yy and parses it + correctly. + + When given a string mm/dd/yyyy it only parses up to the first + two y's, typically resulting in a date in the year 1919. + + Please extend the parsing method(s) to handle strings with + four-digit year values (probably also applicable to various + other locales. */ + public void Test4073003() { + try { + DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); + String[] tests = { "12/25/61", "12/25/1961", "4/3/2010", "4/3/10" }; + for (int i=0; i is incorrectly serialized/deserialized."); + } else { + logln("DateFormat instance which uses TimeZone <" + + IDs[i] + "> is correctly serialized/deserialized."); + } + } + if (!pass) { + errln("Fail: DateFormat serialization/equality bug"); + } + } + catch (IOException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + catch (ClassNotFoundException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + finally { + TimeZone.setDefault(savedTimeZone); + } + } + + public void Test4101483() { + SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.US); + FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD); + Date d= new Date(9234567890L); + StringBuffer buf = new StringBuffer(""); + logln(sdf.format(d, buf, fp).toString()); + logln(d + " => " + buf); + logln("beginIndex = " + fp.getBeginIndex()); + logln("endIndex = " + fp.getEndIndex()); + if (fp.getBeginIndex() == fp.getEndIndex()) errln("Fail: Empty field"); + } + + /** + * Bug 4103340 + * Bug 4138203 + * This bug really only works in Locale.US, since that's what the locale + * used for Date.toString() is. Bug 4138203 reports that it fails on Korean + * NT; it would actually have failed on any non-US locale. Now it should + * work on all locales. + */ + public void Test4103340() { + // choose a date that is the FIRST of some month + // and some arbitrary time + Date d=new Date(97, 3, 1, 1, 1, 1); + SimpleDateFormat df=new SimpleDateFormat("MMMM", Locale.US); + + String s = d.toString(); + String s2 = df.format(d); + logln("Date="+s); + logln("DF="+s2); + if (s.indexOf(s2.substring(0,2)) == -1) + errln("Months should match"); + } + + public void Test4103341() { + TimeZone saveZone =TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("CST")); + SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + if (!simple.getTimeZone().equals(TimeZone.getDefault())) + errln("Fail: SimpleDateFormat not using default zone"); + } + finally { + TimeZone.setDefault(saveZone); + } + } + + public void Test4104136() { + SimpleDateFormat sdf = new SimpleDateFormat(); + String pattern = "'time' hh:mm"; + sdf.applyPattern(pattern); + logln("pattern: \"" + pattern + "\""); + + Object[] DATA = { + "time 10:30", new ParsePosition(10), new Date(70, Calendar.JANUARY, 1, 10, 30), + "time 10:x", new ParsePosition(0), null, + "time 10x", new ParsePosition(0), null, + }; + for (int i=0; i \"" + + str + "\", exp \"" + OUT[i] + '"'); + } + } + + // Test parsing + fmt.applyPattern("s.S"); + String[] IN = { "1.4", "1.04", "1.004", "1.45", "1.456", + "1.4567", "1.45678" }; + int[] MS = { 4, 4, 4, 45, 456, 567, 678 }; + for (int i=0; i " + + ms + " ms, exp " + MS[i] + " ms"); + } + } + } + + /** + * SimpleDateFormat incorrect handling of 2 single quotes in format() + */ + public void Test4151631() { + String pattern = "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'"; + logln("pattern=" + pattern); + SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US); + String result = format.format(new Date(1998-1900, Calendar.JUNE, 30, 13, 30, 0)); + if (!result.equals("TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')")) { + errln("Fail: result=" + result); + } + else { + logln("Pass: result=" + result); + } + } + + /** + * 'z' at end of date format throws index exception in SimpleDateFormat + * CANNOT REPRODUCE THIS BUG ON 1.2FCS + */ + public void Test4151706() { + SimpleDateFormat fmt = + new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss z", Locale.US); + try { + Date d = fmt.parse("Thursday, 31-Dec-98 23:00:00 GMT"); + if (d.getTime() != Date.UTC(1998-1900, Calendar.DECEMBER, 31, 23, 0, 0)) + errln("Incorrect value: " + d); + } catch (Exception e) { + errln("Fail: " + e); + } + } + + /** + * SimpleDateFormat fails to parse redundant data. + * This is actually a bug down in GregorianCalendar, but it was reported + * as follows... + */ + public void Test4153860() throws ParseException { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + SimpleDateFormat sf = (SimpleDateFormat)DateFormat.getDateTimeInstance(); + // Set the pattern + sf.applyPattern("yyyy.MM-dd"); + // Try to create a Date for February 4th + Date d1 = sf.parse("1998.02-04"); + // Set the pattern, this time to use the W value + sf.applyPattern("yyyy.MM-dd W"); + // Try to create a Date for February 4th + Date d2 = sf.parse("1998.02-04 1"); + if (!d1.equals(d2)) { + errln("Parse failed, got " + d2 + + ", expected " + d1); + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + /** + * Confirm that "EST"(GMT-5:00) and "CST"(GMT-6:00) are used in US + * as "EST" or "CST", not Australian "EST" and "CST". + */ + public void Test4406615() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + Date d1, d2; + String dt = "Mon, 1 Jan 2001 00:00:00"; + SimpleDateFormat sdf = + new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); + + try { + d1 = sdf.parse(dt+" EST"); + d2 = sdf.parse(dt+" CST"); + + if (d1.getYear() != (2000-1900) || d1.getMonth() != 11 || + d1.getDate() != 31 || d1.getHours() != 21 || d1.getMinutes() != 0 || + d2.getYear() != (2000-1900) || d2.getMonth() != 11 || + d2.getDate() != 31 || d2.getHours() != 22 || d2.getMinutes() != 0) { + errln("Parse failed, d1 = " + d1 + ", d2 = " + d2); + } else { + logln("Parse passed"); + } + } + catch (Exception e) { + errln("Parse failed, got Exception " + e); + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + } + + /** + * Cannot reproduce this bug under 1.2 FCS -- it may be a convoluted duplicate + * of some other bug that has been fixed. + */ + public void Test4162071() { + String dateString = "Thu, 30-Jul-1999 11:51:14 GMT"; + String format = "EEE', 'dd-MMM-yyyy HH:mm:ss z"; // RFC 822/1123 + SimpleDateFormat df = new + SimpleDateFormat(format, Locale.US); + + try { + Date x = df.parse(dateString); + logln("Parse format \"" + format + "\" ok"); + logln(dateString + " -> " + df.format(x)); + } catch (Exception e) { + errln("Parse format \"" + format + "\" failed."); + } + } + + /** + * DateFormat shouldn't parse year "-1" as a two-digit year (e.g., "-1" -> 1999). + */ + public void Test4182066() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy", + DateFormatSymbols.getInstance(Locale.US)); + SimpleDateFormat dispFmt = new SimpleDateFormat("MMM dd yyyy GG", + DateFormatSymbols.getInstance(Locale.US)); + /* We expect 2-digit year formats to put 2-digit years in the right + * window. Out of range years, that is, anything less than "00" or + * greater than "99", are treated as literal years. So "1/2/3456" + * becomes 3456 AD. Likewise, "1/2/-3" becomes -3 AD == 2 BC. + */ + Object[] DATA = { + "02/29/00", new Date(2000-1900, Calendar.FEBRUARY, 29), + "01/23/01", new Date(2001-1900, Calendar.JANUARY, 23), + "04/05/-1", new Date( -1-1900, Calendar.APRIL, 5), + "01/23/-9", new Date( -9-1900, Calendar.JANUARY, 23), + "11/12/1314", new Date(1314-1900, Calendar.NOVEMBER, 12), + "10/31/1", new Date( 1-1900, Calendar.OCTOBER, 31), + "09/12/+1", null, // "+1" isn't recognized by US NumberFormat + "09/12/001", new Date( 1-1900, Calendar.SEPTEMBER,12), + }; + StringBuffer out = new StringBuffer(); + boolean pass = true; + for (int i=0; i " + actStr + "\n"); + } else { + String expStr = expected != null + ? dispFmt.format(expected) : String.valueOf(expected); + out.append("FAIL: " + str + " => " + actStr + + ", expected " + expStr + "\n"); + pass = false; + } + } + if (pass) { + log(out.toString()); + } else { + err(out.toString()); + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + /** + * Bug 4210209 + * Bug 4209272 + * DateFormat cannot parse Feb 29 2000 when setLenient(false) + */ + public void Test4210209() { + String pattern = "MMM d, yyyy"; + DateFormat fmt = new SimpleDateFormat(pattern, + DateFormatSymbols.getInstance(Locale.US)); + fmt.getCalendar().setLenient(false); + Date d = new Date(2000-1900, Calendar.FEBRUARY, 29); + String s = fmt.format(d); + logln(d + " x " + pattern + " => " + s); + ParsePosition pos = new ParsePosition(0); + d = fmt.parse(s, pos); + logln(d + " <= " + pattern + " x " + s); + logln("Parse pos = " + pos); + if (pos.getErrorIndex() != -1) { + errln("FAIL"); + } + + // The underlying bug is in GregorianCalendar. If the following lines + // succeed, the bug is fixed. If the bug isn't fixed, they will throw + // an exception. + GregorianCalendar cal = new GregorianCalendar(); + cal.clear(); + cal.setLenient(false); + cal.set(2000, Calendar.FEBRUARY, 29); // This should work! + logln(cal.getTime().toString()); + } + + /** + * DateFormat.getDateTimeInstance() allows illegal parameters. + */ + public void Test4213086() { + int[] DATA = { + // Style value, 0/1 for illegal/legal + -99, 0, + -1, 0, + 0, 1, + 1, 1, + 2, 1, + 3, 1, + 4, 0, + 99, 0, + }; + String[] DESC = { + "getDateTimeInstance(date)", + "getDateTimeInstance(time)", + "getDateInstance", + "getTimeInstance", + }; + String[] GOT = { + "disallowed", "allowed", "" + }; + for (int i=0; i \"" + s + '"'); + } else { + errln("FAIL: " + FORMAT_MS + " ms f* \"" + + FORMAT_PAT[i] + "\" -> \"" + s + "\", expect \"" + + FORMAT_TO[i] + '"'); + } + } + + // Test parsing. We want to make sure all digits are read. + fmt.applyPattern(PARSE_PAT); + for (int i=0; i " + ms + " ms"); + } else { + errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + + PARSE_PAT + "\" -> " + ms + " ms, expect " + + PARSE_TO[i] + " ms"); + } + } + + // Test LONG parsing. We want to make sure all digits are read. + fmt.applyPattern(PARSE_LPAT); + for (int i=0; i " + ms + " ms"); + } else { + errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + + PARSE_LPAT + "\" -> " + ms + " ms, expect " + + PARSE_TO[i] + " ms"); + } + } + } + + /** + * Bug in handling of time instance; introduces in fix for 4213086. + */ + public void Test4250359() { + DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT, + Locale.US); + Date d = new Date(1999-1900, Calendar.DECEMBER, 25, + 1, 2, 3); + String s = df.format(d); + // If the bug is present, we see "1:02 AM 1:02 AM". + // Look for more than one instance of "AM". + int i = s.indexOf("AM"); + int j = s.indexOf("AM", i+1); + if (i < 0 || j >= 0) { + errln("FAIL: getTimeInstance().format(d) => \"" + + s + "\""); + } + } + + /** + * Test whether SimpleDataFormat (DateFormatSymbols) can format/parse + * non-localized time zones. + */ + public void Test4261506() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + Locale.setDefault(Locale.JAPAN); + + // XXX: Test assumes "PST" is not TimeZoneNames_ja. Need to + // pick up another time zone when L10N is done to that file. + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN); + String result = fmt.format(new Date(1999, 0, 1)); + logln("format()=>" + result); + if (!result.endsWith("PST")) { + errln("FAIL: SimpleDataFormat.format() did not retrun PST"); + } + + Date d = null; + try { + d = fmt.parse("99/1/1 10:10 PST"); + } catch (ParseException e) { + errln("FAIL: SimpleDataFormat.parse() could not parse PST"); + } + + result = fmt.format(d); + logln("roundtrip:" + result); + if (!result.equals("99/01/01 10:10 PST")) { + errln("FAIL: SimpleDataFomat timezone roundtrip failed"); + } + + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + +} + +//eof diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java b/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java new file mode 100644 index 00000000000..73d023163f1 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java @@ -0,0 +1,727 @@ +/* + * 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 + * 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 test Date Format (Round Trip) + * @bug 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRoundTripTest + */ + +import java.text.*; +import java.util.*; + +public class DateFormatRoundTripTest extends IntlTest { + + static Random RANDOM = null; + + static final long FIXED_SEED = 3141592653589793238L; // Arbitrary fixed value + + // Useful for turning up subtle bugs: Use -infinite and run while at lunch. + boolean INFINITE = false; // Warning -- makes test run infinite loop!!! + + boolean random = false; + + // Options used to reproduce failures + Locale locale = null; + String pattern = null; + Date initialDate = null; + + Locale[] avail; + TimeZone defaultZone; + + // If SPARSENESS is > 0, we don't run each exhaustive possibility. + // There are 24 total possible tests per each locale. A SPARSENESS + // of 12 means we run half of them. A SPARSENESS of 23 means we run + // 1 of them. SPARSENESS _must_ be in the range 0..23. + static final int SPARSENESS = 18; + + static final int TRIALS = 4; + + static final int DEPTH = 5; + + static SimpleDateFormat refFormat = + new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); + + public DateFormatRoundTripTest(boolean rand, long seed, boolean infinite, + Date date, String pat, Locale loc) { + random = rand; + if (random) { + RANDOM = new Random(seed); + } + INFINITE = infinite; + + initialDate = date; + locale = loc; + pattern = pat; + } + + /** + * Parse a name like "fr_FR" into new Locale("fr", "FR", ""); + */ + static Locale createLocale(String name) { + String country = "", + variant = ""; + int i; + if ((i = name.indexOf('_')) >= 0) { + country = name.substring(i+1); + name = name.substring(0, i); + } + if ((i = country.indexOf('_')) >= 0) { + variant = country.substring(i+1); + country = country.substring(0, i); + } + return new Locale(name, country, variant); + } + + public static void main(String[] args) throws Exception { + // Command-line parameters + Locale loc = null; + boolean infinite = false; + boolean random = false; + long seed = FIXED_SEED; + String pat = null; + Date date = null; + + Vector newArgs = new Vector(); + for (int i=0; i] [-locale ] [-date ] [-INFINITE]"); + System.out.println(" [-random | -randomseed | -seed ]"); + System.out.println("* Warning: Some patterns will fail with some locales."); + System.out.println("* Do not use -pattern unless you know what you are doing!"); + System.out.println("When specifying a locale, use a format such as fr_FR."); + System.out.println("Use -pattern, -locale, and -date to reproduce a failure."); + System.out.println("-random Random with fixed seed (same data every run)."); + System.out.println("-randomseed Random with a random seed."); + System.out.println("-seed Random using as seed."); + super.usage(); + } + + static private class TestCase { + private int[] date; + TimeZone zone; + FormatFactory ff; + boolean timeOnly; + private Date _date; + + TestCase(int[] d, TimeZone z, FormatFactory f, boolean timeOnly) { + date = d; + zone = z; + ff = f; + this.timeOnly = timeOnly; + } + + TestCase(Date d, TimeZone z, FormatFactory f, boolean timeOnly) { + date = null; + _date = d; + zone = z; + ff = f; + this.timeOnly = timeOnly; + } + + /** + * Create a format for testing. + */ + DateFormat createFormat() { + return ff.createFormat(); + } + + /** + * Return the Date of this test case; must be called with the default + * zone set to this TestCase's zone. + */ + Date getDate() { + if (_date == null) { + // Date constructor will work right iff we are in the target zone + int h = 0; + int m = 0; + int s = 0; + if (date.length >= 4) { + h = date[3]; + if (date.length >= 5) { + m = date[4]; + if (date.length >= 6) { + s = date[5]; + } + } + } + _date = new Date(date[0] - 1900, date[1] - 1, date[2], + h, m, s); + } + return _date; + } + + public String toString() { + return String.valueOf(getDate().getTime()) + " " + + refFormat.format(getDate()) + " : " + ff.createFormat().format(getDate()); + } + }; + + private interface FormatFactory { + DateFormat createFormat(); + } + + TestCase[] TESTS = { + // Feb 29 2004 -- ordinary leap day + new TestCase(new int[] {2004, 2, 29}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // Feb 29 2000 -- century leap day + new TestCase(new int[] {2000, 2, 29}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // 0:00:00 Jan 1 1999 -- first second of normal year + new TestCase(new int[] {1999, 1, 1}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 23:59:59 Dec 31 1999 -- last second of normal year + new TestCase(new int[] {1999, 12, 31, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 0:00:00 Jan 1 2004 -- first second of leap year + new TestCase(new int[] {2004, 1, 1}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 23:59:59 Dec 31 2004 -- last second of leap year + new TestCase(new int[] {2004, 12, 31, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // October 25, 1998 1:59:59 AM PDT -- just before DST cessation + new TestCase(new Date(909305999000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 25, 1998 1:00:00 AM PST -- just after DST cessation + new TestCase(new Date(909306000000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // April 4, 1999 1:59:59 AM PST -- just before DST onset + new TestCase(new int[] {1999, 4, 4, 1, 59, 59}, + TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // April 4, 1999 3:00:00 AM PDT -- just after DST onset + new TestCase(new Date(923220000000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 4, 1582 11:59:59 PM PDT -- just before Gregorian change + new TestCase(new int[] {1582, 10, 4, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 15, 1582 12:00:00 AM PDT -- just after Gregorian change + new TestCase(new int[] {1582, 10, 15, 0, 0, 0}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + }; + + public void TestDateFormatRoundTrip() { + avail = DateFormat.getAvailableLocales(); + logln("DateFormat available locales: " + avail.length); + logln("Default TimeZone: " + + (defaultZone = TimeZone.getDefault()).getID()); + + if (random || initialDate != null) { + if (RANDOM == null) { + // Need this for sparse coverage to reduce combinatorial explosion, + // even for non-random looped testing (i.e., with explicit date but + // not pattern or locale). + RANDOM = new Random(FIXED_SEED); + } + loopedTest(); + } else { + for (int i=0; i= 0 && random < 24 && TEST_TABLE[i]) { + TEST_TABLE[i] = false; + ++i; + } + } + } + + int itable = 0; + for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getDateInstance(style, loc)); + } + + for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getTimeInstance(style, loc), true); + } + + for (int dstyle=DateFormat.FULL; dstyle<=DateFormat.SHORT; ++dstyle) { + for (int tstyle=DateFormat.FULL; tstyle<=DateFormat.SHORT; ++tstyle) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getDateTimeInstance(dstyle, tstyle, loc)); + } + } + } + + void doTest(Locale loc, DateFormat fmt) { doTest(loc, fmt, false); } + + void doTest(Locale loc, DateFormat fmt, boolean timeOnly) { + doTest(loc, fmt, timeOnly, initialDate != null ? initialDate : generateDate()); + } + + void doTest(Locale loc, DateFormat fmt, boolean timeOnly, Date date) { + // Skip testing with the JapaneseImperialCalendar which + // doesn't support the Gregorian year semantices with 'y'. + if (fmt.getCalendar().getClass().getName().equals("java.util.JapaneseImperialCalendar")) { + return; + } + + String pat = ((SimpleDateFormat)fmt).toPattern(); + String deqPat = dequotePattern(pat); // Remove quoted elements + + boolean hasEra = (deqPat.indexOf("G") != -1); + boolean hasZone = (deqPat.indexOf("z") != -1); + + Calendar cal = fmt.getCalendar(); + + // Because patterns contain incomplete data representing the Date, + // we must be careful of how we do the roundtrip. We start with + // a randomly generated Date because they're easier to generate. + // From this we get a string. The string is our real starting point, + // because this string should parse the same way all the time. Note + // that it will not necessarily parse back to the original date because + // of incompleteness in patterns. For example, a time-only pattern won't + // parse back to the same date. + + try { + for (int i=0; i 0) d[loop] = fmt.parse(s[loop-1]); + s[loop] = fmt.format(d[loop]); + + if (loop > 0) { + if (smatch == 0) { + boolean match = s[loop].equals(s[loop-1]); + if (smatch == 0) { + if (match) smatch = loop; + } + else if (!match) { + // This should never happen; if it does, fail. + smatch = -1; + error = "FAIL: String mismatch after match"; + } + } + + if (dmatch == 0) { + boolean match = d[loop].getTime() == d[loop-1].getTime(); + if (dmatch == 0) { + if (match) dmatch = loop; + } + else if (!match) { + // This should never happen; if it does, fail. + dmatch = -1; + error = "FAIL: Date mismatch after match"; + } + } + + if (smatch != 0 && dmatch != 0) break; + } + } + // At this point loop == DEPTH if we've failed, otherwise loop is the + // max(smatch, dmatch), that is, the index at which we have string and + // date matching. + + // Date usually matches in 2. Exceptions handled below. + int maxDmatch = 2; + int maxSmatch = 1; + if (dmatch > maxDmatch) { + // Time-only pattern with zone information and a starting date in PST. + if (timeOnly && hasZone && fmt.getTimeZone().inDaylightTime(d[0])) { + maxDmatch = 3; + maxSmatch = 2; + } + } + + // String usually matches in 1. Exceptions are checked for here. + if (smatch > maxSmatch) { // Don't compute unless necessary + // Starts in BC, with no era in pattern + if (!hasEra && getField(cal, d[0], Calendar.ERA) == GregorianCalendar.BC) + maxSmatch = 2; + // Starts in DST, no year in pattern + else if (fmt.getTimeZone().inDaylightTime(d[0]) && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Two digit year with zone and year change and zone in pattern + else if (hasZone && + fmt.getTimeZone().inDaylightTime(d[0]) != + fmt.getTimeZone().inDaylightTime(d[dmatch]) && + getField(cal, d[0], Calendar.YEAR) != + getField(cal, d[dmatch], Calendar.YEAR) && + deqPat.indexOf("y") != -1 && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Two digit year, year change, DST changeover hour. Example: + // FAIL: Pattern: dd/MM/yy HH:mm:ss + // Date matched in 2, wanted 2 + // String matched in 2, wanted 1 + // Thu Apr 02 02:35:52.110 PST 1795 AD F> 02/04/95 02:35:52 + // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 + // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 d== s== + // The problem is that the initial time is not a DST onset day, but + // then the year changes, and the resultant parsed time IS a DST + // onset day. The hour "2:XX" makes no sense if 2:00 is the DST + // onset, so DateFormat interprets it as 1:XX (arbitrary -- could + // also be 3:XX, same problem). This results in an extra iteration + // for String match convergence. + else if (!justBeforeOnset(cal, d[0]) && justBeforeOnset(cal, d[dmatch]) && + getField(cal, d[0], Calendar.YEAR) != + getField(cal, d[dmatch], Calendar.YEAR) && + deqPat.indexOf("y") != -1 && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Another spurious failure: + // FAIL: Pattern: dd MMMM yyyy hh:mm:ss + // Date matched in 2, wanted 2 + // String matched in 2, wanted 1 + // Sun Apr 05 14:28:38.410 PDT 3998 AD F> 05 April 3998 02:28:38 + // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 + // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 d== s== + // The problem here is that with an 'hh' pattern, hour from 1-12, + // a lack of AM/PM -- that is, no 'a' in pattern, and an initial + // time in the onset hour + 12:00. + else if (deqPat.indexOf('h') >= 0 + && deqPat.indexOf('a') < 0 + && justBeforeOnset(cal, new Date(d[0].getTime() - 12*60*60*1000L)) + && justBeforeOnset(cal, d[1])) + maxSmatch = 2; + } + + if (dmatch > maxDmatch || smatch > maxSmatch + || dmatch < 0 || smatch < 0) { + StringBuffer out = new StringBuffer(); + if (error != null) { + out.append(error + '\n'); + } + out.append("FAIL: Pattern: " + pat + ", Locale: " + loc + '\n'); + out.append(" Initial date (ms): " + d[0].getTime() + '\n'); + out.append(" Date matched in " + dmatch + + ", wanted " + maxDmatch + '\n'); + out.append(" String matched in " + smatch + + ", wanted " + maxSmatch); + + for (int j=0; j<=loop && j0?" P> ":" ") + refFormat.format(d[j]) + " F> " + + escape(s[j]) + + (j>0&&d[j].getTime()==d[j-1].getTime()?" d==":"") + + (j>0&&s[j].equals(s[j-1])?" s==":"")); + } + errln(escape(out.toString())); + } + } + } + catch (ParseException e) { + errln(e.toString()); + } + } + + /** + * Return a field of the given date + */ + static int getField(Calendar cal, Date d, int f) { + // Should be synchronized, but we're single threaded so it's ok + cal.setTime(d); + return cal.get(f); + } + + /** + * Return true if the given Date is in the 1 hour window BEFORE the + * change from STD to DST for the given Calendar. + */ + static final boolean justBeforeOnset(Calendar cal, Date d) { + return nearOnset(cal, d, false); + } + + /** + * Return true if the given Date is in the 1 hour window AFTER the + * change from STD to DST for the given Calendar. + */ + static final boolean justAfterOnset(Calendar cal, Date d) { + return nearOnset(cal, d, true); + } + + /** + * Return true if the given Date is in the 1 hour (or whatever the + * DST savings is) window before or after the onset of DST. + */ + static boolean nearOnset(Calendar cal, Date d, boolean after) { + cal.setTime(d); + if ((cal.get(Calendar.DST_OFFSET) == 0) == after) { + return false; + } + int delta; + try { + delta = ((SimpleTimeZone) cal.getTimeZone()).getDSTSavings(); + } catch (ClassCastException e) { + delta = 60*60*1000; // One hour as ms + } + cal.setTime(new Date(d.getTime() + (after ? -delta : delta))); + return (cal.get(Calendar.DST_OFFSET) == 0) == after; + } + + static String escape(String s) { + StringBuffer buf = new StringBuffer(); + for (int i=0; i 0) { + try (FileOutputStream fos = + new FileOutputStream("SDFserialized.ser")) { + ObjectOutputStream oStream = new ObjectOutputStream(fos); + oStream.writeObject(sdf); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + try (InputStream is = + HexDumpReader.getStreamFromHexDump("SDFserialized.ser.txt")) { + ObjectInputStream iStream = new ObjectInputStream(is); + sdf1 = (SimpleDateFormat)iStream.readObject(); + } + + DateFormatSymbols dfs = sdf.getDateFormatSymbols(); + DateFormatSymbols dfs1 = sdf1.getDateFormatSymbols(); + System.out.println(sdf + "," + sdf.toPattern()); + System.out.println(sdf1 + "," + sdf1.toPattern()); + + // time zone display names should not be a part of this + // compatibility test. See 4112924 and 4282899. + dfs.setZoneStrings(dfs1.getZoneStrings()); + // localPatternChars should not be a part of this + // compatibility test. See 4322313. + dfs.setLocalPatternChars(dfs1.getLocalPatternChars()); + sdf.setDateFormatSymbols(dfs); + + // decimal format symbols should not be part of this + // compatibility test - old decimal format symbols get filled + // in with the root locale (4290801) + DecimalFormat df1 = (DecimalFormat) sdf1.getNumberFormat(); + df1.setDecimalFormatSymbols(df.getDecimalFormatSymbols()); + + if (!dfs.equals(dfs1)) { + err = true; + System.err.println( + "Error: serialized DateFormatSymbols is different"); + } + if (!sdf.equals(sdf1)) { + err = true; + System.err.println( + "Error: serialized SimpleDateFormat is different"); + } + if (err) { + throw new Exception("Serialization failed."); + } + } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatTest.java b/jdk/test/java/text/Format/DateFormat/DateFormatTest.java new file mode 100644 index 00000000000..c4f148f3d77 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatTest.java @@ -0,0 +1,1207 @@ +/* + * 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 + * 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 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571 + * @summary test DateFormat and SimpleDateFormat. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest + */ + +import java.util.*; +import java.text.*; +import static java.util.GregorianCalendar.*; + +public class DateFormatTest extends IntlTest +{ + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new DateFormatTest().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + // Test 4 digit year parsing with pattern "yy" + @SuppressWarnings("deprecation") + public void TestYearParsing() + { + String str = "7/Sep/2001"; + Date exp = new Date(2001-1900, SEPTEMBER, 7); + String pat = "d/MMM/yy"; + SimpleDateFormat sdf = new SimpleDateFormat(pat, Locale.US); + try { + Date d = sdf.parse(str); + logln(str + " parses with " + pat + " to " + d); + if (d.getTime() != exp.getTime()) { + errln("FAIL: Expected " + exp); + } + } + catch (ParseException e) { + errln(str + " parse fails with " + pat); + } + } + + // Test written by Wally Wedel and emailed to me. + public void TestWallyWedel() + { + /* + * Instantiate a TimeZone so we can get the ids. + */ + TimeZone tz = new SimpleTimeZone(7,""); + /* + * Computational variables. + */ + int offset, hours, minutes; + /* + * Instantiate a SimpleDateFormat set up to produce a full time + zone name. + */ + SimpleDateFormat sdf = new SimpleDateFormat("zzzz"); + /* + * A String array for the time zone ids. + */ + String[] ids = TimeZone.getAvailableIDs(); + /* + * How many ids do we have? + */ + logln("Time Zone IDs size: " + ids.length); + /* + * Column headings (sort of) + */ + logln("Ordinal ID offset(h:m) name"); + /* + * Loop through the tzs. + */ + Date today = new Date(); + Calendar cal = Calendar.getInstance(); + for (int i = 0; i < ids.length; i++) { + // logln(i + " " + ids[i]); + TimeZone ttz = TimeZone.getTimeZone(ids[i]); + // offset = ttz.getRawOffset(); + cal.setTimeZone(ttz); + cal.setTime(today); + offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); + // logln(i + " " + ids[i] + " offset " + offset); + char sign = '+'; + if (offset < 0) { sign = '-'; offset = -offset; } + hours = offset/3600000; + minutes = (offset%3600000)/60000; + String dstOffset = "" + sign + (hours < 10 ? "0" : "") + + hours + ':' + (minutes < 10 ? "0" : "") + minutes; + /* + * Instantiate a date so we can display the time zone name. + */ + sdf.setTimeZone(ttz); + /* + * Format the output. + */ + StringBuffer tzS = new StringBuffer(); + sdf.format(today,tzS, new FieldPosition(0)); + String fmtOffset = tzS.toString(); + String fmtDstOffset = null; + if (fmtOffset.startsWith("GMT")) + { + fmtDstOffset = fmtOffset.substring(3); + } + /* + * Show our result. + */ + boolean ok = fmtDstOffset == null || fmtDstOffset.equals(dstOffset); + if (ok) + { + logln(i + " " + ids[i] + " " + dstOffset + + " " + fmtOffset + + (fmtDstOffset != null ? " ok" : " ?")); + } + else + { + errln(i + " " + ids[i] + " " + dstOffset + + " " + fmtOffset + " *** FAIL ***"); + } + } + } + + // Test equals + public void TestEquals() + { + DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL); + + DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL); + + if (!fmtA.equals(fmtB)) { + errln("FAIL"); + } + } + + // Check out some specific parsing problem + @SuppressWarnings("deprecation") + public void TestTwoDigitYearDSTParse() + { + SimpleDateFormat fullFmt = + new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); + + //DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL, + // Locale.ENGLISH); + SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z", + Locale.ENGLISH); + //Date date = new Date(2004-1900, Calendar.APRIL, 3, 2, 20, 47); + //logln(fmt.format(date)); // This shows what the current locale format is + //logln(((SimpleDateFormat)fmt).toPattern()); + TimeZone save = TimeZone.getDefault(); + TimeZone PST = TimeZone.getTimeZone("PST"); + String s = "03-Apr-04 2:20:47 o'clock AM PST"; + int hour = 2; + try { + TimeZone.setDefault(PST); + Date d = fmt.parse(s); + logln(s + " P> " + fullFmt.format(d)); + if (d.getHours() != hour) { + errln("FAIL: Should parse to hour " + hour); + } + } + catch (ParseException e) { errln("FAIL: " + e.getMessage()); } + finally { + TimeZone.setDefault(save); + } + } + + static String escape(String s) + { + StringBuilder buf = new StringBuilder(); + for (int i=0; i> 12)); + buf.append(Integer.toHexString((c & 0x0F00) >> 8)); + buf.append(Integer.toHexString((c & 0x00F0) >> 4)); + buf.append(Integer.toHexString(c & 0x000F)); + } + } + return buf.toString(); + } + + // Test field position return values + static String fieldNames[] = { + "ERA_FIELD", "YEAR_FIELD", "MONTH_FIELD", + "WEEK_OF_YEAR_FIELD", "WEEK_OF_MONTH_FIELD", "DATE_FIELD", + "DAY_OF_YEAR_FIELD", "DAY_OF_WEEK_FIELD", "DAY_OF_WEEK_IN_MONTH_FIELD", + "AM_PM_FIELD", "HOUR0_FIELD", "HOUR1_FIELD", + "HOUR_OF_DAY0_FIELD", "HOUR_OF_DAY1_FIELD", + "MINUTE_FIELD", "SECOND_FIELD", + "MILLISECOND_FIELD", "TIMEZONE_FIELD", + }; + static int fieldIDs[] = { + DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD, + DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.DATE_FIELD, + DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, + DateFormat.AM_PM_FIELD, DateFormat.HOUR0_FIELD, DateFormat.HOUR1_FIELD, + DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.HOUR_OF_DAY1_FIELD, + DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD, + DateFormat.MILLISECOND_FIELD, DateFormat.TIMEZONE_FIELD, + }; + + /** + * Bug 4089987 + */ + public void TestFieldPosition() + { + DateFormat[] dateFormats = { + DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL, + Locale.US), + + DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.FRANCE), + new SimpleDateFormat("G, y, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"), + new SimpleDateFormat("G, yy, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"), + new SimpleDateFormat( "GGGG, yyyy, MMMM, dddd, kkkk, HHHH, mmmm, ssss, " + + "SSSS, EEEE, DDDD, " + + "FFFF, wwww, WWWW, aaaa, hhhh, KKKK, zzzz") + }; + String[] expected = + { + "", "1997", "August", "", "", "13", "", "Wednesday", "", + "PM", "", "2", "", "", "34", "12", "", "PDT", + + "", "1997", "ao\u00FBt", "", "", "13", "", "mercredi", "", "", + "", "", "14", "", "34", "", "", "PDT" /*"GMT-07:00"*/, + + "AD", "1997", "8", "33", "3", "13", "225", "Wed", "2", "PM", + "2", "2", "14", "14", "34", "12", "513", "PDT", + + "AD", "97", "8", "33", "3", "13", "225", "Wed", "2", "PM", + "2", "2", "14", "14", "34", "12", "513", "PDT", + + "AD", "1997", "August", "0033", "0003", "0013", "0225", + "Wednesday", "0002", "PM", "0002", "0002", "0014", "0014", + "0034", "0012", "0513", "Pacific Daylight Time", + }; + Date someDate = new Date(871508052513L); + TimeZone PST = TimeZone.getTimeZone("PST"); + for (int j = 0, exp = 0; j < dateFormats.length; ++j) { + DateFormat df = dateFormats[j]; + if (!(df instanceof SimpleDateFormat)) { + continue; + } + df.setTimeZone(PST); + logln(" Pattern = " + ((SimpleDateFormat)df).toPattern()); + logln(" Result = " + df.format(someDate)); + for (int i = 0; i < fieldIDs.length; ++i) + { + String field = getFieldText(df, fieldIDs[i], someDate); + if (!field.equals(expected[exp])) { + errln("FAIL: field #" + i + " " + fieldNames[i] + " = \"" + + escape(field) + "\", expected \"" + escape(expected[exp]) + "\""); + } + ++exp; + } + } + } + // get the string value for the given field for the given date + static String getFieldText(DateFormat df, int field, Date date) + { + StringBuffer buffer = new StringBuffer(); + FieldPosition pos = new FieldPosition(field); + df.format(date, buffer, pos); + return buffer.toString().substring(pos.getBeginIndex(), + pos.getEndIndex()); + } + + // Test parsing of partial strings + @SuppressWarnings("deprecation") + public void TestPartialParse994() + { + SimpleDateFormat f = new SimpleDateFormat(); + Calendar cal = new GregorianCalendar(2014 - 80, JANUARY, 1); + f.set2DigitYearStart(cal.getTime()); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", new Date(97, 1-1, 17, 10, 11, 42)); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null); + } + + void tryPat994(SimpleDateFormat format, String pat, String str, Date expected) + { + logln("Pattern \"" + pat + "\" String \"" + str + "\""); + try { + format.applyPattern(pat); + Date date = format.parse(str); + String f = format.format(date); + logln(" parse(" + str + ") -> " + date.toString()); + logln(" format -> " + f); + if (expected == null || + !date.equals(expected)) { + errln("FAIL: Expected " + expected); + } + if (!f.equals(str)) { + errln("FAIL: Expected " + str); + } + } + catch(ParseException e) { + logln("ParseException: " + e.getMessage()); + if (expected != null) { + errln("FAIL: Expected " + expected); + } + } + catch(Exception e) { + errln("*** Exception:"); + e.printStackTrace(); + } + } + + // Test pattern with runs things together + public void TestRunTogetherPattern985() + { + String format = "yyyyMMddHHmmssSSS"; + String now, then; + + SimpleDateFormat formatter = new SimpleDateFormat(format); + + Date date1 = new Date(); + now = formatter.format(date1); + + logln(now); + + ParsePosition pos = new ParsePosition(0); + + Date date2 = formatter.parse(now, pos); + if (date2 == null) { + then = "Parse stopped at " + pos.getIndex(); + } else { + then = formatter.format(date2); + } + + logln(then); + + if (!date2.equals(date1)) { + errln("FAIL"); + } + } + + // Test patterns which run numbers together + @SuppressWarnings("deprecation") + public void TestRunTogetherPattern917() + { + SimpleDateFormat fmt; + String myDate; + + fmt = new SimpleDateFormat( "yyyy/MM/dd" ); + myDate = "1997/02/03"; + _testIt917( fmt, myDate, new Date(97, 2-1, 3) ); + + fmt = new SimpleDateFormat( "yyyyMMdd" ); + myDate = "19970304"; + _testIt917( fmt, myDate, new Date(97, 3-1, 4) ); + + } + void _testIt917( SimpleDateFormat fmt, String str, Date expected ) + { + logln( "pattern=" + fmt.toPattern() + " string=" + str ); + + Object o; + try { + o = fmt.parseObject( str ); + } catch( ParseException e ) { + e.printStackTrace(); + return; + } + logln( "Parsed object: " + o ); + if (!o.equals(expected)) { + errln("FAIL: Expected " + expected); + } + + String formatted = fmt.format( o ); + logln( "Formatted string: " + formatted ); + if (!formatted.equals(str)) { + errln("FAIL: Expected " + str); + } + } + + // Test Czech month formatting -- this can cause a problem because the June and + // July month names share a common prefix. + @SuppressWarnings("deprecation") + public void TestCzechMonths459() + { + // Use Czech, which has month names with shared prefixes for June and July + DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, new Locale("cs", "", "")); + //((SimpleDateFormat)fmt).applyPattern("MMMM d yyyy"); + logln("Pattern " + ((SimpleDateFormat)fmt).toPattern()); + + Date june = new Date(97, Calendar.JUNE, 15); + Date july = new Date(97, Calendar.JULY, 15); + + String juneStr = fmt.format(june); + String julyStr = fmt.format(july); + + try { + logln("format(June 15 1997) = " + juneStr); + Date d = fmt.parse(juneStr); + String s = fmt.format(d); + int month = d.getMonth(); + logln(" -> parse -> " + s + " (month = " + month + ")"); + if (month != JUNE) { + errln("FAIL: Month should be June"); + } + + logln("format(July 15 1997) = " + julyStr); + d = fmt.parse(julyStr); + s = fmt.format(d); + month = d.getMonth(); + logln(" -> parse -> " + s + " (month = " + month + ")"); + if (month != JULY) { + errln("FAIL: Month should be July"); + } + } + catch (ParseException e) { + errln("Exception: " + e); + } + } + + // Test big D (day of year) versus little d (day of month) + @SuppressWarnings("deprecation") + public void TestLetterDPattern212() + { + String dateString = "1995-040.05:01:29"; + String bigD = "yyyy-DDD.hh:mm:ss"; + String littleD = "yyyy-ddd.hh:mm:ss"; + Date expLittleD = new Date(95, 0, 1, 5, 1, 29); + Date expBigD = new Date(expLittleD.getTime() + 39*24*3600000L); // 39 days + expLittleD = expBigD; // Expect the same, with default lenient parsing + logln( "dateString= " + dateString ); + SimpleDateFormat formatter = new SimpleDateFormat(bigD); + ParsePosition pos = new ParsePosition(0); + Date myDate = formatter.parse( dateString, pos ); + logln("Using " + bigD + " -> " + myDate); + if (myDate.getTime() != expBigD.getTime()) { + errln("FAIL: Expected " + expBigD + " got " + myDate); + } + + formatter = new SimpleDateFormat(littleD); + pos = new ParsePosition(0); + myDate = formatter.parse( dateString, pos ); + logln("Using " + littleD + " -> " + myDate); + if (myDate.getTime() != expLittleD.getTime()) { + errln("FAIL: Expected " + expLittleD + " got " + myDate); + } + } + + // Test the 'G' day of year pattern + @SuppressWarnings("deprecation") + public void TestDayOfYearPattern195() + { + Date today = new Date(); + Date expected = new Date(today.getYear(), today.getMonth(), today.getDate()); + + logln("Test Date: " + today); + + SimpleDateFormat sdf = + (SimpleDateFormat)SimpleDateFormat.getDateInstance(); + + tryPattern(sdf, today, null, expected); + tryPattern(sdf, today, "G yyyy DDD", expected); + } + + void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected) + { + if (pattern != null) { + sdf.applyPattern(pattern); + } + logln("pattern: " + sdf.toPattern()); + + String formatResult = sdf.format(d); + logln(" format -> " + formatResult); + try { + Date d2 = sdf.parse(formatResult); + logln(" parse(" + formatResult + ") -> " + d2); + if (d2.getTime() != expected.getTime()) { + errln("FAIL: Expected " + expected); + } + String format2 = sdf.format(d2); + logln(" format -> " + format2); + if (!formatResult.equals(format2)) { + errln("FAIL: Round trip drift"); + } + } + catch(Exception e) { + errln("Error: " + e.getMessage()); + } + } + + // Test a pattern with single quotes + @SuppressWarnings("deprecation") + public void TestQuotePattern161() + { + // This pattern used to end in " zzz" but that makes this test zone-dependent + SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz"); + Date currentTime_1 = new Date(97, Calendar.AUGUST, 13, 10, 42, 28); + String dateString = formatter.format(currentTime_1); + String exp = "08/13/1997 at 10:42:28 AM "; + logln("format(" + currentTime_1 + ") = " + dateString); + if (!dateString.regionMatches(0, exp, 0, exp.length())) { + errln("FAIL: Expected " + exp); + } + } + + // Test the parsing of bad input strings + /** Demonstrates a number of bugs in DateFormat.parse(String) where + * either StringIndexOutOfBoundsException is thrown or null is + * returned instead of ParseException. To reproduce, run this program + * and notice all the "SHOULD NOT HAPPEN" errors. Note also that the + * 1 line that should be correct is off by 100 years. (In this day + * and age, no one would assume that 1/1/00 is Jan 1 1900.) + **/ + public void TestBadInput135() + { + int looks[] = { DateFormat.SHORT, DateFormat.MEDIUM, + DateFormat.LONG, DateFormat.FULL }; + String strings[] = { "Mar 15", "Mar 15 1997", "asdf", + "3/1/97 1:23:", "3/1/00 1:23:45 AM" }; + DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + String expected = "March 1, 2000 1:23:45 AM "; + for ( int i = 0; i < strings.length; ++i ){ + String text = strings[i]; + for ( int j = 0; j < looks.length; ++j ){ + int dateLook = looks[j]; + for ( int k = 0; k < looks.length; ++k ){ + int timeLook = looks[k]; + DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook); + String prefix = text + ", " + dateLook + "/" + timeLook + ": "; + try { + Date when = df.parse(text); + if ( when == null ){ + errln(prefix + + "SHOULD NOT HAPPEN: parse returned null."); + continue; + } + String format = full.format(when); + logln(prefix + "OK: " + format); + // Only match the start -- not the zone, which could vary + if (!format.regionMatches(0, expected, 0, expected.length())) { + errln("FAIL: Expected " + expected); + } + } + catch ( ParseException e ){ + //errln(prefix + e); // This is expected. + } + catch ( StringIndexOutOfBoundsException e ){ + errln(prefix + "SHOULD NOT HAPPEN: " + e); + } + } + } + } + } + + final private static String parseFormats[] = + { + "MMMM d, yyyy", // january 1, 1970 or jan 1, 1970 + "MMMM d yyyy", // january 1 1970 or jan 1 1970 + "M/d/yy", // 1/1/70 + "d MMMM, yyyy", // 1 january, 1970 or 1 jan, 1970 + "d MMMM yyyy", // 1 january 1970 or 1 jan 1970 + "d MMMM", // 1 january or 1 jan + "MMMM d", // january 1 or jan 1 + "yyyy", // 1970 + "h:mm a MMMM d, yyyy" // Date and Time + }; + final private static String inputStrings[] = + { + "bogus string", null, null, null, null, null, null, null, null, null, + "April 1, 1997", "April 1, 1997", null, null, null, null, null, "April 1", null, null, + "Jan 1, 1970", "January 1, 1970", null, null, null, null, null, "January 1", null, null, + "Jan 1 2037", null, "January 1 2037", null, null, null, null, "January 1", null, null, + "1/1/70", null, null, "1/1/70", null, null, null, null, "0001", null, + "5 May 1997", null, null, null, null, "5 May 1997", "5 May", null, "0005", null, + "16 May", null, null, null, null, null, "16 May", null, "0016", null, + "April 30", null, null, null, null, null, null, "April 30", null, null, + "1998", null, null, null, null, null, null, null, "1998", null, + "1", null, null, null, null, null, null, null, "0001", null, // Bug620 + "3:00 pm Jan 1, 1997", null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997", + }; + // More testing of the parsing of bad input + @SuppressWarnings("UnusedAssignment") + public void TestBadInput135a() + { + SimpleDateFormat dateParse = new SimpleDateFormat(); + String s; + Date date; + int PFLENGTH = parseFormats.length; + + dateParse.applyPattern("d MMMM, yyyy"); + dateParse.setTimeZone(TimeZone.getDefault()); + s = "not parseable"; + logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern()); + try { + date = dateParse.parse(s); + errln("FAIL: Expected exception during parse"); + } catch (Exception ex) { + logln("Exception during parse: " + ex); // This is expected + } + + for (int i=0; i " + d.toString()); + if (d.getTime() != expected.getTime()) { + errln("FAIL: Expected " + expected); + } + } catch (ParseException e) { + errln("FAIL: Got exception"); + } + } + + // Test behavior of DateFormat with applied time zone + public void TestDateFormatZone061() + { + Date date; + DateFormat formatter; + + // 25-Mar-97 00:00:00 GMT + date = new Date( 859248000000L ); + logln( "Date 1997/3/25 00:00 GMT: " + date ); + formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK); + formatter.setTimeZone( TimeZone.getTimeZone( "GMT" ) ); + + String temp = formatter.format( date ); + logln( "Formatted in GMT to: " + temp ); + + /* Parse date string */ + try { + Date tempDate = formatter.parse( temp ); + logln( "Parsed to: " + tempDate ); + if (tempDate.getTime() != date.getTime()) { + errln("FAIL: Expected " + date); + } + } + catch( Throwable t ) { + errln( "Date Formatter throws: " + + t.toString() ); + } + } + + // Make sure DateFormat uses the correct zone. + public void TestDateFormatZone146() + { + TimeZone saveDefault = TimeZone.getDefault(); + + try { + TimeZone thedefault = TimeZone.getTimeZone("GMT"); + TimeZone.setDefault(thedefault); + // java.util.Locale.setDefault(new java.util.Locale("ar", "", "")); + + // check to be sure... its GMT all right + TimeZone testdefault = TimeZone.getDefault(); + String testtimezone = testdefault.getID(); + if (testtimezone.equals("GMT")) { + logln("Test timezone = " + testtimezone); + } else { + errln("Test timezone should be GMT, not " + testtimezone); + } + + // now try to use the default GMT time zone + GregorianCalendar greenwichcalendar = + new GregorianCalendar(1997, 3, 4, 23, 0); + //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault()); + //greenwichcalendar.set(1997, 3, 4, 23, 0); + // try anything to set hour to 23:00 !!! + greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23); + // get time + Date greenwichdate = greenwichcalendar.getTime(); + // format every way + String[] DATA = { + "simple format: ", "04/04/97 23:00 GMT", + "MM/dd/yy HH:mm z", + "full format: ", "Friday, April 4, 1997 11:00:00 o'clock PM GMT", + "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z", + "long format: ", "April 4, 1997 11:00:00 PM GMT", + "MMMM d, yyyy h:mm:ss a z", + "default format: ", "04-Apr-97 11:00:00 PM", + "dd-MMM-yy h:mm:ss a", + "short format: ", "4/4/97 11:00 PM", + "M/d/yy h:mm a", + }; + + for (int i=0; i4 y's produces just "2001" until 1.3.1. This + // was fixed in 1.4. + String expected = + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000002001\u5e74"; + SimpleDateFormat sdf = new SimpleDateFormat(pat); + String s = sdf.format(new Date(2001-1900, Calendar.JANUARY, 1)); + if (!expected.equals(s)) { + errln("wrong format result: expected="+expected+", got="+s); + } + Date longday = sdf.parse(s); + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(longday); + if (cal.get(YEAR) != 2001) { + errln("wrong parse result: expected=2001, got=" + cal.get(YEAR)); + } + } catch (Exception e) { + throw e; + } finally { + // Restore the initial time zone + TimeZone.setDefault(initialTimeZone); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java new file mode 100644 index 00000000000..bc37d4f7fba --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java @@ -0,0 +1,273 @@ +/* + * 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 + * 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 test International Date Format + * @bug 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormat + * @key randomness + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - 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. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestDateFormat extends IntlTest { + // Values in milliseconds (== Date) + private static final long ONESECOND = 1000; + private static final long ONEMINUTE = 60 * ONESECOND; + private static final long ONEHOUR = 60 * ONEMINUTE; + private static final long ONEDAY = 24 * ONEHOUR; + private static final double ONEYEAR = 365.25 * ONEDAY; // Approximate + + // EModes + private static final byte GENERIC = 0; + private static final byte TIME = GENERIC + 1; + private static final byte DATE = TIME + 1; + private static final byte DATE_TIME = DATE + 1; + + private DateFormat fFormat = DateFormat.getInstance(); + private String fTestName = new String("getInstance"); + private int fLimit = 3; // How many iterations it should take to reach convergence + + public static void main(String[] args) throws Exception { + new IntlTestDateFormat().run(args); + } + + public void TestLocale() { + localeTest(Locale.getDefault(), "Default Locale"); + } + + // This test does round-trip testing (format -> parse -> format -> parse -> etc.) of DateFormat. + public void localeTest(final Locale locale, final String localeName) { + int timeStyle, dateStyle; + + // For patterns including only time information and a timezone, it may take + // up to three iterations, since the timezone may shift as the year number + // is determined. For other patterns, 2 iterations should suffice. + fLimit = 3; + + for(timeStyle = 0; timeStyle < 4; timeStyle++) { + fTestName = new String("Time test " + timeStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getTimeInstance(timeStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest time getTimeInstance exception"); + throw e; + } + TestFormat(); + } + + fLimit = 2; + + for(dateStyle = 0; dateStyle < 4; dateStyle++) { + fTestName = new String("Date test " + dateStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getDateInstance(dateStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest date getTimeInstance exception"); + throw e; + } + TestFormat(); + } + + for(dateStyle = 0; dateStyle < 4; dateStyle++) { + for(timeStyle = 0; timeStyle < 4; timeStyle++) { + fTestName = new String("DateTime test " + dateStyle + "/" + timeStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest date/time getDateTimeInstance exception"); + throw e; + } + TestFormat(); + } + } + } + + public void TestFormat() { + if (fFormat == null) { + errln("FAIL: DateFormat creation failed"); + return; + } + // logln("TestFormat: " + fTestName); + Date now = new Date(); + tryDate(new Date(0)); + tryDate(new Date((long) 1278161801778.0)); + tryDate(now); + // Shift 6 months into the future, AT THE SAME TIME OF DAY. + // This will test the DST handling. + tryDate(new Date(now.getTime() + 6*30*ONEDAY)); + + Date limit = new Date(now.getTime() * 10); // Arbitrary limit + for (int i=0; i<2; ++i) + // tryDate(new Date(floor(randDouble() * limit))); + tryDate(new Date((long) (randDouble() * limit.getTime()))); + } + + private void describeTest() { + if (fFormat == null) { + errln("FAIL: no DateFormat"); + return; + } + + // Assume it's a SimpleDateFormat and get some info + SimpleDateFormat s = (SimpleDateFormat) fFormat; + logln(fTestName + " Pattern " + s.toPattern()); + } + + private void tryDate(Date theDate) { + final int DEPTH = 10; + Date[] date = new Date[DEPTH]; + StringBuffer[] string = new StringBuffer[DEPTH]; + + int dateMatch = 0; + int stringMatch = 0; + boolean dump = false; + int i; + for (i=0; i 0) { + if (dateMatch == 0 && date[i] == date[i-1]) dateMatch = i; + else if (dateMatch > 0 && date[i] != date[i-1]) { + describeTest(); + errln("********** FAIL: Date mismatch after match."); + dump = true; + break; + } + if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i; + else if (stringMatch > 0 && string[i] != string[i-1]) { + describeTest(); + errln("********** FAIL: String mismatch after match."); + dump = true; + break; + } + } + if (dateMatch > 0 && stringMatch > 0) break; + } + if (i == DEPTH) --i; + + if (stringMatch > fLimit || dateMatch > fLimit) { + describeTest(); + errln("********** FAIL: No string and/or date match within " + fLimit + " iterations."); + dump = true; + } + + if (dump) { + for (int k=0; k<=i; ++k) { + logln("" + k + ": " + date[k] + " F> " + string[k] + " P> "); + } + } + } + + // Return a random double from 0.01 to 1, inclusive + private double randDouble() { + // Assume 8-bit (or larger) rand values. Also assume + // that the system rand() function is very poor, which it always is. + // double d; + // int i; + // do { + // for (i=0; i < sizeof(double); ++i) + // { + // char poke = (char*)&d; + // poke[i] = (rand() & 0xFF); + // } + // } while (TPlatformUtilities.isNaN(d) || TPlatformUtilities.isInfinite(d)); + + // if (d < 0.0) d = -d; + // if (d > 0.0) + // { + // double e = floor(log10(d)); + // if (e < -2.0) d *= pow(10.0, -e-2); + // else if (e > -1.0) d /= pow(10.0, e+1); + // } + // return d; + Random rand = new Random(); + return rand.nextDouble(); + } + + public void TestAvailableLocales() { + final Locale[] locales = DateFormat.getAvailableLocales(); + long count = locales.length; + logln("" + count + " available locales"); + if (locales != null && count != 0) { + StringBuffer all = new StringBuffer(); + for (int i=0; i 0) { + throw new RuntimeException("FAILED: " + errors + " error(s)"); + } + } + + private static void test(Locale locale) { + Locale.setDefault(locale); + + // Tests with the Japanese imperial calendar + Locale calendarLocale = new Locale("ja", "JP", "JP"); + testRoundTrip(calendarLocale); + testRoundTripSimple(calendarLocale, + locale == Locale.ENGLISH ? JAPANESE_EN : JAPANESE_JA); + testParseExceptions(calendarLocale, + locale == Locale.ENGLISH ? EXCEPTION_JAPANESE_EN : EXCEPTION_JAPANESE_JA); + + // Tests with the Thai Buddhist calendar + calendarLocale = new Locale("th", "TH"); + testRoundTrip(calendarLocale); + testRoundTripSimple(calendarLocale, + locale == Locale.ENGLISH ? BUDDHIST_EN : BUDDHIST_JA); + } + + private static void testRoundTrip(Locale calendarLocale) { + DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, + DateFormat.FULL, + calendarLocale); + + long t = System.currentTimeMillis(); + t = (t / 1000) * 1000; // discard milliseconds + testRoundTrip(df, new Date(t)); + + // H1.8.9 + testRoundTrip(df, new Date(1989-1900, AUGUST, 9)); + + // H17.6.13 + testRoundTrip(df, new Date(2005-1900, JUNE, 13)); + } + + private static void testRoundTrip(DateFormat df, Date orig) { + try { + String s = df.format(orig); + Date parsed = df.parse(s); + if (!orig.equals(parsed)) { + error("testRoundTrip: bad date: origianl: '%s', parsed '%s'%n", orig, parsed); + } + } catch (Exception e) { + error("Unexpected exception: %s%n", e); + } + } + + private static void testRoundTripSimple(Locale calendarLocale, Object[][] data) { + try { + for (Object[] item : data) { + String pattern = (String) item[0]; + String str = (String) item[1]; + Date date = (Date) item[2]; + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Calendar cal = Calendar.getInstance(calendarLocale); + sdf.setCalendar(cal); + String s = sdf.format(date); + if (!s.equals(str)) { + error("testRoundTripSimple: Got '%s', expected '%s'%n", s, str); + } + Date d = sdf.parse(str); + if (!d.equals(date)) { + error("testRoundTripSimple: Got '%s', expected '%s'%n", d, date); + } + } + } catch (Exception e) { + error("Unexpected exception: %s%n", e); + } + } + + private static void testParseExceptions(Locale calendarLocale, Object[][] data) { + for (Object[] item : data) { + String pattern = (String) item[0]; + String str = (String) item[1]; + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Calendar cal = Calendar.getInstance(calendarLocale); + sdf.setCalendar(cal); + sdf.setLenient(false); + try { + Date d = sdf.parse(str); + error("testParseExceptions: parsing '%s' doesn't throw a ParseException.%n", str); + } catch (ParseException e) { + // OK + } + } + } + + private static void error(String msg) { + System.out.println(msg); + errors++; + } + + private static void error(String fmt, Object... args) { + System.out.printf(fmt, args); + errors++; + } +} diff --git a/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt b/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt new file mode 100644 index 00000000000..c0ddced4fab --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt @@ -0,0 +1,173 @@ +# +# Copyright (c) 1999, 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. +# + +# Hex dump of a serialized DateFormatSymbols for +# DateFormatSymbolsSerializationTest. + +aced00057372001a6a6176612e746578742e53696d706c6544617465466f726d +61744243c9da9394359002000449001573657269616c56657273696f6e4f6e53 +747265616d4c001364656661756c7443656e7475727953746172747400104c6a +6176612f7574696c2f446174653b4c000a666f726d61744461746174001d4c6a +6176612f746578742f44617465466f726d617453796d626f6c733b4c00077061 +747465726e7400124c6a6176612f6c616e672f537472696e673b787200146a61 +76612e746578742e44617465466f726d6174642ca1e4c22615fc0200024c0008 +63616c656e6461727400144c6a6176612f7574696c2f43616c656e6461723b4c +000c6e756d626572466f726d61747400184c6a6176612f746578742f4e756d62 +6572466f726d61743b787200106a6176612e746578742e466f726d6174fbd8bc +12e90f184302000078707372001b6a6176612e7574696c2e477265676f726961 +6e43616c656e6461728f3dd7d6e5b0d0c10200014a0010677265676f7269616e +4375746f766572787200126a6176612e7574696c2e43616c656e646172e6ea4d +1ec8dc5b8e03000b5a000c6172654669656c647353657449000e666972737444 +61794f665765656b5a0009697354696d655365745a00076c656e69656e744900 +166d696e696d616c44617973496e46697273745765656b4900096e6578745374 +616d7049001573657269616c56657273696f6e4f6e53747265616d4a00047469 +6d655b00066669656c64737400025b495b000569735365747400025b5a4c0004 +7a6f6e657400144c6a6176612f7574696c2f54696d655a6f6e653b7870010000 +000101010000000100000002000000010000000000000000757200025b494dba +602676eab2a502000078700000001100000001000007b2000000000000000100 +0000010000000100000001000000050000000100000000000000000000000000 +00000000000000000000000000000000000000757200025b5a578f203914b85d +e20200007870000000110101010101010101010101010101010101737200186a +6176612e7574696c2e53696d706c6554696d655a6f6e65fa675d60d15ef5a603 +001049000a647374536176696e6773490006656e6444617949000c656e644461 +794f665765656b490007656e644d6f6465490008656e644d6f6e746849000765 +6e6454696d654900097261774f666673657449001573657269616c5665727369 +6f6e4f6e53747265616d490008737461727444617949000e7374617274446179 +4f665765656b49000973746172744d6f646549000a73746172744d6f6e746849 +0009737461727454696d654900097374617274596561725a000b757365446179 +6c696768745b000b6d6f6e74684c656e6774687400025b42787200126a617661 +2e7574696c2e54696d655a6f6e6531b3e9f57744aca10200014c000249447100 +7e00037870740003474d540036ee800000000000000000000000000000000000 +0000000000000000000001000000000000000000000000000000000000000000 +00000000757200025b42acf317f8060854e002000078700000000c1f1c1f1e1f +1e1f1f1e1f1e1f770800000004000000007878fffff4e2f964ac00737200176a +6176612e746578742e446563696d616c466f726d61740bff0362d872303a0200 +0b5a001b646563696d616c536570617261746f72416c7761797353686f776e42 +000c67726f7570696e6753697a654200116d696e4578706f6e656e7444696769 +747349000a6d756c7469706c69657249001573657269616c56657273696f6e4f +6e53747265616d5a00167573654578706f6e656e7469616c4e6f746174696f6e +4c000e6e6567617469766550726566697871007e00034c000e6e656761746976 +6553756666697871007e00034c000e706f73697469766550726566697871007e +00034c000e706f73697469766553756666697871007e00034c000773796d626f +6c737400204c6a6176612f746578742f446563696d616c466f726d617453796d +626f6c733b787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000701032800000003000000 +2800010000000000000001000000000178010300000000010000000100740001 +2d74000071007e001f71007e001f7372001e6a6176612e746578742e44656369 +6d616c466f726d617453796d626f6c73501d17990868939c02000f4300106465 +63696d616c536570617261746f72430005646967697443000b6578706f6e656e +7469616c43001167726f7570696e67536570617261746f724300096d696e7573 +5369676e4300116d6f6e6574617279536570617261746f724300107061747465 +726e536570617261746f724300077065724d696c6c43000770657263656e7449 +001573657269616c56657273696f6e4f6e53747265616d4300097a65726f4469 +6769744c00034e614e71007e00034c000e63757272656e637953796d626f6c71 +007e00034c0008696e66696e69747971007e00034c0012696e746c4375727265 +6e637953796d626f6c71007e00037870002e00230045002c002d002e003b2030 +0025000000010030740003efbfbd740002c2a4740003e2889e74000358585800 +0000017372000e6a6176612e7574696c2e44617465686a81014b597419030000 +78707708fffffe8f24e5cdd7787372001b6a6176612e746578742e4461746546 +6f726d617453796d626f6c73ace671c9351717c20200085b0005616d706d7374 +00135b4c6a6176612f6c616e672f537472696e673b5b00046572617371007e00 +294c00116c6f63616c5061747465726e436861727371007e00035b00066d6f6e +74687371007e00295b000b73686f72744d6f6e74687371007e00295b000d7368 +6f72745765656b6461797371007e00295b00087765656b6461797371007e0029 +5b000b7a6f6e65537472696e67737400145b5b4c6a6176612f6c616e672f5374 +72696e673b7870757200135b4c6a6176612e6c616e672e537472696e673badd2 +56e7e91d7b47020000787000000002740002414d740002504d7571007e002c00 +0000027400024243740002414474001247794d646b486d735345444677576168 +4b7a7571007e002c0000000d7400074a616e7561727974000846656272756172 +797400054d61726368740005417072696c7400034d61797400044a756e657400 +044a756c7974000641756775737474000953657074656d6265727400074f6374 +6f6265727400084e6f76656d626572740008446563656d62657271007e001f75 +71007e002c0000000d7400034a616e7400034665627400034d61727400034170 +7271007e00397400034a756e7400034a756c7400034175677400035365707400 +034f63747400034e6f7674000344656371007e001f7571007e002c0000000871 +007e001f74000353756e7400034d6f6e74000354756574000357656474000354 +68757400034672697400035361747571007e002c0000000871007e001f740006 +53756e6461797400064d6f6e646179740007547565736461797400095765646e +6573646179740008546875727364617974000646726964617974000853617475 +72646179757200145b5b4c6a6176612e6c616e672e537472696e673b324d09ad +8432e45702000078700000001d7571007e002c00000005740003505354740015 +50616369666963205374616e646172642054696d6571007e0060740015506163 +69666963204461796c696768742054696d657400035044547571007e002c0000 +0005740013416d65726963612f4c6f735f416e67656c657371007e006171007e +006071007e006271007e00637571007e002c000000057400034d53547400164d +6f756e7461696e205374616e646172642054696d6571007e00677400164d6f75 +6e7461696e204461796c696768742054696d657400034d44547571007e002c00 +00000574000e416d65726963612f44656e76657271007e006871007e00677100 +7e006971007e006a7571007e002c00000005740003504e5471007e006871007e +006771007e006871007e00677571007e002c0000000574000f416d6572696361 +2f50686f656e697871007e006871007e006771007e006871007e00677571007e +002c0000000574000343535474001543656e7472616c205374616e6461726420 +54696d6571007e007274001543656e7472616c204461796c696768742054696d +657400034344547571007e002c0000000574000f416d65726963612f43686963 +61676f71007e007371007e007271007e007471007e00757571007e002c000000 +057400034553547400154561737465726e205374616e646172642054696d6571 +007e00797400154561737465726e204461796c696768742054696d6574000345 +44547571007e002c00000005740010416d65726963612f4e65775f596f726b71 +007e007a71007e007971007e007b71007e007c7571007e002c00000005740003 +49455471007e007a71007e007971007e007a71007e00797571007e002c000000 +05740014416d65726963612f496e6469616e61706f6c697371007e007a71007e +007971007e007a71007e00797571007e002c0000000574000348535474001448 +6177616969205374616e646172642054696d6571007e008471007e008571007e +00847571007e002c00000005740010506163696669632f486f6e6f6c756c7571 +007e008571007e008471007e008571007e00847571007e002c00000005740003 +415354740014416c61736b61205374616e646172642054696d65740004414b53 +54740014416c61736b61204461796c696768742054696d65740004414b445475 +71007e002c00000005740011416d65726963612f416e63686f7261676571007e +008a71007e008b71007e008c71007e008d7571007e002c0000000574000f416d +65726963612f48616c6966617874001641746c616e746963205374616e646172 +642054696d6571007e008974001641746c616e746963204461796c6967687420 +54696d657400034144547571007e002c00000005740003434e5474001a4e6577 +666f756e646c616e64205374616e646172642054696d657400034e535474001a +4e6577666f756e646c616e64204461796c696768742054696d657400034e4454 +7571007e002c00000005740010416d65726963612f53745f4a6f686e7371007e +009771007e009871007e009971007e009a7571007e002c000000057400034543 +5474001e43656e7472616c204575726f7065616e205374616e64617264205469 +6d6574000343455474001e43656e7472616c204575726f7065616e204461796c +696768742054696d65740004434553547571007e002c0000000574000c457572 +6f70652f506172697371007e009f71007e00a071007e00a171007e00a2757100 +7e002c0000000571007e0017740013477265656e77696368204d65616e205469 +6d6571007e001771007e00a671007e00177571007e002c000000057400114166 +726963612f43617361626c616e636171007e00a671007e001771007e00a67100 +7e00177571007e002c0000000574000e417369612f4a65727573616c656d7400 +1449737261656c205374616e646172642054696d657400034953547400144973 +7261656c204461796c696768742054696d657400034944547571007e002c0000 +00057400034a53547400134a6170616e205374616e646172642054696d657100 +7e00b071007e00b171007e00b07571007e002c0000000574000a417369612f54 +6f6b796f71007e00b171007e00b071007e00b171007e00b07571007e002c0000 +00057400104575726f70652f42756368617265737474001e4561737465726e20 +4575726f7065616e205374616e646172642054696d6574000345455474001e45 +61737465726e204575726f7065616e204461796c696768742054696d65740004 +454553547571007e002c000000057400034354547400134368696e6120537461 +6e646172642054696d6571007e007271007e00bc71007e00757571007e002c00 +00000574000d417369612f5368616e6768616971007e00bc71007e007271007e +00bc71007e0075740019797979792e4d4d2e646420452068682e6d6d2e737320 +7a7a7a0a diff --git a/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java b/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java new file mode 100644 index 00000000000..9975672c806 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2000, 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 4348864 4112924 4425386 4495052 4836940 4851113 8008577 + * @summary test time zone display names in en_US locale + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneNameTest + */ + +import java.util.*; +import java.text.*; + +public class TimeZoneNameTest extends IntlTest +{ + static final String[] data = { + // Added to verify the fix for 4836940 + "N", "Antarctica/Rothera", "ROTT", "Rothera Time", "ROTT", "Rothera Time", + "N", "Asia/Tehran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time", + "N", "Iran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time", + + // Added to verify the fix for 4851113 + "N", "America/Rankin_Inlet", "CST", "Central Standard Time", "CDT", "Central Daylight Time", + "N", "Asia/Samarkand", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time", + "N", "Asia/Tashkent", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time", + "N", "Atlantic/Jan_Mayen", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "Europe/Oslo", "CET", "Central European Time", "CEST", "Central European Summer Time", + + "N", "Pacific/Honolulu", "HST", "Hawaii Standard Time", "HST", "Hawaii Standard Time", + "N", "America/Los_Angeles", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time", + "N", "US/Pacific", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time", + "N", "America/Phoenix", "MST", "Mountain Standard Time", "MST", "Mountain Standard Time", + "N", "America/Denver", "MST", "Mountain Standard Time", "MDT", "Mountain Daylight Time", + "N", "America/Chicago", "CST", "Central Standard Time", "CDT", "Central Daylight Time", + "N", "America/Indianapolis", "EST", "Eastern Standard Time", "EST", "Eastern Standard Time", + "N", "America/Montreal", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "N", "America/Toronto", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "N", "America/New_York", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "S", "America/Manaus", "AMT", "Amazon Time", "AMT", "Amazon Time", + "S", "America/Campo_Grande", "AMT", "Amazon Time", "AMST", "Amazon Summer Time", + "S", "America/Bahia", "BRT", "Brasilia Time", "BRST", "Brasilia Summer Time", + "N", "America/Halifax", "AST", "Atlantic Standard Time", "ADT", "Atlantic Daylight Time", + "N", "GMT", "GMT", "Greenwich Mean Time", "GMT", "Greenwich Mean Time", + "N", "Europe/London", "GMT", "Greenwich Mean Time", "BST", "British Summer Time", + "N", "Europe/Paris", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "WET", "WET", "Western European Time", "WEST", "Western European Summer Time", + "N", "Europe/Berlin", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "Asia/Jerusalem", "IST", "Israel Standard Time", "IDT", "Israel Daylight Time", + "N", "Europe/Helsinki", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time", + "N", "Africa/Cairo", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time", + "N", "Europe/Moscow", "MSK", "Moscow Standard Time", "MSD", "Moscow Daylight Time", + "N", "Asia/Omsk", "OMST", "Omsk Time", "OMSST", "Omsk Summer Time", + "N", "Asia/Shanghai", "CST", "China Standard Time", "CST", "China Standard Time", + "N", "Asia/Tokyo", "JST", "Japan Standard Time", "JST", "Japan Standard Time", + "N", "Japan", "JST", "Japan Standard Time", "JST", "Japan Standard Time", + "N", "Asia/Seoul", "KST", "Korea Standard Time", "KST", "Korea Standard Time", + "N", "ROK", "KST", "Korea Standard Time", "KST", "Korea Standard Time", + "S", "Australia/Darwin", "ACST", "Australian Central Standard Time (Northern Territory)", + "ACST", "Australian Central Standard Time (Northern Territory)", + "S", "Australia/Adelaide", "ACST", "Australian Central Standard Time (South Australia)", + "ACDT", "Australian Central Daylight Time (South Australia)", + "S", "Australia/Broken_Hill", "ACST", "Australian Central Standard Time (South Australia/New South Wales)", + "ACDT", "Australian Central Daylight Time (South Australia/New South Wales)", + "S", "Australia/Hobart", "AEST", "Australian Eastern Standard Time (Tasmania)", + "AEDT", "Australian Eastern Daylight Time (Tasmania)", + "S", "Australia/Brisbane", "AEST", "Australian Eastern Standard Time (Queensland)", + "AEST", "Australian Eastern Standard Time (Queensland)", + "S", "Australia/Sydney", "AEST", "Australian Eastern Standard Time (New South Wales)", + "AEDT", "Australian Eastern Daylight Time (New South Wales)", + "N", "Pacific/Guam", "ChST", "Chamorro Standard Time", + "ChST", "Chamorro Standard Time", + "N", "Pacific/Saipan", "ChST", "Chamorro Standard Time", + "ChST", "Chamorro Standard Time", + }; + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new TimeZoneNameTest().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + public void Test4112924() { + SimpleDateFormat lfmt = new SimpleDateFormat("zzzz"); + SimpleDateFormat sfmt = new SimpleDateFormat("z"); + + GregorianCalendar june = new GregorianCalendar(2000, Calendar.JUNE, 21); + GregorianCalendar december = new GregorianCalendar(2000, Calendar.DECEMBER, 21); + + int count = data.length; + for (int i = 0; i < count; i++) { + GregorianCalendar sol1, sol2; + + // check hemisphere + if ("N".equals(data[i++])) { + sol1 = december; + sol2 = june; + } else { + sol1 = june; + sol2 = december; + } + + TimeZone tz = TimeZone.getTimeZone(data[i++]); + lfmt.setTimeZone(tz); + sfmt.setTimeZone(tz); + + logln(tz.getID() + ": " + sfmt.format(sol1.getTime()) + ", " + lfmt.format(sol1.getTime())); + logln(tz.getID() + ": " + sfmt.format(sol2.getTime()) + ", " + lfmt.format(sol2.getTime())); + String s = sfmt.format(sol1.getTime()); + if (!data[i].equals(s)) { + errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = lfmt.format(sol1.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = sfmt.format(sol2.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = lfmt.format(sol2.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4097450.java b/jdk/test/java/text/Format/DateFormat/bug4097450.java new file mode 100644 index 00000000000..c70194bd877 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4097450.java @@ -0,0 +1,71 @@ +/* + * 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 + * 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 4097450 + */ + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class bug4097450 +{ + public static void main(String args[]) + { + // + // Date parse requiring 4 digit year. + // + String[] dstring = {"97","1997", "97","1997","01","2001", "01","2001" + , "1", + "1","11", "11","111", "111"}; + String[] dformat = {"yy", "yy","yyyy","yyyy","yy", "yy","yyyy","yyyy" + , + "yy","yyyy","yy","yyyy", "yy","yyyy"}; + boolean[] dresult = {true, false, false, true,true, false, false, true + ,false, + false,true, false,false, false}; + SimpleDateFormat formatter; + SimpleDateFormat resultFormatter = new SimpleDateFormat("yyyy"); + + System.out.println("Format\tSource\tResult"); + System.out.println("-------\t-------\t-------"); + for (int i = 0; i < dstring.length; i++) + { + System.out.print(dformat[i] + "\t" + dstring[i] + "\t"); + formatter = new SimpleDateFormat(dformat[i]); + try { + System.out.print(resultFormatter.format(formatter.parse(dstring[ + i]))); + //if ( !dresult[i] ) System.out.print(" <-- error!"); + } + catch (ParseException exception) { + //if ( dresult[i] ) System.out.print(" <-- error!"); + System.out.print("exception --> " + exception); + } + System.out.println(); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4099975.java b/jdk/test/java/text/Format/DateFormat/bug4099975.java new file mode 100644 index 00000000000..812b4996c0f --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4099975.java @@ -0,0 +1,41 @@ +/* + * 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 + * 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 4099975 + */ + +import java.text.*; +import java.util.Date; +public class bug4099975 { + public static void main (String args[]){ + DateFormatSymbols symbols = new DateFormatSymbols(); + SimpleDateFormat df = new SimpleDateFormat("E hh:mm", symbols); + System.out.println(df.toLocalizedPattern()); + symbols.setLocalPatternChars("abcdefghijklmonpqr"); // change value of field + System.out.println(df.toLocalizedPattern()); + + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4117335.java b/jdk/test/java/text/Format/DateFormat/bug4117335.java new file mode 100644 index 00000000000..6c9af2a4716 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4117335.java @@ -0,0 +1,83 @@ +/* + * 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 + * 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 4117335 4432617 + */ + +import java.text.DateFormatSymbols ; +import java.util.Locale; + +public class bug4117335 { + + public static void main(String[] args) throws Exception + { + DateFormatSymbols symbols = new DateFormatSymbols(Locale.JAPAN); + String[] eras = symbols.getEras(); + System.out.println("BC = " + eras[0]); + if (!eras[0].equals(bc)) { + System.out.println("*** Should have been " + bc); + throw new Exception("Error in BC"); + } + System.out.println("AD = " + eras[1]); + if (!eras[1].equals(ad)) { + System.out.println("*** Should have been " + ad); + throw new Exception("Error in AD"); + } + String[][] zones = symbols.getZoneStrings(); + for (int i = 0; i < zones.length; i++) { + if (!"Asia/Tokyo".equals(zones[i][0])) { + continue; + } + System.out.println("Long zone name = " + zones[i][1]); + if (!zones[i][1].equals(jstLong)) { + System.out.println("*** Should have been " + jstLong); + throw new Exception("Error in long TZ name"); + } + System.out.println("Short zone name = " + zones[i][2]); + if (!zones[i][2].equals(jstShort)) { + System.out.println("*** Should have been " + jstShort); + throw new Exception("Error in short TZ name"); + } + System.out.println("Long zone name = " + zones[i][3]); + if (!zones[i][3].equals(jdtLong)) { + System.out.println("*** Should have been " + jdtLong); + throw new Exception("Error in long TZ name"); + } + System.out.println("SHORT zone name = " + zones[i][4]); + if (!zones[i][4].equals(jdtShort)) { + System.out.println("*** Should have been " + jdtShort); + throw new Exception("Error in short TZ name"); + } + } + } + + static final String bc = "\u7d00\u5143\u524d"; + static final String ad = "\u897f\u66a6"; + static final String jstLong = "\u65e5\u672c\u6a19\u6e96\u6642"; + static final String jstShort = "JST"; + static final String jdtLong = "\u65e5\u672c\u590f\u6642\u9593"; + static final String jdtShort = "JDT"; +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4358730.java b/jdk/test/java/text/Format/DateFormat/bug4358730.java new file mode 100644 index 00000000000..dc448ecd767 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4358730.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2000, 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.*; +import java.util.*; +import java.text.*; + +/** + * @test + * @bug 4358730 + * @library /java/text/testlib + * @summary test that confirms Zero-Padding on year. + */ + +public class bug4358730 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4358730().run(args); + } + + String[] patterns = {"y", "yy", "yyy", "yyyy", "yyyyy"}; + String[][] data = { + /* 2 A.D. */ {"2", "02", "002", "0002", "00002"}, + /* 20 A.D. */ {"20", "20", "020", "0020", "00020"}, + /* 200 A.D. */ {"200", "00", "200", "0200", "00200"}, + /* 2000 A.D. */ {"2000", "00", "2000", "2000", "02000"}, + }; + int[] year = {2, 20, 200, 2000}; + + SimpleDateFormat sdf = new SimpleDateFormat(); + int datasize = data.length; + int nPatterns = data[0].length; + + public void Test4358730() { + Locale locale = Locale.getDefault(); + if (locale.equals(new Locale("th", "TH")) || + locale.equals(new Locale("hi", "IN"))) { + return; + } + + TimeZone saveZone = TimeZone.getDefault(); + Locale saveLocale = Locale.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + Locale.setDefault(new Locale("en", "US")); + + for (int i = 0; i < datasize; i++) { + Date d = new Date(year[i]-1900, 10, 15); + for (int j = 0; j < nPatterns; j++) { + sdf.applyPattern(patterns[j]); + if (!data[i][j].equals(sdf.format(d))) { + errln("Invalid format : " + sdf.format(d) + + ", expected : " + data[i][j]); + } + } + } + } + finally { + TimeZone.setDefault(saveZone); + Locale.setDefault(saveLocale); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6271375.java b/jdk/test/java/text/Format/DateFormat/bug6271375.java new file mode 100644 index 00000000000..811470a01d8 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6271375.java @@ -0,0 +1,61 @@ +/* + * 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 + * 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 6271375 7059546 + * @summary Make sure DateFormatSymbols serialization works + * correctly for 'zoneStrings' field + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class bug6271375 { + + public static void main(String[] args) throws Exception { + DateFormatSymbols dfsSrc = DateFormatSymbols.getInstance(); + + try (FileOutputStream fos = new FileOutputStream("dfs.ser"); + ObjectOutputStream oStream = new ObjectOutputStream(fos)) { + oStream.writeObject(dfsSrc); + } catch (Exception e) { + throw new RuntimeException("An exception is thrown.", e); + } + + try (FileInputStream fis = new FileInputStream("dfs.ser"); + ObjectInputStream iStream = new ObjectInputStream(fis)) { + DateFormatSymbols dfsDest = (DateFormatSymbols)iStream.readObject(); + + String[][] zoneStringsSrc = dfsSrc.getZoneStrings(); + String[][] zoneStringsDest = dfsDest.getZoneStrings(); + + if (!Arrays.deepEquals(zoneStringsSrc, zoneStringsDest)) { + throw new RuntimeException("src and dest zone strings are not equal"); + } + } catch (Exception e) { + throw new RuntimeException("An exception is thrown.", e); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6317072.java b/jdk/test/java/text/Format/DateFormat/bug6317072.java new file mode 100644 index 00000000000..d5614223679 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6317072.java @@ -0,0 +1,81 @@ +/* + * 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 + * 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 6317072 + * @summary Make sure NPE is thrown with "null" argumemnts in the + * SimpleDateFormat constructors. + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class bug6317072 { + + public static void main(String[] args) { + + try { + new SimpleDateFormat("yy", (Locale)null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat((String)null, Locale.getDefault()); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat("yy", (DateFormatSymbols)null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat((String)null, DateFormatSymbols.getInstance()); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getTimeInstance(DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getDateInstance(DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6412896.java b/jdk/test/java/text/Format/DateFormat/bug6412896.java new file mode 100644 index 00000000000..b5422814ac6 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6412896.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006, 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 6412896 + * @summary Make sure that an IllegalArgumentException is thrown + * if the length of any row in zoneStrings array is less than 5 + */ + +import java.text.*; + +public class bug6412896 { + + static final String[][] zoneOK = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time", "PDT"}}; + static final String[][] zoneNG = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time"}}; + + public static void main(String[] args) { + + DateFormatSymbols dfs = DateFormatSymbols.getInstance(); + + dfs.setZoneStrings(zoneOK); + + try { + dfs.setZoneStrings(zoneNG); + throw new RuntimeException("should throw an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt b/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt new file mode 100644 index 00000000000..1fb54165c49 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 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. +# + +# Hex dump of a serialized MessageFormat for Bug4185816Test. + +aced0005737200176a6176612e746578742e4d657373616765466f726d617459 +ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e +744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661 +2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75 +74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174 +7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176 +612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572 +00025b494dba602676eab2a502000078700000000a0000000100000000000000 +0000000000000000000000000000000000000000000000000000000000757200 +135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078 +700000000a70737200166a6176612e746578742e43686f696365466f726d6174 +18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c +6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473 +7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000 +2800010000000000000001000000000178757200135b4c6a6176612e6c616e67 +2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066 +696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c +6573757200025b443ea68c14ab635a1e02000078700000000300000000000000 +003ff000000000000040000000000000007070707070707070737200106a6176 +612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863 +6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e +00044c000776617269616e7471007e00047870ffffffff740002555374000265 +6e740000787571007e00070000000a0000000a00000015000000000000000000 +0000000000000000000000000000000000000000000000740016546865206469 +736b20222220636f6e7461696e73202e diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt b/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt new file mode 100644 index 00000000000..459d257339d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 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. +# + +# Hex dump of a corrupted serialized MessageFormat for Bug4185732Test. + +aced0005737200176a6176612e746578742e4d657373616765466f726d617459 +ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e +744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661 +2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75 +74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174 +7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176 +612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572 +00025b494dba602676eab2a502000078700000000a0000000100000000000000 +0000000000000000000000000000000000000000000000000000000000757200 +135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078 +700000000a70737200166a6176612e746578742e43686f696365466f726d6174 +18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c +6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473 +7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000 +2800010000000000000001000000000178757200135b4c6a6176612e6c616e67 +2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066 +696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c +6573757200025b443ea68c14ab635a1e02000078700000000300000000000000 +003ff000000000000040000000000000007070707070707070737200106a6176 +612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863 +6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e +00044c000776617269616e7471007e00047870ffffffff740002555374000265 +6e740000787571007e00070000000a0000000a00000015000000000000000000 +0000000000000000000000000000000000000000000000740010546865206469 +736b20222220636f6e74 diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java b/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java new file mode 100644 index 00000000000..65609941f53 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1999, 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 4185816 + * @library /java/text/testlib + * @build Bug4185816Test IntlTest HexDumpReader + * @run main Bug4185816Test + * @summary test that MessageFormat invariants are preserved across serialization + */ +/* + * + * + * (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.util.*; +import java.io.*; +import java.text.ChoiceFormat; +import java.text.MessageFormat; + +/** + * A Locale can never contains language codes of he, yi or id. + */ +public class Bug4185816Test extends IntlTest { + private static final String FILE_NAME = "Bug4185816.ser"; + private static final String CORRUPT_FILE_NAME = "Bug4185816Corrupt.ser"; + + public static void main(String[] args) throws Exception { + if (args.length == 1 && args[0].equals("prepTest")) { + prepTest(); + } else { + new Bug4185816Test().run(args); + } + } + + public void testIt() throws Exception { + Exception e = checkStreaming(FILE_NAME); + if (e != null) { + errln("MessageFormat did not stream in valid stream: "+e); + e.printStackTrace(); + } + e = checkStreaming(CORRUPT_FILE_NAME); + if (!(e instanceof InvalidObjectException)) { + errln("MessageFormat did NOT detect corrupt stream: "+e); + e.printStackTrace(); + } + } + + public Exception checkStreaming(final String fileName) { + try { + final InputStream is = HexDumpReader.getStreamFromHexDump(fileName + ".txt"); + final ObjectInputStream in = new ObjectInputStream(is); + final MessageFormat form = (MessageFormat)in.readObject(); + final Object[] testArgs = {new Long(12373), "MyDisk"}; + final String result = form.format(testArgs); + in.close(); + } catch (Exception e) { + return e; + } + return null; + } + + /** + * Create a data file for this test. The data file must be corrupted by hand. + */ + private static void prepTest() { + writeFormatToFile(FILE_NAME); + writeFormatToFile(CORRUPT_FILE_NAME); + } + + private static void writeFormatToFile(final String name) { + try { + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream(name)); + + MessageFormat fmt = new MessageFormat("The disk \"{1}\" contains {0}."); + double[] filelimits = {0,1,2}; + String[] filepart = {"no files","one file","{0,number} files"}; + ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); + fmt.setFormat(1,fileform); // NOT zero, see below + + out.writeObject(fmt); + out.close(); + } catch (Exception e) { + System.out.println(e); + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/Bug6481179.java b/jdk/test/java/text/Format/MessageFormat/Bug6481179.java new file mode 100644 index 00000000000..be8e9e29f11 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug6481179.java @@ -0,0 +1,64 @@ +/* + * 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 + * 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 Confirm that a bug in an error message has been fixed. + * @bug 6481179 + */ + +import java.text.MessageFormat; +import java.text.ParseException; + +public class Bug6481179 { + + public static void main(String[] args) { + boolean err = false; + + try { + MessageFormat.format("Testdata {1,invalid_format_type}", + new Object[] { "val0", "val1" }); + + System.err.println("Error: IllegalArgumentException should be thrown."); + err = true; + } + catch (IllegalArgumentException e) { + String expected = "unknown format type: invalid_format_type"; + String got = e.getMessage(); + + if (!expected.equals(got)) { + System.err.println("Error: Unexpected error message: " + got); + err = true; + } + } + catch (Exception e) { + System.err.println("Error: Unexpected exception was thrown: " + e); + err = true; + } + + if (err) { + throw new RuntimeException("Failed."); + } + } + +} diff --git a/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java b/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java new file mode 100644 index 00000000000..1a4ca1d092d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2000, 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 4112090 8008577 + * @summary verify that MessageFormat can handle large numbers of arguments + * @run main/othervm -Djava.locale.providers=COMPAT,SPI LargeMessageFormat + */ + +import java.text.MessageFormat; +import java.text.ParseException; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class LargeMessageFormat { + + public static void main(String[] args) throws ParseException { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + Locale.setDefault(Locale.GERMANY); + TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")); + testFormat(); + testParse(); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + private static final int REPEATS = 89; + + private static void testFormat() { + // construct large argument array + Object[] sample = { + new Integer(0), // replace with running count below + "hello", + new Date(89, 10, 9), + new Integer(567890), + new Double(1234.50) + }; + int samples = sample.length; + Object[] arguments = new Object[REPEATS * (samples + 1)]; + for (int i = 0; i < REPEATS; i++) { + System.arraycopy(sample, 0, arguments, i * samples, samples); + arguments[i * samples] = new Integer(i); + } + + // construct large template + StringBuffer template = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + template.append("section {" + (i * samples) + ", number} - "); + template.append("string: {" + (i * samples + 1) + "}; "); + template.append("date: {" + (i * samples + 2) + ", date}; "); + template.append("integer: {" + (i * samples + 3) + ", number}; "); + template.append("currency: {" + (i * samples + 4) + ", number, currency};\n"); + } + + // construct expected result string + StringBuffer expected = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + expected.append("section " + i + " - "); + expected.append("string: hello; "); + expected.append("date: 09.11.1989; "); + expected.append("integer: 567.890; "); + expected.append("currency: 1.234,50 \u20AC;\n"); + } + + // create message format + MessageFormat format = new MessageFormat(template.toString()); + String result = format.format(arguments); + if (!result.equals(expected.toString())) { + System.out.println("Template:"); + System.out.println(template); + System.out.println("Expected result: "); + System.out.println(expected); + System.out.println("Actual result: "); + System.out.println(result); + throw new RuntimeException(); + } + } + + private static void testParse() throws ParseException { + StringBuffer parseTemplate = new StringBuffer(); + StringBuffer parseInput = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + parseTemplate.append("{" + i + ", number} "); + parseInput.append(i + " "); + } + MessageFormat parseFormat = new MessageFormat(parseTemplate.toString()); + Object[] parseResult = parseFormat.parse(parseInput.toString()); + for (int i = 0; i < REPEATS; i++) { + if (((Number) parseResult[i]).intValue() != i) { + throw new RuntimeException("got wrong parse result"); + } + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java b/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java new file mode 100644 index 00000000000..1d69258f68d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2000, 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 4105380 + * @summary basic tests for new methods getFormatsByArgumentIndex, setFormatByArgumentIndex, setFormatsByArgumentIndex + */ + +import java.text.ChoiceFormat; +import java.text.Format; +import java.text.MessageFormat; +import java.text.NumberFormat; + +public class MessageFormatsByArgumentIndex { + + private static String choicePattern = "0.0#are no files|1.0#is one file|1.0 subsitution failed. result = " + tempBuffer.toString()); + logln("Formatted with extra params : " + tempBuffer); + //This statement gives an exception while formatting... + //If we use pattern[1] for the message with param, + //we get an NullPointerException in MessageFormat.java(617) + //If we use pattern[2] for the message with param, + //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614) + //Both are due to maxOffset not being reset to -1 + //in applyPattern() when the pattern does not + //contain any param. + } catch (Exception foo) { + errln("Exception when formatting with no params."); + } + } + + /* @bug 4058973 + * MessageFormat.toPattern has weird rounding behavior. + */ + public void Test4058973() { + + MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}"); + String pat = fmt.toPattern(); + if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) { + errln("MessageFormat.toPattern failed"); + } + } + /* @bug 4031438 + * More robust message formats. + */ + public void Test4031438() { + String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}."; + String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'."; + + // If the current locale is hi_IN, skip this test case. + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + MessageFormat messageFormatter = new MessageFormat(""); + + try { + logln("Apply with pattern : " + pattern1); + messageFormatter.applyPattern(pattern1); + Object[] params = {new Integer(7)}; + String tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}.")) + errln("Tests arguments < substitution failed. Formatted text=" + + "<" + tempBuffer + ">"); + logln("Formatted with 7 : " + tempBuffer); + ParsePosition status = new ParsePosition(0); + Object[] objs = messageFormatter.parse(tempBuffer, status); + if (objs[params.length] != null) + errln("Parse failed with more than expected arguments"); + for (int i = 0; i < objs.length; i++) { + if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) { + errln("Parse failed on object " + objs[i] + " at index : " + i); + } + } + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}.")) + errln("Tests with no arguments failed"); + logln("Formatted with null : " + tempBuffer); + logln("Apply with pattern : " + pattern2); + messageFormatter.applyPattern(pattern2); + tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ params) failed."); + logln("Formatted with params : " + tempBuffer); + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ null) failed."); + logln("Formatted with null : " + tempBuffer); + logln("toPattern : " + messageFormatter.toPattern()); + } catch (Exception foo) { + errln("Exception when formatting in bug 4031438. "+foo.getMessage()); + } + } + public void Test4052223() + { + ParsePosition pos = new ParsePosition(0); + if (pos.getErrorIndex() != -1) { + errln("ParsePosition.getErrorIndex initialization failed."); + } + MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree."); + String str = new String("There is one apple growing on the peach tree."); + Object[] objs = fmt.parse(str, pos); + logln("unparsable string , should fail at " + pos.getErrorIndex()); + if (pos.getErrorIndex() == -1) + errln("Bug 4052223 failed : parsing string " + str); + pos.setErrorIndex(4); + if (pos.getErrorIndex() != 4) + errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4"); + ChoiceFormat f = new ChoiceFormat( + "-1#are negative|0#are no or fraction|1#is one|1.0"); + Object[] objs1 = null; + Object[] objs2 = {}; + Object[] objs3 = {null}; + try { + logln("pattern: \"" + mf.toPattern() + "\""); + log("format(null) : "); + logln("\"" + mf.format(objs1) + "\""); + log("format({}) : "); + logln("\"" + mf.format(objs2) + "\""); + log("format({null}) :"); + logln("\"" + mf.format(objs3) + "\""); + } catch (Exception e) { + errln("Exception thrown for null argument tests."); + } + } + + /* @bug 4113018 + * MessageFormat.applyPattern works wrong with illegal patterns. + */ + public void Test4113018() + { + String originalPattern = "initial pattern"; + MessageFormat mf = new MessageFormat(originalPattern); + String illegalPattern = "format: {0, xxxYYY}"; + logln("pattern before: \"" + mf.toPattern() + "\""); + logln("illegal pattern: \"" + illegalPattern + "\""); + try { + mf.applyPattern(illegalPattern); + errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern); + } catch (IllegalArgumentException e) { + if (!originalPattern.equals(mf.toPattern())) + errln("pattern after: \"" + mf.toPattern() + "\""); + } + } + /* @bug 4106661 + * ChoiceFormat is silent about the pattern usage in javadoc. + */ + public void Test4106661() + { + ChoiceFormat fmt = new ChoiceFormat( + "-1#are negative| 0#are no or fraction | 1#is one |1.0 " + + out + "; want \"" + DATA[i+1+j] + '"'); + } + String pat = cf.toPattern(); + String pat2 = new ChoiceFormat(pat).toPattern(); + if (!pat.equals(pat2)) + errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + else + logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + } + catch (IllegalArgumentException e) { + errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e); + } + } + } + + /** + * @bug 4112104 + * MessageFormat.equals(null) throws a NullPointerException. The JLS states + * that it should return false. + */ + public void Test4112104() { + MessageFormat format = new MessageFormat(""); + try { + // This should NOT throw an exception + if (format.equals(null)) { + // It also should return false + errln("MessageFormat.equals(null) returns false"); + } + } + catch (NullPointerException e) { + errln("MessageFormat.equals(null) throws " + e); + } + } + + /** + * @bug 4169959 + * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG. + */ + public void Test4169959() { + // This works + logln(MessageFormat.format( "This will {0}", + new String[]{"work"} ) ); + + // This fails + logln(MessageFormat.format( "This will {0}", + new Object[]{ null } ) ); + } + + public void test4232154() { + boolean gotException = false; + try { + MessageFormat format = new MessageFormat("The date is {0:date}"); + } catch (Exception e) { + gotException = true; + if (!(e instanceof IllegalArgumentException)) { + throw new RuntimeException("got wrong exception type"); + } + if ("argument number too large at ".equals(e.getMessage())) { + throw new RuntimeException("got wrong exception message"); + } + } + if (!gotException) { + throw new RuntimeException("didn't get exception for invalid input"); + } + } + + public void test4293229() { + MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''"); + Object[] args = { null }; + String expected = "'{0}' '{0}'"; + String result = format.format(args); + if (!result.equals(expected)) { + throw new RuntimeException("wrong format result - expected \"" + + expected + "\", got \"" + result + "\""); + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/MessageTest.java b/jdk/test/java/text/Format/MessageFormat/MessageTest.java new file mode 100644 index 00000000000..9234ae90c9f --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/MessageTest.java @@ -0,0 +1,102 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test MessageFormat + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - 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. +*/ + + +import java.util.*; +import java.io.*; +import java.text.*; + +public class MessageTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new MessageTest().run(args); + } + + + public void TestMSGPatternTest() { + Object[] testArgs = { + new Double (1), new Double(3456), + "Disk", new Date(10000000000L)}; + + String[] testCases = { + "Quotes '', '{', 'a' {0} '{0}'", + "Quotes '', '{', 'a' {0,number} '{0}'", + "'{'1,number,'#',##} {1,number,'#',##}", + "There are {1} files on {2} at {3}", + "On {2}, there are {1} files, with {0,number,currency}.", + "'{1,number,percent}', {1,number,percent}, ", + "'{1,date,full}', {1,date,full}, ", + "'{3,date,full}', {3,date,full}, ", + "'{1,number,#,##}' {1,number,#,##}", + }; + + for (int i = 0; i < testCases.length; ++i) { + Locale save = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + logln(""); + logln( i + " Pat in: " + testCases[i]); + MessageFormat form = new MessageFormat(testCases[i]); + logln( i + " Pat out: " + form.toPattern()); + String result = form.format(testArgs); + logln( i + " Result: " + result); + Object[] values = form.parse(result); + for (int j = 0; j < testArgs.length; ++j) { + Object testArg = testArgs[j]; + Object value = null; + if (j < values.length) { + value = values[j]; + } + if ((testArg == null && value != null) + || (testArg != null && !testArg.equals(value))) { + logln( i + " " + j + " old: " + testArg); + logln( i + " " + j + " new: " + value); + } + } + } + catch(java.text.ParseException pe ) { + throw new RuntimeException("Error: MessageFormat.parse throws ParseException"); + } + finally{ + Locale.setDefault(save); + } + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/bug4492719.java b/jdk/test/java/text/Format/MessageFormat/bug4492719.java new file mode 100644 index 00000000000..6a1d2184ffe --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/bug4492719.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001, 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 4492719 + * @library /java/text/testlib + * @summary Confirm that Message.parse() interprets time zone which uses "GMT+/-" format correctly and doesn't throw ParseException. + */ + +import java.util.*; +import java.text.*; + +public class bug4492719 extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + MessageFormat mf; + boolean err =false; + + String[] formats = { + "short", "medium", "long", "full" + }; + String[] timezones = { + "America/Los_Angeles", "GMT", "GMT+09:00", "GMT-8:00", + "GMT+123", "GMT-1234", "GMT+2", "GMT-13" + }; + String text; + + Locale.setDefault(Locale.US); + + try { + for (int i = 0; i < timezones.length; i++) { + TimeZone.setDefault(TimeZone.getTimeZone(timezones[i])); + + for (int j = 0; j < formats.length; j++) { + mf = new MessageFormat("{0,time," + formats[j] + "} - time"); + text = MessageFormat.format("{0,time," + formats[j] + "} - time", + new Object [] { new Date(123456789012L)}); + Object[] objs = mf.parse(text); + } + } + } catch (ParseException e) { + err = true; + System.err.println("Invalid ParseException occurred : " + + e.getMessage()); + System.err.println(" TimeZone=" + TimeZone.getDefault()); + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + if (err) { + throw new Exception("MessageFormat.parse(\"GMT format\") failed."); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java new file mode 100644 index 00000000000..1a2e7bf3945 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java @@ -0,0 +1,134 @@ +/* + * 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 + * 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 4018937 + * @summary Confirm that DecimalFormat.parse() parses BigDecimal and BigInteger as expected. + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class BigDecimalCompatibilityTest { + + static boolean err = false; + + static final String[] input_data = { + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + }; + static final String[] exponents = { + "E-100", "E100", "E-900", "E900", "" + }; + static final int[] multipliers = { + -1, 1, -100, 100, -9999, 9999 + }; + + public static void main(String[] args) throws Exception { + Locale loc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + testBigDecimal(); + testBigInteger(); + + Locale.setDefault(loc); + + if (err) { + throw new RuntimeException("Error: Unexpected value"); + } + } + + static private void testBigDecimal() { + DecimalFormat df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMaximumFractionDigits(Integer.MAX_VALUE); + + for (int i = 0; i < input_data.length; i++) { + for (int j = 0; j < input_data.length; j++) { + for (int k = 0; k < input_data.length; k++) { + for (int l = 0; l < input_data.length; l++) { + for (int m = 0; m < exponents.length; m++) { + String s = input_data[i] + input_data[j] + '.' + + input_data[k] + input_data[l] + + exponents[m]; + for (int n = 0; n < multipliers.length; n++) { + test(df, s, multipliers[n]); + test(df, '-'+s, multipliers[n]); + } + } + } + } + } + } + } + + static private void testBigInteger() { + DecimalFormat df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMaximumFractionDigits(Integer.MAX_VALUE); + + for (int i = 0; i < input_data.length; i++) { + for (int j = 0; j < input_data.length; j++) { + String s = input_data[i] + input_data[j]; + for (int k = 0; k < multipliers.length; k++) { + test(df, s, multipliers[k]); + test(df, '-'+s, multipliers[k]); + } + } + } + } + + static void test(DecimalFormat df, String s, int multiplier) { + df.setMultiplier(multiplier); + + Number num = null; + try { + num = df.parse(s); + } + catch (ParseException e) { + err = true; + System.err.println("Failed: Exception occurred: " + e.getMessage()); + return; + } + + BigDecimal bd = new BigDecimal(s); + try { + bd = bd.divide(new BigDecimal(multiplier)); + } + catch (ArithmeticException e) { + bd = bd.divide(new BigDecimal(multiplier), BigDecimal.ROUND_HALF_EVEN); + } + check(num, bd, multiplier); + } + + static void check(Number got, BigDecimal expected, int multiplier) { + if (!got.equals(expected)) { + err = true; + System.err.println("Failed: got:" + got + + ", expected: " + expected + + ", multiplier=" + multiplier); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java new file mode 100644 index 00000000000..14b3a9fec62 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java @@ -0,0 +1,1044 @@ +/* + * 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 + * 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 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalFormat + */ + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.*; +import java.util.*; + +public class BigDecimalFormat extends IntlTest { + + public static void main(String[] args) throws Exception { + new BigDecimalFormat().run(args); + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + StringBuffer formatted = new StringBuffer(1000); + FieldPosition fp; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Format_in_NumberFormat_BigDecimal() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...789 + // To: 0.000...789 (same as From) + formatted.setLength(0); + from = "0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...789 + // To: -0.000...789 (same as From) + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...789 + // To: 123,4...7,890.012...789 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = nonsep_int + "." + fra; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 479); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...789 + // To: -123,4...7,890.012...789 + // ~~~~~~~~~ : FieldPosition(FRACTION_FIELD) + fp = new FieldPosition(DecimalFormat.FRACTION_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 481, 841); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.000...789 + // To: 123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.000...789 + // To: -123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000 + // To: 123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000 + // To: -123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0000 + // To: 0 + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...00001234 + // To: 1,234 + formatted.setLength(0); + from = nonsep_zero + "1234"; + to = "1,234"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...00001234 + // To: -1,234 + // ~ : FieldPosition(GROUPING_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero + "1234"; + to = "-1,234"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 2, 3); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000.0...0 + // To: 0 + formatted.setLength(0); + from = nonsep_zero + "." + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000.0...0 + // To: 0.0 + formatted.setLength(0); + from = "-" + nonsep_zero + "." + nonsep_zero; + to = "0.0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...7890...0 + // To: 1,234...7,890.0123...789 + formatted.setLength(0); + from = nonsep_int + "." + fra + nonsep_zero; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...7890...0 + // To: -1,234...7,890.0123...789 + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra + nonsep_zero; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 1123...890.012...789 + // To : 1.123...8900123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 726); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789 + // To : -1.123...8900123...789E360 + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...0001123...890.012...789 + // To : 1.123...8900123...789E-360 + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1123...890.012...789000...000 + // To : 1.123...8900123...789E360 + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra + nonsep_zero; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789000...000 + // To : -1.123...8900123...789E360 + // ~ : FieldPosition(EXPONENT_SYMBOL) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SYMBOL); + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra + nonsep_zero; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 724); + + /* ------------------------------------------------------------------ */ + + // From: 0.000...0001123...890.012...789000...000 + // To : 1.123...8900123...789E-360 + // ~ : FieldPosition(EXPONENT_SIGN) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SIGN); + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 364); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789000...000 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC1123...890.012...789 + // To : ABC1.123...890.0123...789 + formatted = new StringBuffer("ABC"); + from = "1" + nonsep_int + "." + fra; + to = "ABC1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC-1123...890.012...789 + // To : ABC-1.123...890.0123...789 + // ~ : FieldPosition(DECIMAL_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted = new StringBuffer("ABC"); + from = "-1" + nonsep_int + "." + fra; + to = "ABC-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 5, 6); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 726, 0); + + // From: 0.000...000012...7890123456789 + // To: 0.000...000012...789012346 (Shorter than From) + formatted.setLength(0); + from = "0." + nonsep_zero + fra + fra; + to = "0." + nonsep_zero + fra + "012346"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 723, 0); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...000012...7890123456789 + // To: -0.000...000012...789012 (Shorter than From) + formatted.setLength(0); + from = "-0." + nonsep_zero + fra + fra; + to = "-0." + nonsep_zero + fra + "012"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, 370, 0); + + // From: 1234567890.012...78901234567890 + // To: 12345.67890012...789012346E5 + formatted.setLength(0); + from = "1234567890." + fra + "0123456789"; + to = "12345.67890" + fra + "01235E5"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 364, 0); + + // From: -0.000...0001012...7890123456789 + // To: -1.012...789012E-361 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + "0123456789"; + to = "-1." + fra + "0123E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 366, 0); + + // From: 1012...78901234567890 + // To: 1.012...789012346E370 + formatted.setLength(0); + from = "1" + fra + "0123456789"; + to = "1." + fra + "012346E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 363, 0); + + // From: -1012...7890123456789 + // To: -1.012...789012E370 + formatted.setLength(0); + from = "-1" + fra + "0123456789"; + to = "-1." + fra + "012E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 720); + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Format_in_NumberFormat_BigDecimal_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: 250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(-250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: -250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Format_in_NumberFormat_BigInteger() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890 + // To: -123,4...7,890 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 480); + + /* ------------------------------------------------------------------ */ + + // From: 000...0001234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_zero + nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0001234...7890 + // To: -123,4...7,890 + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-" + nonsep_zero + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000 + // To: 0.0 + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0.0"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 2); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 10123...789 + // To : 1.0123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + fra; + to = "1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 366); + + /* ------------------------------------------------------------------ */ + + // From: -1012...789 + // To : -1.012...789E360 + formatted.setLength(0); + from = "-1" + fra; + to = "-1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 720); + + // From: 12345012...789000...000 + // To : 12345.012...789000...000E720 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "12345" + fra + nonsep_zero; + to = "12345." + fra + nonsep_zero + "E720"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 727, 730); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 365); + + // From: -1234567890012...789000...000 + // To : -12345.67890012...789E365 + formatted.setLength(0); + from = "-1234567890" + fra; + to = "-12345.67890" + fra + "E365"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Format_in_NumberFormat_BigInteger_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(-250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal Long numbers when maximum and minimum digits are + * specified + */ + void test_Format_in_NumberFormat_Long_checkDigits() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: 1234567890 + // To: 000,0...0,000,123,456,789 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = sep_zero.substring(0, 399) + ",123,456,789"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###"); + ((DecimalFormat)nf).setMultiplier(-1); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: 1234567890 + // To: -0000...0000123456789.000...000 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = "-" + nonsep_zero.substring(0, 300) + "123456789." + + nonsep_zero.substring(0, 340); + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: Long.MAX_VALUE + // To: 000,0...0,000,019,807,040,619,342,712,359,383,728,129 + // --------------- + // 280 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,619,342,712,359,383,728,129"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 360); + + // From: Long.MAX_VALUE + // To: -1.9807040628566084396238503936000...000E28 + // --------- + // 312 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = "-1.9807040628566084396238503936" + + nonsep_zero.substring(0, 312) + "E28"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: -198070406193427123615312117760000...0000.000...000E-280 + // ----------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = "-19807040619342712361531211776" + + nonsep_zero.substring(0, 280) + "." + + nonsep_zero.substring(0, 340) + "E-280"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: 000,0...0,000,019,807,040,628,566,084,398,385,987,584.000...000 + // --------------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,628,566,084,398,385,987,584." + + nonsep_zero.substring(0, 340); + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Format_in_NumberFormat_SpecialNumber() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + double[] numbers = { + -0.0, 0.0, Double.NaN, + Double.POSITIVE_INFINITY, 5.1, 5.0, + Double.NEGATIVE_INFINITY, -5.1, -5.0, + }; + int multipliers[] = {0, 5, -5}; + String[][] expected = { + {"-0", "0", "\ufffd", "\ufffd", "0", "0", "\ufffd", "-0", "-0"}, + {"-0", "0", "\ufffd", "\u221e", "25.5", "25", "-\u221e", "-25.5", + "-25"}, + {"0", "-0", "\ufffd", "-\u221e", "-25.5", "-25", "\u221e", "25.5", + "25"}, + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for Long.MIN_VALUE + * (Formatting Long.MIN_VALUE w/ multiplier=-1 used to return a wrong + * number.) + */ + void test_Format_in_NumberFormat_Other() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + long[] numbers = { + Long.MIN_VALUE, + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9,223,372,036,854,775,808"}, // Long.MIN_VALUE + {"9,223,372,036,854,775,808"}, // Long.MIN_VALUE * (-1) + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for MessageFormat + */ + void test_Format_in_MessageFormat() { + MessageFormat mf = new MessageFormat( + " {0, number}\n" + + " {0, number, integer}\n" + + " {0, number, currency}\n" + + " {0, number, percent}\n" + + " {0, number,0.###########E0}\n" + + + " {1, number}\n" + + " {1, number, integer}\n" + + " {1, number, currency}\n" + + " {1, number, percent}\n" + + " {1, number,0.#######E0}\n", + Locale.US + ); + Object[] testArgs = { + new BigInteger("9876543210987654321098765432109876543210"), + new BigDecimal("-12345678901234567890.98765432109876543210987654321"), + }; + String expected = + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00\n" + + " 987,654,321,098,765,432,109,876,543,210,987,654,321,000%\n" + + " 9.87654321099E39\n" + + + " -12,345,678,901,234,567,890.988\n" + + " -12,345,678,901,234,567,891\n" + + " ($12,345,678,901,234,567,890.99)\n" + + " -1,234,567,890,123,456,789,099%\n" + + " -1.2345679E19\n" + ; + + if (!expected.equals(mf.format(testArgs))) { + errln("Wrong format.\n got:\n" + mf.format(testArgs) + + " expected:\n" + expected); + } + } + + private void setDigits(NumberFormat nf, + int i_max, int i_min, int f_max, int f_min) { + nf.setMaximumIntegerDigits(i_max); + nf.setMinimumIntegerDigits(i_min); + nf.setMaximumFractionDigits(f_max); + nf.setMinimumFractionDigits(f_min); + } + + private void checkFormat(String orig, StringBuffer got, String expected, + int multiplier) { + if (!expected.equals(new String(got))) { + errln("Formatting... failed." + + "\n original: " + orig + + "\n multiplier: " + multiplier + + "\n formatted: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkFieldPosition(String orig, FieldPosition fp, int begin, + int end) { + int position; + + if ((position = fp.getBeginIndex()) != begin) { + errln("Formatting... wrong Begin index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + begin + "\n"); + } + if ((position = fp.getEndIndex()) != end) { + errln("Formatting... wrong End index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + end + "\n"); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java new file mode 100644 index 00000000000..be206052d06 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java @@ -0,0 +1,709 @@ +/* + * 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 + * 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 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalParse + */ + +import java.math.BigDecimal; +import java.text.*; +import java.util.*; + +public class BigDecimalParse extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale loc = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new BigDecimalParse().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(loc); + } + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + Number parsed = null; + ParsePosition pp; + boolean exceptionOccurred; + String msg; + DecimalFormat df; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Parse_in_DecimalFormat_BigDecimal() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 1234...7890.012...789 + // To: BigDecimal 1234...7890.012...789 + check(nonsep_int + "." + fra, new BigDecimal(nonsep_int + "." + fra)); + + // From: -1,234...7,890.012...789 + // To: BigDecimal -1234...7890.012...789 + check("-" + sep_int + "." + fra, + new BigDecimal("-" + nonsep_int + "." + fra)); + + // From: 000...0000.0...0 + // To: BigDecimal 0E-360 + check(nonsep_zero + "." + nonsep_zero, + new BigDecimal(nonsep_zero + "." + nonsep_zero)); + + // From: 0.000...0000123...789E370 + // To: BigDecimal 0.0123...789 + check("0.0000000000" + nonsep_zero + fra + "E370", + new BigDecimal("0.0000000000" + nonsep_zero + fra + "E370")); + + // From: 0.1123...890E-360 + // To: BigDecimal 1.123...890E-361 + check("0.1" + nonsep_int + "E-360", + new BigDecimal("0.1" + nonsep_int + "E-360")); + + // From: 000...0000.0...0123...7890 + // To: BigDecimal 1.234...890E-361 + check(nonsep_zero + "." + nonsep_zero + nonsep_int, + new BigDecimal(nonsep_zero + "." + nonsep_zero + nonsep_int)); + + // From: 0.123...890E360 + // To: BigDecimal 123...890 + check("0." + nonsep_int + "E360", + new BigDecimal("0." + nonsep_int + "E360")); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Parse_in_DecimalFormat_BigDecimal_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000.000...000 + // To: 1000...0000.000...000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: -1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: 250,0...0,000.000...000 + // To: -1000...0000.000...000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: 1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that ArithmeticException is handled properly + // From: 1000.000 + // To: 333.333 + df.setMultiplier(3); + check("1000.000", new BigDecimal("333.333")); + + // Confirm that ArithmeticException is handled properly + // From: 10000.0000 + // To: 303.0303 + df.setMultiplier(33); + check("10000.0000", new BigDecimal("303.0303")); + } + + /** + * Test for division by zero (BigDecimal) + */ + void test_Parse_in_DecimalFormat_BigDecimal_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", new Double(Double.NEGATIVE_INFINITY)); + + // From: -0.00 + // To: Double.NaN + check("-0.00", new Double(Double.NaN)); + } + + /** + * Test for division by zero (Double) + */ + void test_Parse_in_DecimalFormat_Double_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000.000 + // To: Double.NEGATIVE_INFINITY + check("-1000.000", new Double(Double.NEGATIVE_INFINITY)); + + // From: 0.0 + // To: Double.NaN + check("0.0", new Double(Double.NaN)); + + // From: -0.0 (Double) + // To: Double.NaN + check("-0.0", new Double(Double.NaN)); + + // From: Double.NaN + // To: Double.NaN + check("\ufffd", new Double(Double.NaN)); + + // From: Double.POSITIVE_INFINITY + // To: Double.NaN + check("\u221e", new Double(Double.POSITIVE_INFINITY)); + + // From: Double.NEGATIVE_INFINITY + // To: Double.NaN + check("-\u221e", new Double(Double.NEGATIVE_INFINITY)); + } + + /** + * Test for division by zero (Long) + */ + void test_Parse_in_DecimalFormat_Long_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000 + // To: Double.POSITIVE_INFINITY + check("1000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", new Double(Double.NEGATIVE_INFINITY)); + + // From: -000 (Long) + // To: Double.NaN + check("-000", new Double(Double.NaN)); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Parse_in_DecimalFormat_BigInteger() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 123...890 + // To: BigDecimal 123...890 + check(nonsep_int + nonsep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: 123,4...7,890 + // To: BigDecimal 1234...7890 + check(sep_int + "," + sep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: -000...000123...890 + // To: BigDecimal -123...890 + check("-" + nonsep_zero + nonsep_int, new BigDecimal("-" + nonsep_int)); + + // From: -000,0...0,000,123,4...7,890 + // To: BigDecimal -123...890 + check("-" + sep_zero + "," + sep_int, new BigDecimal("-" + nonsep_int)); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Parse_in_DecimalFormat_BigInteger_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000 + // To: 1000...0000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: -1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: 250,0...0,000 + // To: -1000...0000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: 1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: 250,0...0,000E-360 + // To: -1000...0000.000...000 + check("250,000,000," + sep_zero + "," + sep_zero + "E-360", + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that a division which results in a irrational number is done + // properly + // From: 1000 + // To: 333 + df.setMultiplier(3); + check("1000", new BigDecimal("333")); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Parse_in_DecimalFormat_SpecialNumber() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "0", "0.0", "25", "25.0", "25.5", "\u221e", "\ufffd", + "-0", "-0.0", "-25", "-25.0", "-25.5", "-\u221e", + }; + int multipliers[] = {5, -5}; + Number[][] expected = { + { + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + new Double(Double.POSITIVE_INFINITY), new Double(Double.NaN), + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN), + }, + { + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN), + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + new Double(Double.POSITIVE_INFINITY), + }, + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), expected[i][j]); + } + } + } + + /** + * Test for special numbers + */ + void test_Parse_in_DecimalFormat_Other() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "-9223372036854775808", // Long.MIN_VALUE + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9223372036854775808"}, // Long.MIN_VALUE + {"9223372036854775808"}, // Long.MAX_VALUE+1 = abs(MIN_VALUE) + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), + new BigDecimal(expected[i][j])); + } + } + } + + static final String[] patterns = { + " {0, number} ", + " {0, number} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + + " {0, number} ", + " {0, number} ", + " {0, number, integer} ", + " {0, number, integer} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + }; + static final String[] from = { + " 12,345,678,901,234,567,890.98765432109876543210987654321 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321 ", + " $12,345,678,901,234,567,890.98765432109876543210987654321 ", + " ($12,345,678,901,234,567,890.98765432109876543210987654321) ", + " 1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " -1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " 12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210E5 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210E-5 ", + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00 ", + " ($9,876,543,210,987,654,321,098,765,432,109,876,543,210.00) ", + " 987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " 98,765,432,109,876,543,210.98765432109876543210E20 ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,000,000,000,000,000,000,000E-20 ", + }; + + static final String[] expected1 = { // isParseIntegerOnly() == false + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "0.1234567890123456789098765432109876543210987654321", + "-0.1234567890123456789098765432109876543210987654321", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210.00", + "-9876543210987654321098765432109876543210.00", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[] parsePosition1 = { + 60, 61, 61, 63, 64, 65, 64, 65, + 57, 58, 59, 61, 61, 63, 60, 61, 54, 88, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(false) + */ + void test_Parse_in_MessageFormat_NotParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != -1) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:-1, got:"+ + pp.getErrorIndex() + " for " + from[i]); + } + if (pp.getIndex() != parsePosition1[i]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition1[i] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + checkType(from[i], getType(new BigDecimal(expected1[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected1[i]), + (Number)parsed[0]); + } + } + + static final String[] expected2 = { // isParseIntegerOnly() == true + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "0", + "0", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[][] parsePosition2 = { // {errorIndex, index} + /* + * Should keep in mind that the expected result is different from + * DecimalFormat.parse() for some cases. + */ + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + + {-1, 57}, {-1, 58}, {-1, 59}, {-1, 61}, + {56, 0}, // parsing stopped at '.' + // because cannot find '%' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {-1, 60}, {-1, 61}, + {28, 0}, // parsing stopped at '.' + {-1, 88}, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_MessageFormat_ParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + ((DecimalFormat)formats[j]).setParseIntegerOnly(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != parsePosition2[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition2[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from[i]); + } + if (pp.getIndex() != parsePosition2[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition2[i][1] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition2[i][0] == -1) { + checkType(from[i], getType(new BigDecimal(expected2[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected2[i]), + (Number)parsed[0]); + } + } + } + + static final String[] from3 = { + "12,345,678,901,234,567,890.98765432109876543210987654321", + "-12,345,678,901,234,567,890.98765432109876543210987654321", + "9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "-9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "1234556790000E-8", + }; + static final String[] expected3 = { + "12345678901234567890", + "-12345678901234567890", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "12345.56790000", + }; + static final int[][] parsePosition3 = { // {errorIndex, index} + {-1, 26}, + {-1, 27}, + {-1, 53}, + {-1, 54}, + {-1, 16}, + }; + + /** + * Test for DecimalFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_DecimalFormat_ParseIntegerOnly() { + DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance(); + df.setParseBigDecimal(true); + + for (int i=0; i < from3.length; i++) { + pp = new ParsePosition(0); + Number parsed = null; + + try { + parsed = df.parse(from3[i], pp); + + if (pp.getErrorIndex() != parsePosition3[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition3[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from3[i]); + } + if (pp.getIndex() != parsePosition3[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition3[i][1] + ", got:"+ pp.getIndex() + + " for " + from3[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition3[i][0] == -1) { + checkType(from3[i], getType(new BigDecimal(expected3[i])), + getType(parsed)); + checkParse(from3[i], new BigDecimal(expected3[i]), parsed); + } + } + } + + protected void check(String from, Number to) { + pp = new ParsePosition(0); + try { + parsed = df.parse(from, pp); + } + catch(Exception e) { + exceptionOccurred = true; + errln(e.getMessage()); + } + if (!exceptionOccurred) { + checkParse(from, to, parsed); + checkType(from, getType(to), getType(parsed)); + checkParsePosition(from, from.length(), pp.getIndex()); + } + } + + private void checkParse(String orig, Number expected, Number got) { + if (!expected.equals(got)) { + errln("Parsing... failed." + + "\n original: " + orig + + "\n parsed: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkType(String orig, String expected, String got) { + if (!expected.equals(got)) { + errln("Parsing... unexpected Class returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkParsePosition(String orig, int expected, int got) { + if (expected != got) { + errln("Parsing... wrong ParsePosition returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private String getType(Number number) { + return number.getClass().getName(); + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4208135.java b/jdk/test/java/text/Format/NumberFormat/Bug4208135.java new file mode 100644 index 00000000000..3f5785b6f6c --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4208135.java @@ -0,0 +1,127 @@ +/* + * 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 + * 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 Confirm that the decimal separator is shown when explicitly requested. + * @bug 4208135 + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class Bug4208135 { + + static DecimalFormat df; + + static boolean err = false; + + static public void main(String[] args){ + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + df = new DecimalFormat(); + + df.applyPattern("0.#E0"); + + df.setDecimalSeparatorAlwaysShown(true); + checkFormat(new Double(0.0), "0.E0"); + checkFormat(new Double(10.0), "1.E1"); + checkFormat(new Double(1000.0), "1.E3"); + checkFormat(new Long(0), "0.E0"); + checkFormat(new Long(10), "1.E1"); + checkFormat(new Long(1000), "1.E3"); + checkFormat(new BigDecimal("0.0"), "0.E0"); + checkFormat(new BigDecimal("10.0"), "1.E1"); + checkFormat(new BigDecimal("1000.0"), "1.E3"); + checkFormat(new BigInteger("00"), "0.E0"); + checkFormat(new BigInteger("10"), "1.E1"); + checkFormat(new BigInteger("1000"), "1.E3"); + + df.setDecimalSeparatorAlwaysShown(false); + checkFormat(new Double(0.0), "0E0"); + checkFormat(new Double(10.0), "1E1"); + checkFormat(new Double(1000.0), "1E3"); + checkFormat(new Long(0), "0E0"); + checkFormat(new Long(10), "1E1"); + checkFormat(new Long(1000), "1E3"); + checkFormat(new BigDecimal("0.0"), "0E0"); + checkFormat(new BigDecimal("10.0"), "1E1"); + checkFormat(new BigDecimal("1000.0"), "1E3"); + checkFormat(new BigInteger("0"), "0E0"); + checkFormat(new BigInteger("10"), "1E1"); + checkFormat(new BigInteger("1000"), "1E3"); + + df.applyPattern("0.###"); + + df.setDecimalSeparatorAlwaysShown(true); + checkFormat(new Double(0.0), "0."); + checkFormat(new Double(10.0), "10."); + checkFormat(new Double(1000.0), "1000."); + checkFormat(new Long(0), "0."); + checkFormat(new Long(10), "10."); + checkFormat(new Long(1000), "1000."); + checkFormat(new BigDecimal("0.0"), "0."); + checkFormat(new BigDecimal("10.0"), "10."); + checkFormat(new BigDecimal("1000.0"), "1000."); + checkFormat(new BigInteger("0"), "0."); + checkFormat(new BigInteger("10"), "10."); + checkFormat(new BigInteger("1000"), "1000."); + + df.setDecimalSeparatorAlwaysShown(false); + checkFormat(new Double(0.0), "0"); + checkFormat(new Double(10.0), "10"); + checkFormat(new Double(1000.0), "1000"); + checkFormat(new Long(0), "0"); + checkFormat(new Long(10), "10"); + checkFormat(new Long(1000), "1000"); + checkFormat(new BigDecimal("0.0"), "0"); + checkFormat(new BigDecimal("10.0"), "10"); + checkFormat(new BigDecimal("1000.0"), "1000"); + checkFormat(new BigInteger("0"), "0"); + checkFormat(new BigInteger("10"), "10"); + checkFormat(new BigInteger("1000"), "1000"); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format/parse with DecimalFormat"); + } + } + + static void checkFormat(Number num, String expected) { + String got = df.format(num); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error:" + + "\n\tnumber: " + num + + "\n\tSeparatorShown? : " + df.isDecimalSeparatorAlwaysShown() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4833877.java b/jdk/test/java/text/Format/NumberFormat/Bug4833877.java new file mode 100644 index 00000000000..5f3c5056014 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4833877.java @@ -0,0 +1,464 @@ +/* + * 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 + * 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 Confirm that the negative multiplier works as expected. + * @bug 4833877 + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class Bug4833877 { + + static DecimalFormat df; + + static boolean err = false; + + public static void main(String[] args) throws Exception { + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + /* ================================================================ */ + + df = new DecimalFormat(); + df.setMaximumFractionDigits(50); + df.setMultiplier(4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "1,010.10101010101"); + checkParse("-1,010.10101010101", new Double(-252.5252525252525)); + + checkFormat(new Double(-2222.2222), "-8,888.8888"); + checkParse("8888.8888", new Double(2222.2222)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "4,000"); + checkParse("-4,000", new Long(-1000)); + + checkFormat(new Long(-250), "-1,000"); + checkParse("1000", new Long(250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("22222.222222222222222222222"), + "88,888.888888888888888888888"); + checkParse("-88,888.888888888888888888888", + new BigDecimal("-22222.222222222222222222222")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "-4,444,444,444,444,444,444.444444444444444444"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "88,888,888,888,888,888,888,888,888"); + checkParse("-88,888,888,888,888,888,888,888,888", + new BigDecimal("-22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "-4,444,444,444,444,444,444,444,444"); + checkParse("4444444444444444444444444", + new BigDecimal("1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "-1,010.10101010101"); + checkParse("-1,010.10101010101", new Double(252.5252525252525)); + + checkFormat(new Double(-2222.2222), "8,888.8888"); + checkParse("8888.8888", new Double(-2222.2222)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "-4,000"); + checkParse("-4,000", new Long(1000)); + + checkFormat(new Long(-250), "1,000"); + checkParse("1000", new Long(-250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("22222.222222222222222222222"), + "-88,888.888888888888888888888"); + checkParse("-88,888.888888888888888888888", + new BigDecimal("22222.222222222222222222222")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "4,444,444,444,444,444,444.444444444444444444"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("-1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "-88,888,888,888,888,888,888,888,888"); + checkParse("-88,888,888,888,888,888,888,888,888", + new BigDecimal("22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "4,444,444,444,444,444,444,444,444"); + checkParse("4444444444444444444444444", + new BigDecimal("-1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-3); + + /* + * Test for double/Double + */ + checkFormat(new Double(3333.3333333), "-9,999.9999999"); + checkParse("-10,000.00000000000", new Double(3333.3333333333335));// rounding error + + df.setParseIntegerOnly(true); + checkFormat(new Double(-3333.3333333), "9,999.9999999"); + checkParse("10,000.00000000000", new Long(-3333)); + df.setParseIntegerOnly(false); + checkFormat(new Double(-3333.3333333), "9,999.9999999"); + checkParse("10,000.00000000000", new Double(-3333.3333333333335));// rounding error + + /* + * Test for long/Long + */ + checkFormat(new Long(3333), "-9,999"); + df.setParseIntegerOnly(true); + checkParse("-10,000", new Long(3333)); + df.setParseIntegerOnly(false); + checkParse("-10000", new Double(3333.3333333333335));// rounding error + + checkFormat(new Long(-3333), "9,999"); + df.setParseIntegerOnly(true); + checkParse("10,000", new Long(-3333)); + df.setParseIntegerOnly(false); + checkParse("10000", new Double(-3333.3333333333335));// rounding error + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("33333.333333333333333333333"), + "-99,999.999999999999999999999"); + checkParse("-100,000.000000000000000000000", + new BigDecimal("33333.333333333333333333333")); + + checkFormat(new BigDecimal("-33333.333333333333333333333"), + "99,999.999999999999999999999"); + checkParse("100,000.000000000000000000000", + new BigDecimal("-33333.333333333333333333333")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("33333333333333333333333333"), + "-99,999,999,999,999,999,999,999,999"); + checkParse("-100,000,000,000,000,000,000,000,000", + new BigDecimal("33333333333333333333333333")); + + checkFormat(new BigInteger("-33333333333333333333333333"), + "99,999,999,999,999,999,999,999,999"); + df.setParseIntegerOnly(true); + checkParse("100,000,000,000,000,000,000,000,000.000", + new BigDecimal("-33333333333333333333333333")); + df.setParseIntegerOnly(false); + checkParse("100,000,000,000,000,000,000,000,000.000", + new BigDecimal("-33333333333333333333333333.333")); + + /* ================================================================ */ + + df = new DecimalFormat("0.#E0;-0.#E0"); + df.setMaximumFractionDigits(50); + df.setMultiplier(4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "1.01010101010101E3"); + checkParse("-1.01010101010101E3", new Double(-2.525252525252525E2)); + + checkFormat(new Double(-2222.2222), "-8.8888888E3"); + checkParse("8888.8888", new Double(2.2222222E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "4E3"); + checkParse("-4E3", new Long(-1000)); + + checkFormat(new Long(-250), "-1E3"); + checkParse("1000", new Long(250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("22222.222222222222222222222"), + "8.8888888888888888888888888E4"); + checkParse("-8.8888888888888888888888888E4", + new BigDecimal("-2.2222222222222222222222222E4")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "-4.444444444444444444444444444444444444E18"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "8.8888888888888888888888888E25"); + checkParse("-8.8888888888888888888888888E25", + new BigDecimal("-22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "-4.444444444444444444444444E24"); + checkParse("4444444444444444444444444", + new BigDecimal("1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "-1.01010101010101E3"); + checkParse("-1.01010101010101E3", new Double(2.525252525252525E2)); + + checkFormat(new Double(-2222.2222), "8.8888888E3"); + checkParse("8888.8888", new Double(-2.2222222E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "-4E3"); + checkParse("-4E3", new Long(1000)); + + checkFormat(new Long(-250), "1E3"); + checkParse("1000", new Long(-250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("22222.222222222222222222222"), + "-8.8888888888888888888888888E4"); + checkParse("-8.8888888888888888888888888E4", + new BigDecimal("2.2222222222222222222222222E4")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "4.444444444444444444444444444444444444E18"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("-1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "-8.8888888888888888888888888E25"); + checkParse("-8.8888888888888888888888888E25", + new BigDecimal("22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "4.444444444444444444444444E24"); + checkParse("4444444444444444444444444", + new BigDecimal("-1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-3); + + /* + * Test for double/Double + */ + checkFormat(new Double(3333.3333333), "-9.9999999999E3"); + checkParse("-1.00000000000000E3", new Double(3.33333333333333333E2)); + + df.setParseIntegerOnly(true); + checkFormat(new Double(-3333.3333333), "9.9999999999E3"); + checkParse("10.00000000000000E3", new Long(-3)); + df.setParseIntegerOnly(false); + checkFormat(new Double(-3333.3333333), "9.9999999999E3"); + checkParse("10.00000000000000E3", new Double(-3.33333333333333333E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(3333), "-9.999E3"); + df.setParseIntegerOnly(true); + checkParse("-1.0E4", new Long(0)); + df.setParseIntegerOnly(false); + checkParse("-1.0E4", new Double(3333.3333333333335)); + + checkFormat(new Long(-3333), "9.999E3"); + df.setParseIntegerOnly(true); + checkParse("10.0E4", new Long(-3)); + df.setParseIntegerOnly(false); + checkParse("10.0E4", new Double(-33333.3333333333336)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("333.333333333333333333333333"), + "-9.99999999999999999999999999E2"); + checkParse("-1.0000000000000000000000000E3", + new BigDecimal("3.333333333333333333333333E2")); + + df.setParseIntegerOnly(true); + checkFormat(new BigDecimal("-333.333333333333333333333333"), + "9.99999999999999999999999999E2"); + checkParse("10.0000000000000000000000000E3", + new BigDecimal("-3")); + df.setParseIntegerOnly(false); + checkFormat(new BigDecimal("-333.333333333333333333333333"), + "9.99999999999999999999999999E2"); + checkParse("1.0000000000000000000000000E3", + new BigDecimal("-3.333333333333333333333333E2")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("33333333333333333333333333"), + "-9.9999999999999999999999999E25"); + checkParse("-100000000000000000000000000", + new BigDecimal("33333333333333333333333333")); + + checkFormat(new BigInteger("-33333333333333333333333333"), + "9.9999999999999999999999999E25"); + df.setParseIntegerOnly(true); + checkParse("100000000000000000000000000000", + new BigDecimal("-33333333333333333333333333333")); + df.setParseIntegerOnly(false); + checkParse("100000000000000000000000000.000", + new BigDecimal("-33333333333333333333333333.333")); + + /* ================================================================ */ + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format/parse with DecimalFormat"); + } + } + + static void checkFormat(Number num, String expected) { + String got = df.format(num); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error:" + + "\n\tnumber: " + num + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, Double expected) { + Double got = (Double)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(double) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, Long expected) { + Long got = (Long)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(long) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, BigDecimal expected) { + BigDecimal got = (BigDecimal)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(BigDecimal) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4838107.java b/jdk/test/java/text/Format/NumberFormat/Bug4838107.java new file mode 100644 index 00000000000..a15d537d8e6 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4838107.java @@ -0,0 +1,248 @@ +/* + * 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 + * 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 4838107 8008577 + * @summary Confirm that DecimalFormat can format a number with negative exponent number correctly. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4838107 + */ + +import java.math.*; +import java.util.*; +import java.text.*; + +public class Bug4838107 extends IntlTest { + + static DecimalFormat df; + static DecimalFormatSymbols dfs; + static boolean err = false; + + static public void main(String[] args) { + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + /** + * This bug is about exponential formatting. But I added test cases for: + * - Double and BigDecimal numbers which don't have exponent parts. + * - Long and BigInteger numbers which don't support exponential + * notation. + * because there are few test cases for suffix and prefix. + * And also, I added test cases to guarantee further formatting and + * parsing using the same DecimalFormat instance will not change the + * Number's value anymore. + */ + + test_double(); + test_long(); + test_BigDecimal(); + test_BigInteger(); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format with DecimalFormat"); + } + } + + static void test_double() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new Double(1234), "1,234"); + test(new Double(0.1234), "0.123"); // rounded + test(new Double(-1234), "-1,234"); + test(new Double(-0.1234), "-0.123"); // rounded + + test(new Double(Double.POSITIVE_INFINITY), "\u221e"); + test(new Double(Double.NEGATIVE_INFINITY), "-\u221e"); + test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix + test(new Double(0.0), "0"); + test(new Double(-0.0), "-0"); // with the minus sign + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #.###E00", 'm'); + test(new Double(1234), "

    1.234E03"); + test(new Double(0.1234), "

    1.234Em01"); + test(new Double(-1234), "m

    1.234E03"); + test(new Double(-0.1234), "m

    1.234Em01"); + + prepareFormatter("

    #.###E00;#.###E00", 'm'); + test(new Double(1234), "

    1.234E03"); + test(new Double(0.1234), "

    1.234Em01"); + test(new Double(-1234), "1.234E03"); + test(new Double(-0.1234), "1.234Em01"); + + prepareFormatter("#.###E00;

    #.###E00", 'm'); + test(new Double(1234), "1.234E03"); + test(new Double(0.1234), "1.234Em01"); + test(new Double(-1234), "

    1.234E03"); + test(new Double(-0.1234), "

    1.234Em01"); + + prepareFormatter("

    #.###E00;

    -#.###E00", 'm'); + test(new Double(1234), "

    1.234E03"); + test(new Double(0.1234), "

    1.234Em01"); + test(new Double(-1234), "

    m1.234E03"); + test(new Double(-0.1234), "

    m1.234Em01"); + + test(new Double(Double.POSITIVE_INFINITY), "

    \u221e"); + test(new Double(Double.NEGATIVE_INFINITY), "

    m\u221e"); + test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix + test(new Double(0.0), "

    0E00"); + test(new Double(-0.0), "

    m0E00"); // with the minus sign + } + + static void test_BigDecimal() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new BigDecimal("123456789012345678901234567890"), + "123,456,789,012,345,678,901,234,567,890"); + test(new BigDecimal("0.000000000123456789012345678901234567890"), + "0"); + test(new BigDecimal("-123456789012345678901234567890"), + "-123,456,789,012,345,678,901,234,567,890"); + test(new BigDecimal("-0.000000000123456789012345678901234567890"), + "-0"); + + test(new BigDecimal("0"), "0"); + test(new BigDecimal("-0"), "0"); + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #.####################E00;

    -#.####################E00", 'm'); + test(new BigDecimal("123456789012345678901234567890"), + "

    1.23456789012345678901E29"); + test(new BigDecimal("0.000000000123456789012345678901234567890"), + "

    1.23456789012345678901Em10"); + test(new BigDecimal("-123456789012345678901234567890"), + "

    m1.23456789012345678901E29"); + test(new BigDecimal("-0.000000000123456789012345678901234567890"), + "

    m1.23456789012345678901Em10"); + + test(new BigDecimal("0"), "

    0E00"); + test(new BigDecimal("-0"), "

    0E00"); + } + + static void test_long() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new Long(123456789), "123,456,789"); + test(new Long(-123456789), "-123,456,789"); + + test(new Long(0), "0"); + test(new Long(-0), "0"); + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #,###;

    -#,###", 'm'); + test(new Long(123456789), "

    123,456,789"); + test(new Long(-123456789), "

    m123,456,789"); + + test(new Long(0), "

    0"); + test(new Long(-0), "

    0"); + } + + static void test_BigInteger() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new BigInteger("123456789012345678901234567890"), + "123,456,789,012,345,678,901,234,567,890"); + test(new BigInteger("-123456789012345678901234567890"), + "-123,456,789,012,345,678,901,234,567,890"); + + test(new BigInteger("0"), "0"); + test(new BigInteger("-0"), "0"); + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #,###;

    -#,###", 'm'); + test(new BigInteger("123456789012345678901234567890"), + "

    123,456,789,012,345,678,901,234,567,890"); + test(new BigInteger("-123456789012345678901234567890"), + "

    m123,456,789,012,345,678,901,234,567,890"); + + test(new BigInteger("0"), "

    0"); + test(new BigInteger("-0"), "

    0"); + } + + static void prepareFormatter(String pattern, char minusSign) { + dfs = df.getDecimalFormatSymbols(); + df.applyPattern(pattern); + dfs.setMinusSign(minusSign); + df.setDecimalFormatSymbols(dfs); + } + + static void test(Number num, String str) { + String formatted = df.format(num); + if (!formatted.equals(str)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error: \n\tnumber: " + num + + "\n\tminus sign: " + dfs.getMinusSign() + + "\n\tgot: " + formatted + + "\n\texpected: " + str); + return; + } + + if (num instanceof BigDecimal || num instanceof BigInteger) { + df.setParseBigDecimal(true); + } + Number parsed1 = null, parsed2 = null; + try { + parsed1 = df.parse(formatted); + formatted = df.format(parsed1); + parsed2 = df.parse(formatted); + if (!parsed1.equals(parsed2)) { + err = true; + System.err.println(" DecimalFormat roundtrip parse(" + + num.getClass().getName() + + ") error: \n\toriginal number: " + str + + "\n\tparsed number: " + parsed1 + + " (" + parsed1.getClass().getName() + ")" + + "\n\tformatted number: " + formatted + + "\n\tre-parsed number: " + parsed2 + + " (" + parsed2.getClass().getName() + ")" + + "\n\tminus sign: " + dfs.getMinusSign()); + } + } + catch (Exception e) { + err = true; + System.err.println(" DecimalFormat parse(" + + num.getClass().getName() + + ") threw an Exception: " + e.getMessage() + + "\n\toriginal number: " + str + + "\n\tparsed number : " + parsed1 + + " (" + parsed1.getClass().getName() + ")" + + "\n\tformatted number: " + formatted + + "\n\tre-parsed number: " + parsed2 + + " (" + parsed2.getClass().getName() + ")" + + "\n\tminus sign: " + dfs.getMinusSign()); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4944439.java b/jdk/test/java/text/Format/NumberFormat/Bug4944439.java new file mode 100644 index 00000000000..beb4d77c235 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4944439.java @@ -0,0 +1,111 @@ +/* + * 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 + * 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 4944439 + * @summary Confirm that numbers where all digits after the decimal separator are 0 + * and which are between Long.MIN_VALUE and Long.MAX_VALUE are returned as Long(not double). + */ + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.DecimalFormat; +import java.util.Locale; + +public class Bug4944439 { + + static boolean err = false; + static DecimalFormat df; + + public static void main(String[] args) throws Exception { + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + df = new DecimalFormat(); + String s = "-9223372036854775809"; // Long.MIN_VALUE-1 + check_Double(s); + + test(Long.MIN_VALUE, Long.MIN_VALUE+10); + test(-10, 10); + test(Long.MAX_VALUE-10, Long.MAX_VALUE-1); + + s = "9223372036854775807.00"; // Long.MAX_VALUE + check_Long(s); + s = "9223372036854775808"; // Long.MAX_VALUE+1 + check_Double(s); + + s = "-0.0"; + check_Double(s); + s = "0.0"; + check_Long(s); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong parsing with DecimalFormat"); + } + } + + private static void test(long from, long to) throws Exception { + for (long l = from; l <= to; l++) { + check_Long(Long.toString(l) + ".00"); + } + } + + private static void check_Long(String s) throws Exception { + Number number = df.parse(s); + if (!(number instanceof Long)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(\"" + s + + "\") should return a Long, but returned a " + + number.getClass().getName()); + } + + int index = s.indexOf('.'); + Long l = new Long(s.substring(0, index)); + if (!l.equals(number)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(" + s + + ") should return a Long(" + l + "), but returned " + number); + } + } + + private static void check_Double(String s) throws Exception { + Number number = df.parse(s); + if (!(number instanceof Double)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(\"" + s + + "\") should return a Double, but returned a " + + number.getClass().getName()); + } + + Double d = new Double(s); + if (!d.equals(number)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(" + s + + ") should return a Double(" + d + "), but returned " + number); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4990596.java b/jdk/test/java/text/Format/NumberFormat/Bug4990596.java new file mode 100644 index 00000000000..a8c03b8a035 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4990596.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004, 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 4990596 + * @summary Make sure that any subclass of Number can be formatted using DecimalFormat.format(). + */ + +import java.text.DecimalFormat; + +public class Bug4990596 { + + public static void main(String[] args) { + new DecimalFormat().format(new MutableInteger(0)); + } + + public static class MutableInteger extends Number { + public int value; + + public MutableInteger() { + } + public MutableInteger(int value) { + this.value = value; + } + public double doubleValue() { + return this.value; + } + public float floatValue() { + return this.value; + } + public int intValue() { + return this.value; + } + public long longValue() { + return this.value; + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug6278616.java b/jdk/test/java/text/Format/NumberFormat/Bug6278616.java new file mode 100644 index 00000000000..9066a7da02e --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug6278616.java @@ -0,0 +1,69 @@ +/* + * 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 + * 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 Confirm that AtomicInteger and AtomicLong are formatted correctly. + * @bug 6278616 + */ + +import java.text.NumberFormat; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import java.util.Locale; + +public class Bug6278616 { + + static final int[] ints = { + Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE + }; + + static final long[] longs = { + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE + }; + + public static void main(String[] args) { + NumberFormat nf = NumberFormat.getInstance(); + + for (int j = 0; j < ints.length; j++) { + String s_i = nf.format(new Integer(ints[j])); + String s_ai = nf.format(new AtomicInteger(ints[j])); + if (!s_i.equals(s_ai)) { + throw new RuntimeException("format(AtomicInteger " + s_ai + + ") doesn't equal format(Integer " + + s_i + ")"); + } + } + + for (int j = 0; j < longs.length; j++) { + String s_l = nf.format(new Long(longs[j])); + String s_al = nf.format(new AtomicLong(longs[j])); + if (!s_l.equals(s_al)) { + throw new RuntimeException("format(AtomicLong " + s_al + + ") doesn't equal format(Long " + + s_l + ")"); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/CurrencyFormat.java b/jdk/test/java/text/Format/NumberFormat/CurrencyFormat.java new file mode 100644 index 00000000000..96fa3976701 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/CurrencyFormat.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001, 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 4290801 4942982 5102005 8008577 8021121 + * @summary Basic tests for currency formatting. + * @run main/othervm -Djava.locale.providers=JRE,SPI CurrencyFormat + */ + +import java.io.File; +import java.io.FileInputStream; +import java.util.Currency; +import java.util.Locale; +import java.util.Properties; +import java.util.StringTokenizer; +import java.util.TimeZone; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; + +public class CurrencyFormat { + + public static void main(String[] args) throws Exception { + testFormatting(); + testSymbols(); + } + + static void testFormatting() { + boolean failed = false; + Locale[] locales = { + Locale.US, + Locale.JAPAN, + Locale.GERMANY, + Locale.ITALY, + new Locale("it", "IT", "EURO") }; + Currency[] currencies = { + null, + Currency.getInstance("USD"), + Currency.getInstance("JPY"), + Currency.getInstance("DEM"), + Currency.getInstance("EUR"), + }; + String[][] expecteds = { + {"$1,234.56", "$1,234.56", "JPY1,235", "DEM1,234.56", "EUR1,234.56"}, + {"\uFFE51,235", "USD1,234.56", "\uFFE51,235", "DEM1,234.56", "EUR1,234.56"}, + {"1.234,56 \u20AC", "1.234,56 USD", "1.235 JPY", "1.234,56 DM", "1.234,56 \u20AC"}, + {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"}, + {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"}, + }; + + for (int i = 0; i < locales.length; i++) { + Locale locale = locales[i]; + NumberFormat format = NumberFormat.getCurrencyInstance(locale); + for (int j = 0; j < currencies.length; j++) { + Currency currency = currencies[j]; + String expected = expecteds[i][j]; + if (currency != null) { + format.setCurrency(currency); + int digits = currency.getDefaultFractionDigits(); + format.setMinimumFractionDigits(digits); + format.setMaximumFractionDigits(digits); + } + String result = format.format(1234.56); + if (!result.equals(expected)) { + failed = true; + System.out.println("FAIL: Locale " + locale + + (currency == null ? ", default currency" : (", currency: " + currency)) + + ", expected: " + expected + + ", actual: " + result); + } + } + } + + if (failed) { + throw new RuntimeException(); + } + } + + static void testSymbols() throws Exception { + FileInputStream stream = new FileInputStream(new File(System.getProperty("test.src", "."), "CurrencySymbols.properties")); + Properties props = new Properties(); + props.load(stream); + SimpleDateFormat format = null; + + Locale[] locales = NumberFormat.getAvailableLocales(); + for (int i = 0; i < locales.length; i++) { + Locale locale = locales[i]; + DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); + String result = symbols.getCurrencySymbol(); + String expected = (String) props.get(locale.toString()); + + if (expected == null) { + System.out.println("Warning: No expected currency symbol defined for locale " + locale); + } else { + if (expected.contains(";")) { + StringTokenizer tokens = new StringTokenizer(expected, ";"); + int tokensCount = tokens.countTokens(); + + if (tokensCount == 3) { + expected = tokens.nextToken(); + if (format == null) { + format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + format.setLenient(false); + } + + if (format.parse(tokens.nextToken()).getTime() < System.currentTimeMillis()) { + expected = tokens.nextToken(); + } + } + } + + if (!expected.equals(result)) { + throw new RuntimeException("Wrong currency symbol for locale " + + locale + ", expected: " + expected + ", got: " + result); + } + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/CurrencySymbols.properties b/jdk/test/java/text/Format/NumberFormat/CurrencySymbols.properties new file mode 100644 index 00000000000..cc919005db7 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/CurrencySymbols.properties @@ -0,0 +1,134 @@ +ar=\u00A4 +ar_AE=\u062F.\u0625.\u200F +ar_BH=\u062F.\u0628.\u200F +ar_DZ=\u062F.\u062C.\u200F +ar_EG=\u062C.\u0645.\u200F +ar_IQ=\u062F.\u0639.\u200F +ar_JO=\u062F.\u0623.\u200F +ar_KW=\u062F.\u0643.\u200F +ar_LB=\u0644.\u0644.\u200F +ar_LY=\u062F.\u0644.\u200F +ar_MA=\u062F.\u0645.\u200F +ar_OM=\u0631.\u0639.\u200F +ar_QA=\u0631.\u0642.\u200F +ar_SA=\u0631.\u0633.\u200F +# see bug 4412080 +# ar_SD=\u062C.\u0633.\u200F +ar_SY=\u0644.\u0633.\u200F +ar_TN=\u062F.\u062A.\u200F +ar_YE=\u0631.\u064A.\u200F +be=\u00A4 +# see bug 4412080 +# be_BY=\u0420\u0443\u0431 +bg=\u00A4 +# see bug 4412080 +# bg_BG=Lr +ca=\u00A4 +ca_ES=\u20AC +cs=\u00A4 +cs_CZ=K\u010D +da=\u00A4 +da_DK=kr +de=\u00A4 +de_AT=\u20AC +de_CH=SFr. +de_DE=\u20AC +de_LU=\u20AC +el=\u00A4 +el_GR=\u20AC +en=\u00A4 +en_AU=$ +en_CA=$ +en_GB=\u00A3 +en_IE=\u20AC +en_NZ=$ +en_US=$ +en_ZA=R +es=\u00A4 +es_AR=$ +es_BO=B$ +es_CL=Ch$ +# 5102005 +es_CO=$ +es_CR=C +es_CU=CU$ +es_DO=RD$ +# see bug 4412080 +# es_EC=S/ +es_ES=\u20AC +es_GT=Q +es_HN=L +es_MX=$ +es_NI=$C +es_PA=B +es_PE=S/. +es_PR=$ +es_PY=G +es_SV=C +es_UY=NU$ +es_VE=Bs.F. +et=\u00A4 +et_EE=\u20AC +fi=\u00A4 +fi_FI=\u20AC +fr=\u00A4 +fr_BE=\u20AC +fr_CA=$ +fr_CH=SFr. +fr_FR=\u20AC +fr_LU=\u20AC +hi_IN=\u0930\u0942 +hr=\u00A4 +hr_HR=Kn +hu=\u00A4 +hu_HU=Ft +is=\u00A4 +is_IS=kr. +it=\u00A4 +it_CH=SFr. +it_IT=\u20AC +iw=\u00A4 +iw_IL=\u05E9"\u05D7 +ja=\u00A4 +ja_JP=\uFFE5 +ko=\u00A4 +ko_KR=\uFFE6 +lt=\u00A4 +lt_LT=Lt;2014-12-31-22-00-00;\u20AC +lv=\u00A4 +lv_LV=Ls;2013-12-31-22-00-00;\u20AC +mk=\u00A4 +mk_MK=Den +nl=\u00A4 +nl_BE=\u20AC +nl_NL=\u20AC +no=\u00A4 +no_NO=kr +no_NO_NY=kr +pl=\u00A4 +pl_PL=z\u0142 +pt=\u00A4 +pt_BR=R$ +pt_PT=\u20AC +ro=\u00A4 +ro_RO=LEI +ru=\u00A4 +ru_RU=\u0440\u0443\u0431. +sk=\u00A4 +sk_SK=\u20AC +sl=\u00A4 +sl_SI=\u20AC +sq=\u00A4 +sq_AL=Lek +sv=\u00A4 +sv_SE=kr +th=\u00A4 +th_TH=\u0E3F +tr=\u00A4 +tr_TR=TL +uk=\u00A4 +uk_UA=\u0433\u0440\u043d. +zh=\u00A4 +zh_CN=\uFFE5 +zh_HK=HK$ +zh_TW=NT$ diff --git a/jdk/test/java/text/Format/NumberFormat/DFSDeserialization142.java b/jdk/test/java/text/Format/NumberFormat/DFSDeserialization142.java new file mode 100644 index 00000000000..2927f4e2c3b --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSDeserialization142.java @@ -0,0 +1,56 @@ +/* + * 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 + * 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. + */ + +/* + * No at-test for this test, because it needs to be run on older version JDK than 1.6 to test. + * It was tested using 1.4.2. The file object was created using JDK1.6. + */ + + + +import java.awt.*; +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSDeserialization142{ + + public static void main(String[] args) + { + try { + + File file = new File("DecimalFormatSymbols.current"); + FileInputStream istream = new FileInputStream(file); + ObjectInputStream p = new ObjectInputStream(istream); + DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject(); + if (dfs.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){ + System.out.println("Serialization/Deserialization Test Passed."); + }else{ + throw new Exception("Serialization/Deserialization Test Failed:"+dfs.getCurrencySymbol()); + } + istream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DFSExponential.java b/jdk/test/java/text/Format/NumberFormat/DFSExponential.java new file mode 100644 index 00000000000..898fb3feccb --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSExponential.java @@ -0,0 +1,87 @@ +/* + * 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 + * 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 4068067 + * @library /java/text/testlib + * @summary test NumberFormat with exponential separator symbols. It also tests the new + * public methods in DecimalFormatSymbols, setExponentSeparator() and + * getExponentSeparator() + */ + +import java.util.*; +import java.text.*; + +public class DFSExponential extends IntlTest +{ + + public static void main(String[] args) throws Exception { + new DFSExponential().run(args); + } + + + public void DFSExponenTest() throws Exception { + DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); + String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" }; + double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 }; + long lval[] = { 0, -1, 1, 123456789 }; + String valFormat[][] = { + {"1.234x10^-2", "1.2346x10^8", "1.23x10^300", "-3.1416x10^-271"}, + {"12.340x10^-03", "12.346x10^07", "12.300x10^299", "-31.416x10^-272"}, + {"12.34x10^-003", "123.4568x10^006", "1.23x10^300", "-314.1593x10^-273"}, + {"1.234x10^-2", "1.235x10^8", "1.23x10^300", "[3.142x10^-271]"}, + }; + + + int ival = 0, ilval = 0; + logln("Default exponent separator: "+sym.getExponentSeparator()); + try { + sym.setExponentSeparator("x10^"); + } catch (NullPointerException e){ + errln("null String was passed to set an exponent separator symbol"); + throw new RuntimeException("Test Malfunction: null String was passed to set an exponent separator symbol" ); + } + logln("Current exponent separator: "+sym.getExponentSeparator()); + + for (int p=0; p "+s); + if(valFormat[p][v].equals(s)){ + logln(": Passed"); + }else{ + errln(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s); + throw new RuntimeException(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s); + } + } + } //end of the first for loop + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DFSSerialization.java b/jdk/test/java/text/Format/NumberFormat/DFSSerialization.java new file mode 100644 index 00000000000..40b40b39b87 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSSerialization.java @@ -0,0 +1,151 @@ +/* + * 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 + * 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 4068067 + * @library /java/text/testlib + * @build DFSSerialization IntlTest HexDumpReader + * @run main DFSSerialization + * @summary Three different tests are done. 1.read from the object created using jdk1.4.2 2.create a valid DecimalFormatSymbols object with current JDK, then read the object 3.Try to create an valid DecimalFormatSymbols object by passing null to set null for the exponent separator symbol. Expect the NullPointerException. + */ + +import java.awt.*; +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSSerialization extends IntlTest{ + public static void main(String[] args) throws Exception { + new DFSSerialization().run(args); + } + public void TestDFSSerialization(){ + /* + * 1. read from the object created using jdk1.4.2 + */ + File oldFile = new File(System.getProperty("test.src", "."), "DecimalFormatSymbols.142.txt"); + DecimalFormatSymbols dfs142 = readTestObject(oldFile); + if (dfs142 != null){ + if (dfs142.getExponentSeparator().equals("E") && dfs142.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){ + System.out.println("\n Deserialization of JDK1.4.2 Object from the current JDK: Passed."); + logln(" Deserialization of JDK1.4.2 Object from the current JDK: Passed."); + } else { + errln(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:" + +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator()); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:" + +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator()); + } + } + /* + * 2. create a valid DecimalFormatSymbols object with current JDK, then read the object + */ + String validObject = "DecimalFormatSymbols.current"; + File currentFile = createTestObject(validObject, "*SpecialExponentSeparator*"); + + DecimalFormatSymbols dfsValid = readTestObject(currentFile); + if (dfsValid != null){ + if (dfsValid.getExponentSeparator().equals("*SpecialExponentSeparator*") && + dfsValid.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){ + System.out.println(" Deserialization of current JDK Object from the current JDK: Passed."); + logln(" Deserialization of current JDK Object from the current JDK: Passed."); + } else { + errln(" Deserialization of current JDK Object from the current JDK was Failed:" + +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator()); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException(" Deserialization of current Object from the current JDK was Failed:" + +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator()); + } + } + /* + * 3. Try to create an valid DecimalFormatSymbols object by passing null + * to set null for the exponent separator symbol. Expect the NullPointerException. + */ + DecimalFormatSymbols symNPE = new DecimalFormatSymbols(Locale.US); + boolean npePassed = false; + try { + symNPE.setExponentSeparator(null); + } catch (NullPointerException npe){ + npePassed = true; + System.out.println(" Trying to set exponent separator with null: Passed."); + logln(" Trying to set exponent separator with null: Passed."); + } + if (!npePassed){ + System.out.println(" Trying to set exponent separator with null:Failed."); + errln(" Trying to set exponent separator with null:Failed."); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException(" Trying to set exponent separator with null:Failed."); + } + + } + + private DecimalFormatSymbols readTestObject(File inputFile){ + try (InputStream istream = inputFile.getName().endsWith(".txt") ? + HexDumpReader.getStreamFromHexDump(inputFile) : + new FileInputStream(inputFile)) { + ObjectInputStream p = new ObjectInputStream(istream); + DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject(); + return dfs; + } catch (Exception e) { + errln("Test Malfunction in DFSSerialization: Exception while reading the object"); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException("Test Malfunction: re-throwing the exception", e); + } + } + + private File createTestObject(String objectName, String expString){ + DecimalFormatSymbols dfs= new DecimalFormatSymbols(); + dfs.setExponentSeparator(expString); + dfs.setCurrencySymbol("*SpecialCurrencySymbol*"); + logln(" The special exponent separator is set : " + dfs.getExponentSeparator()); + logln(" The special currency symbol is set : " + dfs.getCurrencySymbol()); + + // 6345659: create a test object in the test.class dir where test user has a write permission. + File file = new File(System.getProperty("test.class", "."), objectName); + try (FileOutputStream ostream = new FileOutputStream(file)) { + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(dfs); + //System.out.println(" The special currency symbol is set : " + dfs.getCurrencySymbol()); + return file; + } catch (Exception e){ + errln("Test Malfunction in DFSSerialization: Exception while creating an object"); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException("Test Malfunction: re-throwing the exception", e); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DFSSerialization142.java b/jdk/test/java/text/Format/NumberFormat/DFSSerialization142.java new file mode 100644 index 00000000000..4a5e873ee23 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSSerialization142.java @@ -0,0 +1,54 @@ +/* + * 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 + * 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. + */ + +/* + * No at-test for this test, because it needs to be run on JDK 1.4.2 + * Instead, the resulting serialized file + * DecimalFormatSymbols.142 is archived. + */ + +import java.awt.*; +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSSerialization142 { + + public static void main(String[] args) + { + try { + + DecimalFormatSymbols dfs= new DecimalFormatSymbols(); + System.out.println("Default currency symbol in the default locale : " + dfs.getCurrencySymbol()); + dfs.setCurrencySymbol("*SpecialCurrencySymbol*"); + System.out.println("The special currency symbol is set : " + dfs.getCurrencySymbol()); + FileOutputStream ostream = new FileOutputStream("DecimalFormatSymbols.142"); + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(dfs); + ostream.close(); + System.out.println("DecimalFormatSymbols saved ok."); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DecimalFormat.114.txt b/jdk/test/java/text/Format/NumberFormat/DecimalFormat.114.txt new file mode 100644 index 00000000000..efa6df41419 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormat.114.txt @@ -0,0 +1,54 @@ +# +# 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 +# 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. +# + +# Hex dump of a serialized DecimalFormat for SerializationLoadTest. + +aced000573720012436865636b446563696d616c466f726d6174aa9218d3b530 +540a0200014c000a5f646563466f726d61747400194c6a6176612f746578742f +446563696d616c466f726d61743b7870737200176a6176612e746578742e4465 +63696d616c466f726d61740bff0362d872303a0200085a001b646563696d616c +536570617261746f72416c7761797353686f776e42000c67726f7570696e6753 +697a6549000a6d756c7469706c6965724c000e6e656761746976655072656669 +787400124c6a6176612f6c616e672f537472696e673b4c000e6e656761746976 +655375666669787400124c6a6176612f6c616e672f537472696e673b4c000e70 +6f7369746976655072656669787400124c6a6176612f6c616e672f537472696e +673b4c000e706f7369746976655375666669787400124c6a6176612f6c616e67 +2f537472696e673b4c000773796d626f6c737400204c6a6176612f746578742f +446563696d616c466f726d617453796d626f6c733b787200166a6176612e7465 +78742e4e756d626572466f726d6174dff6b3bf137d07e80200065a000c67726f +7570696e67557365644200116d61784672616374696f6e446967697473420010 +6d6178496e74656765724469676974734200116d696e4672616374696f6e4469 +676974734200106d696e496e74656765724469676974735a0010706172736549 +6e74656765724f6e6c79787200106a6176612e746578742e466f726d6174fbd8 +bc12e90f1843020000787001037f0001000003000000017400012d7400007400 +007400007372001e6a6176612e746578742e446563696d616c466f726d617453 +796d626f6c73501d17990868939c02000c430010646563696d616c5365706172 +61746f72430005646967697443001167726f7570696e67536570617261746f72 +4300096d696e75735369676e4300107061747465726e536570617261746f7243 +00077065724d696c6c43000770657263656e744300097a65726f44696769744c +00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e637572 +72656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e673b +4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e673b +4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c61 +6e672f537472696e673b7870002e0023002c002d003b203000250030740003ef +bfbd74000124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt new file mode 100644 index 00000000000..6707e375a99 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt @@ -0,0 +1,39 @@ +# +# 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 +# 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. +# + +# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest. + +aced000573720019436865636b446563696d616c466f726d617453796d626f6c +737763237e1aa359bb0200014c00115f646563466f726d617453796d626f6c73 +7400204c6a6176612f746578742f446563696d616c466f726d617453796d626f +6c733b78707372001e6a6176612e746578742e446563696d616c466f726d6174 +53796d626f6c73501d17990868939c02000c430010646563696d616c53657061 +7261746f72430005646967697443001167726f7570696e67536570617261746f +724300096d696e75735369676e4300107061747465726e536570617261746f72 +4300077065724d696c6c43000770657263656e744300097a65726f4469676974 +4c00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e6375 +7272656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e67 +3b4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e67 +3b4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c +616e672f537472696e673b7870002e0023002c002d003b203000250030740003 +efbfbd74000124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt new file mode 100644 index 00000000000..723f107b402 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt @@ -0,0 +1,42 @@ +# +# 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 +# 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. +# + +# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest. + +aced00057372001e6a6176612e746578742e446563696d616c466f726d617453 +796d626f6c73501d17990868939c020010430010646563696d616c5365706172 +61746f72430005646967697443000b6578706f6e656e7469616c43001167726f +7570696e67536570617261746f724300096d696e75735369676e4300116d6f6e +6574617279536570617261746f724300107061747465726e536570617261746f +724300077065724d696c6c43000770657263656e7449001573657269616c5665 +7273696f6e4f6e53747265616d4300097a65726f44696769744c00034e614e74 +00124c6a6176612f6c616e672f537472696e673b4c000e63757272656e637953 +796d626f6c71007e00014c0008696e66696e69747971007e00014c0012696e74 +6c43757272656e637953796d626f6c71007e00014c00066c6f63616c65740012 +4c6a6176612f7574696c2f4c6f63616c653b7870002e00230045002c002d002e +003b20300025000000020030740003efbfbd7400172a5370656369616c437572 +72656e637953796d626f6c2a740003e2889e740003434e59737200106a617661 +2e7574696c2e4c6f63616c657ef811609c30f9ec03000449000868617368636f +64654c0007636f756e74727971007e00014c00086c616e677561676571007e00 +014c000776617269616e7471007e00017870ffffffff740002434e7400027a68 +74000078 diff --git a/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java new file mode 100644 index 00000000000..fcda5b863b4 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java @@ -0,0 +1,255 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test International Decimal Format API + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - 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. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestDecimalFormatAPI extends IntlTest +{ + public static void main(String[] args) throws Exception { + new IntlTestDecimalFormatAPI().run(args); + } + + // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage. + public void TestAPI() + { + Locale reservedLocale = Locale.getDefault(); + try { + logln("DecimalFormat API test---"); logln(""); + Locale.setDefault(Locale.ENGLISH); + + // ======= Test constructors + + logln("Testing DecimalFormat constructors"); + + DecimalFormat def = new DecimalFormat(); + + final String pattern = new String("#,##0.# FF"); + DecimalFormat pat = null; + try { + pat = new DecimalFormat(pattern); + } + catch (IllegalArgumentException e) { + errln("ERROR: Could not create DecimalFormat (pattern)"); + } + + DecimalFormatSymbols symbols = + new DecimalFormatSymbols(Locale.FRENCH); + + DecimalFormat cust1 = new DecimalFormat(pattern, symbols); + + // ======= Test clone(), assignment, and equality + + logln("Testing clone() and equality operators"); + + Format clone = (Format) def.clone(); + if( ! def.equals(clone)) { + errln("ERROR: Clone() failed"); + } + + // ======= Test various format() methods + + logln("Testing various format() methods"); + +// final double d = -10456.0037; // this appears as + // -10456.003700000001 on NT +// final double d = -1.04560037e-4; // this appears as + // -1.0456003700000002E-4 on NT + final double d = -10456.00370000000000; // this works! + final long l = 100000000; + logln("" + d + " is the double value"); + + StringBuffer res1 = new StringBuffer(); + StringBuffer res2 = new StringBuffer(); + StringBuffer res3 = new StringBuffer(); + StringBuffer res4 = new StringBuffer(); + FieldPosition pos1 = new FieldPosition(0); + FieldPosition pos2 = new FieldPosition(0); + FieldPosition pos3 = new FieldPosition(0); + FieldPosition pos4 = new FieldPosition(0); + + res1 = def.format(d, res1, pos1); + logln("" + d + " formatted to " + res1); + + res2 = pat.format(l, res2, pos2); + logln("" + l + " formatted to " + res2); + + res3 = cust1.format(d, res3, pos3); + logln("" + d + " formatted to " + res3); + + res4 = cust1.format(l, res4, pos4); + logln("" + l + " formatted to " + res4); + + // ======= Test parse() + + logln("Testing parse()"); + + String text = new String("-10,456.0037"); + ParsePosition pos = new ParsePosition(0); + String patt = new String("#,##0.#"); + pat.applyPattern(patt); + double d2 = pat.parse(text, pos).doubleValue(); + if(d2 != d) { + errln("ERROR: Roundtrip failed (via parse(" + + d2 + " != " + d + ")) for " + text); + } + logln(text + " parsed into " + (long) d2); + + // ======= Test getters and setters + + logln("Testing getters and setters"); + + final DecimalFormatSymbols syms = pat.getDecimalFormatSymbols(); + def.setDecimalFormatSymbols(syms); + if(!pat.getDecimalFormatSymbols().equals( + def.getDecimalFormatSymbols())) { + errln("ERROR: set DecimalFormatSymbols() failed"); + } + + String posPrefix; + pat.setPositivePrefix("+"); + posPrefix = pat.getPositivePrefix(); + logln("Positive prefix (should be +): " + posPrefix); + if(posPrefix != "+") { + errln("ERROR: setPositivePrefix() failed"); + } + + String negPrefix; + pat.setNegativePrefix("-"); + negPrefix = pat.getNegativePrefix(); + logln("Negative prefix (should be -): " + negPrefix); + if(negPrefix != "-") { + errln("ERROR: setNegativePrefix() failed"); + } + + String posSuffix; + pat.setPositiveSuffix("_"); + posSuffix = pat.getPositiveSuffix(); + logln("Positive suffix (should be _): " + posSuffix); + if(posSuffix != "_") { + errln("ERROR: setPositiveSuffix() failed"); + } + + String negSuffix; + pat.setNegativeSuffix("~"); + negSuffix = pat.getNegativeSuffix(); + logln("Negative suffix (should be ~): " + negSuffix); + if(negSuffix != "~") { + errln("ERROR: setNegativeSuffix() failed"); + } + + long multiplier = 0; + pat.setMultiplier(8); + multiplier = pat.getMultiplier(); + logln("Multiplier (should be 8): " + multiplier); + if(multiplier != 8) { + errln("ERROR: setMultiplier() failed"); + } + + int groupingSize = 0; + pat.setGroupingSize(2); + groupingSize = pat.getGroupingSize(); + logln("Grouping size (should be 2): " + (long) groupingSize); + if(groupingSize != 2) { + errln("ERROR: setGroupingSize() failed"); + } + + pat.setDecimalSeparatorAlwaysShown(true); + boolean tf = pat.isDecimalSeparatorAlwaysShown(); + logln("DecimalSeparatorIsAlwaysShown (should be true) is " + + (tf ? "true" : "false")); + if(tf != true) { + errln("ERROR: setDecimalSeparatorAlwaysShown() failed"); + } + + String funkyPat; + funkyPat = pat.toPattern(); + logln("Pattern is " + funkyPat); + + String locPat; + locPat = pat.toLocalizedPattern(); + logln("Localized pattern is " + locPat); + + // ======= Test applyPattern() + + logln("Testing applyPattern()"); + + String p1 = new String("#,##0.0#;(#,##0.0#)"); + logln("Applying pattern " + p1); + pat.applyPattern(p1); + String s2; + s2 = pat.toPattern(); + logln("Extracted pattern is " + s2); + if( ! s2.equals(p1) ) { + errln("ERROR: toPattern() result did not match " + + "pattern applied"); + } + + String p2 = new String("#,##0.0# FF;(#,##0.0# FF)"); + logln("Applying pattern " + p2); + pat.applyLocalizedPattern(p2); + String s3; + s3 = pat.toLocalizedPattern(); + logln("Extracted pattern is " + s3); + if( ! s3.equals(p2) ) { + errln("ERROR: toLocalizedPattern() result did not match " + + "pattern applied"); + } + + // ======= Test getStaticClassID() + +// logln("Testing instanceof()"); + +// try { +// NumberFormat test = new DecimalFormat(); + +// if (! (test instanceof DecimalFormat)) { +// errln("ERROR: instanceof failed"); +// } +// } +// catch (Exception e) { +// errln("ERROR: Couldn't create a DecimalFormat"); +// } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java new file mode 100644 index 00000000000..cd19fee1e35 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java @@ -0,0 +1,139 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test International Decimal Format Symbols + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - 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. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestDecimalFormatSymbols extends IntlTest +{ + public static void main(String[] args) throws Exception { + new IntlTestDecimalFormatSymbols().run(args); + } + + // Test the API of DecimalFormatSymbols; primarily a simple get/set set. + public void TestSymbols() + { + DecimalFormatSymbols fr = new DecimalFormatSymbols(Locale.FRENCH); + + DecimalFormatSymbols en = new DecimalFormatSymbols(Locale.ENGLISH); + + if(en.equals(fr)) { + errln("ERROR: English DecimalFormatSymbols equal to French"); + } + + // just do some VERY basic tests to make sure that get/set work + + char zero = en.getZeroDigit(); + fr.setZeroDigit(zero); + if(fr.getZeroDigit() != en.getZeroDigit()) { + errln("ERROR: get/set ZeroDigit failed"); + } + + char group = en.getGroupingSeparator(); + fr.setGroupingSeparator(group); + if(fr.getGroupingSeparator() != en.getGroupingSeparator()) { + errln("ERROR: get/set GroupingSeparator failed"); + } + + char decimal = en.getDecimalSeparator(); + fr.setDecimalSeparator(decimal); + if(fr.getDecimalSeparator() != en.getDecimalSeparator()) { + errln("ERROR: get/set DecimalSeparator failed"); + } + + char perMill = en.getPerMill(); + fr.setPerMill(perMill); + if(fr.getPerMill() != en.getPerMill()) { + errln("ERROR: get/set PerMill failed"); + } + + char percent = en.getPercent(); + fr.setPercent(percent); + if(fr.getPercent() != en.getPercent()) { + errln("ERROR: get/set Percent failed"); + } + + char digit = en.getDigit(); + fr.setDigit(digit); + if(fr.getPercent() != en.getPercent()) { + errln("ERROR: get/set Percent failed"); + } + + char patternSeparator = en.getPatternSeparator(); + fr.setPatternSeparator(patternSeparator); + if(fr.getPatternSeparator() != en.getPatternSeparator()) { + errln("ERROR: get/set PatternSeparator failed"); + } + + String infinity = en.getInfinity(); + fr.setInfinity(infinity); + String infinity2 = fr.getInfinity(); + if(! infinity.equals(infinity2)) { + errln("ERROR: get/set Infinity failed"); + } + + String nan = en.getNaN(); + fr.setNaN(nan); + String nan2 = fr.getNaN(); + if(! nan.equals(nan2)) { + errln("ERROR: get/set NaN failed"); + } + + char minusSign = en.getMinusSign(); + fr.setMinusSign(minusSign); + if(fr.getMinusSign() != en.getMinusSign()) { + errln("ERROR: get/set MinusSign failed"); + } + +// char exponential = en.getExponentialSymbol(); +// fr.setExponentialSymbol(exponential); +// if(fr.getExponentialSymbol() != en.getExponentialSymbol()) { +// errln("ERROR: get/set Exponential failed"); +// } + + DecimalFormatSymbols foo = new DecimalFormatSymbols(); + + en = (DecimalFormatSymbols) fr.clone(); + + if(! en.equals(fr)) { + errln("ERROR: Clone failed"); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java b/jdk/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java new file mode 100644 index 00000000000..ab1069bdfc2 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java @@ -0,0 +1,220 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test International Number Format API + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - 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. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestNumberFormatAPI extends IntlTest +{ + public static void main(String[] args) throws Exception { + new IntlTestNumberFormatAPI().run(args); + } + + // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage. + public void TestAPI() + { + Locale reservedLocale = Locale.getDefault(); + try { + logln("NumberFormat API test---"); logln(""); + Locale.setDefault(Locale.ENGLISH); + + // ======= Test constructors + + logln("Testing NumberFormat constructors"); + + NumberFormat def = NumberFormat.getInstance(); + + NumberFormat fr = NumberFormat.getInstance(Locale.FRENCH); + + NumberFormat cur = NumberFormat.getCurrencyInstance(); + + NumberFormat cur_fr = + NumberFormat.getCurrencyInstance(Locale.FRENCH); + + NumberFormat per = NumberFormat.getPercentInstance(); + + NumberFormat per_fr = + NumberFormat.getPercentInstance(Locale.FRENCH); + + // ======= Test equality + + logln("Testing equality operator"); + + if( per_fr.equals(cur_fr) ) { + errln("ERROR: == failed"); + } + + // ======= Test various format() methods + + logln("Testing various format() methods"); + +// final double d = -10456.0037; // this appears as + // -10456.003700000001 on NT +// final double d = -1.04560037e-4; // this appears as + // -1.0456003700000002E-4 on NT + final double d = -10456.00370000000000; // this works! + final long l = 100000000; + + String res1 = new String(); + String res2 = new String(); + StringBuffer res3 = new StringBuffer(); + StringBuffer res4 = new StringBuffer(); + StringBuffer res5 = new StringBuffer(); + StringBuffer res6 = new StringBuffer(); + FieldPosition pos1 = new FieldPosition(0); + FieldPosition pos2 = new FieldPosition(0); + FieldPosition pos3 = new FieldPosition(0); + FieldPosition pos4 = new FieldPosition(0); + + res1 = cur_fr.format(d); + logln( "" + d + " formatted to " + res1); + + res2 = cur_fr.format(l); + logln("" + l + " formatted to " + res2); + + res3 = cur_fr.format(d, res3, pos1); + logln( "" + d + " formatted to " + res3); + + res4 = cur_fr.format(l, res4, pos2); + logln("" + l + " formatted to " + res4); + + res5 = cur_fr.format(d, res5, pos3); + logln("" + d + " formatted to " + res5); + + res6 = cur_fr.format(l, res6, pos4); + logln("" + l + " formatted to " + res6); + + + // ======= Test parse() + + logln("Testing parse()"); + +// String text = new String("-10,456.0037"); + String text = new String("-10456,0037"); + ParsePosition pos = new ParsePosition(0); + ParsePosition pos01 = new ParsePosition(0); + double d1 = ((Number)fr.parseObject(text, pos)).doubleValue(); + if(d1 != d) { + errln("ERROR: Roundtrip failed (via parse()) for " + text); + } + logln(text + " parsed into " + d1); + + double d2 = fr.parse(text, pos01).doubleValue(); + if(d2 != d) { + errln("ERROR: Roundtrip failed (via parse()) for " + text); + } + logln(text + " parsed into " + d2); + + double d3 = 0; + try { + d3 = fr.parse(text).doubleValue(); + } + catch (ParseException e) { + errln("ERROR: parse() failed"); + } + if(d3 != d) { + errln("ERROR: Roundtrip failed (via parse()) for " + text); + } + logln(text + " parsed into " + d3); + + + // ======= Test getters and setters + + logln("Testing getters and setters"); + + final Locale[] locales = NumberFormat.getAvailableLocales(); + long count = locales.length; + logln("Got " + count + " locales" ); + for(int i = 0; i < count; i++) { + String name; + name = locales[i].getDisplayName(); + logln(name); + } + + fr.setParseIntegerOnly( def.isParseIntegerOnly() ); + if(fr.isParseIntegerOnly() != def.isParseIntegerOnly() ) { + errln("ERROR: setParseIntegerOnly() failed"); + } + + fr.setGroupingUsed( def.isGroupingUsed() ); + if(fr.isGroupingUsed() != def.isGroupingUsed() ) { + errln("ERROR: setGroupingUsed() failed"); + } + + fr.setMaximumIntegerDigits( def.getMaximumIntegerDigits() ); + if(fr.getMaximumIntegerDigits() != def.getMaximumIntegerDigits() ) { + errln("ERROR: setMaximumIntegerDigits() failed"); + } + + fr.setMinimumIntegerDigits( def.getMinimumIntegerDigits() ); + if(fr.getMinimumIntegerDigits() != def.getMinimumIntegerDigits() ) { + errln("ERROR: setMinimumIntegerDigits() failed"); + } + + fr.setMaximumFractionDigits( def.getMaximumFractionDigits() ); + if(fr.getMaximumFractionDigits() != def.getMaximumFractionDigits() ) { + errln("ERROR: setMaximumFractionDigits() failed"); + } + + fr.setMinimumFractionDigits( def.getMinimumFractionDigits() ); + if(fr.getMinimumFractionDigits() != def.getMinimumFractionDigits() ) { + errln("ERROR: setMinimumFractionDigits() failed"); + } + + // ======= Test getStaticClassID() + +// logln("Testing instanceof()"); + +// try { +// NumberFormat test = new DecimalFormat(); + +// if (! (test instanceof DecimalFormat)) { +// errln("ERROR: instanceof failed"); +// } +// } +// catch (Exception e) { +// errln("ERROR: Couldn't create a DecimalFormat"); +// } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt new file mode 100644 index 00000000000..d27bb94eb69 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt @@ -0,0 +1,57 @@ +# +# Copyright (c) 1999, 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. +# + +# Hex dump of a serialized NumberFormat for NumberRegression. + +aced0005737200176a6176612e746578742e446563696d616c466f726d61740b +ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77 +61797353686f776e42000c67726f7570696e6753697a654200116d696e457870 +6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961 +6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961 +6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61 +76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978 +71007e00014c000e706f73697469766550726566697871007e00014c000e706f +73697469766553756666697871007e00014c000773796d626f6c737400204c6a +6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872 +00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8 +03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e +4469676974734200106d6178496e74656765724469676974734900156d617869 +6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567 +65724469676974734200116d696e4672616374696f6e4469676974734200106d +696e496e74656765724469676974734900156d696e696d756d4672616374696f +6e4469676974734900146d696e696d756d496e74656765724469676974735a00 +107061727365496e74656765724f6e6c7949001573657269616c56657273696f +6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc +12e90f18430200007870017f7f00000123000001217f7f000001240000012200 +00000001780003000000000100000001007400012d7400007400007400007372 +001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73 +501d17990868939c02000f430010646563696d616c536570617261746f724300 +05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753 +6570617261746f724300096d696e75735369676e4300116d6f6e657461727953 +6570617261746f724300107061747465726e536570617261746f724300077065 +724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f +6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00 +0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971 +007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870 +002e00230045002c002d002e003b20300025000000010030740003efbfbd7400 +0124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt new file mode 100644 index 00000000000..8da4dde6bd1 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt @@ -0,0 +1,57 @@ +# +# Copyright (c) 1999, 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. +# + +# Hex dump of a serialized NumberFormat for NumberRegression. + +aced0005737200176a6176612e746578742e446563696d616c466f726d61740b +ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77 +61797353686f776e42000c67726f7570696e6753697a654200116d696e457870 +6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961 +6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961 +6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61 +76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978 +71007e00014c000e706f73697469766550726566697871007e00014c000e706f +73697469766553756666697871007e00014c000773796d626f6c737400204c6a +6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872 +00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8 +03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e +4469676974734200106d6178496e74656765724469676974734900156d617869 +6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567 +65724469676974734200116d696e4672616374696f6e4469676974734200106d +696e496e74656765724469676974734900156d696e696d756d4672616374696f +6e4469676974734900146d696e696d756d496e74656765724469676974735a00 +107061727365496e74656765724f6e6c7949001573657269616c56657273696f +6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc +12e90f18430200007870017f7f00000314000003127f7f000003130000031100 +00000001780003000000000100000001007400012d7400007400007400007372 +001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73 +501d17990868939c02000f430010646563696d616c536570617261746f724300 +05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753 +6570617261746f724300096d696e75735369676e4300116d6f6e657461727953 +6570617261746f724300107061747465726e536570617261746f724300077065 +724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f +6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00 +0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971 +007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870 +002e00230045002c002d002e003b20300025000000010030740003efbfbd7400 +0124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/NumberFormatRounding.java b/jdk/test/java/text/Format/NumberFormat/NumberFormatRounding.java new file mode 100644 index 00000000000..895d885ff2e --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberFormatRounding.java @@ -0,0 +1,130 @@ +/* + * 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 + * 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 4092330 6246348 + * @summary Tests for rounding mode in NumberFormat + */ + +import java.math.*; +import java.text.*; + +public class NumberFormatRounding { + + static final String AE = "ArithmeticException"; + + static final double src[] = {5.5, 2.5, 1.6, 1.1, 1.0, -1.0, -1.1, -1.6, -2.5, -5.5, + 5.501, -5.501, 5.500, -5.500, 1.001, -1.001, 4.501, -4.501, 4.500, -4.500}; + static final String up[] = {"6", "3", "2", "2", "1", "-1", "-2", "-2", "-3", "-6", + "6", "-6", "6", "-6", "2", "-2", "5", "-5", "5", "-5"}; + static final String down[] = {"5", "2", "1", "1", "1", "-1", "-1", "-1", "-2", "-5", + "5", "-5", "5", "-5", "1", "-1", "4", "-4", "4", "-4"}; + static final String ceiling[] = {"6", "3", "2", "2", "1", "-1", "-1", "-1", "-2", "-5", + "6", "-5", "6", "-5", "2", "-1", "5", "-4", "5", "-4"}; + static final String floor[] = {"5", "2", "1", "1", "1", "-1", "-2", "-2", "-3", "-6", + "5", "-6", "5", "-6", "1", "-2", "4", "-5", "4", "-5"}; + static final String half_up[] = {"6", "3", "2", "1", "1", "-1", "-1", "-2", "-3", "-6", + "6", "-6", "6", "-6", "1", "-1", "5", "-5", "5", "-5"}; + static final String half_down[] = {"5", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-5", + "6", "-6", "5", "-5", "1", "-1", "5", "-5", "4", "-4"}; + static final String half_even[] = {"6", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-6", + "6", "-6", "6", "-6", "1", "-1", "5", "-5", "4", "-4"}; + static final String unnecessary[] = {AE, AE, AE, AE, "1", "-1", AE, AE, AE, AE, + AE, AE, AE, AE, AE, AE, AE, AE, AE, AE}; + + public static void main(String[] args) { + basicTest(); + + roundTest(RoundingMode.UP, up); + roundTest(RoundingMode.DOWN, down); + roundTest(RoundingMode.CEILING, ceiling); + roundTest(RoundingMode.FLOOR, floor); + roundTest(RoundingMode.HALF_UP, half_up); + roundTest(RoundingMode.HALF_DOWN, half_down); + roundTest(RoundingMode.HALF_EVEN, half_even); + roundTest(RoundingMode.UNNECESSARY, unnecessary); + } + + static void basicTest() { + NumberFormat nf = NumberFormat.getIntegerInstance(); + + if (nf.getRoundingMode() != RoundingMode.HALF_EVEN) { + throw new RuntimeException("default rounding is not HALF_EVEN"); + } + + try { + nf.setRoundingMode(null); + throw new RuntimeException( + "NullPointerException is not thrown by calling setRoundingMode(null)"); + } catch (NullPointerException npe) { + // continue testing + } + + ChoiceFormat cf = new ChoiceFormat(""); + + try { + cf.setRoundingMode(RoundingMode.HALF_EVEN); + throw new RuntimeException( + "UnsupportedOperationException is not thrown by calling setRoundingMode()"); + } catch (UnsupportedOperationException uoe) { + // continue testing + } + + try { + cf.getRoundingMode(); + throw new RuntimeException( + "UnsupportedOperationException is not thrown by calling getRoundingMode()"); + } catch (UnsupportedOperationException uoe) { + // continue testing + } + } + + static void roundTest(RoundingMode rm, String[] expected) { + NumberFormat nf = NumberFormat.getIntegerInstance(); + nf.setRoundingMode(rm); + + if (nf.getRoundingMode() != rm) { + throw new RuntimeException("set rounding mode is not returned by get method"); + } + + for (int i = 0; i < src.length; i ++) { + String result = null; + try { + result = nf.parse(nf.format(src[i])).toString(); + if (!result.equals(expected[i])) { + throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result); + } + } catch (ArithmeticException ae) { + if (expected[i].equals(AE)) { + continue; + } else { + result = AE; + throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result); + } + } catch (ParseException pe) { + throw new RuntimeException("ParseException ocurred.", pe); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/NumberRegression.java b/jdk/test/java/text/Format/NumberFormat/NumberRegression.java new file mode 100644 index 00000000000..674fdd619ca --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberRegression.java @@ -0,0 +1,1824 @@ +/* + * 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 + * 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 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014 + * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245 + * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713 + * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840 + * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198 + * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742 + * 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577 + * @summary Regression tests for NumberFormat and associated classes + * @library /java/text/testlib + * @build IntlTest HexDumpReader + * @modules java.base/sun.util.resources + * @compile -XDignore.symbol.file NumberRegression.java + * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberRegression + */ + +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - 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. +*/ + +import java.text.*; +import java.util.*; +import java.math.BigDecimal; +import java.io.*; +import java.math.BigInteger; +import sun.util.resources.LocaleData; + +public class NumberRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new NumberRegression().run(args); + } + + /** + * NumberFormat.equals comparing with null should always return false. + */ + public void Test4075713(){ + + try { + MyNumberFormatTest tmp = new MyNumberFormatTest(); + if (!tmp.equals(null)) + logln("NumberFormat.equals passed"); + } catch (NullPointerException e) { + errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception"); + } + } + + /** + * NumberFormat.equals comparing two obj equal even the setGroupingUsed + * flag is different. + */ + public void Test4074620() { + + MyNumberFormatTest nf1 = new MyNumberFormatTest(); + MyNumberFormatTest nf2 = new MyNumberFormatTest(); + + nf1.setGroupingUsed(false); + nf2.setGroupingUsed(true); + + if (nf1.equals(nf2)) errln("Test for bug 4074620 failed"); + else logln("Test for bug 4074620 passed."); + return; + } + + + /** + * DecimalFormat.format() incorrectly uses maxFractionDigits setting. + */ + + public void Test4088161 (){ + DecimalFormat df = new DecimalFormat(); + double d = 100; + df.setMinimumFractionDigits(0); + df.setMaximumFractionDigits(16); + StringBuffer sBuf1 = new StringBuffer(""); + FieldPosition fp1 = new FieldPosition(0); + logln("d = " + d); + logln("maxFractionDigits = " + df.getMaximumFractionDigits()); + logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'"); + df.setMaximumFractionDigits(17); + StringBuffer sBuf2 = new StringBuffer(""); + FieldPosition fp2 = new FieldPosition(0); + logln("maxFractionDigits = " + df.getMaximumFractionDigits()); + df.format(d, sBuf2, fp2); + String expected = Locale.getDefault().equals(new Locale("hi", "IN")) ? + "\u0967\u0966\u0966" : "100"; + if (!sBuf2.toString().equals(expected)) + errln(" format(d) = '" + sBuf2 + "'"); + } + /** + * DecimalFormatSymbols should be cloned in the ctor DecimalFormat. + * DecimalFormat(String, DecimalFormatSymbols). + */ + public void Test4087245 (){ + DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(); + DecimalFormat df = new DecimalFormat("#,##0.0", symbols); + long n = 123; + StringBuffer buf1 = new StringBuffer(); + StringBuffer buf2 = new StringBuffer(); + logln("format(" + n + ") = " + + df.format(n, buf1, new FieldPosition(0))); + symbols.setDecimalSeparator('p'); // change value of field + logln("format(" + n + ") = " + + df.format(n, buf2, new FieldPosition(0))); + if (!buf1.toString().equals(buf2.toString())) + errln("Test for bug 4087245 failed"); + } + /** + * DecimalFormat.format() incorrectly formats 0.0 + */ + public void Test4087535 () + { + DecimalFormat df = new DecimalFormat(); + df.setMinimumIntegerDigits(0); + + double n = 0; + String buffer = new String(); + buffer = df.format(n); + if (buffer.length() == 0) + errln(n + ": '" + buffer + "'"); + n = 0.1; + buffer = df.format(n); + if (buffer.length() == 0) + errln(n + ": '" + buffer + "'"); + } + + /** + * DecimalFormat.format fails when groupingSize is set to 0. + */ + public void Test4088503 (){ + DecimalFormat df = new DecimalFormat(); + df.setGroupingSize(0); + StringBuffer sBuf = new StringBuffer(""); + FieldPosition fp = new FieldPosition(0); + try { + logln(df.format(123, sBuf, fp).toString()); + } catch (Exception foo) { + errln("Test for bug 4088503 failed."); + } + + } + /** + * NumberFormat.getCurrencyInstance is wrong. + */ + public void Test4066646 () { + float returnfloat = 0.0f; + assignFloatValue(2.04f); + assignFloatValue(2.03f); + assignFloatValue(2.02f); + assignFloatValue(0.0f); + } + + public float assignFloatValue(float returnfloat) + { + logln(" VALUE " + returnfloat); + NumberFormat nfcommon = NumberFormat.getCurrencyInstance(Locale.US); + nfcommon.setGroupingUsed(false); + + String stringValue = nfcommon.format(returnfloat).substring(1); + if (Float.valueOf(stringValue).floatValue() != returnfloat) + errln(" DISPLAYVALUE " + stringValue); + return returnfloat; + } // End Of assignFloatValue() + + /** + * DecimalFormat throws exception when parsing "0" + */ + public void Test4059870() { + DecimalFormat format = new DecimalFormat("00"); + try { + logln(format.parse("0").toString()); + } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); } + } + /** + * DecimalFormatSymbol.equals should always return false when + * comparing with null. + */ + + public void Test4083018 (){ + DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(); + try { + if (!dfs.equals(null)) + logln("Test Passed!"); + } catch (Exception foo) { + errln("Test for bug 4083018 failed => Message : " + foo.getMessage()); + } + } + /** + * DecimalFormat does not round up correctly. + */ + public void Test4071492 (){ + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + double x = 0.00159999; + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(4); + String out = nf.format(x); + logln("0.00159999 formats with 4 fractional digits to " + out); + String expected = "0.0016"; + if (!out.equals(expected)) + errln("FAIL: Expected " + expected); + Locale.setDefault(savedLocale); + } + + /** + * A space as a group separator for localized pattern causes + * wrong format. WorkAround : use non-breaking space. + */ + public void Test4086575() { + + NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE); + logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern()); + logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern()); + + // No group separator + logln("...applyLocalizedPattern ###,00;(###,00) "); + ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)"); + logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); + logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); + + logln("nf: " + nf.format(1234)); // 1234,00 + logln("nf: " + nf.format(-1234)); // (1234,00) + + // Space as group separator + + logln("...applyLocalizedPattern # ###,00;(# ###,00) "); + ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)"); + logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); + logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); + String buffer = nf.format(1234); + if (!buffer.equals("1\u00a0234,00")) + errln("nf : " + buffer); // Expect 1 234,00 + buffer = nf.format(-1234); + if (!buffer.equals("(1\u00a0234,00)")) + errln("nf : " + buffer); // Expect (1 234,00) + + // Erroneously prints: + // 1234,00 , + // (1234,00 ,) + + } + /** + * DecimalFormat.parse returns wrong value + */ + public void Test4068693() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + logln("----- Test Application -----"); + ParsePosition pos; + DecimalFormat df = new DecimalFormat(); + Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0)); + if (!d.toString().equals("123.55456")) { + errln("Result -> " + d.doubleValue()); + } + Locale.setDefault(savedLocale); + } + + /* bugs 4069754, 4067878 + * null pointer thrown when accessing a deserialized DecimalFormat + * object. + */ + public void Test4069754() + { + try { + myformat it = new myformat(); + logln(it.Now()); + FileOutputStream ostream = new FileOutputStream("t.tmp"); + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(it); + ostream.close(); + logln("Saved ok."); + + FileInputStream istream = new FileInputStream("t.tmp"); + ObjectInputStream p2 = new ObjectInputStream(istream); + myformat it2 = (myformat)p2.readObject(); + logln(it2.Now()); + istream.close(); + logln("Loaded ok."); + } catch (Exception foo) { + errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage()); + } + } + + /** + * DecimalFormat.applyPattern(String) allows illegal patterns + */ + public void Test4087251 (){ + DecimalFormat df = new DecimalFormat(); + try { + df.applyPattern("#.#.#"); + logln("toPattern() returns \"" + df.toPattern() + "\""); + errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + logln("Caught Illegal Argument Error !"); + } + // Second test; added 5/11/98 when reported to fail on 1.2b3 + try { + df.applyPattern("#0.0#0#0"); + logln("toPattern() returns \"" + df.toPattern() + "\""); + errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + logln("Ok - IllegalArgumentException for #0.0#0#0"); + } + } + + /** + * DecimalFormat.format() loses precision + */ + public void Test4090489 (){ + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + df.setMinimumFractionDigits(10); + df.setGroupingUsed(false); + double d = 1.000000000000001E7; + BigDecimal bd = new BigDecimal(d); + StringBuffer sb = new StringBuffer(""); + FieldPosition fp = new FieldPosition(0); + logln("d = " + d); + logln("BigDecimal.toString(): " + bd.toString()); + df.format(d, sb, fp); + if (!sb.toString().equals("10000000.0000000100")) { + errln("DecimalFormat.format(): " + sb.toString()); + } + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.format() loses precision + */ + public void Test4090504 () + { + double d = 1; + logln("d = " + d); + DecimalFormat df = new DecimalFormat(); + StringBuffer sb; + FieldPosition fp; + try { + for (int i = 17; i <= 20; i++) { + df.setMaximumFractionDigits(i); + sb = new StringBuffer(""); + fp = new FieldPosition(0); + logln(" getMaximumFractionDigits() = " + i); + logln(" formated: " + df.format(d, sb, fp)); + } + } catch (Exception foo) { + errln("Bug 4090504 regression test failed. Message : " + foo.getMessage()); + } + } + /** + * DecimalFormat.parse(String str, ParsePosition pp) loses precision + */ + public void Test4095713 () + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + String str = "0.1234"; + Double d1 = new Double(str); + Double d2 = (Double) df.parse(str, new ParsePosition(0)); + logln(d1.toString()); + if (d2.doubleValue() != d1.doubleValue()) + errln("Bug 4095713 test failed, new double value : " + d2.doubleValue()); + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.parse() fails when multiplier is not set to 1 + */ + public void Test4092561 () + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + + String str = Long.toString(Long.MIN_VALUE); + logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); + df.setMultiplier(100); + Number num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != -9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue()); + } + + df.setMultiplier(-100); + num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != 9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue()); + } + + str = Long.toString(Long.MAX_VALUE); + logln("Long.MAX_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); + + df.setMultiplier(100); + num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != 9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue()); + } + + df.setMultiplier(-100); + num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != -9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue()); + } + + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat: Negative format ignored. + */ + public void Test4092480 () + { + DecimalFormat dfFoo = new DecimalFormat("000"); + + try { + dfFoo.applyPattern("0000;-000"); + if (!dfFoo.toPattern().equals("#0000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + dfFoo.applyPattern("000;-000"); + if (!dfFoo.toPattern().equals("#000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + + dfFoo.applyPattern("000;-0000"); + if (!dfFoo.toPattern().equals("#000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + + dfFoo.applyPattern("0000;-000"); + if (!dfFoo.toPattern().equals("#0000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + } catch (Exception foo) { + errln("Message " + foo.getMessage()); + } + } + /** + * NumberFormat.getCurrencyInstance() produces format that uses + * decimal separator instead of monetary decimal separator. + * + * Rewrote this test not to depend on the actual pattern. Pattern should + * never contain the monetary separator! Decimal separator in pattern is + * interpreted as monetary separator if currency symbol is seen! + */ + public void Test4087244 () { + Locale de = new Locale("pt", "PT"); + DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de); + DecimalFormatSymbols sym = df.getDecimalFormatSymbols(); + sym.setMonetaryDecimalSeparator('$'); + df.setDecimalFormatSymbols(sym); + char decSep = sym.getDecimalSeparator(); + char monSep = sym.getMonetaryDecimalSeparator(); + char zero = sym.getZeroDigit(); + if (decSep == monSep) { + errln("ERROR in test: want decimal sep != monetary sep"); + } else { + df.setMinimumIntegerDigits(1); + df.setMinimumFractionDigits(2); + String str = df.format(1.23); + String monStr = "1" + monSep + "23"; + String decStr = "1" + decSep + "23"; + if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) { + logln("OK: 1.23 -> \"" + str + "\" contains \"" + + monStr + "\" and not \"" + decStr + '"'); + } else { + errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" + + monStr + + "\" and not \"" + decStr + '"'); + } + } + } + /** + * Number format data rounding errors for locale FR + */ + public void Test4070798 () { + NumberFormat formatter; + String tempString; + /* User error : + String expectedDefault = "-5\u00a0789,987"; + String expectedCurrency = "5\u00a0789,98 F"; + String expectedPercent = "-578\u00a0998%"; + */ + String expectedDefault = "-5\u00a0789,988"; + String expectedCurrency = "5\u00a0789,99 \u20AC"; + // changed for bug 6547501 + String expectedPercent = "-578\u00a0999 %"; + + formatter = NumberFormat.getNumberInstance(Locale.FRANCE); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedDefault)) { + logln ("Bug 4070798 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + + formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE); + tempString = formatter.format( 5789.9876 ); + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4070798 currency test assed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + + + formatter = NumberFormat.getPercentInstance(Locale.FRANCE); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4070798 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + } + /** + * Data rounding errors for French (Canada) locale + */ + public void Test4071005 () { + + NumberFormat formatter; + String tempString; + /* user error : + String expectedDefault = "-5 789,987"; + String expectedCurrency = "5 789,98 $"; + String expectedPercent = "-578 998%"; + */ + String expectedDefault = "-5\u00a0789,988"; + String expectedCurrency = "5\u00a0789,99 $"; + // changed for bug 6547501 + String expectedPercent = "-578\u00a0999 %"; + + formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH); + tempString = formatter.format (-5789.9876); + if (tempString.equals(expectedDefault)) { + logln ("Bug 4071005 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH); + tempString = formatter.format( 5789.9876 ) ; + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4071005 currency test passed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4071005 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + } + + /** + * Data rounding errors for German (Germany) locale + */ + public void Test4071014 () { + NumberFormat formatter; + String tempString; + /* user error : + String expectedDefault = "-5.789,987"; + String expectedCurrency = "5.789,98 DM"; + String expectedPercent = "-578.998%"; + */ + String expectedDefault = "-5.789,988"; + String expectedCurrency = "5.789,99 \u20AC"; + String expectedPercent = "-578.999%"; + + formatter = NumberFormat.getNumberInstance(Locale.GERMANY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedDefault)) { + logln ("Bug 4071014 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY); + tempString = formatter.format( 5789.9876 ) ; + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4071014 currency test passed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + + formatter = NumberFormat.getPercentInstance(Locale.GERMANY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4071014 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + + } + /** + * Data rounding errors for Italian locale number formats + */ + public void Test4071859 () { + NumberFormat formatter; + String tempString; + /* user error : + String expectedDefault = "-5.789,987"; + String expectedCurrency = "-L. 5.789,98"; + String expectedPercent = "-578.998%"; + */ + String expectedDefault = "-5.789,988"; + String expectedCurrency = "-\u20AC 5.789,99"; + String expectedPercent = "-578.999%"; + + formatter = NumberFormat.getNumberInstance(Locale.ITALY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedDefault)) { + logln ("Bug 4071859 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + formatter = NumberFormat.getCurrencyInstance(Locale.ITALY); + tempString = formatter.format( -5789.9876 ) ; + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4071859 currency test passed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + + formatter = NumberFormat.getPercentInstance(Locale.ITALY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4071859 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + + } + + /* bug 4071859 + * Test rounding for nearest even. + */ + public void Test4093610() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat("#0.#"); + + roundingTest(df, 12.15, "12.2"); // Rounding-up. Above tie (12.150..) + roundingTest(df, 12.25, "12.2"); // No round-up. Exact + half-even rule. + roundingTest(df, 12.45, "12.4"); // No round-up. Below tie (12.449..) + roundingTest(df, 12.450000001,"12.5"); // Rounding-up. Above tie. + roundingTest(df, 12.55, "12.6"); // Rounding-up. Above tie (12.550..) + roundingTest(df, 12.650000001,"12.7"); // Rounding-up. Above tie. + roundingTest(df, 12.75, "12.8"); // Rounding-up. Exact + half-even rule. + roundingTest(df, 12.750000001,"12.8"); // Rounding-up. Above tie. + roundingTest(df, 12.85, "12.8"); // No round-up. Below tie (12.849..) + roundingTest(df, 12.850000001,"12.9"); // Rounding-up. Above tie. + roundingTest(df, 12.950000001,"13"); // Rounding-up. Above tie. + + Locale.setDefault(savedLocale); + } + + void roundingTest(DecimalFormat df, double x, String expected) + { + String out = df.format(x); + logln("" + x + " formats with 1 fractional digits to " + out); + if (!out.equals(expected)) errln("FAIL: Expected " + expected); + } + /** + * Tests the setMaximumFractionDigits limit. + */ + public void Test4098741() + { + try { + NumberFormat fmt = NumberFormat.getPercentInstance(); + fmt.setMaximumFractionDigits(20); + logln(fmt.format(.001)); + } catch (Exception foo) { + errln("Bug 4098471 failed with exception thrown : " + foo.getMessage()); + } + } + /** + * Tests illegal pattern exception. + * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated. + * Part2 has been fixed. + */ + public void Test4074454() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#"); + logln("Inconsistent negative pattern is fine."); + DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces"); + String tempString = newFmt.format(3456.78); + if (!tempString.equals("3,456.78 p'ieces")) + errln("Failed! 3,456.78 p'ieces expected, but got : " + tempString); + } catch (Exception foo) { + errln("An exception was thrown for any inconsistent negative pattern."); + } + Locale.setDefault(savedLocale); + } + + /** + * Tests all different comments. + * Response to some comments : + * [1] DecimalFormat.parse API documentation is more than just one line. + * This is not a reproducable doc error in 116 source code. + * [2] See updated javadoc. + * [3] Fixed. + * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails, + * a null object will be returned. The unchanged parse position also + * reflects an error. + * NumberFormat.parse(String) : If parsing fails, an ParseException + * will be thrown. + * See updated javadoc for more details. + * [5] See updated javadoc. + * [6] See updated javadoc. + * [7] This is a correct behavior if the DateFormat object is linient. + * Otherwise, an IllegalArgumentException will be thrown when formatting + * "January 35". See GregorianCalendar class javadoc for more details. + */ + public void Test4099404() + { + try { + DecimalFormat fmt = new DecimalFormat("000.0#0"); + errln("Bug 4099404 failed applying illegal pattern \"000.0#0\""); + } catch (Exception foo) { + logln("Bug 4099404 pattern \"000.0#0\" passed"); + } + try { + DecimalFormat fmt = new DecimalFormat("0#0.000"); + errln("Bug 4099404 failed applying illegal pattern \"0#0.000\""); + } catch (Exception foo) { + logln("Bug 4099404 pattern \"0#0.000\" passed"); + } + } + /** + * DecimalFormat.applyPattern doesn't set minimum integer digits + */ + public void Test4101481() + { + DecimalFormat sdf = new DecimalFormat("#,##0"); + if (sdf.getMinimumIntegerDigits() != 1) + errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits()); + } + /** + * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition(). + */ + public void Test4052223() + { + try { + DecimalFormat fmt = new DecimalFormat("#,#00.00"); + Number num = fmt.parse("abc3"); + errln("Bug 4052223 failed : can't parse string \"a\". Got " + num); + } catch (ParseException foo) { + logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset()); + } + } + /** + * API tests for API addition request A9. + */ + public void Test4061302() + { + DecimalFormatSymbols fmt = DecimalFormatSymbols.getInstance(); + String currency = fmt.getCurrencySymbol(); + String intlCurrency = fmt.getInternationalCurrencySymbol(); + char monDecSeparator = fmt.getMonetaryDecimalSeparator(); + if (currency.equals("") || + intlCurrency.equals("") || + monDecSeparator == 0) { + errln("getCurrencySymbols failed, got empty string."); + } + logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); + fmt.setCurrencySymbol("XYZ"); + fmt.setInternationalCurrencySymbol("ABC"); + fmt.setMonetaryDecimalSeparator('*'); + currency = fmt.getCurrencySymbol(); + intlCurrency = fmt.getInternationalCurrencySymbol(); + monDecSeparator = fmt.getMonetaryDecimalSeparator(); + if (!currency.equals("XYZ") || + !intlCurrency.equals("ABC") || + monDecSeparator != '*') { + errln("setCurrencySymbols failed."); + } + logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); + } + /** + * API tests for API addition request A23. FieldPosition.getBeginIndex and + * FieldPosition.getEndIndex. + */ + public void Test4062486() + { + DecimalFormat fmt = new DecimalFormat("#,##0.00"); + StringBuffer formatted = new StringBuffer(); + FieldPosition field = new FieldPosition(0); + Double num = new Double(1234.5); + fmt.format(num, formatted, field); + if (field.getBeginIndex() != 0 && field.getEndIndex() != 5) + errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); + field.setBeginIndex(7); + field.setEndIndex(4); + if (field.getBeginIndex() != 7 && field.getEndIndex() != 4) + errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); + } + + /** + * DecimalFormat.parse incorrectly works with a group separator. + */ + public void Test4108738() + { + + DecimalFormat df = new DecimalFormat("#,##0.###", + DecimalFormatSymbols.getInstance(java.util.Locale.US)); + String text = "1.222,111"; + Number num = df.parse(text,new ParsePosition(0)); + if (!num.toString().equals("1.222")) + errln("\"" + text + "\" is parsed as " + num); + text = "1.222x111"; + num = df.parse(text,new ParsePosition(0)); + if (!num.toString().equals("1.222")) + errln("\"" + text + "\" is parsed as " + num); + } + + /** + * DecimalFormat.format() incorrectly formats negative doubles. + */ + public void Test4106658() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706 + double d1 = -0.0; + double d2 = -0.0001; + StringBuffer buffer = new StringBuffer(); + logln("pattern: \"" + df.toPattern() + "\""); + df.format(d1, buffer, new FieldPosition(0)); + if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 + errln(d1 + " is formatted as " + buffer); + } + buffer.setLength(0); + df.format(d2, buffer, new FieldPosition(0)); + if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 + errln(d2 + " is formatted as " + buffer); + } + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.parse returns 0 if string parameter is incorrect. + */ + public void Test4106662() + { + DecimalFormat df = new DecimalFormat(); + String text = "x"; + ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0); + + logln("pattern: \"" + df.toPattern() + "\""); + Number num = df.parse(text, pos1); + if (num != null) { + errln("Test Failed: \"" + text + "\" is parsed as " + num); + } + df = null; + df = new DecimalFormat("$###.00"); + num = df.parse("$", pos2); + if (num != null){ + errln("Test Failed: \"$\" is parsed as " + num); + } + } + + /** + * NumberFormat.parse doesn't return null + */ + public void Test4114639() + { + NumberFormat format = NumberFormat.getInstance(); + String text = "time 10:x"; + ParsePosition pos = new ParsePosition(8); + Number result = format.parse(text, pos); + if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't + } + + /** + * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG. + */ + public void Test4106664() + { + DecimalFormat df = new DecimalFormat(); + long n = 1234567890123456L; + int m = 12345678; + BigInteger bigN = BigInteger.valueOf(n); + bigN = bigN.multiply(BigInteger.valueOf(m)); + df.setMultiplier(m); + df.setGroupingUsed(false); + logln("formated: " + + df.format(n, new StringBuffer(), new FieldPosition(0))); + logln("expected: " + bigN.toString()); + } + /** + * DecimalFormat.format incorrectly formats -0.0. + */ + public void Test4106667() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + df.setPositivePrefix("+"); + double d = -0.0; + logln("pattern: \"" + df.toPattern() + "\""); + StringBuffer buffer = new StringBuffer(); + df.format(d, buffer, new FieldPosition(0)); + if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 + errln(d + " is formatted as " + buffer); + } + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.setMaximumIntegerDigits() works incorrectly. + */ + public void Test4110936() + { + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumIntegerDigits(128); + logln("setMaximumIntegerDigits(128)"); + if (nf.getMaximumIntegerDigits() != 128) + errln("getMaximumIntegerDigits() returns " + + nf.getMaximumIntegerDigits()); + } + + /** + * Locale data should use generic currency symbol + * + * 1) Make sure that all currency formats use the generic currency symbol. + * 2) Make sure we get the same results using the generic symbol or a + * hard-coded one. + */ + public void Test4122840() + { + Locale[] locales = NumberFormat.getAvailableLocales(); + + for (int i = 0; i < locales.length; i++) { + ResourceBundle rb = LocaleData.getBundle("sun.text.resources.FormatData", + locales[i]); + // + // Get the currency pattern for this locale. We have to fish it + // out of the ResourceBundle directly, since DecimalFormat.toPattern + // will return the localized symbol, not \00a4 + // + String[] numPatterns = (String[])rb.getObject("NumberPatterns"); + String pattern = numPatterns[1]; + + if (pattern.indexOf("\u00A4") == -1 ) { + errln("Currency format for " + locales[i] + + " does not contain generic currency symbol:" + + pattern ); + } + + // Create a DecimalFormat using the pattern we got and format a number + DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locales[i]); + DecimalFormat fmt1 = new DecimalFormat(pattern, symbols); + + String result1 = fmt1.format(1.111); + + // + // Now substitute in the locale's currency symbol and create another + // pattern. Replace the decimal separator with the monetary separator. + // + char decSep = symbols.getDecimalSeparator(); + char monSep = symbols.getMonetaryDecimalSeparator(); + StringBuffer buf = new StringBuffer(pattern); + for (int j = 0; j < buf.length(); j++) { + if (buf.charAt(j) == '\u00a4') { + String cur = "'" + symbols.getCurrencySymbol() + "'"; + buf.replace(j, j+1, cur); + j += cur.length() - 1; + } + } + symbols.setDecimalSeparator(monSep); + DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols); + + String result2 = fmt2.format(1.111); + + if (!result1.equals(result2)) { + errln("Results for " + locales[i] + " differ: " + + result1 + " vs " + result2); + } + } + } + + /** + * DecimalFormat.format() delivers wrong string. + */ + public void Test4125885() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + double rate = 12.34; + DecimalFormat formatDec = new DecimalFormat ("000.00"); + logln("toPattern: " + formatDec.toPattern()); + String rateString= formatDec.format(rate); + if (!rateString.equals("012.34")) + errln("result : " + rateString + " expected : 012.34"); + rate = 0.1234; + formatDec = null; + formatDec = new DecimalFormat ("+000.00%;-000.00%"); + logln("toPattern: " + formatDec.toPattern()); + rateString= formatDec.format(rate); + if (!rateString.equals("+012.34%")) + errln("result : " + rateString + " expected : +012.34%"); + Locale.setDefault(savedLocale); + } + + /** + ** + * DecimalFormat produces extra zeros when formatting numbers. + */ + public void Test4134034() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat nf = new DecimalFormat("##,###,###.00"); + + String f = nf.format(9.02); + if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02"); + + f = nf.format(0); + if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00"); + Locale.setDefault(savedLocale); + } + + /** + * CANNOT REPRODUCE - This bug could not be reproduced. It may be + * a duplicate of 4134034. + * + * JDK 1.1.6 Bug, did NOT occur in 1.1.5 + * Possibly related to bug 4125885. + * + * This class demonstrates a regression in version 1.1.6 + * of DecimalFormat class. + * + * 1.1.6 Results + * Value 1.2 Format #.00 Result '01.20' !!!wrong + * Value 1.2 Format 0.00 Result '001.20' !!!wrong + * Value 1.2 Format 00.00 Result '0001.20' !!!wrong + * Value 1.2 Format #0.0# Result '1.2' + * Value 1.2 Format #0.00 Result '001.20' !!!wrong + * + * 1.1.5 Results + * Value 1.2 Format #.00 Result '1.20' + * Value 1.2 Format 0.00 Result '1.20' + * Value 1.2 Format 00.00 Result '01.20' + * Value 1.2 Format #0.0# Result '1.2' + * Value 1.2 Format #0.00 Result '1.20' + */ + public void Test4134300() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + String[] DATA = { + // Pattern Expected string + "#.00", "1.20", + "0.00", "1.20", + "00.00", "01.20", + "#0.0#", "1.2", + "#0.00", "1.20", + }; + for (int i=0; i " + s); + s = f.format(-123.456); + if (!s.equals("-123.456")) + errln("Fail: Format empty pattern x -123.456 => " + s); + } + } + + /** + * BigDecimal numbers get their fractions truncated by NumberFormat. + */ + public void Test4141750() { + try { + String str = "12345.67"; + BigDecimal bd = new BigDecimal(str); + NumberFormat nf = NumberFormat.getInstance(Locale.US); + String sd = nf.format(bd); + if (!sd.endsWith("67")) { + errln("Fail: " + str + " x format -> " + sd); + } + } + catch (Exception e) { + errln(e.toString()); + e.printStackTrace(); + } + } + + /** + * DecimalFormat toPattern() doesn't quote special characters or handle + * single quotes. + */ + public void Test4145457() { + try { + DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(); + DecimalFormatSymbols sym = nf.getDecimalFormatSymbols(); + sym.setDecimalSeparator('\''); + nf.setDecimalFormatSymbols(sym); + double pi = 3.14159; + + String[] PATS = { "#.00 'num''ber'", "''#.00''" }; + + for (int i=0; i \"" + pat + '"'); + + if (val == val2 && out.equals(out2)) { + logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" + + out + "\" -> " + val + " -> \"" + + out2 + "\" -> " + val2); + } + else { + errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" + + out + "\" -> " + val + " -> \"" + + out2 + "\" -> " + val2); + } + } + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + /** + * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. + * CANNOT REPRODUCE + * This bug is a duplicate of 4139344, which is a duplicate of 4134300 + */ + public void Test4147295() { + DecimalFormat sdf = new DecimalFormat(); + String pattern = "#,###"; + logln("Applying pattern \"" + pattern + "\""); + sdf.applyPattern(pattern); + int minIntDig = sdf.getMinimumIntegerDigits(); + if (minIntDig != 0) { + errln("Test failed"); + errln(" Minimum integer digits : " + minIntDig); + errln(" new pattern: " + sdf.toPattern()); + } else { + logln("Test passed"); + logln(" Minimum integer digits : " + minIntDig); + } + } + + /** + * DecimalFormat formats -0.0 as +0.0 + * See also older related bug 4106658, 4106667 + */ + public void Test4147706() { + DecimalFormat df = new DecimalFormat("#,##0.0##"); + df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH)); + double d1 = -0.0; + double d2 = -0.0001; + StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0)); + StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0)); + if (!f1.toString().equals("-0.0")) { + errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"'); + } + if (!f2.toString().equals("-0.0")) { + errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"'); + } + } + + /** + * NumberFormat cannot format Double.MAX_VALUE + */ + public void Test4162198() { + double dbl = Double.MAX_VALUE; + NumberFormat f = NumberFormat.getInstance(); + f.setMaximumFractionDigits(Integer.MAX_VALUE); + f.setMaximumIntegerDigits(Integer.MAX_VALUE); + String s = f.format(dbl); + logln("The number " + dbl + " formatted to " + s); + Number n = null; + try { + n = f.parse(s); + } catch (java.text.ParseException e) { + errln("Caught a ParseException:"); + e.printStackTrace(); + } + logln("The string " + s + " parsed as " + n); + if (n.doubleValue() != dbl) { + errln("Round trip failure"); + } + } + + /** + * NumberFormat does not parse negative zero. + */ + public void Test4162852() throws ParseException { + for (int i=0; i<2; ++i) { + NumberFormat f = (i == 0) ? NumberFormat.getInstance() + : NumberFormat.getPercentInstance(); + double d = -0.0; + String s = f.format(d); + double e = f.parse(s).doubleValue(); + logln("" + + d + " -> " + + '"' + s + '"' + " -> " + + e); + if (e != 0.0 || 1.0/e > 0.0) { + logln("Failed to parse negative zero"); + } + } + } + + /** + * NumberFormat truncates data + */ + public void Test4167494() throws Exception { + NumberFormat fmt = NumberFormat.getInstance(Locale.US); + + double a = Double.MAX_VALUE; + String s = fmt.format(a); + double b = fmt.parse(s).doubleValue(); + boolean match = a == b; + if (match) { + logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); + } else { + errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); + } + + // We don't test Double.MIN_VALUE because the locale data for the US + // currently doesn't specify enough digits to display Double.MIN_VALUE. + // This is correct for now; however, we leave this here as a reminder + // in case we want to address this later. + if (false) { + a = Double.MIN_VALUE; + s = fmt.format(a); + b = fmt.parse(s).doubleValue(); + match = a == b; + if (match) { + logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); + } else { + errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); + } + } + } + + /** + * DecimalFormat.parse() fails when ParseIntegerOnly set to true + */ + public void Test4170798() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + df.setParseIntegerOnly(true); + Number n = df.parse("-0.0", new ParsePosition(0)); + if (!(n instanceof Long || n instanceof Integer) + || n.intValue() != 0) { + errln("FAIL: parse(\"-0.0\") returns " + + n + " (" + n.getClass().getName() + ')'); + } + Locale.setDefault(savedLocale); + } + + /** + * toPattern only puts the first grouping separator in. + */ + public void Test4176114() { + String[] DATA = { + "00", "#00", + "000", "#000", // No grouping + "#000", "#000", // No grouping + "#,##0", "#,##0", + "#,000", "#,000", + "0,000", "#0,000", + "00,000", "#00,000", + "000,000", "#,000,000", + "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported + }; + for (int i=0; i " + s + ", want " + DATA[i+1]); + } + } + } + + /** + * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2 + */ + public void Test4179818() { + String DATA[] = { + // Input Pattern Expected output + "1.2511", "#.#", "1.3", + "1.2501", "#.#", "1.3", + "0.9999", "#", "1", + }; + DecimalFormat fmt = new DecimalFormat("#", + DecimalFormatSymbols.getInstance(Locale.US)); + for (int i=0; i " + fmt.format(-1) + + ", exp ^1"); + } + if (!fmt.getNegativePrefix().equals("^")) { + errln("FAIL: (minus=^).getNegativePrefix -> " + + fmt.getNegativePrefix() + ", exp ^"); + } + sym.setMinusSign('-'); + + fmt.applyPattern("#%"); + sym.setPercent('^'); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(0.25).equals("25^")) { + errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) + + ", exp 25^"); + } + if (!fmt.getPositiveSuffix().equals("^")) { + errln("FAIL: (percent=^).getPositiveSuffix -> " + + fmt.getPositiveSuffix() + ", exp ^"); + } + sym.setPercent('%'); + + fmt.applyPattern("#\u2030"); + sym.setPerMill('^'); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(0.25).equals("250^")) { + errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) + + ", exp 250^"); + } + if (!fmt.getPositiveSuffix().equals("^")) { + errln("FAIL: (permill=^).getPositiveSuffix -> " + + fmt.getPositiveSuffix() + ", exp ^"); + } + sym.setPerMill('\u2030'); + + fmt.applyPattern("\u00A4#.00"); + sym.setCurrencySymbol("usd"); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(12.5).equals("usd12.50")) { + errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) + + ", exp usd12.50"); + } + if (!fmt.getPositivePrefix().equals("usd")) { + errln("FAIL: (currency=usd).getPositivePrefix -> " + + fmt.getPositivePrefix() + ", exp usd"); + } + sym.setCurrencySymbol("$"); + + fmt.applyPattern("\u00A4\u00A4#.00"); + sym.setInternationalCurrencySymbol("DOL"); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(12.5).equals("DOL12.50")) { + errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) + + ", exp DOL12.50"); + } + if (!fmt.getPositivePrefix().equals("DOL")) { + errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " + + fmt.getPositivePrefix() + ", exp DOL"); + } + sym.setInternationalCurrencySymbol("USD"); + + // Since the pattern logic has changed, make sure that patterns round + // trip properly. Test stream in/out integrity too. + Locale[] avail = NumberFormat.getAvailableLocales(); + for (int i=0; i \"" + pat + + "\" -> \"" + f2.toPattern() + '"'); + } + + // Test toLocalizedPattern/applyLocalizedPattern round trip + pat = df.toLocalizedPattern(); + f2.applyLocalizedPattern(pat); + if (!df.equals(f2)) { + errln("FAIL: " + avail[i] + " -> localized \"" + pat + + "\" -> \"" + f2.toPattern() + '"'); + } + + // Test writeObject/readObject round trip + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(df); + oos.flush(); + baos.close(); + byte[] bytes = baos.toByteArray(); + ObjectInputStream ois = + new ObjectInputStream(new ByteArrayInputStream(bytes)); + f2 = (DecimalFormat) ois.readObject(); + if (!df.equals(f2)) { + errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat + + "\" -> " + + (f2 != null ? ("\""+f2.toPattern()+'"') : "null")); + } + + } + } + } + + /** + * DecimalFormat.parse() fails for mulipliers 2^n. + */ + public void Test4216742() throws ParseException { + DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US); + long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L}; + for (int i=0; i 0 != DATA[i] > 0) { + errln("\"" + str + "\" parse(x " + fmt.getMultiplier() + + ") => " + n); + } + } + } + } + + /** + * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction + * digits. + */ + public void Test4217661() { + Object[] DATA = { + new Double(0.001), "0", + new Double(1.001), "1", + new Double(0.006), "0.01", + new Double(1.006), "1.01", + }; + NumberFormat fmt = NumberFormat.getInstance(Locale.US); + fmt.setMaximumFractionDigits(2); + for (int i=0; i 0 && args[0].equals("-debug")) { + DEBUG = true; + String[] newargs = new String[args.length - 1]; + System.arraycopy(args, 1, newargs, 0, newargs.length); + args = newargs; + } + new NumberRoundTrip().run(args); + } + + public void TestNumberFormatRoundTrip() { + logln("Default Locale"); + localeName = "Default Locale"; + formatName = "getInstance"; + doTest(NumberFormat.getInstance()); + formatName = "getNumberInstance"; + doTest(NumberFormat.getNumberInstance()); + formatName = "getCurrencyInstance"; + doTest(NumberFormat.getCurrencyInstance()); + formatName = "getPercentInstance"; + doTest(NumberFormat.getPercentInstance()); + + Locale[] loc = NumberFormat.getAvailableLocales(); + for (int i=0; i " + escape(s)); + n = fmt.parse(s); + if (DEBUG) logln(" " + escape(s) + " P> " + n); + s2 = fmt.format(n); + if (DEBUG) logln(" " + n + " F> " + escape(s2)); + + if (STRING_COMPARE) { + if (!s.equals(s2)) { + if (fmt instanceof DecimalFormat) { + logln("Text mismatch: expected: " + s + ", got: " + s2 + " --- Try BigDecimal parsing."); + ((DecimalFormat)fmt).setParseBigDecimal(true); + n = fmt.parse(s); + if (DEBUG) logln(" " + escape(s) + " P> " + n); + s2 = fmt.format(n); + if (DEBUG) logln(" " + n + " F> " + escape(s2)); + ((DecimalFormat)fmt).setParseBigDecimal(false); + + if (!s.equals(s2)) { + err = "STRING ERROR(DecimalFormat): "; + } + } else { + err = "STRING ERROR(NumberFormat): "; + } + } + } + + if (EXACT_NUMERIC_COMPARE) { + if (value.doubleValue() != n.doubleValue()) { + err += "NUMERIC ERROR: "; + } + } else { + // Compute proportional error + double error = proportionalError(value, n); + + if (error > MAX_ERROR) { + err += "NUMERIC ERROR " + error + ": "; + } + + if (error > max_numeric_error) max_numeric_error = error; + if (error < min_numeric_error) min_numeric_error = error; + } + + String message = value + typeOf(value) + " F> " + + escape(s) + " P> " + + n + typeOf(n) + " F> " + + escape(s2); + if (err.length() > 0) { + errln("*** " + err + " with " + + formatName + " in " + localeName + + " " + message); + } else { + logln(message); + } + } catch (ParseException e) { + errln("*** " + e.toString() + " with " + + formatName + " in " + localeName); + } + } + + static String typeOf(Number n) { + if (n instanceof Long) return " Long"; + if (n instanceof Double) return " Double"; + return " Number"; + } + + static String escape(String s) { + StringBuffer buf = new StringBuffer(); + for (int i=0; i> 12)); + buf.append(Integer.toHexString((c & 0x0F00) >> 8)); + buf.append(Integer.toHexString((c & 0x00F0) >> 4)); + buf.append(Integer.toHexString(c & 0x000F)); + } + } + return buf.toString(); + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/NumberTest.java b/jdk/test/java/text/Format/NumberFormat/NumberTest.java new file mode 100644 index 00000000000..ca519bb6dab --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberTest.java @@ -0,0 +1,411 @@ +/* + * 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 + * 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 4122840 4135202 4408066 4838107 8008577 + * @summary test NumberFormat + * @library /java/text/testlib + * @modules java.base/sun.util.resources + * @compile -XDignore.symbol.file NumberTest.java + * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberTest + */ + +import java.util.*; +import java.text.*; +import sun.util.resources.LocaleData; + +public class NumberTest extends IntlTest +{ + public static void main(String[] args) throws Exception { + new NumberTest().run(args); + } + + // Test pattern handling + public void TestPatterns() + { + DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US); + String pat[] = { "#.#", "#.", ".#", "#" }; + String newpat[] = { "#0.#", "#0.", "#.0", "#" }; + String num[] = { "0", "0.", ".0", "0" }; + for (int i=0; i \"" + + fmt.toPattern() + '"'); + + for (int v=0; v " + escape(s)); + if (!s.equals(valFormat[v+ival])) { + errln("FAIL: Expected " + valFormat[v+ival] + + ", got " + s + + ", pattern=" + fmt.toPattern()); + } + + ParsePosition pos = new ParsePosition(0); + Number a = fmt.parse(s, pos); + if (pos.getIndex() == s.length()) { + logln(" Parse -> " + a); + if (a.doubleValue() != valParse[v+ival]) { + errln("FAIL: Expected " + valParse[v+ival] + + ", got " + a.doubleValue() + + ", pattern=" + fmt.toPattern()); + } + } else { + errln(" FAIL: Partial parse (" + pos.getIndex() + + " chars) -> " + a); + } + } + for (int v=0; v " + escape(s)); + if (!s.equals(lvalFormat[v+ilval])) { + errln("ERROR: Expected " + lvalFormat[v+ilval] + + ", got " + s + + ", pattern=" + fmt.toPattern()); + } + + ParsePosition pos = new ParsePosition(0); + Number a = fmt.parse(s, pos); + if (pos.getIndex() == s.length()) { + logln(" Parse -> " + a); + if (a.longValue() != lvalParse[v+ilval]) { + errln("FAIL: Expected " + lvalParse[v+ilval] + + ", got " + a + + ", pattern=" + fmt.toPattern()); + } + } else { + errln(" FAIL: Partial parse (" + pos.getIndex() + + " chars) -> " + a); + } + } + ival += val.length; + ilval += lval.length; + } + } + + // Test the handling of quotes + public void TestQuotes() + { + String pat; + DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US); + DecimalFormat fmt = new DecimalFormat(pat = "a'fo''o'b#", sym); + String s = fmt.format(123); + logln("Pattern \"" + pat + "\""); + logln(" Format 123 -> " + escape(s)); + if (!s.equals("afo'ob123")) errln("FAIL: Expected afo'ob123"); + + fmt = new DecimalFormat(pat = "a''b#", sym); + s = fmt.format(123); + logln("Pattern \"" + pat + "\""); + logln(" Format 123 -> " + escape(s)); + if (!s.equals("a'b123")) errln("FAIL: Expected a'b123"); + } + + // Test the use of the currency sign + public void TestCurrencySign() + { + DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US); + DecimalFormat fmt = new DecimalFormat("\u00A4#,##0.00;-\u00A4#,##0.00", sym); + // Can't test this properly until currency API goes public + // DecimalFormatSymbols sym = fmt.getDecimalFormatSymbols(); + + String s = fmt.format(1234.56); + logln("Pattern \"" + fmt.toPattern() + "\""); + logln(" Format " + 1234.56 + " -> " + escape(s)); + if (!s.equals("$1,234.56")) errln("FAIL: Expected $1,234.56"); + s = fmt.format(-1234.56); + logln(" Format " + -1234.56 + " -> " + escape(s)); + if (!s.equals("-$1,234.56")) errln("FAIL: Expected -$1,234.56"); + + fmt = new DecimalFormat("\u00A4\u00A4 #,##0.00;\u00A4\u00A4 -#,##0.00", sym); + s = fmt.format(1234.56); + logln("Pattern \"" + fmt.toPattern() + "\""); + logln(" Format " + 1234.56 + " -> " + escape(s)); + if (!s.equals("USD 1,234.56")) errln("FAIL: Expected USD 1,234.56"); + s = fmt.format(-1234.56); + logln(" Format " + -1234.56 + " -> " + escape(s)); + if (!s.equals("USD -1,234.56")) errln("FAIL: Expected USD -1,234.56"); + } + static String escape(String s) + { + StringBuffer buf = new StringBuffer(); + char HEX[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; + for (int i=0; i> 12]); + buf.append(HEX[(c & 0x0F00) >> 8]); + buf.append(HEX[(c & 0x00F0) >> 4]); + buf.append(HEX[c & 0x000F]); + } + } + return buf.toString(); + } + + // Test simple currency format + // Bug 4024941; this code used to throw a NumberFormat exception + public void TestCurrency() { + NumberFormat currencyFmt = + NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH); + String s = currencyFmt.format(1.50); + logln("Un pauvre ici a..........." + s); + if (!s.equals("1,50 $")) { + errln("FAIL: Expected 1,50 $; got " + s + "; "+ dumpFmt(currencyFmt)); + } + currencyFmt = NumberFormat.getCurrencyInstance(Locale.GERMANY); + s = currencyFmt.format(1.50); + logln("Un pauvre en Allemagne a.." + s); + if (!s.equals("1,50 \u20AC")) { + errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt)); + } + currencyFmt = NumberFormat.getCurrencyInstance(Locale.FRANCE); + s = currencyFmt.format(1.50); + logln("Un pauvre en France a....." + s); + if (!s.equals("1,50 \u20AC")) { + errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt)); + } + } + + String dumpFmt(NumberFormat numfmt) { + DecimalFormat fmt = (DecimalFormat)numfmt; + StringBuffer buf = new StringBuffer(); + buf.append("pattern \""); + buf.append(fmt.toPattern()); + buf.append("\", currency \""); + buf.append(fmt.getDecimalFormatSymbols().getCurrencySymbol()); + buf.append("\""); + return buf.toString(); + } + + // Test numeric parsing + // Bug 4059870 + public void TestParse() + { + String arg = "0"; + java.text.DecimalFormat format = new java.text.DecimalFormat("00"); + try { + Number n = format.parse(arg); + logln("parse(" + arg + ") = " + n); + if (n.doubleValue() != 0.0) errln("FAIL: Expected 0"); + } catch (Exception e) { errln("Exception caught: " + e); } + } + + // Test rounding + public void TestRounding487() { + NumberFormat nf = NumberFormat.getInstance(Locale.US); + roundingTest(nf, 0.00159999, 4, "0.0016"); + roundingTest(nf, 0.00995, 4, "0.01"); + roundingTest(nf, 12.7995, 3, "12.8"); + roundingTest(nf, 12.4999, 0, "12"); + roundingTest(nf, -19.5, 0, "-20"); + } + + void roundingTest(NumberFormat nf, double x, int maxFractionDigits, String expected) { + nf.setMaximumFractionDigits(maxFractionDigits); + String out = nf.format(x); + logln("" + x + " formats with " + maxFractionDigits + " fractional digits to " + out); + if (!out.equals(expected)) { + errln("FAIL: Expected " + expected + ", got " + out); + } + } + + /** + * Bug 4135202 + * DecimalFormat should recognize not only Latin digits 0-9 (\u0030-\u0039) + * but also various other ranges of Unicode digits, such as Arabic + * digits \u0660-\u0669 and Devanagari digits \u0966-\u096F, to name + * a couple. + * @see java.lang.Character#isDigit(char) + */ + public void TestUnicodeDigits() { + char[] zeros = { + 0x0030, // ISO-LATIN-1 digits ('0' through '9') + 0x0660, // Arabic-Indic digits + 0x06F0, // Extended Arabic-Indic digits + 0x0966, // Devanagari digits + 0x09E6, // Bengali digits + 0x0A66, // Gurmukhi digits + 0x0AE6, // Gujarati digits + 0x0B66, // Oriya digits + 0x0BE6, // Tamil digits + 0x0C66, // Telugu digits + 0x0CE6, // Kannada digits + 0x0D66, // Malayalam digits + 0x0E50, // Thai digits + 0x0ED0, // Lao digits + 0x0F20, // Tibetan digits + 0xFF10, // Fullwidth digits + }; + NumberFormat format = NumberFormat.getInstance(); + for (int i=0; i= 0) { + if (customNeg.indexOf(INTL_SYM) >= 0) + errln("Fail: Positive and negative patterns use different symbols"); + else + logln("Ok: " + locales[i] + + " uses currency symbol: " + genericPos + + ", " + customPos); + } + else if (customPos.indexOf(INTL_SYM) >= 0) { + if (customNeg.indexOf(SYM) >= 0) + errln("Fail: Positive and negative patterns use different symbols"); + else + logln("Ok: " + locales[i] + + " uses intl. currency symbol: " + genericPos + + ", " + customPos); + } + else { + errln("FAIL: " + locales[i] + + " contains no currency symbol (impossible!)"); + } + } + } + else logln("Skipping " + locales[i] + "; not a DecimalFormat"); + } + } + + public void TestIntegerFormat() throws ParseException { + NumberFormat format = NumberFormat.getIntegerInstance(Locale.GERMANY); + + float[] formatInput = { 12345.67f, -12345.67f, -0, 0 }; + String[] formatExpected = { "12.346", "-12.346", "0", "0" }; + + for (int i = 0; i < formatInput.length; i++) { + String result = format.format(formatInput[i]); + if (!result.equals(formatExpected[i])) { + errln("FAIL: Expected " + formatExpected[i] + ", got " + result); + } + } + + String[] parseInput = { "0", "-0", "12.345,67", "-12.345,67" }; + float[] parseExpected = { 0, 0, 12345, -12345 }; + + for (int i = 0; i < parseInput.length; i++) { + float result = ((Number) format.parse(parseInput[i])).floatValue(); + if (result != parseExpected[i]) { + errln("FAIL: Expected " + parseExpected[i] + ", got " + result); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/PositionTest.java b/jdk/test/java/text/Format/NumberFormat/PositionTest.java new file mode 100644 index 00000000000..31a5a3dbebd --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/PositionTest.java @@ -0,0 +1,221 @@ +/* + * 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 + * 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 4109023 4153060 4153061 + * @library /java/text/testlib + * @summary test ParsePosition and FieldPosition + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - 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. +*/ + +import java.text.*; +import java.io.*; + +public class PositionTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new PositionTest().run(args); + } + + public void TestParsePosition() { + ParsePosition pp1 = new ParsePosition(0); + if (pp1.getIndex() == 0) { + logln("PP constructor() tested."); + }else{ + errln("*** PP getIndex or constructor() result"); + } + + { + int to = 5; + ParsePosition pp2 = new ParsePosition ( to ); + if (pp2.getIndex() == 5) { + logln("PP getIndex and constructor(TextOffset) tested."); + }else{ + errln("*** PP getIndex or constructor(TextOffset) result"); + } + pp2.setIndex( 3 ); + if (pp2.getIndex() == 3) { + logln("PP setIndex tested."); + }else{ + errln("*** PP getIndex or setIndex result"); + } + } + + ParsePosition pp2, pp3; + pp2 = new ParsePosition( 3 ); + pp3 = new ParsePosition( 5 ); + ParsePosition pp4 = new ParsePosition(5); + if (! pp2.equals(pp3)) { + logln("PP not equals tested."); + }else{ + errln("*** PP not equals fails"); + } + if (pp3.equals(pp4)) { + logln("PP equals tested."); + }else{ + errln("*** PP equals fails (" + pp3.getIndex() + " != " + pp4.getIndex() + ")"); + } + + ParsePosition pp5; + pp5 = pp4; + if (pp4.equals(pp5)) { + logln("PP operator= tested."); + }else{ + errln("*** PP operator= operator== or operator != result"); + } + + } + + public void TestFieldPosition() { + FieldPosition fp = new FieldPosition( 7 ); + + if (fp.getField() == 7) { + logln("FP constructor(int) and getField tested."); + }else{ + errln("*** FP constructor(int) or getField"); + } + + FieldPosition fph = new FieldPosition( 3 ); + if ( fph.getField() != 3) errln("*** FP getField or heap constr."); + + boolean err1 = false; + boolean err2 = false; + boolean err3 = false; +// for (long i = -50; i < 50; i++ ) { +// fp.setField( i+8 ); +// fp.setBeginIndex( i+6 ); +// fp.setEndIndex( i+7 ); +// if (fp.getField() != i+8) err1 = true; +// if (fp.getBeginIndex() != i+6) err2 = true; +// if (fp.getEndIndex() != i+7) err3 = true; +// } + if (!err1) { + logln("FP setField and getField tested."); + }else{ + errln("*** FP setField or getField"); + } + if (!err2) { + logln("FP setBeginIndex and getBeginIndex tested."); + }else{ + errln("*** FP setBeginIndex or getBeginIndex"); + } + if (!err3) { + logln("FP setEndIndex and getEndIndex tested."); + }else{ + errln("*** FP setEndIndex or getEndIndex"); + } + + logln(""); + } + + public void TestFieldPosition_example() { + //***** no error detection yet !!!!!!! + //***** this test is for compiler checks and visual verification only. + double doubleNum[] = { 123456789.0, -12345678.9, 1234567.89, -123456.789, + 12345.6789, -1234.56789, 123.456789, -12.3456789, 1.23456789}; + int dNumSize = doubleNum.length; + + DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(); + fmt.setDecimalSeparatorAlwaysShown(true); + + final int tempLen = 20; + StringBuffer temp; + + for (int i=0; iformat(doubleNum[i], buf, pos), fmtText); + StringBuffer res = fmt.format(doubleNum[i], buf, pos); + int tempOffset = (tempLen <= (tempLen - pos.getEndIndex())) ? + tempLen : (tempLen - pos.getEndIndex()); + for (int j=0; j succeeded."); + } +} diff --git a/jdk/test/java/text/Format/common/Bug6215962.java b/jdk/test/java/text/Format/common/Bug6215962.java new file mode 100644 index 00000000000..85dd5e2cebd --- /dev/null +++ b/jdk/test/java/text/Format/common/Bug6215962.java @@ -0,0 +1,161 @@ +/* + * 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 + * 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 6215962 + * @summary Confirm that replacing Utility.arayEquals methods have with + * Arrays.equals introduces no problem. + */ +import java.text.*; +import java.util.*; + +public class Bug6215962 { + + public static void main(String[] args) { + testMessageFormat(); + testChoiceFormat(); + testDateFormatSymbols(); + } + + /** + * Test cases for MessageFormat + */ + static void testMessageFormat() { + MessageFormat mf1 = new MessageFormat("{0}", null); + MessageFormat mf2 = new MessageFormat("{0}", null); + check(mf1, mf2, true); + + mf1.setLocale(null); + check(mf1, mf2, true); + + mf1 = new MessageFormat("{0}", Locale.US); + check(mf1, mf2, false); + + mf2 = new MessageFormat("{0}", Locale.JAPAN); + check(mf1, mf2, false); + + mf1 = new MessageFormat("{0}", new Locale("ja", "JP")); + check(mf1, mf2, true); + + mf1.setLocale(null); + check(mf1, mf2, false); + + mf1 = new MessageFormat("{0}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, false); + + mf2 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, false); + + mf1 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, true); + + mf1 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, false); + + mf2 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, true); + } + + static void check(MessageFormat f1, MessageFormat f2, boolean expected) { + boolean got = f1.equals(f2); + if (got != expected) { + throw new RuntimeException("Test failed for MessageFormat.equals(). Got: " + got + ", Expected: " + expected); + } + } + + /** + * Test cases for MessageFormat + */ + static void testChoiceFormat() { + double[] limits0 = {0,1,2,3,4,5,6}; + double[] limits1 = {1,2,3,4,5,6,7}; + String[] monthNames0 = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + String[] monthNames1 = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}; + + ChoiceFormat cf1 = new ChoiceFormat(limits1, monthNames0); + ChoiceFormat cf2 = new ChoiceFormat(limits1, monthNames0); + check(cf1, cf2, true); + + cf2 = new ChoiceFormat(limits0, monthNames0); + check(cf1, cf2, false); + + cf2 = new ChoiceFormat(limits1, monthNames1); + check(cf1, cf2, false); + } + + static void check(ChoiceFormat f1, ChoiceFormat f2, boolean expected) { + boolean got = f1.equals(f2); + if (got != expected) { + throw new RuntimeException("Test failed for ChoiceFormat.equals(). Got: " + got + ", Expected: " + expected); + } + } + + /** + * Test cases for DateFormatSymbols + */ + static void testDateFormatSymbols() { + DateFormatSymbols dfs1 = new DateFormatSymbols(); + DateFormatSymbols dfs2 = new DateFormatSymbols(); + check(dfs1, dfs2, true); + + // Becase eras, months, shortmonths, weekdays, shortweekdays, ampms are + // the same data type (String[]) and are treated in the same way, here + // I test only Months. + String[] tmp = dfs1.getMonths(); + String saved = tmp[0]; + tmp[0] = "Foo"; + dfs1.setMonths(tmp); + check(dfs1, dfs2, false); + + tmp[0] = saved; + dfs1.setMonths(tmp); + check(dfs1, dfs2, true); + + // Test LocalizedpatternChars (String) + String pattern = dfs2.getLocalPatternChars(); + dfs2.setLocalPatternChars("Bar"); + check(dfs1, dfs2, false); + + dfs2.setLocalPatternChars(pattern); + check(dfs1, dfs2, true); + + // Test TimeZone strings (String[][]) + String[][] zones = dfs1.getZoneStrings(); + saved = zones[0][1]; + zones[0][1] = "Yokohama Summer Time"; + dfs1.setZoneStrings(zones); + check(dfs1, dfs2, false); + + zones[0][1] = saved; + dfs1.setZoneStrings(zones); + check(dfs1, dfs2, true); + } + + static void check(DateFormatSymbols dfs1, DateFormatSymbols dfs2, boolean expected) { + boolean got = dfs1.equals(dfs2); + if (got != expected) { + throw new RuntimeException("Test failed for DateFormatSymbols.equals(). Got: " + got + ", Expected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/common/ChoiceFormat.ser.txt b/jdk/test/java/text/Format/common/ChoiceFormat.ser.txt new file mode 100644 index 00000000000..4947d1936e7 --- /dev/null +++ b/jdk/test/java/text/Format/common/ChoiceFormat.ser.txt @@ -0,0 +1,37 @@ +# +# 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 +# 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. +# + +# Hex dump of a serialized ChoiceFormat for Bug4769840. + +aced0005737200166a6176612e746578742e43686f696365466f726d617418e9 +c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61 +76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400 +025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3 +bf137d07e80200065a000c67726f7570696e67557365644200116d6178467261 +6374696f6e4469676974734200106d6178496e74656765724469676974734200 +116d696e4672616374696f6e4469676974734200106d696e496e746567657244 +69676974735a00107061727365496e74656765724f6e6c79787200106a617661 +2e746578742e466f726d6174fbd8bc12e90f1843020000787001032800010075 +7200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200 +0078700000000274000420666f6f74000420626172757200025b443ea68c14ab +635a1e02000078700000000200000000000000003ff0000000000000 diff --git a/jdk/test/java/text/Format/common/DateFormat.Field.ser.txt b/jdk/test/java/text/Format/common/DateFormat.Field.ser.txt new file mode 100644 index 00000000000..e78f24409e7 --- /dev/null +++ b/jdk/test/java/text/Format/common/DateFormat.Field.ser.txt @@ -0,0 +1,32 @@ +# +# 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 +# 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. +# + +# Hex dump of a serialized DateFormat.Field for Bug4769840. + +aced00057372001a6a6176612e746578742e44617465466f726d617424466965 +6c646744fc81f123e71002000149000d63616c656e6461724669656c64787200 +166a6176612e746578742e466f726d6174244669656c6403d7fbbd383b0f9b02 +00007872002f6a6176612e746578742e41747472696275746564436861726163 +7465724974657261746f7224417474726962757465811e7426cd47175c020001 +4c00046e616d657400124c6a6176612f6c616e672f537472696e673b78707400 +0974696d65207a6f6e65ffffffff diff --git a/jdk/test/java/text/Format/common/FormatIteratorTest.java b/jdk/test/java/text/Format/common/FormatIteratorTest.java new file mode 100644 index 00000000000..7102f59dec2 --- /dev/null +++ b/jdk/test/java/text/Format/common/FormatIteratorTest.java @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2000, 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 4018937 + * @library /java/text/testlib + * @build FormatIteratorTest PParser IntlTest + * @run main FormatIteratorTest + * @summary Tests the formatToCharacterIterator method of SimpleDateFormat, + * MessageFormat and DecimalFormat. + */ + +import java.io.*; +import java.lang.reflect.*; +import java.text.*; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +/** + * FormatTester creates Formats, and tests the resulting FieldPositions + * and AttributedCharacterIterator based on a file. The file is a hierarchical + * set of key/value pairs, where each value can also be an array or map. The + * top map must contain a tests entry, which will be an array consisting + * of pairs of maps. The first map specifies the Format that + * should be created, and consists of: + *

    + *   class = className
    + *   args = (arg1 arg2 ...)
    + *   valueClass = className
    + *   valueArgs = (arg1 arg2 ...)
    + * 
    + * The second map dictates what to test, and should consist of the following: + *
    + *   length = lengthOfFormattedString
    + *   text = Result of Formatting
    + *   0...lengthOfFormattedString = (arg1 arg2 ...)
    + *   limits = ( range1 range2 ...)
    + *   fieldPositions = ( fp1 fp2 ...)
    + * 
    + * lengthOfFormattedString indicate the total length of formatted + * string. text indicates the resulting string. + * 0...x where x == lengthOfFormattedString - 1 is + * an array of the attributes that should exist at the particular + * location. limits is an array of maps, where each map + * can be used to test the bounds of a set of attributes. Each map will + * consist of: + *
    + *   attributes = array of attributes
    + *   begin = start location
    + *   begin2 = second start location
    + *   end = limit location
    + *   end2 = second limit location
    + * 
    + * These are tested by iterating from begin to end in the CharacterIterator + * and doing the following at each index: + *
    + *   getRunStart() == begin
    + *   getRunStart(attributes) == begin2
    + *   getRunLimit() == end
    + *   getRunLimit(attributes) == end2
    + * 
    + * fieldPositions is used to test the results of invoking + * format with a FieldPosition. + * fieldPositions is an array of maps, where each map contains + * the following: + *
    + *   field = Integer field reference (optional)
    + *   fieldID = Object reference
    + *   begin = begin index of FieldPosition after formatting
    + *   end = end index of FieldPosition after formatting
    + * 
    + * Any lines starting with {@code '#'} are comment lines and ignored. + */ +public class FormatIteratorTest extends IntlTest { + private static HashMap attrs; + private Format format; + private Object value; + private String text; + + public static final Object ARG0_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG1_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG2_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG3_FIELD_ID = MessageFormat. + Field.ARGUMENT; + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + // The current tests are only appropriate for US. If tests are + // added for other locales are added, then a property should be + // added to each file (test) to be able to specify the locale. + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + new FormatIteratorTest().run(args); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + public FormatIteratorTest() { + } + + public void testDecimalFormat() { + _test(new File(System.getProperty("test.src", "."), + "decimalFormat.props")); + } + + public void testMessageFormat() { + _test(new File(System.getProperty("test.src", "."), + "messageFormat.props")); + } + + public void testDateFormat() { + _test(new File(System.getProperty("test.src", "."), + "dateFormat.props")); + } + + private void _test(File file) { + try { + attrs = new HashMap(); + logln("testing: " + file); + PParser parser = new PParser(); + Hashtable contents = parser.parse(new BufferedReader( + new FileReader(file))); + Vector test = (Vector)contents.get("tests"); + + for (int counter = 0; counter < test.size(); counter++) { + logln("creating: " + (counter / 2)); + + AttributedCharacterIterator iterator = + create((Hashtable)test.get(counter)); + + logln("verifying: " + (counter / 2)); + verify(iterator, (Hashtable)test.get(++counter)); + } + } catch (IOException ioe) { + errln("Error reading: " + ioe); + } + } + + public void verify(AttributedCharacterIterator iterator,Hashtable table) { + int length = Integer.parseInt((String)table.get("length")); + + // Verify the text + if (!getText(iterator).equals( + escapeIfNecessary((String)table.get("text")))) { + String text = getText(iterator); + + errln("text doesn't match, got: " + getText(iterator)); + } + if (iterator.getBeginIndex() != 0) { + errln("Bogus start: " + iterator.getBeginIndex()); + } + if (iterator.getEndIndex() != length) { + errln("Bogus end: " + iterator.getEndIndex()); + } + for (int counter = 0; counter < length; counter++) { + iterator.setIndex(counter); + if (!verifyAttributes(iterator.getAttributes().keySet(), + makeAttributes((Vector)table.get(Integer. + toString(counter))))) { + errln("Attributes don't match at " + counter + " expecting " + + makeAttributes((Vector)table.get(Integer.toString + (counter))) + " got " + + iterator.getAttributes().keySet()); + } + } + for (int counter = length - 1; counter >= 0; counter--) { + iterator.setIndex(counter); + if (!verifyAttributes(iterator.getAttributes().keySet(), + makeAttributes((Vector)table.get(Integer. + toString(counter))))) { + errln("Attributes don't match at " + counter + " expecting " + + makeAttributes((Vector)table.get(Integer.toString + (counter))) + " got " + + iterator.getAttributes().keySet()); + } + } + verifyLimits(iterator, table); + + text = escapeIfNecessary((String)table.get("text")); + Vector fps = (Vector)table.get("fieldPositions"); + + if (fps != null) { + for (int counter = 0; counter < fps.size(); counter++) { + verifyFieldPosition(counter, (Hashtable)fps.get(counter)); + } + } + } + + private void verifyLimits(AttributedCharacterIterator iterator, + Hashtable table) { + Vector limits = (Vector)table.get("limits"); + + if (limits != null) { + for (int counter = 0; counter < limits.size(); counter++) { + verifyLimit(iterator, (Hashtable)limits.get(counter)); + } + } + } + + private void verifyLimit(AttributedCharacterIterator iterator, + Hashtable table) { + int begin = Integer.parseInt((String)table.get("begin")); + int end = Integer.parseInt((String)table.get("end")); + Set attrs = makeAttributes((Vector)table.get("attributes")); + String begin2S = (String)table.get("begin2"); + int begin2 = (begin2S != null) ? Integer.parseInt(begin2S) : begin; + String end2S = (String)table.get("end2"); + int end2 = (end2S != null) ? Integer.parseInt(end2S) : end; + + for (int counter = begin; counter < end; counter++) { + iterator.setIndex(counter); + if (iterator.getRunStart() != begin) { + errln("Begin doesn't match want " + begin + " got " + + iterator.getRunStart() + " at " + counter + " attrs " + + attrs); + } + if (iterator.getRunStart(attrs) != begin2) { + errln("Begin2 doesn't match want " + begin2 + " got " + + iterator.getRunStart(attrs) + " at " + counter + + " attrs " + attrs); + } + if (iterator.getRunLimit() != end) { + errln("End doesn't match want " + end + " got " + + iterator.getRunLimit() + " at " + counter + " attrs " + + attrs); + } + if (iterator.getRunLimit(attrs) != end2) { + errln("End2 doesn't match want " + end2 + " got " + + iterator.getRunLimit(attrs) + " at " + counter + + " attrs " + attrs); + } + } + } + + private boolean verifyAttributes(Set a, Set b) { + boolean aEmpty = (a.size() == 0); + boolean bEmpty = (b.size() == 0); + + if (aEmpty && bEmpty) { + return true; + } + else if (aEmpty || bEmpty) { + return false; + } + return a.equals(b); + } + + private String getText(AttributedCharacterIterator iterator) { + StringBuffer buffer = new StringBuffer(); + + for (int counter = 0; counter < iterator.getEndIndex(); counter++) { + buffer.append(iterator.setIndex(counter)); + } + return buffer.toString(); + } + + private void verifyFieldPosition(int index, Hashtable table) { + Object o = table.get("field"); + int begin = Integer.parseInt((String)table.get("begin")); + int end = Integer.parseInt((String)table.get("end")); + + if (o != null) { + FieldPosition fp = new FieldPosition(((Integer) + lookupField((String)o)).intValue()); + + verifyFieldPosition(fp, begin, end, index); + } + o = table.get("fieldID"); + if (o != null) { + FieldPosition fp = new FieldPosition((Format.Field) + lookupField((String)o)); + verifyFieldPosition(fp, begin, end, index); + } + } + + private void verifyFieldPosition(FieldPosition fp, int begin, int end, + int index) { + StringBuffer buffer = new StringBuffer(); + + format.format(value, buffer, fp); + if (fp.getBeginIndex() != begin) { + errln("bogus begin want " + begin + " got " + fp.getBeginIndex() + + " for " + fp + " at " + index); + } + if (fp.getEndIndex() != end) { + errln("bogus end want " + end + " got " + fp.getEndIndex() + + " for " + fp + " at " + index); + } + if (!buffer.toString().equals(text)) { + errln("Text does not match, want !" + buffer.toString() + + "! got !" + text + "!"); + } + } + + public AttributedCharacterIterator create(Hashtable table) { + format = (Format)createInstance((String)table.get("class"), + ((Vector)table.get("args")).toArray()); + value = createInstance((String)table.get("valueClass"), + ((Vector)table.get("valueArgs")).toArray()); + + logln("Created format: " + format + " value " + value); + AttributedCharacterIterator aci = format. + formatToCharacterIterator(value); + + logln("Obtained Iterator: " + aci); + return aci; + } + + public Format.Field makeAttribute(String name) { + return (Format.Field)lookupField(name); + } + + private Object createInstance(String className, Object[] args) { + if (className.equals("java.lang.reflect.Array")) { + for (int counter = 0; counter < args.length; counter++) { + if (args[counter] instanceof Vector) { + Vector v = (Vector)args[counter]; + + args[counter] = createInstance((String)v.get(0), + ((Vector)v.get(1)).toArray()); + } + } + return args; + } + for (int counter = 0; counter < args.length; counter++) { + args[counter] = escapeIfNecessary((String)args[counter]); + } + try { + if (className.equals("java.util.concurrent.atomic.AtomicInteger")) { + return new AtomicInteger(Integer.valueOf((String)args[0])); + } else if (className.equals("java.util.concurrent.atomic.AtomicLong")) { + return new AtomicLong(Long.valueOf((String)args[0])); + } else { + Class klass = lookupClass(className); + Constructor cons = klass.getConstructor( + new Class[] { String.class }); + Object value = cons.newInstance(args); + + return value; + } + } catch (Throwable th) { + errln("Error creating instance " + th); + return null; + } + } + + private Class lookupClass(String name) throws ClassNotFoundException { + try { + Class klass = Class.forName(name); + + return klass; + } catch (ClassNotFoundException e1) {} + + try { + Class klass = Class.forName("java.lang." + name); + + return klass; + } catch (ClassNotFoundException e1) {} + + Class klass = Class.forName("java.text." + name); + + return klass; + } + + private Object lookupField(String name) { + Throwable error = null; + + try { + int dotIndex = name.indexOf('.'); + Class klass = lookupClass(name.substring(0, dotIndex)); + String fieldName = name.substring(dotIndex + 1); + Field[] fields = klass.getFields(); + + for (int counter = fields.length - 1; counter >= 0; counter--) { + if (fields[counter].getName().equals(fieldName)) { + return fields[counter].get(null); + } + } + } catch (Throwable th) { + error = th; + } + errln("Could not lookup field " + name + " " + error); + return null; + } + + protected String escapeIfNecessary(String string) { + if (string != null) { + int index; + + if ((index = string.indexOf("\\u")) != -1) { + StringBuffer sb = new StringBuffer(string.substring(0, index)); + + sb.append((char)Integer.parseInt( + string.substring(index + 2, index + 6), 16)); + sb.append(string.substring(index + 6)); + string = sb.toString(); + } + } + return string; + } + + public Set makeAttributes(Vector names) { + HashSet set = new HashSet(Math.max(1, names.size())); + + for (int counter = 0; counter < names.size(); counter++) { + set.add(makeAttribute((String)names.get(counter))); + } + return set; + } +} diff --git a/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt b/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt new file mode 100644 index 00000000000..5428b76680c --- /dev/null +++ b/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt @@ -0,0 +1,32 @@ +# +# 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 +# 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. +# + +# Hex dump of a serialized MessageFormat.Field for Bug4769840. + +aced00057372001d6a6176612e746578742e4d657373616765466f726d617424 +4669656c646da23d2c7b46bfaa020000787200166a6176612e746578742e466f +726d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e7465 +78742e417474726962757465644368617261637465724974657261746f722441 +7474726962757465811e7426cd47175c0200014c00046e616d657400124c6a61 +76612f6c616e672f537472696e673b78707400166d6573736167652061726775 +6d656e74206669656c64 diff --git a/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt b/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt new file mode 100644 index 00000000000..12851638adf --- /dev/null +++ b/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt @@ -0,0 +1,31 @@ +# +# 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 +# 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. +# + +# Hex dump of a serialized NumberFormat.Field for Bug4769840. + +aced00057372001c6a6176612e746578742e4e756d626572466f726d61742446 +69656c646802a038193ff37a020000787200166a6176612e746578742e466f72 +6d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e746578 +742e417474726962757465644368617261637465724974657261746f72244174 +74726962757465811e7426cd47175c0200014c00046e616d657400124c6a6176 +612f6c616e672f537472696e673b7870740007696e7465676572 diff --git a/jdk/test/java/text/Format/common/PParser.java b/jdk/test/java/text/Format/common/PParser.java new file mode 100644 index 00000000000..6ada76b1059 --- /dev/null +++ b/jdk/test/java/text/Format/common/PParser.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2000, 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.*; +import java.util.*; + +/* + * assignment : key = value; + * key : string + * value : string | array | dict + * nValue : , value + * array : ( value nValue ) + * nAssignment: , assignment|value + * dict : { assignment* } + * string : "*" or anything but a ,(){}= + * + * special characters: ,(){}= + */ + +public class PParser { + protected static final int OPEN_PAIR = 1; + protected static final int CLOSE_PAIR = 2; + protected static final int OPEN_ARRAY = 3; + protected static final int CLOSE_ARRAY = 4; + protected static final int MORE = 5; + protected static final int EQUAL = 6; + protected static final int STRING = 7; + protected static final int WS = 8; + + protected Reader reader; + protected boolean bufferedToken; + protected StringBuffer stringBuffer = new StringBuffer(); + protected int lastChar; + protected int lastToken; + protected int lineNumber; + protected int column; + + public PParser() { + } + + public Hashtable parse(Reader r) throws IOException { + this.reader = r; + bufferedToken = false; + lineNumber = 0; + column = 0; + if (getToken() != OPEN_PAIR) { + error("No initial open"); + } + return parsePair(); + } + + protected Object parseValue(int lookAhead) throws IOException { + int token; + + if (lookAhead == -1) { + token = getToken(); + } else { + token = lookAhead; + } + switch (token) { + case STRING: + return stringBuffer.toString(); + case OPEN_ARRAY: + return parseArray(); + case OPEN_PAIR: + return parsePair(); + default: + error("Expecting value"); + } + return null; + } + + protected Object parseArray() throws IOException { + Vector array = new Vector(); + int token; + + while ((token = getToken()) != CLOSE_ARRAY) { + if (token == MORE) { + token = getToken(); + } + if (token != CLOSE_ARRAY) { + array.addElement(parseValue(token)); + } + } + return array; + } + + protected Hashtable parsePair() throws IOException { + Hashtable ht = new Hashtable(11); + int token; + + while ((token = getToken()) != CLOSE_PAIR) { + if (token != STRING) { + error("Pair expecting string got"); + } + String key = stringBuffer.toString(); + + if (getToken() != EQUAL) { + error("Expecting = "); + } + + Object value = parseValue(-1); + ht.put(key, value); + } + return ht; + } + + protected void ungetToken() { + if (bufferedToken) { + error("Can not buffer more than one token"); + } + bufferedToken = true; + } + + protected int getToken() throws IOException { + int token = getToken(false, false); + + return token; + } + + protected int getToken(boolean wantsWS, boolean inString) + throws IOException { + if (bufferedToken) { + bufferedToken = false; + if (lastToken != WS || wantsWS) { + return lastToken; + } + } + while ((lastChar = reader.read()) != -1) { + // If a line starts with '#', skip the line. + if (column == 0 && lastChar == '#') { + while ((lastChar = reader.read()) != -1 + && lastChar != '\n') { + } + if (lastChar == -1) { + break; + } + } + + column++; + switch(lastChar) { + case '\n': + lineNumber++; + column = 0; + case ' ': + case '\r': + case '\t': + if (wantsWS) { + lastToken = WS; + return WS; + } + break; + case ',': + lastToken = MORE; + return MORE; + case '(': + lastToken = OPEN_ARRAY; + return OPEN_ARRAY; + case ')': + lastToken = CLOSE_ARRAY; + return CLOSE_ARRAY; + case '{': + lastToken = OPEN_PAIR; + return OPEN_PAIR; + case '}': + lastToken = CLOSE_PAIR; + return CLOSE_PAIR; + case '=': + lastToken = EQUAL; + return EQUAL; + case '"': + lastToken = STRING; + if (!inString) { + stringBuffer.setLength(0); + while (true) { + getToken(true, true); + if (lastChar == '"') { + lastToken = STRING; + return STRING; + } + stringBuffer.append((char)lastChar); + } + } + return STRING; + default: + lastToken = STRING; + if (!inString) { + stringBuffer.setLength(0); + stringBuffer.append((char)lastChar); + while (getToken(true, true) == STRING) { + if (lastChar == '"') { + error("Unexpected quote"); + } + stringBuffer.append((char)lastChar); + } + ungetToken(); + } + return STRING; + } + } + return -1; + } + + protected void error(String errorString) { + throw new RuntimeException(errorString + " at line " + lineNumber + " column " + column); + } + + public static void dump(Object o) { + if (o instanceof String) { + System.out.print(o); + } else if(o instanceof Vector) { + Enumeration e = ((Vector)o).elements(); + + dump(" ("); + while (e.hasMoreElements()) { + dump(e.nextElement()); + dump(" -- "); + } + dump(" )"); + } else { + Hashtable ht = (Hashtable)o; + Enumeration e = ht.keys(); + + dump(" {"); + while (e.hasMoreElements()) { + Object key = e.nextElement(); + + dump(key); + dump(" = "); + dump(ht.get(key)); + dump(";"); + } + dump(" }"); + } + } + + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("need filename"); + } else { + try { + FileReader fr = new FileReader(args[0]); + PParser parser = new PParser(); + Hashtable ht = parser.parse(fr); + + dump(ht); + System.out.println(); + } + catch (IOException ioe) { + System.out.println("Couldn't parse: " + ioe); + } + } + } +} diff --git a/jdk/test/java/text/Format/common/dateFormat.props b/jdk/test/java/text/Format/common/dateFormat.props new file mode 100644 index 00000000000..22bb9a44d78 --- /dev/null +++ b/jdk/test/java/text/Format/common/dateFormat.props @@ -0,0 +1,333 @@ +# +# Copyright (c) 2000, 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 data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.SimpleDateFormat + args = ("M/dd/yy") + valueClass = java.util.Date + valueArgs = ("7/10/71") + } + { + length = 7 + text = "7/10/71" + 0 = (DateFormat$Field.MONTH) + 1 = () + 2 = (DateFormat$Field.DAY_OF_MONTH) + 3 = (DateFormat$Field.DAY_OF_MONTH) + 4 = () + 5 = (DateFormat$Field.YEAR) + 6 = (DateFormat$Field.YEAR) + limits = ( { attributes = (DateFormat$Field.MONTH) + begin = 0 end = 1} + { attributes = () + begin = 1 begin2 = 0 end = 2 end2 = 7} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 5 end2 = 7} + { attributes = (DateFormat$Field.YEAR) + begin = 5 end = 7} + ) + fieldPositions = + ( + { + field = DateFormat.MONTH_FIELD + fieldID = DateFormat$Field.MONTH + begin = 0 end = 1 + } + { + field = DateFormat.DATE_FIELD + fieldID = DateFormat$Field.DAY_OF_MONTH + begin = 2 end = 4 + } + { + field = DateFormat.YEAR_FIELD + fieldID = DateFormat$Field.YEAR + begin = 5 end = 7 + } + ) + } + + { + class = java.text.SimpleDateFormat + args = ("EEEEEEE MMMMMMMMMMMMM yyyy GG") + valueClass = java.util.Date + valueArgs = ("12/10/2020") + } + { + length = 25 + text = "Thursday December 2020 AD" + 0 = (DateFormat$Field.DAY_OF_WEEK) + 1 = (DateFormat$Field.DAY_OF_WEEK) + 2 = (DateFormat$Field.DAY_OF_WEEK) + 3 = (DateFormat$Field.DAY_OF_WEEK) + 4 = (DateFormat$Field.DAY_OF_WEEK) + 5 = (DateFormat$Field.DAY_OF_WEEK) + 6 = (DateFormat$Field.DAY_OF_WEEK) + 7 = (DateFormat$Field.DAY_OF_WEEK) + 8 = () + 9 = (DateFormat$Field.MONTH) + 10 = (DateFormat$Field.MONTH) + 11 = (DateFormat$Field.MONTH) + 12 = (DateFormat$Field.MONTH) + 13 = (DateFormat$Field.MONTH) + 14 = (DateFormat$Field.MONTH) + 15 = (DateFormat$Field.MONTH) + 16 = (DateFormat$Field.MONTH) + 17 = () + 18 = (DateFormat$Field.YEAR) + 19 = (DateFormat$Field.YEAR) + 20 = (DateFormat$Field.YEAR) + 21 = (DateFormat$Field.YEAR) + 22 = () + 23 = (DateFormat$Field.ERA) + 24 = (DateFormat$Field.ERA) + limits = ( { attributes = (DateFormat$Field.DAY_OF_WEEK) + begin = 0 end = 8} + { attributes = () + begin = 8 begin2 = 0 end = 9 end2 = 25} + { attributes = (DateFormat$Field.MONTH) + begin = 9 end = 17} + { attributes = () + begin = 17 begin2 = 0 end = 18 end2 = 25} + { attributes = (DateFormat$Field.YEAR) + begin = 18 end = 22} + { attributes = () + begin = 22 begin2 = 0 end = 23 end2 = 25} + { attributes = (DateFormat$Field.ERA) + begin = 23 end = 25} + ) + fieldPositions = + ( + { + field = DateFormat.DAY_OF_WEEK_FIELD + fieldID = DateFormat$Field.DAY_OF_WEEK + begin = 0 end = 8 + } + { + field = DateFormat.MONTH_FIELD + fieldID = DateFormat$Field.MONTH + begin = 9 end = 17 + } + { + field = DateFormat.YEAR_FIELD + fieldID = DateFormat$Field.YEAR + begin = 18 end = 22 + } + { + field = DateFormat.ERA_FIELD + fieldID = DateFormat$Field.ERA + begin = 23 end = 25 + } + ) + } + + { + class = java.text.SimpleDateFormat + args = ("h HH:mm:ss:SSS aa") + valueClass = java.util.Date + valueArgs = ("1/1/2000 2:52:12 PM") + } + { + length = 17 + text = "2 14:52:12:000 PM" + 0 = (DateFormat$Field.HOUR1) + 1 = () + 2 = (DateFormat$Field.HOUR_OF_DAY0) + 3 = (DateFormat$Field.HOUR_OF_DAY0) + 4 = () + 5 = (DateFormat$Field.MINUTE) + 6 = (DateFormat$Field.MINUTE) + 7 = () + 8 = (DateFormat$Field.SECOND) + 9 = (DateFormat$Field.SECOND) + 10 = () + 11 = (DateFormat$Field.MILLISECOND) + 12 = (DateFormat$Field.MILLISECOND) + 13 = (DateFormat$Field.MILLISECOND) + 14 = () + 15 = (DateFormat$Field.AM_PM) + 16 = (DateFormat$Field.AM_PM) + limits = ( { attributes = (DateFormat$Field.HOUR1) + begin = 0 end = 1} + { attributes = () + begin = 1 begin2 = 0 end = 2 end2 = 17} + { attributes = (DateFormat$Field.HOUR_OF_DAY0) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 5 end2 = 17} + { attributes = (DateFormat$Field.MINUTE) + begin = 5 end = 7} + { attributes = () + begin = 7 begin2 = 0 end = 8 end2 = 17} + { attributes = (DateFormat$Field.SECOND) + begin = 8 end = 10} + { attributes = () + begin = 10 begin2 = 0 end = 11 end2 = 17} + { attributes = (DateFormat$Field.MILLISECOND) + begin = 11 end = 14} + { attributes = () + begin = 14 begin2 = 0 end = 15 end2 = 17} + { attributes = (DateFormat$Field.AM_PM) + begin = 15 end = 17} + ) + fieldPositions = + ( + { + field = DateFormat.HOUR1_FIELD + fieldID = DateFormat$Field.HOUR1 + begin = 0 end = 1 + } + { + field = DateFormat.HOUR_OF_DAY0_FIELD + fieldID = DateFormat$Field.HOUR_OF_DAY0 + begin = 2 end = 4 + } + { + field = DateFormat.MINUTE_FIELD + fieldID = DateFormat$Field.MINUTE + begin = 5 end = 7 + } + { + field = DateFormat.SECOND_FIELD + fieldID = DateFormat$Field.SECOND + begin = 8 end = 10 + } + { + field = DateFormat.MILLISECOND_FIELD + fieldID = DateFormat$Field.MILLISECOND + begin = 11 end = 14 + } + { + field = DateFormat.AM_PM_FIELD + fieldID = DateFormat$Field.AM_PM + begin = 15 end = 17 + } + ) + } + + + { + class = java.text.SimpleDateFormat + args = ("kk KK DDD FF ww WW zz") + valueClass = java.util.Date + valueArgs = ("4/26/2031 2:02:52 AM") + } + { + length = 22 + text = "02 02 116 04 17 04 PDT" + 0 = (DateFormat$Field.HOUR_OF_DAY1) + 1 = (DateFormat$Field.HOUR_OF_DAY1) + 2 = () + 3 = (DateFormat$Field.HOUR0) + 4 = (DateFormat$Field.HOUR0) + 5 = () + 6 = (DateFormat$Field.DAY_OF_YEAR) + 7 = (DateFormat$Field.DAY_OF_YEAR) + 8 = (DateFormat$Field.DAY_OF_YEAR) + 9 = () + 10 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + 11 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + 12 = () + 13 = (DateFormat$Field.WEEK_OF_YEAR) + 14 = (DateFormat$Field.WEEK_OF_YEAR) + 15 = () + 16 = (DateFormat$Field.WEEK_OF_MONTH) + 17 = (DateFormat$Field.WEEK_OF_MONTH) + 18 = () + 19 = (DateFormat$Field.TIME_ZONE) + 20 = (DateFormat$Field.TIME_ZONE) + 21 = (DateFormat$Field.TIME_ZONE) + limits = ( { attributes = (DateFormat$Field.HOUR_OF_DAY1) + begin = 0 end = 2} + { attributes = () + begin = 2 begin2 = 0 end = 3 end2 = 22} + { attributes = (DateFormat$Field.HOUR0) + begin = 3 end = 5} + { attributes = () + begin = 5 begin2 = 0 end = 6 end2 = 22} + { attributes = (DateFormat$Field.DAY_OF_YEAR) + begin = 6 end = 9} + { attributes = () + begin = 9 begin2 = 0 end = 10 end2 = 22} + { attributes = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + begin = 10 end = 12} + { attributes = () + begin = 12 begin2 = 0 end = 13 end2 = 22} + { attributes = (DateFormat$Field.WEEK_OF_YEAR) + begin = 13 end = 15} + { attributes = () + begin = 15 begin2 = 0 end = 16 end2 = 22} + { attributes = (DateFormat$Field.WEEK_OF_MONTH) + begin = 16 end = 18} + { attributes = () + begin = 18 begin2 = 0 end = 19 end2 = 22} + { attributes = (DateFormat$Field.TIME_ZONE) + begin = 19 end = 22} + ) + fieldPositions = + ( + { + field = DateFormat.HOUR_OF_DAY1_FIELD + fieldID = DateFormat$Field.HOUR_OF_DAY1 + begin = 0 end = 2 + } + { + field = DateFormat.HOUR0_FIELD + fieldID = DateFormat$Field.HOUR0 + begin = 3 end = 5 + } + { + field = DateFormat.DAY_OF_YEAR_FIELD + fieldID = DateFormat$Field.DAY_OF_YEAR + begin = 6 end = 9 + } + { + field = DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD + fieldID = DateFormat$Field.DAY_OF_WEEK_IN_MONTH + begin = 10 end = 12 + } + { + field = DateFormat.WEEK_OF_YEAR_FIELD + fieldID = DateFormat$Field.WEEK_OF_YEAR + begin = 13 end = 15 + } + { + field = DateFormat.WEEK_OF_MONTH_FIELD + fieldID = DateFormat$Field.WEEK_OF_MONTH + begin = 16 end = 18 + } + { + field = DateFormat.TIMEZONE_FIELD + fieldID = DateFormat$Field.TIME_ZONE + begin = 19 end = 22 + } + ) + } + ) +} diff --git a/jdk/test/java/text/Format/common/decimalFormat.props b/jdk/test/java/text/Format/common/decimalFormat.props new file mode 100644 index 00000000000..e6d9adc7974 --- /dev/null +++ b/jdk/test/java/text/Format/common/decimalFormat.props @@ -0,0 +1,1280 @@ +# +# Copyright (c) 2000, 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 data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Integer + valueArgs = ("1234567") + } + { + length = 9 + text = "1,234,567" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 9} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 9 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###.##") + valueClass = java.lang.Float + valueArgs = ("567.78") + } + { + length = 6 + text = "567.78" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 4 = (NumberFormat$Field.FRACTION) + 5 = (NumberFormat$Field.FRACTION) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 3 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.FRACTION) + begin = 4 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 3 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 3 end = 4 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 4 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("0.#E00") + valueClass = java.lang.Float + valueArgs = ("1200") + } + { + length = 6 + text = "1.2E03" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 2 = (NumberFormat$Field.FRACTION) + 3 = (NumberFormat$Field.EXPONENT_SYMBOL) + 4 = (NumberFormat$Field.EXPONENT) + 5 = (NumberFormat$Field.EXPONENT) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.FRACTION) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.EXPONENT_SYMBOL) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.EXPONENT) + begin = 4 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 1 end = 2 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 2 end = 3 + } + { + fieldID = NumberFormat$Field.EXPONENT_SYMBOL + begin = 3 end = 4 + } + { + fieldID = NumberFormat$Field.EXPONENT + begin = 4 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("0.#E00") + valueClass = java.lang.Float + valueArgs = ("-.0012") + } + { + length = 8 + text = "-1.2E-03" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 3 = (NumberFormat$Field.FRACTION) + 4 = (NumberFormat$Field.EXPONENT_SYMBOL) + 5 = (NumberFormat$Field.EXPONENT_SIGN) + 6 = (NumberFormat$Field.EXPONENT) + 7 = (NumberFormat$Field.EXPONENT) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.FRACTION) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.EXPONENT_SYMBOL) + begin = 4 end = 5} + { attributes = (NumberFormat$Field.EXPONENT_SIGN) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.EXPONENT) + begin = 6 end = 8} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 2 end = 3 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 3 end = 4 + } + { + fieldID = NumberFormat$Field.EXPONENT_SYMBOL + begin = 4 end = 5 + } + { + fieldID = NumberFormat$Field.EXPONENT_SIGN + begin = 5 end = 6 + } + { + fieldID = NumberFormat$Field.EXPONENT + begin = 6 end = 8 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###;(#,###)") + valueClass = java.lang.Integer + valueArgs = ("-1234") + } + { + length = 7 + text = "(1,234)" + 0 = () + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = () + limits = ( { attributes = () + begin = 0 end = 1 end2 = 7 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = () + begin = 6 begin2 = 0 end = 7} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 6 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###;-#,###") + valueClass = java.lang.Integer + valueArgs = ("-134") + } + { + length = 4 + text = "-134" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 4 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("+#,###") + valueClass = java.lang.Integer + valueArgs = ("134") + } + { + length = 4 + text = "+134" + 0 = () + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end2 = 4 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 4 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("##.0#%") + valueClass = java.lang.Float + valueArgs = (".1234") + } + { + length = 6 + text = "12.34%" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 3 = (NumberFormat$Field.FRACTION) + 4 = (NumberFormat$Field.FRACTION) + 5 = (NumberFormat$Field.PERCENT) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 2 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 2 end = 3 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 3 end = 5 } + { attributes = (NumberFormat$Field.PERCENT) + begin = 5 end = 6 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 2 end = 3 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 3 end = 5 + } + { + fieldID = NumberFormat$Field.PERCENT + begin = 5 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,##.#\u2030") + valueClass = java.lang.Float + valueArgs = (".1234") + } + { + length = 7 + text = "1,23.4\u2030" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.GROUPING_SEPARATOR + NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 5 = (NumberFormat$Field.FRACTION) + 6 = (NumberFormat$Field.PERMILLE) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 4 } + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 4 end = 5 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 5 end = 6 } + { attributes = (NumberFormat$Field.PERMILLE) + begin = 6 end = 7 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 4 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 4 end = 5 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 5 end = 6 + } + { + fieldID = NumberFormat$Field.PERMILLE + begin = 6 end = 7 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("\u00A40,000.00") + valueClass = java.lang.Float + valueArgs = ("12.51") + } + { + length = 9 + text = "$0,012.51" + 0 = (NumberFormat$Field.CURRENCY) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.GROUPING_SEPARATOR + NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 7 = (NumberFormat$Field.FRACTION) + 8 = (NumberFormat$Field.FRACTION) + limits = ( { attributes = (NumberFormat$Field.CURRENCY) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 6 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 3 begin2 = 1 end = 6 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 6 end = 7 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 7 end = 9 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.CURRENCY + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 6 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 6 end = 7 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 7 end = 9 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.math.BigInteger + valueArgs = ("-12345678901234567890123456789012345") + } + { + length = 47 + text = "-12,345,678,901,234,567,890,123,456,789,012,345" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + 26 = (NumberFormat$Field.INTEGER) + 27 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 28 = (NumberFormat$Field.INTEGER) + 29 = (NumberFormat$Field.INTEGER) + 30 = (NumberFormat$Field.INTEGER) + 31 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 32 = (NumberFormat$Field.INTEGER) + 33 = (NumberFormat$Field.INTEGER) + 34 = (NumberFormat$Field.INTEGER) + 35 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 36 = (NumberFormat$Field.INTEGER) + 37 = (NumberFormat$Field.INTEGER) + 38 = (NumberFormat$Field.INTEGER) + 39 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 40 = (NumberFormat$Field.INTEGER) + 41 = (NumberFormat$Field.INTEGER) + 42 = (NumberFormat$Field.INTEGER) + 43 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 44 = (NumberFormat$Field.INTEGER) + 45 = (NumberFormat$Field.INTEGER) + 46 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 3 end2 = 47 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 3 end = 4 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 4 begin2 = 1 end = 7 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 7 end = 8 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 8 begin2 = 1 end = 11 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 11 end = 12 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 12 begin2 = 1 end = 15 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 15 end = 16 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 16 begin2 = 1 end = 19 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 20 begin2 = 1 end = 23 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 23 end = 24 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 24 begin2 = 1 end = 27 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 27 end = 28 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 28 begin2 = 1 end = 31 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 31 end = 32 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 32 begin2 = 1 end = 35 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 35 end = 36 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 36 begin2 = 1 end = 39 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 39 end = 40 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 40 begin2 = 1 end = 43 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 43 begin2 = 43 end = 44 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 44 begin2 = 1 end = 47} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 47 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###.#####################") + valueClass = java.math.BigDecimal + valueArgs = ("-123456789012345678901234567890.12345678901234567890") + } + { + length = 60 + text = "-123,456,789,012,345,678,901,234,567,890.1234567890123456789" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 25 = (NumberFormat$Field.INTEGER) + 26 = (NumberFormat$Field.INTEGER) + 27 = (NumberFormat$Field.INTEGER) + 28 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 29 = (NumberFormat$Field.INTEGER) + 30 = (NumberFormat$Field.INTEGER) + 31 = (NumberFormat$Field.INTEGER) + 32 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 33 = (NumberFormat$Field.INTEGER) + 34 = (NumberFormat$Field.INTEGER) + 35 = (NumberFormat$Field.INTEGER) + 36 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 37 = (NumberFormat$Field.INTEGER) + 38 = (NumberFormat$Field.INTEGER) + 39 = (NumberFormat$Field.INTEGER) + 40 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 41 = (NumberFormat$Field.FRACTION) + 42 = (NumberFormat$Field.FRACTION) + 43 = (NumberFormat$Field.FRACTION) + 44 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 46 = (NumberFormat$Field.FRACTION) + 47 = (NumberFormat$Field.FRACTION) + 48 = (NumberFormat$Field.FRACTION) + 49 = (NumberFormat$Field.FRACTION) + 50 = (NumberFormat$Field.FRACTION) + 51 = (NumberFormat$Field.FRACTION) + 52 = (NumberFormat$Field.FRACTION) + 53 = (NumberFormat$Field.FRACTION) + 54 = (NumberFormat$Field.FRACTION) + 55 = (NumberFormat$Field.FRACTION) + 56 = (NumberFormat$Field.FRACTION) + 57 = (NumberFormat$Field.FRACTION) + 58 = (NumberFormat$Field.FRACTION) + 59 = (NumberFormat$Field.FRACTION) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 end2 = 40 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 4 end = 5 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 5 begin2 = 1 end = 8 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 8 end = 9 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 9 begin2 = 1 end = 12 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 12 end = 13 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 13 begin2 = 1 end = 16 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 16 end = 17 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 17 begin2 = 1 end = 20 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 20 end = 21 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 21 begin2 = 1 end = 24 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 24 end = 25 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 25 begin2 = 1 end = 28 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 28 end = 29 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 29 begin2 = 1 end = 32 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 32 end = 33 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 33 begin2 = 1 end = 36 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 36 end = 37 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 37 begin2 = 1 end = 40 end2 = 40} + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 40 end = 41 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 41 begin2 = 41 end = 60 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 40 end = 41 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 40 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 41 end = 60 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Long + valueArgs = ("9223372036854775807") + } + { + length = 25 + text = "9,223,372,036,854,775,807" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 25} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 25 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicLong + valueArgs = ("9223372036854775807") + } + { + length = 25 + text = "9,223,372,036,854,775,807" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 25} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 25 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Long + valueArgs = ("-9223372036854775808") + } + { + length = 26 + text = "-9,223,372,036,854,775,808" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 26} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 26 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicLong + valueArgs = ("-9223372036854775808") + } + { + length = 26 + text = "-9,223,372,036,854,775,808" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 26} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 26 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicInteger + valueArgs = ("2147483647") + } + { + length = 13 + text = "2,147,483,647" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 13} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 13 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicInteger + valueArgs = ("-2147483648") + } + { + length = 14 + text = "-2,147,483,648" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 14 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + ) +} diff --git a/jdk/test/java/text/Format/common/messageFormat.props b/jdk/test/java/text/Format/common/messageFormat.props new file mode 100644 index 00000000000..c8aaeecfd32 --- /dev/null +++ b/jdk/test/java/text/Format/common/messageFormat.props @@ -0,0 +1,520 @@ +# +# Copyright (c) 2000, 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 data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.MessageFormat + args = ("0={0} 1={1}") + valueClass = java.lang.reflect.Array + valueArgs = ("zero" "one") + } + { + length = 12 + text = "0=zero 1=one" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = (MessageFormat$Field.ARGUMENT) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = () + 7 = () + 8 = () + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT) + 11 = (MessageFormat$Field.ARGUMENT) + limits = ( { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 6} + { attributes = () + begin = 0 begin2 = 0 end = 2 end2 = 12} + { attributes = () + begin = 6 begin2 = 0 end = 9 end2 = 12} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 9 end = 12} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 6 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0} 1={1} 0={0}") + valueClass = java.lang.reflect.Array + valueArgs = ("ze" "on") + } + { + length = 14 + text = "0=ze 1=on 0=ze" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = () + 5 = () + 6 = () + 7 = (MessageFormat$Field.ARGUMENT) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = () + 10 = () + 11 = () + 12 = (MessageFormat$Field.ARGUMENT) + 13 = (MessageFormat$Field.ARGUMENT) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 7 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 7 end = 9} + { attributes = () + begin = 9 begin2 = 0 end = 12 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 12 end = 14} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 4 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("5/23/2001")) (Integer ("20122"))) + } + { + length = 23 + text = "0=May 23, 2001 1=20,122" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 17 end = 19 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 17 end = 19 end2 = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 20 begin2 = 17 end = 23} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("1/22/2003")) (java.math.BigInteger ("12345678901234567890123456789012345"))) + } + { + length = 63 + text = "0=Jan 22, 2003 1=12,345,678,901,234,567,890,123,456,789,012,345" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 48 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 49 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 50 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 51 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 52 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 53 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 54 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 55 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 56 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 57 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 58 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 59 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 60 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 61 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 62 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 63} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 63} + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 17 end = 19 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 20 begin2 = 17 end = 23 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 23 end = 24 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 24 begin2 = 17 end = 27 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 27 end = 28 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 28 begin2 = 17 end = 31 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 31 end = 32 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 32 begin2 = 17 end = 35 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 35 end = 36 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 36 begin2 = 17 end = 39 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 39 end = 40 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 40 begin2 = 17 end = 43 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 43 end = 44 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 44 begin2 = 17 end = 47 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 47 end = 48 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 48 begin2 = 17 end = 51 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 51 end = 52 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 52 begin2 = 17 end = 55 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 55 end = 56 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 56 begin2 = 17 end = 59 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 59 end = 60 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 60 begin2 = 17 end = 63} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("1/26/2003")) (java.math.BigDecimal ("-12345678901234567890.1239"))) + } + { + length = 48 + text = "0=Jan 26, 2003 1=-12,345,678,901,234,567,890.124" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.SIGN) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.DECIMAL_SEPARATOR) + 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 48} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 48} + + { attributes = (NumberFormat$Field.SIGN) + begin = 17 end = 18 } + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 18 end = 20 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 20 end = 21 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 21 begin2 = 18 end = 24 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 24 end = 25 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 25 begin2 = 18 end = 28 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 28 end = 29 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 29 begin2 = 18 end = 32 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 32 end = 33 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 33 begin2 = 18 end = 36 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 36 end = 37 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 37 begin2 = 18 end = 40 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 40 end = 41 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 41 begin2 = 18 end = 44 end2 = 44} + + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 44 begin2 = 41 end = 45 end2 = 48} + + { attributes = (NumberFormat$Field.FRACTION + MessageFormat$Field.ARGUMENT) + begin = 45 end = 48} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,choice,-1#neg| 0#zero | 1#more}xx") + valueClass = java.lang.reflect.Array + valueArgs = ((Integer ("-11"))) + } + { + length = 7 + text = "0=negxx" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = (MessageFormat$Field.ARGUMENT) + 5 = () + 6 = () + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 7} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5} + { attributes = () + begin = 5 begin2 = 0 end = 7} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 5 + } + ) + } + ) +} + diff --git a/jdk/test/java/text/testlib/HexDumpReader.java b/jdk/test/java/text/testlib/HexDumpReader.java new file mode 100644 index 00000000000..31a820d04d4 --- /dev/null +++ b/jdk/test/java/text/testlib/HexDumpReader.java @@ -0,0 +1,115 @@ +/* + * 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.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * HexDumpReader provides utility methods to read a hex dump text file + * and convert to an InputStream. The format supported by the methods + * can be generated by the following command. + * + * $ od -vw -t x1 foo | sed -r -e 's/^[0-9]+ ?//' -e 's/ //g' -e '/^$/d' + */ +public class HexDumpReader { + public static InputStream getStreamFromHexDump(String fileName) { + return getStreamFromHexDump(new File(System.getProperty("test.src", "."), + fileName)); + } + + public static InputStream getStreamFromHexDump(File hexFile) { + ByteArrayBuilder bab = new ByteArrayBuilder(); + int lineNo = 0; + try (BufferedReader reader + = new BufferedReader(new InputStreamReader(new FileInputStream(hexFile), + "us-ascii"))) { + String line; + while ((line = reader.readLine()) != null) { + lineNo++; + line = line.trim(); + // Skip blank and comment lines. + if (line.length() == 0) { + continue; + } + int x = line.indexOf('#'); + if (x == 0) { + continue; + } + if (x > 0) { + line = line.substring(0, x).trim(); + } + int len = line.length(); + for (int i = 0; i < len; i += 2) { + bab.put((byte)Integer.parseInt(line, i, i + 2, 16)); + } + } + } catch (Exception e) { + throw new RuntimeException(hexFile.getName() + ":error:" + lineNo + ": " + e, e); + } + return new ByteArrayInputStream(bab.toArray()); + } + + + private static class ByteArrayBuilder { + private static final int BUFFER_SIZE = 4096; + + private int size; + private List bytes; + private byte[] current; + private int offset; + + ByteArrayBuilder() { + bytes = new ArrayList<>(); + current = new byte[BUFFER_SIZE]; + } + + void put(byte b) { + if (offset == BUFFER_SIZE) { + bytes.add(current); + current = new byte[BUFFER_SIZE]; + offset = 0; + } + current[offset++] = b; + size++; + } + + byte[] toArray() { + byte[] buf = new byte[size]; + int ptr = 0; + for (byte[] ba : bytes) { + System.arraycopy(ba, 0, buf, ptr, ba.length); + ptr += ba.length; + } + System.arraycopy(current, 0, buf, ptr, offset); + assert ptr + offset == size; + return buf; + } + } + +} diff --git a/jdk/test/java/text/testlib/IntlTest.java b/jdk/test/java/text/testlib/IntlTest.java new file mode 100644 index 00000000000..d8ae8572f30 --- /dev/null +++ b/jdk/test/java/text/testlib/IntlTest.java @@ -0,0 +1,266 @@ +/* + * 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 + * 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.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * IntlTest 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 public void methods named "Test*" or + * "test*" with no arguments. 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 abstract class IntlTest { + + //------------------------------------------------------------------------ + // Everything below here is boilerplate code that makes it possible + // to add a new test by simply adding a method to an existing class. + //------------------------------------------------------------------------ + + protected IntlTest() { + // Populate testMethods with all the test methods. + Method[] methods = getClass().getDeclaredMethods(); + for (Method method : methods) { + if (Modifier.isPublic(method.getModifiers()) + && method.getReturnType() == void.class + && method.getParameterCount() == 0) { + String name = method.getName(); + if (name.length() > 4) { + if (name.startsWith("Test") || name.startsWith("test")) { + testMethods.put(name, method); + } + } + } + } + } + + protected void run(String[] args) throws Exception + { + // Set up the log and reference streams. We use PrintWriters in order to + // take advantage of character conversion. The JavaEsc converter will + // convert Unicode outside the ASCII range to Java's \\uxxxx notation. + log = new PrintWriter(System.out, true); + + // Parse the test arguments. They can be either the flag + // "-verbose" or names of test methods. Create a list of + // tests to be run. + List testsToRun = new ArrayList<>(args.length); + for (String arg : args) { + switch (arg) { + case "-verbose": + verbose = true; + break; + case "-prompt": + prompt = true; + break; + case "-nothrow": + nothrow = true; + break; + default: + Method m = testMethods.get(arg); + if (m == null) { + System.out.println("Method " + arg + ": not found"); + usage(); + return; + } + testsToRun.add(m); + break; + } + } + + // If no test method names were given explicitly, run them all. + if (testsToRun.isEmpty()) { + testsToRun.addAll(testMethods.values()); + } + + System.out.println(getClass().getName() + " {"); + indentLevel++; + + // Run the list of tests given in the test arguments + for (Method testMethod : testsToRun) { + int oldCount = errorCount; + + writeTestName(testMethod.getName()); + + try { + testMethod.invoke(this, new Object[0]); + } catch (IllegalAccessException e) { + errln("Can't acces test method " + testMethod.getName()); + } catch (InvocationTargetException e) { + errln("Uncaught exception thrown in test method " + + testMethod.getName()); + e.getTargetException().printStackTrace(this.log); + } + writeTestResult(errorCount - oldCount); + } + indentLevel--; + writeTestResult(errorCount); + + if (prompt) { + System.out.println("Hit RETURN to exit..."); + try { + System.in.read(); + } catch (IOException e) { + System.out.println("Exception: " + e.toString() + e.getMessage()); + } + } + if (nothrow) { + System.exit(errorCount); + } + } + + /** + * Adds the given message to the log if we are in verbose mode. + */ + protected void log(String message) { + logImpl(message, false); + } + + protected void logln(String message) { + logImpl(message, true); + } + + protected void logln() { + logImpl(null, true); + } + + private void logImpl(String message, boolean newline) { + if (verbose) { + if (message != null) { + indent(indentLevel + 1); + log.print(message); + } + if (newline) { + log.println(); + } + } + } + + protected void err(String message) { + errImpl(message, false); + } + + protected void errln(String message) { + errImpl(message, true); + } + + private void errImpl(String message, boolean newline) { + errorCount++; + indent(indentLevel + 1); + log.print(message); + if (newline) { + log.println(); + } + log.flush(); + + if (!nothrow) { + throw new RuntimeException(message); + } + } + + protected int getErrorCount() { + return errorCount; + } + + 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"); + } + } + + /* + * Returns a spece-delimited hex String. + */ + protected static String toHexString(String s) { + StringBuilder sb = new StringBuilder(" "); + + for (int i = 0; i < s.length(); i++) { + sb.append(Integer.toHexString(s.charAt(i))); + sb.append(' '); + } + + return sb.toString(); + } + + private void indent(int distance) { + if (needLineFeed) { + log.println(" {"); + 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] [-prompt] [test names]"); + + System.out.println(" Available test names:"); + for (String methodName : testMethods.keySet()) { + System.out.println("\t" + methodName); + } + } + + private boolean prompt; + private boolean nothrow; + protected boolean verbose; + + private PrintWriter log; + private int indentLevel; + private boolean needLineFeed; + private int errorCount; + + private final Map testMethods = new LinkedHashMap<>(); + + private static final String SPACES = " "; +} diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java index d1092d15ee6..c86805f9bfe 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java +++ b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java @@ -442,28 +442,44 @@ public class TCKIsoFields { } //----------------------------------------------------------------------- - // range refinedby + // rangeRefinedBy //----------------------------------------------------------------------- @DataProvider(name="isofields") Object[][] data_isofields() { return new Object[][] { - {IsoFields.DAY_OF_QUARTER}, - {IsoFields.QUARTER_OF_YEAR}, - {IsoFields.WEEK_OF_WEEK_BASED_YEAR}, - {IsoFields.WEEK_BASED_YEAR}, + {IsoFields.DAY_OF_QUARTER, 49, ValueRange.of(1, 91)}, + {IsoFields.QUARTER_OF_YEAR, 2, ValueRange.of(1, 4)}, + {IsoFields.WEEK_OF_WEEK_BASED_YEAR, 20, ValueRange.of(1, 52)}, + {IsoFields.WEEK_BASED_YEAR, 2016, ValueRange.of(LocalDate.MIN.getYear(), + LocalDate.MAX.getYear())}, }; } @Test(dataProvider = "isofields") - public void test_isofields_rangerefinedby(TemporalField field) { - field.rangeRefinedBy(LocalDate.now()); + public void test_isofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) { + LocalDate date = LocalDate.of(2016, 5, 19); + assertEquals(field.rangeRefinedBy(date), valueRange); } @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class) - public void test_nonisofields_rangerefinedby(TemporalField field) { + public void test_nonisofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) { field.rangeRefinedBy(ThaiBuddhistDate.now()); } + //----------------------------------------------------------------------- + // getFrom + //----------------------------------------------------------------------- + @Test(dataProvider = "isofields") + public void test_isofields_getFrom(TemporalField field, int value, ValueRange valueRange) { + LocalDate date = LocalDate.of(2016, 5, 19); + assertEquals(field.getFrom(date), value); + } + + @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class) + public void test_nonisofields_getFrom(TemporalField field, int value, ValueRange valueRange) { + field.getFrom(ThaiBuddhistDate.now()); + } + //----------------------------------------------------------------------- public void test_loop() { // loop round at least one 400 year cycle, including before 1970 diff --git a/jdk/test/java/util/Calendar/BuddhistCalendarTest.java b/jdk/test/java/util/Calendar/BuddhistCalendarTest.java new file mode 100644 index 00000000000..8d6a5fc3466 --- /dev/null +++ b/jdk/test/java/util/Calendar/BuddhistCalendarTest.java @@ -0,0 +1,243 @@ +/* + * 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 + * 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 4817812 4847186 4956227 4956479 + * @summary Confirm that BuddhistCalendar's add(), roll() and toString() work correctly with Buddhist Era years. + */ + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Locale; +import static java.util.Calendar.*; + +public class BuddhistCalendarTest { + + private static final Locale THAI_LOCALE = new Locale("th", "TH"); + + public static void main(String[] args) { + testAddRoll(); + testToString(); + testException(); + testLeastMax(); + } + + /** + * 4817812 + */ + static void testAddRoll() { + Calendar cal; + int base, year; + + /* + * Test: BuddhistCalendar.add(YEAR) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.add(YEAR, 1); + year = cal.get(YEAR); + check(year, base+1, "add(+YEAR)"); + + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.add(YEAR, -3); + year = cal.get(YEAR); + check(year, base-3, "add(-YEAR)"); + + /* + * Test BuddhistCalendar.add(MONTH) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(MONTH, DECEMBER); + cal.add(MONTH, 2); + year = cal.get(YEAR); + check(year, base+1, "add(+MONTH)"); + + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(MONTH, FEBRUARY); + cal.add(MONTH, -4); + year = cal.get(YEAR); + check(year, base-1, "add(-MONTH)"); + + /* + * Test BuddhistCalendar.roll(YEAR) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.roll(YEAR, 2); + year = cal.get(YEAR); + check(year, base+2, "roll(+YEAR)"); + + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.roll(YEAR, -4); + year = cal.get(YEAR); + check(year, base-4, "roll(-YEAR)"); + + /* + * Test BuddhistCalendar.roll(WEEK_OF_YEAR) + */ + cal = getBuddhistCalendar(); + cal.set(YEAR, 2543); // A.D.2000 + cal.set(MONTH, DECEMBER); + cal.set(DATE, 31); + base = cal.get(YEAR); + check(base, 2543, "roll(+WEEK_OF_YEAR)"); + cal.roll(WEEK_OF_YEAR, 10); + year = cal.get(YEAR); + check(year, base, "roll(+WEEK_OF_YEAR)"); + + cal = getBuddhistCalendar(); + cal.set(YEAR, 2543); // A.D.2000 + cal.set(MONTH, JANUARY); + cal.set(DATE, 1); + base = cal.get(YEAR); + check(base, 2543, "roll(+WEEK_OF_YEAR)"); + cal.roll(WEEK_OF_YEAR, -10); + year = cal.get(YEAR); + check(year, base, "roll(-WEEK_OF_YEAR)"); + + /* + * Test Calendar.set(year, month, date) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(3001, APRIL, 10); + year = cal.get(YEAR); + check(year, 3001, "set(year, month, date)"); + + /* + * Test Calendar.set(year, month, date, hour, minute) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(3020, MAY, 20, 9, 10); + year = cal.get(YEAR); + check(year, 3020, "set(year, month, date, hour, minute)"); + + /* + * Test Calendar.set(year, month, date, hour, minute, second) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(3120, MAY, 20, 9, 10, 52); + year = cal.get(YEAR); + check(year, 3120, "set(year, month, date, hour, minute, second)"); + + /* + * Test BuddhistCalendar.getActualMaximum(YEAR); + * set(YEAR)/get(YEAR) in this method doesn't affect the real + * YEAR value because a clone is used with set()&get(). + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + int limit = cal.getActualMaximum(YEAR); + year = cal.get(YEAR); + check(year, base, "BuddhistCalendar.getActualMaximum(YEAR)"); + + /* + * Test BuddhistCalendar.getActualMinimum(YEAR); + * This doesn't call set(YEAR) nor get(YEAR), though. + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + limit = cal.getActualMinimum(YEAR); + year = cal.get(YEAR); + check(year, base, "BuddhistCalendar.getActualMinimum(YEAR)"); + } + + /** + * 4847186: BuddhistCalendar: toString() returns Gregorian year + */ + static void testToString() { + Calendar cal = getBuddhistCalendar(); + int year = cal.get(YEAR); + String s = cal.toString(); + String y = s.replaceAll(".+,YEAR=(\\d+),.+", "$1"); + if (Integer.parseInt(y) != year) { + throw new RuntimeException("toString(): wrong year value: got " + y + + ", expected " + year); + } + } + + /** + * 4956479: BuddhistCalendar methods may return wrong values after exception + */ + static void testException() { + Calendar cal = getBuddhistCalendar(); + int year = cal.get(YEAR); + boolean exceptionOccurred = false; + try { + cal.add(100, +1); // cause exception + } catch (Exception e) { + exceptionOccurred = true; + } + if (!exceptionOccurred) { + throw new RuntimeException("testException: test case failed: no exception thrown"); + } + int year2 = cal.get(YEAR); + if (year2 != year) { + throw new RuntimeException("wrong year value after exception: got " + year2 + + ", expected " + year); + } + } + + /** + * 4956227: getLeastMaximum(WEEK_OF_MONTH) return diff. val. for Greg. and Buddhist Calendar + */ + static void testLeastMax() { + Calendar bc = getBuddhistCalendar(); + // Specify THAI_LOCALE to get the same params for WEEK + // calculations (6904680). + Calendar gc = new GregorianCalendar(THAI_LOCALE); + for (int f = 0; f < Calendar.FIELD_COUNT; f++) { + if (f == ERA || f == YEAR) { + continue; + } + int bn = bc.getLeastMaximum(f); + int gn = gc.getLeastMaximum(f); + if (bn != gn) { + throw new RuntimeException("inconsistent Least Max value for " + Koyomi.getFieldName(f) + + ": Buddhist=" + bn + + ": Gregorian=" + gn); + } + } + } + + /** + * @return a BuddhistCalendar + */ + static Calendar getBuddhistCalendar() { + return Calendar.getInstance(THAI_LOCALE); + } + + static void check(int got, int expected, String s) { + if (got != expected) { + throw new RuntimeException("Failed: " + + s + ": got:" + got + ", expected:" + expected); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4302966.java b/jdk/test/java/util/Calendar/Bug4302966.java new file mode 100644 index 00000000000..6c3b9c3d60e --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4302966.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2001, 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 4302966 + * @summary In Czech Republic first day of week is Monday not Sunday + */ + +import java.util.Calendar; +import java.util.Locale; + +public class Bug4302966 { + + public static void main(String[] args) { + Calendar czechCalendar = Calendar.getInstance(new Locale("cs")); + int firstDayOfWeek = czechCalendar.getFirstDayOfWeek(); + if (firstDayOfWeek != Calendar.MONDAY) { + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4766302.java b/jdk/test/java/util/Calendar/Bug4766302.java new file mode 100644 index 00000000000..42df92b7e16 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4766302.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 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 4766302 + * @summary Make sure that computeTime call doesn't reset the isTimeSet value. + */ + +import java.util.GregorianCalendar; + +public class Bug4766302 { + + static class MyCalendar extends GregorianCalendar { + boolean isTimeStillSet() { + return isTimeSet; + } + + protected void computeTime() { + super.computeTime(); + } + } + + public static void main(String[] args) { + MyCalendar cal = new MyCalendar(); + cal.computeTime(); + if (!cal.isTimeStillSet()) { + throw new RuntimeException("computeTime() call reset isTimeSet."); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4851640.java b/jdk/test/java/util/Calendar/Bug4851640.java new file mode 100644 index 00000000000..4f5add37679 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4851640.java @@ -0,0 +1,59 @@ +/* + * 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 + * 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 4851640 + * @summary Make sure not to set UNSET fields to COMPUTED after time calculation. + */ + +import java.util.GregorianCalendar; +import static java.util.Calendar.*; + +public class Bug4851640 { + + public static void main(String args[]) { + GregorianCalendar cal = new GregorianCalendar(); + cal.clear(); + cal.set(YEAR, 2003); + long t = cal.getTime().getTime(); + + // For the time calculation, the MONTH and DAY_OF_MONTH fields + // (with the default values) have been used for determining + // the date. However, both the MONTH and DAY_OF_MONTH fields + // should be kept UNSET after the time calculation. + if (cal.isSet(MONTH) || cal.isSet(DAY_OF_MONTH)) { + throw new RuntimeException("After getTime(): MONTH field=" + cal.isSet(MONTH) + + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH)); + } + + // After calling get() for any field, all field values are + // recalculated and their field states are set to + // COMPUTED. isSet() must return true. + int y = cal.get(YEAR); + if (!(cal.isSet(MONTH) && cal.isSet(DAY_OF_MONTH))) { + throw new RuntimeException("After get(): MONTH field=" + cal.isSet(MONTH) + + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH)); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4958050.java b/jdk/test/java/util/Calendar/Bug4958050.java new file mode 100644 index 00000000000..dfd627cda6f --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4958050.java @@ -0,0 +1,255 @@ +/* + * 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 + * 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 4958050 + * @summary Make sure that add() and roll() handle time zone offset changes (both raw and DST) correctly. + */ + +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) { + // All the test cases depend on historical GMT offset changes + // of Asia/Novosibirsk. + Koyomi cal = new Koyomi(TimeZone.getTimeZone("Asia/Novosibirsk"), Locale.US); + 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 }; + 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.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()); + } + cal.clear(); + 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()); + } + + // roll() + cal.clear(); + 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()); + } + cal.clear(); + 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()); + } + } + + // Test the day fields + 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.add(field, +1); + if (!cal.checkDate(1919, DECEMBER, 14)) { + error("1919/12/13: add("+cal.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()); + } + cal.clear(); + 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()); + } + 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()); + } + + // roll() + cal.clear(); + 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()); + } + cal.clear(); + cal.set(1930, JUNE, 21, 01, 00, 00); + amount = -1; + if (field == DAY_OF_WEEK) { + amount -= 700; + } + 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()); + } + } + + // Test the AM_PM field + // add() + cal.clear(); + 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)) { + error("1919/12/13: add(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + 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)) { + error("1930/6/20: add(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + 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)) { + error("1930/6/10: add(AM_PM, +3)\n" + + 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)) { + error("1919/12/14 11:50:00: add(AM_PM, -1)\n" + + 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)) { + error("1930/6/20: add(AM_PM, -1)\n" + + 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)) { + error("1930/6/10: add(AM_PM, -3)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + // roll() (should NOT change the date) + cal.clear(); + 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)) { + error("1919/12/13: roll(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + 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)) { + error("1930/6/20: roll(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + 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)) { + error("1930/6/10: roll(AM_PM, +3)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + // Test the HOUR_OF_DAY field + // add() + cal.clear(); + cal.set(1930, JUNE, 20, 23, 00, 00); + 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()); + } + + // roll() (should NOT change the date) + cal.clear(); + cal.set(1930, JUNE, 20, 23, 00, 00); + 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()); + } + + checkErrors(); + } + + static void error(String s) { + System.out.println(s); + errorCount++; + } + + static void checkErrors() { + if (errorCount > 0) { + throw new RuntimeException("Failed: " + errorCount + " error(s)"); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug5078053.java b/jdk/test/java/util/Calendar/Bug5078053.java new file mode 100644 index 00000000000..c6bb25bcf82 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug5078053.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2004, 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 5078053 + * @summary Make sure that Calendar.complete() normalizes stamp[] to + * COMPUTED. This can be observed through add() and roll(). + */ + +import java.util.TimeZone; +import static java.util.Calendar.*; + +public class Bug5078053 { + static int errorCount = 0; + + public static void main(String[] args) { + TimeZone defaultTz = TimeZone.getDefault(); + + try { + TimeZone tz = TimeZone.getTimeZone("Australia/Adelaide"); + TimeZone.setDefault(tz); + Koyomi cal = new Koyomi(); + cal.setFirstDayOfWeek(2); + cal.setMinimalDaysInFirstWeek(4); + + // test roll() + cal.clear(); + // 2002-01-01T00:00:00 in Australia/Adelaide + cal.setTimeInMillis(1009805400000L); + System.out.println(cal.getTime()); + // The following set calls shouldn't affect roll() and add() + cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK)); + cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR)); + cal.getTime(); + cal.roll(MONTH, +1); + System.out.println("roll: " + cal.getTime()); + if (!cal.checkDate(2002, FEBRUARY, 1)) { + error("roll(MONTH, +1): " + cal.getMessage()); + } + cal.roll(MONTH, -1); + if (!cal.checkDate(2002, JANUARY, 1)) { + error("roll(MONTH, -1): " + cal.getMessage()); + } + + // test add() + cal.clear(); + // 2002-01-01T00:00:00+0930 in Australia/Adelaide + cal.setTimeInMillis(1009805400000L); + cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK)); + cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR)); + cal.getTime(); + cal.add(MONTH, +1); + System.out.println(" add: " + cal.getTime()); + if (!cal.checkDate(2002, FEBRUARY, 1)) { + error("add(MONTH, +1): " + cal.getMessage()); + } + cal.add(MONTH, -1); + if (!cal.checkDate(2002, JANUARY, 1)) { + error("add(MONTH, -1): " + cal.getMessage()); + } + } + finally { + TimeZone.setDefault(defaultTz); + } + + checkErrors(); + } + + static void error(String s) { + System.out.println(s); + errorCount++; + } + + static void checkErrors() { + if (errorCount > 0) { + throw new RuntimeException("Failed: " + errorCount + " error(s)"); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug6178071.java b/jdk/test/java/util/Calendar/Bug6178071.java new file mode 100644 index 00000000000..8d361c76bcb --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug6178071.java @@ -0,0 +1,50 @@ +/* + * 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 + * 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 6178071 6440854 + * @summary Make sure that setting HOUR right after a construction works + * as expected. + */ + +import java.util.GregorianCalendar; +import static java.util.Calendar.*; + +public class Bug6178071 { + public static void main(String[] args) { + GregorianCalendar cal = new GregorianCalendar(2004, JANUARY, 1); + cal.set(HOUR, 1); + if (cal.get(HOUR_OF_DAY) != 1 || + cal.get(HOUR) != 1 || cal.get(AM_PM) != AM) { + throw new RuntimeException("Unexpected hour of day: " + cal.getTime()); + } + + // Test case for 6440854 + GregorianCalendar gc = new GregorianCalendar(2006,5,16); + gc.setLenient(false); + gc.set(HOUR_OF_DAY, 10); + // The following line shouldn't throw an IllegalArgumentException. + gc.get(YEAR); + } +} diff --git a/jdk/test/java/util/Calendar/Bug6234795.java b/jdk/test/java/util/Calendar/Bug6234795.java new file mode 100644 index 00000000000..d1b2bc55c01 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug6234795.java @@ -0,0 +1,97 @@ +/* + * 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 + * 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 6234795 + * @summary Rolling of HOUR or HOUR_OF_SET must set the other hour field. + */ + +import java.util.GregorianCalendar; +import static java.util.Calendar.AM; +import static java.util.Calendar.AM_PM; +import static java.util.Calendar.HOUR; +import static java.util.Calendar.HOUR_OF_DAY; +import static java.util.Calendar.SEPTEMBER; +import java.util.Locale; +import java.util.TimeZone; + +public class Bug6234795 { + public static void main(String[] args) { + testRoll(HOUR); + testRoll(HOUR_OF_DAY); + } + + static void testRoll(int field) { + GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US); + cal.clear(); + cal.set(2005, SEPTEMBER, 12); + + int otherField = (field == HOUR) ? HOUR_OF_DAY : HOUR; + int unit = (field == HOUR) ? 12 : 24; + int h; + for (h = 0; h <= 72; h++) { + int hour = cal.get(otherField); + int expected = h % 12; + if (hour != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "+: h=" + h + ", got " + hour + + ", expected " + expected); + } + if (field == HOUR_OF_DAY) { + int ampm = cal.get(AM_PM); + expected = (h % unit) / 12; + if (ampm != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "+: h=" + h + ", got " + + toString(ampm) + + ", expected " + toString(expected)); + } + } + cal.roll(field, +1); + } + for (; h >= 0; h--) { + int hour = cal.get(otherField); + int expected = h % 12; + if (hour != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "-: h=" + h + ", got " + hour + + ", expected " + expected); + } + if (field == HOUR_OF_DAY) { + int ampm = cal.get(AM_PM); + expected = (h % unit) / 12; + if (ampm != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "-: h=" + h + ", got " + toString(ampm) + + ", expected " + toString(expected)); + } + } + cal.roll(field, -1); + } + } + + static String toString(int ampm) { + return ampm == AM ? "AM" : "PM"; + } +} diff --git a/jdk/test/java/util/Calendar/Bug6448234.java b/jdk/test/java/util/Calendar/Bug6448234.java new file mode 100644 index 00000000000..16cf0fca1c4 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug6448234.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006, 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 6448234 + * @summary Make sure indexing of DAY_OF_WEEK is correct in JapaneseImperialCalendar.getDisplayName. + */ + +import java.util.Calendar; +import java.util.Locale; +import static java.util.Calendar.*; + +public class Bug6448234 { + public static void main(String[] args) { + Calendar jcal = Calendar.getInstance(new Locale("ja", "JP", "JP")); + Calendar gcal = Calendar.getInstance(Locale.US); + + for (int i = SUNDAY; i <= SATURDAY; i++) { + jcal.set(DAY_OF_WEEK, i); + gcal.set(DAY_OF_WEEK, i); + + // Test LONG + String j = jcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US); + String g = gcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US); + if (!j.equals(g)) { + throw new RuntimeException("Got " + j + ", expected " + g); + } + + // Test SHORT + j = jcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US); + g = gcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US); + if (!j.equals(g)) { + throw new RuntimeException("Got " + j + ", expected " + g); + } + } + } +} diff --git a/jdk/test/java/util/Calendar/CalendarLimitTest.java b/jdk/test/java/util/Calendar/CalendarLimitTest.java new file mode 100644 index 00000000000..69dcbb5efcf --- /dev/null +++ b/jdk/test/java/util/Calendar/CalendarLimitTest.java @@ -0,0 +1,202 @@ +/* + * 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 + * 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 4033662 + * @library /java/text/testlib + * @summary test for limit on Calendar + * @run main CalendarLimitTest -verbose + */ + +import java.util.*; +import java.text.*; + +/** + * This test verifies the behavior of Calendar around the very earliest limits + * which it can handle. It also verifies the behavior for large values of millis. + * + * Note: There used to be a limit, due to a bug, for early times. There is + * currently no limit. + * + * March 17, 1998: Added code to make sure big + dates are big + AD years, and + * big - dates are big + BC years. + */ +public class CalendarLimitTest extends IntlTest +{ + // This number determined empirically; this is the old limit, + // which we test for to make sure it isn't there anymore. + static final long EARLIEST_SUPPORTED_MILLIS = -210993120000000L; + + static final int EPOCH_JULIAN_DAY = 2440588; // Jaunary 1, 1970 (Gregorian) + static final int JAN_1_1_JULIAN_DAY = 1721426; // January 1, year 1 (Gregorian) + + // Useful millisecond constants + static final int ONE_SECOND = 1000; + static final int ONE_MINUTE = 60*ONE_SECOND; + static final int ONE_HOUR = 60*ONE_MINUTE; + static final int ONE_DAY = 24*ONE_HOUR; + static final int ONE_WEEK = 7*ONE_DAY; + static final long ONE_YEAR = (long)(365.2425 * ONE_DAY); + + static long ORIGIN; // This is the *approximate* point at which BC switches to AD + + public static void main(String argv[]) throws Exception { + new CalendarLimitTest().run(argv); + } + + /** + * Converts Julian day to time as milliseconds. + * @param julian the given Julian day number. + * @return time as milliseconds. + */ + private static final long julianDayToMillis(long julian) { + return (julian - EPOCH_JULIAN_DAY) * ONE_DAY; + } + + /** + * Verify that the given time is processed without problem. + * @return the adjust year, with 0 = 1 BC, -1 = 2 BC, etc. + */ + int test(long millis, Calendar cal, DateFormat fmt) + { + Exception exception = null; + String theDate = ""; + try { + Date d= new Date(millis); + cal.setTime(d); + theDate = fmt.format(d); + } + catch (IllegalArgumentException e) { + exception = e; + } + String s = "0x" + Long.toHexString(millis) + " " + theDate; + + int era=cal.get(Calendar.ERA), year=cal.get(Calendar.YEAR), + dom=cal.get(Calendar.DATE), mon=cal.get(Calendar.MONTH); + + cal.clear(); + cal.set(year, mon, dom); + cal.set(Calendar.ERA, era); + Date rt = cal.getTime(); + + boolean ok = true; + if (exception != null) { + errln("FAIL: Exception " + s); + ok = false; + } + if (((millis >= ORIGIN) && (era != GregorianCalendar.AD)) || + ((millis < ORIGIN) && (era != GregorianCalendar.BC)) || + (year < 1)) { + errln("FAIL: Bad year/era " + s); + ok = false; + } + if (dom<1 || dom>31) { + errln("FAIL: Bad DOM " + s); + ok = false; + } + if (Math.abs(millis - rt.getTime()) > ONE_DAY) { + errln("FAIL: RT fail " + s + " -> 0x" + + Long.toHexString(rt.getTime()) + " " + + fmt.format(rt)); + ok = false; + } + if (ok) logln(s); + if (era==GregorianCalendar.BC) year = 1-year; + return year; + } + + public void TestCalendarLimit() + { + ORIGIN = julianDayToMillis(JAN_1_1_JULIAN_DAY); + + Calendar cal = Calendar.getInstance(); + // You must set the time zone to GMT+0 or the edge cases like + // Long.MIN_VALUE, Long.MAX_VALUE, and right around the threshold + // won't work, since before converting to fields the calendar code + // will add the offset for the zone. + cal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca")); + + DateFormat dateFormat = DateFormat.getDateInstance(); + dateFormat.setCalendar(cal); // Make sure you do this -- same reason as above + ((SimpleDateFormat)dateFormat).applyPattern("MMM d, yyyy G"); + + // Don't expect any failure for positive longs + int lastYear=0; + boolean first=true; + for (long m = Long.MAX_VALUE; m > 0; m >>= 1) + { + int y = test(m, cal, dateFormat); + if (!first && y > lastYear) + errln("FAIL: Years should be decreasing " + lastYear + " " + y); + first = false; + lastYear = y; + } + + // Expect failures for negative millis below threshold + first = true; + for (long m = Long.MIN_VALUE; m < 0; m /= 2) // Don't use m >>= 1 + { + int y = test(m, cal, dateFormat); + if (!first && y < lastYear) + errln("FAIL: Years should be increasing " + lastYear + " " + y); + first = false; + lastYear = y; + } + + // Test right around the threshold + test(EARLIEST_SUPPORTED_MILLIS, cal, dateFormat); + test(EARLIEST_SUPPORTED_MILLIS-1, cal, dateFormat); + + // Test a date that should work + test(Long.MIN_VALUE + ONE_DAY, cal, dateFormat); + + // Try hours in the earliest day or two + // JUST FOR DEBUGGING: + if (false) { + ((SimpleDateFormat)dateFormat).applyPattern("H:mm MMM d, yyyy G"); + for (int dom=2; dom<=3; ++dom) { + for (int h=0; h<24; ++h) { + cal.clear(); + cal.set(Calendar.ERA, GregorianCalendar.BC); + cal.set(292269055, Calendar.DECEMBER, dom, h, 0); + Date d = cal.getTime(); + cal.setTime(d); + logln("" + h + ":00 Dec "+dom+", 292269055 BC -> " + + Long.toHexString(d.getTime()) + " -> " + + dateFormat.format(cal.getTime())); + } + } + // Other way + long t = 0x80000000018c5c00L; // Dec 3, 292269055 BC + while (t<0) { + cal.setTime(new Date(t)); + logln("0x" + Long.toHexString(t) + " -> " + + dateFormat.format(cal.getTime())); + t -= ONE_HOUR; + } + } + } +} + +//eof diff --git a/jdk/test/java/util/Calendar/CalendarRegression.java b/jdk/test/java/util/Calendar/CalendarRegression.java new file mode 100644 index 00000000000..baae13f14fd --- /dev/null +++ b/jdk/test/java/util/Calendar/CalendarRegression.java @@ -0,0 +1,2496 @@ +/* + * 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 + * 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 4031502 4035301 4040996 4051765 4059654 4061476 4070502 4071197 4071385 + * 4073929 4083167 4086724 4092362 4095407 4096231 4096539 4100311 4103271 + * 4106136 4108764 4114578 4118384 4125881 4125892 4136399 4141665 4142933 + * 4145158 4145983 4147269 4149677 4162587 4165343 4166109 4167060 4173516 + * 4174361 4177484 4197699 4209071 4288792 4328747 4413980 4546637 4623997 + * 4685354 4655637 4683492 4080631 4080631 4167995 4340146 4639407 + * 4652815 4652830 4740554 4936355 4738710 4633646 4846659 4822110 4960642 + * 4973919 4980088 4965624 5013094 5006864 8152077 + * @library /java/text/testlib + */ + +import java.lang.reflect.*; +import java.io.*; +import java.util.*; +import java.text.*; + +public class CalendarRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new CalendarRegression().run(args); + } + + /* + 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 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 + * @param date The date to start from + */ + public static Date getAssociatedDate(Date d) { + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(d); + //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH + // cal.getTime(); // <--- REMOVE THIS TO SEE BUG + while (true) { + int wd = cal.get(Calendar.DAY_OF_WEEK); + if (wd == Calendar.SATURDAY || wd == Calendar.SUNDAY) { + cal.add(Calendar.DATE, 1); + // cal.getTime(); + } + else + break; + } + return cal.getTime(); + } + + public void Test4071197() { + dowTest(false); + dowTest(true); + } + + void dowTest(boolean lenient) { + GregorianCalendar cal = new GregorianCalendar(); + cal.set(1997, Calendar.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); + logln(cal.getTime().toString()); + if (min != Calendar.SUNDAY || max != Calendar.SATURDAY) + errln("FAIL: Min/max bad"); + if (dow < min || dow > max) + errln("FAIL: Day of week " + dow + " out of range"); + if (dow != Calendar.SUNDAY) + errln("FAIL: Day of week should be SUNDAY Got " + dow); + } + + public void Test4071385() { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(98, Calendar.JUNE, 24)); + cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field + logln(cal.getTime().toString()); + if (!cal.getTime().equals(new Date(98, Calendar.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) + errln("Fail: Calendar not initialized"); + } + + public void Test4083167() { + TimeZone saveZone = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + 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); + + logln("Current time: " + firstDate.toString()); + + 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); + if (firstMillisInDay != millisInDay) { + errln("Day has shifted " + lastDate); + } + } + } + finally { + TimeZone.setDefault(saveZone); + } + } + + public void Test4086724() { + SimpleDateFormat date; + TimeZone saveZone = TimeZone.getDefault(); + Locale saveLocale = Locale.getDefault(); + + String summerTime = "British Summer Time"; + String standardTime = "Greenwich Mean Time"; + try { + Locale.setDefault(Locale.UK); + TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); + date = new SimpleDateFormat("zzzz"); + + Calendar cal=Calendar.getInstance(); + cal.set(1997,Calendar.SEPTEMBER,30); + Date now=cal.getTime(); + String formattedDate = date.format(now); + if (!formattedDate.equals(summerTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 40) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + cal.set(1996,Calendar.DECEMBER,31); + now=cal.getTime(); + formattedDate = date.format(now); + if (!formattedDate.equals(standardTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 1) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + cal.set(1997,Calendar.JANUARY,1); + now=cal.getTime(); + formattedDate = date.format(now); + if (!formattedDate.equals(standardTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 1) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + cal.set(1997,Calendar.JANUARY,8); + now=cal.getTime(); + formattedDate = date.format(now); + if (!formattedDate.equals(standardTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 2) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + } + finally { + Locale.setDefault(saveLocale); + TimeZone.setDefault(saveZone); + } + } + + public void Test4092362() { + GregorianCalendar cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40); + /*cal1.set( Calendar.YEAR, 1997 ); + cal1.set( Calendar.MONTH, 10 ); + cal1.set( Calendar.DATE, 11 ); + cal1.set( Calendar.HOUR, 10 ); + 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++ ); + + GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40); + /*cal2.set( Calendar.YEAR, 1997 ); + cal2.set( Calendar.MONTH, 10 ); + cal2.set( Calendar.DATE, 11 ); + cal2.set( Calendar.HOUR, 10 ); + 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 ) ) + 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) + errln("Fail: Want THURSDAY Got " + dow); + } + + public void Test4096231() { + TimeZone GMT = TimeZone.getTimeZone("GMT"); + TimeZone PST = TimeZone.getTimeZone("PST"); + int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997; + + Calendar cal1 = new GregorianCalendar(PST); + cal1.setTime(new Date(880698639000L)); + int p; + logln("PST 1 is: " + (p=cal1.get(cal1.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))); + cal1.setTime(new Date(880698639000L)); + logln("GMT 2 is: " + (h2=cal1.get(cal1.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) + 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(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)); + + 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())); + 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)); + // 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) + errln("Fail: Calendar zone behavior faulty"); + } + + public void Test4096539() { + 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 = "); + + gc.add(Calendar.MONTH, 1); + logln((m2=gc.get(Calendar.MONTH)+1)+"/"+ + gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR) + ); + int m = (m1 % 12) + 1; + if (m2 != m) + errln("Fail: Want " + m + " Got " + m2); + } + + } + + public void Test4100311() { + GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance(); + cal.set(Calendar.YEAR, 1997); + cal.set(Calendar.DAY_OF_YEAR, 1); + Date d = cal.getTime(); // Should be Jan 1 + logln(d.toString()); + if (cal.get(Calendar.DAY_OF_YEAR) != 1) + errln("Fail: DAY_OF_YEAR not set"); + } + + public void Test4103271() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + SimpleDateFormat sdf = new SimpleDateFormat(); + int numYears=40, startYear=1997, numDays=15; + String output, testDesc; + 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++) { + 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 53) { + Date d = testCal.getTime(); + calWOY = String.valueOf(actWOY); + output = testDesc + " - " + sdf.format(d) + "\t"; + output = output + "\t" + calWOY; + logln(output); + fail = true; + } + } + } + } + } + + int[] DATA = { + 3, 52, 52, 52, 52, 52, 52, 52, + 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 (!after.equals(testCal.getTime())) { + logln("\tFAIL\n\t\texp: " + after); + fail = true; + } 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 (!before.equals(testCal.getTime())) { + logln("\tFAIL\n\t\texp: " + before); + fail = true; + } + else logln("\tOK"); + } + + if (fail) { + errln("Fail: Week of year misbehaving"); + } + } + + 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); + } + } + } + + /** + * This is a bug in the validation code of GregorianCalendar. As reported, + * the bug seems worse than it really is, due to a bug in the way the bug + * report test was written. In reality the bug is restricted to the DAY_OF_YEAR + * field. - liu 6/29/98 + */ + public void Test4147269() { + final String[] fieldName = { + "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" + }; + 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++) { + 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; + 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) {} + } + } + + /** + * Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE) + * doesn't behave as a pure Julian calendar. + * CANNOT REPRODUCE THIS BUG + */ + public void Test4149677() { + TimeZone[] zones = { TimeZone.getTimeZone("GMT"), + TimeZone.getTimeZone("PST"), + TimeZone.getTimeZone("EAT") }; + for (int i=0; i0) logln("---"); + + cal.clear(); + cal.set(1998, Calendar.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); + d = cal.getTime(); + String sPlus = d.toString(); + logln("+ " + i + ": " + sPlus); + + cal.clear(); + cal.set(1998, Calendar.APRIL, 6, i-24, 0); + d = cal.getTime(); + String sMinus = d.toString(); + logln("- " + i + ": " + sMinus); + + if (!s0.equals(sPlus) || !s0.equals(sMinus)) { + errln("Fail: All three lines must match"); + } + } + } + finally { + TimeZone.setDefault(savedTz); + } + } + + /** + * Adding 12 months behaves differently from adding 1 year + */ + public void Test4165343() { + GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29); + Date start = calendar.getTime(); + logln("init date: " + start); + calendar.add(Calendar.MONTH, 12); + Date date1 = calendar.getTime(); + logln("after adding 12 months: " + date1); + calendar.setTime(start); + calendar.add(Calendar.YEAR, 1); + Date date2 = calendar.getTime(); + logln("after adding one year : " + date2); + if (date1.equals(date2)) { + logln("Test passed"); + } else { + errln("Test failed"); + } + } + + /** + * GregorianCalendar.getActualMaximum() does not account for first day of week. + */ + 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 + */ + boolean passed = true; + int field = Calendar.WEEK_OF_MONTH; + + GregorianCalendar calendar = new GregorianCalendar(Locale.US); + calendar.set(1998, Calendar.MARCH, 1); + calendar.setMinimalDaysInFirstWeek(1); + logln("Date: " + calendar.getTime()); + + int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH); + + for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) { + calendar.setFirstDayOfWeek(firstInWeek); + int returned = calendar.getActualMaximum(field); + 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")); + + if (returned != expected) { + passed = false; + } + } + if (!passed) { + errln("Test failed"); + } + } + + /** + * Calendar.getActualMaximum(YEAR) works wrong. + * + * Note: Before 1.5, this test case assumed that + * setGregorianChange didn't change object's date. But it was + * changed. See 4928615. + */ + public void Test4167060() { + int field = Calendar.YEAR; + DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G", + Locale.US); + + int[][] dates = { + // year, month, day of month + { 100, Calendar.NOVEMBER, 1 }, + { -99 /*100BC*/, Calendar.JANUARY, 1 }, + { 1996, Calendar.FEBRUARY, 29 }}; + + String[] id = { "Hybrid", "Gregorian", "Julian" }; + + for (int k=0; k<3; ++k) { + logln("--- " + id[k] + " ---"); + + for (int j = 0; j < dates.length; ++j) { + GregorianCalendar calendar = new GregorianCalendar(); + if (k == 1) { + calendar.setGregorianChange(new Date(Long.MIN_VALUE)); + } else if (k == 2) { + calendar.setGregorianChange(new Date(Long.MAX_VALUE)); + } + calendar.set(dates[j][0], dates[j][1], dates[j][2]); + format.setCalendar((Calendar)calendar.clone()); + + Date dateBefore = calendar.getTime(); + + int maxYear = calendar.getActualMaximum(field); + logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime())); + logln("date before: " + format.format(dateBefore)); + + int years[] = {2000, maxYear-1, maxYear, maxYear+1}; + + for (int i = 0; i < years.length; i++) { + boolean valid = years[i] <= maxYear; + calendar.set(field, years[i]); + Date dateAfter = calendar.getTime(); + int newYear = calendar.get(field); + calendar.setTime(dateBefore); // restore calendar for next use + + 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]) { + errln(" FAIL: " + newYear + " should be invalid"); + } + } + } + } + } + + /** + * Calendar.roll broken + * This bug relies on the TimeZone bug 4173604 to also be fixed. + */ + public void Test4173516() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + int fieldsList[][] = { + { 1997, Calendar.FEBRUARY, 1, 10, 45, 15, 900 }, + { 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 }, + // test case for 4960642 with default cutover + { 1582, Calendar.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" + }; + + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + int limit = 40; + + try { + GregorianCalendar cal = new GregorianCalendar(); + + cal.setTime(new Date(0)); + cal.roll(Calendar.HOUR, 0x7F000000); + cal.roll(Calendar.HOUR, -0x7F000000); + if (cal.getTime().getTime() != 0) { + 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 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); + } + } + } + } + } + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + public void Test4174361() { + GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29); + + calendar.add(Calendar.MONTH, 10); + Date date1 = calendar.getTime(); + int d1 = calendar.get(Calendar.DAY_OF_MONTH); + + calendar = new GregorianCalendar(1996, 1, 29); + calendar.add(Calendar.MONTH, 11); + Date date2 = calendar.getTime(); + int d2 = calendar.get(Calendar.DAY_OF_MONTH); + + if (d1 != d2) { + errln("adding months to Feb 29 broken"); + } + } + + /** + * Calendar does not update field values when setTimeZone is called. + */ + public void Test4177484() { + TimeZone PST = TimeZone.getTimeZone("PST"); + TimeZone EST = TimeZone.getTimeZone("EST"); + + 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); + cal.setTimeZone(EST); + int h2 = cal.get(Calendar.HOUR_OF_DAY); + if (h1 == h2) { + errln("FAIL: Fields not updated after setTimeZone"); + } + + // getTime() must NOT change when time zone is changed. + // getTime() returns zone-independent time in ms. + cal.clear(); + cal.setTimeZone(PST); + cal.set(Calendar.HOUR_OF_DAY, 10); + Date pst10 = cal.getTime(); + cal.setTimeZone(EST); + Date est10 = cal.getTime(); + if (!pst10.equals(est10)) { + errln("FAIL: setTimeZone changed time"); + } + } + + /** + * Week of year is wrong at the start and end of the year. + */ + public void Test4197699() { + GregorianCalendar cal = new GregorianCalendar(); + cal.setFirstDayOfWeek(Calendar.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, + }; + + for (int i=0; i " + actual + + ", want " + DATA[i+1]); + } + } + } + + public void Test4288792() throws Exception + { + TimeZone savedTZ = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + GregorianCalendar cal = new GregorianCalendar(); + try { + 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++) { + // 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); + + for (int k = 1; k < 7; k++) { + cal.add(Calendar.DATE, 1); + int WOY = cal.get(Calendar.WEEK_OF_YEAR); + if (WOY != maxWeek) { + errln(cal.getTime() + ",got=" + WOY + + ",expected=" + maxWeek + + ",min=" + j1 + ",first=" + j); + } + } + + cal.add(Calendar.DATE, 1); + int WOY = cal.get(Calendar.WEEK_OF_YEAR); + if (WOY != 1) { + errln(cal.getTime() + ",got=" + WOY + + ",expected=1,min=" + j1 + ",first" + j); + } + } + } + } + } + finally { + TimeZone.setDefault(savedTZ); + } + } + + public void Test4328747() throws Exception { + Calendar c = (Calendar)Calendar.getInstance(Locale.US); + c.clear(); + c.set(1966,0,1); // 1 jan 1966 + + // serialize + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream s = new ObjectOutputStream(out); + s.writeObject(c); + s.flush(); + + // deserialize + ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); + 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)) { + errln("deserialized Calendar returned wrong date field(s): " + + result.get(c.YEAR) + "/" + result.get(c.MONTH) + "/" + result.get(c.DATE) + + ", expected 1966/0/1"); + } + } + + /** + * Test whether Calendar can be serialized/deserialized correctly + * even if invalid/customized TimeZone is used. + */ + public void Test4413980() { + TimeZone savedTimeZone = TimeZone.getDefault(); + try { + boolean pass = true; + 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(); + + // serialize + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream s = new ObjectOutputStream(out); + s.writeObject(c); + s.flush(); + + // deserialize + ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); + + if (!c.equals(t.readObject())) { + pass = false; + 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."); + } + } + if (!pass) { + errln("Fail: Calendar serialization/equality bug"); + } + } + catch (IOException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + catch (ClassNotFoundException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + finally { + TimeZone.setDefault(savedTimeZone); + } + } + + /** + * 4546637: Incorrect WEEK_OF_MONTH after changing First Day Of Week + */ + public void Test4546637() { + GregorianCalendar day = new GregorianCalendar (2001, Calendar.NOVEMBER, 04); + day.setMinimalDaysInFirstWeek(1); + int wom = day.get(Calendar.WEEK_OF_MONTH); + + day.setFirstDayOfWeek(Calendar.MONDAY); + if (day.get(Calendar.WEEK_OF_MONTH) != 1) { + errln("Fail: 2001/11/4 must be the first week of the month."); + } + } + + /** + * 4623997: GregorianCalendar returns bad WEEK_OF_YEAR + */ + public void Test4623997() { + GregorianCalendar cal = new GregorianCalendar(2000, GregorianCalendar.JANUARY, 1); + + int dow = cal.get(GregorianCalendar.DAY_OF_WEEK); + + cal.setFirstDayOfWeek(GregorianCalendar.MONDAY); + cal.setMinimalDaysInFirstWeek(4); + + if (cal.get(GregorianCalendar.WEEK_OF_YEAR) != 52) { + errln("Fail: 2000/1/1 must be the 52nd week of the year."); + } + } + + /** + * 4685354: Handling of Calendar fields setting state is broken + * + *

    Need to use SimpleDateFormat to test because a call to + * get(int) changes internal states of a Calendar. + */ + public void Test4685354() { + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + Calendar calendar = Calendar.getInstance(Locale.US); + DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); + String expected = "1999/12/31"; + Date t; + String s; + + try { + calendar.setTime(df.parse(expected)); + } catch (Exception e) { + throw new RuntimeException("Unexpected parse exception", e); + } + + t = calendar.getTime(); + calendar.set(Calendar.DAY_OF_MONTH, 33); + t = calendar.getTime(); + calendar.set(Calendar.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); + } + + // The same thing must work with ZONE_OFFSET set + try { + calendar.setTime(df.parse(expected)); + } catch (Exception e) { + 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); + t = calendar.getTime(); + calendar.set(Calendar.DAY_OF_MONTH, 0); + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("DAY_OF_MONTH: expected: " + expected + ", got: " + s); + } + + expected = "1999/12/24"; // 0th week of 2000 + calendar.clear(); + Date initialDate = null; + try { + initialDate = df.parse(expected); + calendar.setTime(initialDate); + } catch (Exception e) { + throw new RuntimeException("Unexpected parse exception", e); + } + t = calendar.getTime(); + calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); + // jump to the next year + calendar.set(Calendar.WEEK_OF_YEAR, 100); + t = calendar.getTime(); + calendar.set(Calendar.WEEK_OF_YEAR, 0); + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("WEEK_OF_YEAR: expected: " + expected + ", got: " + s); + } + // change the state back + calendar.clear(); + calendar.setTime(initialDate); + calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); + // jump to next month + calendar.set(Calendar.WEEK_OF_MONTH, 7); + t = calendar.getTime(); + calendar.set(Calendar.WEEK_OF_MONTH, 0); + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("WEEK_OF_MONTH: expected: " + expected + ", got: " + s); + } + + // Make sure the time fields work correctly. + calendar.clear(); + df = new SimpleDateFormat("HH:mm:ss"); + TimeZone tz = TimeZone.getTimeZone("GMT"); + df.setTimeZone(tz); + calendar.setTimeZone(tz); + expected = "22:59:59"; + try { + calendar.setTime(df.parse(expected)); + } catch (Exception e) { + throw new RuntimeException("Unexpected parse exception", e); + } + t = calendar.getTime(); + // time should be 22:59:59. + calendar.set(Calendar.MINUTE, 61); + // time should be 23:01:59. + t = calendar.getTime(); + calendar.set(Calendar.MINUTE, -1); + // time should be back to 22:59:59. + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("MINUTE: expected: " + expected + ", got: " + s); + } + } + + /** + * 4655637: Calendar.set() for DAY_OF_WEEK does not return the right value + * + *

    Need to use SimpleDateFormat to test because a call to + * get(int) changes internal states of a Calendar. + */ + public void Test4655637() { + // Skip this test case if it's Thai locale + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(1029814211523L)); + cal.set(Calendar.YEAR, 2001); + Date t = cal.getTime(); + cal.set(Calendar.MONTH, Calendar.JANUARY); + t = cal.getTime(); + + cal.set(Calendar.DAY_OF_MONTH, 8); + t = cal.getTime(); + + cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); + String expected = "2001/01/08"; + String s = df.format(cal.getTime()); + if (!expected.equals(s)) { + errln("expected: " + expected + ", got: " + s); + } + } + + /** + * 4683492: Invalid value for MONTH in GregorianCalendar causes exception in getTime(). + * + *

    Need to use SimpleDateFormat to test because a call to + * get(int) changes internal states of a Calendar. + * + *

    This test case throws ArrayIndexOutOfBoundsException without the fix. + */ + 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); + DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); + String expected = "2003/01/31"; + String s = df.format(cal.getTime()); + if (!expected.equals(s)) { + errln("expected: " + expected + ", got: " + s); + } + } + + /** + * 4080631: Calendar.hashCode is amazingly bad + */ + public void Test4080631() { + Calendar cal = Calendar.getInstance(); + int h1 = cal.hashCode(); + cal.add(cal.SECOND, +1); + int h2 = cal.hashCode(); + Calendar cal2 = (Calendar) cal.clone(); + cal.add(cal.MILLISECOND, +1); + int h3 = cal.hashCode(); + logln("hash code: h1="+h1+", h2="+h2+", h3="+h3); + if (h1 == h2 || h1 == h3 || h2 == h3) { + errln("hash code is poor: hashCode="+h1); + } + h2 = cal2.hashCode(); + cal.add(cal.MILLISECOND, -1); + int h4 = cal.hashCode(); + logln("hash code: h2="+h2+", h4="+h4); + if (cal.equals(cal2) && h2 != h4) { + errln("broken hash code: h2="+h2+", h4="+h4); + } + int x = cal.getFirstDayOfWeek() + 3; + if (x > cal.SATURDAY) { + x -= 7; + } + cal.setFirstDayOfWeek(x); + int h5 = cal.hashCode(); + logln("hash code: h4="+h4+", h5="+h5); + if (h4 == h5) { + errln("has code is poor with first day of week param: hashCode="+h4); + } + } + + /** + * 4125161: RFE: GregorianCalendar needs more era names (BCE and CE) + */ + /* + public void Test4125161() throws Exception { + Class gc = GregorianCalendar.class; + Field f; + int mod; + f = gc.getDeclaredField("BCE"); + mod = f.getModifiers(); + if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) { + errln("BCE: wrong modifiers: " + mod); + } + f = gc.getDeclaredField("CE"); + mod = f.getModifiers(); + if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) { + errln("CE: wrong modifiers: " + mod); + } + if (GregorianCalendar.BCE != GregorianCalendar.BC + || GregorianCalendar.CE != GregorianCalendar.AD) { + errln("Wrong BCE and/or CE values"); + } + } + */ + + /** + * 4167995: GregorianCalendar.setGregorianChange() not to spec + */ + public void Test4167995() { + 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)) { + 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)) { + 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)) { + 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)) { + 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)) { + 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)) { + errln(gc.getMessage()); + } + } + + /** + * 4340146: Calendar.equals modifies state + */ + public void Test4340146() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.set(2003, cal.OCTOBER, 32); + cal.equals(new Koyomi()); + if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) { + errln(cal.getMessage()); + } + new Koyomi().equals(cal); + if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) { + errln(cal.getMessage()); + } + } + + /** + * 4639407: GregorianCalendar doesn't work in non-lenient due to timezone bounds checking + */ + public void Test4639407() { + // The following operations in non-lenient mode shouldn't + // throw IllegalArgumentException. + Koyomi cal = new Koyomi(TimeZone.getTimeZone("Pacific/Kiritimati")); + cal.setLenient(false); + cal.set(2003, cal.OCTOBER, 10); + cal.getTime(); + cal.setTimeZone(TimeZone.getTimeZone("Pacific/Tongatapu")); + cal.set(2003, cal.OCTOBER, 10); + cal.getTime(); + } + + /** + * 4652815: rolling week-of-year back hundreds of weeks changes year + */ + 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); + } + + private void testRoll(Koyomi cal, int year, int month, int dayOfMonth) { + cal.clear(); + cal.set(year, month, dayOfMonth); + 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)) { + 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)) { + errln(cal.getMessage()); + } + } + } + + /** + * 4652830: GregorianCalendar roll behaves unexpectedly for dates in BC era + */ + public void Test4652830() { + 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) { + errln(" wrong actual max of DAY_OF_YEAR: got " + + cal.getActualMaximum(cal.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)) { + errln(cal.getMessage()); + } + cal.roll(cal.DAY_OF_MONTH, +1); + if (!cal.checkFieldValue(cal.ERA, cal.BC) + || !cal.checkDate(9, cal.FEBRUARY, 1)) { + errln(cal.getMessage()); + } + } + + /** + * 4740554: GregorianCalendar.getActualMaximum is inconsistent with normalization + */ + public void Test4740554() { + 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)) { + errln(cal.getMessage()); + } + if (!cal.checkActualMaximum(cal.DAY_OF_MONTH, 29)) { + errln(cal.getMessage()); + } + } + + /** + * 4936355: GregorianCalendar causes overflow/underflow with time of day calculation + */ + 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.clear(); + cal.set(1970, cal.JANUARY, 1); + checkTimeCalculation(cal, 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.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.clear(); + cal.set(250000, cal.JANUARY, 1); + checkTimeCalculation(cal, 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); + } + + private void checkTimeCalculation(Koyomi cal, int field, int value, long expectedDelta) { + long time = cal.getTimeInMillis(); + cal.set(field, value); + long time2 = cal.getTimeInMillis(); + 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)); + } + } + + /** + * 4722650: Calendar.equals can throw an exception in non-lenient + * (piggy-back tests for compareTo() which is new in 1.5) + */ + public void Test4722650() { + Calendar cal1 = new GregorianCalendar(); + cal1.clear(); + Calendar cal2 = new GregorianCalendar(); + cal2.clear(); + cal2.setLenient(false); + + cal1.set(2003, Calendar.OCTOBER, 31); + cal2.set(2003, Calendar.OCTOBER, 31); + try { + if (cal1.equals(cal2)) { + errln("lenient and non-lenient shouldn't be equal. (2003/10/31)"); + } + if (cal1.compareTo(cal2) != 0) { + errln("cal1 and cal2 should represent the same time. (2003/10/31)"); + } + } catch (IllegalArgumentException e) { + errln("equals threw IllegalArugumentException with non-lenient"); + } + + cal1.set(2003, Calendar.OCTOBER, 32); + cal2.set(2003, Calendar.OCTOBER, 32); + try { + if (cal1.equals(cal2)) { + errln("lenient and non-lenient shouldn't be equal. (2003/10/32)"); + } + if (cal1.compareTo(cal2) != 0) { + errln("cal1 and cal2 should represent the same time. (2003/10/32)"); + } + } catch (IllegalArgumentException e) { + errln("equals threw IllegalArugumentException with non-lenient"); + } + + cal1 = Calendar.getInstance(new Locale("th", "TH")); + cal1.setTimeInMillis(0L); + cal2 = Calendar.getInstance(Locale.US); + cal2.setTimeInMillis(0L); + if (cal1.equals(cal2)) { + errln("Buddhist.equals(Gregorian) shouldn't be true. (millis=0)"); + } + if (cal1.compareTo(cal2) != 0) { + errln("cal1 (Buddhist) and cal2 (Gregorian) should represent the same time. (millis=0)"); + } + } + + /** + * 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); + 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 (cal0.after(cal2)) { + errln("cal0 shouldn't be after cal2"); + } + if (cal2.before(cal0)) { + errln("cal2 shouldn't be before cal0"); + } + + if (cal0.after(new Integer(0))) { + errln("cal0.after() returned true with an Integer."); + } + if (cal0.before(new Integer(0))) { + errln("cal0.before() returned true with an Integer."); + } + if (cal0.after(null)) { + errln("cal0.after() returned true with null."); + } + if (cal0.before(null)) { + errln("cal0.before() returned true with null."); + } + } + + /** + * 4633646: Setting WEEK_OF_MONTH to 1 results in incorrect date + */ + public void Test4633646() { + Koyomi cal = new Koyomi(Locale.US); + cal.setTime(new Date(2002-1900, 1-1, 28)); + sub4633646(cal); + + cal.setLenient(false); + cal.setTime(new Date(2002-1900, 1-1, 28)); + sub4633646(cal); + + cal = new Koyomi(Locale.US); + cal.clear(); + cal.set(2002, cal.JANUARY, 28); + sub4633646(cal); + + cal.clear(); + cal.setLenient(false); + cal.set(2002, cal.JANUARY, 28); + sub4633646(cal); + } + + void sub4633646(Koyomi cal) { + cal.getTime(); + cal.set(cal.WEEK_OF_MONTH, 1); + if (cal.isLenient()) { + if (!cal.checkDate(2001, cal.DECEMBER, 31)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(cal.WEEK_OF_MONTH, 6)) { + errln(cal.getMessage()); + } + } else { + try { + Date d = cal.getTime(); + errln("didn't throw IllegalArgumentException in non-lenient"); + } catch (IllegalArgumentException e) { + } + } + } + + /** + * 4846659: Calendar: Both set() and roll() don't work for AM_PM time field + * (Partially fixed only roll as of 1.5) + */ + public void Test4846659() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.set(2003, cal.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)) { + errln("roll: AM_PM didn't change to PM"); + } + + cal.clear(); + cal.set(2003, cal.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)) { + errln("set: AM_PM didn't change to PM"); + } + + cal.clear(); + cal.set(2003, cal.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)) { + errln("set: both AM_PM and HOUT didn't change to PM"); + } + } + + /** + * 4822110: GregorianCalendar.get() returns an incorrect date after setFirstDayOfWeek() + */ + public void Test4822110() { + Koyomi cal = new Koyomi(Locale.US); + // June 2003 + // S M Tu W Th F S + // 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 + cal.clear(); + // 6/1 to 6/7 should be the 1st week of June. + cal.set(2003, cal.JUNE, 2); + cal.getTime(); // Let cal calculate time. + cal.setFirstDayOfWeek(cal.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("1st Sunday of June 2003 with FirstDayOfWeek=MONDAY"); + if (!cal.checkDate(2003, cal.JUNE, 8)) { + errln(cal.getMessage()); + } + } + + /** + * 4973919: Inconsistent GregorianCalendar hashCode before and after serialization + */ + public void Test4966499() throws Exception { + GregorianCalendar date1 = new GregorianCalendar(2004, Calendar.JANUARY, 7); + + // Serialize date1 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(date1); + + byte[] buffer = baos.toByteArray(); + + // Deserialize it + ByteArrayInputStream bais = new ByteArrayInputStream(buffer); + ObjectInputStream ois = new ObjectInputStream(bais); + 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())+")"); + } + } + + /** + * 4980088: GregorianCalendar.getActualMaximum doesn't throw exception + */ + public void Test4980088() { + GregorianCalendar cal = new GregorianCalendar(); + try { + int x = cal.getMaximum(100); + errln("getMaximum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getMaximum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getLeastMaximum(100); + errln("getLeastMaximum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getLeastMaximum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getActualMaximum(100); + errln("getActualMaximum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getActualMaximum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getMinimum(100); + errln("getMinimum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getMinimum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getGreatestMinimum(100); + errln("getGreatestMinimum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getGreatestMinimum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getActualMinimum(100); + errln("getActualMinimum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getActualMinimum: " + e.getClass().getName() + ": " + e.getMessage()); + } + } + + /** + * 4965624: GregorianCalendar.isLeapYear(1000) returns incorrect value + */ + public void Test4965624() { + // 5013094: This test case needs to use "GMT" to specify + // Gregorian cutover dates. + 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); + + Iterator itr = data.keySet().iterator(); + while (itr.hasNext()) { + Date d = itr.next(); + boolean expected = data.get(d).booleanValue(); + GregorianCalendar cal = new GregorianCalendar(); + cal.setGregorianChange(d); + if (cal.isLeapYear(1000) != expected) { + errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) + + " with cutover date (Julian) " + d); + } + } + } + finally { + TimeZone.setDefault(savedZone); + } + } + + // Note that we can't use Date to produce Gregorian calendar dates + // before the default cutover date. + static Date getGregorianDate(int year, int month, int dayOfMonth) { + GregorianCalendar g = new GregorianCalendar(); + // Make g a pure Gregorian calendar + g.setGregorianChange(new Date(Long.MIN_VALUE)); + g.clear(); + g.set(year, month, dayOfMonth); + return g.getTime(); + } + + /** + * 5006864: Define the minimum value of DAY_OF_WEEK_IN_MONTH as 1 + */ + public void Test5006864() { + GregorianCalendar cal = new GregorianCalendar(); + int min = cal.getMinimum(cal.DAY_OF_WEEK_IN_MONTH); + if (min != 1) { + errln("GregorianCalendar.getMinimum(DAY_OF_WEEK_IN_MONTH) returned " + + min + ", expected 1."); + } + min = cal.getGreatestMinimum(cal.DAY_OF_WEEK_IN_MONTH); + if (min != 1) { + errln("GregorianCalendar.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH) returned " + + min + ", expected 1."); + } + } +} diff --git a/jdk/test/java/util/Calendar/CalendarTest.java b/jdk/test/java/util/Calendar/CalendarTest.java new file mode 100644 index 00000000000..d8320295a6d --- /dev/null +++ b/jdk/test/java/util/Calendar/CalendarTest.java @@ -0,0 +1,1102 @@ +/* + * 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 + * 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 4064654 4374886 4984320 4984574 4944795 + * @library /java/text/testlib + * @summary test for Calendar + * @key randomness + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class CalendarTest extends IntlTest { + static final int ONE_DAY = 24*60*60*1000; + static final int EPOCH_JULIAN = 2440588; + + public static void main(String argv[]) throws Exception { + new CalendarTest().run(argv); + } + + /** + * Test the behavior of the GregorianCalendar around the changeover. + */ + public void TestGregorianChangeover() { + TimeZone savedZone = TimeZone.getDefault(); + /* + Changeover -7 days: 1582/9/28 dow=6 + Changeover -6 days: 1582/9/29 dow=7 + Changeover -5 days: 1582/9/30 dow=1 + Changeover -4 days: 1582/10/1 dow=2 + Changeover -3 days: 1582/10/2 dow=3 + Changeover -2 days: 1582/10/3 dow=4 + Changeover -1 days: 1582/10/4 dow=5 + Changeover +0 days: 1582/10/15 dow=6 + Changeover +1 days: 1582/10/16 dow=7 + Changeover +2 days: 1582/10/17 dow=1 + Changeover +3 days: 1582/10/18 dow=2 + Changeover +4 days: 1582/10/19 dow=3 + Changeover +5 days: 1582/10/20 dow=4 + 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 }; + // ^ <-Changeover Fri Oct 15 1582 + + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Date co = new Date(1582-1900, Calendar.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); + 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); + + 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 { + TimeZone.setDefault(savedZone); + } + } + + /** + * Test the mapping between millis and fields. For the purposes + * of this test, we don't care about timezones and week data + * (first day of week, minimal days in first week). + */ + 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, + }; + + try { + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + Date PURE_GREGORIAN = new Date(Long.MIN_VALUE); + Date PURE_JULIAN = new Date(Long.MAX_VALUE); + 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 year2, month2, dom2; + long millis = ((long)julian - EPOCH_JULIAN) * ONE_DAY; + String s; + + // Test Gregorian computation + cal.setGregorianChange(PURE_GREGORIAN); + cal.clear(); + cal.set(year, month, dom); + 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) { + errln(s + " FAIL"); + } else { + logln(s); + } + + // Test Julian computation + 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) { + 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) { + auxMapping(cal, y, m, 15); + } + } + } + finally { + TimeZone.setDefault(saveZone); + } + } + private void auxMapping(Calendar cal, int y, int m, int d) { + cal.clear(); + 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); + } + + public void TestGenericAPI() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + String str; + + Date when = new Date(90, Calendar.APRIL, 15); + + String tzid = "TestZone"; + int tzoffset = 123400; + + SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid); + Calendar cal = (Calendar)Calendar.getInstance((SimpleTimeZone)zone.clone()); + + 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 != *cal2)) errln("FAIL: Calendar.operator!= 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"); + + cal.roll(Calendar.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"); + + // C++ only + /* TimeZone z = cal.orphanTimeZone(); + if (z.getID(str) != tzid || + z.getRawOffset() != tzoffset) + errln("FAIL: orphanTimeZone failed"); + */ + + for (int i = 0; i < 2; ++i) { + boolean lenient = ( i > 0 ); + cal.setLenient(lenient); + if (lenient != cal.isLenient()) errln("FAIL: setLenient/isLenient failed"); + // Later: Check for lenient behavior + } + + int i; + for (i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) { + cal.setFirstDayOfWeek(i); + 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"); + } + + for (i = 0; i < Calendar.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)) + errln("FAIL: getLeastMaximum larger than getMaximum for field " + i); + if (cal.getMinimum(i) >= cal.getMaximum(i)) + errln("FAIL: getMinimum not less than getMaximum for field " + i); + } + + cal.setTimeZone(TimeZone.getDefault()); + cal.clear(); + cal.set(1984, 5, 24); + if (cal.getTime().getTime() != new Date(84, 5, 24).getTime()) { + errln("FAIL: Calendar.set(3 args) failed"); + logln(" Got: " + cal.getTime() + " Expected: " + new Date(84, 5, 24)); + } + + cal.clear(); + cal.set(1985, 3, 2, 11, 49); + if (cal.getTime().getTime() != new Date(85, 3, 2, 11, 49).getTime()) { + errln("FAIL: Calendar.set(5 args) failed"); + logln(" Got: " + cal.getTime() + " Expected: " + new Date(85, 3, 2, 11, 49)); + } + + cal.clear(); + cal.set(1995, 9, 12, 1, 39, 55); + if (cal.getTime().getTime() != new Date(95, 9, 12, 1, 39, 55).getTime()) { + errln("FAIL: Calendar.set(6 args) failed"); + logln(" Got: " + cal.getTime() + " Expected: " + new Date(95, 9, 12, 1, 39, 55)); + } + + 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]); + } + cal.clear(i); + 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 { + for (i = 0; i < count; ++i) { + cal = Calendar.getInstance(loc[i]); + // delete cal; + } + } + + cal = Calendar.getInstance(TimeZone.getDefault(), Locale.ENGLISH); + // delete cal; + + cal = Calendar.getInstance(zone, Locale.ENGLISH); + // delete cal; + + GregorianCalendar gc = new GregorianCalendar(zone); + // delete gc; + + gc = new GregorianCalendar(Locale.ENGLISH); + // delete gc; + + gc = new GregorianCalendar(Locale.ENGLISH); + // delete gc; + + gc = new GregorianCalendar(zone, Locale.ENGLISH); + // delete gc; + + gc = new GregorianCalendar(zone); + // delete gc; + + gc = new GregorianCalendar(1998, 10, 14, 21, 43); + 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()) + errln("FAIL: new GregorianCalendar(ymdhms) failed"); + + // C++ only: + // GregorianCalendar gc2 = new GregorianCalendar(Locale.ENGLISH); + // gc2 = gc; + // if (gc2 != gc || !(gc2 == gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed"); + // delete gc; + // delete z; + } + + // Verify Roger Webster's bug + public void TestRog() { + GregorianCalendar gc = new GregorianCalendar(); + + int year = 1997, month = Calendar.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); + + 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)) + errln("FAIL: Date " + gc.getTime() + " wrong"); + } + } + + // Verify DAY_OF_WEEK + public void TestDOW943() { + dowTest(false); + dowTest(true); + } + + void dowTest(boolean lenient) { + GregorianCalendar cal = new GregorianCalendar(); + cal.set(1997, Calendar.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) { + errln("FAIL2: Day of week should be SUNDAY; is " + dow + ": " + cal.getTime()); + } + if (min != Calendar.SUNDAY || max != Calendar.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) { + errln("FAIL: Clones share fields"); + } + } + + // Verify effect of Gregorian cutoff value + public void TestGregorianChange768() { + boolean b; + GregorianCalendar c = new GregorianCalendar(); + logln("With cutoff " + c.getGregorianChange()); + logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800))); + logln(" (should be FALSE)"); + 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(" (should be TRUE)"); + 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; + 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.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(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); + + 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.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.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"); + } + 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) { + logln("PASS: " + msg + c.getTime()); + } + 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"); + } + + // Test the behavior of GMT vs. local time + public void TestGMTvsLocal4064654() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + // Sample output 1: + // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 1 1 12 0 0 + // date = Wed Jan 01 04:00:00 PST 1997 + // offset for Wed Jan 01 04:00:00 PST 1997= -8hr + test4064654(1997, 1, 1, 12, 0, 0); + + // Sample output 2: + // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 4 16 18 30 0 + // date = Wed Apr 16 10:30:00 PDT 1997 + // offset for Wed Apr 16 10:30:00 PDT 1997= -7hr + + // Note that in sample output 2 according to the offset, the gmt time + // of the result would be 1997 4 16 17 30 0 which is different from the + // input of 1997 4 16 18 30 0. + test4064654(1997, 4, 16, 18, 30, 0); + } + void test4064654(int yr, int mo, int dt, int hr, int mn, int sc) { + 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); + + date = gmtcal.getTime(); + 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)); + + 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 expected = ((hr * 60 + mn) * 60 + sc) * 1000; + + 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() { + 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); + // ma feb 03 00:00:00 GMT+00:00 1997 + 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); + // ma feb 03 13:11:06 GMT+00:00 1997 + String s2 = cal.getTime ().toString (); + + if (s.equals(s2)) + logln("Pass: " + s + " == " + s2); + 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 ); + check520(temp, y, m, d); + + temp.add( temp.YEAR, 1 ); + y++; + check520(temp, y, m, d); + + temp.add( temp.MONTH, 1 ); + m++; + check520(temp, y, m, d); + + temp.add( temp.DATE, 1 ); + d++; + check520(temp, y, m, d); + + temp.add( temp.DATE, 2 ); + d += 2; + check520(temp, y, m, d); + + temp.add( temp.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)); + } + else logln("Confirmed: " + + y + "/" + (m+1) + "/" + d); + } + + // Verify that setting fields works. This test fails when an exception is thrown. + public void TestFieldSet4781() { + try { + GregorianCalendar g = new GregorianCalendar(); + 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); + // 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)) + logln("Same"); + else + logln("Different"); + } + catch (IllegalArgumentException e) { + errln("Unexpected exception seen: " + e); + } + } + + // Test serialization of a Calendar object + public void TestSerialize337() { + Calendar cal = Calendar.getInstance(); + + boolean ok = false; + + try { + FileOutputStream f = new FileOutputStream(FILENAME); + ObjectOutput s = new ObjectOutputStream(f); + s.writeObject(PREFIX); + s.writeObject(cal); + s.writeObject(POSTFIX); + f.close(); + + 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(); + in.close(); + + ok = pre.equals(PREFIX) && + post.equals(POSTFIX) && + cal.equals(c); + + File fl = new File(FILENAME); + fl.delete(); + } + catch (IOException e) { + errln("FAIL: Exception received:"); + // e.printStackTrace(log); + } + catch (ClassNotFoundException e) { + errln("FAIL: Exception received:"); + // e.printStackTrace(log); + } + + if (!ok) errln("Serialization of Calendar object failed."); + } + static final String PREFIX = "abc"; + static final String POSTFIX = "def"; + static final String FILENAME = "tmp337.bin"; + + // Try to zero out the seconds field + public void TestSecondsZero121() { + 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(); + String s = d.toString(); + if (s.indexOf(":00 ") < 0) errln("Expected to see :00 in " + s); + } + + // Try various sequences of add, set, and get method calls. + public void TestAddSetGet0610() { + // + // Error case 1: + // - Upon initialization calendar fields, millis = System.currentTime + // - After set is called fields are initialized, time is not + // - 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 ) ; + String v = value(calendar); + logln( "1B) " + v ); + logln( "--) 1993/0/5" ) ; + if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } + + // + // Error case 2: + // - 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 ) ; + String v = value(calendar); + logln( "2B) " + v ); + logln( "--) 1993/0/5" ) ; + if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } + + // + // Error case 3: + // - Upon initialization calendar fields, millis = 0 + // - 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 ) ; + String v = value(calendar); + 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 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 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; ) { + 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"); + } + } + } + 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 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" + }; + + // 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() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + 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 */ + }; + + 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}, + }; + + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + + try { + for (int j = 0; j < lt.length; j++) { + Locale l = new Locale(lt[j][0], lt[j][1]); + TimeZone z = TimeZone.getTimeZone(lt[j][2]); + Locale.setDefault(l); + TimeZone.setDefault(z); + Calendar c = Calendar.getInstance(); + Date d = new Date(-z.getRawOffset()); + + int val; + int[] EPOCH_FIELDS = goldenData[j]; + c.setTime(d); + + 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]); + err = true; + } + } + if (err) { + errln("Failed: \n\tDate=" + d + "\n\tTimeZone=" + z + + "\n\tLocale=" + l + "\n\tCalendar=" + c); + } + } + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + } + + // 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); + 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); + 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); + int expectedDOW = 1 + (DOW + delta - 1) % 7; + if (newDOW != expectedDOW) { + errln("Day of week should be " + expectedDOW + + " instead of " + newDOW + " on " + cur.getTime()); + return; + } + } + while (newDOW != initialDOW); + } + + public void TestActualMinMax() { + Calendar cal = new GregorianCalendar(1967, Calendar.MARCH, 10); + cal.setFirstDayOfWeek(Calendar.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)); + + 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(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)); + // 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)); + + cal.set(Calendar.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)); + } + + public void TestRoll() { + Calendar cal = new GregorianCalendar(1997, Calendar.JANUARY, 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]) + 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."); + } + + cal.set(1996, Calendar.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 }; + + 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]) + 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) + "."); + } + + // 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"); + + // 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"); + } + + /* + * Confirm that multiple calls to Calendar.set() works correctly. + */ + public void Test4374886() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + + try { + Locale.setDefault(Locale.US); + 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); + + 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) { + errln("Failed : got " + cal.getTime() + ", expected Mon Jan 22, 2001"); + } + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + } +} + +//eof diff --git a/jdk/test/java/util/Calendar/FieldStateTest.java b/jdk/test/java/util/Calendar/FieldStateTest.java new file mode 100644 index 00000000000..caa6f219a24 --- /dev/null +++ b/jdk/test/java/util/Calendar/FieldStateTest.java @@ -0,0 +1,216 @@ +/* + * 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 + * 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 4860664 4916815 4867075 + * @library /java/text/testlib + * @build Koyomi + * @run main FieldStateTest + * @summary Unit tests for internal fields states. + */ + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import static java.util.Calendar.*; + +public class FieldStateTest extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Locale.setDefault(Locale.US); + + new FieldStateTest().run(args); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + public void TestFieldState() { + Koyomi cal = new Koyomi(); + logln("Right after instantialtion:"); + if (!cal.checkAllSet()) { + errln(cal.getMessage()); + } + + logln("Set date to 2003/10/31 after the instantiation:"); + cal.set(2003, OCTOBER, 31); + // let cal calculate the time + cal.getTime(); + // At this point, all fields have to be recalculated and + // happen to have the set-state from the instantiation. The + // three fields should have "externally set" and the rest of + // the fields have "computed". But we can't distinguish them + // outside the package. + if (!cal.checkAllSet()) { + errln(cal.getMessage()); + } + // Make sure that the correct date was produced. + if (!cal.checkInternalDate(2003, OCTOBER, 31, FRIDAY)) { + errln(cal.getMessage()); + } + + logln("Change to Monday of the week, which is 2003/10/27:"); + cal.set(DAY_OF_WEEK, MONDAY); + cal.getTime(); + if (!cal.checkDate(2003, OCTOBER, 27)) { + errln(cal.getMessage()); + } + + // The same operation didn't work after calling clear() before + // 1.5 because the set-state was just depends on its previous + // operations. After the instantiation, all the fields are set + // to "computed". But after calling clear(), the state becomes + // "unset". + logln("Set to 2003/10/31 after clear():"); + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.getTime(); + cal.set(DAY_OF_WEEK, MONDAY); + if (!cal.checkDate(2003, OCTOBER, 27, MONDAY)) { + errln(cal.getMessage()); + } + + logln("Set to 2003/10/31 after clear(), then to the 51st week of year (12/19):"); + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.getTime(); + cal.set(WEEK_OF_YEAR, 51); + if (!cal.checkFieldValue(WEEK_OF_YEAR, 51)) { + errln(cal.getMessage()); + } + if (!cal.checkDate(2003, DECEMBER, 19, FRIDAY)) { + errln(cal.getMessage()); + } + + logln("Set to 2003/10 Mon of 4th week (10/20: 43rd week of year, 293rd day):"); + cal.clear(); + cal.set(YEAR, 2003); + cal.set(MONTH, OCTOBER); + cal.set(DAY_OF_WEEK, MONDAY); + cal.set(WEEK_OF_MONTH, 4); + cal.getTime(); + if (!cal.checkFieldValue(DAY_OF_MONTH, 20)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(WEEK_OF_YEAR, 43)) { + errln(cal.getMessage()); + } + + logln("Set to 2003/10 Mon of 43rd week of year (10/20: 4th week of month, 293rd day):"); + cal.clear(); + cal.set(YEAR, 2003); + cal.set(DAY_OF_WEEK, MONDAY); + cal.set(WEEK_OF_YEAR, 43); + cal.getTime(); + if (!cal.checkDate(2003, OCTOBER, 20, MONDAY)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(WEEK_OF_MONTH, 4)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) { + errln(cal.getMessage()); + } + + 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)); + cal.set(DAY_OF_WEEK, SUNDAY); + cal.set(2003, OCTOBER, 31); // 2003/10/31 is Friday. + cal.set(ZONE_OFFSET, 0); + cal.set(DST_OFFSET, 0); + + // This call should change the day of week to FRIDAY since the + // selected field combination should be YEAR, MONTH and + // DAY_OF_MONTH. The other calendar fields must be normalized + // with the selected date. + cal.getTime(); + cal.set(WEEK_OF_YEAR, 43); + if (!cal.checkDate(2003, OCTOBER, 24, FRIDAY)) { + errln(cal.getMessage()); + } + } + + /* + * 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."); + Koyomi cal = new Koyomi(); + cal.clear(); + // 2003/9/26 (Fri) + cal.set(2003, SEPTEMBER, 26); + // Go to August then back to September + cal.roll(MONTH, -1); + cal.roll(MONTH, +1); + Koyomi cal2 = (Koyomi) cal.clone(); + cal2.getTime(); + // Sunday of the week should be 2003/9/21. + cal2.set(DAY_OF_WEEK, SUNDAY); + if (!cal2.checkDate(2003, SEPTEMBER, 21, SUNDAY)) { + errln(cal2.getMessage()); + } + } + + /* + * 4867075: GregorianCalendar get() calls complete() internally, should getTime() too? + */ + public void Test4867075() { + Koyomi cal = new Koyomi(Locale.US); + 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, WEDNESDAY, 2003, DECEMBER, 31); + 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) { + cal.set(DAY_OF_WEEK, dayOfWeek); + cal.getTime(); + if (!cal.checkInternalDate(expectedYear, expectedMonth, expectedDayOfMonth, dayOfWeek)) { + errln(cal.getMessage()); + } + } + + static String toHexString(int x) { + return Integer.toHexString(x); + } +} diff --git a/jdk/test/java/util/Calendar/GregorianCutoverTest.java b/jdk/test/java/util/Calendar/GregorianCutoverTest.java new file mode 100644 index 00000000000..bd743ae19f6 --- /dev/null +++ b/jdk/test/java/util/Calendar/GregorianCutoverTest.java @@ -0,0 +1,324 @@ +/* + * 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 + * 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 4359204 4928615 4743587 4956232 6459836 6549953 + * @library /java/text/testlib + * @build Koyomi + * @run main GregorianCutoverTest + * @summary Unit tests related to the Gregorian cutover support. + */ + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import static java.util.GregorianCalendar.*; + +public class GregorianCutoverTest extends IntlTest { + + public static void main(String[] args) throws Exception { + TimeZone tz = TimeZone.getDefault(); + Locale lc = Locale.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Locale.setDefault(Locale.US); + + new GregorianCutoverTest().run(args); + } finally { + TimeZone.setDefault(tz); + Locale.setDefault(lc); + } + } + + /** + * 4359204: GregorianCalendar.get(cal.DAY_OF_YEAR) is inconsistent for year 1582 + */ + public void Test4359204() { + Koyomi cal = new Koyomi(); + + cal.set(1582, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(1582, OCTOBER, 1); + checkContinuity(cal, WEEK_OF_MONTH); + + // JCK tests the cutover date 1970-1-1 (Epoch) + cal.setGregorianChange(new Date(0)); + cal.set(1969, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(1969, DECEMBER, 1); + checkContinuity(cal, WEEK_OF_MONTH); + cal.set(1970, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + + // Use large date (year >= 50000) + cal.setGregorianChange(new Date(50000-1900, JANUARY, 20)); + cal.set(49998, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(49999, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(50000, JANUARY, 20); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + + // Handling of "overlapping" dates may still be incorrect as + // of 1.5. Also, there's no way to disambiguate "overlapping" + // dates. + // millis=-112033929600000: date=-1581-10-15T00:00:00.000Z + cal.setGregorianChange(new Date(-112033929600000L)); + cal.set(ERA, AD); + cal.set(-1581, JANUARY, 1); + // The year should have 379 days. + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + + logln("Default cutover"); + cal = new Koyomi(); + cal.set(1582, OCTOBER, 1); + logln(" roll --DAY_OF_MONTH from 1582/10/01"); + cal.roll(DAY_OF_MONTH, -1); + if (!cal.checkDate(1582, OCTOBER, 31)) { + errln(cal.getMessage()); + } + logln(" roll DAY_OF_MONTH+10 from 1582/10/31"); + cal.roll(DAY_OF_MONTH, +10); + if (!cal.checkDate(1582, OCTOBER, 20)) { + errln(cal.getMessage()); + } + logln(" roll DAY_OF_MONTH-10 from 1582/10/20"); + cal.roll(DAY_OF_MONTH, -10); + if (!cal.checkDate(1582, OCTOBER, 31)) { + errln(cal.getMessage()); + } + logln(" roll back one day further"); + cal.roll(DAY_OF_MONTH, +1); + if (!cal.checkDate(1582, OCTOBER, 1)) { + errln(cal.getMessage()); + } + + // 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)); + cal.set(ERA, AD); + cal.set(YEAR, 1970); + logln(" Set DAY_OF_YEAR to the 28th day of 1970"); + cal.set(DAY_OF_YEAR, 28); + if (!cal.checkDate(1970, FEBRUARY, 1)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(WEEK_OF_YEAR, 5)) { + errln(cal.getMessage()); + } + logln(" 1969/12/22 should be the 356th day of the year."); + cal.set(1969, DECEMBER, 22); + if (!cal.checkFieldValue(DAY_OF_YEAR, 356)) { + errln(cal.getMessage()); + } + logln(" Set DAY_OF_YEAR to autual maximum."); + int actualMaxDayOfYear = cal.getActualMaximum(DAY_OF_YEAR); + if (actualMaxDayOfYear != 356) { + errln("actual maximum of DAY_OF_YEAR: got " + actualMaxDayOfYear + ", expected 356"); + } + cal.set(DAY_OF_YEAR, actualMaxDayOfYear); + if (!cal.checkDate(1969, DECEMBER, 22)) { + errln(cal.getMessage()); + } + cal.set(1969, DECEMBER, 22); + cal.roll(DAY_OF_YEAR, +1); + logln(" Set to 1969/12/22 and roll DAY_OF_YEAR++"); + if (!cal.checkDate(1969, JANUARY, 1)) { + errln(cal.getMessage()); + } + logln(" 1970/1/5 should be the first day of the year."); + cal.set(1970, JANUARY, 5); + if (!cal.checkFieldValue(DAY_OF_YEAR, 1)) { + errln(cal.getMessage()); + } + logln(" roll --DAY_OF_MONTH from 1970/1/5"); + cal.roll(DAY_OF_MONTH, -1); + if (!cal.checkDate(1970, JANUARY, 31)) { + errln(cal.getMessage()); + } + logln(" roll back one day of month"); + cal.roll(DAY_OF_MONTH, +1); + if (!cal.checkDate(1970, JANUARY, 5)) { + errln(cal.getMessage()); + } + + // Test "missing" dates in non-lenient. + cal = new Koyomi(); // new instance for the default cutover + cal.setLenient(false); + try { + // the next day of 1582/10/4 (Julian) is 1582/10/15 (Gregorian) + logln("1582/10/10 doesn't exit with the default cutover."); + cal.set(1582, OCTOBER, 10); + cal.getTime(); + errln(" Didn't throw IllegalArgumentException in non-lenient."); + } catch (IllegalArgumentException e) { + } + } + + private void checkContinuity(Koyomi cal, int field) { + cal.getTime(); + logln(Koyomi.getFieldName(field) + " starting on " + cal.toDateString()); + int max = cal.getActualMaximum(field); + for (int i = 1; i <= max; i++) { + logln(i + " " + cal.toDateString()); + if (!cal.checkFieldValue(field, i)) { + errln(" " + cal.toDateString() + ":\t" + cal.getMessage()); + } + cal.add(field, +1); + } + } + + /** + * 4928615: GregorianCalendar returns wrong dates after setGregorianChange + */ + public void Test4928615() { + Koyomi cal = new Koyomi(); + logln("Today is 2003/10/1 Gregorian."); + 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))); + 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))); + if (!cal.checkDate(2003, SEPTEMBER, 18)) { + errln(" " + cal.getMessage()); + } + } + + /** + * 4743587: GregorianCalendar.getLeastMaximum() returns wrong values + */ + public void Test4743587() { + 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)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(WEEK_OF_YEAR, 52-((10+6)/7))) { + errln(" " + cal.getMessage()); + } + // Corrected for 4956232 + if (!cal.checkLeastMaximum(DAY_OF_MONTH, 28)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(WEEK_OF_MONTH, 3)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(DAY_OF_WEEK_IN_MONTH, 3)) { + errln(" " + cal.getMessage()); + } + // make sure that getLeastMaximum calls didn't affect the date + if (!cal.equals(cal2)) { + errln(" getLeastMaximum calls modified the object."); + } + if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 1)) { + errln(" " + cal.getMessage()); + } + + logln(" changing the date to 1582/10/20 for actual min/max tests"); + cal.set(1582, OCTOBER, 20); + if (!cal.checkActualMinimum(DAY_OF_MONTH, 1)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) { + errln(" " + cal.getMessage()); + } + + cal = new Koyomi(); + logln("Change the cutover date to 1970/1/5."); + cal.setGregorianChange(new Date(1970-1900, 0, 5)); + if (!cal.checkLeastMaximum(DAY_OF_YEAR, 356)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(DAY_OF_MONTH, 22)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 5)) { + errln(" " + cal.getMessage()); + } + cal.set(1970, JANUARY, 10); + if (!cal.checkActualMinimum(DAY_OF_MONTH, 5)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) { + errln(" " + cal.getMessage()); + } + } + + /** + * 6459836: (cal) GregorianCalendar set method provides wrong result + */ + public void Test6459836() { + 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)) { + 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)) { + errln("test case 2: " + gc1.getMessage()); + } + } + + /** + * 6549953 (cal) WEEK_OF_YEAR and DAY_OF_YEAR calculation problems around Gregorian cutover + */ + public void Test6549953() { + Koyomi cal = new Koyomi(); + + cal.set(YEAR, 1582); + cal.set(WEEK_OF_YEAR, 42); + cal.set(DAY_OF_WEEK, FRIDAY); + cal.checkFieldValue(WEEK_OF_YEAR, 42); + cal.checkFieldValue(DAY_OF_WEEK, FRIDAY); + if (!cal.checkDate(1582, OCTOBER, 29)) { + errln(cal.getMessage()); + } + cal.clear(); + cal.set(1582, OCTOBER, 1); + cal.set(DAY_OF_YEAR, 292); + if (!cal.checkDate(1582, OCTOBER, 29)) { + errln(cal.getMessage()); + } + } +} diff --git a/jdk/test/java/util/Calendar/JulianTest.java b/jdk/test/java/util/Calendar/JulianTest.java new file mode 100644 index 00000000000..bd7105bce89 --- /dev/null +++ b/jdk/test/java/util/Calendar/JulianTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004, 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 5029449 + * @summary Tests for the Julian calendar system (before the Gregorian cutover) + * @library /java/text/testlib + */ + +import static java.util.GregorianCalendar.*; + +public class JulianTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new JulianTest().run(args); + } + + /* + * 5029449: Regression: GregorianCalendar produces wrong Julian calendar dates in BC 1 + */ + public void Test5029449() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.set(1, JANUARY, 0); + // Date should be BC 1/12/31 + if (!cal.checkFieldValue(ERA, BC) + || !cal.checkDate(1, DECEMBER, 31)) { + errln(cal.getMessage()); + } + } +} diff --git a/jdk/test/java/util/Calendar/Koyomi.java b/jdk/test/java/util/Calendar/Koyomi.java new file mode 100644 index 00000000000..8eec03b5de4 --- /dev/null +++ b/jdk/test/java/util/Calendar/Koyomi.java @@ -0,0 +1,289 @@ +/* + * 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 + * 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 static java.util.Calendar.*; + +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + * GregorianCalendar subclass for testing. + */ +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", + "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET", + "DST_OFFSET" + }; + + static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1; + + public Koyomi() { + } + + public Koyomi(TimeZone tz) { + super(tz); + } + + public Koyomi(Locale loc) { + super(loc); + } + + public Koyomi(TimeZone tz, Locale loc) { + super(tz, loc); + } + + @Override + public void computeTime() { + super.computeTime(); + } + + @Override + public void computeFields() { + super.computeFields(); + } + + @Override + public void complete() { + super.complete(); + } + + static String getFieldName(int field) { + return FIELD_NAMES[field]; + } + + String toDateString() { + StringBuilder sb = new StringBuilder(); + sb.append(internalGet(ERA) == 0 ? "BCE " : ""); + sb.append(internalGet(YEAR)).append('-'); + sb.append(internalGet(MONTH)+1).append('-'); + sb.append(internalGet(DAY_OF_MONTH)); + return sb.toString(); + } + + String toTimeString() { + StringBuilder sb = new StringBuilder(); + sb.append(internalGet(HOUR_OF_DAY)).append(':'); + sb.append(internalGet(MINUTE)).append(':'); + sb.append(internalGet(SECOND)).append('.'); + int ms = internalGet(MILLISECOND); + if (ms < 100) { + sb.append('0'); + if (ms < 10) { + sb.append('0'); + } + } + sb.append(ms); + int offset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); + offset /= 60000; + offset = (offset/60) * 100 + (offset%60); + if (offset >= 0) { + sb.append('+'); + } else { + sb.append('-'); + offset = -offset; + } + if (offset < 1000) { + sb.append('0'); + if (offset < 100) { + sb.append('0'); + } + } + sb.append(offset); + return sb.toString(); + } + + String toDateTimeString() { + return toDateString() + "T" + toTimeString(); + } + + StringBuilder msg = new StringBuilder(); + + void initTest() { + msg = new StringBuilder(); + } + + String getMessage() { + String s = msg.toString(); + msg = new StringBuilder(); + return " " + s; + } + + void setMessage(String msg) { + this.msg = new StringBuilder(msg); + } + + void appendMessage(String msg) { + this.msg.append(msg); + } + + boolean getStatus() { + return msg.length() == 0; + } + + int getSetStateFields() { + int mask = 0; + for (int i = 0; i < FIELD_COUNT; i++) { + if (isSet(i)) { + mask |= 1 << i; + } + } + return mask; + } + + int[] getFields() { + int[] fds = new int[fields.length]; + System.arraycopy(fields, 0, fds, 0, fds.length); + return fds; + } + + boolean checkAllSet() { + initTest(); + for (int i = 0; i < FIELD_COUNT; i++) { + checkFieldState(i, true); + } + return getStatus(); + } + + boolean checkInternalDate(int year, int month, int dayOfMonth) { + initTest(); + checkInternalFieldValue(YEAR, year); + checkInternalFieldValue(MONTH, month); + checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth); + return getStatus(); + } + + boolean checkInternalDate(int year, int month, int dayOfMonth, int dayOfWeek) { + initTest(); + checkInternalFieldValue(YEAR, year); + checkInternalFieldValue(MONTH, month); + checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth); + checkInternalFieldValue(DAY_OF_WEEK, dayOfWeek); + return getStatus(); + } + + boolean checkActualMaximum(int field, int expectedValue) { + int val; + if ((val = getActualMaximum(field)) != expectedValue) { + appendMessage("getActualMaximum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkLeastMaximum(int field, int expectedValue) { + int val; + if ((val = getLeastMaximum(field)) != expectedValue) { + appendMessage("getLeastMaximum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkActualMinimum(int field, int expectedValue) { + int val; + if ((val = getActualMinimum(field)) != expectedValue) { + appendMessage("getActualMinimum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkGreatestMinimum(int field, int expectedValue) { + int val; + if ((val = getGreatestMinimum(field)) != expectedValue) { + appendMessage("getGreatestMinimum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkDate(int year, int month, int dayOfMonth) { + initTest(); + checkFieldValue(YEAR, year); + checkFieldValue(MONTH, month); + checkFieldValue(DAY_OF_MONTH, dayOfMonth); + return getStatus(); + } + + boolean checkDate(int year, int month, int dayOfMonth, int dayOfWeek) { + initTest(); + checkFieldValue(YEAR, year); + checkFieldValue(MONTH, month); + checkFieldValue(DAY_OF_MONTH, dayOfMonth); + checkFieldValue(DAY_OF_WEEK, dayOfWeek); + return getStatus(); + } + + boolean checkDateTime(int year, int month, int dayOfMonth, + int hourOfDay, int minute, int second, int ms) { + initTest(); + checkFieldValue(YEAR, year); + checkFieldValue(MONTH, month); + checkFieldValue(DAY_OF_MONTH, dayOfMonth); + checkFieldValue(HOUR_OF_DAY, hourOfDay); + checkFieldValue(MINUTE, minute); + checkFieldValue(SECOND, second); + checkFieldValue(MILLISECOND, ms); + return getStatus(); + } + + boolean checkTime(int hourOfDay, int minute, int second, int ms) { + initTest(); + checkFieldValue(HOUR_OF_DAY, hourOfDay); + checkFieldValue(MINUTE, minute); + checkFieldValue(SECOND, second); + checkFieldValue(MILLISECOND, ms); + return getStatus(); + } + + boolean checkFieldState(int field, boolean expectedState) { + if (isSet(field) != expectedState) { + appendMessage(FIELD_NAMES[field] + " state is not " + expectedState + "; "); + return false; + } + return true; + } + + boolean checkFieldValue(int field, int expectedValue) { + int val; + if ((val = get(field)) != expectedValue) { + appendMessage("get(" + FIELD_NAMES[field] + "): got " + val + + ", expected " + expectedValue + "; "); + return false; + } + return true; + } + + boolean checkInternalFieldValue(int field, int expectedValue) { + int val; + if ((val = internalGet(field)) != expectedValue) { + appendMessage("internalGet(" + FIELD_NAMES[field] + "): got " + val + + ", expected " + expectedValue + "; "); + return false; + } + return true; + } +} diff --git a/jdk/test/java/util/Calendar/Limit.java b/jdk/test/java/util/Calendar/Limit.java new file mode 100644 index 00000000000..1ab0e172dc8 --- /dev/null +++ b/jdk/test/java/util/Calendar/Limit.java @@ -0,0 +1,64 @@ +/* + * 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 + * 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.*; +import java.text.*; + +/** + * Test GregorianCalendar limits, which should not exist. + * @test + * @bug 4056585 + * @summary Make sure that GregorianCalendar works far in the past and future. + * @author Alan Liu + */ +public class Limit { + static final long ONE_DAY = 24*60*60*1000L; + + public static void main(String args[]) throws Exception { + GregorianCalendar c = new GregorianCalendar(); + DateFormat fmt = new SimpleDateFormat("EEEE, MMMM dd, yyyy G", Locale.US); + long bigMillis = 300000000000000L; + + try { + // We check two things: + // 1. That handling millis in the range of +/- bigMillis works. + // bigMillis is a value that used to blow up. + // 2. The round-trip format/parse works in these extreme areas. + c.setTime(new Date(-bigMillis)); + String s = fmt.format(c.getTime()); + Date d = fmt.parse(s); + if (Math.abs(d.getTime() + bigMillis) >= ONE_DAY) { + throw new Exception(s + " != " + fmt.format(d)); + } + + c.setTime(new Date(+bigMillis)); + s = fmt.format(c.getTime()); + d = fmt.parse(s); + if (Math.abs(d.getTime() - bigMillis) >= ONE_DAY) { + throw new Exception(s + " != " + fmt.format(d)); + } + } catch (IllegalArgumentException | ParseException e) { + throw e; + } + } +} diff --git a/jdk/test/java/util/Calendar/NonLenientTest.java b/jdk/test/java/util/Calendar/NonLenientTest.java new file mode 100644 index 00000000000..6c42c594932 --- /dev/null +++ b/jdk/test/java/util/Calendar/NonLenientTest.java @@ -0,0 +1,221 @@ +/* + * 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 + * 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 4147269 4266783 4726030 + * @summary Make sure that validation is adequate in non-lenient mode. + * @library /java/text/testlib + */ + +import java.util.*; + +import static java.util.Calendar.*; + +public class NonLenientTest extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + new NonLenientTest().run(args); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + public void TestValidationInNonLenient() { + Koyomi cal = getNonLenient(); + + // 2003 isn't a leap year. + cal.set(2003, FEBRUARY, 29); + validate(cal, "2003/2/29"); + + // October has only 31 days. + cal.set(2003, OCTOBER, 32); + validate(cal, "2003/10/32"); + + // 2003/10/31 is Friday. + cal.set(2003, OCTOBER, 31); + cal.set(DAY_OF_WEEK, SUNDAY); + validate(cal, "2003/10/31 SUNDAY"); + + // 2003/10/31 is the 304th day of the year. + cal.clear(); + cal.set(DAY_OF_YEAR, 1); + cal.set(2003, OCTOBER, 31); + validate(cal, "2003/10/31 DAY_OF_YEAR=1"); + + // 2003/10 isn't the 1st week of the year. + cal.clear(); + cal.set(YEAR, 2003); + cal.set(WEEK_OF_YEAR, 1); + cal.set(MONTH, OCTOBER); + validate(cal, "2003/10 WEEK_OF_YEAR=1"); + + // The 1st week of 2003 doesn't have Monday. + cal.clear(); + cal.set(YEAR, 2003); + cal.set(WEEK_OF_YEAR, 1); + cal.set(DAY_OF_WEEK, MONDAY); + validate(cal, "2003 WEEK_OF_YEAR=1 MONDAY."); + + // 2003 has 52 weeks. + cal.clear(); + cal.set(YEAR, 2003); + cal.set(WEEK_OF_YEAR, 53); + cal.set(DAY_OF_WEEK, WEDNESDAY); + validate(cal, "2003 WEEK_OF_YEAR=53"); + + /* + * These test cases assume incompatible behavior in Tiger as + * the result of the validation bug fixes. However, it looks + * like we have to allow applications to set ZONE_OFFSET and + * DST_OFFSET values to modify the time zone offsets given by + * a TimeZone. The definition of non-leniency for time zone + * offsets is somewhat vague. (See 6231602) + * + * The following test cases are now disabled. + + // America/Los_Angeles is GMT-08:00 + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.set(ZONE_OFFSET, 0); + validate(cal, "ZONE_OFFSET=0:00 in America/Los_Angeles"); + + // 2003/10/31 shouldn't be in DST. + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.set(DST_OFFSET, 60*60*1000); + validate(cal, "2003/10/31 DST_OFFSET=1:00 in America/Los_Angeles"); + + */ + } + + /** + * 4266783: java.util.GregorianCalendar: incorrect validation in non-lenient + */ + public void Test4266783() { + Koyomi cal = getNonLenient(); + // 2003/1 has up to 5 weeks. + cal.set(YEAR, 2003); + cal.set(MONTH, JANUARY); + cal.set(WEEK_OF_MONTH, 6); + cal.set(DAY_OF_WEEK, SUNDAY); + validate(cal, "6th Sunday in Jan 2003"); + } + + + /** + * 4726030: GregorianCalendar doesn't check invalid dates in non-lenient + */ + public void Test4726030() { + Koyomi cal = getNonLenient(); + // Default year is 1970 in GregorianCalendar which isn't a leap year. + cal.set(MONTH, FEBRUARY); + cal.set(DAY_OF_MONTH, 29); + validate(cal, "2/29 in the default year 1970"); + } + + /** + * 4147269: java.util.GregorianCalendar.computeTime() works wrong when lenient is false + */ + public void Test4147269() { + Koyomi calendar = getNonLenient(); + Date date = (new GregorianCalendar(1996,0,3)).getTime(); + + for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + calendar.setTime(date); + int max = calendar.getActualMaximum(field); + 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 +")"); + } catch (IllegalArgumentException e) { + } + } + + for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + calendar.setTime(date); + int min = calendar.getActualMinimum(field); + 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 +")"); + } catch (IllegalArgumentException e) { + } + } + } + + void validate(Koyomi cal, String desc) { + int[] originalFields = cal.getFields(); + int setFields = cal.getSetStateFields(); + + try { + cal.complete(); + errln(desc + " should throw IllegalArgumentException in non-lenient."); + } catch (IllegalArgumentException e) { + } + + // The code below will be executed with the -nothrow option + + // 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++) { + if (cal.isSet(i) && originalFields[i] != afterFields[i]) { + errln(" complete() modified fields[" + cal.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)); + } + } + + static Koyomi getNonLenient() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.setLenient(false); + return cal; + } + + static String toHex(int x) { + return Integer.toHexString(x); + } +} diff --git a/jdk/test/java/util/Calendar/ResolutionTest.java b/jdk/test/java/util/Calendar/ResolutionTest.java new file mode 100644 index 00000000000..98356131b0a --- /dev/null +++ b/jdk/test/java/util/Calendar/ResolutionTest.java @@ -0,0 +1,111 @@ +/* + * 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 + * 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 6452848 + * @summary Make sure that the resolution of (WEKK_OF_MONTH + + * DAY_OF_WEEK) and (DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK) works as + * specified in the API. + * @key randomness + */ + +import java.util.*; +import static java.util.Calendar.*; + +public class ResolutionTest { + static Random rand = new Random(); + + public static void main(String[] args) { + for (int year = 1995; year < 2011; year++) { + for (int month = JANUARY; month <= DECEMBER; month++) { + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + test(year, month, dow); + } + } + } + } + + static void test(int year, int month, int dow) { + Calendar cal = new GregorianCalendar(year, month, 1); + int max = cal.getActualMaximum(DAY_OF_MONTH); + ArrayList list = new ArrayList(); + for (int d = 1; d <= max; d++) { + cal.clear(); + cal.set(year, month, d); + if (cal.get(DAY_OF_WEEK) == dow) { + list.add(d); + } + } + for (int i = 0; i < 100; i++) { + int nth = rand.nextInt(list.size()); // 0-based + int day = list.get(nth); + nth++; // 1-based + testDayOfWeekInMonth(year, month, nth, dow, day); + } + + // Put WEEK_OF_MONTH-DAY_OF_MONTH pairs + list = new ArrayList(); + for (int d = 1; d <= max; d++) { + cal.clear(); + cal.set(year, month, d); + if (cal.get(DAY_OF_WEEK) == dow) { + list.add(cal.get(WEEK_OF_MONTH)); + list.add(d); + } + } + for (int i = 0; i < list.size(); i++) { + int nth = list.get(i++); + int day = list.get(i); + testWeekOfMonth(year, month, nth, dow, day); + } + } + + static Koyomi cal = new Koyomi(); + + static void testDayOfWeekInMonth(int year, int month, int nth, int dow, int expected) { + // don't call clear() here + cal.set(YEAR, year); + cal.set(MONTH, month); + // Set DAY_OF_WEEK_IN_MONTH before DAY_OF_WEEK + cal.set(DAY_OF_WEEK_IN_MONTH, nth); + cal.set(DAY_OF_WEEK, dow); + if (!cal.checkDate(year, month, expected)) { + throw new RuntimeException(String.format("DOWIM: year=%d, month=%d, nth=%d, dow=%d:%s%n", + year, month+1, nth, dow, cal.getMessage())); + } + } + + static void testWeekOfMonth(int year, int month, int nth, int dow, int expected) { + // don't call clear() here + cal.set(YEAR, year); + cal.set(MONTH, month); + // Set WEEK_OF_MONTH before DAY_OF_WEEK + cal.set(WEEK_OF_MONTH, nth); + cal.set(DAY_OF_WEEK, dow); + if (!cal.checkDate(year, month, expected)) { + throw new RuntimeException(String.format("WOM: year=%d, month=%d, nth=%d, dow=%d:%s%n", + year, month+1, nth, dow, cal.getMessage())); + } + } +} diff --git a/jdk/test/java/util/Calendar/RollDayOfWeekTest.java b/jdk/test/java/util/Calendar/RollDayOfWeekTest.java new file mode 100644 index 00000000000..5b85016c311 --- /dev/null +++ b/jdk/test/java/util/Calendar/RollDayOfWeekTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2004, 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 5090555 5091805 + * @summary Make sure that rolling DAY_OF_WEEK stays in the same week + * around year boundaries. + * @run main/othervm RollDayOfWeekTest 5 5 + */ + +import java.util.*; + +import static java.util.Calendar.*; + +// Usage: java RollDayOfWeekTest [pastYears futureYears] +public class RollDayOfWeekTest { + public static void main(String[] args) { + int pastYears = 5, futureYears = 23; + if (args.length == 2) { + pastYears = Integer.parseInt(args[0]); + pastYears = Math.max(1, Math.min(pastYears, 5)); + futureYears = Integer.parseInt(args[1]); + futureYears = Math.max(1, Math.min(futureYears, 28)); + } + + System.out.printf("Test [%d .. %+d] year range.%n", -pastYears, futureYears); + Calendar cal = new GregorianCalendar(); + int year = cal.get(YEAR) - pastYears; + + // Use the all combinations of firstDayOfWeek and + // minimalDaysInFirstWeek values in the year range current + // year - pastYears to current year + futureYears. + for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) { + for (int mdifw = 1; mdifw <= 7; mdifw++) { + cal.clear(); + cal.setFirstDayOfWeek(fdw); + cal.setMinimalDaysInFirstWeek(mdifw); + cal.set(year, JANUARY, 1); + checkRoll(cal, futureYears); + } + } + + // testing roll from BCE to CE + year = -1; + for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) { + for (int mdifw = 1; mdifw <= 7; mdifw++) { + cal.clear(); + cal.setFirstDayOfWeek(fdw); + cal.setMinimalDaysInFirstWeek(mdifw); + cal.set(year, JANUARY, 1); + checkRoll(cal, 4); + } + } + } + + + static void checkRoll(Calendar cal, int years) { + Calendar cal2 = null, cal3 = null, prev = null; + // Check 28 years + for (int x = 0; x < (int)(365.2425*years); x++) { + cal2 = (Calendar) cal.clone(); + cal3 = (Calendar) cal.clone(); + + // roll foreword + for (int i = 0; i < 10; i++) { + prev = (Calendar) cal2.clone(); + cal2.roll(Calendar.DAY_OF_WEEK, +1); + roll(cal3, +1); + long t2 = cal2.getTimeInMillis(); + long t3 = cal3.getTimeInMillis(); + if (t2 != t3) { + System.err.println("prev: " + prev.getTime() + "\n" + prev); + System.err.println("cal2: " + cal2.getTime() + "\n" + cal2); + System.err.println("cal3: " + cal3.getTime() + "\n" + cal3); + throw new RuntimeException("+1: t2=" + t2 + ", t3=" + t3); + } + } + + // roll backward + for (int i = 0; i < 10; i++) { + prev = (Calendar) cal2.clone(); + cal2.roll(Calendar.DAY_OF_WEEK, -1); + roll(cal3, -1); + long t2 = cal2.getTimeInMillis(); + long t3 = cal3.getTimeInMillis(); + if (t2 != t3) { + System.err.println("prev: " + prev.getTime() + "\n" + prev); + System.err.println("cal2: " + cal2.getTime() + "\n" + cal2); + System.err.println("cal3: " + cal3.getTime() + "\n" + cal3); + throw new RuntimeException("-1: t2=" + t2 + ", t3=" + t3); + } + } + cal.add(DAY_OF_YEAR, +1); + } + } + + // Another way to roll within the same week. + static void roll(Calendar cal, int n) { + int doy = cal.get(DAY_OF_YEAR); + int diff = cal.get(DAY_OF_WEEK) - cal.getFirstDayOfWeek(); + if (diff < 0) { + diff += 7; + } + + // dow1: first day of the week + int dow1 = doy - diff; + n %= 7; + doy += n; + if (doy < dow1) { + doy += 7; + } else if (doy >= dow1 + 7) { + doy -= 7; + } + cal.set(DAY_OF_YEAR, doy); + } +} diff --git a/jdk/test/java/util/Calendar/StampOverflow.java b/jdk/test/java/util/Calendar/StampOverflow.java new file mode 100644 index 00000000000..fc10595c87f --- /dev/null +++ b/jdk/test/java/util/Calendar/StampOverflow.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2001, 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 4404619 6348819 + * @summary Make sure that Calendar doesn't cause nextStamp overflow. + */ + +import java.lang.reflect.*; +import java.util.*; +import static java.util.Calendar.*; + +// Calendar fails when turning negative to positive (zero), not +// positive to negative with nextStamp. If a negative value was set to +// nextStamp, it would fail even with the fix. So, there's no way to +// reproduce the symptom in a short time -- at leaset it would take a +// couple of hours even if we started with Integer.MAX_VALUE. So, this +// test case just checks that set() calls don't cause any nextStamp +// overflow. + +public class StampOverflow { + public static void main(String[] args) throws IllegalAccessException { + // Get a Field for "nextStamp". + Field nextstamp = null; + try { + nextstamp = Calendar.class.getDeclaredField("nextStamp"); + } catch (NoSuchFieldException e) { + throw new RuntimeException("implementation changed?", e); + } + + nextstamp.setAccessible(true); + + Calendar cal = new GregorianCalendar(); + int initialValue = nextstamp.getInt(cal); + // Set nextStamp to a very large number + nextstamp.setInt(cal, Integer.MAX_VALUE - 100); + + for (int i = 0; i < 1000; i++) { + invoke(cal); + int stampValue = nextstamp.getInt(cal); + // nextStamp must not be less than initialValue. + if (stampValue < initialValue) { + throw new RuntimeException("invalid nextStamp: " + stampValue); + } + } + } + + static void invoke(Calendar cal) { + cal.clear(); + cal.set(2000, NOVEMBER, 2, 0, 0, 0); + int y = cal.get(YEAR); + int m = cal.get(MONTH); + int d = cal.get(DAY_OF_MONTH); + if (y != 2000 || m != NOVEMBER || d != 2) { + throw new RuntimeException("wrong date produced (" + + y + "/" + (m+1) + "/" + d + ")"); + } + } +} diff --git a/jdk/test/java/util/Calendar/ZoneOffsets.java b/jdk/test/java/util/Calendar/ZoneOffsets.java new file mode 100644 index 00000000000..147df337497 --- /dev/null +++ b/jdk/test/java/util/Calendar/ZoneOffsets.java @@ -0,0 +1,231 @@ +/* + * 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 + * 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 6231602 + * @summary Make sure that ZONE_OFFSET and/or DST_OFFSET setting is + * taken into account for time calculations. + */ + +import java.util.*; +import static java.util.GregorianCalendar.*; + +public class ZoneOffsets { + // This TimeZone always returns the dstOffset value. + private static class TestTimeZone extends TimeZone { + private int gmtOffset; + private int dstOffset; + + TestTimeZone(int gmtOffset, String id, int dstOffset) { + this.gmtOffset = gmtOffset; + setID(id); + this.dstOffset = dstOffset; + } + + public int getOffset(int era, int year, int month, int day, + int dayOfWeek, int milliseconds) { + return gmtOffset + dstOffset; + } + + public int getOffset(long date) { + return gmtOffset + dstOffset; + } + + public void setRawOffset(int offsetMillis) { + gmtOffset = offsetMillis; + } + + public int getRawOffset() { + return gmtOffset; + } + + public int getDSTSavings() { + return dstOffset; + } + + public boolean useDaylightTime() { + return dstOffset != 0; + } + + public boolean inDaylightTime(Date date) { + return dstOffset != 0; + } + + public String toString() { + return "TestTimeZone[" + getID() + ", " + gmtOffset + ", " + dstOffset + "]"; + } + } + + private static Locale[] locales = { + Locale.getDefault(), + new Locale("th", "TH"), + 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 }, + }; + + public static void main(String[] args) { + for (int l = 0; l < locales.length; l++) { + Locale loc = locales[l]; + for (int i = 0; i < offsets.length; i++) { + test(loc, offsets[i][0], offsets[i][1]); + } + } + + // The test case in the bug report. + GregorianCalendar cal = new GregorianCalendar(); + cal.setLenient(false); + cal.setGregorianChange(new Date(Long.MIN_VALUE)); + cal.clear(); + cal.set(ZONE_OFFSET, 0); + cal.set(DST_OFFSET, 0); + cal.set(ERA, AD); + cal.set(2004, FEBRUARY, 3, 0, 0, 0); + cal.set(MILLISECOND, 0); + // The following line should not throw an IllegalArgumentException. + cal.getTime(); + } + + private static void test(Locale loc, int gmtOffset, int dstOffset) { + TimeZone tz1 = new TestTimeZone(gmtOffset, + "GMT" + (gmtOffset/HOUR) + "." + (dstOffset/HOUR), + dstOffset); + int someDifferentOffset = gmtOffset + 2 * HOUR; + TimeZone tz2 = new TestTimeZone(someDifferentOffset, + "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); + + // cal1 is the base line. + Calendar cal1 = Calendar.getInstance(tz1, loc); + cal1.clear(); + cal1.set(2005, MARCH, 11); + long t1 = cal1.getTime().getTime(); + int gmt = cal1.get(ZONE_OFFSET); + int dst = cal1.get(DST_OFFSET); + + // Test 8 cases with cal2. + Calendar cal2 = Calendar.getInstance(tz2, loc); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test1: set only ZONE_OFFSET + cal2.set(ZONE_OFFSET, gmtOffset); + if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) { + error("Test1", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test2: set only DST_OFFSET + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) { + error("Test2", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz2); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test3: set both ZONE_OFFSET and DST_OFFSET + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test3", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test4: set both ZONE_OFFSET and DST_OFFSET + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test4", loc, cal2, gmtOffset, dstOffset, t1); + } + + // Test the same thing in non-lenient + cal2.setLenient(false); + + cal2.setTimeZone(tz2); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test5: set only ZONE_OFFSET in non-lenient + cal2.set(ZONE_OFFSET, gmtOffset); + if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) { + error("Test5", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test6: set only DST_OFFSET in non-lenient + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) { + error("Test6", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz2); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test7: set both ZONE_OFFSET and DST_OFFSET in non-lenient + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test7", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test8: set both ZONE_OFFSET and DST_OFFSET in non-lenient + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test8", loc, cal2, gmtOffset, dstOffset, t1); + } + } + + 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()); + } +} diff --git a/jdk/test/java/util/Calendar/bug4028518.java b/jdk/test/java/util/Calendar/bug4028518.java new file mode 100644 index 00000000000..982b93adc86 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4028518.java @@ -0,0 +1,56 @@ +/* + * 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 + * 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 4028518 + * @summary Make sure cloned GregorianCalendar is unchanged by modifying its original. + */ + +import java.util.GregorianCalendar ; +import static java.util.Calendar.*; + +public class bug4028518 { + + public static void main(String[] args) + { + GregorianCalendar cal1 = new GregorianCalendar() ; + GregorianCalendar cal2 = (GregorianCalendar) cal1.clone() ; + + printdate(cal1, "cal1: ") ; + printdate(cal2, "cal2 - cloned(): ") ; + cal1.add(DAY_OF_MONTH, 1) ; + printdate(cal1, "cal1 after adding 1 day: ") ; + printdate(cal2, "cal2 should be unmodified: ") ; + if (cal1.get(DAY_OF_MONTH) == cal2.get(DAY_OF_MONTH)) { + throw new RuntimeException("cloned GregorianCalendar modified"); + } + } + + private static void printdate(GregorianCalendar cal, String string) + { + System.out.println(string + (cal.get(MONTH) + 1) + + "/" + cal.get(DAY_OF_MONTH) + + "/" + cal.get(YEAR)) ; + } +} diff --git a/jdk/test/java/util/Calendar/bug4100311.java b/jdk/test/java/util/Calendar/bug4100311.java new file mode 100644 index 00000000000..ef0f36ecbd2 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4100311.java @@ -0,0 +1,47 @@ +/* + * 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 + * 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 4100311 + * @summary Make sure set(DAY_OF_YEAR, 1) works. + */ + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Date; + +public class bug4100311 +{ + @SuppressWarnings("deprecation") + public static void main(String args[]) + { + GregorianCalendar cal = new GregorianCalendar(); + cal.set(Calendar.YEAR, 1997); + cal.set(Calendar.DAY_OF_YEAR, 1); + Date d = cal.getTime(); // Should be Jan 1 + if (d.getMonth() != 0 || d.getDate() != 1) { + throw new RuntimeException("Date isn't Jan 1"); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4243802.java b/jdk/test/java/util/Calendar/bug4243802.java new file mode 100644 index 00000000000..1f3b910c1b3 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4243802.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001, 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 4243802 + * @summary confirm that Calendar.setTimeInMillis() and + * getTimeInMillis() can be called from a user program. (They used to + * be protected methods.) + * @library /java/text/testlib + */ + +import java.util.*; + +public class bug4243802 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4243802().run(args); + } + + /** + * 4243802: RFE: need way to set the date of a calendar without a Date object + */ + public void Test4243802() { + TimeZone saveZone = TimeZone.getDefault(); + Locale saveLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + + Calendar cal1 = Calendar.getInstance(); + Calendar cal2 = Calendar.getInstance(); + + cal1.clear(); + cal2.clear(); + cal1.set(2001, Calendar.JANUARY, 25, 1, 23, 45); + cal2.setTimeInMillis(cal1.getTimeInMillis()); + if ((cal2.get(Calendar.YEAR) != 2001) || + (cal2.get(Calendar.MONTH) != Calendar.JANUARY) || + (cal2.get(Calendar.DAY_OF_MONTH) != 25) || + (cal2.get(Calendar.HOUR_OF_DAY) != 1) || + (cal2.get(Calendar.MINUTE) != 23) || + (cal2.get(Calendar.SECOND) != 45) || + (cal2.get(Calendar.MILLISECOND) != 0)) { + errln("Failed: expected 1/25/2001 1:23:45.000" + + ", got " + (cal2.get(Calendar.MONTH)+1) + "/" + + cal2.get(Calendar.DAY_OF_MONTH) +"/" + + cal2.get(Calendar.YEAR) + " " + + cal2.get(Calendar.HOUR_OF_DAY) + ":" + + cal2.get(Calendar.MINUTE) + ":" + + cal2.get(Calendar.SECOND) + "." + + toMillis(cal2.get(Calendar.MILLISECOND))); + } + logln("Passed."); + } + finally { + Locale.setDefault(saveLocale); + TimeZone.setDefault(saveZone); + } + } + + private String toMillis(int m) { + StringBuffer sb = new StringBuffer(); + if (m < 100) { + sb.append('0'); + } + if (m < 10) { + sb.append('0'); + } + sb.append(m); + return sb.toString(); + } +} diff --git a/jdk/test/java/util/Calendar/bug4316678.java b/jdk/test/java/util/Calendar/bug4316678.java new file mode 100644 index 00000000000..8ae6bbc294f --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4316678.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2000, 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.*; +import java.util.*; +import java.text.*; + +/** + * @test + * @bug 4316678 + * @summary test that Calendar's Serializasion works correctly. + * @library /java/text/testlib + */ +public class bug4316678 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4316678().run(args); + } + + public void Test4316678() throws Exception { + GregorianCalendar gc1; + GregorianCalendar gc2; + TimeZone saveZone = TimeZone.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + gc1 = new GregorianCalendar(2000, Calendar.OCTOBER, 10); + try (ObjectOutputStream out + = new ObjectOutputStream(new FileOutputStream("bug4316678.ser"))) { + out.writeObject(gc1); + } + + try (ObjectInputStream in + = new ObjectInputStream(new FileInputStream("bug4316678.ser"))) { + gc2 = (GregorianCalendar)in.readObject(); + } + + gc1.set(Calendar.DATE, 16); + gc2.set(Calendar.DATE, 16); + if (!gc1.getTime().equals(gc2.getTime())) { + errln("Invalid Time :" + gc2.getTime() + + ", expected :" + gc1.getTime()); + } + } finally { + TimeZone.setDefault(saveZone); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4372743.java b/jdk/test/java/util/Calendar/bug4372743.java new file mode 100644 index 00000000000..1800ebc002a --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4372743.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 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 4372743 + * @summary test that checks transitions of ERA and YEAR which are caused by add(MONTH). + * @library /java/text/testlib + */ + +import java.io.*; +import java.util.*; +import java.text.*; + +import static java.util.GregorianCalendar.*; + +public class bug4372743 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4372743().run(args); + } + + 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}, + }; + 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]); + } + if (gc.get(YEAR) != 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]); + } + } + + public void Test4372743() { + GregorianCalendar gc; + TimeZone saveZone = TimeZone.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + /* Set March 3, A.D. 2 */ + gc = new GregorianCalendar(2, MARCH, 3); + for (int i = 0; i < tablesize; i++) { + check(gc, i); + gc.add(gc.MONTH, -1); + } + + /* Again, Set March 3, A.D. 2 */ + gc = new GregorianCalendar(2, MARCH, 3); + for (int i = 0; i < tablesize; i+=7) { + check(gc, i); + gc.add(gc.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--) { + check(gc, i); + gc.add(gc.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) { + check(gc, i); + gc.add(gc.MONTH, 8); + } + } + finally { + TimeZone.setDefault(saveZone); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4401223.java b/jdk/test/java/util/Calendar/bug4401223.java new file mode 100644 index 00000000000..fbd9e29a8f6 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4401223.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001, 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 4401223 + * @summary Make sure that GregorianCalendar doesn't cause IllegalArgumentException at some special situations which are related to the Leap Year. + * @library /java/text/testlib + */ + +import java.util.*; + +public class bug4401223 extends IntlTest { + + public void Test4401223a() { + int status = 0; + String s = null; + + try { + Date date = new Date(2000-1900, Calendar.FEBRUARY, 29); + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(date); + gc.setLenient(false); + gc.set(Calendar.YEAR, 2001); + s = "02/29/00 & set(YEAR,2001) = " + gc.getTime().toString(); + } catch (Exception ex) { + status++; + s = "Exception occurred for 2/29/00 & set(YEAR,2001): " + ex; + } + if (status > 0) { + errln(s); + } else { + logln(s); + } + } + + public void Test4401223b() { + int status = 0; + String s = null; + + try { + Date date = new Date(2000-1900, Calendar.DECEMBER, 31); + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(date); + gc.setLenient(false); + gc.set(Calendar.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) { + status++; + s = "Wrong Date : 12/31/00 & set(YEAR,2001) ---> " + gc.getTime().toString(); + } else { + s = "12/31/00 & set(YEAR,2001) = " + gc.getTime().toString(); + } + } catch (Exception ex) { + status++; + s = "Exception occurred for 12/31/00 & set(YEAR,2001) : " + ex; + } + if (status > 0) { + errln(s); + } else { + logln(s); + } + } + + public static void main(String[] args) throws Exception { + new bug4401223().run(args); + } +} diff --git a/jdk/test/java/util/Calendar/bug4409072.java b/jdk/test/java/util/Calendar/bug4409072.java new file mode 100644 index 00000000000..d8e56a45547 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4409072.java @@ -0,0 +1,683 @@ +/* + * Copyright (c) 2001, 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 4409072 + * @summary tests for set(), add(), and roll() with various week parameters. + * @library /java/text/testlib + */ + +import java.util.*; +import static java.util.Calendar.*; + +public class bug4409072 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4409072().run(args); + } + + /* Confirm some public methods' behavior in Calendar. + * (e.g. add(), roll(), set()) + */ + public void Test4409072() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + Locale savedLocale = Locale.getDefault(); + TimeZone savedTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + testSet(); + testAdd(); + testRoll(); + } finally { + TimeZone.setDefault(savedTZ); + Locale.setDefault(savedLocale); + } + } + + /* + * Golden data for set() test + */ + static final int[][][] resultWOMForSetTest = { + { /* For year1998 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11}, + /* Mon */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, + /* Tue */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Wed */ {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Thu */ {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Fri */ {10,27}, {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Sat */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11}, {11,11}, + }, + { /* For year1999 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, + /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, + /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, + /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10}, + }, + { /* For year2000 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, + /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, + /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, + /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, + /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + }, + { /* For year2001 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + /* Mon */ {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + /* Tue */ {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + /* Wed */ {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, + /* Thu */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, + /* Fri */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, + /* Sat */ {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + }, + { /* For year2002 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Mon */ {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Tue */ {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Wed */ {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Thu */ {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, + /* Fri */ {10,29}, {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, + /* Sat */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11,13}, + }, + { /* For year2003 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12}, + /* Mon */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Tue */ {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Wed */ {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Thu */ {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Fri */ {10,28}, {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, + /* Sat */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12}, {11,12}, + }, + { /* For year2004 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, + /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, + /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, + /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10}, + }, + { /* For year2005 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, + /* Mon */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, + /* Tue */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, + /* Wed */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, + /* Thu */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, + /* Fri */ {10,25}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, + /* Sat */ {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, + }, + { /* For year2006 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, + /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, + /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, + /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, + /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + }, + }; + + static final int[][][] resultWOYForSetTest1 = { + { /* For year1998 */ + /* FirstDayOfWeek = Sunday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, + {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9}, + /* FirstDayOfWeek = Monday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9}, + /* FirstDayOfWeek = Tuesday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9}, + /* FirstDayOfWeek = Wednesday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, + /* FirstDayOfWeek = Thursday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + /* FirstDayOfWeek = Friday */ + {1997,11,26}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + /* FirstDayOfWeek = Saturday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9}, + {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9}, + }, + { /* For year1999 */ + /* FirstDayOfWeek = Sunday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Monday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Tuesday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Wednesday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Thursday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, + /* FirstDayOfWeek = Friday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + /* FirstDayOfWeek = Saturday */ + {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + }, + { /* For year2000 */ + /* FirstDayOfWeek = Sunday */ + {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Monday */ + {1999,11,31}, {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Tuesday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Wednesday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Thursday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31}, + {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Friday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31}, + {1999,11,31}, {1999,11,31}, {2000, 0, 7}, + /* FirstDayOfWeek = Saturday */ + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + }, + { /* For year2001 */ + /* FirstDayOfWeek = Sunday */ + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0,12}, + /* FirstDayOfWeek = Monday */ + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Tuesday */ + {2000,11,29}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Wednesday */ + {2000,11,29}, {2000,11,29}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Thursday */ + {2000,11,29}, {2000,11,29}, {2000,11,29}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Friday */ + {2000,11,29}, {2000,11,29}, {2000,11,29}, {2000,11,29}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Saturday */ + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0,12}, {2001, 0,12}, + }, + { /* For year2002 */ + /* FirstDayOfWeek = Sunday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0,11}, {2002, 0,11}, + /* FirstDayOfWeek = Monday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0,11}, + /* FirstDayOfWeek = Tuesday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Wednesday */ + {2001,11,28}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Thursday */ + {2001,11,28}, {2001,11,28}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Friday */ + {2001,11,28}, {2001,11,28}, {2001,11,28}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Saturday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0,11}, {2002, 0,11}, {2002, 0,11}, + }, + { /* For year2003 */ + /* FirstDayOfWeek = Sunday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0,10}, {2003, 0,10}, {2003, 0,10}, + /* FirstDayOfWeek = Monday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0,10}, {2003, 0,10}, + /* FirstDayOfWeek = Tuesday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10}, + /* FirstDayOfWeek = Wednesday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + /* FirstDayOfWeek = Thursday */ + {2002,11,27}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + /* FirstDayOfWeek = Friday */ + {2002,11,27}, {2002,11,27}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + /* FirstDayOfWeek = Saturday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10}, + {2003, 0,10}, {2003, 0,10}, {2003, 0,10}, + }, + { /* For year2004 */ + /* FirstDayOfWeek = Sunday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, + {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9}, + /* FirstDayOfWeek = Monday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9}, + /* FirstDayOfWeek = Tuesday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9}, + /* FirstDayOfWeek = Wednesday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, + /* FirstDayOfWeek = Thursday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + /* FirstDayOfWeek = Friday */ + {2003,11,26}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + /* FirstDayOfWeek = Saturday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9}, + {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9}, + }, + { /* For year2005 */ + /* FirstDayOfWeek = Sunday */ + {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Monday */ + {2004,11,31}, {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Tuesday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Wednesday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Thursday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31}, + {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Friday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31}, + {2004,11,31}, {2004,11,31}, {2005, 0, 7}, + /* FirstDayOfWeek = Saturday */ + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + }, + { /* For year2006 */ + /* FirstDayOfWeek = Sunday */ + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Monday */ + {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Tuesday */ + {2005,11,30}, {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Wednesday */ + {2005,11,30}, {2005,11,30}, {2005,11,30}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Thursday */ + {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Friday */ + {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30}, + {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Saturday */ + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0,13}, + } + }; + + static final int[][] resultWOYForSetTest2 = { + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + /* Mon */ {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + /* Tue */ {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + /* Wed */ {4,25}, {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, + /* Thu */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8}, {5, 8}, + /* Fri */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8}, + /* Sat */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + }; + + /** + * Test for set() + */ + void testSet() { + boolean noerror = true; + Calendar cal = Calendar.getInstance(); + int sYear=1998; + int eYear=2006; + + // Loop for FirstDayOfWeek: SUNDAY..SATURDAY + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + + // Loop for MinimalDaysInFirstWeek: 1..7 + for (int minDow = 1; minDow <= 7; minDow++) { + int index = (dow-1)*7 + (minDow-1); + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(YEAR, 2005); + cal.set(DAY_OF_WEEK, WEDNESDAY); + cal.set(WEEK_OF_YEAR, 22); + + int y = 2005; + int m = resultWOYForSetTest2[index][0]; + int d = resultWOYForSetTest2[index][1]; + int year = cal.get(YEAR); + int month = cal.get(MONTH); + int date = cal.get(DATE); + + if (cal.get(WEEK_OF_YEAR) != 22) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=22)" + + " *** get(WEEK_OF_YEAR=" + + cal.get(WEEK_OF_YEAR) + ")" + + ", got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+2005 + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } else if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=22)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + for (int targetYear = sYear; targetYear<= eYear; targetYear++) { + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(YEAR, targetYear); + cal.set(DAY_OF_WEEK, FRIDAY); + cal.set(MONTH, DECEMBER); + cal.set(WEEK_OF_MONTH, 1); + + y = targetYear; + m = resultWOMForSetTest[targetYear-sYear][index][0]; + d = resultWOMForSetTest[targetYear-sYear][index][1]; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : set(WEEK_OF_MONTH=1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(YEAR, targetYear); + cal.set(DAY_OF_WEEK, FRIDAY); + cal.set(WEEK_OF_YEAR, 1); + + y = resultWOYForSetTest1[targetYear-sYear][index][0]; + m = resultWOYForSetTest1[targetYear-sYear][index][1]; + d = resultWOYForSetTest1[targetYear-sYear][index][2]; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if (cal.get(WEEK_OF_YEAR) != 1) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=1)" + + " *** get(WEEK_OF_YEAR=" + + cal.get(WEEK_OF_YEAR) + ")" + + ", got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } else if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + } + } + } + + if (noerror) { + logln("Passed : set() test"); + } + } + + /** + * Test for add() + */ + void testAdd() { + boolean noerror = true; + Calendar cal = Calendar.getInstance(); + + // Loop for FirstDayOfWeek: SUNDAY..SATURDAY + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + + // Loop for MinimalDaysInFirstWeek: 1..7 + for (int minDow = 1; minDow <= 7; minDow++) { + int oldWOY, newWOY; + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(2005, DECEMBER, 7); + oldWOY = cal.get(WEEK_OF_YEAR); + + for (int cnt = 0; cnt < 7; cnt++) { + cal.add(WEEK_OF_YEAR, 1); + } + + int year = cal.get(YEAR); + int month = cal.get(MONTH); + int date = cal.get(DATE); + + if ((year != 2006) || (month != 0) || (date != 25)) { + noerror = false; + errln("Failed : add(WEEK_OF_YEAR+1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected 1/25/2006" + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + for (int cnt = 0; cnt < 10; cnt++) { + cal.add(WEEK_OF_YEAR, -1); + } + newWOY = cal.get(WEEK_OF_YEAR); + + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((oldWOY - newWOY) != 3) { + errln("Failed : add(WEEK_OF_YEAR-1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected 11/16/2005" + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow + + ", WEEK_OF_YEAR=" + newWOY + + " should be " + (oldWOY-3)); + } else if ((year != 2005) || (month != 10) || (date != 16)) { + errln("Failed : add(-1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected 11/16/2005" + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + } + } + + if (noerror) { + logln("Passed : add() test"); + } + } + + /* + * Golden data for roll() test + */ + static final int[] resultWOMForRollTest = { + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ 1, 1, 1, 26, 26, 26, 26, + /* Mon */ 1, 1, 1, 1, 26, 26, 26, + /* Tue */ 31, 31, 31, 31, 31, 24, 24, + /* Wed */ 31, 31, 31, 31, 31, 31, 24, + /* Thu */ 31, 31, 31, 31, 31, 31, 31, + /* Fri */ 1, 31, 31, 31, 31, 31, 31, + /* Sat */ 1, 1, 31, 31, 31, 31, 31, + }; + + static final int[][] resultWOYForRollTest = { + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Mon */ {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Tue */ {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Wed */ {1, 2}, {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Thu */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2}, {1, 2}, + /* Fri */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2}, + /* Sat */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + }; + + /** + * Test for roll() + */ + void testRoll() { + boolean noerror = true; + Calendar cal = Calendar.getInstance(); + + // Loop for FirstDayOfWeek: SUNDAY..SATURDAY + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + + // Loop for MinimalDaysInFirstWeek: 1..7 + for (int minDow = 1; minDow <= 7; minDow++) { + int oldWOY, newWOY; + int index = (dow-1)*7 + (minDow-1); + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(2005, DECEMBER, 12); + oldWOY = cal.get(WEEK_OF_YEAR); + for (int cnt = 0; cnt < 2; cnt++) { + cal.roll(WEEK_OF_MONTH, -1); + } + int y = 2005; + int m = DECEMBER; + int d = resultWOMForRollTest[index]; + int year = cal.get(YEAR); + int month = cal.get(MONTH); + int date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : roll(WEEK_OF_MONTH-1)" + + " got " + (month+1) + "/" + date + "/" + year + + ", expected " + (m+1) + "/" + d + "/" + y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(2005, DECEMBER, 7); + oldWOY = cal.get(WEEK_OF_YEAR); + + for (int cnt = 0; cnt < 7; cnt++) { + cal.roll(WEEK_OF_YEAR, 1); + } + + y = 2005; + m = resultWOYForRollTest[index][0]; + d = resultWOYForRollTest[index][1]; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : roll(WEEK_OF_YEAR+1)" + + " got " + (month+1) + "/" + date + "/" + year + + ", expected " + (m+1) + "/" + d + "/" + y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + for (int cnt = 0; cnt < 10; cnt++) { + cal.roll(WEEK_OF_YEAR, -1); + } + newWOY = cal.get(WEEK_OF_YEAR); + + y = 2005; + m = NOVEMBER; + d = 16; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : roll(WEEK_OF_YEAR-1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + } + } + + if (noerror) { + logln("Passed : roll() test"); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4514831.java b/jdk/test/java/util/Calendar/bug4514831.java new file mode 100644 index 00000000000..9d635e26167 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4514831.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2002, 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 4514831 + * @summary Confirm that GregorianCalendar.roll() works properly during transition from Daylight Saving Time to Standard Time. + */ + +import java.util.*; + +public class bug4514831 { + + public static void main(String[] args) { + Locale savedLocale = Locale.getDefault(); + 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 "; + + 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) + " "; + } + if (!test_roll.equals(golden_data1)) { + err = true; + 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) + " "; + } + if (!test_roll.equals(golden_data2)) { + err = true; + 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) + " "; + } + 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); + } + } finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + + if (err) { + throw new RuntimeException("Wrong roll() transition"); + } + } +} diff --git a/jdk/test/java/util/Date/Bug4955000.java b/jdk/test/java/util/Date/Bug4955000.java new file mode 100644 index 00000000000..c94b23868ca --- /dev/null +++ b/jdk/test/java/util/Date/Bug4955000.java @@ -0,0 +1,144 @@ +/* + * 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 + * 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 4955000 + * @summary Make sure that a Date and a GregorianCalendar produce the + * same date/time. Both are new implementations in 1.5. + */ + +import java.util.*; +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) { + TimeZone defaultTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("NST")); + GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("UTC")); + // Date1025 + int[] years1 = { + Integer.MIN_VALUE, + Integer.MIN_VALUE + 1, + gc.getMinimum(YEAR) - 1, + gc.getMaximum(YEAR) + 1, + Integer.MAX_VALUE - 1, + Integer.MAX_VALUE + }; + for (int i = 0; i < years1.length; i++) { + gc.clear(); + gc.set(years1[i], gc.JANUARY, 1); + long t = gc.getTimeInMillis(); + 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 +")"); + } + } + + // Date2015 + int years[] = { + gc.getGreatestMinimum(YEAR), + gc.getGreatestMinimum(YEAR) + 1, + -1, + 0, + 1, + gc.getLeastMaximum(YEAR) - 1, + gc.getLeastMaximum(YEAR) + }; + + int months[] = { + gc.getMinimum(MONTH), + gc.getMinimum(MONTH) + 1, + gc.getMaximum(MONTH) - 1, + gc.getMaximum(MONTH) + }; + + 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[] = { + gc.getMinimum(HOUR), + gc.getMinimum(HOUR) + 1, + gc.getMaximum(HOUR) - 1, + gc.getMaximum(HOUR) + }; + + int ms[] = { + gc.getMinimum(MINUTE), + gc.getMinimum(MINUTE) + 1, + gc.getMaximum(MINUTE) - 1, + gc.getMaximum(MINUTE) + }; + + 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++) { + int year = years[i] - 1900; + int month = months[j]; + int date = dates[k]; + int hours = hs[m]; + int minutes = ms[n]; + int seconds = ss[p]; + + long result = Date.UTC(year, month, date, + hours, minutes, seconds); + + gc.clear(); + gc.set(year + 1900, month, date, hours, minutes, seconds); + + long expected = gc.getTime().getTime(); + + if (expected != result) { + throw new RuntimeException("expected (" + expected + + ") != result (" + result +")"); + } + } + } + } + } + } + } + } finally { + TimeZone.setDefault(defaultTZ); + } + } +} diff --git a/jdk/test/java/util/Date/DateGregorianCalendarTest.java b/jdk/test/java/util/Date/DateGregorianCalendarTest.java new file mode 100644 index 00000000000..49dbc8bc41a --- /dev/null +++ b/jdk/test/java/util/Date/DateGregorianCalendarTest.java @@ -0,0 +1,235 @@ +/* + * 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 + * 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 4614842 + * @summary Make sure that a Date and a GregorianCalendar produce the same date/time. Both are new implementations in 1.5. + * @run main DateGregorianCalendarTest 15 + */ + +import java.util.*; +import static java.util.GregorianCalendar.*; + +// Usage: java DateGregorianCalendarTest [duration] + +@SuppressWarnings("deprecation") +public class DateGregorianCalendarTest { + static volatile boolean runrun = true; + static int nThreads; + + public static void main(String[] args) { + int duration = 600; + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + + TimeZone savedTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Thread[] t = new Thread[10]; // for future bugs... + int index = 0; + t[index++] = new Thread(new Runnable() { + public void run() { + GregorianCalendar gc = new GregorianCalendar(); + + long delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000); + long count = 0; + try { + for (long t = Long.MIN_VALUE; runrun && t < Long.MAX_VALUE-delta; t += delta) { + gc.setTimeInMillis(t); + Date date = new Date(t); + int y; + if (!((y = gc.get(YEAR)) == (date.getYear()+1900) && + gc.get(MONTH) == date.getMonth() && + gc.get(DAY_OF_MONTH) == date.getDate() && + gc.get(HOUR_OF_DAY) == date.getHours() && + gc.get(MINUTE) == date.getMinutes() && + gc.get(SECOND) == date.getSeconds())) { + throw new RuntimeException("GregorinCalendar and Date returned different dates." + +" (millis=" + t + ")\n" + +"GC=" + gc + "\nDate=" + date); + } + ++count; + if (y >= 1) { + delta = (long)(365.2422 * 24 * 60 * 60 * 1000); + } + if (y >= 1970) { + delta = (24 * 60 * 60 * 1000); + } + if (y >= 2039) { + delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000); + } + } + if (runrun) { + System.out.println("Part I (count="+count+"): Passed"); + } else { + System.out.println("Part I (count="+count+"): Incomplete"); + } + } catch (RuntimeException e) { + System.out.println("Part I (count="+count+"): FAILED"); + runrun = false; + throw e; + } finally { + decrementCounter(); + } + } + }); + + t[index++] = new Thread(new Runnable() { + public void run() { + GregorianCalendar gc = new GregorianCalendar(); + + long count = 0; + int delta; + try { + for (long year = Integer.MIN_VALUE+1900; + runrun && year <= Integer.MAX_VALUE; year += delta) { + checkTimes(gc, year, JANUARY, 1, 0, 0, 0); + ++count; + delta = getDelta((int)year); + } + + for (long month = Integer.MIN_VALUE; + runrun && month <= Integer.MAX_VALUE; month += delta) { + checkTimes(gc, 1900, month, 1, 0, 0, 0); + ++count; + delta = getDelta(gc.get(YEAR)); + } + + for (long dayOfMonth = Integer.MIN_VALUE; + runrun && dayOfMonth <= Integer.MAX_VALUE; dayOfMonth += delta) { + checkTimes(gc, 1900, JANUARY, dayOfMonth, 0, 0, 0); + ++count; + delta = getDelta(gc.get(YEAR)); + } + if (runrun) { + System.out.println("Part II (count="+count+"): Passed"); + } else { + System.out.println("Part II (count="+count+"): Incomplete"); + } + } catch (RuntimeException e) { + System.out.println("Part II (count="+count+"): FAILED"); + runrun = false; + throw e; + } finally { + decrementCounter(); + } + } + }); + + // t3 takes more than 10 minutes (on Ultra-60 450MHz) without + // the 4936355 fix due to getting the small delta. + t[index++] = new Thread(new Runnable() { + public void run() { + GregorianCalendar gc = new GregorianCalendar(); + + long count = 0; + int delta; + try { + for (long hourOfDay = Integer.MIN_VALUE; + runrun && hourOfDay <= Integer.MAX_VALUE; hourOfDay += delta) { + checkTimes(gc, 1970, JANUARY, 1, hourOfDay, 0, 0); + ++count; + delta = getDelta(gc.get(YEAR)); + } + for (long minutes = Integer.MIN_VALUE; + runrun && minutes <= Integer.MAX_VALUE; minutes += delta) { + checkTimes(gc, 1970, JANUARY, 1, 0, minutes, 0); + ++count; + delta = getDelta(gc.get(YEAR)) * 60; + } + for (long seconds = Integer.MIN_VALUE; + runrun && seconds <= Integer.MAX_VALUE; seconds += delta) { + checkTimes(gc, 1970, JANUARY, 1, 0, 0, seconds); + ++count; + delta = getDelta(gc.get(YEAR)) * 60 * 60; + } + if (runrun) { + System.out.println("Part III (count="+count+"): Passed"); + } else { + System.out.println("Part III (count="+count+"): Incomplete"); + } + } catch (RuntimeException e) { + System.out.println("Part III (count="+count+"): FAILED"); + runrun = false; + throw e; + } finally { + decrementCounter(); + } + } + }); + + for (int i = 0; i < index; i++) { + incrementCounter(); + t[i].start(); + } + + try { + for (int i = 0; getCounter() > 0 && i < duration; i++) { + Thread.sleep(1000); + } + runrun = false; + for (int i = 0; i < index; i++) { + t[i].join(); + } + } catch (InterruptedException e) { + } + } finally { + TimeZone.setDefault(savedTZ); + } + } + + static void checkTimes(GregorianCalendar gc, long year, long month, long dayOfMonth, + long hourOfDay, long minutes, long seconds) { + gc.clear(); + gc.set((int)year, (int)month, (int)dayOfMonth, (int)hourOfDay, (int)minutes, (int)seconds); + long time = gc.getTimeInMillis(); + Date date = new Date((int)year - 1900, (int)month, (int)dayOfMonth, + (int)hourOfDay, (int)minutes, (int)seconds); + long time2 = date.getTime(); + if (time != time2) { + throw new RuntimeException("GregorinCalendar and Date returned different values.\n" + +"year="+year+", month="+month+", dayOfMonth="+dayOfMonth + +"\nhourOfDay="+hourOfDay+", minutes="+minutes+", seconds="+seconds + +"\ntime=" + time + ", time2=" + time2 + +"\nGC=" + gc + "\nDate=" + date); + } + } + + static final int getDelta(int year) { + return (year >= 1970 && year <= 2039) ? 1 : 1<<13; + } + + synchronized static void incrementCounter() { + nThreads++; + } + + synchronized static void decrementCounter() { + nThreads--; + } + + synchronized static int getCounter() { + return nThreads; + } +} diff --git a/jdk/test/java/util/Date/DateRegression.java b/jdk/test/java/util/Date/DateRegression.java new file mode 100644 index 00000000000..70d8a5bf706 --- /dev/null +++ b/jdk/test/java/util/Date/DateRegression.java @@ -0,0 +1,241 @@ +/* + * 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 + * 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 4023247 4027685 4032037 4072029 4073003 4118010 4120606 4133833 4136916 6274757 6314387 + * @library /java/text/testlib + */ + +import java.util.*; + +@SuppressWarnings("deprecation") +public class DateRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new DateRegression().run(args); + } + + /** + * @bug 4023247 + */ + public void Test4023247() { + Date d1 = new Date(0); + Date d2 = new Date(0); + + d1.setYear(96); + d1.setMonth(11); + d1.setDate(22); + d1.setHours(0); + d1.setMinutes(0); + d1.setSeconds(0); + + d2.setYear(96); + d2.setMonth(11); + d2.setDate(22); + d2.setHours(0); + d2.setMinutes(0); + d2.setSeconds(0); + + if (d1.hashCode() != d2.hashCode()) + errln("Fail: Date hashCode misbehaves"); + } + + /** + * @bug 4027685 + */ + public void Test4027685() { + // Should be 01/16/97 00:00:00 + Date nite = new Date("16-JAN-97 12:00 AM"); + // Should be 01/16/97 12:00:00 + Date noon = new Date("16-JAN-97 12:00 PM"); + + logln("Midnight = " + nite + ", Noon = " + noon); + if (!nite.equals(new Date(97, Calendar.JANUARY, 16, 0, 0)) || + !noon.equals(new Date(97, Calendar.JANUARY, 16, 12, 0))) + errln("Fail: Nite/Noon confused"); + } + + /** + * @bug 4032037 + */ + public void Test4032037() { + Date ref = new Date(97, 1, 10); + Date d = new Date(Date.parse("2/10/97")); + logln("Date.parse(2/10/97) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + d = new Date(Date.parse("10 feb 1997")); + logln("Date.parse(10 feb 1997) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + d = new Date("2/10/97"); + logln("Date(2/10/97) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + d = new Date("10 feb 1997"); + logln("Date(10 feb 1997) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + } + + /** + * @bug 4072029 + */ + public void Test4072029() { + TimeZone saveZone = TimeZone.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + Date now = new Date(); + String s = now.toString(); + Date now2 = new Date(now.toString()); + String s2 = now2.toString(); // An hour's difference + + if (!s.equals(s2) || + Math.abs(now.getTime() - now2.getTime()) > 60000 /*one min*/) { + errln("Fail: Roundtrip toString/parse"); + } + } + finally { + TimeZone.setDefault(saveZone); + } + } + + /** + * @bug 4073003 + */ + public void Test4073003() { + Date d = new Date(Date.parse("01/02/1984")); + if (!d.equals(new Date(84, 0, 2))) + errln("Fail: Want 1/2/1984 Got " + d); + d = new Date(Date.parse("02/03/2012")); + if (!d.equals(new Date(112, 1, 3))) + errln("Fail: Want 2/3/2012 Got " + d); + d = new Date(Date.parse("03/04/15")); + if (!d.equals(new Date(115, 2, 4))) + errln("Fail: Want 3/4/2015 Got " + d); + } + + /** + * @bug 4118010 + * Regress bug: + * Feb. 2000 has 29 days, but Date(2000, 1, 29) returns March 01, 2000 + * NOTE: This turned out to be a user error (passing in 2000 instead + * of 2000-1900 to the Date constructor). + */ + public void Test4118010() { + Date d=new java.util.Date(2000-1900, Calendar.FEBRUARY, 29); + int m=d.getMonth(); + int date=d.getDate(); + if (m != Calendar.FEBRUARY || + date != 29) + errln("Fail: Want Feb 29, got " + d); + } + + /** + * @bug 4120606 + * Date objects share state after cloning. + */ + public void Test4120606() { + Date d = new Date(98, Calendar.JUNE, 24); + d.setMonth(Calendar.MAY); + Date e = (Date)d.clone(); + d.setMonth(Calendar.FEBRUARY); + if (e.getMonth() != Calendar.MAY) { + errln("Cloned Date objects share state"); + } + } + + /** + * @bug 4133833 + * Date constructor crashes with parameters out of range, when it should + * normalize. + */ + public void Test4133833() { + Date date = new java.util.Date(12,15,19); + Date exp = new Date(1913-1900, Calendar.APRIL, 19); + if (!date.equals(exp)) + errln("Fail: Want " + exp + + "; got " + date); + } + + /** + * @bug 4136916 + * Date.toString() throws exception in 1.2b4-E + * CANNOT REPRODUCE this bug + */ + public void Test4136916() { + Date time = new Date(); + logln(time.toString()); + } + + /** + * @bug 6274757 + * Date getTime and toString interaction for some time values + */ + public void Test6274757() { + TimeZone savedTz = TimeZone.getDefault(); + try { + // Use a time zone west of GMT. + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + TimeZone jdkGMT = TimeZone.getTimeZone("GMT"); + Calendar jdkCal = Calendar.getInstance(jdkGMT); + jdkCal.clear(); + jdkCal.set(1582, Calendar.OCTOBER, 15); + logln("JDK time: " + jdkCal.getTime().getTime() ); + logln("JDK time (str): " + jdkCal.getTime() ); + logln("Day of month: " + jdkCal.get(Calendar.DAY_OF_MONTH)); + Date co = jdkCal.getTime(); + logln("Change over (Oct 15 1582) = " + co + " (" + + co.getTime() + ")"); + long a = jdkCal.getTime().getTime(); + Date c = jdkCal.getTime(); + c.toString(); + long b = c.getTime(); + + if (a != b) { + errln("ERROR: " + a + " != " + b); + } else { + logln(a + " = " + b); + } + } finally { + TimeZone.setDefault(savedTz); + } + } + + /** + * @bug 6314387 + * JCK6.0: api/java_util/Date/index.html#misc fails, mustang + */ + public void Test6314387() { + Date d = new Date(Long.MAX_VALUE); + int y = d.getYear(); + if (y != 292277094) { + errln("yesr: got " + y + ", expected 292277094"); + } + d = new Date(Long.MIN_VALUE); + y = d.getYear(); + if (y != 292267155) { + errln("yesr: got " + y + ", expected 292267155"); + } + } +} + +//eof diff --git a/jdk/test/java/util/Date/DateTest.java b/jdk/test/java/util/Date/DateTest.java new file mode 100644 index 00000000000..98392760ba3 --- /dev/null +++ b/jdk/test/java/util/Date/DateTest.java @@ -0,0 +1,236 @@ +/* + * 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 + * 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 4143459 + * @summary test Date + * @library /java/text/testlib + */ + +import java.text.*; +import java.util.*; + +@SuppressWarnings("deprecation") +public class DateTest extends IntlTest +{ + public static void main(String[] args) throws Exception { + new DateTest().run(args); + } + + /** + * @bug 4143459 + * Warning: Use TestDefaultZone() for complete testing of this bug. + */ + public void TestDefaultZoneLite() { + // Note: This test is redundant with TestDefaultZone(). It was added by + // request to provide a short&sweet test for this bug. It does not test + // all cases though, so IF THIS TEST PASSES, THE BUG MAY STILL BE + // PRESENT. Use TestDefaultZone() to be sure. + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Date d = new Date(); + d.setYear(98); + d.setMonth(Calendar.JANUARY); + d.setDate(1); + d.setHours(6); + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + if (d.getHours() != 22) { + errln("Fail: Date.setHours()/getHours() ignoring default zone"); + } + } + finally { TimeZone.setDefault(save); } + } + + /** + * @bug 4143459 + */ + public void TestDefaultZone() { + // Various problems can creep up, with the current implementation of Date, + // when the default zone is changed. + + TimeZone saveZone = TimeZone.getDefault(); + try { + + Date d = new Date(); // Trigger static init + Date ref = new Date(883634400000L); // This is Thu Jan 1 1998 6:00 am GMT + String refstr = "Jan 1 1998 6:00"; + TimeZone GMT = TimeZone.getTimeZone("GMT"); + TimeZone PST = TimeZone.getTimeZone("PST"); + + String[] names = { "year", "month", "date", "day of week", "hour", "offset" }; + int[] GMT_EXP = { 98, Calendar.JANUARY, 1, Calendar.THURSDAY - Calendar.SUNDAY, 6, 0 }; + int[] PST_EXP = { 97, Calendar.DECEMBER, 31, Calendar.WEDNESDAY - Calendar.SUNDAY, 22, 480 }; + + // There are two cases to consider: a Date object with no Calendar + // sub-object (most Date objects), and a Date object with a Calendar + // sub-object. We make two passes to cover the two cases. + for (int pass=0; pass<2; ++pass) { + logln(pass == 0 ? "Normal Date object" : "Date with Calendar sub-object"); + + TimeZone.setDefault(GMT); + d = new Date(refstr); + if (pass == 1) { + // Force creation of Calendar sub-object + d.setYear(d.getYear()); + } + if (d.getTime() != ref.getTime()) { + errln("FAIL: new Date(\"" + refstr + "\") x GMT -> " + d + + " " + d.getTime() + " ms"); + } + + int[] fields = { d.getYear(), d.getMonth(), d.getDate(), + d.getDay(), d.getHours(), d.getTimezoneOffset() }; + for (int i=0; i PER_LOOP_LIMIT) + logln("WARNING: Date constructor/getYear slower than " + + PER_LOOP_LIMIT + " ms"); + } + static double PER_LOOP_LIMIT = 3.0; + + /** + * Verify that the Date(String) constructor works. + */ + public void TestParseOfGMT() + { + Date OUT = null; + + /* Input values */ + String stringVal = "Jan 01 00:00:00 GMT 1900"; + long expectedVal = -2208988800000L; + + OUT = new Date( stringVal ); + + if( OUT.getTime( ) == expectedVal ) { + // logln("PASS"); + } + else { + errln( "Expected: " + + new Date( expectedVal ) + + ": " + + expectedVal + + " Received: " + + OUT.toString() + + ": " + + OUT.getTime() ); + } + } + + // Check out Date's behavior with large negative year values; bug 664 + // As of the fix to bug 4056585, Date should work correctly with + // large negative years. + public void TestDateNegativeYears() + { + Date d1= new Date(80,-1,2); + logln(d1.toString()); + d1= new Date(-80,-1,2); + logln(d1.toString()); + boolean e = false; + try { + d1= new Date(-800000,-1,2); + logln(d1.toString()); + } + catch (IllegalArgumentException ex) { + e = true; + } + if (e) errln("FAIL: Saw exception for year -800000"); + else logln("Pass: No exception for year -800000"); + } + + // Verify the behavior of Date + public void TestDate480() + { + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + Date d1=new java.util.Date(97,8,13,10,8,13); + logln("d = "+d1); + Date d2=new java.util.Date(97,8,13,30,8,13); // 20 hours later + logln("d+20h = "+d2); + + double delta = (d2.getTime() - d1.getTime()) / 3600000; + + logln("delta = " + delta + "h"); + + if (delta != 20.0) errln("Expected delta of 20; got " + delta); + + Calendar cal = Calendar.getInstance(); + cal.clear(); + cal.set(1997,8,13,10,8,13); + Date t1 = cal.getTime(); + logln("d = "+t1); + cal.clear(); + cal.set(1997,8,13,30,8,13); // 20 hours later + Date t2 = cal.getTime(); + logln("d+20h = "+t2); + + double delta2 = (t2.getTime() - t1.getTime()) / 3600000; + + logln("delta = " + delta2 + "h"); + + if (delta != 20.0) errln("Expected delta of 20; got " + delta2); + } + finally { + TimeZone.setDefault(save); + } + } +} diff --git a/jdk/test/java/util/Date/TZ.java b/jdk/test/java/util/Date/TZ.java new file mode 100644 index 00000000000..56722a1cdb7 --- /dev/null +++ b/jdk/test/java/util/Date/TZ.java @@ -0,0 +1,58 @@ +/* + * 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 + * 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 4108737 + * @summary java.util.Date doesn't fail if current TimeZone is changed + */ + +import java.util.TimeZone; +import java.util.Date; + +public class TZ { + + public static void main(String args[]) { + TimeZone tz = TimeZone.getDefault(); + try { + testMain(); + } finally { + TimeZone.setDefault(tz); + } + } + + static void testMain() { + String expectedResult = "Sat Feb 01 00:00:00 PST 1997"; + + // load the java.util.Date class in the GMT timezone + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + new Date(); // load the class (to run static initializers) + + // use the class in different timezone + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + @SuppressWarnings("deprecation") + Date date = new Date(97, 1, 1); + if (!date.toString().equals(expectedResult)) { + throw new RuntimeException("Regression bug id #4108737 - Date fails if default time zone changed"); + } + } +} diff --git a/jdk/test/java/util/Date/TimestampTest.java b/jdk/test/java/util/Date/TimestampTest.java new file mode 100644 index 00000000000..950f0a5fb91 --- /dev/null +++ b/jdk/test/java/util/Date/TimestampTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2004, 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 5008227 + * @summary Make sure that changes to the Date class don't break java.sql.Timestamp. + * @modules java.sql + * @library /java/text/testlib + */ + +import java.util.*; +import java.sql.Timestamp; + +public class TimestampTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new TimestampTest().run(args); + } + + /** + * 5008227: java.sql.Timestamp.after() is not returning correct result + * + * Test before(), after(), equals(), compareTo() and getTime(). + */ + public void Test5008227() { + long t = System.currentTimeMillis(); + Timestamp ts1 = new Timestamp(t), ts2 = new Timestamp(t); + ts1.setNanos(999999999); + ts2.setNanos( 1000000); + compareTimestamps(ts1, ts2, 1); + + ts1.setTime(t + 1000); + ts2.setTime(t); + ts1.setNanos( 999999); + ts2.setNanos(999999999); + compareTimestamps(ts1, ts2, 1); + + ts1.setTime(t); + ts2.setTime(t); + ts1.setNanos(123456789); + ts2.setNanos(123456789); + compareTimestamps(ts1, ts2, 0); + + ts1.setTime(t); + ts2.setTime(t); + ts1.setNanos(1); + ts2.setNanos(2); + compareTimestamps(ts1, ts2, -1); + + ts1.setTime(t); + ts2.setTime(t+1000); + ts1.setNanos(999999); + ts2.setNanos( 0); + compareTimestamps(ts1, ts2, -1); + } + + /** + * Compares two Timestamps with the expected result. + * + * @param ts1 the first Timestamp + * @param ts2 the second Timestamp + * @param expect the expected relation between ts1 and ts2; 0 if + * ts1 equals to ts2, or 1 if ts1 is after ts2, or -1 if ts1 is + * before ts2. + */ + private void compareTimestamps(Timestamp ts1, Timestamp ts2, int expected) { + boolean expectedResult = expected > 0; + boolean result = ts1.after(ts2); + if (result != expectedResult) { + errln("ts1.after(ts2) returned " + result + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + + expectedResult = expected < 0; + result = ts1.before(ts2); + if (result != expectedResult) { + errln("ts1.before(ts2) returned " + result + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + + expectedResult = expected == 0; + result = ts1.equals(ts2); + if (result != expectedResult) { + errln("ts1.equals(ts2) returned " + result + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + + int x = ts1.compareTo(ts2); + int y = (x > 0) ? 1 : (x < 0) ? -1 : 0; + if (y != expected) { + errln("ts1.compareTo(ts2) returned " + x + ", expected " + + relation(expected, "") + "0" + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + long t1 = ts1.getTime(); + long t2 = ts2.getTime(); + int z = (t1 > t2) ? 1 : (t1 < t2) ? -1 : 0; + if (z == 0) { + int n1 = ts1.getNanos(); + int n2 = ts2.getNanos(); + z = (n1 > n2) ? 1 : (n1 < n2) ? -1 : 0; + } + if (z != expected) { + errln("ts1.getTime() " + relation(z, "==") + " ts2.getTime(), expected " + + relation(expected, "==") + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + } + + private static String relation(int x, String whenEqual) { + return (x > 0) ? ">" : (x < 0) ? "<" : whenEqual; + } +} diff --git a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.html b/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.html deleted file mode 100644 index 4214467a1e9..00000000000 --- a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.html +++ /dev/null @@ -1,3 +0,0 @@ - -This is a test. - diff --git a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java b/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java deleted file mode 100644 index 7a1969164f0..00000000000 --- a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2007, 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 4126805 - * @ignore until 6842022 is resolved - * @run applet RestrictedBundleTest.html - * @summary I was able to reproduce this bug with 1.2b2, but not with the current 1.2 - * build. It appears that it was fixed by changes to the class-loading mechanism, - * which now throws a ClassNotFoundException where before it was propagating through - * a bogus ClassFormatError. Therefore, this is just an additional regression test - * for whatever bug that was. - */ - -import java.util.ResourceBundle; -import java.applet.Applet; -import java.util.MissingResourceException; - -public class RestrictedBundleTest extends Applet { - public void init() { - super.init(); - try { - ResourceBundle bundle = ResourceBundle.getBundle("unavailable.base.name"); - - throw new RuntimeException("Error: MissingResourceException is not thrown"); - } - catch (MissingResourceException e) { - // other types of error will propagate back out into the test harness - System.out.println("OK"); - } - } -} diff --git a/jdk/test/java/util/TimeZone/Bug4322313.java b/jdk/test/java/util/TimeZone/Bug4322313.java new file mode 100644 index 00000000000..fdd1f7c92ce --- /dev/null +++ b/jdk/test/java/util/TimeZone/Bug4322313.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2001, 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 4322313 + * @summary Make sure that new implementation of custom time zone + * support for TimeZone.getTimeZone() works correctly and the + * getDisplayName() methods are locale independent. + * @library /java/text/testlib + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +public class Bug4322313 extends IntlTest { + private static final int MPM = 60 * 1000; /* Milliseconds per minute */ + private static final Object[][] VALIDS = { + /* given ID rawOffset normalized ID */ + {"GMT+00:00", 0, "GMT+00:00"}, + {"GMT+3:04", 184 * MPM, "GMT+03:04"}, + {"GMT+03:04", 184 * MPM, "GMT+03:04"}, + {"GMT+13:42", 822 * MPM, "GMT+13:42"}, + /* ISO-LATIN-1 digits */ + {"GMT+\u0030\u0031:\u0032\u0033", 83 * MPM, "GMT+01:23"}, + + {"GMT+0", 0, "GMT+00:00"}, + {"GMT+3", 180 * MPM, "GMT+03:00"}, + {"GMT+13", 780 * MPM, "GMT+13:00"}, + {"GMT+034", 34 * MPM, "GMT+00:34"}, + {"GMT+1034", 634 * MPM, "GMT+10:34"}, + + {"GMT-00:00", 0, "GMT-00:00"}, + {"GMT-3:04", -184 * MPM, "GMT-03:04"}, + {"GMT-03:04", -184 * MPM, "GMT-03:04"}, + {"GMT-13:42", -822 * MPM, "GMT-13:42"}, + /* ISO-LATIN-1 digits */ + {"GMT-\u0030\u0031:\u0032\u0033", -83 * MPM, "GMT-01:23"}, + + {"GMT-0", 0, "GMT-00:00"}, + {"GMT-3", -180 * MPM, "GMT-03:00"}, + {"GMT-13", -780 * MPM, "GMT-13:00"}, + {"GMT-034", -34 * MPM, "GMT-00:34"}, + {"GMT-1034", -634 * MPM, "GMT-10:34"}, + }; + + private static final String[] INVALIDS = { + "GMT+5:8", "GMT+11:1", "GMT+23:60", "GMT+24:13", + "GMT+0a:0A", "GMT +13:42", "GMT+ 13:42", "GMT+13 :42", + "GMT+13: 42", "GMT+421:950", "GMT+-13:42", "GMT+!13:42", + "GMT+a", "GMT+24", "GMT+060", "GMT+3003", + "GMT+42195", "GMT+-1", "GMT+-15", " GMT", + + "GMT-5:8", "GMT-11:1", "GMT-23:60", "GMT-24:13", + "GMT-0a:0A", "GMT -13:42", "GMT- 13:42", "GMT-13 :42", + "GMT-13: 42", "GMT-421:950", "GMT-+13:42", "GMT-#13:42", + "GMT-a", "GMT-24", "GMT-060", "GMT-2403", + "GMT-42195", "GMT-+1", "GMT-+15", "G M T", + "GMT+09:00 ", + }; + + void Test4322313() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + boolean err = false; + + Locale[] locs = Locale.getAvailableLocales(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + + for (int i = 0; i < locs.length; i++) { + Locale.setDefault(locs[i]); + + /* Okay case */ + for (int k = 0; k < VALIDS.length; k++) { + TimeZone tz = TimeZone.getTimeZone((String)VALIDS[k][0]); + int offset; + + if (!tz.getID().equals(VALIDS[k][2])) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Invalid TimeZone ID, expected:" + + VALIDS[k][2] + ", got:" + tz.getID() + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Valid TimeZone ID, got:" + VALIDS[k][2]); + } + + offset = tz.getRawOffset(); + if (offset != (int)VALIDS[k][1]) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Invalid RawOffset, expected:" + VALIDS[k][1] + + ", got:" + offset + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Vaild RawOffset, got:" + offset); + } + + offset = tz.getDSTSavings(); + if (offset != 0) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] DSTSavings should be zero, got:" + offset + + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] DSTSavings is zero."); + } + } + + /* Error case */ + for (int k=0; k < INVALIDS.length; k++) { + TimeZone tz = TimeZone.getTimeZone(INVALIDS[k]); + int offset; + + if (!tz.getID().equals("GMT")) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] Invalid TimeZone ID, expected:GMT, got:" + + tz.getID() + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] Valid TimeZone ID, got:" + tz.getID()); + } + + offset = tz.getRawOffset(); + if (offset != 0) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] RawOffset should be zero, got:" + offset + + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] RawOffset is zero."); + } + + offset = tz.getDSTSavings(); + if (offset != 0) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] DSTSavings should be zero, got:" + offset + + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] DSTSavings is zero."); + } + } + + // getDisplayName() tests + { + String normalizedID = "GMT-08:00"; + TimeZone tz = TimeZone.getTimeZone("GMT-8"); + String s; + s = tz.getDisplayName(true, tz.LONG); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + s = tz.getDisplayName(true, tz.SHORT); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + s = tz.getDisplayName(false, tz.LONG); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + s = tz.getDisplayName(false, tz.SHORT); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + } + } + } finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + if (err) { + errln("TimeZone.getTimeZone() test failed"); + } else { + logln("TimeZone.getTimeZone() test passed"); + } + } + + public static void main (String[] args) throws Exception { + new Bug4322313().run(args); + } +} diff --git a/jdk/test/java/util/TimeZone/Bug5097350.java b/jdk/test/java/util/TimeZone/Bug5097350.java new file mode 100644 index 00000000000..ff0894bf3d7 --- /dev/null +++ b/jdk/test/java/util/TimeZone/Bug5097350.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004, 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 5097350 + * @summary Make sure that TimeZone.getTimeZone returns a clone of a cached TimeZone instance. + */ + +import java.util.*; +import java.text.*; + +public class Bug5097350 { + public static void main(String[] args) { + String[] tzids = TimeZone.getAvailableIDs(); + List ids = new ArrayList<>(tzids.length + 10); + ids.addAll(Arrays.asList(tzids)); + // add some custom ids + ids.add("GMT+1"); + ids.add("GMT-7:00"); + ids.add("GMT+10:20"); + ids.add("GMT-00:00"); + ids.add("GMT+00:00"); + + for (String id : ids) { + test(id); + } + } + + private static void test(String id) { + TimeZone tz1 = TimeZone.getTimeZone(id); + int offset1 = tz1.getRawOffset(); + tz1.setRawOffset(offset1 + 13 * 60 * 60 * 1000); + + TimeZone tz2 = TimeZone.getTimeZone(id); + if (tz1 == tz2) { + throw new RuntimeException("TimeZones are identical: " + id); + } + if (offset1 != tz2.getRawOffset()) { + throw new RuntimeException("Offset changed through aliasing: " + id); + } + } +} diff --git a/jdk/test/java/util/TimeZone/CheckDisplayNames.java b/jdk/test/java/util/TimeZone/CheckDisplayNames.java new file mode 100644 index 00000000000..efdb5cdf38d --- /dev/null +++ b/jdk/test/java/util/TimeZone/CheckDisplayNames.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 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 6405639 8008577 + * @summary Validate timezone display names in + * src/java.base/share/classes/sun/util/resources/TimeZoneNames.java. + * @modules java.base/sun.util.resources + * @compile -XDignore.symbol.file CheckDisplayNames.java + * @run main/othervm -Djava.locale.providers=COMPAT,SPI CheckDisplayNames + */ + +import java.util.*; +import sun.util.resources.TimeZoneNames; + +/** + * CheckDisplayNames checks all available time zones in the Java run + * time environment and sees if those have their display names besides doing + * some other test cases. It outputs time zones that don't have display names + * if -source option is specified. + *

    + *
    + *    Usage: java CheckDisplayNames [-source]
    + *              -source ... produces source code for editing TimeZoneNames.java.
    + * 
    + *
    + */ +public class CheckDisplayNames { + + private static boolean err = false; + private static boolean src = false; + + private static Locale[] locales = Locale.getAvailableLocales(); + private static String[] zones = TimeZone.getAvailableIDs(); + + private static String[] zones_118 = { + "ACT", "Australia/Darwin", + "AET", "Australia/Sydney", + "AGT", "America/Buenos_Aires", + "ART", "Africa/Cairo", + "AST", "America/Anchorage", + "BET", "America/Sao_Paulo", + "BST", "Asia/Dacca", + "CAT", "Africa/Harare", + "CNT", "America/St_Johns", + "CST", "America/Chicago", + "CTT", "Asia/Shanghai", + "EAT", "Africa/Addis_Ababa", + "ECT", "Europe/Paris", +// "EET", "Africa/Istanbul", + "EST", "America/New_York", + "HST", "Pacific/Honolulu", + "IET", "America/Indiana/Indianapolis", +// Comment out for this test case fails as the result of L10N for hi_IN. +// "IST", "Asia/Calcutta", + "JST", "Asia/Tokyo", +// "MET", "Asia/Tehran", + "MIT", "Pacific/Apia", + "MST", "America/Denver", + "NET", "Asia/Yerevan", + "NST", "Pacific/Auckland", + "PLT", "Asia/Karachi", + "PNT", "America/Phoenix", + "PRT", "America/Puerto_Rico", + "PST", "America/Los_Angeles", + "SST", "Pacific/Guadalcanal", + "VST", "Asia/Saigon", + }; + + + public static void main(String[] argv) { + Locale reservedLocale = Locale.getDefault(); + try { + if (argv.length == 1 && "-source".equals(argv[0])) { + src = true; + } + + testDisplayNames(); + testRAWoffsetAndDisplayNames(); + test118DisplayNames(); + + if (err) { + throw new RuntimeException( + "TimeZone display name validation failed."); + } else { + System.out.println( + "\nAll test passed.\nTotal number of valid TimeZone id is " + + zones.length); + } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + + } + + /* + * Checks if each timezone ID has display names. If it doesn't and + * "-source" option was specified, source code is generated. + */ + private static void testDisplayNames() { + System.out.println("Checking if each entry in TimeZoneNames is a valid TimeZone ID"); + + Locale.setDefault(Locale.US); + Enumeration data = new TimeZoneNames().getKeys(); + + while (data.hasMoreElements()) { + String name = (String)data.nextElement(); + String id = TimeZone.getTimeZone(name).getID(); + if (!name.equals(id)) { + System.err.println("\t" + name + " doesn't seem to be a valid TimeZone ID."); + err = true; + } + } + + System.out.println("Checking if each TimeZone ID has display names."); + + for (int i = 0; i < zones.length; i++) { + String id = zones[i]; + + if (id != null) { + if (id.startsWith("Etc/GMT")) { + continue; + } + if (id.indexOf("Riyadh8") != -1) { + continue; + } + if (id.equals("GMT0")) { + continue; + } + } + + TimeZone tz = TimeZone.getTimeZone(id); + String name = tz.getDisplayName(); + + if (name == null || name.startsWith("GMT+") || name.startsWith("GMT-")) { + if (src) { + System.out.println("\t {\"" + tz.getID() + "\", " + + "new String[] {\"Standard Time Name\", \"ST\",\n" + + "\t\t\t\t\t\t\"Daylight Time Name\", \"DT\"}},"); + } else { + System.err.println("\t" + tz.getID() + " doesn't seem to have display names"); + err = true; + } + } + } + } + + /* + * Compares + * - raw DST offset + * - short display names in non-DST + * - short display names in DST + * - long display names in DST + * of two timezones whose long display names in non-DST are same. + * If one of these are different, there may be a bug. + */ + private static void testRAWoffsetAndDisplayNames() { + System.out.println("Checking if each entry in TimeZoneNames is a valid TimeZone ID"); + + HashMap map = new HashMap(); + + for (int i = 0; i < locales.length; i++) { + map.clear(); + + for (int j = 0; j < zones.length; j++) { + TimeZone tz1 = TimeZone.getTimeZone(zones[j]); + String name = tz1.getDisplayName(false, TimeZone.LONG, locales[i]); + + if (map.containsKey(name)) { + TimeZone tz2 = map.get(name); + + int offset1 = tz1.getRawOffset(); + int offset2 = tz2.getRawOffset(); + if (offset1 != offset2) { + System.err.println("Two timezones which have the same long display name \"" + + name + "\" in non-DST have different DST offsets in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + offset1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + offset2 + ")"); + } + + String name1 = tz1.getDisplayName(false, TimeZone.SHORT, locales[i]); + String name2 = tz2.getDisplayName(false, TimeZone.SHORT, locales[i]); + if (!(name1.equals("GMT") && name2.equals("GMT")) && + !(name1.equals("CET") && name2.equals("MET")) && + !(name1.equals("MET") && name2.equals("CET"))) { + if (!name1.equals(name2)) { + System.err.println("Two timezones which have the same short display name \"" + + name + + "\" in non-DST have different short display names in non-DST in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + name2 + ")"); + } + + name1 = tz1.getDisplayName(true, TimeZone.SHORT, locales[i]); + name2 = tz2.getDisplayName(true, TimeZone.SHORT, locales[i]); + if (!name1.equals(name2)) { + System.err.println("Two timezones which have the same short display name \"" + + name + + "\" in non-DST have different short display names in DST in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + name2 + ")"); + } + + name1 = tz1.getDisplayName(true, TimeZone.LONG, locales[i]); + name2 = tz2.getDisplayName(true, TimeZone.LONG, locales[i]); + if (!name1.equals(name2)) { + System.err.println("Two timezones which have the same long display name \"" + + name + + "\" in non-DST have different long display names in DST in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + name2 + ")"); + } + } + } else { + map.put(name, tz1); + } + } + } + } + + /* + * Compares three-letter timezones' display names with corresponding + * "popular" timezones. + */ + private static void test118DisplayNames() { + System.out.println("Checking compatibility of Java 1.1.X's three-letter timezones"); + + for (int i = 0; i < zones_118.length; i+=2) { + String id_118 = zones_118[i]; + String id_later = zones_118[i+1]; + String zone_118, zone_later, localename; + TimeZone tz_118 = TimeZone.getTimeZone(id_118); + TimeZone tz_later = TimeZone.getTimeZone(id_later); + + for (int j = 0; j < locales.length; j++) { + localename = locales[j].toString(); + zone_118 = tz_118.getDisplayName(false, TimeZone.SHORT, locales[j]); + zone_later = tz_later.getDisplayName(false, TimeZone.SHORT, locales[j]); + check(id_118, id_later, zone_118, zone_later, "short", "non-DST", localename); + + zone_118 = tz_118.getDisplayName(true, TimeZone.SHORT, locales[j]); + zone_later = tz_later.getDisplayName(true, TimeZone.SHORT, locales[j]); + check(id_118, id_later, zone_118, zone_later, "short", "DST", localename); + + zone_118 = tz_118.getDisplayName(false, TimeZone.LONG, locales[j]); + zone_later = tz_later.getDisplayName(false, TimeZone.LONG, locales[j]); + check(id_118, id_later, zone_118, zone_later, "long", "non-DST", localename); + + zone_118 = tz_118.getDisplayName(true, TimeZone.LONG, locales[j]); + zone_later = tz_later.getDisplayName(true, TimeZone.LONG, locales[j]); + check(id_118, id_later, zone_118, zone_later, "long", "DST", localename); + } + } + } + + private static void check(String zoneID_118, String zoneID_later, + String zonename_118, String zonename_later, + String format, String dst, String loc) { + if (!zonename_118.equals(zonename_later)) { + System.err.println("JDK 118 TimeZone \"" + zoneID_118 + + "\" has a different " + format + + " display name from its equivalent timezone \"" + + zoneID_later + "\" in " + dst + " in " + loc + " locale."); + System.err.println(" Got: " + zonename_118 + ", Expected: " + + zonename_later); + err = true; + } + } + +} diff --git a/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.html b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.html new file mode 100644 index 00000000000..1fa0659ed63 --- /dev/null +++ b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.html @@ -0,0 +1,74 @@ + + + + + + Disable Auto-adjust Daylight Saving Time Test + + + +This applet tests the platform time zone detection on all platforms (Part I) +and on/off of DST adjustment on Windows (Part II). + +Part I: + +Observe the displayed Time zone ID and the local time. If you can change +the platform time zone setting, try several time zones. If both the ID and +the local time, including the time zone name and its time zone offset, are +always correct, Part I passes. Note that some time zone IDs have their +aliases that may be displayed. For example, "US/Pacific" is an alias of +"America/Los_Angeles". + +If you are running this applet in non-English locale, the time zone names +can be displayed in the local language and English by pushing the +English/Local button. + +If platform time zones are NOT detected correctly, press the Fail button +to finish this applet. + +If this platform is Windows, proceed to Part II. Otherwise, press the Pass +button to finish this applet. + +Part II: + +Note that Part II may require the Administrator privilege to change +Windows setting. + + 1. Open the Date and Time control panel. + 2. Select any time zone where daylight saving time is *currently* in effect, + such as "(GMT-08:00) Pacific Time (US & Canada); Tijuana", + "(GMT+10:00) Canberra, Melbourne, Sydney", and Apply. + 3. Observe the local time on the control panel (Date&Time pane) and + the applet local time should be the same (daylight time). + 4. Clear "Automatically adjust clock for daylight saving changes" and Apply. + 5. Observe the two local times should be the same (standard time). + 6. Select "Automatically adjust clock for daylight saving changes" and Apply. + +If the local time in the control panel and applet are always the same, +then this test passes. Press the Pass or Fail button based on the Part II +result and finish this applet. + + + + diff --git a/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.java b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.java new file mode 100644 index 00000000000..a6d3ac50866 --- /dev/null +++ b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.java @@ -0,0 +1,108 @@ +/* + * 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 + * 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 4296930 5033603 7092679 + * @summary Make sure that Java runtime detects the platform time zone + * correctly. Also make sure that the system time zone detection code + * detects the "Automatically adjust clock for daylight saving + * changes" setting correctly on Windows. + * @run applet/manual=yesno DefaultTimeZoneTest.html + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.text.*; +import java.util.*; + +public class DefaultTimeZoneTest extends JApplet implements Runnable { + static final String FORMAT = "yyyy-MM-dd HH:mm:ss zzzz (XXX)"; + JLabel tzid; + JLabel label; + SimpleDateFormat sdf = new SimpleDateFormat(FORMAT); + JButton button = new JButton("English"); + Thread clock; + boolean english = false; + + @Override + public void init() { + tzid = new JLabel("Time zone ID: " + sdf.getTimeZone().getID(), SwingConstants.CENTER); + tzid.setAlignmentX(Component.CENTER_ALIGNMENT); + label = new JLabel(sdf.format(new Date()), SwingConstants.CENTER); + label.setAlignmentX(Component.CENTER_ALIGNMENT); + button.addActionListener(new ActionListener() { + @Override + @SuppressWarnings("deprecation") + public void actionPerformed(ActionEvent e) { + english = (english == false); + Locale loc = english ? Locale.US : Locale.getDefault(); + sdf = new SimpleDateFormat(FORMAT, loc); + button.setLabel(!english ? "English" : "Local"); + } + }); + button.setAlignmentX(Component.CENTER_ALIGNMENT); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + panel.add(tzid); + panel.add(Box.createRigidArea(new Dimension(0, 5))); + panel.add(label); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + panel.add(button); + getContentPane().add(panel); + } + + @Override + public void start() { + clock = new Thread(this); + clock.start(); + } + + @Override + public void stop() { + clock = null; + } + + @Override + public void run() { + Thread me = Thread.currentThread(); + + while (clock == me) { + // Reset the default time zone so that + // TimeZone.getDefault will detect the platform time zone + TimeZone.setDefault(null); + System.setProperty("user.timezone", ""); + TimeZone tz = TimeZone.getDefault(); + sdf.setTimeZone(tz); + tzid.setText("Time zone ID: " + tz.getID()); + label.setText(sdf.format(new Date())); + repaint(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } +} diff --git a/jdk/test/java/util/TimeZone/HongKong.java b/jdk/test/java/util/TimeZone/HongKong.java new file mode 100644 index 00000000000..ef9c3f923f5 --- /dev/null +++ b/jdk/test/java/util/TimeZone/HongKong.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2001, 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 4487276 8008577 + * @summary Verify that Hong Kong locale uses traditional Chinese names. + * @run main/othervm -Djava.locale.providers=COMPAT,SPI HongKong + */ + +import java.util.Locale; +import java.util.TimeZone; + +public class HongKong { + public static void main(String[] args) { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(new Locale("zh", "HK")); + checkCountry(Locale.GERMANY, "\u5fb7\u570b"); + checkCountry(Locale.FRANCE, "\u6cd5\u570b"); + checkCountry(Locale.ITALY, "\u7fa9\u5927\u5229"); + checkTimeZone("Asia/Shanghai", + "\u4e2d\u570b\u6a19\u6e96\u6642\u9593"); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + private static void checkCountry(Locale country, String expected) { + String actual = country.getDisplayCountry(); + if (!expected.equals(actual)) { + throw new RuntimeException(); + } + } + + private static void checkTimeZone(String timeZoneID, String expected) { + TimeZone timeZone = TimeZone.getTimeZone(timeZoneID); + String actual = timeZone.getDisplayName(); + if (!expected.equals(actual)) { + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/util/TimeZone/IDTest.java b/jdk/test/java/util/TimeZone/IDTest.java new file mode 100644 index 00000000000..d5396b619b8 --- /dev/null +++ b/jdk/test/java/util/TimeZone/IDTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002, 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 4509255 5055567 6176318 7090844 + * @summary Tests consistencies of time zone IDs. + */ + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; + +public class IDTest { + public static void main(String[] args) { + Set ids = new HashSet<>(); + Map> tree = new TreeMap<>(); + + String[] tzs = TimeZone.getAvailableIDs(); + String[] tzs2 = TimeZone.getAvailableIDs(); + if (tzs.length != tzs2.length) { + throw new RuntimeException("tzs.length(" + tzs.length + + ") != tzs2.length(" + tzs2.length + ")"); + } + for (int i = 0; i < tzs.length; i++) { + if (tzs[i] != tzs2[i]) { + throw new RuntimeException(i + ": " + tzs[i] + " != " + tzs2[i]); + } + } + + System.out.println("Total: " + tzs.length + " time zone IDs"); + for (String id : tzs) { + ids.add(id); + TimeZone tz = TimeZone.getTimeZone(id); + Integer offset = tz.getRawOffset(); + Set s = tree.get(offset); + if (s == null) { + s = new HashSet<>(); + tree.put(offset, s); + } + s.add(id); + } + + for (Integer key : tree.keySet()) { + Set s1 = tree.get(key); + + // Make sure no duplicates in the other sets + for (Integer k : tree.keySet()) { + if (k.equals(key)) { + continue; + } + Set s2 = new HashSet<>(tree.get(k)); + s2.retainAll(s1); + if (!s2.isEmpty()) { + throw new RuntimeException("s1 included in the subset for " + (k.intValue()/60000) + + " (" + s2 + " shouldn't be in s1)"); + } + } + + // Check the getAvailableIDs(int) call to return the same + // set of IDs + int offset = key.intValue(); + tzs = TimeZone.getAvailableIDs(offset); + tzs2 = TimeZone.getAvailableIDs(offset); + if (!Arrays.equals(tzs, tzs2)) { + throw new RuntimeException("inconsistent tzs from getAvailableIDs("+offset+")"); + } + Set s2 = new HashSet<>(); + s2.addAll(Arrays.asList(tzs)); + if (!s1.equals(s2)) { + throw new RuntimeException("s1 != s2 for " + offset/60000 + + " (diff=" + getDiff(s1, s2) + ")"); + } + if (!ids.containsAll(s2)) { + throw new RuntimeException("s2 isn't a subset of ids (" + getDiff(s2, ids) + + " not in ids)"); + } + } + + for (Integer key : tree.keySet()) { + Set s1 = tree.get(key); + ids.removeAll(s1); + } + if (!ids.isEmpty()) { + throw new RuntimeException("ids didn't become empty. (" + ids + ")"); + } + } + + private static String getDiff(Set set1, Set set2) { + Set s1 = new HashSet<>(set1); + s1.removeAll(set2); + + Set s2 = new HashSet<>(set2); + s2.removeAll(set1); + s2.addAll(s1); + return s2.toString(); + } +} diff --git a/jdk/test/java/util/TimeZone/TimeZoneBoundaryTest.java b/jdk/test/java/util/TimeZone/TimeZoneBoundaryTest.java new file mode 100644 index 00000000000..a1d44ea080d --- /dev/null +++ b/jdk/test/java/util/TimeZone/TimeZoneBoundaryTest.java @@ -0,0 +1,491 @@ +/* + * 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 + * 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 /java/text/testlib + * @summary test Time Zone Boundary + */ + +import java.text.*; +import java.util.*; + +/** + * A test which discovers the boundaries of DST programmatically and verifies + * that they are correct. + */ +public class TimeZoneBoundaryTest extends IntlTest +{ + static final int ONE_SECOND = 1000; + static final int ONE_MINUTE = 60*ONE_SECOND; + static final int ONE_HOUR = 60*ONE_MINUTE; + static final long ONE_DAY = 24*ONE_HOUR; + static final long ONE_YEAR = (long)(365.25 * ONE_DAY); + static final long SIX_MONTHS = ONE_YEAR / 2; + + static final int MONTH_LENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31}; + + // These values are empirically determined to be correct + static final long PST_1997_BEG = 860320800000L; + static final long PST_1997_END = 877856400000L; + + // Minimum interval for binary searches in ms; should be no larger + // than 1000. + static final long INTERVAL = 10; // Milliseconds + + static final String AUSTRALIA = "Australia/Adelaide"; + static final long AUSTRALIA_1997_BEG = 877797000000L; + static final long AUSTRALIA_1997_END = 859653000000L; + + public static void main(String[] args) throws Exception { + new TimeZoneBoundaryTest().run(args); + } + + /** + * Date.toString().substring() Boundary Test + * Look for a DST changeover to occur within 6 months of the given Date. + * The initial Date.toString() should yield a string containing the + * startMode as a SUBSTRING. The boundary will be tested to be + * at the expectedBoundary value. + */ + void findDaylightBoundaryUsingDate(Date d, String startMode, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + if (d.toString().indexOf(startMode) == -1) + { + logln("Error: " + startMode + " not present in " + d); + } + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + String s = new Date(mid).toString(); + // logln(s); + if (s.indexOf(startMode) != -1) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Date Before: " + showDate(min)); + logln("Date After: " + showDate(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, long expectedBoundary) + { + findDaylightBoundaryUsingTimeZone(d, startsInDST, expectedBoundary, + TimeZone.getDefault()); + } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, + long expectedBoundary, TimeZone tz) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + if (tz.inDaylightTime(d) != startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + d + ") != " + startsInDST); + startsInDST = !startsInDST; // Flip over; find the apparent value + } + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + (new Date(max)) + ") != " + (!startsInDST)); + return; + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + boolean isIn = tz.inDaylightTime(new Date(mid)); + if (isIn == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln(tz.getID() + " Before: " + showDate(min, tz)); + logln(tz.getID() + " After: " + showDate(max, tz)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + private static String showDate(long l) + { + return showDate(new Date(l)); + } + + @SuppressWarnings("deprecation") + private static String showDate(Date d) + { + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + d.getTime(); + } + + private static String showDate(long l, TimeZone z) + { + return showDate(new Date(l), z); + } + + @SuppressWarnings("deprecation") + private static String showDate(Date d, TimeZone zone) + { + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + fmt.setTimeZone(zone); + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + fmt.format(d); + } + + private static String showNN(int n) + { + return ((n < 10) ? "0" : "") + n; + } + + /** + * Given a date, a TimeZone, and expected values for inDaylightTime, + * useDaylightTime, zone and DST offset, verify that this is the case. + */ + void verifyDST(Date d, TimeZone time_zone, + boolean expUseDaylightTime, boolean expInDaylightTime, + int expZoneOffset, int expDSTOffset) + { + logln("-- Verifying time " + d + + " in zone " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) == expInDaylightTime) + logln("PASS: inDaylightTime = " + time_zone.inDaylightTime(d)); + else + errln("FAIL: inDaylightTime = " + time_zone.inDaylightTime(d)); + + if (time_zone.useDaylightTime() == expUseDaylightTime) + logln("PASS: useDaylightTime = " + time_zone.useDaylightTime()); + else + errln("FAIL: useDaylightTime = " + time_zone.useDaylightTime()); + + if (time_zone.getRawOffset() == expZoneOffset) + logln("PASS: getRawOffset() = " + expZoneOffset/(double)ONE_HOUR); + else + errln("FAIL: getRawOffset() = " + time_zone.getRawOffset()/(double)ONE_HOUR + + "; expected " + expZoneOffset/(double)ONE_HOUR); + + GregorianCalendar gc = new GregorianCalendar(time_zone); + gc.setTime(d); + int offset = time_zone.getOffset(gc.get(gc.ERA), gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), gc.get(gc.DAY_OF_WEEK), + ((gc.get(gc.HOUR_OF_DAY) * 60 + + gc.get(gc.MINUTE)) * 60 + + gc.get(gc.SECOND)) * 1000 + + gc.get(gc.MILLISECOND)); + if (offset == expDSTOffset) + logln("PASS: getOffset() = " + offset/(double)ONE_HOUR); + else + errln("FAIL: getOffset() = " + offset/(double)ONE_HOUR + + "; expected " + expDSTOffset/(double)ONE_HOUR); + } + + @SuppressWarnings("deprecation") + public void TestBoundaries() + { + TimeZone pst = TimeZone.getTimeZone("PST"); + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(pst); + + // DST changeover for PST is 4/6/1997 at 2 hours past midnight + Date d = new Date(97,Calendar.APRIL,6); + + // i is minutes past midnight standard time + for (int i=60; i<=180; i+=15) + { + boolean inDST = (i >= 120); + Date e = new Date(d.getTime() + i*60*1000); + verifyDST(e, pst, true, inDST, -8*ONE_HOUR, + inDST ? -7*ONE_HOUR : -8*ONE_HOUR); + } + + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,0,1), "PST", PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,6,1), "PDT", PST_1997_END); + + // Southern hemisphere test + logln("========================================"); + TimeZone z = TimeZone.getTimeZone(AUSTRALIA); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), true, AUSTRALIA_1997_END, z); + + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), false, PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true, PST_1997_END); + } finally { + TimeZone.setDefault(save); + } + } + + void testUsingBinarySearch(SimpleTimeZone tz, Date d, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + (long)(365.25 / 2 * ONE_DAY); + + // First check the boundaries + boolean startsInDST = tz.inDaylightTime(d); + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST)); + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Binary Search Before: " + showDate(min)); + logln("Binary Search After: " + showDate(max)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + /* + static void testUsingMillis(Date d, boolean startsInDST) + { + long millis = d.getTime(); + long max = millis + (long)(370 * ONE_DAY); // A year plus extra + + boolean lastDST = startsInDST; + while (millis < max) + { + cal.setTime(new Date(millis)); + boolean inDaylight = cal.inDaylightTime(); + + if (inDaylight != lastDST) + { + logln("Switch " + (inDaylight ? "into" : "out of") + + " DST at " + (new Date(millis))); + lastDST = inDaylight; + } + + millis += 15*ONE_MINUTE; + } + } + */ + + /** + * Test new rule formats. + */ + @SuppressWarnings("deprecation") + public void TestNewRules() + { + //logln(Locale.getDefault().getDisplayName()); + //logln(TimeZone.getDefault().getID()); + //logln(new Date(0)); + + if (true) + { + // Doesn't matter what the default TimeZone is here, since we + // are creating our own TimeZone objects. + + SimpleTimeZone tz; + + logln("-----------------------------------------------------------------"); + logln("Aug 2ndTues .. Mar 15"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_1", + Calendar.AUGUST, 2, Calendar.TUESDAY, 2*ONE_HOUR, + Calendar.MARCH, 15, 0, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,0,1), 858416400000L); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,6,1), 871380000000L); + + logln("-----------------------------------------------------------------"); + logln("Apr Wed>=14 .. Sep Sun<=20"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_2", + Calendar.APRIL, 14, -Calendar.WEDNESDAY, 2*ONE_HOUR, + Calendar.SEPTEMBER, -20, -Calendar.SUNDAY, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,0,1), 861184800000L); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,6,1), 874227600000L); + } + + /* + if (true) + { + logln("========================================"); + logln("Stepping using millis"); + testUsingMillis(new Date(97,0,1), false); + } + + if (true) + { + logln("========================================"); + logln("Stepping using fields"); + testUsingFields(1997, false); + } + + if (false) + { + cal.clear(); + cal.set(1997, 3, 5, 10, 0); + // cal.inDaylightTime(); + logln("Date = " + cal.getTime()); + logln("Millis = " + cal.getTime().getTime()/3600000); + } + */ + } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + // Long Bug + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + //public void Test3() + //{ + // findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true); + //} + + /** + * Find boundaries by stepping. + */ + @SuppressWarnings("deprecation") + void findBoundariesStepwise(int year, long interval, TimeZone z, int expectedChanges) + { + Date d = new Date(year - 1900, Calendar.JANUARY, 1); + long time = d.getTime(); // ms + long limit = time + ONE_YEAR + ONE_DAY; + boolean lastState = z.inDaylightTime(d); + int changes = 0; + logln("-- Zone " + z.getID() + " starts in " + year + " with DST = " + lastState); + logln("useDaylightTime = " + z.useDaylightTime()); + while (time < limit) + { + d.setTime(time); + boolean state = z.inDaylightTime(d); + if (state != lastState) + { + logln((state ? "Entry " : "Exit ") + + "at " + d); + lastState = state; + ++changes; + } + time += interval; + } + if (changes == 0) + { + if (!lastState && !z.useDaylightTime()) logln("No DST"); + else errln("FAIL: Timezone<" + z.getID() + "> DST all year, or no DST with true useDaylightTime"); + } + else if (changes != 2) + { + errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; should see 0 or 2"); + } + else if (!z.useDaylightTime()) + { + errln("FAIL: Timezone<" + z.getID() + "> useDaylightTime false but 2 changes seen"); + } + if (changes != expectedChanges) + { + errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; expected " + expectedChanges); + } + } + + public void TestStepwise() + { + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("ACT"), 0); + // "EST" is disabled because its behavior depends on the mapping property. (6466476). + //findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("EST"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("HST"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST8PDT"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST8PDT"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Japan"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Europe/Paris"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("America/Los_Angeles"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone(AUSTRALIA), 2); + } +} diff --git a/jdk/test/java/util/TimeZone/TimeZoneRegression.java b/jdk/test/java/util/TimeZone/TimeZoneRegression.java new file mode 100644 index 00000000000..8b9e2f4a22a --- /dev/null +++ b/jdk/test/java/util/TimeZone/TimeZoneRegression.java @@ -0,0 +1,995 @@ +/* + * 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 + * 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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429 + * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960 + * 4966229 6433179 6851214 8007520 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression + */ + +import java.util.*; +import java.io.*; +import java.text.*; + +public class TimeZoneRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new TimeZoneRegression().run(args); + } + + public void Test4052967() { + logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***"); + String id = TimeZone.getDefault().getID(); + logln("user.timezone: " + System.getProperty("user.timezone", "")); + logln("TimeZone.getDefault().getID(): " + id); + logln(new Date().toString()); + logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***"); + } + + public void Test4073209() { + TimeZone z1 = TimeZone.getTimeZone("PST"); + TimeZone z2 = TimeZone.getTimeZone("PST"); + if (z1 == z2) { + errln("Fail: TimeZone should return clones"); + } + } + + @SuppressWarnings("deprecation") + public void Test4073215() { + SimpleTimeZone z = new SimpleTimeZone(0, "GMT"); + if (z.useDaylightTime()) { + errln("Fail: Fix test to start with non-DST zone"); + } + z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0); + z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0); + if (!z.useDaylightTime()) { + errln("Fail: DST not active"); + } + if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) || + !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) || + z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) { + errln("Fail: DST not working as expected"); + } + } + + /** + * The expected behavior of TimeZone around the boundaries is: + * (Assume transition time of 2:00 AM) + * day of onset 1:59 AM STD = display name 1:59 AM ST + * 2:00 AM STD = display name 3:00 AM DT + * day of end 0:59 AM STD = display name 1:59 AM DT + * 1:00 AM STD = display name 1:00 AM ST + */ + public void Test4084933() { + // test both SimpleTimeZone and ZoneInfo objects. + // @since 1.4 + sub4084933(getPST()); + sub4084933(TimeZone.getTimeZone("PST")); + } + + private void sub4084933(TimeZone tz) { + long offset1 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)); + long offset2 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset3 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)); + long offset4 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1); + + /* + * The following was added just for consistency. It shows that going *to* Daylight + * Savings Time (PDT) does work at 2am. + */ + + long offset5 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)); + long offset6 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset7 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)); + long offset8 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1); + + long SToffset = -8 * 60*60*1000L; + long DToffset = -7 * 60*60*1000L; + if (offset1 != SToffset || offset2 != SToffset || + offset3 != SToffset || offset4 != DToffset || + offset5 != DToffset || offset6 != SToffset || + offset7 != SToffset || offset8 != SToffset) + errln("Fail: TimeZone misbehaving"); { + } + } + + public void Test4096952() { + String[] ZONES = { "GMT", "MET", "IST" }; + boolean pass = true; + try { + for (int i=0; i= ONE_DAY) { + millis -= ONE_DAY; + ++date; + dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7); + } + + tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA), + testCal.get(Calendar.YEAR), + testCal.get(Calendar.MONTH), + date, + dow, + millis); + tzRawOffset = testTZ.getRawOffset(); + tzOffsetFloat = new Float((float)tzOffset/(float)3600000); + tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000); + + Date testDate = testCal.getTime(); + + boolean inDaylightTime = testTZ.inDaylightTime(testDate); + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + sdf.setCalendar(testCal); + String inDaylightTimeString; + + boolean passed; + + if (inDaylightTime) + { + inDaylightTimeString = " DST "; + passed = (tzOffset == (tzRawOffset + 3600000)); + } + else + { + inDaylightTimeString = " "; + passed = (tzOffset == tzRawOffset); + } + + String output = testTZ.getID() + " " + sdf.format(testDate) + + " Offset(" + tzOffsetFloat + ")" + + " RawOffset(" + tzRawOffsetFloat + ")" + + " " + millis/(float)3600000 + " " + + inDaylightTimeString; + + if (passed) + output += " "; + else + output += "ERROR"; + + if (passed) logln(output); else errln(output); + return passed; + } + + /** + * CANNOT REPRODUDE + * + * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never + * should have been made public. It's simply too hard to use correctly. + * + * The original test code failed to do the following: + * (1) Call Calendar.setTime() before getting the fields! + * (2) Use the right millis (as usual) for getOffset(); they were passing + * in the MILLIS field, instead of the STANDARD MILLIS IN DAY. + * When you fix these two problems, the test passes, as expected. + */ + public void Test4126678() { + // Note: this test depends on the PST time zone. + TimeZone initialZone = TimeZone.getDefault(); + + // test both SimpleTimeZone and ZoneInfo objects. + // @since 1.4 + sub4126678(getPST()); + sub4126678(TimeZone.getTimeZone("PST")); + + // restore the initial time zone so that this test case + // doesn't affect the others. + TimeZone.setDefault(initialZone); + } + + @SuppressWarnings("deprecation") + private void sub4126678(TimeZone tz) { + Calendar cal = Calendar.getInstance(); + TimeZone.setDefault(tz); + cal.setTimeZone(tz); + + Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0); + // the dt value is local time in PST. + if (!tz.inDaylightTime(dt)) + errln("We're not in Daylight Savings Time and we should be.\n"); + + cal.setTime(dt); + int era = cal.get(Calendar.ERA); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH); + int day = cal.get(Calendar.DATE); + int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); + int millis = cal.get(Calendar.MILLISECOND) + + (cal.get(Calendar.SECOND) + + (cal.get(Calendar.MINUTE) + + (cal.get(Calendar.HOUR) * 60) * 60) * 1000) - + cal.get(Calendar.DST_OFFSET); + + long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis); + long raw_offset = tz.getRawOffset(); + if (offset == raw_offset) { + errln("Offsets should not match when in DST"); + } + } + + /** + * TimeZone.getAvailableIDs(int) throws exception for certain values, + * due to a faulty constant in TimeZone.java. + */ + public void Test4151406() { + int max = 0; + for (int h=-28; h<=30; ++h) { + // h is in half-hours from GMT; rawoffset is in millis + int rawoffset = h * 1800000; + int hh = (h<0) ? -h : h; + String hname = ((h<0) ? "GMT-" : "GMT+") + + ((hh/2 < 10) ? "0" : "") + + (hh/2) + ':' + + ((hh%2==0) ? "00" : "30"); + try { + String[] ids = TimeZone.getAvailableIDs(rawoffset); + if (ids.length > max) max = ids.length; + logln(hname + ' ' + ids.length + + ((ids.length > 0) ? (" e.g. " + ids[0]) : "")); + } catch (Exception e) { + errln(hname + ' ' + "Fail: " + e); + } + } + logln("Maximum zones per offset = " + max); + } + + public void Test4151429() { + try { + TimeZone tz = TimeZone.getTimeZone("GMT"); + String name = tz.getDisplayName(true, Integer.MAX_VALUE, + Locale.getDefault()); + errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()"); + } catch(IllegalArgumentException e) {} + } + + /** + * SimpleTimeZone accepts illegal DST savings values. These values + * must be non-zero. There is no upper limit at this time. + */ + public void Test4154525() { + final int GOOD = 1, BAD = 0; + int[] DATA = { + 1, GOOD, + 0, BAD, + -1, BAD, + 60*60*1000, GOOD, + Integer.MIN_VALUE, BAD, + // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time + }; + for (int i=0; i) should work but throws " + ex) + : ", ) should fail but doesn't")); + } + + ex = null; + try { + SimpleTimeZone temp = new SimpleTimeZone(0, "Z", + GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME, + month, day, dayOfWeek, time); + } catch (IllegalArgumentException e) { + ex = e; + } + if ((ex == null) != shouldBeGood) { + errln("SimpleTimeZone(, month=" + month + ", day=" + day + + ", dayOfWeek=" + dayOfWeek + ", time=" + time + + (shouldBeGood ? (") should work but throws " + ex) + : ") should fail but doesn't")); + } + } + } + + /** + * SimpleTimeZone.getOffset accepts illegal arguments. + */ + public void Test4154650() { + final int GOOD=1, BAD=0; + final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST; + final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000; + int[] DATA = { + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, + }; + + TimeZone tz = TimeZone.getDefault(); + for (int i=0; i " + DATA[i+1] + ", exp " + DATA[i+2]); + } + } + } + + /** + * SimpleTimeZone allows invalid DOM values. + */ + public void Test4184229() { + SimpleTimeZone zone = null; + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 startDay"); + } catch(IllegalArgumentException e) { + logln("(a) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 endDay"); + } catch(IllegalArgumentException e) { + logln("(b) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 startDay +savings"); + } catch(IllegalArgumentException e) { + logln("(c) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 endDay +savings"); + } catch(IllegalArgumentException e) { + logln("(d) " + e.getMessage()); + } + // Make a valid constructor call for subsequent tests. + zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0); + try { + zone.setStartRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); + } catch(IllegalArgumentException e) { + logln("(e) " + e.getMessage()); + } + try { + zone.setStartRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule"); + } catch(IllegalArgumentException e) { + logln("(f) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings"); + } catch(IllegalArgumentException e) { + logln("(g) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule"); + } catch(IllegalArgumentException e) { + logln("(h) " + e.getMessage()); + } + } + + /** + * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get + * of 2/29/1996 (leap day). + */ + public void Test4208960 () { + // test both SimpleTimeZone and ZoneInfo objects. + // @since 1.4 + sub4208960(getPST()); + sub4208960(TimeZone.getTimeZone("PST")); + } + + private void sub4208960(TimeZone tz) { + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + } catch (IllegalArgumentException e) { + errln("FAILED: to get TimeZone.getOffset(2/29/96)"); + } + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception."); + } catch (IllegalArgumentException e) { + logln("got IllegalArgumentException"); + } + } + + /** + * 4966229: java.util.Date methods may works incorrect. + * sun.util.calendar.ZoneInfo doesn't clone properly. + */ + @SuppressWarnings("deprecation") + public void Test4966229() { + TimeZone savedTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Date d = new Date(2100-1900, 5, 1); // specify year >2037 + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); + + Calendar cal = new GregorianCalendar(tz); + cal.setTime(d); + + // Change the raw offset in tz + int offset = tz.getRawOffset(); + tz.setRawOffset(0); + + TimeZone tz2 = (TimeZone) tz.clone(); + Calendar cal2 = new GregorianCalendar(tz2); + cal2.setTime(d); + int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY); + + // Restore the GMT offset in tz which shouldn't affect tz2 + tz.setRawOffset(offset); + cal2.setTime(d); + int hourOfDay = cal2.get(cal.HOUR_OF_DAY); + if (hourOfDay != expectedHourOfDay) { + errln("wrong hour of day: got: " + hourOfDay + + ", expected: " + expectedHourOfDay); + } + } finally { + TimeZone.setDefault(savedTZ); + } + } + + /** + * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+ + */ + public void Test6433179() { + // Use the old America/Winnipeg rule for testing. Note that + // startMode is WALL_TIME for testing. It's actually + // STANDARD_TIME, though. + //Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S + //Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D + TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg", + Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + 1*ONE_HOUR); + Calendar cal = Calendar.getInstance(tz, Locale.US); + cal.clear(); + cal.set(2039, Calendar.OCTOBER, 1); + cal.getTime(); + cal.set(cal.DAY_OF_WEEK, cal.SUNDAY); + cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1); + cal.add(Calendar.HOUR_OF_DAY, 2); + if (cal.get(cal.DST_OFFSET) == 0) { + errln("Should still be in DST."); + } + } + + private static final int ONE_HOUR = 60 * 60 * 1000; + /** + * Returns an instance of SimpleTimeZone for + * "PST". (TimeZone.getTimeZone() no longer returns a + * SimpleTimeZone object.) + * @since 1.4 + */ + private SimpleTimeZone getPST() { + return new SimpleTimeZone(-8*ONE_HOUR, "PST", + Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, + 1*ONE_HOUR); + } +} +//eof diff --git a/jdk/test/java/util/TimeZone/TimeZoneTest.java b/jdk/test/java/util/TimeZone/TimeZoneTest.java new file mode 100644 index 00000000000..2413d15e8f5 --- /dev/null +++ b/jdk/test/java/util/TimeZone/TimeZoneTest.java @@ -0,0 +1,737 @@ +/* + * 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 + * 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 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483 + * 8008577 8077685 8098547 8133321 8138716 8148446 + * @modules java.base/sun.util.resources + * @library /java/text/testlib + * @summary test TimeZone + */ + +import java.io.*; +import java.text.*; +import java.util.*; +import sun.util.resources.LocaleData; + +public class TimeZoneTest extends IntlTest +{ + static final int millisPerHour = 3600000; + + public static void main(String[] args) throws Exception { + new TimeZoneTest().run(args); + } + + /** + * Bug 4130885 + * Certain short zone IDs, used since 1.1.x, are incorrect. + * + * The worst of these is: + * + * "CAT" (Central African Time) should be GMT+2:00, but instead returns a + * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, + * or AZOST, depending on which zone is meant, but in no case is it CAT. + * + * Other wrong zone IDs: + * + * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, + * GMT-5:00. European Central time is abbreviated CEST. + * + * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, + * GMT-11:00. Solomon Island time is SBT. + * + * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for + * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. + * + * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in + * another bug.] It should be "AKST". AST is Atlantic Standard Time, + * GMT-4:00. + * + * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, + * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct + * from MST with daylight savings. + * + * In addition to these problems, a number of zones are FAKE. That is, they + * don't match what people use in the real world. + * + * FAKE zones: + * + * EET (should be EEST) + * ART (should be EET) + * MET (should be IRST) + * NET (should be AMST) + * PLT (should be PKT) + * BST (should be BDT) + * VST (should be ICT) + * CTT (should be CST) + + * ACT (should be CST) + + * AET (should be EST) + + * MIT (should be WST) + + * IET (should be EST) + + * PRT (should be AST) + + * CNT (should be NST) + * AGT (should be ARST) + * BET (should be EST) + + * + * + A zone with the correct name already exists and means something + * else. E.g., EST usually indicates the US Eastern zone, so it cannot be + * used for Brazil (BET). + */ + public void TestShortZoneIDs() throws Exception { + + ZoneDescriptor[] JDK_116_REFERENCE_LIST = { + new ZoneDescriptor("MIT", 780, true), + new ZoneDescriptor("HST", -600, false), + new ZoneDescriptor("AST", -540, true), + new ZoneDescriptor("PST", -480, true), + new ZoneDescriptor("PNT", -420, false), + new ZoneDescriptor("MST", -420, false), + new ZoneDescriptor("CST", -360, true), + new ZoneDescriptor("IET", -300, true), + new ZoneDescriptor("EST", -300, false), + new ZoneDescriptor("PRT", -240, false), + new ZoneDescriptor("CNT", -210, true), + new ZoneDescriptor("AGT", -180, false), + new ZoneDescriptor("BET", -180, true), + // new ZoneDescriptor("CAT", -60, false), // Wrong: + // As of bug 4130885, fix CAT (Central Africa) + new ZoneDescriptor("CAT", 120, false), // Africa/Harare + new ZoneDescriptor("GMT", 0, false), + new ZoneDescriptor("UTC", 0, false), + new ZoneDescriptor("ECT", 60, true), + new ZoneDescriptor("ART", 120, false), + new ZoneDescriptor("EET", 120, true), + new ZoneDescriptor("EAT", 180, false), + new ZoneDescriptor("MET", 60, true), + new ZoneDescriptor("NET", 240, false), + new ZoneDescriptor("PLT", 300, false), + new ZoneDescriptor("IST", 330, false), + new ZoneDescriptor("BST", 360, false), + new ZoneDescriptor("VST", 420, false), + new ZoneDescriptor("CTT", 480, false), + new ZoneDescriptor("JST", 540, false), + new ZoneDescriptor("ACT", 570, false), + new ZoneDescriptor("AET", 600, true), + new ZoneDescriptor("SST", 660, false), + // new ZoneDescriptor("NST", 720, false), + // As of bug 4130885, fix NST (New Zealand) + new ZoneDescriptor("NST", 720, true), // Pacific/Auckland + }; + + Map hash = new HashMap<>(); + + String[] ids = TimeZone.getAvailableIDs(); + for (String id : ids) { + if (id.length() == 3) { + hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id))); + } + } + + for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) { + ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i]; + ZoneDescriptor currentZone = hash.get(referenceZone.getID()); + if (referenceZone.equals(currentZone)) { + logln("ok " + referenceZone); + } + else { + errln("Fail: Expected " + referenceZone + + "; got " + currentZone); + } + } + } + + /** + * A descriptor for a zone; used to regress the short zone IDs. + */ + static class ZoneDescriptor { + String id; + int offset; // In minutes + boolean daylight; + + ZoneDescriptor(TimeZone zone) { + this.id = zone.getID(); + this.offset = zone.getRawOffset() / 60000; + this.daylight = zone.useDaylightTime(); + } + + ZoneDescriptor(String id, int offset, boolean daylight) { + this.id = id; + this.offset = offset; + this.daylight = daylight; + } + + public String getID() { return id; } + + @Override + public boolean equals(Object o) { + ZoneDescriptor that = (ZoneDescriptor)o; + return that != null && + id.equals(that.id) && + offset == that.offset && + daylight == that.daylight; + } + + @Override + public int hashCode() { + return id.hashCode() ^ offset | (daylight ? 1 : 0); + } + + @Override + public String toString() { + int min = offset; + char sign = '+'; + if (min < 0) { sign = '-'; min = -min; } + + return "Zone[\"" + id + "\", GMT" + sign + (min/60) + ':' + + (min%60<10?"0":"") + (min%60) + ", " + + (daylight ? "Daylight" : "Standard") + "]"; + } + + public static int compare(Object o1, Object o2) { + ZoneDescriptor i1 = (ZoneDescriptor)o1; + ZoneDescriptor i2 = (ZoneDescriptor)o2; + if (i1.offset > i2.offset) return 1; + if (i1.offset < i2.offset) return -1; + if (i1.daylight && !i2.daylight) return 1; + if (!i1.daylight && i2.daylight) return -1; + return i1.id.compareTo(i2.id); + } + } + + static final String formatMinutes(int min) { + char sign = '+'; + if (min < 0) { sign = '-'; min = -min; } + int h = min/60; + min = min%60; + return "" + sign + h + ":" + ((min<10) ? "0" : "") + min; + } + /** + * As part of the VM fix (see CCC approved RFE 4028006, bug + * 4044013), TimeZone.getTimeZone() has been modified to recognize + * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and + * GMT[+-]hh. Test this behavior here. + * + * Bug 4044013 + * + * ID "Custom" is no longer used for TimeZone objects created with + * a custom time zone ID, such as "GMT-8". See 4322313. + */ + public void TestCustomParse() throws Exception { + Object[] DATA = { + // ID Expected offset in minutes + "GMT", null, + "GMT+0", new Integer(0), + "GMT+1", new Integer(60), + "GMT-0030", new Integer(-30), + "GMT+15:99", null, + "GMT+", null, + "GMT-", null, + "GMT+0:", null, + "GMT-:", null, + "GMT+0010", new Integer(10), // Interpret this as 00:10 + "GMT-10", new Integer(-10*60), + "GMT+30", null, + "GMT-3:30", new Integer(-(3*60+30)), + "GMT-230", new Integer(-(2*60+30)), + }; + for (int i=0; i generic GMT"); + // When TimeZone.getTimeZone() can't parse the id, it + // returns GMT -- a dubious practice, but required for + // backward compatibility. + if (exp != null) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + " for " + id + ", got parse failure"); + } + } + else { + int ioffset = zone.getRawOffset()/60000; + String offset = formatMinutes(ioffset); + logln(id + " -> " + zone.getID() + " GMT" + offset); + if (exp == null) { + throw new Exception("Expected parse failure for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + else if (ioffset != exp.intValue()) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + ", id Custom, for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + } + } + } + + /** + * Test the basic functionality of the getDisplayName() API. + * + * Bug 4112869 + * Bug 4028006 + * + * See also API change request A41. + * + * 4/21/98 - make smarter, so the test works if the ext resources + * are present or not. + */ + public void TestDisplayName() { + TimeZone zone = TimeZone.getTimeZone("PST"); + String name = zone.getDisplayName(Locale.ENGLISH); + logln("PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + //***************************************************************** + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + Object[] DATA = { + new Boolean(false), new Integer(TimeZone.SHORT), "PST", + new Boolean(true), new Integer(TimeZone.SHORT), "PDT", + new Boolean(false), new Integer(TimeZone.LONG), "Pacific Standard Time", + new Boolean(true), new Integer(TimeZone.LONG), "Pacific Daylight Time", + }; + + for (int i=0; i" + zone2.inDaylightTime(new Date())); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("Modified PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + // Make sure we get the default display format for Locales + // with no display name data. + Locale zh_CN = Locale.SIMPLIFIED_CHINESE; + name = zone.getDisplayName(zh_CN); + //***************************************************************** + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + logln("PST(zh_CN)->" + name); + + // Now be smart -- check to see if zh resource is even present. + // If not, we expect the en fallback behavior. + ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames", + Locale.ENGLISH); + ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames", + zh_CN); + + boolean noZH = enRB == zhRB; + + if (noZH) { + logln("Warning: Not testing the zh_CN behavior because resource is absent"); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected Pacific Standard Time"); + } + else if (!name.equals("Pacific Standard Time") && + !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") && + !name.equals("GMT-08:00") && + !name.equals("GMT-8:00") && + !name.equals("GMT-0800") && + !name.equals("GMT-800")) { + errln("Fail: Expected GMT-08:00 or something similar"); + errln("************************************************************"); + errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED"); + errln("************************************************************"); + } + + // Now try a non-existent zone + zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("GMT+90min->" + name); + if (!name.equals("GMT+01:30") && + !name.equals("GMT+1:30") && + !name.equals("GMT+0130") && + !name.equals("GMT+130")) + errln("Fail: Expected GMT+01:30 or something similar"); + } + + public void TestGenericAPI() { + String id = "NewGMT"; + int offset = 12345; + + SimpleTimeZone zone = new SimpleTimeZone(offset, id); + if (zone.useDaylightTime()) { + errln("FAIL: useDaylightTime should return false"); + } + + TimeZone zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) { + errln("FAIL: clone or operator== failed"); + } + zoneclone.setID("abc"); + if (zoneclone.equals(zone)) { + errln("FAIL: clone or operator!= failed"); + } + + zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) { + errln("FAIL: clone or operator== failed"); + } + zoneclone.setRawOffset(45678); + if (zoneclone.equals(zone)) { + errln("FAIL: clone or operator!= failed"); + } + + TimeZone saveDefault = TimeZone.getDefault(); + try { + TimeZone.setDefault(zone); + TimeZone defaultzone = TimeZone.getDefault(); + if (defaultzone == zone) { + errln("FAIL: Default object is identical, not clone"); + } + if (!defaultzone.equals(zone)) { + errln("FAIL: Default object is not equal"); + } + } + finally { + TimeZone.setDefault(saveDefault); + } + } + + @SuppressWarnings("deprecation") + public void TestRuleAPI() + { + // ErrorCode status = ZERO_ERROR; + + int offset = (int)(60*60*1000*1.75); // Pick a weird offset + SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); + if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); + + // Establish our expected transition times. Do this with a non-DST + // calendar with the (above) declared local offset. + GregorianCalendar gc = new GregorianCalendar(zone); + gc.clear(); + gc.set(1990, Calendar.MARCH, 1); + long marchOneStd = gc.getTime().getTime(); // Local Std time midnight + gc.clear(); + gc.set(1990, Calendar.JULY, 1); + long julyOneStd = gc.getTime().getTime(); // Local Std time midnight + + // Starting and ending hours, WALL TIME + int startHour = (int)(2.25 * 3600000); + int endHour = (int)(3.5 * 3600000); + + zone.setStartRule(Calendar.MARCH, 1, 0, startHour); + zone.setEndRule (Calendar.JULY, 1, 0, endHour); + + gc = new GregorianCalendar(zone); + // if (failure(status, "new GregorianCalendar")) return; + + long marchOne = marchOneStd + startHour; + long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time + + long expMarchOne = 636251400000L; + if (marchOne != expMarchOne) + { + errln("FAIL: Expected start computed as " + marchOne + + " = " + new Date(marchOne)); + logln(" Should be " + expMarchOne + + " = " + new Date(expMarchOne)); + } + + long expJulyOne = 646793100000L; + if (julyOne != expJulyOne) + { + errln("FAIL: Expected start computed as " + julyOne + + " = " + new Date(julyOne)); + logln(" Should be " + expJulyOne + + " = " + new Date(expJulyOne)); + } + + testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(), + new Date(90, Calendar.JUNE, 15).getTime(), marchOne); + testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(), + new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne); + + if (zone.inDaylightTime(new Date(marchOne - 1000)) || + !zone.inDaylightTime(new Date(marchOne))) + errln("FAIL: Start rule broken"); + if (!zone.inDaylightTime(new Date(julyOne - 1000)) || + zone.inDaylightTime(new Date(julyOne))) + errln("FAIL: End rule broken"); + + zone.setStartYear(1991); + if (zone.inDaylightTime(new Date(marchOne)) || + zone.inDaylightTime(new Date(julyOne - 1000))) + errln("FAIL: Start year broken"); + + // failure(status, "TestRuleAPI"); + // delete gc; + // delete zone; + } + + void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) + { + // ErrorCode status = ZERO_ERROR; + boolean startsInDST = tz.inDaylightTime(new Date(min)); + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + if (tz.inDaylightTime(new Date(max)) == startsInDST) { + logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); + return; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + while ((max - min) > INTERVAL) { + long mid = (min + max) / 2; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) { + min = mid; + } + else { + max = mid; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + } + logln("Binary Search Before: " + min + " = " + new Date(min)); + logln("Binary Search After: " + max + " = " + new Date(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && + mindelta <= INTERVAL && + mindelta >= 0 && + mindelta <= INTERVAL) + logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + else + errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + } + + static final int INTERVAL = 100; + + // Bug 006; verify the offset for a specific zone. + public void TestPRTOffset() + { + TimeZone tz = TimeZone.getTimeZone( "PRT" ); + if( tz == null ) { + errln( "FAIL: TimeZone(PRT) is null" ); + } + else{ + if (tz.getRawOffset() != (-4*millisPerHour)) + errln("FAIL: Offset for PRT should be -4"); + } + + } + + // Test various calls + @SuppressWarnings("deprecation") + public void TestVariousAPI518() + { + TimeZone time_zone = TimeZone.getTimeZone("PST"); + Date d = new Date(97, Calendar.APRIL, 30); + + logln("The timezone is " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) != true) + errln("FAIL: inDaylightTime returned false"); + + if (time_zone.useDaylightTime() != true) + errln("FAIL: useDaylightTime returned false"); + + if (time_zone.getRawOffset() != -8*millisPerHour) + errln( "FAIL: getRawOffset returned wrong value"); + + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(d); + if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), + gc.get(gc.DAY_OF_WEEK), 0) + != -7*millisPerHour) + errln("FAIL: getOffset returned wrong value"); + } + + // Test getAvailableID API + public void TestGetAvailableIDs913() + { + StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); + String[] s = TimeZone.getAvailableIDs(); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + buf.setLength(0); + buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); + s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + TimeZone tz = TimeZone.getTimeZone("PST"); + if (tz != null) + logln("getTimeZone(PST) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + tz = TimeZone.getTimeZone("America/Los_Angeles"); + if (tz != null) + logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + // Bug 4096694 + tz = TimeZone.getTimeZone("NON_EXISTENT"); + if (tz == null) + errln("FAIL: getTimeZone(NON_EXISTENT) = null"); + else if (!tz.getID().equals("GMT")) + errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); + } + + /** + * Bug 4107276 + */ + public void TestDSTSavings() { + // It might be better to find a way to integrate this test into the main TimeZone + // tests above, but I don't have time to figure out how to do this (or if it's + // even really a good idea). Let's consider that a future. --rtg 1/27/98 + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", + Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, + (int)(0.5 * millisPerHour)); + + if (tz.getRawOffset() != -5 * millisPerHour) + errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + + " hours instead of -5 hours."); + if (!tz.useDaylightTime()) + errln("Test time zone should use DST but claims it doesn't."); + if (tz.getDSTSavings() != 0.5 * millisPerHour) + errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / + millisPerHour) + " hours instead."); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4.5 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + tz.setDSTSavings(millisPerHour); + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + } + + /** + * Bug 4107570 + */ + public void TestAlternateRules() { + // Like TestDSTSavings, this test should probably be integrated somehow with the main + // test at the top of this class, but I didn't have time to figure out how to do that. + // --rtg 1/28/98 + + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); + + // test the day-of-month API + tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); + tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + // test the day-of-week-after-day-in-month API + tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); + tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, + Calendar.WEDNESDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + } +} + +//eof diff --git a/jdk/test/java/util/TimeZone/TransitionTest.java b/jdk/test/java/util/TimeZone/TransitionTest.java new file mode 100644 index 00000000000..5f012d09d72 --- /dev/null +++ b/jdk/test/java/util/TimeZone/TransitionTest.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002, 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 4278609 4761696 + * @library /java/text/testlib + * @summary Make sure to handle DST transition ending at 0:00 January 1. + */ + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.SimpleTimeZone; +import java.util.TimeZone; + +public class TransitionTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new TransitionTest().run(args); + } + + public void Test4278609() { + SimpleTimeZone tz = new SimpleTimeZone(0, "MyTimeZone", + /* DST start day: August, 1, 0:00 */ + Calendar.AUGUST, 1, 0, 0, + /* DST end day: January, 1, 0:00 (wall-clock)*/ + Calendar.JANUARY, 1, 0, 0, + 60 * 60 * 1000); + + Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + + // setting a date using GMT zone just after the end rule of tz zone + cal.clear(); + cal.set(Calendar.ERA, GregorianCalendar.AD); + cal.set(1998, Calendar.DECEMBER, 31, 23, 01, 00); + + Date date = cal.getTime(); + + int millis = cal.get(Calendar.HOUR_OF_DAY) * 3600000 + + cal.get(Calendar.MINUTE) * 60000 + + cal.get(Calendar.SECOND) * 1000 + + cal.get(Calendar.MILLISECOND); + /* we must use standard local time */ + millis += tz.getRawOffset(); + + int offset = tz.getOffset(cal.get(Calendar.ERA), + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH), + cal.get(Calendar.DATE), + cal.get(Calendar.DAY_OF_WEEK), + millis); + + if (offset != 0) { + SimpleDateFormat format = new SimpleDateFormat("dd MMM HH:mm:ss zzz", + Locale.US); + format.setTimeZone(tz); + errln("Wrong DST transition: " + tz + + "\na date just after DST = " + format.format(date) + + "\ngetOffset = " + offset); + } + } + + /* + * 4761696: Rewrite SimpleTimeZone to support correct DST transitions + * + * Derived from JCK test cases some of which specify wrong day of week values. + */ + public void Test4761696() { + GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + + // test#1 + int rawOffset = -43200000; + int saving = 1800000; + int timeOfDay = 84600001; + SimpleTimeZone tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JULY, 1, 0, 0, + Calendar.JANUARY, 1, 0, 0, + saving); + int year = Integer.MIN_VALUE; + tz.setStartYear(year); + int offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.DECEMBER, + 31, + 1, // should be SATURDAY + timeOfDay); + int y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(cal.ERA, cal.AD); + cal.set(y, Calendar.DECEMBER, 31); + cal.set(cal.MILLISECOND, timeOfDay); + long localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(cal.ERA, cal.AD); + cal.set(y + 1, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, -saving); + long endTime = cal.getTimeInMillis() + rawOffset; + long expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#1: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#2 + saving = 1; + timeOfDay = 0; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JULY, 1, 0, 0, + Calendar.JANUARY, 1, 0, 0, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.AUGUST, + 15, + 1, // should be MONDAY + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.AUGUST, 15); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(y + 1, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, -saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("Wrong offset: got "+offset+", expected="+expectedOffset); + } + + rawOffset = 43200000; + saving = 1; + timeOfDay = 3599998; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JULY, 1, 0, 3600000, + Calendar.JANUARY, 1, 0, 3600000, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.JANUARY, + 1, + 1, + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(y + 1, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, 3600000-saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#2: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#3 + rawOffset = -43200000; + saving = 1800000; + timeOfDay = 84600001; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.SEPTEMBER, 1, 0, 0, + Calendar.MARCH, 1, 0, 0, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.FEBRUARY, + 28, + 1, + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.FEBRUARY, 28); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(y, Calendar.MARCH, 1); + cal.set(cal.MILLISECOND, -saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#3: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#4 + rawOffset = -43200000; + saving = 1; + timeOfDay = 0; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JANUARY, -4, 1, 3600000, + Calendar.JULY, -4, 1, 3600000, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.JANUARY, + 10, + 2, // should be 1 (SUNDAY) + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.JANUARY, 10); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(cal.YEAR, y); + cal.set(cal.MONTH, Calendar.JANUARY); + cal.set(cal.DAY_OF_MONTH, 8); + cal.set(cal.WEEK_OF_MONTH, cal.getActualMaximum(cal.WEEK_OF_MONTH)-4+1); + cal.set(cal.DAY_OF_WEEK, 1); + cal.set(cal.MILLISECOND, 3600000-saving); + long startTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime >= startTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#4: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#5 + rawOffset = 0; + saving = 3600000; + timeOfDay = 7200000; + year = 1982; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.APRIL, 1, 0, 7200000, + Calendar.OCTOBER, 10, 0, 7200000, + saving); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.OCTOBER, + 10, + 1, + timeOfDay); + cal.clear(); + cal.set(year, Calendar.OCTOBER, 10); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(year, Calendar.OCTOBER, 10); + cal.set(cal.MILLISECOND, 7200000-saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#5: wrong offset: got "+offset+", expected="+expectedOffset); + } + } + + public static final long floorDivide(long n, long d) { + return ((n >= 0) ? + (n / d) : (((n + 1L) / d) - 1L)); + } + + public static final long mod(long x, long y) { + return (x - y * floorDivide(x, y)); + } +} diff --git a/jdk/test/java/util/TimeZone/UTCAliasTest.java b/jdk/test/java/util/TimeZone/UTCAliasTest.java new file mode 100644 index 00000000000..aa7079326c0 --- /dev/null +++ b/jdk/test/java/util/TimeZone/UTCAliasTest.java @@ -0,0 +1,52 @@ +/* + * 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 + * 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 6282072 + * @summary Make sure that "UTC" is an alias of "Etc/UTC" as defined in the tzdata backward. + * @modules java.base/sun.util.calendar + * @compile -XDignore.symbol.file UTCAliasTest.java + */ + +import java.util.*; +import sun.util.calendar.ZoneInfo; + +public class UTCAliasTest { + public static void main(String[] args) { + Map map = ZoneInfo.getAliasTable(); + String alias = map.get("UTC"); + if (!alias.equals("Etc/UTC")) { + throw new RuntimeException("got " + alias + ", expected Etc/UTC"); + } + TimeZone GMT = TimeZone.getTimeZone("GMT"); + TimeZone UTC = TimeZone.getTimeZone("UTC"); + if (!GMT.hasSameRules(UTC)) { + throw new RuntimeException("GMT and UTC have different rules"); + } + TimeZone EtcUTC = TimeZone.getTimeZone("Etc/UTC"); + if (!UTC.hasSameRules(EtcUTC)) { + throw new RuntimeException("UTC and Etc/UTC have different rules"); + } + } +} diff --git a/jdk/test/java/util/TimeZone/bug4096952.java b/jdk/test/java/util/TimeZone/bug4096952.java new file mode 100644 index 00000000000..20ccc685ac6 --- /dev/null +++ b/jdk/test/java/util/TimeZone/bug4096952.java @@ -0,0 +1,67 @@ +/* + * 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 + * 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 4096952 + * @summary simple serialization/deserialization test + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.TimeZone; + +public class bug4096952 { + + public static void main(String[] args) { + int errors = 0; + String[] ZONES = { "GMT", "MET", "IST" }; + for (String id : ZONES) { + TimeZone zone = TimeZone.getTimeZone(id); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream ostream = new ObjectOutputStream(baos)) { + ostream.writeObject(zone); + } + try (ObjectInputStream istream + = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + if (!zone.equals(istream.readObject())) { + errors++; + System.out.println("Time zone " + id + " are not equal to serialized/deserialized one."); + } else { + System.out.println("Time zone " + id + " ok."); + } + } + } catch (IOException | ClassNotFoundException e) { + errors++; + System.out.println(e); + } + } + if (errors > 0) { + throw new RuntimeException("test failed"); + } + } +} diff --git a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java index 82f9ead09f5..913aea78c46 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java +++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java @@ -25,13 +25,10 @@ * @test * @bug 6503247 6574123 * @summary Test resilience to tryAcquire methods that throw - * @library /lib/testlibrary/ * @author Martin Buchholz */ -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -39,7 +36,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; -import jdk.testlibrary.Utils; /** * This uses a variant of the standard Mutex demo, except with a @@ -48,22 +44,10 @@ import jdk.testlibrary.Utils; */ @SuppressWarnings("serial") public class FlakyMutex implements Lock { - static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static class MyError extends Error {} static class MyException extends Exception {} static class MyRuntimeException extends RuntimeException {} - static final Random rnd = new Random(); - - static void maybeThrow() { - switch (rnd.nextInt(10)) { - case 0: throw new MyError(); - case 1: throw new MyRuntimeException(); - case 2: FlakyMutex.uncheckedThrow(new MyException()); - default: /* Do nothing */ break; - } - } - static void checkThrowable(Throwable t) { check((t instanceof MyError) || (t instanceof MyException) || @@ -72,31 +56,35 @@ public class FlakyMutex implements Lock { static void realMain(String[] args) throws Throwable { final int nThreads = 3; - final CyclicBarrier barrier = new CyclicBarrier(nThreads + 1); - final FlakyMutex m = new FlakyMutex(); + final int iterations = 10_000; + final CyclicBarrier startingGate = new CyclicBarrier(nThreads); + final FlakyMutex mutex = new FlakyMutex(); final ExecutorService es = Executors.newFixedThreadPool(nThreads); - for (int i = 0; i < nThreads; i++) { - es.submit(new Runnable() { public void run() { - try { - barrier.await(); - for (int i = 0; i < 10000; i++) { - for (;;) { - try { m.lock(); break; } - catch (Throwable t) { checkThrowable(t); } - } - - try { check(! m.tryLock()); } + final Runnable task = () -> { + try { + startingGate.await(); + for (int i = 0; i < iterations; i++) { + for (;;) { + try { mutex.lock(); break; } catch (Throwable t) { checkThrowable(t); } - - try { check(! m.tryLock(1, TimeUnit.MICROSECONDS)); } - catch (Throwable t) { checkThrowable(t); } - - m.unlock(); } - } catch (Throwable t) { unexpected(t); }}});} - barrier.await(); + + try { check(! mutex.tryLock()); } + catch (Throwable t) { checkThrowable(t); } + + try { check(! mutex.tryLock(1, TimeUnit.MICROSECONDS)); } + catch (Throwable t) { checkThrowable(t); } + + mutex.unlock(); + } + } catch (Throwable t) { unexpected(t); } + }; + + for (int i = 0; i < nThreads; i++) + es.submit(task); es.shutdown(); - check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + // Let test harness handle timeout + check(es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)); } private static class FlakySync extends AbstractQueuedLongSynchronizer { @@ -116,8 +104,12 @@ public class FlakyMutex implements Lock { do {} while (hasQueuedPredecessors() != hasQueuedThreads()); } - maybeThrow(); - return compareAndSetState(0, 1); + switch (ThreadLocalRandom.current().nextInt(10)) { + case 0: throw new MyError(); + case 1: throw new MyRuntimeException(); + case 2: FlakyMutex.uncheckedThrow(new MyException()); + default: return compareAndSetState(0, 1); + } } public boolean tryRelease(long releases) { diff --git a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java index 5ad9d068a2a..2d82c455574 100644 --- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java +++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java @@ -35,16 +35,10 @@ * @test * @bug 8074773 * @summary Stress test looks for lost unparks - * @library /lib/testlibrary/ - * @modules java.management - * @run main/timeout=1200 ParkLoops */ -import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; import java.util.SplittableRandom; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -52,11 +46,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.LockSupport; -import jdk.testlibrary.Utils; public final class ParkLoops { - static final long TEST_TIMEOUT_SECONDS = Utils.adjustTimeout(1000); - static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final int THREADS = 4; static final int ITERS = 30_000; @@ -126,28 +117,13 @@ public final class ParkLoops { final AtomicReferenceArray threads = new AtomicReferenceArray<>(THREADS); final CountDownLatch done = new CountDownLatch(THREADS); - final Runnable parker = new Parker(threads, done, rnd.split()); - final Runnable unparker = new Unparker(threads, done, rnd.split()); for (int i = 0; i < THREADS; i++) { - pool.submit(parker); - pool.submit(unparker); - } - try { - if (!done.await(TEST_TIMEOUT_SECONDS, SECONDS)) { - dumpAllStacks(); - throw new AssertionError("lost unpark"); - } - } finally { - pool.shutdown(); - pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); - } - } - - static void dumpAllStacks() { - ThreadInfo[] threadInfos = - ManagementFactory.getThreadMXBean().dumpAllThreads(true, true); - for (ThreadInfo threadInfo : threadInfos) { - System.err.print(threadInfo); + pool.submit(new Parker(threads, done, rnd.split())); + pool.submit(new Unparker(threads, done, rnd.split())); } + // Let test harness handle timeout + done.await(); + pool.shutdown(); + pool.awaitTermination(Long.MAX_VALUE, SECONDS); } } diff --git a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java index 340e7f972a4..4149559adad 100644 --- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java +++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java @@ -3322,7 +3322,7 @@ public class CompletableFutureTest extends JSR166TestCase { () -> f.obtrudeException(null), () -> CompletableFuture.delayedExecutor(1L, SECONDS, null), - () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()), + () -> CompletableFuture.delayedExecutor(1L, null, exec), () -> CompletableFuture.delayedExecutor(1L, null), () -> f.orTimeout(1L, null), @@ -3552,7 +3552,7 @@ public class CompletableFutureTest extends JSR166TestCase { long timeoutMillis = timeoutMillis(); CompletableFuture f = new CompletableFuture<>(); long startTime = System.nanoTime(); - f.orTimeout(timeoutMillis, MILLISECONDS); + assertSame(f, f.orTimeout(timeoutMillis, MILLISECONDS)); checkCompletedWithTimeoutException(f); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); } @@ -3567,8 +3567,8 @@ public class CompletableFutureTest extends JSR166TestCase { CompletableFuture g = new CompletableFuture<>(); long startTime = System.nanoTime(); f.complete(v1); - f.orTimeout(LONG_DELAY_MS, MILLISECONDS); - g.orTimeout(LONG_DELAY_MS, MILLISECONDS); + assertSame(f, f.orTimeout(LONG_DELAY_MS, MILLISECONDS)); + assertSame(g, g.orTimeout(LONG_DELAY_MS, MILLISECONDS)); g.complete(v1); checkCompletedNormally(f, v1); checkCompletedNormally(g, v1); @@ -3583,11 +3583,14 @@ public class CompletableFutureTest extends JSR166TestCase { () -> testCompleteOnTimeout_timesOut(null)); } + /** + * completeOnTimeout completes with given value if not complete + */ public void testCompleteOnTimeout_timesOut(Integer v) { long timeoutMillis = timeoutMillis(); CompletableFuture f = new CompletableFuture<>(); long startTime = System.nanoTime(); - f.completeOnTimeout(v, timeoutMillis, MILLISECONDS); + assertSame(f, f.completeOnTimeout(v, timeoutMillis, MILLISECONDS)); assertSame(v, f.join()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); f.complete(99); // should have no effect @@ -3604,8 +3607,8 @@ public class CompletableFutureTest extends JSR166TestCase { CompletableFuture g = new CompletableFuture<>(); long startTime = System.nanoTime(); f.complete(v1); - f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); - g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); + assertSame(f, f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS)); + assertSame(g, g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS)); g.complete(v1); checkCompletedNormally(f, v1); checkCompletedNormally(g, v1); diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java new file mode 100644 index 00000000000..8169d5fa5f6 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java @@ -0,0 +1,137 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ExecutorCompletionService9Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ExecutorCompletionService9Test.class); + } + + void solveAll(Executor e, + Collection> solvers) + throws InterruptedException, ExecutionException { + CompletionService cs + = new ExecutorCompletionService<>(e); + solvers.forEach(cs::submit); + for (int i = solvers.size(); i > 0; i--) { + Integer r = cs.take().get(); + if (r != null) + use(r); + } + } + + void solveAny(Executor e, + Collection> solvers) + throws InterruptedException { + CompletionService cs + = new ExecutorCompletionService<>(e); + int n = solvers.size(); + List> futures = new ArrayList<>(n); + Integer result = null; + try { + solvers.forEach((solver) -> futures.add(cs.submit(solver))); + for (int i = n; i > 0; i--) { + try { + Integer r = cs.take().get(); + if (r != null) { + result = r; + break; + } + } catch (ExecutionException ignore) {} + } + } finally { + futures.forEach((future) -> future.cancel(true)); + } + + if (result != null) + use(result); + } + + HashSet results; + + void use(Integer x) { + if (results == null) results = new HashSet(); + results.add(x); + } + + /** + * The first "solvers" sample code in the class javadoc works. + */ + public void testSolveAll() + throws InterruptedException, ExecutionException { + Set> solvers = Set.of( + () -> null, + () -> 1, + () -> 2, + () -> 3, + () -> null); + solveAll(cachedThreadPool, solvers); + assertEquals(Set.of(1, 2, 3), results); + } + + /** + * The second "solvers" sample code in the class javadoc works. + */ + public void testSolveAny() + throws InterruptedException { + Set> solvers = Set.of( + () -> { throw new ArithmeticException(); }, + () -> null, + () -> 1, + () -> 2); + solveAny(cachedThreadPool, solvers); + assertEquals(1, results.size()); + Integer elt = results.iterator().next(); + assertTrue(elt.equals(1) || elt.equals(2)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java index 29db17a7a0d..6e4d00f3d0f 100644 --- a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java @@ -37,8 +37,11 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; @@ -59,7 +62,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { } /** - * Creating a new ECS with null Executor throw NPE + * new ExecutorCompletionService(null) throws NullPointerException */ public void testConstructorNPE() { try { @@ -69,111 +72,147 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { } /** - * Creating a new ECS with null queue throw NPE + * new ExecutorCompletionService(e, null) throws NullPointerException */ public void testConstructorNPE2() { try { - ExecutorService e = Executors.newCachedThreadPool(); - new ExecutorCompletionService(e, null); + new ExecutorCompletionService(cachedThreadPool, null); shouldThrow(); } catch (NullPointerException success) {} } /** - * Submitting a null callable throws NPE + * ecs.submit(null) throws NullPointerException */ - public void testSubmitNPE() { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = null; - try { - ecs.submit(c); - shouldThrow(); - } catch (NullPointerException success) {} - } + public void testSubmitNullCallable() { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + try { + cs.submit((Callable) null); + shouldThrow(); + } catch (NullPointerException success) {} } /** - * Submitting a null runnable throws NPE + * ecs.submit(null, val) throws NullPointerException */ - public void testSubmitNPE2() { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Runnable r = null; - try { - ecs.submit(r, Boolean.TRUE); - shouldThrow(); - } catch (NullPointerException success) {} - } + public void testSubmitNullRunnable() { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + try { + cs.submit((Runnable) null, Boolean.TRUE); + shouldThrow(); + } catch (NullPointerException success) {} } /** * A taken submitted task is completed */ - public void testTake() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = new StringTask(); - ecs.submit(c); - Future f = ecs.take(); - assertTrue(f.isDone()); - } + public void testTake() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + cs.submit(new StringTask()); + Future f = cs.take(); + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); } /** * Take returns the same future object returned by submit */ public void testTake2() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = new StringTask(); - Future f1 = ecs.submit(c); - Future f2 = ecs.take(); - assertSame(f1, f2); - } + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + Future f1 = cs.submit(new StringTask()); + Future f2 = cs.take(); + assertSame(f1, f2); } /** - * If poll returns non-null, the returned task is completed + * poll returns non-null when the returned task is completed */ - public void testPoll1() throws Exception { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); - Callable c = new StringTask(); - ecs.submit(c); + public void testPoll1() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + assertNull(cs.poll()); + cs.submit(new StringTask()); - long startTime = System.nanoTime(); - Future f; - while ((f = ecs.poll()) == null) { - if (millisElapsedSince(startTime) > LONG_DELAY_MS) - fail("timed out"); - Thread.yield(); + long startTime = System.nanoTime(); + Future f; + while ((f = cs.poll()) == null) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); + } + + /** + * timed poll returns non-null when the returned task is completed + */ + public void testPoll2() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + assertNull(cs.poll()); + cs.submit(new StringTask()); + + long startTime = System.nanoTime(); + Future f; + while ((f = cs.poll(SHORT_DELAY_MS, MILLISECONDS)) == null) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); + } + + /** + * poll returns null before the returned task is completed + */ + public void testPollReturnsNull() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + final CountDownLatch proceed = new CountDownLatch(1); + cs.submit(new Callable() { public String call() throws Exception { + proceed.await(); + return TEST_STRING; + }}); + assertNull(cs.poll()); + assertNull(cs.poll(0L, MILLISECONDS)); + assertNull(cs.poll(Long.MIN_VALUE, MILLISECONDS)); + long startTime = System.nanoTime(); + assertNull(cs.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + proceed.countDown(); + assertSame(TEST_STRING, cs.take().get()); + } + + /** + * successful and failed tasks are both returned + */ + public void testTaskAssortment() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + ArithmeticException ex = new ArithmeticException(); + for (int i = 0; i < 2; i++) { + cs.submit(new StringTask()); + cs.submit(callableThrowing(ex)); + cs.submit(runnableThrowing(ex), null); + } + int normalCompletions = 0; + int exceptionalCompletions = 0; + for (int i = 0; i < 3 * 2; i++) { + try { + if (cs.take().get() == TEST_STRING) + normalCompletions++; + } + catch (ExecutionException expected) { + assertTrue(expected.getCause() instanceof ArithmeticException); + exceptionalCompletions++; } - assertTrue(f.isDone()); - assertSame(TEST_STRING, f.get()); - } - } - - /** - * If timed poll returns non-null, the returned task is completed - */ - public void testPoll2() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); - Callable c = new StringTask(); - ecs.submit(c); - Future f = ecs.poll(SHORT_DELAY_MS, MILLISECONDS); - if (f != null) - assertTrue(f.isDone()); } + assertEquals(2 * 1, normalCompletions); + assertEquals(2 * 2, exceptionalCompletions); + assertNull(cs.poll()); } /** @@ -184,7 +223,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { final AtomicBoolean done = new AtomicBoolean(false); class MyCallableFuture extends FutureTask { MyCallableFuture(Callable c) { super(c); } - protected void done() { done.set(true); } + @Override protected void done() { done.set(true); } } final ExecutorService e = new ThreadPoolExecutor(1, 1, @@ -193,15 +232,14 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { protected RunnableFuture newTaskFor(Callable c) { return new MyCallableFuture(c); }}; - ExecutorCompletionService ecs = - new ExecutorCompletionService(e); + CompletionService cs = new ExecutorCompletionService<>(e); try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); + assertNull(cs.poll()); Callable c = new StringTask(); - Future f1 = ecs.submit(c); + Future f1 = cs.submit(c); assertTrue("submit must return MyCallableFuture", f1 instanceof MyCallableFuture); - Future f2 = ecs.take(); + Future f2 = cs.take(); assertSame("submit and take must return same objects", f1, f2); assertTrue("completed task must have set done", done.get()); } @@ -215,7 +253,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { final AtomicBoolean done = new AtomicBoolean(false); class MyRunnableFuture extends FutureTask { MyRunnableFuture(Runnable t, V r) { super(t, r); } - protected void done() { done.set(true); } + @Override protected void done() { done.set(true); } } final ExecutorService e = new ThreadPoolExecutor(1, 1, @@ -224,15 +262,14 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { protected RunnableFuture newTaskFor(Runnable t, T r) { return new MyRunnableFuture(t, r); }}; - final ExecutorCompletionService ecs = - new ExecutorCompletionService(e); + CompletionService cs = new ExecutorCompletionService<>(e); try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); + assertNull(cs.poll()); Runnable r = new NoOpRunnable(); - Future f1 = ecs.submit(r, null); + Future f1 = cs.submit(r, null); assertTrue("submit must return MyRunnableFuture", f1 instanceof MyRunnableFuture); - Future f2 = ecs.take(); + Future f2 = cs.take(); assertSame("submit and take must return same objects", f1, f2); assertTrue("completed task must have set done", done.get()); } diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index b189ce6b128..14907badc6f 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -39,6 +39,7 @@ * @modules java.management * @build * * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase + * @run junit/othervm/timeout=1000 -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 -Djsr166.testImplementationDetails=true JSR166TestCase */ import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -85,6 +86,7 @@ import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveTask; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.Semaphore; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; @@ -546,7 +548,7 @@ public class JSR166TestCase extends TestCase { // Java9+ test classes if (atLeastJava9()) { String[] java9TestClassNames = { - // Currently empty, but expecting varhandle tests + "ExecutorCompletionService9Test", }; addNamedTestClasses(suite, java9TestClassNames); } @@ -1860,4 +1862,19 @@ public class JSR166TestCase extends TestCase { } catch (NoSuchElementException success) {} assertFalse(it.hasNext()); } + + public Callable callableThrowing(final Exception ex) { + return new Callable() { public T call() throws Exception { throw ex; }}; + } + + public Runnable runnableThrowing(final RuntimeException ex) { + return new Runnable() { public void run() { throw ex; }}; + } + + /** A reusable thread pool to be shared by tests. */ + static final ExecutorService cachedThreadPool = + new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 1000L, MILLISECONDS, + new SynchronousQueue()); + } diff --git a/jdk/test/java/util/logging/XMLFormatterDate.java b/jdk/test/java/util/logging/XMLFormatterDate.java index 28eb1246694..ee0eeb98b57 100644 --- a/jdk/test/java/util/logging/XMLFormatterDate.java +++ b/jdk/test/java/util/logging/XMLFormatterDate.java @@ -21,10 +21,18 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import java.util.Calendar; -import java.util.GregorianCalendar; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.time.Month; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.util.Locale; +import java.util.Properties; +import java.util.function.Supplier; import java.util.logging.Level; +import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.XMLFormatter; @@ -33,9 +41,25 @@ import java.util.logging.XMLFormatter; * @bug 8028185 * @summary XMLFormatter.format emits incorrect year (year + 1900) * @author dfuchs + * @run main/othervm XMLFormatterDate */ public class XMLFormatterDate { + static final class TimeStamp { + + final ZonedDateTime zdt; + TimeStamp(ZoneId zoneId) { + zdt = ZonedDateTime.now(zoneId); + } + int getYear() { + return zdt.getYear(); + } + boolean isJanuaryFirst() { + return zdt.getMonth() == Month.JANUARY && zdt.getDayOfMonth() == 1; + } + } + + /** * Before the fix, JDK8 prints: {@code * @@ -64,39 +88,62 @@ public class XMLFormatterDate { try { Locale.setDefault(Locale.ENGLISH); - final GregorianCalendar cal1 = new GregorianCalendar(); - final int year1 = cal1.get(Calendar.YEAR); + // Test with default format: by default date is in UTC. + System.out.println("Testing with UTC"); + test(() -> new TimeStamp(ZoneOffset.UTC)); - LogRecord record = new LogRecord(Level.INFO, "test"); - XMLFormatter formatter = new XMLFormatter(); - final String formatted = formatter.format(record); - System.out.println(formatted); - - final GregorianCalendar cal2 = new GregorianCalendar(); - final int year2 = cal2.get(Calendar.YEAR); - if (year2 < 1900) { - throw new Error("Invalid system year: " + year2); + // Change LogManager configuration so that new + // XMLFormatter prints date in the pre Java 9 local zone format + try { + Properties props = new Properties(); + props.setProperty("java.util.logging.XMLFormatter.useInstant", "false"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + props.store(baos, ""); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + LogManager.getLogManager().updateConfiguration(bais, (k) -> (o,n) -> n!=null?n:o); + } catch (IOException io) { + throw new RuntimeException(io); } - StringBuilder buf2 = new StringBuilder() - .append("").append(year2).append("-"); - if (!formatted.contains(buf2.toString())) { - StringBuilder buf1 = new StringBuilder() - .append("").append(year1).append("-"); - if (formatted.contains(buf1) - && year2 == year1 + 1 - && cal2.get(Calendar.MONTH) == Calendar.JANUARY - && cal2.get(Calendar.DAY_OF_MONTH) == 1) { - // Oh! The year just switched in the midst of the test... - System.out.println("Happy new year!"); - } else { - throw new Error("Expected year " + year2 - + " not found in log:\n" + formatted); - } - } + // re test with the old format: date will be in the local time zone. + System.out.println("Testing with old format"); + test(() -> new TimeStamp(ZoneId.systemDefault())); + } finally { Locale.setDefault(locale); } } + static void test(Supplier timeStampSupplier) { + + TimeStamp t1 = timeStampSupplier.get(); + int year1 = t1.getYear(); + + LogRecord record = new LogRecord(Level.INFO, "test"); + XMLFormatter formatter = new XMLFormatter(); + final String formatted = formatter.format(record); + System.out.println(formatted); + + final TimeStamp t2 = timeStampSupplier.get(); + final int year2 = t2.getYear(); + if (year2 < 1900) { + throw new Error("Invalid system year: " + year2); + } + + final StringBuilder buf2 = new StringBuilder() + .append("").append(year2).append("-"); + if (!formatted.contains(buf2.toString())) { + StringBuilder buf1 = new StringBuilder() + .append("").append(year1).append("-"); + if (formatted.contains(buf1) && year2 == year1 + 1 + && t2.isJanuaryFirst()) { + // Oh! The year just switched in the midst of the test... + System.out.println("Happy new year!"); + } else { + throw new Error("Expected year " + year2 + + " not found in log:\n" + formatted); + } + } + } + } diff --git a/jdk/test/jdk/internal/jrtfs/Basic.java b/jdk/test/jdk/internal/jrtfs/Basic.java index 0af30c5e2f7..9c29d8c1428 100644 --- a/jdk/test/jdk/internal/jrtfs/Basic.java +++ b/jdk/test/jdk/internal/jrtfs/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -65,15 +65,31 @@ public class Basic { private FileSystem theFileSystem; private FileSystem fs; + private boolean isExplodedBuild = false; @BeforeClass public void setup() { + theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/")); + Path javaHomeDir = Paths.get(System.getProperty("java.home")); + Path jrtJarPath = javaHomeDir.resolve("jrt-fs.jar"); + Path modulesPath = javaHomeDir.resolve("lib/modules"); + isExplodedBuild = !Files.exists(jrtJarPath) + && !Files.exists(modulesPath); + if (Files.notExists(jrtJarPath) + && Files.notExists(modulesPath)) { + System.out.printf("Following files not exist: %s, %s", + jrtJarPath.toString(), modulesPath.toString()); + System.out.println(); + System.out.println("It is most probably an exploded build." + + " Skip non-default FileSystem testing."); + return; + } + + Map env = new HashMap<>(); + // set java.home property to be underlying java.home + // so that jrt-fs.jar loading is exercised. + env.put("java.home", System.getProperty("java.home")); try { - theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/")); - Map env = new HashMap<>(); - // set java.home property to be underlying java.home - // so that jrt-fs.jar loading is exercised. - env.put("java.home", System.getProperty("java.home")); fs = FileSystems.newFileSystem(URI.create("jrt:/"), env); } catch (IOException ioExp) { throw new RuntimeException(ioExp); @@ -131,6 +147,12 @@ public class Basic { @Test public void testNewFileSystemWithJavaHome() throws Exception { + if (isExplodedBuild) { + System.out.println("Skip testNewFileSystemWithJavaHome" + + " since this is an exploded build"); + return; + } + Map env = new HashMap<>(); // set java.home property to be underlying java.home // so that jrt-fs.jar loading is exercised. @@ -154,6 +176,11 @@ public class Basic { @Test(dataProvider = "knownClassFiles") public void testKnownClassFiles(String path, boolean theDefault) throws Exception { + if (isExplodedBuild && !theDefault) { + System.out.println("Skip testKnownClassFiles with non-default FileSystem"); + return; + } + FileSystem fs = selectFileSystem(theDefault); Path classFile = fs.getPath(path); @@ -201,6 +228,11 @@ public class Basic { @Test(dataProvider = "knownDirectories") public void testKnownDirectories(String path, boolean theDefault) throws Exception { + if (isExplodedBuild && !theDefault) { + System.out.println("Skip testKnownDirectories with non-default FileSystem"); + return; + } + FileSystem fs = selectFileSystem(theDefault); Path dir = fs.getPath(path); @@ -684,3 +716,4 @@ public class Basic { assertEquals(dirPrefixOkayCount, childCount); } } + diff --git a/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java index ca02ad931d6..f882e88e30a 100644 --- a/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java +++ b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java @@ -25,6 +25,7 @@ * @test * @bug 8765432 * @summary Basic test for SocketFlow API + * @modules jdk.net * @run testng SocketFlowBasic */ diff --git a/jdk/test/jdk/net/Sockets/SupportedOptions.java b/jdk/test/jdk/net/Sockets/SupportedOptions.java index 0ef21204629..caf4d025d67 100644 --- a/jdk/test/jdk/net/Sockets/SupportedOptions.java +++ b/jdk/test/jdk/net/Sockets/SupportedOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /* * @test * @bug 8062744 + * @modules jdk.net * @run main SupportedOptions */ diff --git a/jdk/test/jdk/net/Sockets/Test.java b/jdk/test/jdk/net/Sockets/Test.java index 8bb03c54919..bd76fff4e67 100644 --- a/jdk/test/jdk/net/Sockets/Test.java +++ b/jdk/test/jdk/net/Sockets/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,24 +25,35 @@ * @test * @bug 8032808 8044773 * @modules jdk.net + * @library /lib/testlibrary + * @build jdk.testlibrary.* * @run main/othervm -Xcheck:jni Test success * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail * @run main/othervm/policy=policy.success -Xcheck:jni Test success */ -import java.net.*; +import jdk.net.ExtendedSocketOptions; +import jdk.net.SocketFlow; +import jdk.net.Sockets; +import jdk.testlibrary.OSInfo; + import java.io.IOException; -import java.nio.channels.*; -import java.util.concurrent.*; -import java.util.Set; -import jdk.net.*; +import java.net.*; +import java.nio.channels.AsynchronousSocketChannel; +import java.nio.channels.DatagramChannel; +import java.nio.channels.SocketChannel; +import java.util.concurrent.Future; + import static java.lang.System.out; +import static jdk.net.ExtendedSocketOptions.SO_FLOW_SLA; public class Test { interface Runner { void run() throws Exception; } static boolean expectSuccess; + private static final boolean expectSupport = checkExpectedOptionSupport(); + private static final double solarisVersionToCheck = 11.2; public static void main(String[] args) throws Exception { @@ -54,9 +65,8 @@ public class Test { expectSuccess = args[0].equals("success"); // Main thing is to check for JNI problems - // Doesn't matter if current system does not support the option - // and currently setting the option with the loopback interface - // doesn't work either + // Doesn't matter if currently setting the option with the loopback + // interface doesn't work boolean sm = System.getSecurityManager() != null; out.println("Security Manager enabled: " + sm); @@ -75,56 +85,70 @@ public class Test { final int udp_port = dg.getLocalPort(); - // If option not available, end test - Set> options = dg.supportedOptions(); - if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) { - System.out.println("SO_FLOW_SLA not supported"); - return; - } - final Socket s = new Socket("127.0.0.1", tcp_port); final SocketChannel sc = SocketChannel.open(); sc.connect(new InetSocketAddress("127.0.0.1", tcp_port)); doTest("Sockets.setOption Socket", () -> { out.println(flowIn); - Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + if (s.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } + Sockets.setOption(s, SO_FLOW_SLA, flowIn); out.println(flowIn); }); - doTest("Sockets.getOption Socket",() -> { - Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); + + doTest("Sockets.getOption Socket", () -> { + Sockets.getOption(s, SO_FLOW_SLA); out.println(flowIn); }); - doTest("Sockets.setOption SocketChannel",() -> - sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn) + + doTest("Sockets.setOption SocketChannel", () -> { + if (sc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } + sc.setOption(SO_FLOW_SLA, flowIn); + }); + doTest("Sockets.getOption SocketChannel", () -> + sc.getOption(SO_FLOW_SLA) ); - doTest("Sockets.getOption SocketChannel",() -> - sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA) - ); - doTest("Sockets.setOption DatagramSocket",() -> { + doTest("Sockets.setOption DatagramSocket", () -> { try (DatagramSocket dg1 = new DatagramSocket(0)) { + if (dg1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } + dg1.connect(loop, udp_port); - Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + Sockets.setOption(dg1, SO_FLOW_SLA, flowIn); } }); doTest("Sockets.setOption DatagramSocket 2", () -> { try (DatagramChannel dg2 = DatagramChannel.open()) { + if (dg2.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } dg2.bind(new InetSocketAddress(loop, 0)); dg2.connect(new InetSocketAddress(loop, udp_port)); - dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + dg2.setOption(SO_FLOW_SLA, flowIn); } }); doTest("Sockets.setOption MulticastSocket", () -> { try (MulticastSocket mc1 = new MulticastSocket(0)) { + if (mc1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } mc1.connect(loop, udp_port); - Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + Sockets.setOption(mc1, SO_FLOW_SLA, flowIn); } }); doTest("Sockets.setOption AsynchronousSocketChannel", () -> { try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) { + if (asc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } Future f = asc.connect(loopad); f.get(); - asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + asc.setOption(SO_FLOW_SLA, flowIn); } }); } @@ -144,14 +168,43 @@ public class Test { throw new RuntimeException("Unexpected SecurityException", e); } else { out.println("Caught expected: " + e); + return; } } catch (UnsupportedOperationException e) { - System.out.println(e); + if (expectSupport) { + throw new RuntimeException("Test failed: " + + "unexpected UnsupportedOperationException"); + } + out.println("UnsupportedOperationException as expected"); + return; } catch (IOException e) { // Probably a permission error, but we're not // going to check unless a specific permission exception // is defined. System.out.println(e); } + if (!expectSupport) { + throw new RuntimeException("Test failed: " + + "UnsupportedOperationException was not thrown"); + } } + + private static boolean checkExpectedOptionSupport() { + if (OSInfo.getOSType().equals(OSInfo.OSType.SOLARIS)) { + double solarisVersion = OSInfo.getSolarisVersion(); + if (solarisVersion >= solarisVersionToCheck) { + System.out.println("This Solaris version (" + solarisVersion + + ") should support SO_FLOW_SLA option"); + return true; + } else { + System.out.println("This Solaris version (" + solarisVersion + + ") should not support SO_FLOW_SLA option"); + } + } else { + System.out.println("Not Solaris, SO_FLOW_SLA should not be " + + "supported"); + } + return false; + } + } diff --git a/jdk/test/jdk/net/Sockets/policy.fail b/jdk/test/jdk/net/Sockets/policy.fail index 29d1215e708..1c9b57d90d7 100644 --- a/jdk/test/jdk/net/Sockets/policy.fail +++ b/jdk/test/jdk/net/Sockets/policy.fail @@ -1,4 +1,8 @@ grant { + permission java.util.PropertyPermission "os.name", "read"; + permission java.io.FilePermission "<>", "execute"; + permission java.util.PropertyPermission "line.separator", "read"; + permission java.io.FilePermission "/etc/release", "read"; permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; permission java.net.SocketPermission "localhost", "listen" ; }; diff --git a/jdk/test/jdk/net/Sockets/policy.success b/jdk/test/jdk/net/Sockets/policy.success index 6f99151a38f..653b755b338 100644 --- a/jdk/test/jdk/net/Sockets/policy.success +++ b/jdk/test/jdk/net/Sockets/policy.success @@ -1,4 +1,8 @@ grant { + permission java.util.PropertyPermission "os.name", "read"; + permission java.io.FilePermission "<>", "execute"; + permission java.util.PropertyPermission "line.separator", "read"; + permission java.io.FilePermission "/etc/release", "read"; permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; permission java.net.SocketPermission "localhost", "listen" ; permission jdk.net.NetworkPermission "setOption.SO_FLOW_SLA"; diff --git a/jdk/test/jdk/nio/zipfs/Basic.java b/jdk/test/jdk/nio/zipfs/Basic.java index f29e4bd123e..60ac2e7e0ad 100644 --- a/jdk/test/jdk/nio/zipfs/Basic.java +++ b/jdk/test/jdk/nio/zipfs/Basic.java @@ -31,6 +31,7 @@ import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.ProviderMismatchException; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; @@ -39,14 +40,15 @@ import java.net.URI; import java.io.IOException; import java.util.Collections; import java.util.Map; - +import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; /** * @test - * @bug 8038500 8040059 8150366 8150496 + * @bug 8038500 8040059 8150366 8150496 8147539 * @summary Basic test for zip provider * * @run main Basic * @run main/othervm/java.security.policy=test.policy Basic + * @modules jdk.zipfs */ public class Basic { @@ -89,7 +91,7 @@ public class Basic { found = false; try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("/"))) { for (Path entry: stream) { - found = entry.toString().equals("/META-INF/"); + found = entry.toString().equals("/META-INF"); if (found) break; } } @@ -117,6 +119,13 @@ public class Basic { if (!store.supportsFileAttributeView("basic")) throw new RuntimeException("BasicFileAttributeView should be supported"); + // Test: watch register should throw PME + try { + fs.getPath("/") + .register(FileSystems.getDefault().newWatchService(), ENTRY_CREATE); + throw new RuntimeException("watch service is not supported"); + } catch (ProviderMismatchException x) { } + // Test: ClosedFileSystemException fs.close(); if (fs.isOpen()) diff --git a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java index 7f5f37b44fa..6e483c6e21a 100644 --- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java +++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java @@ -28,6 +28,9 @@ * @library /lib/testlibrary/java/util/jar * @build Compiler JarBuilder CreateMultiReleaseTestJars * @run testng MultiReleaseJarTest + * @modules java.compiler + * jdk.jartool + * jdk.zipfs */ import java.io.IOException; diff --git a/jdk/test/jdk/nio/zipfs/PathOps.java b/jdk/test/jdk/nio/zipfs/PathOps.java index 8f428515cbc..1bd72f7bf9c 100644 --- a/jdk/test/jdk/nio/zipfs/PathOps.java +++ b/jdk/test/jdk/nio/zipfs/PathOps.java @@ -31,11 +31,12 @@ import java.nio.file.Path; /** * * @test - * @bug 8038500 8040059 + * @bug 8038500 8040059 8139956 8146754 * @summary Tests path operations for zip provider. * * @run main PathOps * @run main/othervm/java.security.policy=test.policy PathOps + * @modules jdk.zipfs */ public class PathOps { @@ -424,6 +425,11 @@ public class PathOps { test("/") .relativize("/a", "a") .relativize("/a/c", "a/c"); + // 8146754 + test("/tmp/path") + .relativize("/tmp/path/a.txt", "a.txt"); + test("/tmp/path/") + .relativize("/tmp/path/a.txt", "a.txt"); // normalize test("/") @@ -486,7 +492,16 @@ public class PathOps { // isSameFile test("/fileDoesNotExist") .isSameFile("/fileDoesNotExist"); - } + + // 8139956 + out.println("check getNameCount"); + int nc = fs.getPath("/").relativize(fs.getPath("/")).getNameCount(); + if (nc != 1) { + out.format("\tExpected: 1\n"); + out.format("\tActual: %d\n", nc); + throw new RuntimeException("getNameCount of empty path failed"); + } + } static void npes() { header("NullPointerException"); diff --git a/jdk/test/jdk/nio/zipfs/ZFSTests.java b/jdk/test/jdk/nio/zipfs/ZFSTests.java index 8febcf2730d..d9542601afe 100644 --- a/jdk/test/jdk/nio/zipfs/ZFSTests.java +++ b/jdk/test/jdk/nio/zipfs/ZFSTests.java @@ -22,11 +22,12 @@ */ /* @test - * @bug 7156873 8040059 8028480 8034773 + * @bug 7156873 8040059 8028480 8034773 8153248 * @summary ZipFileSystem regression tests * * @run main ZFSTests * @run main/othervm/java.security.policy=test.policy ZFSTests + * @modules jdk.zipfs */ @@ -42,7 +43,7 @@ public class ZFSTests { public static void main(String[] args) throws Throwable { test7156873(); - testOpenOptions(); + tests(); } static void test7156873() throws Throwable { @@ -61,7 +62,7 @@ public class ZFSTests { } } - static void testOpenOptions() throws Throwable { + static void tests() throws Throwable { Path path = Paths.get("file.zip"); try { URI uri = URI.create("jar:" + path.toUri()); @@ -95,6 +96,18 @@ public class ZFSTests { } catch (IllegalArgumentException x) { // expected x.printStackTrace(); } + + //8153248 + Path dir = fs.getPath("/dir"); + Path subdir = fs.getPath("/dir/subdir"); + Files.createDirectory(dir); + Files.createDirectory(subdir); + Files.list(dir) + .forEach( child -> { + System.out.println("child:" + child); + if (child.toString().endsWith("/")) + throw new RuntimeException("subdir names ends with /"); + }); } } finally { Files.deleteIfExists(path); diff --git a/jdk/test/jdk/nio/zipfs/ZipFSTester.java b/jdk/test/jdk/nio/zipfs/ZipFSTester.java index 58389250e43..683bcae00b6 100644 --- a/jdk/test/jdk/nio/zipfs/ZipFSTester.java +++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java @@ -74,6 +74,7 @@ import static java.nio.file.StandardCopyOption.*; * @summary Test Zip filesystem provider * @run main ZipFSTester * @run main/othervm/java.security.policy=test.policy ZipFSTester + * @modules jdk.zipfs */ public class ZipFSTester { diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java index f95fdeefc1b..7cdc714b0fd 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java @@ -28,6 +28,9 @@ package jdk.testlibrary; import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.InputStreamReader; import static jdk.testlibrary.OSInfo.OSType.*; @@ -147,6 +150,28 @@ public class OSInfo { } } + public static double getSolarisVersion() { + try { + OutputAnalyzer output = ProcessTools.executeProcess("uname", "-v"); + System.out.println("'uname -v' finished with code " + + output.getExitValue()); + return Double.parseDouble(output.getOutput()); + } catch (Exception e) { + System.out.println("First attempt failed with: " + e.getMessage()); + } + + //Try to get Solaris version from /etc/release + try (BufferedReader in = + new BufferedReader(new FileReader("/etc/release"))) { + String line = in.readLine().trim().split(" ")[2]; + return Double.parseDouble(line); + } catch (Exception e) { + System.out.println("Second attempt failed with: " + e.getMessage()); + } + + throw new RuntimeException("Unable to get Solaris version"); + } + public static class WindowsVersion implements Comparable { private final int major; diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java index 35cffc1c994..e2c2f110fc5 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java @@ -423,7 +423,7 @@ public final class ProcessTools { * @param cmds The command line to execute. * @return The output from the process. */ - public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { + public static OutputAnalyzer executeProcess(String... cmds) throws Exception { return executeProcess(new ProcessBuilder(cmds)); } diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java index 4fedb362c5c..17e50c70354 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 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 @@ -23,8 +23,6 @@ package jdk.testlibrary; -import com.sun.net.httpserver.*; - import java.util.*; import java.util.concurrent.*; import java.io.*; @@ -54,7 +52,7 @@ public class SimpleSSLContext { * loads default keystore from SimpleSSLContext * source directory */ - public SimpleSSLContext () throws IOException { + public SimpleSSLContext() throws IOException { String paths = System.getProperty("test.src.path"); StringTokenizer st = new StringTokenizer(paths, File.pathSeparator); boolean securityExceptions = false; @@ -63,8 +61,10 @@ public class SimpleSSLContext { try { File f = new File(path, "jdk/testlibrary/testkeys"); if (f.exists()) { - init (new FileInputStream(f)); - return; + try (FileInputStream fis = new FileInputStream(f)) { + init(fis); + return; + } } } catch (SecurityException e) { // catch and ignore because permission only required @@ -80,13 +80,14 @@ public class SimpleSSLContext { /** * loads default keystore from given directory */ - public SimpleSSLContext (String dir) throws IOException { + public SimpleSSLContext(String dir) throws IOException { String file = dir+"/testkeys"; - FileInputStream fis = new FileInputStream(file); - init(fis); + try (FileInputStream fis = new FileInputStream(file)) { + init(fis); + } } - private void init (InputStream i) throws IOException { + private void init(InputStream i) throws IOException { try { char[] passphrase = "passphrase".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS"); @@ -98,22 +99,22 @@ public class SimpleSSLContext { TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); - ssl = SSLContext.getInstance ("TLS"); + ssl = SSLContext.getInstance("TLS"); ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); } catch (KeyManagementException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (KeyStoreException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (UnrecoverableKeyException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (CertificateException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (NoSuchAlgorithmException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } } - public SSLContext get () { + public SSLContext get() { return ssl; } } diff --git a/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh b/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh index b47a5efcf0c..a93f2652613 100644 --- a/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh +++ b/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 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 @@ -26,6 +26,7 @@ # @test # @bug 4763315 +# @modules java.naming # @build CanonicalName Lookup # @run shell/timeout=120 cname.sh # @summary Test DNS provider's handling of CNAME records diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java index 8791b4e27af..1d837841fb4 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 * @bug 4333920 + * @modules jdk.httpserver * @run main ChunkedEncodingTest * @summary ChunkedEncodingTest unit test */ diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java index 35b76396930..6affe7a767c 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -26,6 +26,7 @@ * @bug 4333920 4994372 * @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem * @modules java.base/sun.net + * jdk.httpserver * @run main ChunkedEncodingWithProgressMonitorTest */ diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java b/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java index 0423c81060f..a1737d79c23 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 * @bug 6446990 + * @modules jdk.httpserver * @run main/othervm TestAvailable * @summary HttpURLConnection#available() reads more and more data into memory */ diff --git a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java index a017e6eca9e..82b4e36d01c 100644 --- a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java +++ b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 * @bug 5026745 6631048 + * @modules jdk.httpserver * @run main/othervm/timeout=500 Test * @summary Cannot flush output stream when writing to an HttpUrlConnection */ diff --git a/jdk/test/sun/net/www/http/HttpClient/B7025238.java b/jdk/test/sun/net/www/http/HttpClient/B7025238.java index 313972594a4..1af7ec83d5f 100644 --- a/jdk/test/sun/net/www/http/HttpClient/B7025238.java +++ b/jdk/test/sun/net/www/http/HttpClient/B7025238.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 @@ -30,6 +30,7 @@ import java.util.concurrent.Executors; /* * @test * @bug 7025238 + * @modules jdk.httpserver * @summary HttpURLConnection does not handle URLs with an empty path component */ public class B7025238 { diff --git a/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java b/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java index 11d6729ae21..7eaa4f74ed4 100644 --- a/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java +++ b/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java @@ -41,6 +41,7 @@ import java.util.List; * @summary Tests for HTTP Digest auth * The impl maintains a cache for auth info, * the testcases run in a separate JVM to avoid cache hits + * @modules jdk.httpserver * @run main/othervm DigestAuth good * @run main/othervm DigestAuth only_nonce * @run main/othervm DigestAuth sha1 diff --git a/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java b/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java index d5dfde58233..6423de7e409 100644 --- a/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java +++ b/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.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 @@ -40,6 +40,7 @@ import sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback; * @test * @bug 8137174 * @modules java.base/sun.net.www.protocol.http.ntlm + * jdk.httpserver * @summary Checks if NTLM auth works fine if security manager set * @run main/othervm/java.security.policy=NTLMAuthWithSM.policy NTLMAuthWithSM */ diff --git a/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java b/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java index 07d353cba85..104be1d6d94 100644 --- a/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java +++ b/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.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 @@ -30,6 +30,7 @@ import java.net.*; /* * @test * @bug 7157360 + * @modules jdk.httpserver * @summary HttpURLConnection: HTTP method DELETE doesn't support output */ public class PostOnDelete { diff --git a/jdk/test/sun/net/www/protocol/http/6550798/test.java b/jdk/test/sun/net/www/protocol/http/6550798/test.java index 9bcf5f91548..95f70f58911 100644 --- a/jdk/test/sun/net/www/protocol/http/6550798/test.java +++ b/jdk/test/sun/net/www/protocol/http/6550798/test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ * @test * @bug 6550798 * @summary Using InputStream.skip with ResponseCache will cause partial data to be cached + * @modules jdk.httpserver * @run main/othervm test */ diff --git a/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java b/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java index d052b018ffa..250557e9c55 100644 --- a/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java +++ b/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 * @bug 6358532 + * @modules jdk.httpserver * @run main/othervm AsyncDisconnect * @summary HttpURLConnection.disconnect doesn't really do the job */ diff --git a/jdk/test/sun/net/www/protocol/http/B5017051.java b/jdk/test/sun/net/www/protocol/http/B5017051.java index 8e1218d1a3a..1859be41a61 100644 --- a/jdk/test/sun/net/www/protocol/http/B5017051.java +++ b/jdk/test/sun/net/www/protocol/http/B5017051.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 5017051 6360774 + * @modules jdk.httpserver * @run main/othervm B5017051 * @summary Tests CR 5017051 & 6360774 */ diff --git a/jdk/test/sun/net/www/protocol/http/B6299712.java b/jdk/test/sun/net/www/protocol/http/B6299712.java index cf7be47e3ef..24c78d64bfa 100644 --- a/jdk/test/sun/net/www/protocol/http/B6299712.java +++ b/jdk/test/sun/net/www/protocol/http/B6299712.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 @@ -24,6 +24,7 @@ /* * @test * @bug 6299712 7150552 + * @modules jdk.httpserver * @run main/othervm B6299712 * @summary NullPointerException in sun.net.www.protocol.http.HttpURLConnection.followRedirect */ diff --git a/jdk/test/sun/net/www/protocol/http/B6369510.java b/jdk/test/sun/net/www/protocol/http/B6369510.java index 7757f091d7b..2068b04b5b2 100644 --- a/jdk/test/sun/net/www/protocol/http/B6369510.java +++ b/jdk/test/sun/net/www/protocol/http/B6369510.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 * @bug 6369510 + * @modules jdk.httpserver * @run main/othervm B6369510 * @summary HttpURLConnection sets Content-Type to application/x-www-form-urlencoded */ diff --git a/jdk/test/sun/net/www/protocol/http/B6518816.java b/jdk/test/sun/net/www/protocol/http/B6518816.java index d74db8ef2aa..929387c3e7b 100644 --- a/jdk/test/sun/net/www/protocol/http/B6518816.java +++ b/jdk/test/sun/net/www/protocol/http/B6518816.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 @@ -24,6 +24,7 @@ /* * @test * @bug 6518816 + * @modules jdk.httpserver * @run main/othervm B6518816 */ diff --git a/jdk/test/sun/net/www/protocol/http/B6641309.java b/jdk/test/sun/net/www/protocol/http/B6641309.java index 9da4da3aef0..25952c65cd7 100644 --- a/jdk/test/sun/net/www/protocol/http/B6641309.java +++ b/jdk/test/sun/net/www/protocol/http/B6641309.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6641309 + * @modules jdk.httpserver * @summary Wrong Cookie separator used in HttpURLConnection */ diff --git a/jdk/test/sun/net/www/protocol/http/B6660405.java b/jdk/test/sun/net/www/protocol/http/B6660405.java index 8cde84eca9f..50b5838e2c5 100644 --- a/jdk/test/sun/net/www/protocol/http/B6660405.java +++ b/jdk/test/sun/net/www/protocol/http/B6660405.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6660405 + * @modules jdk.httpserver * @summary HttpURLConnection returns the wrong InputStream */ diff --git a/jdk/test/sun/net/www/protocol/http/B8012625.java b/jdk/test/sun/net/www/protocol/http/B8012625.java index c8c8ef0c033..8145941530c 100644 --- a/jdk/test/sun/net/www/protocol/http/B8012625.java +++ b/jdk/test/sun/net/www/protocol/http/B8012625.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 @@ -24,6 +24,7 @@ /** * @test * @bug 8012625 + * @modules jdk.httpserver * @run main B8012625 */ diff --git a/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java b/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java index 5e8bb8e4c41..02e54b1529d 100644 --- a/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java +++ b/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 * @bug 6947917 + * @modules jdk.httpserver * @summary Error in basic authentication when user name and password are long */ diff --git a/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java b/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java index 33a143b5b5c..e673080306f 100644 --- a/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java +++ b/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 * @bug 6488669 6595324 6993490 + * @modules jdk.httpserver * @run main/othervm ChunkedErrorStream * @summary Chunked ErrorStream tests */ diff --git a/jdk/test/sun/net/www/protocol/http/HttpOnly.java b/jdk/test/sun/net/www/protocol/http/HttpOnly.java index 6a2ce8256d9..d377ebf7c15 100644 --- a/jdk/test/sun/net/www/protocol/http/HttpOnly.java +++ b/jdk/test/sun/net/www/protocol/http/HttpOnly.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 @@ -23,6 +23,7 @@ /** * @test * @bug 7095980 8007315 + * @modules jdk.httpserver * @summary Ensure HttpURLConnection (and supporting APIs) don't expose * HttpOnly cookies */ diff --git a/jdk/test/sun/net/www/protocol/http/HttpStreams.java b/jdk/test/sun/net/www/protocol/http/HttpStreams.java index 897cd6572b5..9b94b53e09b 100644 --- a/jdk/test/sun/net/www/protocol/http/HttpStreams.java +++ b/jdk/test/sun/net/www/protocol/http/HttpStreams.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 @@ -24,6 +24,7 @@ /** * @test * @bug 8011719 + * @modules jdk.httpserver * @summary Basic checks to verify behavior of returned input streams */ diff --git a/jdk/test/sun/net/www/protocol/http/NoCache.java b/jdk/test/sun/net/www/protocol/http/NoCache.java index f452bc3d497..f60efcb1ed8 100644 --- a/jdk/test/sun/net/www/protocol/http/NoCache.java +++ b/jdk/test/sun/net/www/protocol/http/NoCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 7133367 + * @modules jdk.httpserver * @summary ResponseCache.put should not be called when setUseCaches(false) */ diff --git a/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java b/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java index 6582a67744f..8c485af01ac 100644 --- a/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java +++ b/jdk/test/sun/net/www/protocol/http/RedirectOnPost.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 @@ -24,6 +24,7 @@ /** * @test * @library /lib/testlibrary/ + * @modules jdk.httpserver * @build jdk.testlibrary.SimpleSSLContext * @compile RedirectOnPost.java * @run main/othervm RedirectOnPost diff --git a/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java b/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java index 31954bb17d0..dad3d29e7a4 100644 --- a/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java +++ b/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 * @bug 6472250 + * @modules jdk.httpserver * @run main/othervm StreamingOutputStream * @summary HttpURLConnection.getOutputStream streaming mode bug when called multiple times */ diff --git a/jdk/test/sun/net/www/protocol/http/UserAuth.java b/jdk/test/sun/net/www/protocol/http/UserAuth.java index 4d5b2de12d0..81432a8086f 100644 --- a/jdk/test/sun/net/www/protocol/http/UserAuth.java +++ b/jdk/test/sun/net/www/protocol/http/UserAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 * @bug 6421122 + * @modules jdk.httpserver * @run main/othervm UserAuth * @summary Authorization header removed for preemptive authentication by user code */ diff --git a/jdk/test/sun/net/www/protocol/http/UserCookie.java b/jdk/test/sun/net/www/protocol/http/UserCookie.java index 2216385f312..ee5e15285cf 100644 --- a/jdk/test/sun/net/www/protocol/http/UserCookie.java +++ b/jdk/test/sun/net/www/protocol/http/UserCookie.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 * @bug 6439651 + * @modules jdk.httpserver * @run main/othervm UserAuth * @summary Sending "Cookie" header with JRE 1.5.0_07 doesn't work anymore */ diff --git a/jdk/test/sun/net/www/protocol/http/ZoneId.java b/jdk/test/sun/net/www/protocol/http/ZoneId.java index fb611a4ea52..6d8b7d1b628 100644 --- a/jdk/test/sun/net/www/protocol/http/ZoneId.java +++ b/jdk/test/sun/net/www/protocol/http/ZoneId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,6 +26,7 @@ * @bug 8027308 * @key intermittent * @modules java.base/sun.net.www.protocol.http + * jdk.httpserver * @summary verifies that HttpURLConnection does not send the zone id in the * 'Host' field of the header: * Host: [fe80::a00:27ff:aaaa:aaaa] instead of diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java index a7e0bc3ab14..68b20803ae9 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -26,6 +26,7 @@ * @bug 6771432 * @summary createSocket() - smpatch fails using 1.6.0_10 because of * "Unconnected sockets not implemented" + * @modules jdk.httpserver * @run main/othervm HttpsCreateSockTest * * SunJSSE does not support dynamic system properties, no way to re-use diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java index 4011cea722e..6e1414f8cdd 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ * @test * @bug 6614957 * @summary HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets + * @modules jdk.httpserver * @run main/othervm HttpsSocketFacTest * * SunJSSE does not support dynamic system properties, no way to re-use diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java index f6b01a08d40..e97de717772 100644 --- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java +++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -26,6 +26,9 @@ * @bug 8132734 8144062 * @summary Test that URL connections to multi-release jars can be runtime versioned * @library /lib/testlibrary/java/util/jar + * @modules java.compiler + * jdk.httpserver + * jdk.jartool * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer * @run testng MultiReleaseJarURLConnection */ diff --git a/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java b/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java index 8c8049bdf5c..9ec2dbfd019 100644 --- a/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java +++ b/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java @@ -43,6 +43,7 @@ import java.util.Random; /* * @test * @requires sun.arch.data.model == "64" + * @modules java.management * @build TestMaxCachedBufferSize * @run main/othervm TestMaxCachedBufferSize * @run main/othervm -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize diff --git a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java index bd2fcdadc31..45a7c178455 100644 --- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java +++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java @@ -33,6 +33,7 @@ import java.security.spec.DSAParameterSpec; import java.security.spec.InvalidParameterSpecException; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /* * @test @@ -41,26 +42,15 @@ import java.util.List; * @summary Verify that DSAGenParameterSpec can and can only be used to generate * DSA within some certain range of key sizes as described in the class * specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and - * (3072, 256) should be OK for DSAGenParameterSpec. But the real - * implementation SUN doesn't support (3072, 256). - * @run main TestDSAGenParameterSpec + * (3072, 256) should be OK for DSAGenParameterSpec. + * @run main TestDSAGenParameterSpec 2048,256,true 2048,224,true 1024,160,true 4096,256 3072,224 2048,160 1024,224 512,160 + * @run main TestDSAGenParameterSpec 3072,256,true */ public class TestDSAGenParameterSpec { private static final String ALGORITHM_NAME = "DSA"; private static final String PROVIDER_NAME = "SUN"; - private static final List DATA = Arrays.asList( - new DataTuple(1024, 160, true, true), - new DataTuple(2048, 224, true, true), - new DataTuple(2048, 256, true, true), - new DataTuple(3072, 256, true, false), - new DataTuple(1024, 224), - new DataTuple(2048, 160), - new DataTuple(4096, 256), - new DataTuple(512, 160), - new DataTuple(3072, 224)); - private static void testDSAGenParameterSpec(DataTuple dataTuple) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidParameterSpecException, InvalidAlgorithmParameterException { @@ -84,14 +74,7 @@ public class TestDSAGenParameterSpec { checkParam(param, genParamSpec); System.out.println("Test case passed"); } catch (InvalidParameterException ipe) { - // The DSAGenParameterSpec API support this, but the real - // implementation in SUN doesn't - if (!dataTuple.isSunProviderSupported) { - System.out.println("Test case passed: expected " - + "InvalidParameterException is caught"); - } else { - throw new RuntimeException("Test case failed.", ipe); - } + throw new RuntimeException("Test case failed.", ipe); } } @@ -127,11 +110,9 @@ public class TestDSAGenParameterSpec { throw new RuntimeException("Wrong seed length"); } - // use the parameters to generate real DSA keys KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM_NAME, PROVIDER_NAME); keyGen.initialize(spec); - keyGen.generateKeyPair(); } private static DSAGenParameterSpec createGenParameterSpec( @@ -158,10 +139,21 @@ public class TestDSAGenParameterSpec { } public static void main(String[] args) throws Exception { - for (DataTuple dataTuple : DATA) { + List dataTuples = Arrays.stream(args) + .map(arg -> arg.split(",")).map(params -> { + int primePLen = Integer.valueOf(params[0]); + int subprimeQLen = Integer.valueOf(params[1]); + boolean isDSASpecSupported = false; + if (params.length == 3) { + isDSASpecSupported = Boolean.valueOf(params[2]); + } + return new DataTuple(primePLen, subprimeQLen, + isDSASpecSupported); + }).collect(Collectors.toList()); + + for (DataTuple dataTuple : dataTuples) { testDSAGenParameterSpec(dataTuple); } - System.out.println("All tests passed"); } private static class DataTuple { @@ -169,18 +161,13 @@ public class TestDSAGenParameterSpec { private int primePLen; private int subprimeQLen; private boolean isDSASpecSupported; - private boolean isSunProviderSupported; private DataTuple(int primePLen, int subprimeQLen, - boolean isDSASpecSupported, boolean isSunProviderSupported) { + boolean isDSASpecSupported) { this.primePLen = primePLen; this.subprimeQLen = subprimeQLen; this.isDSASpecSupported = isDSASpecSupported; - this.isSunProviderSupported = isSunProviderSupported; - } - - private DataTuple(int primePLen, int subprimeQLen) { - this(primePLen, subprimeQLen, false, false); } } } + diff --git a/jdk/test/sun/security/provider/PolicyFile/Modules.java b/jdk/test/sun/security/provider/PolicyFile/Modules.java index 855441e036a..914ef05790d 100644 --- a/jdk/test/sun/security/provider/PolicyFile/Modules.java +++ b/jdk/test/sun/security/provider/PolicyFile/Modules.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 @@ -25,6 +25,19 @@ * @test * @bug 8047771 * @summary check permissions and principals from various modules + * @modules java.desktop + * java.logging + * java.management + * java.security.jgss + * java.smartcardio + * java.sql + * java.xml + * java.xml.bind + * jdk.attach + * jdk.jdi + * jdk.net + * jdk.security.auth + * jdk.security.jgss * @compile -addmods java.xml.ws,java.smartcardio Modules.java * @run main/othervm/java.security.policy==modules.policy * -addmods java.xml.ws,java.smartcardio Modules diff --git a/jdk/test/sun/text/IntHashtable/Bug4170614Test.java b/jdk/test/sun/text/IntHashtable/Bug4170614Test.java new file mode 100644 index 00000000000..97e08a1bdd4 --- /dev/null +++ b/jdk/test/sun/text/IntHashtable/Bug4170614Test.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1999, 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. + */ + +/* + (this test doesn't have an at-test tag because it's run by a shell + script instead of directly by the test harness) +*/ + +/* + * + * + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - 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. + * + */ +package java.text; +import sun.text.IntHashtable; + + +/** + * This class tests some internal hashCode() functions. + * Bug #4170614 complained that we had two iternal classes that + * break the invariant that if a.equals(b) than a.hashCode() == + * b.hashCode(). This is because these classes overrode equals() + * but not hashCode(). These are both purely internal classes, and + * the library itself doesn't actually call hashCode(), so this isn't + * actually causing anyone problems yet. But if these classes are + * ever exposed in the API, their hashCode() methods need to work right. + * PatternEntry will never be exposed in the API, but IntHashtable + * might be. This is a shell test to allow us to access classes that + * are declared package private. + * @author Richard Gillam + */ +public class Bug4170614Test { + public static void main(String[] args) throws Exception { + testIntHashtable(); + testPatternEntry(); + } + + + public static void testIntHashtable() throws Exception { + IntHashtable fred = new IntHashtable(); + fred.put(1, 10); + fred.put(2, 20); + fred.put(3, 30); + + IntHashtable barney = new IntHashtable(); + barney.put(1, 10); + barney.put(3, 30); + barney.put(2, 20); + + IntHashtable homer = new IntHashtable(); + homer.put(3, 30); + homer.put(1, 10); + homer.put(7, 900); + + if (fred.equals(barney)) { + System.out.println("fred.equals(barney)"); + } + else { + System.out.println("!fred.equals(barney)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("barney.hashCode() == " + barney.hashCode()); + + if (!fred.equals(barney)) { + throw new Exception("equals() failed on two hashtables that are equal"); + } + + if (fred.hashCode() != barney.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are equal"); + } + + System.out.println(); + if (fred.equals(homer)) { + System.out.println("fred.equals(homer)"); + } + else { + System.out.println("!fred.equals(homer)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("homer.hashCode() == " + homer.hashCode()); + + if (fred.equals(homer)) { + throw new Exception("equals() failed on two hashtables that are not equal"); + } + + if (fred.hashCode() == homer.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are not equal"); + } + + System.out.println(); + System.out.println("testIntHashtable() passed.\n"); + } + + public static void testPatternEntry() throws Exception { + PatternEntry fred = new PatternEntry(1, + new StringBuffer("hello"), + new StringBuffer("up")); + PatternEntry barney = new PatternEntry(1, + new StringBuffer("hello"), + new StringBuffer("down")); + // (equals() only considers the "chars" field, so fred and barney are equal) + PatternEntry homer = new PatternEntry(1, + new StringBuffer("goodbye"), + new StringBuffer("up")); + + if (fred.equals(barney)) { + System.out.println("fred.equals(barney)"); + } + else { + System.out.println("!fred.equals(barney)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("barney.hashCode() == " + barney.hashCode()); + + if (!fred.equals(barney)) { + throw new Exception("equals() failed on two hashtables that are equal"); + } + + if (fred.hashCode() != barney.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are equal"); + } + + System.out.println(); + if (fred.equals(homer)) { + System.out.println("fred.equals(homer)"); + } + else { + System.out.println("!fred.equals(homer)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("homer.hashCode() == " + homer.hashCode()); + + if (fred.equals(homer)) { + throw new Exception("equals() failed on two hashtables that are not equal"); + } + + if (fred.hashCode() == homer.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are not equal"); + } + + System.out.println(); + System.out.println("testPatternEntry() passed.\n"); + } +} diff --git a/jdk/test/sun/text/IntHashtable/Bug4170614Test.sh b/jdk/test/sun/text/IntHashtable/Bug4170614Test.sh new file mode 100644 index 00000000000..b8dad0084a6 --- /dev/null +++ b/jdk/test/sun/text/IntHashtable/Bug4170614Test.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# +# Copyright (c) 1999, 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 4170614 +# @summary Test internal hashCode() functions +# + +set -x +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}" + +goback=`pwd` + +cd ${TESTSRC} + +TEST_JAVABASE=${TESTCLASSES}/java.base +mkdir -p ${TEST_JAVABASE} +${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ + -Xmodule:java.base \ + -d ${TEST_JAVABASE} Bug4170614Test.java + +${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:java.base=${TEST_JAVABASE} java.text.Bug4170614Test + +result=$? + +cd ${goback} + +if [ $result -eq 0 ] +then + echo "Passed" +else + echo "Failed" +fi +exit $result + + + diff --git a/jdk/test/sun/text/IntHashtable/Bug4705389.java b/jdk/test/sun/text/IntHashtable/Bug4705389.java new file mode 100644 index 00000000000..d2f6e49a829 --- /dev/null +++ b/jdk/test/sun/text/IntHashtable/Bug4705389.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002, 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 4705389 + * @summary Make sure to find removed slots, which test case will be timed out without the fix. + * @modules java.base/sun.text + * @run main/timeout=10 Bug4705389 + */ + +import sun.text.IntHashtable; + +public class Bug4705389 { + public static void main(String args[]) { + IntHashtable table = new IntHashtable(); + for (int i = 1; i < 132; ++i) { + table.put(i, 0); + table.remove(i); + } + table.put(132, 0); + } +} diff --git a/jdk/test/sun/util/logging/SourceClassName.java b/jdk/test/sun/util/logging/SourceClassName.java index 0de431a1a20..f3023122618 100644 --- a/jdk/test/sun/util/logging/SourceClassName.java +++ b/jdk/test/sun/util/logging/SourceClassName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ * logger. * * @modules java.base/sun.util.logging + * java.logging * @compile -XDignore.symbol.file SourceClassName.java * @run main/othervm SourceClassName */ diff --git a/make/Images.gmk b/make/Images.gmk index 92adf3013db..c3e93a47a97 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -115,9 +115,12 @@ JMODS := $(wildcard $(IMAGES_OUTPUTDIR)/jmods/*.jmod) # Use this file inside the image as target for make rule JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX) -JLINK_ORDER_RESOURCES := \ - *module-info.class* \ - @$(SUPPORT_OUTPUTDIR)/classlist/classlist,/java.base/java/* \ +JLINK_ORDER_RESOURCES := *module-info.class* +ifeq ($(ENABLE_GENERATE_CLASSLIST), true) + JLINK_ORDER_RESOURCES += @$(SUPPORT_OUTPUTDIR)/classlist/classlist +endif +JLINK_ORDER_RESOURCES += \ + /java.base/java/* \ /java.base/jdk/* \ /java.base/sun/* \ /java.base/com/* \ @@ -125,9 +128,10 @@ JLINK_ORDER_RESOURCES := \ # JLINK_TOOL := $(JLINK) --modulepath $(IMAGES_OUTPUTDIR)/jmods \ - --endian $(OPENJDK_BUILD_CPU_ENDIAN) \ - --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \ - --release-info $(BASE_RELEASE_FILE) + --endian $(OPENJDK_BUILD_CPU_ENDIAN) \ + --release-info $(BASE_RELEASE_FILE) \ + --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \ + # ifeq ($(JLINK_KEEP_PACKAGED_MODULES), true) JLINK_EXTRA_OPTS := --keep-packaged-modules $(JDK_IMAGE_DIR)/jmods @@ -369,19 +373,21 @@ JDK_TARGETS += $(JDK_IMAGE_DIR)/src.zip ################################################################################ # classlist -$(eval $(call SetupCopyFiles, JDK_COPY_CLASSLIST, \ - FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ - DEST := $(JDK_IMAGE_DIR)/lib, \ -)) +ifeq ($(ENABLE_GENERATE_CLASSLIST), true) + $(eval $(call SetupCopyFiles, JDK_COPY_CLASSLIST, \ + FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ + DEST := $(JDK_IMAGE_DIR)/lib, \ + )) -JDK_TARGETS += $(JDK_COPY_CLASSLIST) + JDK_TARGETS += $(JDK_COPY_CLASSLIST) -$(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \ - FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ - DEST := $(JRE_IMAGE_DIR)/lib, \ -)) + $(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \ + FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ + DEST := $(JRE_IMAGE_DIR)/lib, \ + )) -JRE_TARGETS += $(JRE_COPY_CLASSLIST) + JRE_TARGETS += $(JRE_COPY_CLASSLIST) +endif ################################################################################ # /demo dir diff --git a/make/Main.gmk b/make/Main.gmk index cbde81f552c..d703a266fa1 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -373,8 +373,10 @@ ALL_TARGETS += create-buildjdk-copy create-buildjdk-interim-image interim-image: +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f InterimImage.gmk) -generate-classlist: +ifeq ($(ENABLE_GENERATE_CLASSLIST), true) + generate-classlist: +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f GenerateClasslist.gmk) +endif ALL_TARGETS += interim-image generate-classlist @@ -640,18 +642,22 @@ else jrtfs-jar: interim-langtools - ifeq ($(CREATE_BUILDJDK), true) - # If creating a buildjdk, the interim image needs to be based on that. - generate-classlist: create-buildjdk - else ifeq ($(EXTERNAL_BUILDJDK), false) - # If an external buildjdk has been provided, we skip generating an - # interim-image and just use the external buildjdk for generating - # classlist. - generate-classlist: interim-image - endif - generate-classlist: buildtools-jdk + ifeq ($(ENABLE_GENERATE_CLASSLIST), true) + ifeq ($(CREATE_BUILDJDK), true) + # If creating a buildjdk, the interim image needs to be based on that. + generate-classlist: create-buildjdk + else ifeq ($(EXTERNAL_BUILDJDK), false) + # If an external buildjdk has been provided, we skip generating an + # interim-image and just use the external buildjdk for generating + # classlist. + generate-classlist: interim-image + endif + generate-classlist: buildtools-jdk - jimages: jmods zip-source source-tips demos samples jrtfs-jar generate-classlist + jimages: generate-classlist + endif + + jimages: jmods zip-source source-tips demos samples jrtfs-jar profiles: jmods zip-source source-tips jrtfs-jar diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 4aa4df6e17e..d14800deeb1 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -353,3 +353,4 @@ ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114 5267e91811614bac129817e566f730e9d63cf22a jdk-9+117 05679aac2f7ec3d8dd2a96d7e7899906224bf5cf jdk-9+118 621ad507bf9b07e7c6da2150aa619fe7e78ec5a0 jdk-9+119 +7ab7fc00b147e5b50d6bd5516147680f11c0b165 jdk-9+120 diff --git a/nashorn/samples/test.js b/nashorn/samples/test.js index dfe4b7b937a..217cab164ba 100644 --- a/nashorn/samples/test.js +++ b/nashorn/samples/test.js @@ -31,4 +31,4 @@ print("Hello World"); var System = Java.type("java.lang.System"); -print(System.getProperty("jdk.launcher.patch.0")); +print(System.getProperty("java.home")); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java index b2090dcca6b..0fb867f91ce 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java @@ -238,7 +238,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin @Override public MethodHandle call() { return Bootstrap.createDynamicCallInvoker(double.class, - ScriptFunction.class, Object.class, Object.class, Object.class); + Object.class, Object.class, Object.class, Object.class); } }); } @@ -1210,23 +1210,23 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin return copy; } - private static ScriptFunction compareFunction(final Object comparefn) { + private static Object compareFunction(final Object comparefn) { if (comparefn == ScriptRuntime.UNDEFINED) { return null; } - if (! (comparefn instanceof ScriptFunction)) { + if (!Bootstrap.isCallable(comparefn)) { throw typeError("not.a.function", ScriptRuntime.safeToString(comparefn)); } - return (ScriptFunction)comparefn; + return comparefn; } private static Object[] sort(final Object[] array, final Object comparefn) { - final ScriptFunction cmp = compareFunction(comparefn); + final Object cmp = compareFunction(comparefn); final List list = Arrays.asList(array); - final Object cmpThis = cmp == null || cmp.isStrict() ? ScriptRuntime.UNDEFINED : Global.instance(); + final Object cmpThis = cmp == null || Bootstrap.isStrictCallable(cmp) ? ScriptRuntime.UNDEFINED : Global.instance(); try { Collections.sort(list, new Comparator() { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java index b5e139c79bc..b8141a9b5fb 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java @@ -47,7 +47,6 @@ import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSONFunctions; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; import jdk.nashorn.internal.runtime.linker.Bootstrap; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java index 3b5998063af..3bf1663933a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java @@ -45,7 +45,6 @@ import jdk.nashorn.internal.runtime.BitVector; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ParserException; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.Bootstrap; @@ -655,7 +654,7 @@ public final class NativeRegExp extends ScriptObject { * @param replacement Replacement string. * @return String with substitutions. */ - String replace(final String string, final String replacement, final ScriptFunction function) throws Throwable { + String replace(final String string, final String replacement, final Object function) throws Throwable { final RegExpMatcher matcher = regexp.match(string); if (matcher == null) { @@ -671,7 +670,7 @@ public final class NativeRegExp extends ScriptObject { sb.append(string, 0, matcher.start()); if (function != null) { - final Object self = function.isStrict() ? UNDEFINED : Global.instance(); + final Object self = Bootstrap.isStrictCallable(function) ? UNDEFINED : Global.instance(); sb.append(callReplaceValue(getReplaceValueInvoker(), function, self, matcher, string)); } else { appendReplacement(matcher, string, replacement, sb); @@ -691,7 +690,7 @@ public final class NativeRegExp extends ScriptObject { final StringBuilder sb = new StringBuilder(); final MethodHandle invoker = function == null ? null : getReplaceValueInvoker(); - final Object self = function == null || function.isStrict() ? UNDEFINED : Global.instance(); + final Object self = function == null || Bootstrap.isStrictCallable(function) ? UNDEFINED : Global.instance(); do { sb.append(string, thisIndex, matcher.start()); @@ -807,12 +806,12 @@ public final class NativeRegExp extends ScriptObject { new Callable() { @Override public MethodHandle call() { - return Bootstrap.createDynamicCallInvoker(String.class, ScriptFunction.class, Object.class, Object[].class); + return Bootstrap.createDynamicCallInvoker(String.class, Object.class, Object.class, Object[].class); } }); } - private String callReplaceValue(final MethodHandle invoker, final ScriptFunction function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable { + private String callReplaceValue(final MethodHandle invoker, final Object function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable { final Object[] groups = groups(matcher); final Object[] args = Arrays.copyOf(groups, groups.length + 2); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java index 33e087bde80..ec1619e1b88 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java @@ -58,10 +58,10 @@ import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.OptimisticBuiltins; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.arrays.ArrayIndex; +import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.NashornGuards; import jdk.nashorn.internal.runtime.linker.PrimitiveLookup; @@ -743,8 +743,8 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti nativeRegExp = NativeRegExp.flatRegExp(JSType.toString(string)); } - if (replacement instanceof ScriptFunction) { - return nativeRegExp.replace(str, "", (ScriptFunction)replacement); + if (Bootstrap.isCallable(replacement)) { + return nativeRegExp.replace(str, "", replacement); } return nativeRegExp.replace(str, JSType.toString(replacement), null); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java index 6e11734e20a..7b08a78f807 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java @@ -31,7 +31,6 @@ import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; -import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java index 19e5f1c8405..fb27bffc7a7 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java @@ -31,7 +31,6 @@ import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; -import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java index 5f56c364c6b..32cdc09d661 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java @@ -46,7 +46,7 @@ public final class JSONFunctions { @Override public MethodHandle call() { return Bootstrap.createDynamicCallInvoker(Object.class, - ScriptFunction.class, ScriptObject.class, String.class, Object.class); + Object.class, Object.class, String.class, Object.class); } }); } @@ -90,16 +90,16 @@ public final class JSONFunctions { // apply 'reviver' function if available private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) { - if (reviver instanceof ScriptFunction) { + if (Bootstrap.isCallable(reviver)) { final ScriptObject root = global.newObject(); root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered); - return walk(root, "", (ScriptFunction)reviver); + return walk(root, "", reviver); } return unfiltered; } // This is the abstract "Walk" operation from the spec. - private static Object walk(final ScriptObject holder, final Object name, final ScriptFunction reviver) { + private static Object walk(final ScriptObject holder, final Object name, final Object reviver) { final Object val = holder.get(name); if (val instanceof ScriptObject) { final ScriptObject valueObj = (ScriptObject)val; @@ -131,7 +131,7 @@ public final class JSONFunctions { try { // Object.class, ScriptFunction.class, ScriptObject.class, String.class, Object.class); - return getREVIVER_INVOKER().invokeExact(reviver, holder, JSType.toString(name), val); + return getREVIVER_INVOKER().invokeExact(reviver, (Object)holder, JSType.toString(name), val); } catch(Error|RuntimeException t) { throw t; } catch(final Throwable t) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java index 9648da3e0f2..cdbbb0fea22 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java @@ -171,7 +171,9 @@ public final class Bootstrap { return ((JSObject)callable).isStrictFunction(); } else if (callable instanceof BoundCallable) { return isStrictCallable(((BoundCallable)callable).getCallable()); - } else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass) { + } else if (BeansLinker.isDynamicMethod(callable) || + callable instanceof StaticClass || + isFunctionalInterfaceObject(callable)) { return false; } throw notFunction(callable); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java index b81cd2add9e..d2a46eae78f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java @@ -186,7 +186,7 @@ public class NashornBeansLinker implements GuardingDynamicLinker { if (iface.isAnnotationPresent(FunctionalInterface.class)) { // return the first abstract method for (final Method m : iface.getMethods()) { - if (Modifier.isAbstract(m.getModifiers())) { + if (Modifier.isAbstract(m.getModifiers()) && !isOverridableObjectMethod(m)) { return m.getName(); } } @@ -197,6 +197,23 @@ public class NashornBeansLinker implements GuardingDynamicLinker { return findFunctionalInterfaceMethodName(clazz.getSuperclass()); } + // is this an overridable java.lang.Object method? + private static boolean isOverridableObjectMethod(final Method m) { + switch (m.getName()) { + case "equals": + if (m.getReturnType() == boolean.class) { + final Class[] params = m.getParameterTypes(); + return params.length == 1 && params[0] == Object.class; + } + return false; + case "hashCode": + return m.getReturnType() == int.class && m.getParameterCount() == 0; + case "toString": + return m.getReturnType() == String.class && m.getParameterCount() == 0; + } + return false; + } + // Returns @FunctionalInterface annotated interface's single abstract // method name. If not found, returns null. static String getFunctionalInterfaceMethodName(final Class clazz) { diff --git a/nashorn/test/script/basic/JDK-8157680.js b/nashorn/test/script/basic/JDK-8157680.js new file mode 100644 index 00000000000..02c868ecfcd --- /dev/null +++ b/nashorn/test/script/basic/JDK-8157680.js @@ -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. + */ + +/** + * JDK-8157680: Callback parameter of any JS builtin implementation should accept any Callable + * + * @option -scripting + * @test + * @run + */ + +var SM = Java.type("javax.script.ScriptEngineManager") +var engine = new SM().getEngineByName("nashorn") + +engine.put("output", print); +var reviver = engine.eval(< " + value) + return value + } +}) + +// compare function from the mirror world +var arr = [34,567,-3, 53].sort(engine.eval(< y)? 1 : 0) +EOF)) +print(arr) + +// compare function as a JSObject function +arr = [34,57,-3, 53, 670, 33].sort(new AJO() { + isFunction: function() true, + call: function(thiz, args) { + var x = args[0], y = args[1] + return x < y? -1 : ((x > y)? 1 : 0) + } +}) +print(arr) + +// replacer function from mirror world +var str = "hello".replace(/l/g, engine.eval(< hello +-3,34,53,567 +-3,33,34,53,57,670 +he__o +hELLo diff --git a/nashorn/test/script/basic/JDK-8157819.js b/nashorn/test/script/basic/JDK-8157819.js new file mode 100644 index 00000000000..869aa15f8d2 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8157819.js @@ -0,0 +1,46 @@ +/* + * 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-8157819: TypeError when a java.util.Comparator object is invoked as a function + * + * @test + * @run + */ + +var compare = java.util.Comparator.naturalOrder() +Assert.assertTrue(compare("nashorn", "ecmascript") > 0) +Assert.assertTrue(compare("abc", "xyz") < 0) +Assert.assertTrue(compare("hello", "hello") == 0) + +var rcompare = java.util.Comparator.reverseOrder() +Assert.assertTrue(rcompare("nashorn", "ecmascript") < 0) +Assert.assertTrue(rcompare("abc", "xyz") > 0) +Assert.assertTrue(rcompare("hello", "hello") == 0) + +var arr = [ "nashorn", "JavaScript", "ECMAScript", "ecmascript", "js" ] +Assert.assertEquals(arr.sort(compare).join(), + "ECMAScript,JavaScript,ecmascript,js,nashorn") +Assert.assertEquals(arr.sort(rcompare).join(), + "nashorn,js,ecmascript,JavaScript,ECMAScript") +