" +
+ 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/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/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/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);
+ }
+}
From a29401159ff5f3c726b0bbb0307a21ae38cd92c4 Mon Sep 17 00:00:00 2001
From: Jim Laskey
Date: Fri, 27 May 2016 12:34:08 -0300
Subject: [PATCH 41/48] 8156209: Add argument checks to BasicImageReader calls
Reviewed-by: sundar
---
.../jdk/internal/jimage/BasicImageReader.java | 30 ++++++++++++++-----
.../jdk/internal/jimage/ImageHeader.java | 5 ++++
.../jdk/internal/jimage/ImageLocation.java | 10 +++++--
.../jdk/internal/jimage/ImageReader.java | 8 +++++
.../internal/jimage/ImageReaderFactory.java | 2 ++
.../jdk/internal/jimage/ImageStream.java | 9 +++---
.../internal/jimage/ImageStringsReader.java | 17 +++++++++--
7 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
index 68b076784f5..07038b9ef5e 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
@@ -67,9 +67,9 @@ public class BasicImageReader implements AutoCloseable {
static private final boolean MAP_ALL =
isSystemProperty("jdk.image.map.all", "true", IS_64_BIT ? "true" : "false");
- private final String name;
- private final ByteOrder byteOrder;
private final Path imagePath;
+ private final ByteOrder byteOrder;
+ private final String name;
private final ByteBuffer memoryMap;
private final FileChannel channel;
private final ImageHeader header;
@@ -83,11 +83,9 @@ public class BasicImageReader implements AutoCloseable {
protected BasicImageReader(Path path, ByteOrder byteOrder)
throws IOException {
- Objects.requireNonNull(path);
- Objects.requireNonNull(byteOrder);
- this.name = path.toString();
- this.byteOrder = byteOrder;
- imagePath = path;
+ this.imagePath = Objects.requireNonNull(path);
+ this.byteOrder = Objects.requireNonNull(byteOrder);
+ this.name = this.imagePath.toString();
ByteBuffer map;
@@ -211,6 +209,8 @@ public class BasicImageReader implements AutoCloseable {
}
public static void releaseByteBuffer(ByteBuffer buffer) {
+ Objects.requireNonNull(buffer);
+
if (!MAP_ALL) {
ImageBufferCache.releaseBuffer(buffer);
}
@@ -240,10 +240,14 @@ public class BasicImageReader implements AutoCloseable {
}
public ImageLocation findLocation(String mn, String rn) {
+ Objects.requireNonNull(mn);
+ Objects.requireNonNull(rn);
+
return findLocation("/" + mn + "/" + rn);
}
public synchronized ImageLocation findLocation(String name) {
+ Objects.requireNonNull(name);
// Details of the algorithm used here can be found in
// jdk.tools.jlink.internal.PerfectHashBuilder.
byte[] bytes = ImageStringsReader.mutf8FromString(name);
@@ -287,16 +291,25 @@ public class BasicImageReader implements AutoCloseable {
}
public long[] getAttributes(int offset) {
+ if (offset < 0 || offset >= locations.limit()) {
+ throw new IndexOutOfBoundsException("offset");
+ }
+
ByteBuffer buffer = slice(locations, offset, locations.limit() - offset);
return ImageLocation.decompress(buffer);
}
public String getString(int offset) {
+ if (offset < 0 || offset >= strings.limit()) {
+ throw new IndexOutOfBoundsException("offset");
+ }
+
ByteBuffer buffer = slice(strings, offset, strings.limit() - offset);
return ImageStringsReader.stringFromByteBuffer(buffer);
}
private byte[] getBufferBytes(ByteBuffer buffer) {
+ Objects.requireNonNull(buffer);
byte[] bytes = new byte[buffer.limit()];
buffer.get(bytes);
@@ -343,6 +356,7 @@ public class BasicImageReader implements AutoCloseable {
}
public byte[] getResource(String name) {
+ Objects.requireNonNull(name);
ImageLocation location = findLocation(name);
return location != null ? getResource(location) : null;
@@ -362,6 +376,7 @@ public class BasicImageReader implements AutoCloseable {
}
public ByteBuffer getResourceBuffer(ImageLocation loc) {
+ Objects.requireNonNull(loc);
long offset = loc.getContentOffset() + indexSize;
long compressedSize = loc.getCompressedSize();
long uncompressedSize = loc.getUncompressedSize();
@@ -399,6 +414,7 @@ public class BasicImageReader implements AutoCloseable {
}
public InputStream getResourceStream(ImageLocation loc) {
+ Objects.requireNonNull(loc);
byte[] bytes = getResource(loc);
return new ByteArrayInputStream(bytes);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
index 094f8dd6929..a7ab8a45286 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
@@ -27,6 +27,7 @@ package jdk.internal.jimage;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
+import java.util.Objects;
/**
* @implNote This class needs to maintain JDK 8 source compatibility.
@@ -75,6 +76,8 @@ public final class ImageHeader {
}
static ImageHeader readFrom(IntBuffer buffer) {
+ Objects.requireNonNull(buffer);
+
if (buffer.capacity() != HEADER_SLOTS) {
throw new InternalError("jimage header not the correct size");
}
@@ -94,11 +97,13 @@ public final class ImageHeader {
}
public void writeTo(ImageStream stream) {
+ Objects.requireNonNull(stream);
stream.ensure(getHeaderSize());
writeTo(stream.getBuffer());
}
public void writeTo(ByteBuffer buffer) {
+ Objects.requireNonNull(buffer);
buffer.putInt(magic);
buffer.putInt(majorVersion << 16 | minorVersion);
buffer.putInt(flags);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
index a8147d2a53a..16787dad3af 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
@@ -26,6 +26,7 @@
package jdk.internal.jimage;
import java.nio.ByteBuffer;
+import java.util.Objects;
/**
* @implNote This class needs to maintain JDK 8 source compatibility.
@@ -50,8 +51,8 @@ public class ImageLocation {
protected final ImageStrings strings;
public ImageLocation(long[] attributes, ImageStrings strings) {
- this.attributes = attributes;
- this.strings = strings;
+ this.attributes = Objects.requireNonNull(attributes);
+ this.strings = Objects.requireNonNull(strings);
}
ImageStrings getStrings() {
@@ -67,6 +68,7 @@ public class ImageLocation {
}
static long[] decompress(ByteBuffer bytes) {
+ Objects.requireNonNull(bytes);
long[] attributes = new long[ATTRIBUTE_COUNT];
if (bytes != null) {
@@ -103,6 +105,7 @@ public class ImageLocation {
}
public static byte[] compress(long[] attributes) {
+ Objects.requireNonNull(attributes);
ImageStream stream = new ImageStream(16);
for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) {
@@ -124,6 +127,8 @@ public class ImageLocation {
}
public boolean verify(String name) {
+ Objects.requireNonNull(name);
+
return name.equals(getFullName());
}
@@ -250,6 +255,7 @@ public class ImageLocation {
}
static ImageLocation readFrom(BasicImageReader reader, int offset) {
+ Objects.requireNonNull(reader);
long[] attributes = reader.getAttributes(offset);
ImageStringsReader strings = reader.getStrings();
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java
index a747ea8aa7b..60ab472db3e 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java
@@ -59,6 +59,9 @@ public final class ImageReader implements AutoCloseable {
}
public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException {
+ Objects.requireNonNull(imagePath);
+ Objects.requireNonNull(byteOrder);
+
return SharedImageReader.open(imagePath, byteOrder);
}
@@ -218,6 +221,9 @@ public final class ImageReader implements AutoCloseable {
}
public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException {
+ Objects.requireNonNull(imagePath);
+ Objects.requireNonNull(byteOrder);
+
synchronized (OPEN_FILES) {
SharedImageReader reader = OPEN_FILES.get(imagePath);
@@ -237,6 +243,8 @@ public final class ImageReader implements AutoCloseable {
}
public void close(ImageReader image) throws IOException {
+ Objects.requireNonNull(image);
+
synchronized (OPEN_FILES) {
if (!openers.remove(image)) {
throw new IOException("image file already closed");
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java
index 23be8faaf19..092b309b0b7 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java
@@ -31,6 +31,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
+import java.util.Objects;
/**
* Factory to get ImageReader
@@ -54,6 +55,7 @@ public class ImageReaderFactory {
* Returns an {@code ImageReader} to read from the given image file
*/
public static ImageReader get(Path jimage) throws IOException {
+ Objects.requireNonNull(jimage);
ImageReader reader = readers.get(jimage);
if (reader != null) {
return reader;
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
index 6abe1e651aa..dfa6394acdf 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
@@ -28,6 +28,7 @@ package jdk.internal.jimage;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
+import java.util.Objects;
/**
* @implNote This class needs to maintain JDK 8 source compatibility.
@@ -57,16 +58,16 @@ public class ImageStream {
public ImageStream(int size, ByteOrder byteOrder) {
buffer = ByteBuffer.allocate(size);
- buffer.order(byteOrder);
+ buffer.order(Objects.requireNonNull(byteOrder));
}
public ImageStream(byte[] bytes, ByteOrder byteOrder) {
- buffer = ByteBuffer.wrap(bytes);
- buffer.order(byteOrder);
+ buffer = ByteBuffer.wrap(Objects.requireNonNull(bytes));
+ buffer.order(Objects.requireNonNull(byteOrder));
}
public ImageStream(ByteBuffer buffer) {
- this.buffer = buffer;
+ this.buffer = Objects.requireNonNull(buffer);
}
public ImageStream align(int alignment) {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
index 7a6ad7b75f4..acddf421d9d 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
@@ -27,6 +27,7 @@ package jdk.internal.jimage;
import java.io.UTFDataFormatException;
import java.nio.ByteBuffer;
+import java.util.Objects;
/**
* @implNote This class needs to maintain JDK 8 source compatibility.
@@ -40,7 +41,7 @@ public class ImageStringsReader implements ImageStrings {
private final BasicImageReader reader;
ImageStringsReader(BasicImageReader reader) {
- this.reader = reader;
+ this.reader = Objects.requireNonNull(reader);
}
@Override
@@ -54,7 +55,19 @@ public class ImageStringsReader implements ImageStrings {
}
private static int hashCode(byte[] bytes, int offset, int count, int seed) {
- for (int i = offset, limit = offset + count; i < limit; i++) {
+ Objects.requireNonNull(bytes);
+
+ if (offset < 0 || offset >= bytes.length) {
+ throw new IndexOutOfBoundsException("offset");
+ }
+
+ int limit = offset + count;
+
+ if (limit < 0 || limit > bytes.length) {
+ throw new IndexOutOfBoundsException("limit");
+ }
+
+ for (int i = offset; i < limit; i++) {
seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF);
}
From b9ff64a7cb9e11af7b440e1693a435142676a2e0 Mon Sep 17 00:00:00 2001
From: Mandy Chung
Date: Fri, 27 May 2016 08:52:22 -0700
Subject: [PATCH 42/48] 8157986: Runtime support for javac to determine
arguments to the runtime environment
Reviewed-by: alanb
---
jdk/make/mapfiles/libjava/mapfile-vers | 1 +
.../share/classes/jdk/internal/misc/VM.java | 17 +++++++++++++++++
.../java.base/share/classes/module-info.java | 1 +
jdk/src/java.base/share/native/libjava/VM.c | 5 +++++
4 files changed, 24 insertions(+)
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/jdk/internal/misc/VM.java b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
index af8d3253a22..2a839fdd593 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
@@ -475,6 +475,23 @@ public class VM {
*/
public static native long getNanoTimeAdjustment(long offsetInSeconds);
+ /**
+ * Returns the VM arguments for this runtime environment.
+ *
+ * @implNote
+ * The HotSpot JVM processes the input arguments from multiple sources
+ * in the following order:
+ * 1. JAVA_TOOL_OPTIONS environment variable
+ * 2. Options from JNI Invocation API
+ * 3. _JAVA_OPTIONS environment variable
+ *
+ * If VM options file is specified via -XX:VMOptionsFile, the vm options
+ * file is read and expanded in place of -XX:VMOptionFile option.
+ *
+ * Open issue with -XX:Flags (see JDK-8157979)
+ */
+ public static native String[] getRuntimeArguments();
+
static {
initialize();
}
diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java
index a1b13336fa2..d21c881ee30 100644
--- a/jdk/src/java.base/share/classes/module-info.java
+++ b/jdk/src/java.base/share/classes/module-info.java
@@ -165,6 +165,7 @@ module java.base {
java.sql,
java.xml,
jdk.charsets,
+ jdk.compiler,
jdk.jartool,
jdk.jlink,
jdk.net,
diff --git a/jdk/src/java.base/share/native/libjava/VM.c b/jdk/src/java.base/share/native/libjava/VM.c
index 53837efc518..9e99528c63d 100644
--- a/jdk/src/java.base/share/native/libjava/VM.c
+++ b/jdk/src/java.base/share/native/libjava/VM.c
@@ -55,3 +55,8 @@ Java_jdk_internal_misc_VM_initialize(JNIEnv *env, jclass cls) {
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));
}
+
+JNIEXPORT jobjectArray JNICALL
+Java_jdk_internal_misc_VM_getRuntimeArguments(JNIEnv *env, jclass cls) {
+ return JVM_GetVmArguments(env);
+}
From 74982b9113a7e60eba07d07aaa55d508396b8c43 Mon Sep 17 00:00:00 2001
From: Jim Laskey
Date: Fri, 27 May 2016 14:02:28 -0300
Subject: [PATCH 43/48] 8158061: Additional argument checks to BasicImageReader
calls
Reviewed-by: alanb, coffeys
---
.../classes/jdk/internal/jimage/ImageStringsReader.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
index acddf421d9d..382e6b1696b 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
@@ -57,14 +57,14 @@ public class ImageStringsReader implements ImageStrings {
private static int hashCode(byte[] bytes, int offset, int count, int seed) {
Objects.requireNonNull(bytes);
- if (offset < 0 || offset >= bytes.length) {
- throw new IndexOutOfBoundsException("offset");
+ if (offset < 0 || count < 0 || offset > bytes.length - count) {
+ throw new IndexOutOfBoundsException("offset=" + offset + ", count=" + count);
}
int limit = offset + count;
if (limit < 0 || limit > bytes.length) {
- throw new IndexOutOfBoundsException("limit");
+ throw new IndexOutOfBoundsException("limit=" + limit);
}
for (int i = offset; i < limit; i++) {
From 6d029e80343873833f39d0cdd3473751c7719945 Mon Sep 17 00:00:00 2001
From: Artem Smotrakov
Date: Fri, 27 May 2016 14:24:38 -0700
Subject: [PATCH 44/48] 8152207: Perform array bound checks while getting a
length of bytecode instructions
Reviewed-by: hseigel
---
jdk/src/java.base/share/native/libverify/check_code.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/jdk/src/java.base/share/native/libverify/check_code.c b/jdk/src/java.base/share/native/libverify/check_code.c
index e22101496d7..1f9408fb206 100644
--- a/jdk/src/java.base/share/native/libverify/check_code.c
+++ b/jdk/src/java.base/share/native/libverify/check_code.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -1744,9 +1744,14 @@ static int instruction_length(unsigned char *iptr, unsigned char *end)
}
default: {
+ if (instruction < 0 || instruction > JVM_OPC_MAX)
+ return -1;
+
/* A length of 0 indicates an error. */
- int length = opcode_length[instruction];
- return (length <= 0) ? -1 : length;
+ if (opcode_length[instruction] <= 0)
+ return -1;
+
+ return opcode_length[instruction];
}
}
}
From 9862c36936b3e667fc234e472057df4819ac759a Mon Sep 17 00:00:00 2001
From: Alexandre Iline
Date: Fri, 27 May 2016 14:26:58 -0700
Subject: [PATCH 45/48] 8157996: Unneeded import in
lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java
Reviewed-by: mchung, chegar
---
.../jdk/testlibrary/SimpleSSLContext.java | 35 ++++++++++---------
1 file changed, 18 insertions(+), 17 deletions(-)
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;
}
}
From 3d91ba0bc66e44d500671e3d5c68baab351346b7 Mon Sep 17 00:00:00 2001
From: Srikanth Adayapalam
Date: Sat, 28 May 2016 09:47:28 +0530
Subject: [PATCH 46/48] 8033812: javadoc for java.lang.annotation.ElementType
needs minor correction
Fix incorrect count of type contexts.
Reviewed-by: mcimadamore
---
.../share/classes/java/lang/annotation/ElementType.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java b/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java
index 4590f39edd1..c32ae6a0f15 100644
--- a/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java
+++ b/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java
@@ -46,7 +46,7 @@ package java.lang.annotation;
* {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
* field declaration.
*
- * 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.
*
From 8fe1e0ad30893459293900c0596e5919e0a6d3a3 Mon Sep 17 00:00:00 2001
From: Felix Yang
Date: Sun, 29 May 2016 18:22:21 -0700
Subject: [PATCH 47/48] 8078812: Test RMI with client and servers as modules
Reviewed-by: smarks
---
jdk/test/java/rmi/module/ModuleTest.java | 159 ++++++++++++++++++
.../module/src/mclient/clientpkg/Client.java | 47 ++++++
.../module/src/mserver/serverpkg/Hello.java | 32 ++++
.../module/src/mserver/serverpkg/Server.java | 37 ++++
.../module/src/mtest/testpkg/DummyApp.java | 55 ++++++
5 files changed, 330 insertions(+)
create mode 100644 jdk/test/java/rmi/module/ModuleTest.java
create mode 100644 jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java
create mode 100644 jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java
create mode 100644 jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java
create mode 100644 jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java
diff --git a/jdk/test/java/rmi/module/ModuleTest.java b/jdk/test/java/rmi/module/ModuleTest.java
new file mode 100644
index 00000000000..ad19a71b9f4
--- /dev/null
+++ b/jdk/test/java/rmi/module/ModuleTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.ProcessTools
+ * ModuleTest CompilerUtils JarUtils
+ * @run testng ModuleTest
+ * @summary Basic tests for using rmi in module world
+ */
+
+import static jdk.testlibrary.ProcessTools.executeTestJava;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.nio.file.Paths;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+public class ModuleTest {
+
+ static String fileJoin(String... names) {
+ return String.join(File.separator, names);
+ }
+
+ static String pathJoin(String... paths) {
+ return String.join(File.pathSeparator, paths);
+ }
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+ private static final String CLIENT_EXP = fileJoin("exploded", "mclient");
+ private static final String SERVER_EXP = fileJoin("exploded", "mserver");
+ private static final String MTEST_EXP = fileJoin("exploded", "mtest");
+ private static final String CLIENT_JAR = fileJoin("mods", "mclient.jar");
+ private static final String SERVER_JAR = fileJoin("mods", "mserver.jar");
+ private static final String MTEST_JAR = fileJoin("mods", "mtest.jar");
+
+ private static final String DUMMY_MAIN = "testpkg.DummyApp";
+
+ /**
+ * Compiles all sample classes
+ */
+ @BeforeTest
+ public void compileAll() throws Exception {
+ assertTrue(CompilerUtils.compile(
+ Paths.get(TEST_SRC, "src", "mserver"),
+ Paths.get(SERVER_EXP)));
+
+ JarUtils.createJarFile(
+ Paths.get(SERVER_JAR),
+ Paths.get(SERVER_EXP));
+
+ assertTrue(CompilerUtils.compile(
+ Paths.get(TEST_SRC, "src", "mclient"),
+ Paths.get(CLIENT_EXP),
+ "-cp", SERVER_JAR));
+
+ JarUtils.createJarFile(
+ Paths.get(CLIENT_JAR),
+ Paths.get(CLIENT_EXP));
+
+ assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "mtest"),
+ Paths.get(MTEST_EXP),
+ "-cp", pathJoin(CLIENT_JAR, SERVER_JAR)));
+
+ JarUtils.createJarFile(
+ Paths.get(MTEST_JAR),
+ Paths.get(MTEST_EXP));
+ }
+
+ /**
+ * Test the client, server and dummy application in different modules
+ * @throws Exception
+ */
+ @Test
+ public void testAllInModule() throws Exception {
+ assertEquals(executeTestJava("-mp", pathJoin(MTEST_JAR, CLIENT_JAR, SERVER_JAR),
+ "-addmods", "mclient,mserver",
+ "-m", "mtest/" + DUMMY_MAIN)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue(),
+ 0);
+ }
+
+ /**
+ * Test the client and server in unnamed modules,
+ * while the dummy application is in automatic module
+ * @throws Exception
+ */
+ @Test
+ public void testAppInModule() throws Exception {
+ assertEquals(executeTestJava("-mp", MTEST_JAR,
+ "-cp", pathJoin(CLIENT_JAR, SERVER_JAR),
+ "-m", "mtest/" + DUMMY_MAIN)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue(),
+ 0);
+ }
+
+ /**
+ * Test the client and server in automatic modules,
+ * while the dummy application is in unnamed module
+ * @throws Exception
+ */
+ @Test
+ public void testAppInUnnamedModule() throws Exception {
+ assertEquals(executeTestJava("-mp", pathJoin(CLIENT_JAR, SERVER_JAR),
+ "-addmods", "mclient,mserver",
+ "-cp", MTEST_JAR,
+ DUMMY_MAIN)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue(),
+ 0);
+ }
+
+ /**
+ * Test the server and test application in automatic modules,
+ * with client in unnamed module
+ * @throws Exception
+ */
+ @Test
+ public void testClientInUnamedModule() throws Exception {
+ assertEquals(executeTestJava("-mp", pathJoin(MTEST_JAR, SERVER_JAR),
+ "-addmods", "mserver",
+ "-cp", CLIENT_JAR,
+ "-m", "mtest/" + DUMMY_MAIN)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue(),
+ 0);
+ }
+}
+
diff --git a/jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java b/jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java
new file mode 100644
index 00000000000..0907748c1e9
--- /dev/null
+++ b/jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package clientpkg;
+
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
+import serverpkg.Hello;
+
+public class Client {
+ int port;
+ Hello stub;
+
+ public Client(Hello stub) {
+ this.stub = stub;
+ }
+
+ public String testStub() throws Exception {
+ try {
+ return stub.sayHello();
+ } catch (Exception e) {
+ System.err.println("Client exception: " + e.toString());
+ throw e;
+ }
+ }
+}
diff --git a/jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java b/jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java
new file mode 100644
index 00000000000..4525c09746c
--- /dev/null
+++ b/jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package serverpkg;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Hello extends Remote {
+
+ String sayHello() throws RemoteException;
+}
diff --git a/jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java b/jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java
new file mode 100644
index 00000000000..0ba07492b9e
--- /dev/null
+++ b/jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package serverpkg;
+
+public class Server implements Hello {
+
+ private final String hello = "Hello world!";
+
+ public Server() {
+ }
+
+ @Override
+ public String sayHello() {
+ return hello;
+ }
+}
diff --git a/jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java b/jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java
new file mode 100644
index 00000000000..6fc88d01fab
--- /dev/null
+++ b/jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testpkg;
+
+import java.rmi.server.UnicastRemoteObject;
+
+import clientpkg.Client;
+import serverpkg.Hello;
+import serverpkg.Server;
+
+public class DummyApp {
+
+ public static void main(String args[]) {
+ try {
+ Hello obj = new Server();
+ Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
+
+ Client client = new Client(stub);
+ String testStubReturn = client.testStub();
+ System.out.println("Stub is: " + testStubReturn);
+ if (!testStubReturn.equals(obj.sayHello())) {
+ throw new RuntimeException("Unexpected string from stub call, expected \""
+ + testStubReturn + "\", actual \"" + obj.sayHello() + "\"");
+ } else {
+ System.out.println("Test passed");
+ }
+
+ System.exit(0);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+}
From 212d6de09b6b8151b6e77dc04750a45c7b14a977 Mon Sep 17 00:00:00 2001
From: Masayoshi Okutsu
Date: Mon, 30 May 2016 14:58:59 +0900
Subject: [PATCH 48/48] 8039565: Remove test exclusion for
java/util/ResourceBundle/RestrictedBundleTest.java
Reviewed-by: peytoia
---
.../ResourceBundle/RestrictedBundleTest.html | 3 --
.../ResourceBundle/RestrictedBundleTest.java | 52 -------------------
2 files changed, 55 deletions(-)
delete mode 100644 jdk/test/java/util/ResourceBundle/RestrictedBundleTest.html
delete mode 100644 jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java
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");
- }
- }
-}