From 27a77176a658fd04a0ca87ca585ff4b09964c361 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Tue, 24 May 2016 10:14:41 -0700 Subject: [PATCH 01/48] 8153768: Miscellaneous changes imported from jsr166 CVS 2016-05 Reviewed-by: martin, psandoz, chegar, shade --- .../util/concurrent/ConcurrentHashMap.java | 9 +- .../concurrent/ConcurrentSkipListMap.java | 59 +++-- .../util/concurrent/CountedCompleter.java | 2 +- .../concurrent/ExecutorCompletionService.java | 29 +-- .../classes/java/util/concurrent/Phaser.java | 4 - .../concurrent/locks/Lock/FlakyMutex.java | 72 +++--- .../locks/LockSupport/ParkLoops.java | 36 +-- .../concurrent/tck/CompletableFutureTest.java | 17 +- .../tck/ExecutorCompletionService9Test.java | 137 +++++++++++ .../tck/ExecutorCompletionServiceTest.java | 213 ++++++++++-------- .../util/concurrent/tck/JSR166TestCase.java | 19 +- 11 files changed, 381 insertions(+), 216 deletions(-) create mode 100644 jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index d6ae6557978..d2392c62798 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -1242,7 +1242,8 @@ public class ConcurrentHashMap extends AbstractMap */ public KeySetView keySet() { KeySetView ks; - return (ks = keySet) != null ? ks : (keySet = new KeySetView(this, null)); + if ((ks = keySet) != null) return ks; + return keySet = new KeySetView(this, null); } /** @@ -1265,7 +1266,8 @@ public class ConcurrentHashMap extends AbstractMap */ public Collection values() { ValuesView vs; - return (vs = values) != null ? vs : (values = new ValuesView(this)); + if ((vs = values) != null) return vs; + return values = new ValuesView(this); } /** @@ -1287,7 +1289,8 @@ public class ConcurrentHashMap extends AbstractMap */ public Set> entrySet() { EntrySetView es; - return (es = entrySet) != null ? es : (entrySet = new EntrySetView(this)); + if ((es = entrySet) != null) return es; + return entrySet = new EntrySetView(this); } /** diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index 745de306bc1..e830f5bdda1 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -376,12 +376,12 @@ public class ConcurrentSkipListMap extends AbstractMap /** Lazily initialized key set */ private transient KeySet keySet; - /** Lazily initialized entry set */ - private transient EntrySet entrySet; /** Lazily initialized values collection */ private transient Values values; + /** Lazily initialized entry set */ + private transient EntrySet entrySet; /** Lazily initialized descending key set */ - private transient ConcurrentNavigableMap descendingMap; + private transient SubMap descendingMap; /** * Initializes or resets state. Needed by constructors, clone, @@ -1827,13 +1827,15 @@ public class ConcurrentSkipListMap extends AbstractMap * @return a navigable set view of the keys in this map */ public NavigableSet keySet() { - KeySet ks = keySet; - return (ks != null) ? ks : (keySet = new KeySet<>(this)); + KeySet ks; + if ((ks = keySet) != null) return ks; + return keySet = new KeySet<>(this); } public NavigableSet navigableKeySet() { - KeySet ks = keySet; - return (ks != null) ? ks : (keySet = new KeySet<>(this)); + KeySet ks; + if ((ks = keySet) != null) return ks; + return keySet = new KeySet<>(this); } /** @@ -1856,8 +1858,9 @@ public class ConcurrentSkipListMap extends AbstractMap * weakly consistent. */ public Collection values() { - Values vs = values; - return (vs != null) ? vs : (values = new Values<>(this)); + Values vs; + if ((vs = values) != null) return vs; + return values = new Values<>(this); } /** @@ -1888,14 +1891,16 @@ public class ConcurrentSkipListMap extends AbstractMap * sorted in ascending key order */ public Set> entrySet() { - EntrySet es = entrySet; - return (es != null) ? es : (entrySet = new EntrySet(this)); + EntrySet es; + if ((es = entrySet) != null) return es; + return entrySet = new EntrySet(this); } public ConcurrentNavigableMap descendingMap() { - ConcurrentNavigableMap dm = descendingMap; - return (dm != null) ? dm : (descendingMap = new SubMap - (this, null, false, null, false, true)); + ConcurrentNavigableMap dm; + if ((dm = descendingMap) != null) return dm; + return descendingMap = + new SubMap(this, null, false, null, false, true); } public NavigableSet descendingKeySet() { @@ -2564,7 +2569,7 @@ public class ConcurrentSkipListMap extends AbstractMap * @serial include */ static final class SubMap extends AbstractMap - implements ConcurrentNavigableMap, Cloneable, Serializable { + implements ConcurrentNavigableMap, Serializable { private static final long serialVersionUID = -7647078645895051609L; /** Underlying map */ @@ -2582,8 +2587,8 @@ public class ConcurrentSkipListMap extends AbstractMap // Lazily initialized view holders private transient KeySet keySetView; - private transient Set> entrySetView; - private transient Collection valuesView; + private transient Values valuesView; + private transient EntrySet entrySetView; /** * Creates a new submap, initializing all fields. @@ -3049,23 +3054,27 @@ public class ConcurrentSkipListMap extends AbstractMap /* ---------------- Submap Views -------------- */ public NavigableSet keySet() { - KeySet ks = keySetView; - return (ks != null) ? ks : (keySetView = new KeySet<>(this)); + KeySet ks; + if ((ks = keySetView) != null) return ks; + return keySetView = new KeySet<>(this); } public NavigableSet navigableKeySet() { - KeySet ks = keySetView; - return (ks != null) ? ks : (keySetView = new KeySet<>(this)); + KeySet ks; + if ((ks = keySetView) != null) return ks; + return keySetView = new KeySet<>(this); } public Collection values() { - Collection vs = valuesView; - return (vs != null) ? vs : (valuesView = new Values<>(this)); + Values vs; + if ((vs = valuesView) != null) return vs; + return valuesView = new Values<>(this); } public Set> entrySet() { - Set> es = entrySetView; - return (es != null) ? es : (entrySetView = new EntrySet(this)); + EntrySet es; + if ((es = entrySetView) != null) return es; + return entrySetView = new EntrySet(this); } public NavigableSet descendingKeySet() { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java index e863632d85a..1e56b09dfc1 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java @@ -596,7 +596,7 @@ public abstract class CountedCompleter extends ForkJoinTask { * not, be invoked for each completer in a computation. */ public final void propagateCompletion() { - CountedCompleter a = this, s = a; + CountedCompleter a = this, s; for (int c;;) { if ((c = a.pending) == 0) { if ((a = (s = a).completer) == null) { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java index a0938443529..9591d9b1942 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java @@ -56,13 +56,11 @@ package java.util.concurrent; * void solve(Executor e, * Collection> solvers) * throws InterruptedException, ExecutionException { - * CompletionService ecs - * = new ExecutorCompletionService(e); - * for (Callable s : solvers) - * ecs.submit(s); - * int n = solvers.size(); - * for (int i = 0; i < n; ++i) { - * Result r = ecs.take().get(); + * CompletionService cs + * = new ExecutorCompletionService<>(e); + * solvers.forEach(cs::submit); + * for (int i = solvers.size(); i > 0; i--) { + * Result r = cs.take().get(); * if (r != null) * use(r); * } @@ -76,27 +74,24 @@ package java.util.concurrent; * void solve(Executor e, * Collection> solvers) * throws InterruptedException { - * CompletionService ecs - * = new ExecutorCompletionService(e); + * CompletionService cs + * = new ExecutorCompletionService<>(e); * int n = solvers.size(); * List> futures = new ArrayList<>(n); * Result result = null; * try { - * for (Callable s : solvers) - * futures.add(ecs.submit(s)); - * for (int i = 0; i < n; ++i) { + * solvers.forEach((solver) -> futures.add(cs.submit(solver))); + * for (int i = n; i > 0; i--) { * try { - * Result r = ecs.take().get(); + * Result r = cs.take().get(); * if (r != null) { * result = r; * break; * } * } catch (ExecutionException ignore) {} * } - * } - * finally { - * for (Future f : futures) - * f.cancel(true); + * } finally { + * futures.forEach((future) -> future.cancel(true)); * } * * if (result != null) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java index e8d91e557c0..3fd30e7d3a8 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java @@ -348,10 +348,6 @@ public class Phaser { private final AtomicReference evenQ; private final AtomicReference oddQ; - private AtomicReference queueFor(int phase) { - return ((phase & 1) == 0) ? evenQ : oddQ; - } - /** * Returns message string for bounds exceptions on arrival. */ diff --git a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java index 82f9ead09f5..913aea78c46 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java +++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java @@ -25,13 +25,10 @@ * @test * @bug 6503247 6574123 * @summary Test resilience to tryAcquire methods that throw - * @library /lib/testlibrary/ * @author Martin Buchholz */ -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -39,7 +36,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; -import jdk.testlibrary.Utils; /** * This uses a variant of the standard Mutex demo, except with a @@ -48,22 +44,10 @@ import jdk.testlibrary.Utils; */ @SuppressWarnings("serial") public class FlakyMutex implements Lock { - static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static class MyError extends Error {} static class MyException extends Exception {} static class MyRuntimeException extends RuntimeException {} - static final Random rnd = new Random(); - - static void maybeThrow() { - switch (rnd.nextInt(10)) { - case 0: throw new MyError(); - case 1: throw new MyRuntimeException(); - case 2: FlakyMutex.uncheckedThrow(new MyException()); - default: /* Do nothing */ break; - } - } - static void checkThrowable(Throwable t) { check((t instanceof MyError) || (t instanceof MyException) || @@ -72,31 +56,35 @@ public class FlakyMutex implements Lock { static void realMain(String[] args) throws Throwable { final int nThreads = 3; - final CyclicBarrier barrier = new CyclicBarrier(nThreads + 1); - final FlakyMutex m = new FlakyMutex(); + final int iterations = 10_000; + final CyclicBarrier startingGate = new CyclicBarrier(nThreads); + final FlakyMutex mutex = new FlakyMutex(); final ExecutorService es = Executors.newFixedThreadPool(nThreads); - for (int i = 0; i < nThreads; i++) { - es.submit(new Runnable() { public void run() { - try { - barrier.await(); - for (int i = 0; i < 10000; i++) { - for (;;) { - try { m.lock(); break; } - catch (Throwable t) { checkThrowable(t); } - } - - try { check(! m.tryLock()); } + final Runnable task = () -> { + try { + startingGate.await(); + for (int i = 0; i < iterations; i++) { + for (;;) { + try { mutex.lock(); break; } catch (Throwable t) { checkThrowable(t); } - - try { check(! m.tryLock(1, TimeUnit.MICROSECONDS)); } - catch (Throwable t) { checkThrowable(t); } - - m.unlock(); } - } catch (Throwable t) { unexpected(t); }}});} - barrier.await(); + + try { check(! mutex.tryLock()); } + catch (Throwable t) { checkThrowable(t); } + + try { check(! mutex.tryLock(1, TimeUnit.MICROSECONDS)); } + catch (Throwable t) { checkThrowable(t); } + + mutex.unlock(); + } + } catch (Throwable t) { unexpected(t); } + }; + + for (int i = 0; i < nThreads; i++) + es.submit(task); es.shutdown(); - check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + // Let test harness handle timeout + check(es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)); } private static class FlakySync extends AbstractQueuedLongSynchronizer { @@ -116,8 +104,12 @@ public class FlakyMutex implements Lock { do {} while (hasQueuedPredecessors() != hasQueuedThreads()); } - maybeThrow(); - return compareAndSetState(0, 1); + switch (ThreadLocalRandom.current().nextInt(10)) { + case 0: throw new MyError(); + case 1: throw new MyRuntimeException(); + case 2: FlakyMutex.uncheckedThrow(new MyException()); + default: return compareAndSetState(0, 1); + } } public boolean tryRelease(long releases) { diff --git a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java index 5ad9d068a2a..2d82c455574 100644 --- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java +++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java @@ -35,16 +35,10 @@ * @test * @bug 8074773 * @summary Stress test looks for lost unparks - * @library /lib/testlibrary/ - * @modules java.management - * @run main/timeout=1200 ParkLoops */ -import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; import java.util.SplittableRandom; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -52,11 +46,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.LockSupport; -import jdk.testlibrary.Utils; public final class ParkLoops { - static final long TEST_TIMEOUT_SECONDS = Utils.adjustTimeout(1000); - static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final int THREADS = 4; static final int ITERS = 30_000; @@ -126,28 +117,13 @@ public final class ParkLoops { final AtomicReferenceArray threads = new AtomicReferenceArray<>(THREADS); final CountDownLatch done = new CountDownLatch(THREADS); - final Runnable parker = new Parker(threads, done, rnd.split()); - final Runnable unparker = new Unparker(threads, done, rnd.split()); for (int i = 0; i < THREADS; i++) { - pool.submit(parker); - pool.submit(unparker); - } - try { - if (!done.await(TEST_TIMEOUT_SECONDS, SECONDS)) { - dumpAllStacks(); - throw new AssertionError("lost unpark"); - } - } finally { - pool.shutdown(); - pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); - } - } - - static void dumpAllStacks() { - ThreadInfo[] threadInfos = - ManagementFactory.getThreadMXBean().dumpAllThreads(true, true); - for (ThreadInfo threadInfo : threadInfos) { - System.err.print(threadInfo); + pool.submit(new Parker(threads, done, rnd.split())); + pool.submit(new Unparker(threads, done, rnd.split())); } + // Let test harness handle timeout + done.await(); + pool.shutdown(); + pool.awaitTermination(Long.MAX_VALUE, SECONDS); } } diff --git a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java index 340e7f972a4..4149559adad 100644 --- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java +++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java @@ -3322,7 +3322,7 @@ public class CompletableFutureTest extends JSR166TestCase { () -> f.obtrudeException(null), () -> CompletableFuture.delayedExecutor(1L, SECONDS, null), - () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()), + () -> CompletableFuture.delayedExecutor(1L, null, exec), () -> CompletableFuture.delayedExecutor(1L, null), () -> f.orTimeout(1L, null), @@ -3552,7 +3552,7 @@ public class CompletableFutureTest extends JSR166TestCase { long timeoutMillis = timeoutMillis(); CompletableFuture f = new CompletableFuture<>(); long startTime = System.nanoTime(); - f.orTimeout(timeoutMillis, MILLISECONDS); + assertSame(f, f.orTimeout(timeoutMillis, MILLISECONDS)); checkCompletedWithTimeoutException(f); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); } @@ -3567,8 +3567,8 @@ public class CompletableFutureTest extends JSR166TestCase { CompletableFuture g = new CompletableFuture<>(); long startTime = System.nanoTime(); f.complete(v1); - f.orTimeout(LONG_DELAY_MS, MILLISECONDS); - g.orTimeout(LONG_DELAY_MS, MILLISECONDS); + assertSame(f, f.orTimeout(LONG_DELAY_MS, MILLISECONDS)); + assertSame(g, g.orTimeout(LONG_DELAY_MS, MILLISECONDS)); g.complete(v1); checkCompletedNormally(f, v1); checkCompletedNormally(g, v1); @@ -3583,11 +3583,14 @@ public class CompletableFutureTest extends JSR166TestCase { () -> testCompleteOnTimeout_timesOut(null)); } + /** + * completeOnTimeout completes with given value if not complete + */ public void testCompleteOnTimeout_timesOut(Integer v) { long timeoutMillis = timeoutMillis(); CompletableFuture f = new CompletableFuture<>(); long startTime = System.nanoTime(); - f.completeOnTimeout(v, timeoutMillis, MILLISECONDS); + assertSame(f, f.completeOnTimeout(v, timeoutMillis, MILLISECONDS)); assertSame(v, f.join()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); f.complete(99); // should have no effect @@ -3604,8 +3607,8 @@ public class CompletableFutureTest extends JSR166TestCase { CompletableFuture g = new CompletableFuture<>(); long startTime = System.nanoTime(); f.complete(v1); - f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); - g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); + assertSame(f, f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS)); + assertSame(g, g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS)); g.complete(v1); checkCompletedNormally(f, v1); checkCompletedNormally(g, v1); diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java new file mode 100644 index 00000000000..8169d5fa5f6 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java @@ -0,0 +1,137 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ExecutorCompletionService9Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ExecutorCompletionService9Test.class); + } + + void solveAll(Executor e, + Collection> solvers) + throws InterruptedException, ExecutionException { + CompletionService cs + = new ExecutorCompletionService<>(e); + solvers.forEach(cs::submit); + for (int i = solvers.size(); i > 0; i--) { + Integer r = cs.take().get(); + if (r != null) + use(r); + } + } + + void solveAny(Executor e, + Collection> solvers) + throws InterruptedException { + CompletionService cs + = new ExecutorCompletionService<>(e); + int n = solvers.size(); + List> futures = new ArrayList<>(n); + Integer result = null; + try { + solvers.forEach((solver) -> futures.add(cs.submit(solver))); + for (int i = n; i > 0; i--) { + try { + Integer r = cs.take().get(); + if (r != null) { + result = r; + break; + } + } catch (ExecutionException ignore) {} + } + } finally { + futures.forEach((future) -> future.cancel(true)); + } + + if (result != null) + use(result); + } + + HashSet results; + + void use(Integer x) { + if (results == null) results = new HashSet(); + results.add(x); + } + + /** + * The first "solvers" sample code in the class javadoc works. + */ + public void testSolveAll() + throws InterruptedException, ExecutionException { + Set> solvers = Set.of( + () -> null, + () -> 1, + () -> 2, + () -> 3, + () -> null); + solveAll(cachedThreadPool, solvers); + assertEquals(Set.of(1, 2, 3), results); + } + + /** + * The second "solvers" sample code in the class javadoc works. + */ + public void testSolveAny() + throws InterruptedException { + Set> solvers = Set.of( + () -> { throw new ArithmeticException(); }, + () -> null, + () -> 1, + () -> 2); + solveAny(cachedThreadPool, solvers); + assertEquals(1, results.size()); + Integer elt = results.iterator().next(); + assertTrue(elt.equals(1) || elt.equals(2)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java index 29db17a7a0d..6e4d00f3d0f 100644 --- a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java @@ -37,8 +37,11 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; @@ -59,7 +62,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { } /** - * Creating a new ECS with null Executor throw NPE + * new ExecutorCompletionService(null) throws NullPointerException */ public void testConstructorNPE() { try { @@ -69,111 +72,147 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { } /** - * Creating a new ECS with null queue throw NPE + * new ExecutorCompletionService(e, null) throws NullPointerException */ public void testConstructorNPE2() { try { - ExecutorService e = Executors.newCachedThreadPool(); - new ExecutorCompletionService(e, null); + new ExecutorCompletionService(cachedThreadPool, null); shouldThrow(); } catch (NullPointerException success) {} } /** - * Submitting a null callable throws NPE + * ecs.submit(null) throws NullPointerException */ - public void testSubmitNPE() { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = null; - try { - ecs.submit(c); - shouldThrow(); - } catch (NullPointerException success) {} - } + public void testSubmitNullCallable() { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + try { + cs.submit((Callable) null); + shouldThrow(); + } catch (NullPointerException success) {} } /** - * Submitting a null runnable throws NPE + * ecs.submit(null, val) throws NullPointerException */ - public void testSubmitNPE2() { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Runnable r = null; - try { - ecs.submit(r, Boolean.TRUE); - shouldThrow(); - } catch (NullPointerException success) {} - } + public void testSubmitNullRunnable() { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + try { + cs.submit((Runnable) null, Boolean.TRUE); + shouldThrow(); + } catch (NullPointerException success) {} } /** * A taken submitted task is completed */ - public void testTake() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = new StringTask(); - ecs.submit(c); - Future f = ecs.take(); - assertTrue(f.isDone()); - } + public void testTake() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + cs.submit(new StringTask()); + Future f = cs.take(); + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); } /** * Take returns the same future object returned by submit */ public void testTake2() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = new StringTask(); - Future f1 = ecs.submit(c); - Future f2 = ecs.take(); - assertSame(f1, f2); - } + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + Future f1 = cs.submit(new StringTask()); + Future f2 = cs.take(); + assertSame(f1, f2); } /** - * If poll returns non-null, the returned task is completed + * poll returns non-null when the returned task is completed */ - public void testPoll1() throws Exception { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); - Callable c = new StringTask(); - ecs.submit(c); + public void testPoll1() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + assertNull(cs.poll()); + cs.submit(new StringTask()); - long startTime = System.nanoTime(); - Future f; - while ((f = ecs.poll()) == null) { - if (millisElapsedSince(startTime) > LONG_DELAY_MS) - fail("timed out"); - Thread.yield(); + long startTime = System.nanoTime(); + Future f; + while ((f = cs.poll()) == null) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); + } + + /** + * timed poll returns non-null when the returned task is completed + */ + public void testPoll2() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + assertNull(cs.poll()); + cs.submit(new StringTask()); + + long startTime = System.nanoTime(); + Future f; + while ((f = cs.poll(SHORT_DELAY_MS, MILLISECONDS)) == null) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); + } + + /** + * poll returns null before the returned task is completed + */ + public void testPollReturnsNull() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + final CountDownLatch proceed = new CountDownLatch(1); + cs.submit(new Callable() { public String call() throws Exception { + proceed.await(); + return TEST_STRING; + }}); + assertNull(cs.poll()); + assertNull(cs.poll(0L, MILLISECONDS)); + assertNull(cs.poll(Long.MIN_VALUE, MILLISECONDS)); + long startTime = System.nanoTime(); + assertNull(cs.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + proceed.countDown(); + assertSame(TEST_STRING, cs.take().get()); + } + + /** + * successful and failed tasks are both returned + */ + public void testTaskAssortment() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + ArithmeticException ex = new ArithmeticException(); + for (int i = 0; i < 2; i++) { + cs.submit(new StringTask()); + cs.submit(callableThrowing(ex)); + cs.submit(runnableThrowing(ex), null); + } + int normalCompletions = 0; + int exceptionalCompletions = 0; + for (int i = 0; i < 3 * 2; i++) { + try { + if (cs.take().get() == TEST_STRING) + normalCompletions++; + } + catch (ExecutionException expected) { + assertTrue(expected.getCause() instanceof ArithmeticException); + exceptionalCompletions++; } - assertTrue(f.isDone()); - assertSame(TEST_STRING, f.get()); - } - } - - /** - * If timed poll returns non-null, the returned task is completed - */ - public void testPoll2() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); - Callable c = new StringTask(); - ecs.submit(c); - Future f = ecs.poll(SHORT_DELAY_MS, MILLISECONDS); - if (f != null) - assertTrue(f.isDone()); } + assertEquals(2 * 1, normalCompletions); + assertEquals(2 * 2, exceptionalCompletions); + assertNull(cs.poll()); } /** @@ -184,7 +223,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { final AtomicBoolean done = new AtomicBoolean(false); class MyCallableFuture extends FutureTask { MyCallableFuture(Callable c) { super(c); } - protected void done() { done.set(true); } + @Override protected void done() { done.set(true); } } final ExecutorService e = new ThreadPoolExecutor(1, 1, @@ -193,15 +232,14 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { protected RunnableFuture newTaskFor(Callable c) { return new MyCallableFuture(c); }}; - ExecutorCompletionService ecs = - new ExecutorCompletionService(e); + CompletionService cs = new ExecutorCompletionService<>(e); try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); + assertNull(cs.poll()); Callable c = new StringTask(); - Future f1 = ecs.submit(c); + Future f1 = cs.submit(c); assertTrue("submit must return MyCallableFuture", f1 instanceof MyCallableFuture); - Future f2 = ecs.take(); + Future f2 = cs.take(); assertSame("submit and take must return same objects", f1, f2); assertTrue("completed task must have set done", done.get()); } @@ -215,7 +253,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { final AtomicBoolean done = new AtomicBoolean(false); class MyRunnableFuture extends FutureTask { MyRunnableFuture(Runnable t, V r) { super(t, r); } - protected void done() { done.set(true); } + @Override protected void done() { done.set(true); } } final ExecutorService e = new ThreadPoolExecutor(1, 1, @@ -224,15 +262,14 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { protected RunnableFuture newTaskFor(Runnable t, T r) { return new MyRunnableFuture(t, r); }}; - final ExecutorCompletionService ecs = - new ExecutorCompletionService(e); + CompletionService cs = new ExecutorCompletionService<>(e); try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); + assertNull(cs.poll()); Runnable r = new NoOpRunnable(); - Future f1 = ecs.submit(r, null); + Future f1 = cs.submit(r, null); assertTrue("submit must return MyRunnableFuture", f1 instanceof MyRunnableFuture); - Future f2 = ecs.take(); + Future f2 = cs.take(); assertSame("submit and take must return same objects", f1, f2); assertTrue("completed task must have set done", done.get()); } diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index b189ce6b128..14907badc6f 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -39,6 +39,7 @@ * @modules java.management * @build * * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase + * @run junit/othervm/timeout=1000 -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 -Djsr166.testImplementationDetails=true JSR166TestCase */ import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -85,6 +86,7 @@ import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveTask; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.Semaphore; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; @@ -546,7 +548,7 @@ public class JSR166TestCase extends TestCase { // Java9+ test classes if (atLeastJava9()) { String[] java9TestClassNames = { - // Currently empty, but expecting varhandle tests + "ExecutorCompletionService9Test", }; addNamedTestClasses(suite, java9TestClassNames); } @@ -1860,4 +1862,19 @@ public class JSR166TestCase extends TestCase { } catch (NoSuchElementException success) {} assertFalse(it.hasNext()); } + + public Callable callableThrowing(final Exception ex) { + return new Callable() { public T call() throws Exception { throw ex; }}; + } + + public Runnable runnableThrowing(final RuntimeException ex) { + return new Runnable() { public void run() { throw ex; }}; + } + + /** A reusable thread pool to be shared by tests. */ + static final ExecutorService cachedThreadPool = + new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 1000L, MILLISECONDS, + new SynchronousQueue()); + } From af7a591d3931a2491e3b9327513bbd89c2340b4c Mon Sep 17 00:00:00 2001 From: Vyom Tewari Date: Tue, 24 May 2016 20:15:18 +0100 Subject: [PATCH 02/48] 8016521: InetAddress should not always re-order addresses returned from name service Reviewed-by: chegar --- .../classes/java/net/Inet6AddressImpl.java | 37 +++-- .../share/classes/java/net/InetAddress.java | 26 +++- .../java/net/doc-files/net-properties.html | 15 +- .../share/native/libnet/InetAddress.c | 4 +- .../unix/native/libnet/Inet6AddressImpl.c | 23 ++- .../windows/native/libnet/Inet6AddressImpl.c | 20 ++- .../Inet6Address/PreferIPv6AddressesTest.java | 132 ++++++++++++++++++ 7 files changed, 216 insertions(+), 41 deletions(-) create mode 100644 jdk/test/java/net/Inet6Address/PreferIPv6AddressesTest.java diff --git a/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java b/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java index 6a3dcc76c7d..07f95ac56fb 100644 --- a/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java +++ b/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,10 @@ * questions. */ package java.net; + import java.io.IOException; +import static java.net.InetAddress.PREFER_IPV6_VALUE; +import static java.net.InetAddress.PREFER_SYSTEM_VALUE; /* * Package private implementation of InetAddressImpl for dual @@ -35,15 +38,23 @@ import java.io.IOException; * * @since 1.4 */ - class Inet6AddressImpl implements InetAddressImpl { - public native String getLocalHostName() throws UnknownHostException; - public native InetAddress[] - lookupAllHostAddr(String hostname) throws UnknownHostException; - public native String getHostByAddr(byte[] addr) throws UnknownHostException; - private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException; - public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException { + public native String getLocalHostName() throws UnknownHostException; + + public native InetAddress[] lookupAllHostAddr(String hostname) + throws UnknownHostException; + + public native String getHostByAddr(byte[] addr) throws UnknownHostException; + + private native boolean isReachable0(byte[] addr, int scope, int timeout, + byte[] inf, int ttl, int if_scope) + throws IOException; + + public boolean isReachable(InetAddress addr, int timeout, + NetworkInterface netif, int ttl) + throws IOException + { byte[] ifaddr = null; int scope = -1; int netif_scope = -1; @@ -79,7 +90,8 @@ class Inet6AddressImpl implements InetAddressImpl { public synchronized InetAddress anyLocalAddress() { if (anyLocalAddress == null) { - if (InetAddress.preferIPv6Address) { + if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || + InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) { anyLocalAddress = new Inet6Address(); anyLocalAddress.holder().hostName = "::"; } else { @@ -91,7 +103,8 @@ class Inet6AddressImpl implements InetAddressImpl { public synchronized InetAddress loopbackAddress() { if (loopbackAddress == null) { - if (InetAddress.preferIPv6Address) { + if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || + InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) { byte[] loopback = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; @@ -103,6 +116,6 @@ class Inet6AddressImpl implements InetAddressImpl { return loopbackAddress; } - private InetAddress anyLocalAddress; - private InetAddress loopbackAddress; + private InetAddress anyLocalAddress; + private InetAddress loopbackAddress; } diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index e45b590200a..33e70ea1b43 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -26,8 +26,6 @@ package java.net; import java.util.NavigableSet; -import java.util.Iterator; -import java.util.List; import java.util.ArrayList; import java.util.Objects; import java.util.Scanner; @@ -41,6 +39,7 @@ import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream.PutField; +import java.lang.annotation.Native; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentSkipListSet; @@ -193,6 +192,11 @@ import sun.net.util.IPAddressUtil; */ public class InetAddress implements java.io.Serializable { + + @Native static final int PREFER_IPV4_VALUE = 0; + @Native static final int PREFER_IPV6_VALUE = 1; + @Native static final int PREFER_SYSTEM_VALUE = 2; + /** * Specify the address family: Internet Protocol, Version 4 * @since 1.4 @@ -206,8 +210,7 @@ class InetAddress implements java.io.Serializable { static final int IPv6 = 2; /* Specify address family preference */ - static transient boolean preferIPv6Address = false; - + static transient final int preferIPv6Address; static class InetAddressHolder { /** @@ -293,8 +296,19 @@ class InetAddress implements java.io.Serializable { * Load net library into runtime, and perform initializations. */ static { - preferIPv6Address = java.security.AccessController.doPrivileged( - new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue(); + String str = java.security.AccessController.doPrivileged( + new GetPropertyAction("java.net.preferIPv6Addresses")); + if (str == null) { + preferIPv6Address = PREFER_IPV4_VALUE; + } else if (str.equalsIgnoreCase("true")) { + preferIPv6Address = PREFER_IPV6_VALUE; + } else if (str.equalsIgnoreCase("false")) { + preferIPv6Address = PREFER_IPV4_VALUE; + } else if (str.equalsIgnoreCase("system")) { + preferIPv6Address = PREFER_SYSTEM_VALUE; + } else { + preferIPv6Address = PREFER_IPV4_VALUE; + } AccessController.doPrivileged( new java.security.PrivilegedAction<>() { public Void run() { diff --git a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html index d8e8949fc32..76c82b5b81e 100644 --- a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -1,5 +1,5 @@ "ae" + // "z" --> "aeef" + // + String[][] test2 = { + { "< a & ae = a1 & aeef = z < b < e < f", "" }, + { "a", "1" }, + { "b", "1" }, + { "e", "2" }, + { "f", "4" }, + }; + verifyExpansion(test2); + } + + /* + * @bug 4157299 + */ + public void TestClearBuffers() throws ParseException { + RuleBasedCollator c = new RuleBasedCollator("< a < b < c & ab = d"); + CollationElementIterator i = c.getCollationElementIterator("abcd"); + int e0 = i.next(); // save the first collation element + i.setOffset(3); // go to the expanding character + i.next(); // but only use up half of it + i.setOffset(0); // go back to the beginning + int e = i.next(); // and get this one again + if (e != e0) { + errln("got " + Integer.toString(e, 16) + ", expected " + + Integer.toString(e0, 16)); + } + } + + //------------------------------------------------------------------------ + // Internal utilities + // + + private void backAndForth(CollationElementIterator iter) { + // Run through the iterator forwards and stick it into an array + int [] orders = getOrders(iter); + + // Now go through it backwards and make sure we get the same values + int index = orders.length; + int o; + + while ((o = iter.previous()) != CollationElementIterator.NULLORDER) { + if (o != orders[--index]) { + errln("Mismatch at index " + index + ": " + + orders[index] + " vs " + o); + break; + } + } + if (index != 0) { + errln("Didn't get back to beginning - index is " + index); + + iter.reset(); + err("next: "); + while ((o = iter.next()) != NULLORDER) { + err( Integer.toHexString(o) + " "); + } + errln(""); + + err("prev: "); + while ((o = iter.previous()) != NULLORDER) { + err( Integer.toHexString(o) + " "); + } + errln(""); + } + } + + /** + * Verify that getMaxExpansion works on a given set of collation rules + * + * The first row of the "tests" array contains the collation rules + * at index 0, and the string at index 1 is ignored. + * + * Subsequent rows of the array contain a character and a number, both + * represented as strings. The character's collation order is determined, + * and getMaxExpansion is called for that character. If its value is + * not equal to the specified number, an error results. + */ + private void verifyExpansion(String[][] tests) throws ParseException + { + RuleBasedCollator coll = new RuleBasedCollator(tests[0][0]); + CollationElementIterator iter = coll.getCollationElementIterator(""); + + for (int i = 1; i < tests.length; i++) { + // First get the collation key that the test string expands to + iter.setText(tests[i][0]); + + int order = iter.next(); + + if (order == NULLORDER || iter.next() != NULLORDER) { + iter.reset(); + errln("verifyExpansion: '" + tests[i][0] + + "' has multiple orders:" + orderString(iter)); + } + + int expansion = iter.getMaxExpansion(order); + int expect = new Integer(tests[i][1]).intValue(); + + if (expansion != expect) { + errln("expansion for '" + tests[i][0] + "' is wrong: " + + "expected " + expect + ", got " + expansion); + } + } + } + + /** + * Return an integer array containing all of the collation orders + * returned by calls to next on the specified iterator + */ + private int[] getOrders(CollationElementIterator iter) + { + int maxSize = 100; + int size = 0; + int[] orders = new int[maxSize]; + + int order; + while ((order = iter.next()) != NULLORDER) { + if (size == maxSize) { + maxSize *= 2; + int[] temp = new int[maxSize]; + System.arraycopy(orders, 0, temp, 0, size); + orders = temp; + } + orders[size++] = order; + } + + if (orders.length > size) { + int[] temp = new int[size]; + System.arraycopy(orders, 0, temp, 0, size); + orders = temp; + } + return orders; + }; + + /** + * Return a string containing all of the collation orders + * returned by calls to next on the specified iterator + */ + private String orderString(CollationElementIterator iter) { + StringBuffer buf = new StringBuffer(); + + int order; + while ((order = iter.next()) != NULLORDER) { + buf.append( Integer.toHexString(order) + " "); + } + return buf.toString(); + } + + static final private int NULLORDER = CollationElementIterator.NULLORDER; + RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US); + + String test1 = "What subset of all possible test cases?"; + String test2 = "has the highest probability of detecting"; +} diff --git a/jdk/test/java/text/Collator/JapaneseTest.java b/jdk/test/java/text/Collator/JapaneseTest.java new file mode 100644 index 00000000000..2bd5f6d0179 --- /dev/null +++ b/jdk/test/java/text/Collator/JapaneseTest.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 1.1 02/09/11 + * @bug 4176141 4655819 + * @summary Regression tests for Japanese Collation + */ + +import java.text.*; +import java.util.*; + +public class JapaneseTest { + + // NOTE: + // Golden data in this test case is locale data dependent and + // may need to be changed if the Japanese locale collation rules + // are changed. + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results1 = { + { -1, -1, -1}, + { -1, -1, -1}, + { -1, -1, -1}, + }; + static final String[][] compData1 = { + /* + * Data to verify '<' relationship in LocaleElements_ja.java + */ + {"\u3084", "\u30E6", + "Hiragana \"YA\"(0x3084) <---> Katakana \"YU\"(0x30E6)"}, + {"\u30E6", "\u3088", + "Katakana \"YU\"(0x30E6) <---> Hiragana \"YO\"(0x3088)"}, + {"\u00B1", "\u2260", + "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"}, + {"\u3011", "\u2260", + "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"}, + {"\u2260", "\u2103", + "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"}, + {"\u2260", "\u2606", + "Not Equal To(0x2260) <---> White Star(0x2606)"}, + {"\u30FD", "\u309E", + "Katakana Iteration Mark(0x30FD) <---> Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u3059\u309D", "\u3059\u309E", + "Hiragana \"SU\"(0x3059)Hiragana Iteration Mark(0x309D) <---> Hiragana \"SU\"(0x3059)Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u821E", "\u798F", + "CJK Unified Ideograph(0x821E) <---> CJK Unified Ideograph(0x798F)"}, + + /* + * Data to verify normalization + */ + {"\u2260", "\u225F", + "Not Equal To(0x2260) <---> Questioned Equal To(0x225F)"}, + {"\u226E", "\u2260", + "Not Less-than(0x226E) <---> Not Equal To(0x2260)"}, + {"\u226E", "\u226D", + "Not Less-than(0x226E) <---> Not Equivalent To(0x226D)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results2 = { + { 0, 0, 0}, + { -1, -1, -1}, + { -1, -1, -1}, + }; + static final String[][] compData2 = { + /* + * Data to verify ';' relationship in LocaleElements_ja.java + */ + {"\u3099", "\u309A", + "Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A)"}, + {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3068\u3099\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUTO\"(0x3053 0x3046 0x3068)Combining Katakana-Hiragana Voiced Sound Mark(0X3099)\"U\"(0x3046)"}, + {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3069\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUDOU\"(0x3053 0x3046 0x3069 0x3046)"}, + {"\u3053\u3046\u3069\u3046", "\u3054\u3046\u3068\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3069 0x3046) <---> Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046)"}, + {"\u3054\u3046\u3068\u3046", "\u3054\u3046\u3069\u3046", + "Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046) <---> Hiragana \"GOUDOU\"(0x3054 0x3046 0x3069 0x3046)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results3 = { + { 0, 0, 0}, + { 0, 0, 0}, + { -1, -1, -1}, + }; + static final String[][] compData3 = { + /* + * Data to verify ',' relationship in LocaleElements_ja.java + */ + {"\u3042", "\u3041", + "Hiragana \"A\"(0x3042) <---> Hiragana \"a\"(0x3041)"}, + {"\u3041", "\u30A2", + "Hiragana \"a\"(0x3041) <---> Katakana \"A\"(0x30A2)"}, + {"\u30A2", "\u30A1", + "Katakana \"A\"(0x30A2) <---> Katakana \"a\"(0x30A1)"}, + {"\u3094", "\u30F4", + "Hiragana \"VU\"(0x3094) <---> Katakana \"VU\"(0x30F4)"}, + {"\u3094", "\u30A6\u3099", + "Hiragana \"VU\"(0x3094) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u3046\u3099", "\u30F4", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"}, + {"\u3046\u3099", "\u30A6\u3099", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u30AB\u30A2", "\u30AB\u30FC", + "Katakana \"KAA\"(0x30AB 0x30A2) <---> Katakana \"KA-\"(0x30AB 0x30FC)"}, + {"\u30CB\u30A1\u30A2", "\u30CB\u30A1\u30FC", + "Katakana \"NyaA\"(0x30CB 0x30A1 0x30A2) <---> Katakana \"Nya-\"(0x30CB 0x30A1 0x30FC)"}, + {"\u30B3\u30AA\u30D2\u30A4", "\u30B3\u30FC\u30D2\u30FC", + "Katakana \"KOOHII\"(0x30B3 0x30AA 0x30D2 0x30A4) <---> Katakana \"KO-HI-\"(0x30B3 0x30FC 0x30D2 0x30FC)"}, + {"\u308A\u3088\u3046", "\u308A\u3087\u3046", + "Hiragana \"RIYOU\"(0x308A 0x3088 0x3046) <---> Hiragana \"Ryou\"(0x308A 0x3087 0x3046)"}, + {"\u3081\u3064\u304D", "\u3081\u3063\u304D", + "Hiragana \"METSUKI\"(0x3081 0x3064 0x304D) <---> Hiragana \"MEKKI\"(0x3081 0x3063 0x304D)"}, + {"\u3075\u3042\u3093", "\u30D5\u30A1\u30F3", + "Hiragana \"FUAN\"(0x3075 0x3042 0x3093) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"}, + {"\u3075\u3041\u3093", "\u30D5\u30A2\u30F3", + "Hiragana \"FUaN\"(0x3075 0x3041 0x3093) <---> Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3)"}, + {"\u30D5\u30A2\u30F3", "\u30D5\u30A1\u30F3", + "Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + */ + static final int[][] results4 = { + { 0, 0, 0}, + { 0, 0, 0}, + { 0, 0, 0}, + }; + static final String[][] compData4 = { + /* + * Data to verify Japanese normalization + */ + {"\u309E", "\u309D\u3099", + "Hiragana Voiced Iteration Mark(0x309E) <---> Hiragana Iteration Mark(0x309D)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u30FE", "\u30FD\u3099", + "Katakana Voiced Iteration Mark(0x30FE) <---> Katakana iteration mark(0x30FD)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u306F\u3099", "\u3070", + "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"BA\"(0x3070)"}, + {"\u306F\u309A", "\u3071", + "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A) <---> Hiragana \"PA\"(0x3071)"}, + {"\u30EF\u3099", "\u30F7", + "Katakana \"WA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VA\"(0x30F7)"}, + {"\u30F0\u3099", "\u30F8", + "Katakana \"WI\"(0x30F0)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VI\"(0x30F8)"}, + {"\u30F1\u3099", "\u30F9", + "Katakana \"WE\"(0x30F1)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VE\"(0x30F9)"}, + {"\u30F2\u3099", "\u30FA", + "Katakana \"WO\"(0x30F2)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VO\"(0x30FA)"}, + {"\u3046\u3099", "\u3094", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"VU\"(0x3094)"}, + {"\u30A6\u3099", "\u30F4", + "Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"}, + + // verify normalization + {"\u2260", "\u003D\u0338", + "Not Equal To(0x2260) <---> Equal(0x003D)Combining Long Solidus Overlay(0x0338)"}, + {"\u2262", "\u2261\u0338", + "Not Identical To(0x2262) <---> Identical To(0x2261)Combining Long Solidus Overlay(0x0338)"}, + {"\u226E", "\u003C\u0338", + "Not Less-than(0x226E) <---> Less-than Sign(0x003C)Combining Long Solidus Overlay(0x0338)"}, + + // Verify a character which has been added since Unicode 2.1.X. + {"\u798F", "\uFA1B", + "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + */ + static final int[][] results5 = { + { 1, 0, 0}, + { 1, 0, 0}, + { 1, 0, 0}, + }; + static final String[][] compData5 = { + /* + * Data to verify normalization + */ + {"\u226D", "\u224D\u0338", + "Not Equivalent To(0x226D) <---> Equivalent To(0x224D)Combining Long Solidus Overlay(0x0338)"}, + }; + + static final int[][] results6 = { + { 1, -1, -1}, + { 1, -1, -1}, + { 1, -1, -1}, + }; + static final String[][] compData6 = { + /* + * Data to verify normalization + */ + {"\u226D", "\u226C", + "Not Equivalent To(0x226D) <---> Between(0x226C)"}, + {"\u226D", "\u225F", + "Not Equivalent To(0x226D) <---> Questioned Equal To(0x225F)"}, + }; + + + /* + * The following data isn't used at the moment because iteration marks + * aren't supported now. + */ + static final String[][] compData0 = { + {"\u307F\u307F", "\u307F\u309D", + "Hiragana \"MIMI\"(0x307F 0x307F) <---> Hiragana \"MI\"(0x307F)Hiragana Iteration Mark(0x309D)"}, + {"\u3044\u3059\u305A", "\u3044\u3059\u309E", + "Hiragana \"ISUZU\"(0x3044 0x3059 0x305A) <---> Hiragana \"ISU\"(0x3044 0x3059)Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u30DF\u30DF", "\u30DF\u30FD", + "Katakana \"MIMI\"(0x30DF 0x30DF) <---> Katakana \"MI\"(0x30DF)Katakana Iteration Mark(0x30FD)"}, + {"\u30A4\u30B9\u30BA", "\u30A4\u30B9\u30FE", + "Katakana \"ISUZU\"(0x30A4 0x30B9 0x30BA) <---> Katakana \"ISU\"(0x30A4 0x30B9)Katakana Voiced Iteration Mark(0x30FE)"}, + }; + + + static final String[] decomp_name = { + "NO_DECOMP", "CANONICAL_DECOMP", "FULL_DECOMP" + }; + + static final String[] strength_name = { + "PRIMARY", "SECONDARY", "TERTIARY" + }; + + + Collator col = Collator.getInstance(Locale.JAPAN); + int result = 0; + + public static void main(String[] args) throws Exception { + new JapaneseTest().run(); + } + + public void run() { + // Use all available localse on the initial testing.... + // Locale[] locales = Locale.getAvailableLocales(); + Locale[] locales = { Locale.getDefault() }; + + for (int l = 0; l < locales.length; l++) { + Locale.setDefault(locales[l]); + + for (int decomp = 0; decomp < 3; decomp++) {// See decomp_name. + col.setDecomposition(decomp); + + for (int strength = 0; strength < 3; strength++) {// See strength_name. +// System.err.println("\n" + locales[l] + ": " + strength_name[strength] + " --- " + decomp_name[decomp]); + + col.setStrength(strength); + doCompare(compData1, results1[strength][decomp], strength, decomp); + doCompare(compData2, results2[strength][decomp], strength, decomp); + doCompare(compData3, results3[strength][decomp], strength, decomp); + doCompare(compData4, results4[strength][decomp], strength, decomp); + doCompare(compData5, results5[strength][decomp], strength, decomp); + doCompare(compData6, results6[strength][decomp], strength, decomp); + } + } + } + + /* Check result */ + if (result !=0) { + throw new RuntimeException("Unexpected results on Japanese collation."); + } + } + + void doCompare(String[][] s, int expectedValue, int strength, int decomp) { + int value; + for (int i=0; i < s.length; i++) { + if ((value = col.compare(s[i][0], s[i][1])) != expectedValue) { + result++; + System.err.println(strength_name[strength] + + ": compare() returned unexpected value.(" + + value + ") on " + decomp_name[decomp] + + " Expected(" + expectedValue + + ") for " + s[i][2]); + } + } + } +} diff --git a/jdk/test/java/text/Collator/KoreanTest.java b/jdk/test/java/text/Collator/KoreanTest.java new file mode 100644 index 00000000000..fd314ee13ed --- /dev/null +++ b/jdk/test/java/text/Collator/KoreanTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 1.1 02/09/12 + * @bug 4176141 4655819 + * @summary Regression tests for Korean Collation + */ + +import java.text.*; +import java.util.*; + +public class KoreanTest { + + // NOTE: + // Golden data in this test case is locale data dependent and + // may need to be changed if the Korean locale collation rules + // are changed. + + // And, CollationDecomp has been set to 0(NO_DECOMPOSITION) in + // LocaleElements_ko.java. + // This is very important to consider what is correct behavior in + // Korean Collator. Sometimes different from other locales. + + /* + * TERTIARY(default): s1 < s2, SECONDARY: s1 < s2, PRIMARY: s1 < s2 + */ + static final String[][] compData1 = { + /* + * Data to verify '<' relationship in LocaleElements_ja.java + */ + {"\uACE0\uC591\uC774", "\u732B", + "Hangul \"Cat\"(0xACE0 0xC591 0xC774) <---> Chinese Kanji \"Cat\"(0x732B)"}, + {"\u30FB", "\u2025", + "Katakana middle dot(0x30FB) <---> Two dot leader(0x2025)"}, + + {"\u00B1", "\u2260", + "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"}, + {"\u3011", "\u2260", + "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"}, + {"\u2260", "\u2103", + "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"}, + {"\u2260", "\u2606", + "Not Equal To(0x2260) <---> White Star(0x2606)"}, + + // Unlike other locales' Collator, compare() returns -1 because of + // NO_DECOMPOSITION. + /* above "assumption" is no longer true, now we do normalize ("decomposition") + for the pattern in ko locale, but exclude those hangul syllables, so the + test case below need to be excluded from tiger/1.5 + {"\u003D\u0338", "\u2260", + "Equal(0x003D)Combining Long Solidus Overlay(0x0338) <---> Not Equal To(0x2260)"}, + */ + }; + + /* + * TERTIARY(default): s1 = s2, SECONDARY: s1 = s2, PRIMARY: s1 = s2 + */ + static final String[][] compData2 = { + // Verify a character which has been added since Unicode 2.1.X. + {"\u798F", "\uFA1B", + "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"}, + + }; + + Collator col = Collator.getInstance(Locale.KOREA); + int result = 0; + + public static void main(String[] args) throws Exception { + new KoreanTest().run(); + } + + public void run() { + // + // Test for TERTIARY(default) + // + doCompare(compData1); + doEquals(compData2); + + // + // Test for SECONDARY + // + col.setStrength(Collator.SECONDARY); + doCompare(compData1); + doEquals(compData2); + + // + // Test for PRIMARY + // + col.setStrength(Collator.PRIMARY); + doCompare(compData1); + doEquals(compData2); + + if (result !=0) { + throw new RuntimeException("Unexpected results on Korean collation."); + } + } + + /* compare() should return -1 for each combination. */ + void doCompare(String[][] s) { + int value; + for (int i=0; i < s.length; i++) { + if ((value = col.compare(s[i][0], s[i][1])) > -1) { + result++; + System.err.println("TERTIARY: The first string should be less than the second string: " + + s[i][2] + " compare() returned " + value + "."); + } + } + } + + /* equals() should return true for each combination. */ + void doEquals(String[][] s) { + for (int i=0; i < s.length; i++) { + if (!col.equals(s[i][0], s[i][1])) { + result++; + System.err.println("TERTIARY: The first string should be equals to the second string: " + + s[i][2] + " compare() returned " + + col.compare(s[i][0], s[i][1] + ".")); + } + } + } +} diff --git a/jdk/test/java/text/Collator/MonkeyTest.java b/jdk/test/java/text/Collator/MonkeyTest.java new file mode 100644 index 00000000000..9539bf5f5ae --- /dev/null +++ b/jdk/test/java/text/Collator/MonkeyTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /java/text/testlib + * @summary test Collation, Monkey style + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.io.IOException; +import java.util.Random; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.text.CollationKey; + +public class MonkeyTest extends CollatorTest +{ + public static void main(String[] args) throws Exception { + new MonkeyTest().run(args); + } + + public void report(String s, String t, int result, int revResult) + { + if (result == -1) + { + if (revResult != 1) + errln(" --> Test Failed"); + } + else if (result == 1) + { + if (revResult != -1) + errln(" --> Test Failed"); + } + else if (result == 0) + { + if (revResult != 0) + errln(" --> Test Failed"); + } + } + + public void TestCollationKey() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + CollationKey CollationKey1 = myCollator.getCollationKey(subs); + CollationKey CollationKey2 = myCollator.getCollationKey(subt); + int result = CollationKey1.compareTo(CollationKey2); // Tertiary + int revResult = CollationKey2.compareTo(CollationKey1); // Tertiary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.SECONDARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Secondary + revResult = CollationKey2.compareTo(CollationKey1); // Secondary + report(("CollationKey(" + subs + ")") , ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.PRIMARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Primary + revResult = CollationKey2.compareTo(CollationKey1); // Primary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + String addOne = subs + "\uE000"; + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(addOne); + result = CollationKey1.compareTo(CollationKey2); + if (result != -1) + errln("CollationKey(" + subs + ")" + ".LT." + "CollationKey(" + addOne + ") Failed."); + result = CollationKey2.compareTo(CollationKey1); + if (result != 1) + errln("CollationKey(" + addOne + ")" + ".GT." + "CollationKey(" + subs + ") Failed."); + } + private static int checkValue(int value) + { + value *= (value > 0) ? 1 : -1; + return value; + } + public void TestCompare() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + int result = myCollator.compare(subs, subt); // Tertiary + int revResult = myCollator.compare(subt, subs); // Tertiary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.SECONDARY); + result = myCollator.compare(subs, subt); // Secondary + revResult = myCollator.compare(subt, subs); // Secondary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.PRIMARY); + result = myCollator.compare(subs, subt); // Primary + revResult = myCollator.compare(subt, subs); // Primary + report(subs, subt, result, revResult); + String addOne = subs + "\uE000"; + result = myCollator.compare(subs, addOne); + if (result != -1) + errln("Test : " + subs + " .LT. " + addOne + " Failed."); + result = myCollator.compare(addOne, subs); + if (result != 1) + errln("Test : " + addOne + " .GE. " + subs + " Failed."); + } + private static Collator myCollator = Collator.getInstance(); +} diff --git a/jdk/test/java/text/Collator/Regression.java b/jdk/test/java/text/Collator/Regression.java new file mode 100644 index 00000000000..958ce29c524 --- /dev/null +++ b/jdk/test/java/text/Collator/Regression.java @@ -0,0 +1,940 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4048446 4051866 4053636 4054238 4054734 4054736 4058613 4059820 4060154 + * 4062418 4065540 4066189 4066696 4076676 4078588 4079231 4081866 4087241 + * 4087243 4092260 4095316 4101940 4103436 4114076 4114077 4124632 4132736 + * 4133509 4139572 4141640 4179126 4179686 4244884 4663220 + * @library /java/text/testlib + * @summary Regression tests for Collation and associated classes + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.Locale; +import java.util.Vector; + + +public class Regression extends CollatorTest { + + public static void main(String[] args) throws Exception { + new Regression().run(args); + } + + // CollationElementIterator.reset() doesn't work + // + public void Test4048446() { + CollationElementIterator i1 = en_us.getCollationElementIterator(test1); + CollationElementIterator i2 = en_us.getCollationElementIterator(test1); + + while ( i1.next() != CollationElementIterator.NULLORDER ) { + } + i1.reset(); + + assertEqual(i1, i2); + } + + + // Collator -> rules -> Collator round-trip broken for expanding characters + // + public void Test4051866() throws ParseException { + // Build a collator containing expanding characters + RuleBasedCollator c1 = new RuleBasedCollator("< o " + +"& oe ,o\u3080" + +"& oe ,\u1530 ,O" + +"& OE ,O\u3080" + +"& OE ,\u1520" + +"< p ,P"); + + // Build another using the rules from the first + RuleBasedCollator c2 = new RuleBasedCollator(c1.getRules()); + + // Make sure they're the same + if (!c1.getRules().equals(c2.getRules())) { + errln("Rules are not equal"); + } + } + + // Collator thinks "black-bird" == "black" + // + public void Test4053636() { + if (en_us.equals("black-bird","black")) { + errln("black-bird == black"); + } + } + + + // CollationElementIterator will not work correctly if the associated + // Collator object's mode is changed + // + public void Test4054238() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + CollationElementIterator i1 = en_us.getCollationElementIterator(test3); + + c.setDecomposition(Collator.NO_DECOMPOSITION); + CollationElementIterator i2 = en_us.getCollationElementIterator(test3); + + // At this point, BOTH iterators should use NO_DECOMPOSITION, since the + // collator itself is in that mode + assertEqual(i1, i2); + } + + // Collator.IDENTICAL documented but not implemented + // + public void Test4054734() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + try { + c.setStrength(Collator.IDENTICAL); + } + catch (Exception e) { + errln("Caught " + e.toString() + " setting Collator.IDENTICAL"); + } + + String[] decomp = { + "\u0001", "<", "\u0002", + "\u0001", "=", "\u0001", + "A\u0001", ">", "~\u0002", // Ensure A and ~ are not compared bitwise + "\u00C0", "=", "A\u0300" // Decomp should make these equal + }; + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + compareArray(c, decomp); + + String[] nodecomp = { + "\u00C0", ">", "A\u0300" // A-grave vs. A combining-grave + }; + c.setDecomposition(Collator.NO_DECOMPOSITION); + compareArray(c, nodecomp); + } + + // Full Decomposition mode not implemented + // + public void Test4054736() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\uFB4f", "=", "\u05D0\u05DC", // Alef-Lamed vs. Alef, Lamed + }; + + compareArray(c, tests); + } + + // Collator.getInstance() causes an ArrayIndexOutofBoundsException for Korean + // + public void Test4058613() { + // Creating a default collator doesn't work when Korean is the default + // locale + + Locale oldDefault = Locale.getDefault(); + + Locale.setDefault( Locale.KOREAN ); + try { + Collator c = Collator.getInstance(); + + // Since the fix to this bug was to turn of decomposition for Korean collators, + // ensure that's what we got + if (c.getDecomposition() != Collator.NO_DECOMPOSITION) { + errln("Decomposition is not set to NO_DECOMPOSITION"); + } + } + finally { + Locale.setDefault(oldDefault); + } + } + + // RuleBasedCollator.getRules does not return the exact pattern as input + // for expanding character sequences + // + public void Test4059820() { + RuleBasedCollator c = null; + try { + c = new RuleBasedCollator("< a < b , c/a < d < z"); + } catch (ParseException e) { + errln("Exception building collator: " + e.toString()); + return; + } + if ( c.getRules().indexOf("c/a") == -1) { + errln("returned rules do not contain 'c/a'"); + } + } + + // MergeCollation::fixEntry broken for "& H < \u0131, \u0130, i, I" + // + public void Test4060154() { + RuleBasedCollator c = null; + try { + c = new RuleBasedCollator("< g, G < h, H < i, I < j, J" + + " & H < \u0131, \u0130, i, I" ); + } catch (ParseException e) { + errln("Exception building collator: " + e.toString()); + return; + } + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + + String[] tertiary = { + "A", "<", "B", + "H", "<", "\u0131", + "H", "<", "I", + "\u0131", "<", "\u0130", + "\u0130", "<", "i", + "\u0130", ">", "H", + }; + c.setStrength(Collator.TERTIARY); + compareArray(c, tertiary); + + String[] secondary = { + "H", "<", "I", + "\u0131", "=", "\u0130", + }; + c.setStrength(Collator.PRIMARY); + compareArray(c, secondary); + }; + + // Secondary/Tertiary comparison incorrect in French Secondary + // + public void Test4062418() throws ParseException { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "p\u00eache", "<", "p\u00e9ch\u00e9", // Comparing accents from end, p\u00e9ch\u00e9 is greater + }; + + compareArray(c, tests); + } + + // Collator.compare() method broken if either string contains spaces + // + public void Test4065540() { + if (en_us.compare("abcd e", "abcd f") == 0) { + errln("'abcd e' == 'abcd f'"); + } + } + + // Unicode characters need to be recursively decomposed to get the + // correct result. For example, + // u1EB1 -> \u0103 + \u0300 -> a + \u0306 + \u0300. + // + public void Test4066189() { + String test1 = "\u1EB1"; + String test2 = "a\u0306\u0300"; + + RuleBasedCollator c1 = (RuleBasedCollator) en_us.clone(); + c1.setDecomposition(Collator.FULL_DECOMPOSITION); + CollationElementIterator i1 = en_us.getCollationElementIterator(test1); + + RuleBasedCollator c2 = (RuleBasedCollator) en_us.clone(); + c2.setDecomposition(Collator.NO_DECOMPOSITION); + CollationElementIterator i2 = en_us.getCollationElementIterator(test2); + + assertEqual(i1, i2); + } + + // French secondary collation checking at the end of compare iteration fails + // + public void Test4066696() { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "\u00e0", "<", "\u01fa", // a-grave < A-ring-acute + }; + + compareArray(c, tests); + } + + + // Bad canonicalization of same-class combining characters + // + public void Test4076676() { + // These combining characters are all in the same class, so they should not + // be reordered, and they should compare as unequal. + String s1 = "A\u0301\u0302\u0300"; + String s2 = "A\u0302\u0300\u0301"; + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + if (c.compare(s1,s2) == 0) { + errln("Same-class combining chars were reordered"); + } + } + + + // RuleBasedCollator.equals(null) throws NullPointerException + // + public void Test4079231() { + try { + if (en_us.equals(null)) { + errln("en_us.equals(null) returned true"); + } + } + catch (Exception e) { + errln("en_us.equals(null) threw " + e.toString()); + } + } + + // RuleBasedCollator breaks on "< a < bb" rule + // + public void Test4078588() throws ParseException { + RuleBasedCollator rbc=new RuleBasedCollator("< a < bb"); + + int result = rbc.compare("a","bb"); + + if (result != -1) { + errln("Compare(a,bb) returned " + result + "; expected -1"); + } + } + + // Combining characters in different classes not reordered properly. + // + public void Test4081866() throws ParseException { + // These combining characters are all in different classes, + // so they should be reordered and the strings should compare as equal. + String s1 = "A\u0300\u0316\u0327\u0315"; + String s2 = "A\u0327\u0316\u0315\u0300"; + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + // Now that the default collators are set to NO_DECOMPOSITION + // (as a result of fixing bug 4114077), we must set it explicitly + // when we're testing reordering behavior. -- lwerner, 5/5/98 + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + + if (c.compare(s1,s2) != 0) { + errln("Combining chars were not reordered"); + } + } + + // string comparison errors in Scandinavian collators + // + public void Test4087241() { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance( + new Locale("da", "DK")); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "\u007a", "<", "\u00e6", // z < ae + "a\u0308", "<", "a\u030a", // a-unlaut < a-ring + "Y", "<", "u\u0308", // Y < u-umlaut + }; + + compareArray(c, tests); + } + + // CollationKey takes ignorable strings into account when it shouldn't + // + public void Test4087243() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] tests = { + "123", "=", "123\u0001", // 1 2 3 = 1 2 3 ctrl-A + }; + + compareArray(c, tests); + } + + // Mu/micro conflict + // Micro symbol and greek lowercase letter Mu should sort identically + // + public void Test4092260() { + Collator c = Collator.getInstance(new Locale("el", "")); + + // will only be equal when FULL_DECOMPOSITION is used + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\u00B5", "=", "\u03BC", + }; + + compareArray(c, tests); + } + + void Test4095316() { + Collator c = Collator.getInstance(new Locale("el", "GR")); + c.setStrength(Collator.TERTIARY); + // javadocs for RuleBasedCollator clearly specify that characters containing compatability + // chars MUST use FULL_DECOMPOSITION to get accurate comparisons. + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\u03D4", "=", "\u03AB", + }; + + compareArray(c, tests); + } + + public void Test4101940() { + try { + RuleBasedCollator c = new RuleBasedCollator("< a < b"); + CollationElementIterator i = c.getCollationElementIterator(""); + i.reset(); + + if (i.next() != i.NULLORDER) { + errln("next did not return NULLORDER"); + } + } + catch (Exception e) { + errln("Caught " + e ); + } + } + + // Collator.compare not handling spaces properly + // + public void Test4103436() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] tests = { + "file", "<", "file access", + "file", "<", "fileaccess", + }; + + compareArray(c, tests); + } + + // Collation not Unicode conformant with Hangul syllables + // + public void Test4114076() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + // + // With Canonical decomposition, Hangul syllables should get decomposed + // into Jamo, but Jamo characters should not be decomposed into + // conjoining Jamo + // + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + String[] test1 = { + "\ud4db", "=", "\u1111\u1171\u11b6", + }; + compareArray(c, test1); + + // Full decomposition result should be the same as canonical decomposition + // for all hangul. + c.setDecomposition(Collator.FULL_DECOMPOSITION); + compareArray(c, test1); + + } + + + // Collator.getCollationKey was hanging on certain character sequences + // + public void Test4124632() throws Exception { + Collator coll = Collator.getInstance(Locale.JAPAN); + + try { + coll.getCollationKey("A\u0308bc"); + } catch (OutOfMemoryError e) { + errln("Ran out of memory -- probably an infinite loop"); + } + } + + // sort order of french words with multiple accents has errors + // + public void Test4132736() { + Collator c = Collator.getInstance(Locale.FRANCE); + + String[] test1 = { + "e\u0300e\u0301", "<", "e\u0301e\u0300", + "e\u0300\u0301", ">", "e\u0301\u0300", + }; + compareArray(c, test1); + } + + // The sorting using java.text.CollationKey is not in the exact order + // + public void Test4133509() { + String[] test1 = { + "Exception", "<", "ExceptionInInitializerError", + "Graphics", "<", "GraphicsEnvironment", + "String", "<", "StringBuffer", + }; + compareArray(en_us, test1); + } + + // Collation with decomposition off doesn't work for Europe + // + public void Test4114077() { + // Ensure that we get the same results with decomposition off + // as we do with it on.... + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] test1 = { + "\u00C0", "=", "A\u0300", // Should be equivalent + "p\u00eache", ">", "p\u00e9ch\u00e9", + "\u0204", "=", "E\u030F", + "\u01fa", "=", "A\u030a\u0301", // a-ring-acute -> a-ring, acute + // -> a, ring, acute + "A\u0300\u0316", "<", "A\u0316\u0300", // No reordering --> unequal + }; + c.setDecomposition(Collator.NO_DECOMPOSITION); + compareArray(c, test1); + + String[] test2 = { + "A\u0300\u0316", "=", "A\u0316\u0300", // Reordering --> equal + }; + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + compareArray(c, test2); + } + + // Support for Swedish gone in 1.1.6 (Can't create Swedish collator) + // + public void Test4141640() { + // + // Rather than just creating a Swedish collator, we might as well + // try to instantiate one for every locale available on the system + // in order to prevent this sort of bug from cropping up in the future + // + Locale[] locales = Collator.getAvailableLocales(); + + for (int i = 0; i < locales.length; i++) { + try { + Collator c = Collator.getInstance(locales[i]); + } catch (Exception e) { + errln("Caught " + e + " creating collator for " + locales[i]); + } + } + } + + // getCollationKey throws exception for spanish text + // Cannot reproduce this bug on 1.2, however it DOES fail on 1.1.6 + // + public void Test4139572() { + // + // Code pasted straight from the bug report + // + // create spanish locale and collator + Locale l = new Locale("es", "es"); + Collator col = Collator.getInstance(l); + + // this spanish phrase kills it! + col.getCollationKey("Nombre De Objeto"); + } + + // RuleBasedCollator doesn't use getCollationElementIterator internally + // + public void Test4146160() throws ParseException { + // + // Use a custom collator class whose getCollationElementIterator + // methods increment a count.... + // + My4146160Collator.count = 0; + new My4146160Collator().getCollationKey("1"); + if (My4146160Collator.count < 1) { + errln("getCollationElementIterator not called"); + } + + My4146160Collator.count = 0; + new My4146160Collator().compare("1", "2"); + if (My4146160Collator.count < 1) { + errln("getCollationElementIterator not called"); + } + } + + static class My4146160Collator extends RuleBasedCollator { + public My4146160Collator() throws ParseException { + super(Regression.en_us.getRules()); + } + + public CollationElementIterator getCollationElementIterator( + String text) { + count++; + return super.getCollationElementIterator(text); + } + public CollationElementIterator getCollationElementIterator( + CharacterIterator text) { + count++; + return super.getCollationElementIterator(text); + } + + public static int count = 0; + }; + + // CollationElementIterator.previous broken for expanding char sequences + // + public void Test4179686() throws ParseException { + + // Create a collator with a few expanding character sequences in it.... + RuleBasedCollator coll = new RuleBasedCollator(en_us.getRules() + + " & ae ; \u00e4 & AE ; \u00c4" + + " & oe ; \u00f6 & OE ; \u00d6" + + " & ue ; \u00fc & UE ; \u00dc"); + + String text = "T\u00f6ne"; // o-umlaut + + CollationElementIterator iter = coll.getCollationElementIterator(text); + Vector elements = new Vector(); + int elem; + + // Iterate forward and collect all of the elements into a Vector + while ((elem = iter.next()) != iter.NULLORDER) { + elements.addElement(new Integer(elem)); + } + + // Now iterate backward and make sure they're the same + int index = elements.size() - 1; + while ((elem = iter.previous()) != iter.NULLORDER) { + int expect = ((Integer)elements.elementAt(index)).intValue(); + + if (elem != expect) { + errln("Mismatch at index " + index + + ": got " + Integer.toString(elem,16) + + ", expected " + Integer.toString(expect,16)); + } + index--; + } + } + + public void Test4244884() throws ParseException { + RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US); + coll = new RuleBasedCollator(coll.getRules() + + " & C < ch , cH , Ch , CH < cat < crunchy"); + + String[] testStrings = new String[] { + "car", + "cave", + "clamp", + "cramp", + "czar", + "church", + "catalogue", + "crunchy", + "dog" + }; + + for (int i = 1; i < testStrings.length; i++) { + if (coll.compare(testStrings[i - 1], testStrings[i]) >= 0) { + errln("error: \"" + testStrings[i - 1] + + "\" is greater than or equal to \"" + testStrings[i] + + "\"."); + } + } + } + + public void Test4179216() throws ParseException { + // you can position a CollationElementIterator in the middle of + // a contracting character sequence, yielding a bogus collation + // element + RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US); + coll = new RuleBasedCollator(coll.getRules() + + " & C < ch , cH , Ch , CH < cat < crunchy"); + String testText = "church church catcatcher runcrunchynchy"; + CollationElementIterator iter = coll.getCollationElementIterator( + testText); + + // test that the "ch" combination works properly + iter.setOffset(4); + int elt4 = CollationElementIterator.primaryOrder(iter.next()); + + iter.reset(); + int elt0 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(5); + int elt5 = CollationElementIterator.primaryOrder(iter.next()); + + if (elt4 != elt0 || elt5 != elt0) + errln("The collation elements at positions 0 (" + elt0 + "), 4 (" + + elt4 + "), and 5 (" + elt5 + ") don't match."); + + // test that the "cat" combination works properly + iter.setOffset(14); + int elt14 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(15); + int elt15 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(16); + int elt16 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(17); + int elt17 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(18); + int elt18 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(19); + int elt19 = CollationElementIterator.primaryOrder(iter.next()); + + if (elt14 != elt15 || elt14 != elt16 || elt14 != elt17 + || elt14 != elt18 || elt14 != elt19) + errln("\"cat\" elements don't match: elt14 = " + elt14 + ", elt15 = " + + elt15 + ", elt16 = " + elt16 + ", elt17 = " + elt17 + + ", elt18 = " + elt18 + ", elt19 = " + elt19); + + // now generate a complete list of the collation elements, + // first using next() and then using setOffset(), and + // make sure both interfaces return the same set of elements + iter.reset(); + + int elt = iter.next(); + int count = 0; + while (elt != CollationElementIterator.NULLORDER) { + ++count; + elt = iter.next(); + } + + String[] nextElements = new String[count]; + String[] setOffsetElements = new String[count]; + int lastPos = 0; + + iter.reset(); + elt = iter.next(); + count = 0; + while (elt != CollationElementIterator.NULLORDER) { + nextElements[count++] = testText.substring(lastPos, iter.getOffset()); + lastPos = iter.getOffset(); + elt = iter.next(); + } + count = 0; + for (int i = 0; i < testText.length(); ) { + iter.setOffset(i); + lastPos = iter.getOffset(); + elt = iter.next(); + setOffsetElements[count++] = testText.substring(lastPos, iter.getOffset()); + i = iter.getOffset(); + } + for (int i = 0; i < nextElements.length; i++) { + if (nextElements[i].equals(setOffsetElements[i])) { + logln(nextElements[i]); + } else { + errln("Error: next() yielded " + nextElements[i] + ", but setOffset() yielded " + + setOffsetElements[i]); + } + } + } + + public void Test4216006() throws Exception { + // rule parser barfs on "<\u00e0=a\u0300", and on other cases + // where the same token (after normalization) appears twice in a row + boolean caughtException = false; + try { + RuleBasedCollator dummy = new RuleBasedCollator("\u00e0= 0) { + errln("List out of order at element #" + i + ": " + + prettify(sortedList[i]) + " >= " + + prettify(sortedList[i + 1])); + } + } + } + + // CollationElementIterator set doesn't work propertly with next/prev + public void Test4663220() { + RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(Locale.US); + CharacterIterator stringIter = new StringCharacterIterator("fox"); + CollationElementIterator iter = collator.getCollationElementIterator(stringIter); + + int[] elements_next = new int[3]; + logln("calling next:"); + for (int i = 0; i < 3; ++i) { + logln("[" + i + "] " + (elements_next[i] = iter.next())); + } + + int[] elements_fwd = new int[3]; + logln("calling set/next:"); + for (int i = 0; i < 3; ++i) { + iter.setOffset(i); + logln("[" + i + "] " + (elements_fwd[i] = iter.next())); + } + + for (int i = 0; i < 3; ++i) { + if (elements_next[i] != elements_fwd[i]) { + errln("mismatch at position " + i + + ": " + elements_next[i] + + " != " + elements_fwd[i]); + } + } + } + + //------------------------------------------------------------------------ + // Internal utilities + // + private void compareArray(Collator c, String[] tests) { + for (int i = 0; i < tests.length; i += 3) { + + int expect = 0; + if (tests[i+1].equals("<")) { + expect = -1; + } else if (tests[i+1].equals(">")) { + expect = 1; + } else if (tests[i+1].equals("=")) { + expect = 0; + } else { + expect = Integer.decode(tests[i+1]).intValue(); + } + + int result = c.compare(tests[i], tests[i+2]); + if (sign(result) != sign(expect)) + { + errln( i/3 + ": compare(" + prettify(tests[i]) + + " , " + prettify(tests[i+2]) + + ") got " + result + "; expected " + expect); + } + else + { + // Collator.compare worked OK; now try the collation keys + CollationKey k1 = c.getCollationKey(tests[i]); + CollationKey k2 = c.getCollationKey(tests[i+2]); + + result = k1.compareTo(k2); + if (sign(result) != sign(expect)) { + errln( i/3 + ": key(" + prettify(tests[i]) + + ").compareTo(key(" + prettify(tests[i+2]) + + ")) got " + result + "; expected " + expect); + + errln(" " + prettify(k1) + " vs. " + prettify(k2)); + } + } + } + } + + private static final int sign(int i) { + if (i < 0) return -1; + if (i > 0) return 1; + return 0; + } + + + static RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US); + + String test1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?"; + String test2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?"; + String test3 = "a\u00FCbeck Gr\u00F6\u00DFe L\u00FCbeck"; +} diff --git a/jdk/test/java/text/Collator/SpanishTest.java b/jdk/test/java/text/Collator/SpanishTest.java new file mode 100644 index 00000000000..fab4ef0d66b --- /dev/null +++ b/jdk/test/java/text/Collator/SpanishTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /java/text/testlib + * @summary test Spanish Collation + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class SpanishTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new SpanishTest().run(args); + } + + /* + * TestPrimary() + */ + private static final String[] primarySourceData = { + "alias", + "acHc", + "acc", + "Hello" + }; + + private static final String[] primaryTargetData = { + "allias", + "aCHc", + "aCHc", + "hellO" + }; + + private static final int[] primaryResults = { + -1, 0, -1, 0 + }; + + /* + * TestTertiary() + */ + private static final String[] tertiarySourceData = { + "alias", + "Elliot", + "Hello", + "acHc", + "acc" + }; + + private static final String[] tertiaryTargetData = { + "allias", + "Emiot", + "hellO", + "aCHc", + "aCHc" + }; + + private static final int[] tertiaryResults = { + -1, -1, 1, -1, -1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("es", "ES", "")); +} diff --git a/jdk/test/java/text/Collator/SurrogatesTest.java b/jdk/test/java/text/Collator/SurrogatesTest.java new file mode 100644 index 00000000000..87df904e882 --- /dev/null +++ b/jdk/test/java/text/Collator/SurrogatesTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /java/text/testlib + * @summary test Supplementary Character Collation + */ + +import java.text.Collator; +import java.text.RuleBasedCollator; + +// Quick dummy program for printing out test results +public class SurrogatesTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new SurrogatesTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "A\ud800\udc04BCD" + }; + + private static final String[] primaryTargetData = { + "A\ud800\udc05BCD" + }; + + private static final int[] primaryResults = { + 0 + }; + + /* + * Data for TestTertiary() + */ + private static final String[] tertiarySourceData = { + "ABCD", + "ABCD", + "A\ud800\udc00CD", + "WXYZ", + "WXYZ", + "AFEM", + "FGM", + "BB", + "BB" + }; + + private static final String[] tertiaryTargetData = { + "A\ud800\udc00CD", + "AB\ud800\udc00D", + "A\ud800\udc01CD", + "W\ud800\udc0aYZ", + "W\ud800\udc0bYZ", + "A\ud800\udc08M", + "\ud800\udc08M", + "\ud800\udc04\ud800\udc02", + "\ud800\udc04\ud800\udc05" + }; + + private static final int[] tertiaryResults = { + -1, 1, 1, 1, -1, -1, -1, -1, 1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private Collator getCollator() { + RuleBasedCollator base = (RuleBasedCollator)Collator.getInstance(); + String rule = base.getRules(); + try { + return new RuleBasedCollator(rule + + "&B < \ud800\udc01 < \ud800\udc00" + + ", \ud800\udc02, \ud800\udc03" + + "; \ud800\udc04, \ud800\udc05" + + "< \ud800\udc06 < \ud800\udc07" + + "&FE < \ud800\udc08" + + "&PE, \ud800\udc09" + + "&Z < \ud800\udc0a < \ud800\udc0b < \ud800\udc0c" + + "&\ud800\udc0a < x, X" + + "&A < \ud800\udc04\ud800\udc05"); + } catch (Exception e) { + errln("Failed to create new RulebasedCollator object"); + return null; + } + } + + private Collator myCollation = getCollator(); +} diff --git a/jdk/test/java/text/Collator/Test4401726.java b/jdk/test/java/text/Collator/Test4401726.java new file mode 100644 index 00000000000..6f9e9ed945e --- /dev/null +++ b/jdk/test/java/text/Collator/Test4401726.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4401726 + * @author John O'Conner + * @library /java/text/testlib + * @summary Regression tests for Collation and associated classes + */ + + +import java.text.*; +import java.util.Locale; +import java.util.Vector; + +public class Test4401726 extends CollatorTest { + + public static void main(String[] args) throws Exception { + new Test4401726().run(args); + } + + public void TestSetOffSet() { + + int[] expected = {0, -1, 65536}; + int[] actual = new int[expected.length]; + + try { + String rule = "< a, A < d; D"; + + RuleBasedCollator rbc = new RuleBasedCollator(rule); + String str = "aD"; + CollationElementIterator iterator = + rbc.getCollationElementIterator(str); + + iterator.setOffset(0); + actual[0] = iterator.getOffset(); + actual[1] = iterator.previous(); + iterator.setOffset(0); + actual[2] = iterator.next(); + + if (compareArray(expected, actual) == false) { + errln("Failed."); + } + + str = "a"; + iterator = rbc.getCollationElementIterator(str); + iterator.setOffset(0); + actual[0] = iterator.getOffset(); + actual[1] = iterator.previous(); + iterator.setOffset(0); + actual[2] = iterator.next(); + + if (compareArray(expected, actual) == false) { + errln("Failed."); + } + + } catch (ParseException e) { + errln("Unexpected ParseException: " + e); + } + + + } + + boolean compareArray(int[] expected, int[] actual) { + boolean retVal = false; + if (expected.length == actual.length) { + int errors = 0; + for(int x=0; x< expected.length; ++x) { + if (expected[x] != actual[x]) { + ++errors; + } + } + if (errors == 0) retVal = true; + } + return retVal; + } +} diff --git a/jdk/test/java/text/Collator/ThaiTest.java b/jdk/test/java/text/Collator/ThaiTest.java new file mode 100644 index 00000000000..7d643446434 --- /dev/null +++ b/jdk/test/java/text/Collator/ThaiTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /java/text/testlib + * @summary test Thai Collation + */ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * + * This software is the proprietary information of Oracle. + * Use is subject to license terms. + * + */ + +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; + +public class ThaiTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new ThaiTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "\u0e01\u0e01", + "\u0e07\u0e42\u0e01\u0e49", + "\u0e10\u0e34\u0e19", + "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32", + "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22", + "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22", + "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30", + "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07", + "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c", + "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07", + "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25", + "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c", + "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21", + "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19", + "\u0e2a\u0e49\u0e28\u0e36\u0e01", + "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27", + "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19", + "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19", + "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19", + "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07", + "\u0e2a\u0e49\u0e44\u0e01\u0e48", + "\u0e2b", + "\u0e2b\u0e0b\u0e2d\u0e07", + "\u0e2b\u0e19", + "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32", + "\u0e2b\u0e21", + "\u0e2b\u0e21\u0e17\u0e2d\u0e07", + "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14", + "\u0e2b\u0e21\u0e49", + "\u0e2b\u0e23\u0e13\u0e22\u0e4c", + "\u0e2b\u0e25", + "\u0e2b\u0e25\u0e19\u0e49\u0e33", + "\u0e2b\u0e25\u0e48", + "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19", + "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b", + "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07", + "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a", + "\u0e2b\u0e49", + "\u0e2d", + "\u0e2d\u0e49", + "\u0e2e\u0e42\u0e25", + "\u0e2e\u0e44\u0e1f", + "\u0e2e\u0e49" + }; + + private static final String[] primaryTargetData = { + "\u0e01\u0e01", + "\u0e07\u0e42\u0e01\u0e49", + "\u0e10\u0e34\u0e19", + "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32", + "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22", + "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22", + "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30", + "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07", + "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c", + "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07", + "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25", + "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c", + "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21", + "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19", + "\u0e2a\u0e49\u0e28\u0e36\u0e01", + "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27", + "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19", + "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19", + "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19", + "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07", + "\u0e2a\u0e49\u0e44\u0e01\u0e48", + "\u0e2b", + "\u0e2b\u0e0b\u0e2d\u0e07", + "\u0e2b\u0e19", + "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32", + "\u0e2b\u0e21", + "\u0e2b\u0e21\u0e17\u0e2d\u0e07", + "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14", + "\u0e2b\u0e21\u0e49", + "\u0e2b\u0e23\u0e13\u0e22\u0e4c", + "\u0e2b\u0e25", + "\u0e2b\u0e25\u0e19\u0e49\u0e33", + "\u0e2b\u0e25\u0e48", + "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19", + "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b", + "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07", + "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a", + "\u0e2b\u0e49", + "\u0e2d", + "\u0e2d\u0e49", + "\u0e2e\u0e42\u0e25", + "\u0e2e\u0e44\u0e1f", + "\u0e2e\u0e49" + }; + + private static final int[] primaryResults = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("th")); +} diff --git a/jdk/test/java/text/Collator/TurkishTest.java b/jdk/test/java/text/Collator/TurkishTest.java new file mode 100644 index 00000000000..f83ef228e06 --- /dev/null +++ b/jdk/test/java/text/Collator/TurkishTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /java/text/testlib + * @summary test Turkish Collation + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class TurkishTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new TurkishTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "\u00FCoid", + "vo\u0131d", + "idea", + "Idea", + "\u0130dea" + }; + + private static final String[] primaryTargetData = { + "void", + "void", + "Idea", + "\u0130dea", + "\u0131dea" + }; + + private static final int[] primaryResults = { + -1, -1, 1, -1, 1 + }; + + /* + * Data for TestTertiary() + */ + private static final String[] tertiarySourceData = { + "s\u0327", + "v\u00E4t", + "old", + "\u00FCoid", + "h\u011Ealt", + "stres\u015E", + "vo\u0131d", + "idea", + "idea", + "\u0131dea" + }; + + private static final String tertiaryTargetData[] = { + "u\u0308", + "vbt", + "\u00D6ay", + "void", + "halt", + "\u015Etre\u015Es", + "void", + "Idea", + "\u0130dea", + "Idea" + }; + + private static final int[] tertiaryResults = { + -1, -1, -1, -1, 1, -1, -1, 1, -1, -1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("tr", "TR", "")); +} diff --git a/jdk/test/java/text/Collator/VietnameseTest.java b/jdk/test/java/text/Collator/VietnameseTest.java new file mode 100644 index 00000000000..faa4921073c --- /dev/null +++ b/jdk/test/java/text/Collator/VietnameseTest.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4932968 5015215 + * @library /java/text/testlib + * @summary test Vietnamese Collation + */ + +/* + ******************************************************************************* + * (C) Copyright IBM Corp. 1996-2003 - All Rights Reserved * + * * + * The original version of this source code and documentation is copyrighted * + * and owned by IBM, These materials are provided under terms of a License * + * Agreement between IBM and Sun. This technology is protected by multiple * + * US and International patents. This notice and attribution to IBM may not * + * to removed. * + ******************************************************************************* + */ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class VietnameseTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new VietnameseTest().run(args); + } + + private final static String testPS[] = { + "a", + "a", + "\u00c2", + "Cz", + "d", + "e", + "e", + "\u1ec7", + "gz", + "i", + "kz", + "nz", + "nh", + "o", + "o", + "\u01a0", + "pz", + "tz", + "tr", + "u", + "u", + "y" + }; + + private final static String testPT[] = { + "\u00e0", + "\u0102", + "\u0102", + "Ch", + "\u0110", + "\u0111", + "\u1eb9", + "\u1eb9", + "gi", + "\u0128", + "kh", + "ng", + "ng", + "\u00f2", + "\u00f4", + "\u00f4", + "ph", + "th", + "th", + "\u1ee5", + "\u01b0", + "\u1ef4" + }; + + private final static int testPR[] = { + 0, + -1, + 1, + 1, + -1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 0, + -1, + 1, + 1, + 1, + 1, + 0, + -1, + 0 + }; + + private final static String testT[] = { + "a", + "A", + "\u00e0", + "\u00c0", + "\u1ea3", + "\u1ea2", + "\u00e3", + "\u00c3", + "\u00e1", + "\u00c1", + "\u1ea1", + "\u1ea0", + "\u0103", + "\u0102", + "\u1eb1", + "\u1eb0", + "\u1eb3", + "\u1eb2", + "\u1eb5", + "\u1eb4", + "\u1eaf", + "\u1eae", + "\u1eb7", + "\u1eb6", + "\u00e2", + "\u00c2", + "\u1ea7", + "\u1ea6", + "\u1ea9", + "\u1ea8", + "\u1eab", + "\u1eaa", + "\u1ea5", + "\u1ea4", + "\u1ead", + "\u1eac", + "b", + "B", + "c", + "C", + "ch", + "Ch", + "CH", + "d", + "D", + "\u0111", + "\u0110", + "e", + "E", + "\u00e8", + "\u00c8", + "\u1ebb", + "\u1eba", + "\u1ebd", + "\u1ebc", + "\u00e9", + "\u00c9", + "\u1eb9", + "\u1eb8", + "\u00ea", + "\u00ca", + "\u1ec1", + "\u1ec0", + "\u1ec3", + "\u1ec2", + "\u1ec5", + "\u1ec4", + "\u1ebf", + "\u1ebe", + "\u1ec7", + "\u1ec6", + "f", + "F", + "g", + "G", + "gi", + "Gi", + "GI", + "gz", + "h", + "H", + "i", + "I", + "\u00ec", + "\u00cc", + "\u1ec9", + "\u1ec8", + "\u0129", + "\u0128", + "\u00ed", + "\u00cd", + "\u1ecb", + "\u1eca", + "j", + "J", + "k", + "K", + "kh", + "Kh", + "KH", + "kz", + "l", + "L", + "m", + "M", + "n", + "N", + "ng", + "Ng", + "NG", + "ngz", + "nh", + "Nh", + "NH", + "nz", + "o", + "O", + "\u00f2", + "\u00d2", + "\u1ecf", + "\u1ece", + "\u00f5", + "\u00d5", + "\u00f3", + "\u00d3", + "\u1ecd", + "\u1ecc", + "\u00f4", + "\u00d4", + "\u1ed3", + "\u1ed2", + "\u1ed5", + "\u1ed4", + "\u1ed7", + "\u1ed6", + "\u1ed1", + "\u1ed0", + "\u1ed9", + "\u1ed8", + "\u01a1", + "\u01a0", + "\u1edd", + "\u1edc", + "\u1edf", + "\u1ede", + "\u1ee1", + "\u1ee0", + "\u1edb", + "\u1eda", + "\u1ee3", + "\u1ee2", + "p", + "P", + "ph", + "Ph", + "PH", + "pz", + "q", + "Q", + "r", + "R", + "s", + "S", + "t", + "T", + "th", + "Th", + "TH", + "thz", + "tr", + "Tr", + "TR", + "tz", + "u", + "U", + "\u00f9", + "\u00d9", + "\u1ee7", + "\u1ee6", + "\u0169", + "\u0168", + "\u00fa", + "\u00da", + "\u1ee5", + "\u1ee4", + "\u01b0", + "\u01af", + "\u1eeb", + "\u1eea", + "\u1eed", + "\u1eec", + "\u1eef", + "\u1eee", + "\u1ee9", + "\u1ee8", + "\u1ef1", + "\u1ef0", + "v", + "V", + "w", + "W", + "x", + "X", + "y", + "Y", + "\u1ef3", + "\u1ef2", + "\u1ef7", + "\u1ef6", + "\u1ef9", + "\u1ef8", + "\u00fd", + "\u00dd", + "\u1ef5", + "\u1ef4", + "z", + "Z" + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, testPS, testPT, testPR); + } + + public void TestTertiary() { + int testLength = testT.length; + + myCollation.setStrength(Collator.TERTIARY); + for (int i = 0; i < testLength - 1; i++) { + for (int j = i+1; j < testLength; j++) { + doTest(myCollation, testT[i], testT[j], -1); + } + } + } + + private final Collator myCollation = Collator.getInstance(new Locale("vi", "VN")); +} diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt new file mode 100644 index 00000000000..23c4e4607fc --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt @@ -0,0 +1,44 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized ChiceFormat for Bug4185732Test. + +aced0005737200166a6176612e746578742e43686f696365466f726d617418e9 +c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61 +76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400 +025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3 +bf137d07e803000b5a000c67726f7570696e67557365644200116d6178467261 +6374696f6e4469676974734200106d6178496e74656765724469676974734900 +156d6178696d756d4672616374696f6e4469676974734900146d6178696d756d +496e74656765724469676974734200116d696e4672616374696f6e4469676974 +734200106d696e496e74656765724469676974734900156d696e696d756d4672 +616374696f6e4469676974734900146d696e696d756d496e7465676572446967 +6974735a00107061727365496e74656765724f6e6c7949001573657269616c56 +657273696f6e4f6e53747265616d787200106a6176612e746578742e466f726d +6174fbd8bc12e90f184302000078700103280000000300000028000100000000 +00000001000000000178757200135b4c6a6176612e6c616e672e537472696e67 +3badd256e7e91d7b470200007870000000067400034d6f6e7400035475657400 +0357656474000454687572740003467269740003536174757200025b443ea68c +14ab635a1e0200007870000000073ff000000000000040000000000000004008 +000000000000401000000000000040140000000000004018000000000000401c +000000000000 diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java new file mode 100644 index 00000000000..06c5dea1f53 --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4185732 + * @library /java/text/testlib + * @build Bug4185732Test IntlTest HexDumpReader + * @run main Bug4185732Test + * @summary test that ChoiceFormat invariants are preserved across serialization + */ +/* + * + * + * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + */ + +import java.util.*; +import java.io.*; +import java.text.ChoiceFormat; + +/** + * A Locale can never contains language codes of he, yi or id. + */ +public class Bug4185732Test extends IntlTest { + public static void main(String[] args) throws Exception { + if (args.length == 1 && args[0].equals("prepTest")) { + prepTest(); + } else { + new Bug4185732Test().run(args); + } + } + + public void testIt() throws Exception { + try { + final ObjectInputStream in + = new ObjectInputStream(HexDumpReader.getStreamFromHexDump("Bug4185732.ser.txt")); + final ChoiceFormat loc = (ChoiceFormat)in.readObject(); + if (loc.getFormats().length != loc.getLimits().length) { + errln("ChoiceFormat did not properly check stream"); + } else { + //for some reason, the data file was VALID. This test + //requires a corrupt data file the format and limit + //arrays are of different length. + errln("Test data file was not properly created"); + } + } catch (InvalidObjectException e) { + //this is what we want to have happen + } catch (Exception e) { + errln(e.toString()); + } + } + + /** + * Create a data file for this test. The data file must be corrupted by hand. + */ + private static void prepTest() { + try { + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream("Bug4185732.ser")); + final double[] limits = {1,2,3,4,5,6,7}; + final String[] formats = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}; + final ChoiceFormat fmt = new ChoiceFormat(limits, formats); + out.writeObject(fmt); + out.close(); + System.out.println("You must invalidate the output file before running the test"); + System.out.println("by modifying the length of one of the array"); + } catch (Exception e) { + System.out.println(e); + } + } +} diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java b/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java new file mode 100644 index 00000000000..d211bb6976e --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4387255 + * @summary Verifies that ChoiceFormat can handle large numbers of choices + */ + +import java.text.ChoiceFormat; + +public class Bug4387255 { + + private static final double[] doubles = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35}; + + private static final String[] strings = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", + "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", + "U", "V", "W", "X", "Y", "Z"}; + + private static final String pattern = + "0#0|1#1|2#2|3#3|4#4|5#5|6#6|7#7|8#8|9#9" + + "|10#A|11#B|12#C|13#D|14#E|15#F|16#G|17#H|18#I|19#J" + + "|20#K|21#L|22#M|23#N|24#O|25#P|26#Q|27#R|28#S|29#T" + + "|30#U|31#V|32#W|33#X|34#Y|35#Z"; + + public static void main(String[] args) throws Exception { + ChoiceFormat choiceFormat1 = new ChoiceFormat(doubles, strings); + ChoiceFormat choiceFormat2 = new ChoiceFormat(pattern); + if (!choiceFormat1.equals(choiceFormat2)) { + System.out.println("choiceFormat1: " + choiceFormat1.toPattern()); + System.out.println("choiceFormat2: " + choiceFormat2.toPattern()); + throw new RuntimeException(); + } + + for (int i = 0; i < doubles.length; i++) { + String result = choiceFormat2.format(doubles[i]); + if (!result.equals(strings[i])) { + throw new RuntimeException("Wrong format result - expected " + + strings[i] + ", got " + result); + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4322313.java b/jdk/test/java/text/Format/DateFormat/Bug4322313.java new file mode 100644 index 00000000000..19987022664 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4322313.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4322313 4833268 6302990 6304305 + * @library /java/text/testlib + * @summary Make sure that new implementation for + * SimpleDateFormat.parse('z' or 'Z') and format('z' or 'Z') work correctly. + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +public class Bug4322313 extends IntlTest { + + public void Test4322313() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + boolean err = false; + long mpm = 60 * 1000; /* Milliseconds per a minute */ + + Locale[] locs = {Locale.US, Locale.JAPAN, Locale.UK, new Locale("ar")}; + + String[] formats = { + "z", + "Z", + }; + + Object[][] valids = { + /* given ID offset format('z'), ('Z') index */ + {"GMT+03:04", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(9)}, + {"GMT+13:42", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(9)}, + {"GMT+00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, + {"GMT+1:11", new Long(-71 * mpm), "GMT+01:11", "+0111", new Integer(8)}, + {"GMT +13:42", new Long(0), "GMT", "+0000", new Integer(3)}, + {" GMT", new Long(0), "GMT", "+0000", new Integer(4)}, + {"+0304", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(5)}, + {"+1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(5)}, + {"+0000", new Long(0), "GMT+00:00", "+0000", new Integer(5)}, + {" +1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(6)}, + /* ISO-LATIN-1 digits */ + {"GMT+\u0030\u0031:\u0032\u0033", new Long(-83 * mpm), "GMT+01:23", "+0123", new Integer(9)}, + + /* In fact, this test case is skipped because TimeZone class can't + * recognize TimeZone IDs like "+00234" or "-00234". + */ + {"+00234", new Long(-23 * mpm), "GMT+00:23", "+0023", new Integer(5)}, + + {"GMT-03:04", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(9)}, + {"GMT-13:42", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(9)}, + {"GMT-00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, + {"GMT-1:11", new Long(71 * mpm), "GMT-01:11", "-0111", new Integer(8)}, + {"GMT -13:42", new Long(0), "GMT", "+0000", new Integer(3)}, + {"-0304", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(5)}, + {"-1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(5)}, + {" -1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(6)}, + /* ISO-LATIN-1 digits */ + {"GMT-\u0030\u0031:\u0032\u0033", new Long(83 * mpm), "GMT-01:23", "-0123", new Integer(9)}, + /* In fact, this test case is skipped because TimeZone class can't + * recognize TimeZone IDs like "+00234" or "-00234". + */ + {"-00234", new Long(23 * mpm), "GMT+00:23", "-0023", new Integer(5)}, + }; + + Object[][] invalids = { + /* given ID error index */ + {"GMT+8", new Integer(5)}, + {"GMT+18", new Integer(6)}, + {"GMT+208", new Integer(6)}, + {"GMT+0304", new Integer(6)}, + {"GMT+42195", new Integer(5)}, + {"GMT+5:8", new Integer(7)}, + {"GMT+23:60", new Integer(8)}, + {"GMT+11:1", new Integer(8)}, + {"GMT+24:13", new Integer(5)}, + {"GMT+421:950", new Integer(5)}, + {"GMT+0a:0A", new Integer(5)}, + {"GMT+ 13:42", new Integer(4)}, + {"GMT+13 :42", new Integer(6)}, + {"GMT+13: 42", new Integer(7)}, + {"GMT+-13:42", new Integer(4)}, + {"G M T", new Integer(0)}, + {"+8", new Integer(2)}, + {"+18", new Integer(3)}, + {"+208", new Integer(4)}, + {"+2360", new Integer(4)}, + {"+2413", new Integer(2)}, + {"+42195", new Integer(2)}, + {"+0AbC", new Integer(2)}, + {"+ 1342", new Integer(1)}, + {"+-1342", new Integer(1)}, + {"1342", new Integer(0)}, + /* Arabic-Indic digits */ + {"GMT+\u0660\u0661:\u0662\u0663", new Integer(4)}, + /* Extended Arabic-Indic digits */ + {"GMT+\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, + /* Devanagari digits */ + {"GMT+\u0966\u0967:\u0968\u0969", new Integer(4)}, + /* Fullwidth digits */ + {"GMT+\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, + + {"GMT-8", new Integer(5)}, + {"GMT-18", new Integer(6)}, + {"GMT-208", new Integer(6)}, + {"GMT-0304", new Integer(6)}, + {"GMT-42195", new Integer(5)}, + {"GMT-5:8", new Integer(7)}, + {"GMT-23:60", new Integer(8)}, + {"GMT-11:1", new Integer(8)}, + {"GMT-24:13", new Integer(5)}, + {"GMT-421:950", new Integer(5)}, + {"GMT-0a:0A", new Integer(5)}, + {"GMT- 13:42", new Integer(4)}, + {"GMT-13 :42", new Integer(6)}, + {"GMT-13: 42", new Integer(7)}, + {"GMT-+13:42", new Integer(4)}, + {"-8", new Integer(2)}, + {"-18", new Integer(3)}, + {"-208", new Integer(4)}, + {"-2360", new Integer(4)}, + {"-2413", new Integer(2)}, + {"-42195", new Integer(2)}, + {"-0AbC", new Integer(2)}, + {"- 1342", new Integer(1)}, + {"--1342", new Integer(1)}, + {"-802", new Integer(2)}, + /* Arabic-Indic digits */ + {"GMT-\u0660\u0661:\u0662\u0663", new Integer(4)}, + /* Extended Arabic-Indic digits */ + {"GMT-\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, + /* Devanagari digits */ + {"GMT-\u0966\u0967:\u0968\u0969", new Integer(4)}, + /* Fullwidth digits */ + {"GMT-\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, + }; + + try { + for (int i=0; i < locs.length; i++) { + Locale.setDefault(locs[i]); + + for (int j=0; j < formats.length; j++) { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + SimpleDateFormat sdf = new SimpleDateFormat(formats[j]); + Date date; + + /* Okay case */ + for (int k=0; k < valids.length; k++) { + ParsePosition pos = new ParsePosition(0); + try { + date = sdf.parse((String)valids[k][0], pos); + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] Unexpected Exception occurred: " + e); + continue; + } + + int offset = pos.getIndex(); + if (offset != ((Integer)valids[k][4]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] invalid index: expected:" + valids[k][4] + + ", got:" + offset); + } + + if (date.getTime() != ((Long)valids[k][1]).longValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][1] + + ", got:" + date.getTime() + ", " + date); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][1] + + ", got:" + date.getTime() + ", " + date); +*/ + + try { + date = sdf.parse((String)valids[k][0]); + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] Unexpected Exception occurred: " + e); + continue; + } + + /* Since TimeZone.getTimeZone() don't treat + * "+00234" or "-00234" as a valid ID, skips. + */ + if (((String)valids[k][0]).length() == 6) { + continue; + } + + /* Since TimeZone.getTimeZone() don't recognize + * +hhmm/-hhmm format, add "GMT" as prefix. + */ + sdf.setTimeZone(TimeZone.getTimeZone( + (((((String)valids[k][0]).charAt(0) != 'G') ? + "GMT" : "") + valids[k][0]))); + StringBuffer s = new StringBuffer(); + sdf.format(date, s, new FieldPosition(0)); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + + String got = s.toString(); + String expected = (String)valids[k][2+j]; + if (!got.equals(expected) && + // special case to allow the difference between + // DateFormatSymbols.getZoneStrings() and + // TimeZone.getDisplayName() for "GMT+-00:00" + !(got.equals("GMT-00:00") && + expected.equals("GMT+00:00"))) { + err = true; + System.err.println("\tFormat Error [Locale=" + + Locale.getDefault() + ", " + + formats[j] + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][2+j] + + ", got:" + s + ", " + date); + } else { +/* + logln("\tFormat Okay [Locale=" + + Locale.getDefault() + ", " + + formats[j] + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][2+j] + + ", got:" + s + ", " + date); +*/ + } + } + } + + /* Error case 1 + * using SimpleDateFormat.parse(String, ParsePosition) + */ + for (int k=0; k < invalids.length; k++) { + ParsePosition pos = new ParsePosition(0); + try { + date = sdf.parse((String)invalids[k][0], pos); + if (date != null) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] expected:null , got:" + date); + } + int offset = pos.getErrorIndex(); + if (offset != ((Integer)invalids[k][1]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] incorrect offset. expected:" + + invalids[k][1] + ", got: " + offset); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] correct offset: " + offset); +*/ + } + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Unexpected Exception occurred: " + e); + } + } + + /* Error case 2 + * using DateFormat.parse(String) + */ + boolean correctParseException = false; + for (int k=0; k < invalids.length; k++) { + try { + date = sdf.parse((String)invalids[k][0]); + } + catch (ParseException e) { + correctParseException = true; + int offset = e.getErrorOffset(); + if (offset != ((Integer)invalids[k][1]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception occurred with an incorrect offset. expected:" + + invalids[k][1] + ", got: " + offset); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception occurred with an correct offset: " + + offset); +*/ + } + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Invalid exception occurred: " + e); + } + finally { + if (!correctParseException) { + err = true; + System.err.println("\tParse Error: [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception didn't occur."); + } + } + } + } + } + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + if (err) { + errln("SimpleDateFormat.parse()/format() test failed"); + } + } + } + + public static void main(String[] args) throws Exception { + new Bug4322313().run(args); + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4407042.java b/jdk/test/java/text/Format/DateFormat/Bug4407042.java new file mode 100644 index 00000000000..8cc557e5a97 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4407042.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4407042 + * @summary Make sure that cloned SimpleDateFormat objects work + * independently in multiple threads. + * @run main Bug4407042 10 + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +// Usage: java Bug4407042 [duration] +public class Bug4407042 { + + static final String TIME_STRING = "2000/11/18 00:01:00"; + static final long UTC_LONG = 974534460000L; + static SimpleDateFormat masterFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + static boolean runrun = true; + static int duration = 100; + + void test() { + Locale locale = Locale.getDefault(); + if (locale.equals(new Locale("th", "TH")) || + locale.equals(new Locale("hi", "IN"))) { + return; + } + + masterFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); + DateParseThread d1 = new DateParseThread(); + DateFormatThread d2 = new DateFormatThread(); + d1.start(); + d2.start(); + int n = Thread.activeCount(); + boolean failed = false; + + for (int i = 0; i < duration; i++) { + try { + Thread.sleep(1000); + if (Thread.activeCount() != n) { + failed = true; + break; + } + } catch (InterruptedException e) { + } + } + runrun = false; + try { + d1.join(); + d2.join(); + } catch (InterruptedException e) { + } + if (failed) { + throw new RuntimeException("Failed"); + } + } + + synchronized static SimpleDateFormat getFormatter() { + return (SimpleDateFormat) masterFormat.clone(); + } + + static class DateParseThread extends Thread { + public void run() { + SimpleDateFormat sdf = getFormatter(); + Calendar cal = null; + + try { + int i = 0; + while (runrun) { + Date date =sdf.parse(TIME_STRING); + long t = date.getTime(); + i++; + if (t != UTC_LONG) { + throw new RuntimeException("Parse Error: " + i + + " (" + sdf.format(date) + ") " + t + + " != " + UTC_LONG); + } + } + } catch (ParseException e) { + e.printStackTrace(); + throw new RuntimeException("Parse Error"); + } + } + } + + static class DateFormatThread extends Thread { + public void run () { + SimpleDateFormat sdf = getFormatter(); + Calendar cal = null; + + int i = 0; + while (runrun) { + i++; + String s = sdf.format(new Date(UTC_LONG)); + if (!s.equals(TIME_STRING)) { + throw new RuntimeException("Format Error: " + i + " " + + s + " != " + TIME_STRING); + } + } + } + } + + public static void main (String[] args) { + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + new Bug4407042().test(); + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4736959.java b/jdk/test/java/text/Format/DateFormat/Bug4736959.java new file mode 100644 index 00000000000..cdb9cad20b4 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4736959.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4736959 + * @summary Make sure to parse "PM" (only) and produce the correct value. + */ + +import java.text.*; +import java.util.*; + +public class Bug4736959 { + /** + * 4736959: JSpinner won't work for AM/PM field + */ + public static void main(String[] args) { + SimpleDateFormat f = new SimpleDateFormat("a", Locale.US); + + Date d1 = f.parse("AM", new ParsePosition(0)); + System.out.println("d1: " + d1); + if (d1.getHours() != 0) { + throw new RuntimeException("Parsing \"AM\": expected 0 (midnight), got " + + d1.getHours()); + } + Date d2 = f.parse("PM", new ParsePosition(0)); + System.out.println("d2: " + d2); + if (d2.getHours() != 12) { + throw new RuntimeException("Parsing \"PM\": expected 12 (noon), got " + + d2.getHours()); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4845901.java b/jdk/test/java/text/Format/DateFormat/Bug4845901.java new file mode 100644 index 00000000000..8ed8bd47648 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4845901.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4845901 + * @summary Make sure that SimpleDateFormat.parse() can distinguish + * the same time zone abbreviation for standard and daylight saving + * time. + */ + +import java.util.*; +import java.text.SimpleDateFormat; + +public class Bug4845901 { + public static void main (String args[]) { + TimeZone savedTZ = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney")); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS z"); + try { + testParse(sdf, "2003.01.13 11:10:00.802 AEDT", 11); + testParse(sdf, "2003.06.12 11:10:00.802 AEST", 11); + testParse(sdf, "2004.12.24 10:10:00.002 AEDT", 10); + testParse(sdf, "2004.08.10 10:10:00.002 AEST", 10); + } finally { + TimeZone.setDefault(savedTZ); + } + } + + static void testParse(SimpleDateFormat sdf, String str, int expectedHour) { + try { + Date parsedDate = sdf.parse(str); + if (parsedDate.getHours() != expectedHour) { + throw new RuntimeException( + "parsed date has wrong hour: " + parsedDate.getHours() + + ", expected: " + expectedHour + + "\ngiven string: " + str + + "\nparsedDate = " + parsedDate); + } + } catch (java.text.ParseException e) { + throw new RuntimeException("parse exception", e); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug6251817.java b/jdk/test/java/text/Format/DateFormat/Bug6251817.java new file mode 100644 index 00000000000..b0dd7fc9c2c --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6251817.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6251817 + * @summary Confirm that a typo was corrected. + */ + +import java.text.*; +import java.util.*; + +public class Bug6251817 { + + public static void main(String[] args) { + SimpleDateFormat sdf = new SimpleDateFormat("zzzz", Locale.US); + sdf.setTimeZone(TimeZone.getTimeZone("Australia/Lord_Howe")); + String got = sdf.format(new Date()); + + if (!got.equals("Lord Howe Standard Time") && + !got.equals("Lord Howe Daylight Time")) { + throw new RuntimeException("Timezone display name for Australia/Lord_Howe is incorrect. Got:" + got); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug6335238.java b/jdk/test/java/text/Format/DateFormat/Bug6335238.java new file mode 100644 index 00000000000..201a1af8f99 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6335238.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 1.1 06/01/24 + * @bug 6335238 + * @summary Make sure that both the original and cloned SimpleDateFormat coexistindependently and don't cut off each other. + * @run main Bug6335238 10 + */ + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +// Usage: java Bug6335238 [duration] +public class Bug6335238 { + + static final long UTC_LONG = 974534460000L; + static final String TIME_STRING = "2000/11/18 00:01:00"; + static SimpleDateFormat masterSdf; + static int duration = 180; + static boolean stopped = false; + static boolean err = false; + + public static void main(String[] args) { + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + + TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific")); + Locale.setDefault(Locale.US); + + masterSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + + try { + // Once it is used, DecimalFormat becomes not thread-safe. + Date d = masterSdf.parse(TIME_STRING); + + new Bug6335238(); + } catch (Exception e) { + System.err.println(e); + err = true; + } finally { + TimeZone.setDefault(savedTimeZone); + Locale.setDefault(savedLocale); + + if (err) { + throw new RuntimeException("Failed: Multiple DateFormat instances didn't work correctly."); + } else { + System.out.println("Passed."); + } + } + } + + public Bug6335238() { + stopped = false; + + DateParseThread d1 = new DateParseThread(); + DateFormatThread d2 = new DateFormatThread(); + DateParseThread d3 = new DateParseThread(); + DateFormatThread d4 = new DateFormatThread(); + + d1.start(); + d2.start(); + d3.start(); + d4.start(); + + try { + Thread.sleep(duration * 1000); + } + catch (Exception e) { + System.err.println(e); + err = true; + } + + stopped = true; + } + + class DateFormatThread extends Thread { + + public void run() { + int i = 0; + + while (!stopped) { + SimpleDateFormat sdf; + synchronized (masterSdf) { + sdf = (SimpleDateFormat)masterSdf.clone(); + } + + i++; + String s = sdf.format(new Date(UTC_LONG)); + + if (!s.equals(TIME_STRING)) { + stopped = true; + err = true; + + throw new RuntimeException("Formatting Date Error: counter=" + + i + ", Got<" + s + "> != Expected<" + TIME_STRING + ">"); + } + } + } + } + + class DateParseThread extends Thread { + + public void run() { + int i = 0; + + while (!stopped) { + SimpleDateFormat sdf; + synchronized (masterSdf) { + sdf = (SimpleDateFormat)masterSdf.clone(); + } + + i++; + Date date; + try { + date = sdf.parse(TIME_STRING); + long t = date.getTime(); + + if (t != UTC_LONG) { + stopped = true; + err = true; + + throw new RuntimeException("Parsing Date Error: counter=" + + i + " Got:" + t + "<" + sdf.format(date) + + "> != " + UTC_LONG); + } + } + catch (ParseException e) { + stopped = true; + err = true; + + throw new RuntimeException(e); + } + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug6530336.java b/jdk/test/java/text/Format/DateFormat/Bug6530336.java new file mode 100644 index 00000000000..d01a96aba9e --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6530336.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6530336 6537997 8008577 + * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug6530336 + */ + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class Bug6530336 { + + public static void main(String[] args) throws Exception { + Locale defaultLocale = Locale.getDefault(); + TimeZone defaultTimeZone = TimeZone.getDefault(); + + boolean err = false; + + try { + Locale locales[] = Locale.getAvailableLocales(); + Locale locale_Japan = new Locale("ja", "JP", "JP"); + TimeZone timezone_LA = TimeZone.getTimeZone("America/Los_Angeles"); + TimeZone.setDefault(timezone_LA); + + TimeZone timezones[] = { + TimeZone.getTimeZone("America/New_York"), + TimeZone.getTimeZone("America/Denver"), + }; + + String[] expected = { + "Sun Jul 15 12:00:00 PDT 2007", + "Sun Jul 15 14:00:00 PDT 2007", + }; + + Date[] dates = new Date[2]; + + for (int i = 0; i < locales.length; i++) { + if (locales[i].getLanguage().equals("th") || + locales[i].equals(locale_Japan)) { + continue; + } + + Locale.setDefault(locales[i]); + + for (int j = 0; j < timezones.length; j++) { + Calendar cal = Calendar.getInstance(timezones[j]); + cal.set(2007, 6, 15, 15, 0, 0); + dates[j] = cal.getTime(); + } + + SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); + + for (int j = 0; j < timezones.length; j++) { + sdf.setTimeZone(timezones[j]); + String date = sdf.format(dates[j]); + sdf.setTimeZone(timezone_LA); + String date_LA = sdf.parse(date).toString(); + + if (!expected[j].equals(date_LA)) { + System.err.println("Got wrong Pacific time (" + + date_LA + ") for (" + date + ") in " + locales[i] + + " in " + timezones[j] + + ".\nExpected=" + expected[j]); + err = true; + } + } + } + } + catch (Exception e) { + e.printStackTrace(); + err = true; + } + finally { + Locale.setDefault(defaultLocale); + TimeZone.setDefault(defaultTimeZone); + + if (err) { + throw new RuntimeException("Failed."); + } + } + } + +} diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java b/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java new file mode 100644 index 00000000000..d276aac088b --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java @@ -0,0 +1,1098 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.text.*; +import java.util.*; +import java.io.*; + +/** + * @test + * @bug 4029195 4052408 4056591 4059917 4060212 4061287 4065240 4071441 4073003 + * 4089106 4100302 4101483 4103340 4103341 4104136 4104522 4106807 4108407 + * 4134203 4138203 4148168 4151631 4151706 4153860 4162071 4182066 4209272 4210209 + * 4213086 4250359 4253490 4266432 4406615 4413980 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRegression + */ +public class DateFormatRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new DateFormatRegression().run(args); + } + + public void Test4029195() { + + Date today = new Date(); + + logln("today: " + today); + + SimpleDateFormat sdf = (SimpleDateFormat)SimpleDateFormat.getDateInstance(); + logln("pattern: " + sdf.toPattern()); + logln("today: " + sdf.format(today)); + + sdf.applyPattern("G yyyy DDD"); + String todayS = sdf.format(today); + logln("today: " + todayS); + try { + today = sdf.parse(todayS); + logln("today date: " + today); + } catch(Exception e) { + logln("Error reparsing date: " + e.getMessage()); + } + + try { + String rt = sdf.format(sdf.parse(todayS)); + logln("round trip: " + rt); + if (!rt.equals(todayS)) errln("Fail: Want " + todayS + " Got " + rt); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4052408() { + + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, + DateFormat.SHORT, Locale.US); + Date date = new Date(97, Calendar.MAY, 3, 8, 55); + String str; + logln(str = fmt.format(date)); + + if (!str.equals("5/3/97 8:55 AM")) + errln("Fail: Test broken; Want 5/3/97 8:55 AM Got " + str); + Hashtable expected = new Hashtable(); + expected.put(new Integer(DateFormat.MONTH_FIELD), "5"); + expected.put(new Integer(DateFormat.DATE_FIELD), "3"); + expected.put(new Integer(DateFormat.YEAR_FIELD), "97"); + expected.put(new Integer(DateFormat.HOUR1_FIELD), "8"); + expected.put(new Integer(DateFormat.MINUTE_FIELD), "55"); + expected.put(new Integer(DateFormat.AM_PM_FIELD), "AM"); + + StringBuffer buf = new StringBuffer(); + String fieldNames[] = { + "ERA_FIELD", + "YEAR_FIELD", + "MONTH_FIELD", + "DATE_FIELD", + "HOUR_OF_DAY1_FIELD", + "HOUR_OF_DAY0_FIELD", + "MINUTE_FIELD", + "SECOND_FIELD", + "MILLISECOND_FIELD", + "DAY_OF_WEEK_FIELD", + "DAY_OF_YEAR_FIELD", + "DAY_OF_WEEK_IN_MONTH_FIELD", + "WEEK_OF_YEAR_FIELD", + "WEEK_OF_MONTH_FIELD", + "AM_PM_FIELD", + "HOUR1_FIELD", + "HOUR0_FIELD", + "TIMEZONE_FIELD", + }; + boolean pass = true; + for (int i=0; i<=17; ++i) { + FieldPosition pos = new FieldPosition(i); + fmt.format(date, buf, pos); + char[] dst = new char[pos.getEndIndex() - pos.getBeginIndex()]; + buf.getChars(pos.getBeginIndex(), pos.getEndIndex(), dst, 0); + str = new String(dst); + log(i + ": " + fieldNames[i] + + ", \"" + str + "\", " + + pos.getBeginIndex() + ", " + + pos.getEndIndex()); + String exp = (String) expected.get(new Integer(i)); + if ((exp == null && str.length() == 0) || + str.equals(exp)) + logln(" ok"); + else { + logln(" expected " + exp); + pass = false; + } + } + if (!pass) errln("Fail: FieldPosition not set right by DateFormat"); + } + + /** + * Verify the function of the [s|g]et2DigitYearStart() API. + */ + public void Test4056591() { + try { + SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd", Locale.US); + Date start = new Date(1809-1900, Calendar.DECEMBER, 25); + fmt.set2DigitYearStart(start); + if (!fmt.get2DigitYearStart().equals(start)) + errln("get2DigitYearStart broken"); + Object[] DATA = { + "091225", new Date(1809-1900, Calendar.DECEMBER, 25), + "091224", new Date(1909-1900, Calendar.DECEMBER, 24), + "091226", new Date(1809-1900, Calendar.DECEMBER, 26), + "611225", new Date(1861-1900, Calendar.DECEMBER, 25), + }; + for (int i=0; i " + got + "; exp " + exp); + if (!got.equals(exp)) errln("set2DigitYearStart broken"); + } + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4059917() { + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + SimpleDateFormat fmt; + String myDate; + + fmt = new SimpleDateFormat( "yyyy/MM/dd" ); + myDate = "1997/01/01"; + aux917( fmt, myDate ); + + fmt = new SimpleDateFormat( "yyyyMMdd" ); + myDate = "19970101"; + aux917( fmt, myDate ); + } + + void aux917( SimpleDateFormat fmt, String str ) { + try { + logln( "==================" ); + logln( "testIt: pattern=" + fmt.toPattern() + + " string=" + str ); + + Object o; + o = fmt.parseObject( str ); + logln( "Parsed object: " + o ); + + String formatted = fmt.format( o ); + logln( "Formatted string: " + formatted ); + if (!formatted.equals(str)) errln("Fail: Want " + str + " Got " + formatted); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4060212() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + String dateString = "1995-040.05:01:29"; + + logln( "dateString= " + dateString ); + logln("Using yyyy-DDD.hh:mm:ss"); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-DDD.hh:mm:ss"); + ParsePosition pos = new ParsePosition(0); + Date myDate = formatter.parse( dateString, pos ); + String myString = DateFormat.getDateTimeInstance( DateFormat.FULL, + DateFormat.LONG).format( myDate ); + logln( myString ); + Calendar cal = new GregorianCalendar(); + cal.setTime(myDate); + if (cal.get(Calendar.DAY_OF_YEAR) != 40) + errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + + " Want 40"); + + logln("Using yyyy-ddd.hh:mm:ss"); + formatter = new SimpleDateFormat("yyyy-ddd.hh:mm:ss"); + pos = new ParsePosition(0); + myDate = formatter.parse( dateString, pos ); + myString = DateFormat.getDateTimeInstance( DateFormat.FULL, + DateFormat.LONG).format( myDate ); + logln( myString ); + cal.setTime(myDate); + if (cal.get(Calendar.DAY_OF_YEAR) != 40) + errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + + " Want 40"); + } + finally { + Locale.setDefault(savedLocale); + } + } + + public void Test4061287() { + SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy"); + try { + logln(df.parse("35/01/1971").toString()); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + df.setLenient(false); + boolean ok = false; + try { + logln(df.parse("35/01/1971").toString()); + } catch (ParseException e) {ok=true;} + if (!ok) errln("Fail: Lenient not working"); + } + + public void Test4065240() { + Date curDate; + DateFormat shortdate, fulldate; + String strShortDate, strFullDate; + Locale saveLocale = Locale.getDefault(); + TimeZone saveZone = TimeZone.getDefault(); + try { + Locale curLocale = new Locale("de","DE"); + Locale.setDefault(curLocale); + TimeZone.setDefault(TimeZone.getTimeZone("EST")); + curDate = new Date(98, 0, 1); + shortdate = DateFormat.getDateInstance(DateFormat.SHORT); + fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG + ); + strShortDate = new String("The current date (short form) is " + shortdate. + format(curDate)); + strFullDate = new String("The current date (long form) is " + fulldate.format(curDate)); + + logln(strShortDate); + logln(strFullDate); + + // UPDATE THIS AS ZONE NAME RESOURCE FOR in de_DE is updated + if (!strFullDate.endsWith("EST") + && !strFullDate.endsWith("GMT-05:00")) { + errln("Fail: Want GMT-05:00"); + } + } + finally { + Locale.setDefault(saveLocale); + TimeZone.setDefault(saveZone); + } + } + + /* + DateFormat.equals is too narrowly defined. As a result, MessageFormat + does not work correctly. DateFormat.equals needs to be written so + that the Calendar sub-object is not compared using Calendar.equals, + but rather compared for equivalency. This may necessitate adding a + (package private) method to Calendar to test for equivalency. + + Currently this bug breaks MessageFormat.toPattern + */ + public void Test4071441() { + DateFormat fmtA = DateFormat.getInstance(); + DateFormat fmtB = DateFormat.getInstance(); + Calendar calA = fmtA.getCalendar(); + Calendar calB = fmtB.getCalendar(); + Date epoch = new Date(0); + Date xmas = new Date(61, Calendar.DECEMBER, 25); + calA.setTime(epoch); + calB.setTime(epoch); + if (!calA.equals(calB)) + errln("Fail: Can't complete test; Calendar instances unequal"); + if (!fmtA.equals(fmtB)) + errln("Fail: DateFormat unequal when Calendars equal"); + calB.setTime(xmas); + if (calA.equals(calB)) + errln("Fail: Can't complete test; Calendar instances equal"); + if (!fmtA.equals(fmtB)) + errln("Fail: DateFormat unequal when Calendars equivalent"); + logln("DateFormat.equals ok"); + } + + /* The java.text.DateFormat.parse(String) method expects for the + US locale a string formatted according to mm/dd/yy and parses it + correctly. + + When given a string mm/dd/yyyy it only parses up to the first + two y's, typically resulting in a date in the year 1919. + + Please extend the parsing method(s) to handle strings with + four-digit year values (probably also applicable to various + other locales. */ + public void Test4073003() { + try { + DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); + String[] tests = { "12/25/61", "12/25/1961", "4/3/2010", "4/3/10" }; + for (int i=0; i is incorrectly serialized/deserialized."); + } else { + logln("DateFormat instance which uses TimeZone <" + + IDs[i] + "> is correctly serialized/deserialized."); + } + } + if (!pass) { + errln("Fail: DateFormat serialization/equality bug"); + } + } + catch (IOException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + catch (ClassNotFoundException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + finally { + TimeZone.setDefault(savedTimeZone); + } + } + + public void Test4101483() { + SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.US); + FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD); + Date d= new Date(9234567890L); + StringBuffer buf = new StringBuffer(""); + logln(sdf.format(d, buf, fp).toString()); + logln(d + " => " + buf); + logln("beginIndex = " + fp.getBeginIndex()); + logln("endIndex = " + fp.getEndIndex()); + if (fp.getBeginIndex() == fp.getEndIndex()) errln("Fail: Empty field"); + } + + /** + * Bug 4103340 + * Bug 4138203 + * This bug really only works in Locale.US, since that's what the locale + * used for Date.toString() is. Bug 4138203 reports that it fails on Korean + * NT; it would actually have failed on any non-US locale. Now it should + * work on all locales. + */ + public void Test4103340() { + // choose a date that is the FIRST of some month + // and some arbitrary time + Date d=new Date(97, 3, 1, 1, 1, 1); + SimpleDateFormat df=new SimpleDateFormat("MMMM", Locale.US); + + String s = d.toString(); + String s2 = df.format(d); + logln("Date="+s); + logln("DF="+s2); + if (s.indexOf(s2.substring(0,2)) == -1) + errln("Months should match"); + } + + public void Test4103341() { + TimeZone saveZone =TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("CST")); + SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + if (!simple.getTimeZone().equals(TimeZone.getDefault())) + errln("Fail: SimpleDateFormat not using default zone"); + } + finally { + TimeZone.setDefault(saveZone); + } + } + + public void Test4104136() { + SimpleDateFormat sdf = new SimpleDateFormat(); + String pattern = "'time' hh:mm"; + sdf.applyPattern(pattern); + logln("pattern: \"" + pattern + "\""); + + Object[] DATA = { + "time 10:30", new ParsePosition(10), new Date(70, Calendar.JANUARY, 1, 10, 30), + "time 10:x", new ParsePosition(0), null, + "time 10x", new ParsePosition(0), null, + }; + for (int i=0; i \"" + + str + "\", exp \"" + OUT[i] + '"'); + } + } + + // Test parsing + fmt.applyPattern("s.S"); + String[] IN = { "1.4", "1.04", "1.004", "1.45", "1.456", + "1.4567", "1.45678" }; + int[] MS = { 4, 4, 4, 45, 456, 567, 678 }; + for (int i=0; i " + + ms + " ms, exp " + MS[i] + " ms"); + } + } + } + + /** + * SimpleDateFormat incorrect handling of 2 single quotes in format() + */ + public void Test4151631() { + String pattern = "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'"; + logln("pattern=" + pattern); + SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US); + String result = format.format(new Date(1998-1900, Calendar.JUNE, 30, 13, 30, 0)); + if (!result.equals("TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')")) { + errln("Fail: result=" + result); + } + else { + logln("Pass: result=" + result); + } + } + + /** + * 'z' at end of date format throws index exception in SimpleDateFormat + * CANNOT REPRODUCE THIS BUG ON 1.2FCS + */ + public void Test4151706() { + SimpleDateFormat fmt = + new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss z", Locale.US); + try { + Date d = fmt.parse("Thursday, 31-Dec-98 23:00:00 GMT"); + if (d.getTime() != Date.UTC(1998-1900, Calendar.DECEMBER, 31, 23, 0, 0)) + errln("Incorrect value: " + d); + } catch (Exception e) { + errln("Fail: " + e); + } + } + + /** + * SimpleDateFormat fails to parse redundant data. + * This is actually a bug down in GregorianCalendar, but it was reported + * as follows... + */ + public void Test4153860() throws ParseException { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + SimpleDateFormat sf = (SimpleDateFormat)DateFormat.getDateTimeInstance(); + // Set the pattern + sf.applyPattern("yyyy.MM-dd"); + // Try to create a Date for February 4th + Date d1 = sf.parse("1998.02-04"); + // Set the pattern, this time to use the W value + sf.applyPattern("yyyy.MM-dd W"); + // Try to create a Date for February 4th + Date d2 = sf.parse("1998.02-04 1"); + if (!d1.equals(d2)) { + errln("Parse failed, got " + d2 + + ", expected " + d1); + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + /** + * Confirm that "EST"(GMT-5:00) and "CST"(GMT-6:00) are used in US + * as "EST" or "CST", not Australian "EST" and "CST". + */ + public void Test4406615() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + Date d1, d2; + String dt = "Mon, 1 Jan 2001 00:00:00"; + SimpleDateFormat sdf = + new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); + + try { + d1 = sdf.parse(dt+" EST"); + d2 = sdf.parse(dt+" CST"); + + if (d1.getYear() != (2000-1900) || d1.getMonth() != 11 || + d1.getDate() != 31 || d1.getHours() != 21 || d1.getMinutes() != 0 || + d2.getYear() != (2000-1900) || d2.getMonth() != 11 || + d2.getDate() != 31 || d2.getHours() != 22 || d2.getMinutes() != 0) { + errln("Parse failed, d1 = " + d1 + ", d2 = " + d2); + } else { + logln("Parse passed"); + } + } + catch (Exception e) { + errln("Parse failed, got Exception " + e); + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + } + + /** + * Cannot reproduce this bug under 1.2 FCS -- it may be a convoluted duplicate + * of some other bug that has been fixed. + */ + public void Test4162071() { + String dateString = "Thu, 30-Jul-1999 11:51:14 GMT"; + String format = "EEE', 'dd-MMM-yyyy HH:mm:ss z"; // RFC 822/1123 + SimpleDateFormat df = new + SimpleDateFormat(format, Locale.US); + + try { + Date x = df.parse(dateString); + logln("Parse format \"" + format + "\" ok"); + logln(dateString + " -> " + df.format(x)); + } catch (Exception e) { + errln("Parse format \"" + format + "\" failed."); + } + } + + /** + * DateFormat shouldn't parse year "-1" as a two-digit year (e.g., "-1" -> 1999). + */ + public void Test4182066() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy", + DateFormatSymbols.getInstance(Locale.US)); + SimpleDateFormat dispFmt = new SimpleDateFormat("MMM dd yyyy GG", + DateFormatSymbols.getInstance(Locale.US)); + /* We expect 2-digit year formats to put 2-digit years in the right + * window. Out of range years, that is, anything less than "00" or + * greater than "99", are treated as literal years. So "1/2/3456" + * becomes 3456 AD. Likewise, "1/2/-3" becomes -3 AD == 2 BC. + */ + Object[] DATA = { + "02/29/00", new Date(2000-1900, Calendar.FEBRUARY, 29), + "01/23/01", new Date(2001-1900, Calendar.JANUARY, 23), + "04/05/-1", new Date( -1-1900, Calendar.APRIL, 5), + "01/23/-9", new Date( -9-1900, Calendar.JANUARY, 23), + "11/12/1314", new Date(1314-1900, Calendar.NOVEMBER, 12), + "10/31/1", new Date( 1-1900, Calendar.OCTOBER, 31), + "09/12/+1", null, // "+1" isn't recognized by US NumberFormat + "09/12/001", new Date( 1-1900, Calendar.SEPTEMBER,12), + }; + StringBuffer out = new StringBuffer(); + boolean pass = true; + for (int i=0; i " + actStr + "\n"); + } else { + String expStr = expected != null + ? dispFmt.format(expected) : String.valueOf(expected); + out.append("FAIL: " + str + " => " + actStr + + ", expected " + expStr + "\n"); + pass = false; + } + } + if (pass) { + log(out.toString()); + } else { + err(out.toString()); + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + /** + * Bug 4210209 + * Bug 4209272 + * DateFormat cannot parse Feb 29 2000 when setLenient(false) + */ + public void Test4210209() { + String pattern = "MMM d, yyyy"; + DateFormat fmt = new SimpleDateFormat(pattern, + DateFormatSymbols.getInstance(Locale.US)); + fmt.getCalendar().setLenient(false); + Date d = new Date(2000-1900, Calendar.FEBRUARY, 29); + String s = fmt.format(d); + logln(d + " x " + pattern + " => " + s); + ParsePosition pos = new ParsePosition(0); + d = fmt.parse(s, pos); + logln(d + " <= " + pattern + " x " + s); + logln("Parse pos = " + pos); + if (pos.getErrorIndex() != -1) { + errln("FAIL"); + } + + // The underlying bug is in GregorianCalendar. If the following lines + // succeed, the bug is fixed. If the bug isn't fixed, they will throw + // an exception. + GregorianCalendar cal = new GregorianCalendar(); + cal.clear(); + cal.setLenient(false); + cal.set(2000, Calendar.FEBRUARY, 29); // This should work! + logln(cal.getTime().toString()); + } + + /** + * DateFormat.getDateTimeInstance() allows illegal parameters. + */ + public void Test4213086() { + int[] DATA = { + // Style value, 0/1 for illegal/legal + -99, 0, + -1, 0, + 0, 1, + 1, 1, + 2, 1, + 3, 1, + 4, 0, + 99, 0, + }; + String[] DESC = { + "getDateTimeInstance(date)", + "getDateTimeInstance(time)", + "getDateInstance", + "getTimeInstance", + }; + String[] GOT = { + "disallowed", "allowed", "" + }; + for (int i=0; i \"" + s + '"'); + } else { + errln("FAIL: " + FORMAT_MS + " ms f* \"" + + FORMAT_PAT[i] + "\" -> \"" + s + "\", expect \"" + + FORMAT_TO[i] + '"'); + } + } + + // Test parsing. We want to make sure all digits are read. + fmt.applyPattern(PARSE_PAT); + for (int i=0; i " + ms + " ms"); + } else { + errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + + PARSE_PAT + "\" -> " + ms + " ms, expect " + + PARSE_TO[i] + " ms"); + } + } + + // Test LONG parsing. We want to make sure all digits are read. + fmt.applyPattern(PARSE_LPAT); + for (int i=0; i " + ms + " ms"); + } else { + errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + + PARSE_LPAT + "\" -> " + ms + " ms, expect " + + PARSE_TO[i] + " ms"); + } + } + } + + /** + * Bug in handling of time instance; introduces in fix for 4213086. + */ + public void Test4250359() { + DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT, + Locale.US); + Date d = new Date(1999-1900, Calendar.DECEMBER, 25, + 1, 2, 3); + String s = df.format(d); + // If the bug is present, we see "1:02 AM 1:02 AM". + // Look for more than one instance of "AM". + int i = s.indexOf("AM"); + int j = s.indexOf("AM", i+1); + if (i < 0 || j >= 0) { + errln("FAIL: getTimeInstance().format(d) => \"" + + s + "\""); + } + } + + /** + * Test whether SimpleDataFormat (DateFormatSymbols) can format/parse + * non-localized time zones. + */ + public void Test4261506() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + Locale.setDefault(Locale.JAPAN); + + // XXX: Test assumes "PST" is not TimeZoneNames_ja. Need to + // pick up another time zone when L10N is done to that file. + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN); + String result = fmt.format(new Date(1999, 0, 1)); + logln("format()=>" + result); + if (!result.endsWith("PST")) { + errln("FAIL: SimpleDataFormat.format() did not retrun PST"); + } + + Date d = null; + try { + d = fmt.parse("99/1/1 10:10 PST"); + } catch (ParseException e) { + errln("FAIL: SimpleDataFormat.parse() could not parse PST"); + } + + result = fmt.format(d); + logln("roundtrip:" + result); + if (!result.equals("99/01/01 10:10 PST")) { + errln("FAIL: SimpleDataFomat timezone roundtrip failed"); + } + + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + +} + +//eof diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java b/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java new file mode 100644 index 00000000000..73d023163f1 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java @@ -0,0 +1,727 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary test Date Format (Round Trip) + * @bug 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRoundTripTest + */ + +import java.text.*; +import java.util.*; + +public class DateFormatRoundTripTest extends IntlTest { + + static Random RANDOM = null; + + static final long FIXED_SEED = 3141592653589793238L; // Arbitrary fixed value + + // Useful for turning up subtle bugs: Use -infinite and run while at lunch. + boolean INFINITE = false; // Warning -- makes test run infinite loop!!! + + boolean random = false; + + // Options used to reproduce failures + Locale locale = null; + String pattern = null; + Date initialDate = null; + + Locale[] avail; + TimeZone defaultZone; + + // If SPARSENESS is > 0, we don't run each exhaustive possibility. + // There are 24 total possible tests per each locale. A SPARSENESS + // of 12 means we run half of them. A SPARSENESS of 23 means we run + // 1 of them. SPARSENESS _must_ be in the range 0..23. + static final int SPARSENESS = 18; + + static final int TRIALS = 4; + + static final int DEPTH = 5; + + static SimpleDateFormat refFormat = + new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); + + public DateFormatRoundTripTest(boolean rand, long seed, boolean infinite, + Date date, String pat, Locale loc) { + random = rand; + if (random) { + RANDOM = new Random(seed); + } + INFINITE = infinite; + + initialDate = date; + locale = loc; + pattern = pat; + } + + /** + * Parse a name like "fr_FR" into new Locale("fr", "FR", ""); + */ + static Locale createLocale(String name) { + String country = "", + variant = ""; + int i; + if ((i = name.indexOf('_')) >= 0) { + country = name.substring(i+1); + name = name.substring(0, i); + } + if ((i = country.indexOf('_')) >= 0) { + variant = country.substring(i+1); + country = country.substring(0, i); + } + return new Locale(name, country, variant); + } + + public static void main(String[] args) throws Exception { + // Command-line parameters + Locale loc = null; + boolean infinite = false; + boolean random = false; + long seed = FIXED_SEED; + String pat = null; + Date date = null; + + Vector newArgs = new Vector(); + for (int i=0; i] [-locale ] [-date ] [-INFINITE]"); + System.out.println(" [-random | -randomseed | -seed ]"); + System.out.println("* Warning: Some patterns will fail with some locales."); + System.out.println("* Do not use -pattern unless you know what you are doing!"); + System.out.println("When specifying a locale, use a format such as fr_FR."); + System.out.println("Use -pattern, -locale, and -date to reproduce a failure."); + System.out.println("-random Random with fixed seed (same data every run)."); + System.out.println("-randomseed Random with a random seed."); + System.out.println("-seed Random using as seed."); + super.usage(); + } + + static private class TestCase { + private int[] date; + TimeZone zone; + FormatFactory ff; + boolean timeOnly; + private Date _date; + + TestCase(int[] d, TimeZone z, FormatFactory f, boolean timeOnly) { + date = d; + zone = z; + ff = f; + this.timeOnly = timeOnly; + } + + TestCase(Date d, TimeZone z, FormatFactory f, boolean timeOnly) { + date = null; + _date = d; + zone = z; + ff = f; + this.timeOnly = timeOnly; + } + + /** + * Create a format for testing. + */ + DateFormat createFormat() { + return ff.createFormat(); + } + + /** + * Return the Date of this test case; must be called with the default + * zone set to this TestCase's zone. + */ + Date getDate() { + if (_date == null) { + // Date constructor will work right iff we are in the target zone + int h = 0; + int m = 0; + int s = 0; + if (date.length >= 4) { + h = date[3]; + if (date.length >= 5) { + m = date[4]; + if (date.length >= 6) { + s = date[5]; + } + } + } + _date = new Date(date[0] - 1900, date[1] - 1, date[2], + h, m, s); + } + return _date; + } + + public String toString() { + return String.valueOf(getDate().getTime()) + " " + + refFormat.format(getDate()) + " : " + ff.createFormat().format(getDate()); + } + }; + + private interface FormatFactory { + DateFormat createFormat(); + } + + TestCase[] TESTS = { + // Feb 29 2004 -- ordinary leap day + new TestCase(new int[] {2004, 2, 29}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // Feb 29 2000 -- century leap day + new TestCase(new int[] {2000, 2, 29}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // 0:00:00 Jan 1 1999 -- first second of normal year + new TestCase(new int[] {1999, 1, 1}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 23:59:59 Dec 31 1999 -- last second of normal year + new TestCase(new int[] {1999, 12, 31, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 0:00:00 Jan 1 2004 -- first second of leap year + new TestCase(new int[] {2004, 1, 1}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 23:59:59 Dec 31 2004 -- last second of leap year + new TestCase(new int[] {2004, 12, 31, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // October 25, 1998 1:59:59 AM PDT -- just before DST cessation + new TestCase(new Date(909305999000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 25, 1998 1:00:00 AM PST -- just after DST cessation + new TestCase(new Date(909306000000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // April 4, 1999 1:59:59 AM PST -- just before DST onset + new TestCase(new int[] {1999, 4, 4, 1, 59, 59}, + TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // April 4, 1999 3:00:00 AM PDT -- just after DST onset + new TestCase(new Date(923220000000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 4, 1582 11:59:59 PM PDT -- just before Gregorian change + new TestCase(new int[] {1582, 10, 4, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 15, 1582 12:00:00 AM PDT -- just after Gregorian change + new TestCase(new int[] {1582, 10, 15, 0, 0, 0}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + }; + + public void TestDateFormatRoundTrip() { + avail = DateFormat.getAvailableLocales(); + logln("DateFormat available locales: " + avail.length); + logln("Default TimeZone: " + + (defaultZone = TimeZone.getDefault()).getID()); + + if (random || initialDate != null) { + if (RANDOM == null) { + // Need this for sparse coverage to reduce combinatorial explosion, + // even for non-random looped testing (i.e., with explicit date but + // not pattern or locale). + RANDOM = new Random(FIXED_SEED); + } + loopedTest(); + } else { + for (int i=0; i= 0 && random < 24 && TEST_TABLE[i]) { + TEST_TABLE[i] = false; + ++i; + } + } + } + + int itable = 0; + for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getDateInstance(style, loc)); + } + + for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getTimeInstance(style, loc), true); + } + + for (int dstyle=DateFormat.FULL; dstyle<=DateFormat.SHORT; ++dstyle) { + for (int tstyle=DateFormat.FULL; tstyle<=DateFormat.SHORT; ++tstyle) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getDateTimeInstance(dstyle, tstyle, loc)); + } + } + } + + void doTest(Locale loc, DateFormat fmt) { doTest(loc, fmt, false); } + + void doTest(Locale loc, DateFormat fmt, boolean timeOnly) { + doTest(loc, fmt, timeOnly, initialDate != null ? initialDate : generateDate()); + } + + void doTest(Locale loc, DateFormat fmt, boolean timeOnly, Date date) { + // Skip testing with the JapaneseImperialCalendar which + // doesn't support the Gregorian year semantices with 'y'. + if (fmt.getCalendar().getClass().getName().equals("java.util.JapaneseImperialCalendar")) { + return; + } + + String pat = ((SimpleDateFormat)fmt).toPattern(); + String deqPat = dequotePattern(pat); // Remove quoted elements + + boolean hasEra = (deqPat.indexOf("G") != -1); + boolean hasZone = (deqPat.indexOf("z") != -1); + + Calendar cal = fmt.getCalendar(); + + // Because patterns contain incomplete data representing the Date, + // we must be careful of how we do the roundtrip. We start with + // a randomly generated Date because they're easier to generate. + // From this we get a string. The string is our real starting point, + // because this string should parse the same way all the time. Note + // that it will not necessarily parse back to the original date because + // of incompleteness in patterns. For example, a time-only pattern won't + // parse back to the same date. + + try { + for (int i=0; i 0) d[loop] = fmt.parse(s[loop-1]); + s[loop] = fmt.format(d[loop]); + + if (loop > 0) { + if (smatch == 0) { + boolean match = s[loop].equals(s[loop-1]); + if (smatch == 0) { + if (match) smatch = loop; + } + else if (!match) { + // This should never happen; if it does, fail. + smatch = -1; + error = "FAIL: String mismatch after match"; + } + } + + if (dmatch == 0) { + boolean match = d[loop].getTime() == d[loop-1].getTime(); + if (dmatch == 0) { + if (match) dmatch = loop; + } + else if (!match) { + // This should never happen; if it does, fail. + dmatch = -1; + error = "FAIL: Date mismatch after match"; + } + } + + if (smatch != 0 && dmatch != 0) break; + } + } + // At this point loop == DEPTH if we've failed, otherwise loop is the + // max(smatch, dmatch), that is, the index at which we have string and + // date matching. + + // Date usually matches in 2. Exceptions handled below. + int maxDmatch = 2; + int maxSmatch = 1; + if (dmatch > maxDmatch) { + // Time-only pattern with zone information and a starting date in PST. + if (timeOnly && hasZone && fmt.getTimeZone().inDaylightTime(d[0])) { + maxDmatch = 3; + maxSmatch = 2; + } + } + + // String usually matches in 1. Exceptions are checked for here. + if (smatch > maxSmatch) { // Don't compute unless necessary + // Starts in BC, with no era in pattern + if (!hasEra && getField(cal, d[0], Calendar.ERA) == GregorianCalendar.BC) + maxSmatch = 2; + // Starts in DST, no year in pattern + else if (fmt.getTimeZone().inDaylightTime(d[0]) && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Two digit year with zone and year change and zone in pattern + else if (hasZone && + fmt.getTimeZone().inDaylightTime(d[0]) != + fmt.getTimeZone().inDaylightTime(d[dmatch]) && + getField(cal, d[0], Calendar.YEAR) != + getField(cal, d[dmatch], Calendar.YEAR) && + deqPat.indexOf("y") != -1 && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Two digit year, year change, DST changeover hour. Example: + // FAIL: Pattern: dd/MM/yy HH:mm:ss + // Date matched in 2, wanted 2 + // String matched in 2, wanted 1 + // Thu Apr 02 02:35:52.110 PST 1795 AD F> 02/04/95 02:35:52 + // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 + // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 d== s== + // The problem is that the initial time is not a DST onset day, but + // then the year changes, and the resultant parsed time IS a DST + // onset day. The hour "2:XX" makes no sense if 2:00 is the DST + // onset, so DateFormat interprets it as 1:XX (arbitrary -- could + // also be 3:XX, same problem). This results in an extra iteration + // for String match convergence. + else if (!justBeforeOnset(cal, d[0]) && justBeforeOnset(cal, d[dmatch]) && + getField(cal, d[0], Calendar.YEAR) != + getField(cal, d[dmatch], Calendar.YEAR) && + deqPat.indexOf("y") != -1 && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Another spurious failure: + // FAIL: Pattern: dd MMMM yyyy hh:mm:ss + // Date matched in 2, wanted 2 + // String matched in 2, wanted 1 + // Sun Apr 05 14:28:38.410 PDT 3998 AD F> 05 April 3998 02:28:38 + // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 + // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 d== s== + // The problem here is that with an 'hh' pattern, hour from 1-12, + // a lack of AM/PM -- that is, no 'a' in pattern, and an initial + // time in the onset hour + 12:00. + else if (deqPat.indexOf('h') >= 0 + && deqPat.indexOf('a') < 0 + && justBeforeOnset(cal, new Date(d[0].getTime() - 12*60*60*1000L)) + && justBeforeOnset(cal, d[1])) + maxSmatch = 2; + } + + if (dmatch > maxDmatch || smatch > maxSmatch + || dmatch < 0 || smatch < 0) { + StringBuffer out = new StringBuffer(); + if (error != null) { + out.append(error + '\n'); + } + out.append("FAIL: Pattern: " + pat + ", Locale: " + loc + '\n'); + out.append(" Initial date (ms): " + d[0].getTime() + '\n'); + out.append(" Date matched in " + dmatch + + ", wanted " + maxDmatch + '\n'); + out.append(" String matched in " + smatch + + ", wanted " + maxSmatch); + + for (int j=0; j<=loop && j0?" P> ":" ") + refFormat.format(d[j]) + " F> " + + escape(s[j]) + + (j>0&&d[j].getTime()==d[j-1].getTime()?" d==":"") + + (j>0&&s[j].equals(s[j-1])?" s==":"")); + } + errln(escape(out.toString())); + } + } + } + catch (ParseException e) { + errln(e.toString()); + } + } + + /** + * Return a field of the given date + */ + static int getField(Calendar cal, Date d, int f) { + // Should be synchronized, but we're single threaded so it's ok + cal.setTime(d); + return cal.get(f); + } + + /** + * Return true if the given Date is in the 1 hour window BEFORE the + * change from STD to DST for the given Calendar. + */ + static final boolean justBeforeOnset(Calendar cal, Date d) { + return nearOnset(cal, d, false); + } + + /** + * Return true if the given Date is in the 1 hour window AFTER the + * change from STD to DST for the given Calendar. + */ + static final boolean justAfterOnset(Calendar cal, Date d) { + return nearOnset(cal, d, true); + } + + /** + * Return true if the given Date is in the 1 hour (or whatever the + * DST savings is) window before or after the onset of DST. + */ + static boolean nearOnset(Calendar cal, Date d, boolean after) { + cal.setTime(d); + if ((cal.get(Calendar.DST_OFFSET) == 0) == after) { + return false; + } + int delta; + try { + delta = ((SimpleTimeZone) cal.getTimeZone()).getDSTSavings(); + } catch (ClassCastException e) { + delta = 60*60*1000; // One hour as ms + } + cal.setTime(new Date(d.getTime() + (after ? -delta : delta))); + return (cal.get(Calendar.DST_OFFSET) == 0) == after; + } + + static String escape(String s) { + StringBuffer buf = new StringBuffer(); + for (int i=0; i 0) { + try (FileOutputStream fos = + new FileOutputStream("SDFserialized.ser")) { + ObjectOutputStream oStream = new ObjectOutputStream(fos); + oStream.writeObject(sdf); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + try (InputStream is = + HexDumpReader.getStreamFromHexDump("SDFserialized.ser.txt")) { + ObjectInputStream iStream = new ObjectInputStream(is); + sdf1 = (SimpleDateFormat)iStream.readObject(); + } + + DateFormatSymbols dfs = sdf.getDateFormatSymbols(); + DateFormatSymbols dfs1 = sdf1.getDateFormatSymbols(); + System.out.println(sdf + "," + sdf.toPattern()); + System.out.println(sdf1 + "," + sdf1.toPattern()); + + // time zone display names should not be a part of this + // compatibility test. See 4112924 and 4282899. + dfs.setZoneStrings(dfs1.getZoneStrings()); + // localPatternChars should not be a part of this + // compatibility test. See 4322313. + dfs.setLocalPatternChars(dfs1.getLocalPatternChars()); + sdf.setDateFormatSymbols(dfs); + + // decimal format symbols should not be part of this + // compatibility test - old decimal format symbols get filled + // in with the root locale (4290801) + DecimalFormat df1 = (DecimalFormat) sdf1.getNumberFormat(); + df1.setDecimalFormatSymbols(df.getDecimalFormatSymbols()); + + if (!dfs.equals(dfs1)) { + err = true; + System.err.println( + "Error: serialized DateFormatSymbols is different"); + } + if (!sdf.equals(sdf1)) { + err = true; + System.err.println( + "Error: serialized SimpleDateFormat is different"); + } + if (err) { + throw new Exception("Serialization failed."); + } + } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatTest.java b/jdk/test/java/text/Format/DateFormat/DateFormatTest.java new file mode 100644 index 00000000000..c4f148f3d77 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatTest.java @@ -0,0 +1,1207 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571 + * @summary test DateFormat and SimpleDateFormat. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest + */ + +import java.util.*; +import java.text.*; +import static java.util.GregorianCalendar.*; + +public class DateFormatTest extends IntlTest +{ + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new DateFormatTest().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + // Test 4 digit year parsing with pattern "yy" + @SuppressWarnings("deprecation") + public void TestYearParsing() + { + String str = "7/Sep/2001"; + Date exp = new Date(2001-1900, SEPTEMBER, 7); + String pat = "d/MMM/yy"; + SimpleDateFormat sdf = new SimpleDateFormat(pat, Locale.US); + try { + Date d = sdf.parse(str); + logln(str + " parses with " + pat + " to " + d); + if (d.getTime() != exp.getTime()) { + errln("FAIL: Expected " + exp); + } + } + catch (ParseException e) { + errln(str + " parse fails with " + pat); + } + } + + // Test written by Wally Wedel and emailed to me. + public void TestWallyWedel() + { + /* + * Instantiate a TimeZone so we can get the ids. + */ + TimeZone tz = new SimpleTimeZone(7,""); + /* + * Computational variables. + */ + int offset, hours, minutes; + /* + * Instantiate a SimpleDateFormat set up to produce a full time + zone name. + */ + SimpleDateFormat sdf = new SimpleDateFormat("zzzz"); + /* + * A String array for the time zone ids. + */ + String[] ids = TimeZone.getAvailableIDs(); + /* + * How many ids do we have? + */ + logln("Time Zone IDs size: " + ids.length); + /* + * Column headings (sort of) + */ + logln("Ordinal ID offset(h:m) name"); + /* + * Loop through the tzs. + */ + Date today = new Date(); + Calendar cal = Calendar.getInstance(); + for (int i = 0; i < ids.length; i++) { + // logln(i + " " + ids[i]); + TimeZone ttz = TimeZone.getTimeZone(ids[i]); + // offset = ttz.getRawOffset(); + cal.setTimeZone(ttz); + cal.setTime(today); + offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); + // logln(i + " " + ids[i] + " offset " + offset); + char sign = '+'; + if (offset < 0) { sign = '-'; offset = -offset; } + hours = offset/3600000; + minutes = (offset%3600000)/60000; + String dstOffset = "" + sign + (hours < 10 ? "0" : "") + + hours + ':' + (minutes < 10 ? "0" : "") + minutes; + /* + * Instantiate a date so we can display the time zone name. + */ + sdf.setTimeZone(ttz); + /* + * Format the output. + */ + StringBuffer tzS = new StringBuffer(); + sdf.format(today,tzS, new FieldPosition(0)); + String fmtOffset = tzS.toString(); + String fmtDstOffset = null; + if (fmtOffset.startsWith("GMT")) + { + fmtDstOffset = fmtOffset.substring(3); + } + /* + * Show our result. + */ + boolean ok = fmtDstOffset == null || fmtDstOffset.equals(dstOffset); + if (ok) + { + logln(i + " " + ids[i] + " " + dstOffset + + " " + fmtOffset + + (fmtDstOffset != null ? " ok" : " ?")); + } + else + { + errln(i + " " + ids[i] + " " + dstOffset + + " " + fmtOffset + " *** FAIL ***"); + } + } + } + + // Test equals + public void TestEquals() + { + DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL); + + DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL); + + if (!fmtA.equals(fmtB)) { + errln("FAIL"); + } + } + + // Check out some specific parsing problem + @SuppressWarnings("deprecation") + public void TestTwoDigitYearDSTParse() + { + SimpleDateFormat fullFmt = + new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); + + //DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL, + // Locale.ENGLISH); + SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z", + Locale.ENGLISH); + //Date date = new Date(2004-1900, Calendar.APRIL, 3, 2, 20, 47); + //logln(fmt.format(date)); // This shows what the current locale format is + //logln(((SimpleDateFormat)fmt).toPattern()); + TimeZone save = TimeZone.getDefault(); + TimeZone PST = TimeZone.getTimeZone("PST"); + String s = "03-Apr-04 2:20:47 o'clock AM PST"; + int hour = 2; + try { + TimeZone.setDefault(PST); + Date d = fmt.parse(s); + logln(s + " P> " + fullFmt.format(d)); + if (d.getHours() != hour) { + errln("FAIL: Should parse to hour " + hour); + } + } + catch (ParseException e) { errln("FAIL: " + e.getMessage()); } + finally { + TimeZone.setDefault(save); + } + } + + static String escape(String s) + { + StringBuilder buf = new StringBuilder(); + for (int i=0; i> 12)); + buf.append(Integer.toHexString((c & 0x0F00) >> 8)); + buf.append(Integer.toHexString((c & 0x00F0) >> 4)); + buf.append(Integer.toHexString(c & 0x000F)); + } + } + return buf.toString(); + } + + // Test field position return values + static String fieldNames[] = { + "ERA_FIELD", "YEAR_FIELD", "MONTH_FIELD", + "WEEK_OF_YEAR_FIELD", "WEEK_OF_MONTH_FIELD", "DATE_FIELD", + "DAY_OF_YEAR_FIELD", "DAY_OF_WEEK_FIELD", "DAY_OF_WEEK_IN_MONTH_FIELD", + "AM_PM_FIELD", "HOUR0_FIELD", "HOUR1_FIELD", + "HOUR_OF_DAY0_FIELD", "HOUR_OF_DAY1_FIELD", + "MINUTE_FIELD", "SECOND_FIELD", + "MILLISECOND_FIELD", "TIMEZONE_FIELD", + }; + static int fieldIDs[] = { + DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD, + DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.DATE_FIELD, + DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, + DateFormat.AM_PM_FIELD, DateFormat.HOUR0_FIELD, DateFormat.HOUR1_FIELD, + DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.HOUR_OF_DAY1_FIELD, + DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD, + DateFormat.MILLISECOND_FIELD, DateFormat.TIMEZONE_FIELD, + }; + + /** + * Bug 4089987 + */ + public void TestFieldPosition() + { + DateFormat[] dateFormats = { + DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL, + Locale.US), + + DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.FRANCE), + new SimpleDateFormat("G, y, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"), + new SimpleDateFormat("G, yy, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"), + new SimpleDateFormat( "GGGG, yyyy, MMMM, dddd, kkkk, HHHH, mmmm, ssss, " + + "SSSS, EEEE, DDDD, " + + "FFFF, wwww, WWWW, aaaa, hhhh, KKKK, zzzz") + }; + String[] expected = + { + "", "1997", "August", "", "", "13", "", "Wednesday", "", + "PM", "", "2", "", "", "34", "12", "", "PDT", + + "", "1997", "ao\u00FBt", "", "", "13", "", "mercredi", "", "", + "", "", "14", "", "34", "", "", "PDT" /*"GMT-07:00"*/, + + "AD", "1997", "8", "33", "3", "13", "225", "Wed", "2", "PM", + "2", "2", "14", "14", "34", "12", "513", "PDT", + + "AD", "97", "8", "33", "3", "13", "225", "Wed", "2", "PM", + "2", "2", "14", "14", "34", "12", "513", "PDT", + + "AD", "1997", "August", "0033", "0003", "0013", "0225", + "Wednesday", "0002", "PM", "0002", "0002", "0014", "0014", + "0034", "0012", "0513", "Pacific Daylight Time", + }; + Date someDate = new Date(871508052513L); + TimeZone PST = TimeZone.getTimeZone("PST"); + for (int j = 0, exp = 0; j < dateFormats.length; ++j) { + DateFormat df = dateFormats[j]; + if (!(df instanceof SimpleDateFormat)) { + continue; + } + df.setTimeZone(PST); + logln(" Pattern = " + ((SimpleDateFormat)df).toPattern()); + logln(" Result = " + df.format(someDate)); + for (int i = 0; i < fieldIDs.length; ++i) + { + String field = getFieldText(df, fieldIDs[i], someDate); + if (!field.equals(expected[exp])) { + errln("FAIL: field #" + i + " " + fieldNames[i] + " = \"" + + escape(field) + "\", expected \"" + escape(expected[exp]) + "\""); + } + ++exp; + } + } + } + // get the string value for the given field for the given date + static String getFieldText(DateFormat df, int field, Date date) + { + StringBuffer buffer = new StringBuffer(); + FieldPosition pos = new FieldPosition(field); + df.format(date, buffer, pos); + return buffer.toString().substring(pos.getBeginIndex(), + pos.getEndIndex()); + } + + // Test parsing of partial strings + @SuppressWarnings("deprecation") + public void TestPartialParse994() + { + SimpleDateFormat f = new SimpleDateFormat(); + Calendar cal = new GregorianCalendar(2014 - 80, JANUARY, 1); + f.set2DigitYearStart(cal.getTime()); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", new Date(97, 1-1, 17, 10, 11, 42)); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null); + } + + void tryPat994(SimpleDateFormat format, String pat, String str, Date expected) + { + logln("Pattern \"" + pat + "\" String \"" + str + "\""); + try { + format.applyPattern(pat); + Date date = format.parse(str); + String f = format.format(date); + logln(" parse(" + str + ") -> " + date.toString()); + logln(" format -> " + f); + if (expected == null || + !date.equals(expected)) { + errln("FAIL: Expected " + expected); + } + if (!f.equals(str)) { + errln("FAIL: Expected " + str); + } + } + catch(ParseException e) { + logln("ParseException: " + e.getMessage()); + if (expected != null) { + errln("FAIL: Expected " + expected); + } + } + catch(Exception e) { + errln("*** Exception:"); + e.printStackTrace(); + } + } + + // Test pattern with runs things together + public void TestRunTogetherPattern985() + { + String format = "yyyyMMddHHmmssSSS"; + String now, then; + + SimpleDateFormat formatter = new SimpleDateFormat(format); + + Date date1 = new Date(); + now = formatter.format(date1); + + logln(now); + + ParsePosition pos = new ParsePosition(0); + + Date date2 = formatter.parse(now, pos); + if (date2 == null) { + then = "Parse stopped at " + pos.getIndex(); + } else { + then = formatter.format(date2); + } + + logln(then); + + if (!date2.equals(date1)) { + errln("FAIL"); + } + } + + // Test patterns which run numbers together + @SuppressWarnings("deprecation") + public void TestRunTogetherPattern917() + { + SimpleDateFormat fmt; + String myDate; + + fmt = new SimpleDateFormat( "yyyy/MM/dd" ); + myDate = "1997/02/03"; + _testIt917( fmt, myDate, new Date(97, 2-1, 3) ); + + fmt = new SimpleDateFormat( "yyyyMMdd" ); + myDate = "19970304"; + _testIt917( fmt, myDate, new Date(97, 3-1, 4) ); + + } + void _testIt917( SimpleDateFormat fmt, String str, Date expected ) + { + logln( "pattern=" + fmt.toPattern() + " string=" + str ); + + Object o; + try { + o = fmt.parseObject( str ); + } catch( ParseException e ) { + e.printStackTrace(); + return; + } + logln( "Parsed object: " + o ); + if (!o.equals(expected)) { + errln("FAIL: Expected " + expected); + } + + String formatted = fmt.format( o ); + logln( "Formatted string: " + formatted ); + if (!formatted.equals(str)) { + errln("FAIL: Expected " + str); + } + } + + // Test Czech month formatting -- this can cause a problem because the June and + // July month names share a common prefix. + @SuppressWarnings("deprecation") + public void TestCzechMonths459() + { + // Use Czech, which has month names with shared prefixes for June and July + DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, new Locale("cs", "", "")); + //((SimpleDateFormat)fmt).applyPattern("MMMM d yyyy"); + logln("Pattern " + ((SimpleDateFormat)fmt).toPattern()); + + Date june = new Date(97, Calendar.JUNE, 15); + Date july = new Date(97, Calendar.JULY, 15); + + String juneStr = fmt.format(june); + String julyStr = fmt.format(july); + + try { + logln("format(June 15 1997) = " + juneStr); + Date d = fmt.parse(juneStr); + String s = fmt.format(d); + int month = d.getMonth(); + logln(" -> parse -> " + s + " (month = " + month + ")"); + if (month != JUNE) { + errln("FAIL: Month should be June"); + } + + logln("format(July 15 1997) = " + julyStr); + d = fmt.parse(julyStr); + s = fmt.format(d); + month = d.getMonth(); + logln(" -> parse -> " + s + " (month = " + month + ")"); + if (month != JULY) { + errln("FAIL: Month should be July"); + } + } + catch (ParseException e) { + errln("Exception: " + e); + } + } + + // Test big D (day of year) versus little d (day of month) + @SuppressWarnings("deprecation") + public void TestLetterDPattern212() + { + String dateString = "1995-040.05:01:29"; + String bigD = "yyyy-DDD.hh:mm:ss"; + String littleD = "yyyy-ddd.hh:mm:ss"; + Date expLittleD = new Date(95, 0, 1, 5, 1, 29); + Date expBigD = new Date(expLittleD.getTime() + 39*24*3600000L); // 39 days + expLittleD = expBigD; // Expect the same, with default lenient parsing + logln( "dateString= " + dateString ); + SimpleDateFormat formatter = new SimpleDateFormat(bigD); + ParsePosition pos = new ParsePosition(0); + Date myDate = formatter.parse( dateString, pos ); + logln("Using " + bigD + " -> " + myDate); + if (myDate.getTime() != expBigD.getTime()) { + errln("FAIL: Expected " + expBigD + " got " + myDate); + } + + formatter = new SimpleDateFormat(littleD); + pos = new ParsePosition(0); + myDate = formatter.parse( dateString, pos ); + logln("Using " + littleD + " -> " + myDate); + if (myDate.getTime() != expLittleD.getTime()) { + errln("FAIL: Expected " + expLittleD + " got " + myDate); + } + } + + // Test the 'G' day of year pattern + @SuppressWarnings("deprecation") + public void TestDayOfYearPattern195() + { + Date today = new Date(); + Date expected = new Date(today.getYear(), today.getMonth(), today.getDate()); + + logln("Test Date: " + today); + + SimpleDateFormat sdf = + (SimpleDateFormat)SimpleDateFormat.getDateInstance(); + + tryPattern(sdf, today, null, expected); + tryPattern(sdf, today, "G yyyy DDD", expected); + } + + void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected) + { + if (pattern != null) { + sdf.applyPattern(pattern); + } + logln("pattern: " + sdf.toPattern()); + + String formatResult = sdf.format(d); + logln(" format -> " + formatResult); + try { + Date d2 = sdf.parse(formatResult); + logln(" parse(" + formatResult + ") -> " + d2); + if (d2.getTime() != expected.getTime()) { + errln("FAIL: Expected " + expected); + } + String format2 = sdf.format(d2); + logln(" format -> " + format2); + if (!formatResult.equals(format2)) { + errln("FAIL: Round trip drift"); + } + } + catch(Exception e) { + errln("Error: " + e.getMessage()); + } + } + + // Test a pattern with single quotes + @SuppressWarnings("deprecation") + public void TestQuotePattern161() + { + // This pattern used to end in " zzz" but that makes this test zone-dependent + SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz"); + Date currentTime_1 = new Date(97, Calendar.AUGUST, 13, 10, 42, 28); + String dateString = formatter.format(currentTime_1); + String exp = "08/13/1997 at 10:42:28 AM "; + logln("format(" + currentTime_1 + ") = " + dateString); + if (!dateString.regionMatches(0, exp, 0, exp.length())) { + errln("FAIL: Expected " + exp); + } + } + + // Test the parsing of bad input strings + /** Demonstrates a number of bugs in DateFormat.parse(String) where + * either StringIndexOutOfBoundsException is thrown or null is + * returned instead of ParseException. To reproduce, run this program + * and notice all the "SHOULD NOT HAPPEN" errors. Note also that the + * 1 line that should be correct is off by 100 years. (In this day + * and age, no one would assume that 1/1/00 is Jan 1 1900.) + **/ + public void TestBadInput135() + { + int looks[] = { DateFormat.SHORT, DateFormat.MEDIUM, + DateFormat.LONG, DateFormat.FULL }; + String strings[] = { "Mar 15", "Mar 15 1997", "asdf", + "3/1/97 1:23:", "3/1/00 1:23:45 AM" }; + DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + String expected = "March 1, 2000 1:23:45 AM "; + for ( int i = 0; i < strings.length; ++i ){ + String text = strings[i]; + for ( int j = 0; j < looks.length; ++j ){ + int dateLook = looks[j]; + for ( int k = 0; k < looks.length; ++k ){ + int timeLook = looks[k]; + DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook); + String prefix = text + ", " + dateLook + "/" + timeLook + ": "; + try { + Date when = df.parse(text); + if ( when == null ){ + errln(prefix + + "SHOULD NOT HAPPEN: parse returned null."); + continue; + } + String format = full.format(when); + logln(prefix + "OK: " + format); + // Only match the start -- not the zone, which could vary + if (!format.regionMatches(0, expected, 0, expected.length())) { + errln("FAIL: Expected " + expected); + } + } + catch ( ParseException e ){ + //errln(prefix + e); // This is expected. + } + catch ( StringIndexOutOfBoundsException e ){ + errln(prefix + "SHOULD NOT HAPPEN: " + e); + } + } + } + } + } + + final private static String parseFormats[] = + { + "MMMM d, yyyy", // january 1, 1970 or jan 1, 1970 + "MMMM d yyyy", // january 1 1970 or jan 1 1970 + "M/d/yy", // 1/1/70 + "d MMMM, yyyy", // 1 january, 1970 or 1 jan, 1970 + "d MMMM yyyy", // 1 january 1970 or 1 jan 1970 + "d MMMM", // 1 january or 1 jan + "MMMM d", // january 1 or jan 1 + "yyyy", // 1970 + "h:mm a MMMM d, yyyy" // Date and Time + }; + final private static String inputStrings[] = + { + "bogus string", null, null, null, null, null, null, null, null, null, + "April 1, 1997", "April 1, 1997", null, null, null, null, null, "April 1", null, null, + "Jan 1, 1970", "January 1, 1970", null, null, null, null, null, "January 1", null, null, + "Jan 1 2037", null, "January 1 2037", null, null, null, null, "January 1", null, null, + "1/1/70", null, null, "1/1/70", null, null, null, null, "0001", null, + "5 May 1997", null, null, null, null, "5 May 1997", "5 May", null, "0005", null, + "16 May", null, null, null, null, null, "16 May", null, "0016", null, + "April 30", null, null, null, null, null, null, "April 30", null, null, + "1998", null, null, null, null, null, null, null, "1998", null, + "1", null, null, null, null, null, null, null, "0001", null, // Bug620 + "3:00 pm Jan 1, 1997", null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997", + }; + // More testing of the parsing of bad input + @SuppressWarnings("UnusedAssignment") + public void TestBadInput135a() + { + SimpleDateFormat dateParse = new SimpleDateFormat(); + String s; + Date date; + int PFLENGTH = parseFormats.length; + + dateParse.applyPattern("d MMMM, yyyy"); + dateParse.setTimeZone(TimeZone.getDefault()); + s = "not parseable"; + logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern()); + try { + date = dateParse.parse(s); + errln("FAIL: Expected exception during parse"); + } catch (Exception ex) { + logln("Exception during parse: " + ex); // This is expected + } + + for (int i=0; i " + d.toString()); + if (d.getTime() != expected.getTime()) { + errln("FAIL: Expected " + expected); + } + } catch (ParseException e) { + errln("FAIL: Got exception"); + } + } + + // Test behavior of DateFormat with applied time zone + public void TestDateFormatZone061() + { + Date date; + DateFormat formatter; + + // 25-Mar-97 00:00:00 GMT + date = new Date( 859248000000L ); + logln( "Date 1997/3/25 00:00 GMT: " + date ); + formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK); + formatter.setTimeZone( TimeZone.getTimeZone( "GMT" ) ); + + String temp = formatter.format( date ); + logln( "Formatted in GMT to: " + temp ); + + /* Parse date string */ + try { + Date tempDate = formatter.parse( temp ); + logln( "Parsed to: " + tempDate ); + if (tempDate.getTime() != date.getTime()) { + errln("FAIL: Expected " + date); + } + } + catch( Throwable t ) { + errln( "Date Formatter throws: " + + t.toString() ); + } + } + + // Make sure DateFormat uses the correct zone. + public void TestDateFormatZone146() + { + TimeZone saveDefault = TimeZone.getDefault(); + + try { + TimeZone thedefault = TimeZone.getTimeZone("GMT"); + TimeZone.setDefault(thedefault); + // java.util.Locale.setDefault(new java.util.Locale("ar", "", "")); + + // check to be sure... its GMT all right + TimeZone testdefault = TimeZone.getDefault(); + String testtimezone = testdefault.getID(); + if (testtimezone.equals("GMT")) { + logln("Test timezone = " + testtimezone); + } else { + errln("Test timezone should be GMT, not " + testtimezone); + } + + // now try to use the default GMT time zone + GregorianCalendar greenwichcalendar = + new GregorianCalendar(1997, 3, 4, 23, 0); + //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault()); + //greenwichcalendar.set(1997, 3, 4, 23, 0); + // try anything to set hour to 23:00 !!! + greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23); + // get time + Date greenwichdate = greenwichcalendar.getTime(); + // format every way + String[] DATA = { + "simple format: ", "04/04/97 23:00 GMT", + "MM/dd/yy HH:mm z", + "full format: ", "Friday, April 4, 1997 11:00:00 o'clock PM GMT", + "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z", + "long format: ", "April 4, 1997 11:00:00 PM GMT", + "MMMM d, yyyy h:mm:ss a z", + "default format: ", "04-Apr-97 11:00:00 PM", + "dd-MMM-yy h:mm:ss a", + "short format: ", "4/4/97 11:00 PM", + "M/d/yy h:mm a", + }; + + for (int i=0; i4 y's produces just "2001" until 1.3.1. This + // was fixed in 1.4. + String expected = + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000002001\u5e74"; + SimpleDateFormat sdf = new SimpleDateFormat(pat); + String s = sdf.format(new Date(2001-1900, Calendar.JANUARY, 1)); + if (!expected.equals(s)) { + errln("wrong format result: expected="+expected+", got="+s); + } + Date longday = sdf.parse(s); + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(longday); + if (cal.get(YEAR) != 2001) { + errln("wrong parse result: expected=2001, got=" + cal.get(YEAR)); + } + } catch (Exception e) { + throw e; + } finally { + // Restore the initial time zone + TimeZone.setDefault(initialTimeZone); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java new file mode 100644 index 00000000000..bc37d4f7fba --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary test International Date Format + * @bug 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormat + * @key randomness + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestDateFormat extends IntlTest { + // Values in milliseconds (== Date) + private static final long ONESECOND = 1000; + private static final long ONEMINUTE = 60 * ONESECOND; + private static final long ONEHOUR = 60 * ONEMINUTE; + private static final long ONEDAY = 24 * ONEHOUR; + private static final double ONEYEAR = 365.25 * ONEDAY; // Approximate + + // EModes + private static final byte GENERIC = 0; + private static final byte TIME = GENERIC + 1; + private static final byte DATE = TIME + 1; + private static final byte DATE_TIME = DATE + 1; + + private DateFormat fFormat = DateFormat.getInstance(); + private String fTestName = new String("getInstance"); + private int fLimit = 3; // How many iterations it should take to reach convergence + + public static void main(String[] args) throws Exception { + new IntlTestDateFormat().run(args); + } + + public void TestLocale() { + localeTest(Locale.getDefault(), "Default Locale"); + } + + // This test does round-trip testing (format -> parse -> format -> parse -> etc.) of DateFormat. + public void localeTest(final Locale locale, final String localeName) { + int timeStyle, dateStyle; + + // For patterns including only time information and a timezone, it may take + // up to three iterations, since the timezone may shift as the year number + // is determined. For other patterns, 2 iterations should suffice. + fLimit = 3; + + for(timeStyle = 0; timeStyle < 4; timeStyle++) { + fTestName = new String("Time test " + timeStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getTimeInstance(timeStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest time getTimeInstance exception"); + throw e; + } + TestFormat(); + } + + fLimit = 2; + + for(dateStyle = 0; dateStyle < 4; dateStyle++) { + fTestName = new String("Date test " + dateStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getDateInstance(dateStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest date getTimeInstance exception"); + throw e; + } + TestFormat(); + } + + for(dateStyle = 0; dateStyle < 4; dateStyle++) { + for(timeStyle = 0; timeStyle < 4; timeStyle++) { + fTestName = new String("DateTime test " + dateStyle + "/" + timeStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest date/time getDateTimeInstance exception"); + throw e; + } + TestFormat(); + } + } + } + + public void TestFormat() { + if (fFormat == null) { + errln("FAIL: DateFormat creation failed"); + return; + } + // logln("TestFormat: " + fTestName); + Date now = new Date(); + tryDate(new Date(0)); + tryDate(new Date((long) 1278161801778.0)); + tryDate(now); + // Shift 6 months into the future, AT THE SAME TIME OF DAY. + // This will test the DST handling. + tryDate(new Date(now.getTime() + 6*30*ONEDAY)); + + Date limit = new Date(now.getTime() * 10); // Arbitrary limit + for (int i=0; i<2; ++i) + // tryDate(new Date(floor(randDouble() * limit))); + tryDate(new Date((long) (randDouble() * limit.getTime()))); + } + + private void describeTest() { + if (fFormat == null) { + errln("FAIL: no DateFormat"); + return; + } + + // Assume it's a SimpleDateFormat and get some info + SimpleDateFormat s = (SimpleDateFormat) fFormat; + logln(fTestName + " Pattern " + s.toPattern()); + } + + private void tryDate(Date theDate) { + final int DEPTH = 10; + Date[] date = new Date[DEPTH]; + StringBuffer[] string = new StringBuffer[DEPTH]; + + int dateMatch = 0; + int stringMatch = 0; + boolean dump = false; + int i; + for (i=0; i 0) { + if (dateMatch == 0 && date[i] == date[i-1]) dateMatch = i; + else if (dateMatch > 0 && date[i] != date[i-1]) { + describeTest(); + errln("********** FAIL: Date mismatch after match."); + dump = true; + break; + } + if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i; + else if (stringMatch > 0 && string[i] != string[i-1]) { + describeTest(); + errln("********** FAIL: String mismatch after match."); + dump = true; + break; + } + } + if (dateMatch > 0 && stringMatch > 0) break; + } + if (i == DEPTH) --i; + + if (stringMatch > fLimit || dateMatch > fLimit) { + describeTest(); + errln("********** FAIL: No string and/or date match within " + fLimit + " iterations."); + dump = true; + } + + if (dump) { + for (int k=0; k<=i; ++k) { + logln("" + k + ": " + date[k] + " F> " + string[k] + " P> "); + } + } + } + + // Return a random double from 0.01 to 1, inclusive + private double randDouble() { + // Assume 8-bit (or larger) rand values. Also assume + // that the system rand() function is very poor, which it always is. + // double d; + // int i; + // do { + // for (i=0; i < sizeof(double); ++i) + // { + // char poke = (char*)&d; + // poke[i] = (rand() & 0xFF); + // } + // } while (TPlatformUtilities.isNaN(d) || TPlatformUtilities.isInfinite(d)); + + // if (d < 0.0) d = -d; + // if (d > 0.0) + // { + // double e = floor(log10(d)); + // if (e < -2.0) d *= pow(10.0, -e-2); + // else if (e > -1.0) d /= pow(10.0, e+1); + // } + // return d; + Random rand = new Random(); + return rand.nextDouble(); + } + + public void TestAvailableLocales() { + final Locale[] locales = DateFormat.getAvailableLocales(); + long count = locales.length; + logln("" + count + " available locales"); + if (locales != null && count != 0) { + StringBuffer all = new StringBuffer(); + for (int i=0; i 0) { + throw new RuntimeException("FAILED: " + errors + " error(s)"); + } + } + + private static void test(Locale locale) { + Locale.setDefault(locale); + + // Tests with the Japanese imperial calendar + Locale calendarLocale = new Locale("ja", "JP", "JP"); + testRoundTrip(calendarLocale); + testRoundTripSimple(calendarLocale, + locale == Locale.ENGLISH ? JAPANESE_EN : JAPANESE_JA); + testParseExceptions(calendarLocale, + locale == Locale.ENGLISH ? EXCEPTION_JAPANESE_EN : EXCEPTION_JAPANESE_JA); + + // Tests with the Thai Buddhist calendar + calendarLocale = new Locale("th", "TH"); + testRoundTrip(calendarLocale); + testRoundTripSimple(calendarLocale, + locale == Locale.ENGLISH ? BUDDHIST_EN : BUDDHIST_JA); + } + + private static void testRoundTrip(Locale calendarLocale) { + DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, + DateFormat.FULL, + calendarLocale); + + long t = System.currentTimeMillis(); + t = (t / 1000) * 1000; // discard milliseconds + testRoundTrip(df, new Date(t)); + + // H1.8.9 + testRoundTrip(df, new Date(1989-1900, AUGUST, 9)); + + // H17.6.13 + testRoundTrip(df, new Date(2005-1900, JUNE, 13)); + } + + private static void testRoundTrip(DateFormat df, Date orig) { + try { + String s = df.format(orig); + Date parsed = df.parse(s); + if (!orig.equals(parsed)) { + error("testRoundTrip: bad date: origianl: '%s', parsed '%s'%n", orig, parsed); + } + } catch (Exception e) { + error("Unexpected exception: %s%n", e); + } + } + + private static void testRoundTripSimple(Locale calendarLocale, Object[][] data) { + try { + for (Object[] item : data) { + String pattern = (String) item[0]; + String str = (String) item[1]; + Date date = (Date) item[2]; + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Calendar cal = Calendar.getInstance(calendarLocale); + sdf.setCalendar(cal); + String s = sdf.format(date); + if (!s.equals(str)) { + error("testRoundTripSimple: Got '%s', expected '%s'%n", s, str); + } + Date d = sdf.parse(str); + if (!d.equals(date)) { + error("testRoundTripSimple: Got '%s', expected '%s'%n", d, date); + } + } + } catch (Exception e) { + error("Unexpected exception: %s%n", e); + } + } + + private static void testParseExceptions(Locale calendarLocale, Object[][] data) { + for (Object[] item : data) { + String pattern = (String) item[0]; + String str = (String) item[1]; + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Calendar cal = Calendar.getInstance(calendarLocale); + sdf.setCalendar(cal); + sdf.setLenient(false); + try { + Date d = sdf.parse(str); + error("testParseExceptions: parsing '%s' doesn't throw a ParseException.%n", str); + } catch (ParseException e) { + // OK + } + } + } + + private static void error(String msg) { + System.out.println(msg); + errors++; + } + + private static void error(String fmt, Object... args) { + System.out.printf(fmt, args); + errors++; + } +} diff --git a/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt b/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt new file mode 100644 index 00000000000..c0ddced4fab --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt @@ -0,0 +1,173 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized DateFormatSymbols for +# DateFormatSymbolsSerializationTest. + +aced00057372001a6a6176612e746578742e53696d706c6544617465466f726d +61744243c9da9394359002000449001573657269616c56657273696f6e4f6e53 +747265616d4c001364656661756c7443656e7475727953746172747400104c6a +6176612f7574696c2f446174653b4c000a666f726d61744461746174001d4c6a +6176612f746578742f44617465466f726d617453796d626f6c733b4c00077061 +747465726e7400124c6a6176612f6c616e672f537472696e673b787200146a61 +76612e746578742e44617465466f726d6174642ca1e4c22615fc0200024c0008 +63616c656e6461727400144c6a6176612f7574696c2f43616c656e6461723b4c +000c6e756d626572466f726d61747400184c6a6176612f746578742f4e756d62 +6572466f726d61743b787200106a6176612e746578742e466f726d6174fbd8bc +12e90f184302000078707372001b6a6176612e7574696c2e477265676f726961 +6e43616c656e6461728f3dd7d6e5b0d0c10200014a0010677265676f7269616e +4375746f766572787200126a6176612e7574696c2e43616c656e646172e6ea4d +1ec8dc5b8e03000b5a000c6172654669656c647353657449000e666972737444 +61794f665765656b5a0009697354696d655365745a00076c656e69656e744900 +166d696e696d616c44617973496e46697273745765656b4900096e6578745374 +616d7049001573657269616c56657273696f6e4f6e53747265616d4a00047469 +6d655b00066669656c64737400025b495b000569735365747400025b5a4c0004 +7a6f6e657400144c6a6176612f7574696c2f54696d655a6f6e653b7870010000 +000101010000000100000002000000010000000000000000757200025b494dba +602676eab2a502000078700000001100000001000007b2000000000000000100 +0000010000000100000001000000050000000100000000000000000000000000 +00000000000000000000000000000000000000757200025b5a578f203914b85d +e20200007870000000110101010101010101010101010101010101737200186a +6176612e7574696c2e53696d706c6554696d655a6f6e65fa675d60d15ef5a603 +001049000a647374536176696e6773490006656e6444617949000c656e644461 +794f665765656b490007656e644d6f6465490008656e644d6f6e746849000765 +6e6454696d654900097261774f666673657449001573657269616c5665727369 +6f6e4f6e53747265616d490008737461727444617949000e7374617274446179 +4f665765656b49000973746172744d6f646549000a73746172744d6f6e746849 +0009737461727454696d654900097374617274596561725a000b757365446179 +6c696768745b000b6d6f6e74684c656e6774687400025b42787200126a617661 +2e7574696c2e54696d655a6f6e6531b3e9f57744aca10200014c000249447100 +7e00037870740003474d540036ee800000000000000000000000000000000000 +0000000000000000000001000000000000000000000000000000000000000000 +00000000757200025b42acf317f8060854e002000078700000000c1f1c1f1e1f +1e1f1f1e1f1e1f770800000004000000007878fffff4e2f964ac00737200176a +6176612e746578742e446563696d616c466f726d61740bff0362d872303a0200 +0b5a001b646563696d616c536570617261746f72416c7761797353686f776e42 +000c67726f7570696e6753697a654200116d696e4578706f6e656e7444696769 +747349000a6d756c7469706c69657249001573657269616c56657273696f6e4f +6e53747265616d5a00167573654578706f6e656e7469616c4e6f746174696f6e +4c000e6e6567617469766550726566697871007e00034c000e6e656761746976 +6553756666697871007e00034c000e706f73697469766550726566697871007e +00034c000e706f73697469766553756666697871007e00034c000773796d626f +6c737400204c6a6176612f746578742f446563696d616c466f726d617453796d +626f6c733b787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000701032800000003000000 +2800010000000000000001000000000178010300000000010000000100740001 +2d74000071007e001f71007e001f7372001e6a6176612e746578742e44656369 +6d616c466f726d617453796d626f6c73501d17990868939c02000f4300106465 +63696d616c536570617261746f72430005646967697443000b6578706f6e656e +7469616c43001167726f7570696e67536570617261746f724300096d696e7573 +5369676e4300116d6f6e6574617279536570617261746f724300107061747465 +726e536570617261746f724300077065724d696c6c43000770657263656e7449 +001573657269616c56657273696f6e4f6e53747265616d4300097a65726f4469 +6769744c00034e614e71007e00034c000e63757272656e637953796d626f6c71 +007e00034c0008696e66696e69747971007e00034c0012696e746c4375727265 +6e637953796d626f6c71007e00037870002e00230045002c002d002e003b2030 +0025000000010030740003efbfbd740002c2a4740003e2889e74000358585800 +0000017372000e6a6176612e7574696c2e44617465686a81014b597419030000 +78707708fffffe8f24e5cdd7787372001b6a6176612e746578742e4461746546 +6f726d617453796d626f6c73ace671c9351717c20200085b0005616d706d7374 +00135b4c6a6176612f6c616e672f537472696e673b5b00046572617371007e00 +294c00116c6f63616c5061747465726e436861727371007e00035b00066d6f6e +74687371007e00295b000b73686f72744d6f6e74687371007e00295b000d7368 +6f72745765656b6461797371007e00295b00087765656b6461797371007e0029 +5b000b7a6f6e65537472696e67737400145b5b4c6a6176612f6c616e672f5374 +72696e673b7870757200135b4c6a6176612e6c616e672e537472696e673badd2 +56e7e91d7b47020000787000000002740002414d740002504d7571007e002c00 +0000027400024243740002414474001247794d646b486d735345444677576168 +4b7a7571007e002c0000000d7400074a616e7561727974000846656272756172 +797400054d61726368740005417072696c7400034d61797400044a756e657400 +044a756c7974000641756775737474000953657074656d6265727400074f6374 +6f6265727400084e6f76656d626572740008446563656d62657271007e001f75 +71007e002c0000000d7400034a616e7400034665627400034d61727400034170 +7271007e00397400034a756e7400034a756c7400034175677400035365707400 +034f63747400034e6f7674000344656371007e001f7571007e002c0000000871 +007e001f74000353756e7400034d6f6e74000354756574000357656474000354 +68757400034672697400035361747571007e002c0000000871007e001f740006 +53756e6461797400064d6f6e646179740007547565736461797400095765646e +6573646179740008546875727364617974000646726964617974000853617475 +72646179757200145b5b4c6a6176612e6c616e672e537472696e673b324d09ad +8432e45702000078700000001d7571007e002c00000005740003505354740015 +50616369666963205374616e646172642054696d6571007e0060740015506163 +69666963204461796c696768742054696d657400035044547571007e002c0000 +0005740013416d65726963612f4c6f735f416e67656c657371007e006171007e +006071007e006271007e00637571007e002c000000057400034d53547400164d +6f756e7461696e205374616e646172642054696d6571007e00677400164d6f75 +6e7461696e204461796c696768742054696d657400034d44547571007e002c00 +00000574000e416d65726963612f44656e76657271007e006871007e00677100 +7e006971007e006a7571007e002c00000005740003504e5471007e006871007e +006771007e006871007e00677571007e002c0000000574000f416d6572696361 +2f50686f656e697871007e006871007e006771007e006871007e00677571007e +002c0000000574000343535474001543656e7472616c205374616e6461726420 +54696d6571007e007274001543656e7472616c204461796c696768742054696d +657400034344547571007e002c0000000574000f416d65726963612f43686963 +61676f71007e007371007e007271007e007471007e00757571007e002c000000 +057400034553547400154561737465726e205374616e646172642054696d6571 +007e00797400154561737465726e204461796c696768742054696d6574000345 +44547571007e002c00000005740010416d65726963612f4e65775f596f726b71 +007e007a71007e007971007e007b71007e007c7571007e002c00000005740003 +49455471007e007a71007e007971007e007a71007e00797571007e002c000000 +05740014416d65726963612f496e6469616e61706f6c697371007e007a71007e +007971007e007a71007e00797571007e002c0000000574000348535474001448 +6177616969205374616e646172642054696d6571007e008471007e008571007e +00847571007e002c00000005740010506163696669632f486f6e6f6c756c7571 +007e008571007e008471007e008571007e00847571007e002c00000005740003 +415354740014416c61736b61205374616e646172642054696d65740004414b53 +54740014416c61736b61204461796c696768742054696d65740004414b445475 +71007e002c00000005740011416d65726963612f416e63686f7261676571007e +008a71007e008b71007e008c71007e008d7571007e002c0000000574000f416d +65726963612f48616c6966617874001641746c616e746963205374616e646172 +642054696d6571007e008974001641746c616e746963204461796c6967687420 +54696d657400034144547571007e002c00000005740003434e5474001a4e6577 +666f756e646c616e64205374616e646172642054696d657400034e535474001a +4e6577666f756e646c616e64204461796c696768742054696d657400034e4454 +7571007e002c00000005740010416d65726963612f53745f4a6f686e7371007e +009771007e009871007e009971007e009a7571007e002c000000057400034543 +5474001e43656e7472616c204575726f7065616e205374616e64617264205469 +6d6574000343455474001e43656e7472616c204575726f7065616e204461796c +696768742054696d65740004434553547571007e002c0000000574000c457572 +6f70652f506172697371007e009f71007e00a071007e00a171007e00a2757100 +7e002c0000000571007e0017740013477265656e77696368204d65616e205469 +6d6571007e001771007e00a671007e00177571007e002c000000057400114166 +726963612f43617361626c616e636171007e00a671007e001771007e00a67100 +7e00177571007e002c0000000574000e417369612f4a65727573616c656d7400 +1449737261656c205374616e646172642054696d657400034953547400144973 +7261656c204461796c696768742054696d657400034944547571007e002c0000 +00057400034a53547400134a6170616e205374616e646172642054696d657100 +7e00b071007e00b171007e00b07571007e002c0000000574000a417369612f54 +6f6b796f71007e00b171007e00b071007e00b171007e00b07571007e002c0000 +00057400104575726f70652f42756368617265737474001e4561737465726e20 +4575726f7065616e205374616e646172642054696d6574000345455474001e45 +61737465726e204575726f7065616e204461796c696768742054696d65740004 +454553547571007e002c000000057400034354547400134368696e6120537461 +6e646172642054696d6571007e007271007e00bc71007e00757571007e002c00 +00000574000d417369612f5368616e6768616971007e00bc71007e007271007e +00bc71007e0075740019797979792e4d4d2e646420452068682e6d6d2e737320 +7a7a7a0a diff --git a/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java b/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java new file mode 100644 index 00000000000..9975672c806 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4348864 4112924 4425386 4495052 4836940 4851113 8008577 + * @summary test time zone display names in en_US locale + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneNameTest + */ + +import java.util.*; +import java.text.*; + +public class TimeZoneNameTest extends IntlTest +{ + static final String[] data = { + // Added to verify the fix for 4836940 + "N", "Antarctica/Rothera", "ROTT", "Rothera Time", "ROTT", "Rothera Time", + "N", "Asia/Tehran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time", + "N", "Iran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time", + + // Added to verify the fix for 4851113 + "N", "America/Rankin_Inlet", "CST", "Central Standard Time", "CDT", "Central Daylight Time", + "N", "Asia/Samarkand", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time", + "N", "Asia/Tashkent", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time", + "N", "Atlantic/Jan_Mayen", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "Europe/Oslo", "CET", "Central European Time", "CEST", "Central European Summer Time", + + "N", "Pacific/Honolulu", "HST", "Hawaii Standard Time", "HST", "Hawaii Standard Time", + "N", "America/Los_Angeles", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time", + "N", "US/Pacific", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time", + "N", "America/Phoenix", "MST", "Mountain Standard Time", "MST", "Mountain Standard Time", + "N", "America/Denver", "MST", "Mountain Standard Time", "MDT", "Mountain Daylight Time", + "N", "America/Chicago", "CST", "Central Standard Time", "CDT", "Central Daylight Time", + "N", "America/Indianapolis", "EST", "Eastern Standard Time", "EST", "Eastern Standard Time", + "N", "America/Montreal", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "N", "America/Toronto", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "N", "America/New_York", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "S", "America/Manaus", "AMT", "Amazon Time", "AMT", "Amazon Time", + "S", "America/Campo_Grande", "AMT", "Amazon Time", "AMST", "Amazon Summer Time", + "S", "America/Bahia", "BRT", "Brasilia Time", "BRST", "Brasilia Summer Time", + "N", "America/Halifax", "AST", "Atlantic Standard Time", "ADT", "Atlantic Daylight Time", + "N", "GMT", "GMT", "Greenwich Mean Time", "GMT", "Greenwich Mean Time", + "N", "Europe/London", "GMT", "Greenwich Mean Time", "BST", "British Summer Time", + "N", "Europe/Paris", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "WET", "WET", "Western European Time", "WEST", "Western European Summer Time", + "N", "Europe/Berlin", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "Asia/Jerusalem", "IST", "Israel Standard Time", "IDT", "Israel Daylight Time", + "N", "Europe/Helsinki", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time", + "N", "Africa/Cairo", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time", + "N", "Europe/Moscow", "MSK", "Moscow Standard Time", "MSD", "Moscow Daylight Time", + "N", "Asia/Omsk", "OMST", "Omsk Time", "OMSST", "Omsk Summer Time", + "N", "Asia/Shanghai", "CST", "China Standard Time", "CST", "China Standard Time", + "N", "Asia/Tokyo", "JST", "Japan Standard Time", "JST", "Japan Standard Time", + "N", "Japan", "JST", "Japan Standard Time", "JST", "Japan Standard Time", + "N", "Asia/Seoul", "KST", "Korea Standard Time", "KST", "Korea Standard Time", + "N", "ROK", "KST", "Korea Standard Time", "KST", "Korea Standard Time", + "S", "Australia/Darwin", "ACST", "Australian Central Standard Time (Northern Territory)", + "ACST", "Australian Central Standard Time (Northern Territory)", + "S", "Australia/Adelaide", "ACST", "Australian Central Standard Time (South Australia)", + "ACDT", "Australian Central Daylight Time (South Australia)", + "S", "Australia/Broken_Hill", "ACST", "Australian Central Standard Time (South Australia/New South Wales)", + "ACDT", "Australian Central Daylight Time (South Australia/New South Wales)", + "S", "Australia/Hobart", "AEST", "Australian Eastern Standard Time (Tasmania)", + "AEDT", "Australian Eastern Daylight Time (Tasmania)", + "S", "Australia/Brisbane", "AEST", "Australian Eastern Standard Time (Queensland)", + "AEST", "Australian Eastern Standard Time (Queensland)", + "S", "Australia/Sydney", "AEST", "Australian Eastern Standard Time (New South Wales)", + "AEDT", "Australian Eastern Daylight Time (New South Wales)", + "N", "Pacific/Guam", "ChST", "Chamorro Standard Time", + "ChST", "Chamorro Standard Time", + "N", "Pacific/Saipan", "ChST", "Chamorro Standard Time", + "ChST", "Chamorro Standard Time", + }; + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new TimeZoneNameTest().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + public void Test4112924() { + SimpleDateFormat lfmt = new SimpleDateFormat("zzzz"); + SimpleDateFormat sfmt = new SimpleDateFormat("z"); + + GregorianCalendar june = new GregorianCalendar(2000, Calendar.JUNE, 21); + GregorianCalendar december = new GregorianCalendar(2000, Calendar.DECEMBER, 21); + + int count = data.length; + for (int i = 0; i < count; i++) { + GregorianCalendar sol1, sol2; + + // check hemisphere + if ("N".equals(data[i++])) { + sol1 = december; + sol2 = june; + } else { + sol1 = june; + sol2 = december; + } + + TimeZone tz = TimeZone.getTimeZone(data[i++]); + lfmt.setTimeZone(tz); + sfmt.setTimeZone(tz); + + logln(tz.getID() + ": " + sfmt.format(sol1.getTime()) + ", " + lfmt.format(sol1.getTime())); + logln(tz.getID() + ": " + sfmt.format(sol2.getTime()) + ", " + lfmt.format(sol2.getTime())); + String s = sfmt.format(sol1.getTime()); + if (!data[i].equals(s)) { + errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = lfmt.format(sol1.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = sfmt.format(sol2.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = lfmt.format(sol2.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4097450.java b/jdk/test/java/text/Format/DateFormat/bug4097450.java new file mode 100644 index 00000000000..c70194bd877 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4097450.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @bug 4097450 + */ + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class bug4097450 +{ + public static void main(String args[]) + { + // + // Date parse requiring 4 digit year. + // + String[] dstring = {"97","1997", "97","1997","01","2001", "01","2001" + , "1", + "1","11", "11","111", "111"}; + String[] dformat = {"yy", "yy","yyyy","yyyy","yy", "yy","yyyy","yyyy" + , + "yy","yyyy","yy","yyyy", "yy","yyyy"}; + boolean[] dresult = {true, false, false, true,true, false, false, true + ,false, + false,true, false,false, false}; + SimpleDateFormat formatter; + SimpleDateFormat resultFormatter = new SimpleDateFormat("yyyy"); + + System.out.println("Format\tSource\tResult"); + System.out.println("-------\t-------\t-------"); + for (int i = 0; i < dstring.length; i++) + { + System.out.print(dformat[i] + "\t" + dstring[i] + "\t"); + formatter = new SimpleDateFormat(dformat[i]); + try { + System.out.print(resultFormatter.format(formatter.parse(dstring[ + i]))); + //if ( !dresult[i] ) System.out.print(" <-- error!"); + } + catch (ParseException exception) { + //if ( dresult[i] ) System.out.print(" <-- error!"); + System.out.print("exception --> " + exception); + } + System.out.println(); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4099975.java b/jdk/test/java/text/Format/DateFormat/bug4099975.java new file mode 100644 index 00000000000..812b4996c0f --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4099975.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @bug 4099975 + */ + +import java.text.*; +import java.util.Date; +public class bug4099975 { + public static void main (String args[]){ + DateFormatSymbols symbols = new DateFormatSymbols(); + SimpleDateFormat df = new SimpleDateFormat("E hh:mm", symbols); + System.out.println(df.toLocalizedPattern()); + symbols.setLocalPatternChars("abcdefghijklmonpqr"); // change value of field + System.out.println(df.toLocalizedPattern()); + + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4117335.java b/jdk/test/java/text/Format/DateFormat/bug4117335.java new file mode 100644 index 00000000000..6c9af2a4716 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4117335.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @bug 4117335 4432617 + */ + +import java.text.DateFormatSymbols ; +import java.util.Locale; + +public class bug4117335 { + + public static void main(String[] args) throws Exception + { + DateFormatSymbols symbols = new DateFormatSymbols(Locale.JAPAN); + String[] eras = symbols.getEras(); + System.out.println("BC = " + eras[0]); + if (!eras[0].equals(bc)) { + System.out.println("*** Should have been " + bc); + throw new Exception("Error in BC"); + } + System.out.println("AD = " + eras[1]); + if (!eras[1].equals(ad)) { + System.out.println("*** Should have been " + ad); + throw new Exception("Error in AD"); + } + String[][] zones = symbols.getZoneStrings(); + for (int i = 0; i < zones.length; i++) { + if (!"Asia/Tokyo".equals(zones[i][0])) { + continue; + } + System.out.println("Long zone name = " + zones[i][1]); + if (!zones[i][1].equals(jstLong)) { + System.out.println("*** Should have been " + jstLong); + throw new Exception("Error in long TZ name"); + } + System.out.println("Short zone name = " + zones[i][2]); + if (!zones[i][2].equals(jstShort)) { + System.out.println("*** Should have been " + jstShort); + throw new Exception("Error in short TZ name"); + } + System.out.println("Long zone name = " + zones[i][3]); + if (!zones[i][3].equals(jdtLong)) { + System.out.println("*** Should have been " + jdtLong); + throw new Exception("Error in long TZ name"); + } + System.out.println("SHORT zone name = " + zones[i][4]); + if (!zones[i][4].equals(jdtShort)) { + System.out.println("*** Should have been " + jdtShort); + throw new Exception("Error in short TZ name"); + } + } + } + + static final String bc = "\u7d00\u5143\u524d"; + static final String ad = "\u897f\u66a6"; + static final String jstLong = "\u65e5\u672c\u6a19\u6e96\u6642"; + static final String jstShort = "JST"; + static final String jdtLong = "\u65e5\u672c\u590f\u6642\u9593"; + static final String jdtShort = "JDT"; +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4358730.java b/jdk/test/java/text/Format/DateFormat/bug4358730.java new file mode 100644 index 00000000000..dc448ecd767 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4358730.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; +import java.text.*; + +/** + * @test + * @bug 4358730 + * @library /java/text/testlib + * @summary test that confirms Zero-Padding on year. + */ + +public class bug4358730 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4358730().run(args); + } + + String[] patterns = {"y", "yy", "yyy", "yyyy", "yyyyy"}; + String[][] data = { + /* 2 A.D. */ {"2", "02", "002", "0002", "00002"}, + /* 20 A.D. */ {"20", "20", "020", "0020", "00020"}, + /* 200 A.D. */ {"200", "00", "200", "0200", "00200"}, + /* 2000 A.D. */ {"2000", "00", "2000", "2000", "02000"}, + }; + int[] year = {2, 20, 200, 2000}; + + SimpleDateFormat sdf = new SimpleDateFormat(); + int datasize = data.length; + int nPatterns = data[0].length; + + public void Test4358730() { + Locale locale = Locale.getDefault(); + if (locale.equals(new Locale("th", "TH")) || + locale.equals(new Locale("hi", "IN"))) { + return; + } + + TimeZone saveZone = TimeZone.getDefault(); + Locale saveLocale = Locale.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + Locale.setDefault(new Locale("en", "US")); + + for (int i = 0; i < datasize; i++) { + Date d = new Date(year[i]-1900, 10, 15); + for (int j = 0; j < nPatterns; j++) { + sdf.applyPattern(patterns[j]); + if (!data[i][j].equals(sdf.format(d))) { + errln("Invalid format : " + sdf.format(d) + + ", expected : " + data[i][j]); + } + } + } + } + finally { + TimeZone.setDefault(saveZone); + Locale.setDefault(saveLocale); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6271375.java b/jdk/test/java/text/Format/DateFormat/bug6271375.java new file mode 100644 index 00000000000..811470a01d8 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6271375.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6271375 7059546 + * @summary Make sure DateFormatSymbols serialization works + * correctly for 'zoneStrings' field + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class bug6271375 { + + public static void main(String[] args) throws Exception { + DateFormatSymbols dfsSrc = DateFormatSymbols.getInstance(); + + try (FileOutputStream fos = new FileOutputStream("dfs.ser"); + ObjectOutputStream oStream = new ObjectOutputStream(fos)) { + oStream.writeObject(dfsSrc); + } catch (Exception e) { + throw new RuntimeException("An exception is thrown.", e); + } + + try (FileInputStream fis = new FileInputStream("dfs.ser"); + ObjectInputStream iStream = new ObjectInputStream(fis)) { + DateFormatSymbols dfsDest = (DateFormatSymbols)iStream.readObject(); + + String[][] zoneStringsSrc = dfsSrc.getZoneStrings(); + String[][] zoneStringsDest = dfsDest.getZoneStrings(); + + if (!Arrays.deepEquals(zoneStringsSrc, zoneStringsDest)) { + throw new RuntimeException("src and dest zone strings are not equal"); + } + } catch (Exception e) { + throw new RuntimeException("An exception is thrown.", e); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6317072.java b/jdk/test/java/text/Format/DateFormat/bug6317072.java new file mode 100644 index 00000000000..d5614223679 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6317072.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6317072 + * @summary Make sure NPE is thrown with "null" argumemnts in the + * SimpleDateFormat constructors. + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class bug6317072 { + + public static void main(String[] args) { + + try { + new SimpleDateFormat("yy", (Locale)null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat((String)null, Locale.getDefault()); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat("yy", (DateFormatSymbols)null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat((String)null, DateFormatSymbols.getInstance()); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getTimeInstance(DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getDateInstance(DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6412896.java b/jdk/test/java/text/Format/DateFormat/bug6412896.java new file mode 100644 index 00000000000..b5422814ac6 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6412896.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6412896 + * @summary Make sure that an IllegalArgumentException is thrown + * if the length of any row in zoneStrings array is less than 5 + */ + +import java.text.*; + +public class bug6412896 { + + static final String[][] zoneOK = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time", "PDT"}}; + static final String[][] zoneNG = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time"}}; + + public static void main(String[] args) { + + DateFormatSymbols dfs = DateFormatSymbols.getInstance(); + + dfs.setZoneStrings(zoneOK); + + try { + dfs.setZoneStrings(zoneNG); + throw new RuntimeException("should throw an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt b/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt new file mode 100644 index 00000000000..1fb54165c49 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized MessageFormat for Bug4185816Test. + +aced0005737200176a6176612e746578742e4d657373616765466f726d617459 +ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e +744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661 +2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75 +74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174 +7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176 +612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572 +00025b494dba602676eab2a502000078700000000a0000000100000000000000 +0000000000000000000000000000000000000000000000000000000000757200 +135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078 +700000000a70737200166a6176612e746578742e43686f696365466f726d6174 +18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c +6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473 +7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000 +2800010000000000000001000000000178757200135b4c6a6176612e6c616e67 +2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066 +696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c +6573757200025b443ea68c14ab635a1e02000078700000000300000000000000 +003ff000000000000040000000000000007070707070707070737200106a6176 +612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863 +6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e +00044c000776617269616e7471007e00047870ffffffff740002555374000265 +6e740000787571007e00070000000a0000000a00000015000000000000000000 +0000000000000000000000000000000000000000000000740016546865206469 +736b20222220636f6e7461696e73202e diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt b/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt new file mode 100644 index 00000000000..459d257339d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a corrupted serialized MessageFormat for Bug4185732Test. + +aced0005737200176a6176612e746578742e4d657373616765466f726d617459 +ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e +744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661 +2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75 +74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174 +7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176 +612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572 +00025b494dba602676eab2a502000078700000000a0000000100000000000000 +0000000000000000000000000000000000000000000000000000000000757200 +135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078 +700000000a70737200166a6176612e746578742e43686f696365466f726d6174 +18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c +6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473 +7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000 +2800010000000000000001000000000178757200135b4c6a6176612e6c616e67 +2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066 +696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c +6573757200025b443ea68c14ab635a1e02000078700000000300000000000000 +003ff000000000000040000000000000007070707070707070737200106a6176 +612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863 +6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e +00044c000776617269616e7471007e00047870ffffffff740002555374000265 +6e740000787571007e00070000000a0000000a00000015000000000000000000 +0000000000000000000000000000000000000000000000740010546865206469 +736b20222220636f6e74 diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java b/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java new file mode 100644 index 00000000000..65609941f53 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4185816 + * @library /java/text/testlib + * @build Bug4185816Test IntlTest HexDumpReader + * @run main Bug4185816Test + * @summary test that MessageFormat invariants are preserved across serialization + */ +/* + * + * + * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + */ + +import java.util.*; +import java.io.*; +import java.text.ChoiceFormat; +import java.text.MessageFormat; + +/** + * A Locale can never contains language codes of he, yi or id. + */ +public class Bug4185816Test extends IntlTest { + private static final String FILE_NAME = "Bug4185816.ser"; + private static final String CORRUPT_FILE_NAME = "Bug4185816Corrupt.ser"; + + public static void main(String[] args) throws Exception { + if (args.length == 1 && args[0].equals("prepTest")) { + prepTest(); + } else { + new Bug4185816Test().run(args); + } + } + + public void testIt() throws Exception { + Exception e = checkStreaming(FILE_NAME); + if (e != null) { + errln("MessageFormat did not stream in valid stream: "+e); + e.printStackTrace(); + } + e = checkStreaming(CORRUPT_FILE_NAME); + if (!(e instanceof InvalidObjectException)) { + errln("MessageFormat did NOT detect corrupt stream: "+e); + e.printStackTrace(); + } + } + + public Exception checkStreaming(final String fileName) { + try { + final InputStream is = HexDumpReader.getStreamFromHexDump(fileName + ".txt"); + final ObjectInputStream in = new ObjectInputStream(is); + final MessageFormat form = (MessageFormat)in.readObject(); + final Object[] testArgs = {new Long(12373), "MyDisk"}; + final String result = form.format(testArgs); + in.close(); + } catch (Exception e) { + return e; + } + return null; + } + + /** + * Create a data file for this test. The data file must be corrupted by hand. + */ + private static void prepTest() { + writeFormatToFile(FILE_NAME); + writeFormatToFile(CORRUPT_FILE_NAME); + } + + private static void writeFormatToFile(final String name) { + try { + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream(name)); + + MessageFormat fmt = new MessageFormat("The disk \"{1}\" contains {0}."); + double[] filelimits = {0,1,2}; + String[] filepart = {"no files","one file","{0,number} files"}; + ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); + fmt.setFormat(1,fileform); // NOT zero, see below + + out.writeObject(fmt); + out.close(); + } catch (Exception e) { + System.out.println(e); + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/Bug6481179.java b/jdk/test/java/text/Format/MessageFormat/Bug6481179.java new file mode 100644 index 00000000000..be8e9e29f11 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug6481179.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Confirm that a bug in an error message has been fixed. + * @bug 6481179 + */ + +import java.text.MessageFormat; +import java.text.ParseException; + +public class Bug6481179 { + + public static void main(String[] args) { + boolean err = false; + + try { + MessageFormat.format("Testdata {1,invalid_format_type}", + new Object[] { "val0", "val1" }); + + System.err.println("Error: IllegalArgumentException should be thrown."); + err = true; + } + catch (IllegalArgumentException e) { + String expected = "unknown format type: invalid_format_type"; + String got = e.getMessage(); + + if (!expected.equals(got)) { + System.err.println("Error: Unexpected error message: " + got); + err = true; + } + } + catch (Exception e) { + System.err.println("Error: Unexpected exception was thrown: " + e); + err = true; + } + + if (err) { + throw new RuntimeException("Failed."); + } + } + +} diff --git a/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java b/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java new file mode 100644 index 00000000000..1a4ca1d092d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4112090 8008577 + * @summary verify that MessageFormat can handle large numbers of arguments + * @run main/othervm -Djava.locale.providers=COMPAT,SPI LargeMessageFormat + */ + +import java.text.MessageFormat; +import java.text.ParseException; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class LargeMessageFormat { + + public static void main(String[] args) throws ParseException { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + Locale.setDefault(Locale.GERMANY); + TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")); + testFormat(); + testParse(); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + private static final int REPEATS = 89; + + private static void testFormat() { + // construct large argument array + Object[] sample = { + new Integer(0), // replace with running count below + "hello", + new Date(89, 10, 9), + new Integer(567890), + new Double(1234.50) + }; + int samples = sample.length; + Object[] arguments = new Object[REPEATS * (samples + 1)]; + for (int i = 0; i < REPEATS; i++) { + System.arraycopy(sample, 0, arguments, i * samples, samples); + arguments[i * samples] = new Integer(i); + } + + // construct large template + StringBuffer template = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + template.append("section {" + (i * samples) + ", number} - "); + template.append("string: {" + (i * samples + 1) + "}; "); + template.append("date: {" + (i * samples + 2) + ", date}; "); + template.append("integer: {" + (i * samples + 3) + ", number}; "); + template.append("currency: {" + (i * samples + 4) + ", number, currency};\n"); + } + + // construct expected result string + StringBuffer expected = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + expected.append("section " + i + " - "); + expected.append("string: hello; "); + expected.append("date: 09.11.1989; "); + expected.append("integer: 567.890; "); + expected.append("currency: 1.234,50 \u20AC;\n"); + } + + // create message format + MessageFormat format = new MessageFormat(template.toString()); + String result = format.format(arguments); + if (!result.equals(expected.toString())) { + System.out.println("Template:"); + System.out.println(template); + System.out.println("Expected result: "); + System.out.println(expected); + System.out.println("Actual result: "); + System.out.println(result); + throw new RuntimeException(); + } + } + + private static void testParse() throws ParseException { + StringBuffer parseTemplate = new StringBuffer(); + StringBuffer parseInput = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + parseTemplate.append("{" + i + ", number} "); + parseInput.append(i + " "); + } + MessageFormat parseFormat = new MessageFormat(parseTemplate.toString()); + Object[] parseResult = parseFormat.parse(parseInput.toString()); + for (int i = 0; i < REPEATS; i++) { + if (((Number) parseResult[i]).intValue() != i) { + throw new RuntimeException("got wrong parse result"); + } + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java b/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java new file mode 100644 index 00000000000..1d69258f68d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4105380 + * @summary basic tests for new methods getFormatsByArgumentIndex, setFormatByArgumentIndex, setFormatsByArgumentIndex + */ + +import java.text.ChoiceFormat; +import java.text.Format; +import java.text.MessageFormat; +import java.text.NumberFormat; + +public class MessageFormatsByArgumentIndex { + + private static String choicePattern = "0.0#are no files|1.0#is one file|1.0 subsitution failed. result = " + tempBuffer.toString()); + logln("Formatted with extra params : " + tempBuffer); + //This statement gives an exception while formatting... + //If we use pattern[1] for the message with param, + //we get an NullPointerException in MessageFormat.java(617) + //If we use pattern[2] for the message with param, + //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614) + //Both are due to maxOffset not being reset to -1 + //in applyPattern() when the pattern does not + //contain any param. + } catch (Exception foo) { + errln("Exception when formatting with no params."); + } + } + + /* @bug 4058973 + * MessageFormat.toPattern has weird rounding behavior. + */ + public void Test4058973() { + + MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}"); + String pat = fmt.toPattern(); + if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) { + errln("MessageFormat.toPattern failed"); + } + } + /* @bug 4031438 + * More robust message formats. + */ + public void Test4031438() { + String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}."; + String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'."; + + // If the current locale is hi_IN, skip this test case. + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + MessageFormat messageFormatter = new MessageFormat(""); + + try { + logln("Apply with pattern : " + pattern1); + messageFormatter.applyPattern(pattern1); + Object[] params = {new Integer(7)}; + String tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}.")) + errln("Tests arguments < substitution failed. Formatted text=" + + "<" + tempBuffer + ">"); + logln("Formatted with 7 : " + tempBuffer); + ParsePosition status = new ParsePosition(0); + Object[] objs = messageFormatter.parse(tempBuffer, status); + if (objs[params.length] != null) + errln("Parse failed with more than expected arguments"); + for (int i = 0; i < objs.length; i++) { + if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) { + errln("Parse failed on object " + objs[i] + " at index : " + i); + } + } + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}.")) + errln("Tests with no arguments failed"); + logln("Formatted with null : " + tempBuffer); + logln("Apply with pattern : " + pattern2); + messageFormatter.applyPattern(pattern2); + tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ params) failed."); + logln("Formatted with params : " + tempBuffer); + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ null) failed."); + logln("Formatted with null : " + tempBuffer); + logln("toPattern : " + messageFormatter.toPattern()); + } catch (Exception foo) { + errln("Exception when formatting in bug 4031438. "+foo.getMessage()); + } + } + public void Test4052223() + { + ParsePosition pos = new ParsePosition(0); + if (pos.getErrorIndex() != -1) { + errln("ParsePosition.getErrorIndex initialization failed."); + } + MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree."); + String str = new String("There is one apple growing on the peach tree."); + Object[] objs = fmt.parse(str, pos); + logln("unparsable string , should fail at " + pos.getErrorIndex()); + if (pos.getErrorIndex() == -1) + errln("Bug 4052223 failed : parsing string " + str); + pos.setErrorIndex(4); + if (pos.getErrorIndex() != 4) + errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4"); + ChoiceFormat f = new ChoiceFormat( + "-1#are negative|0#are no or fraction|1#is one|1.0"); + Object[] objs1 = null; + Object[] objs2 = {}; + Object[] objs3 = {null}; + try { + logln("pattern: \"" + mf.toPattern() + "\""); + log("format(null) : "); + logln("\"" + mf.format(objs1) + "\""); + log("format({}) : "); + logln("\"" + mf.format(objs2) + "\""); + log("format({null}) :"); + logln("\"" + mf.format(objs3) + "\""); + } catch (Exception e) { + errln("Exception thrown for null argument tests."); + } + } + + /* @bug 4113018 + * MessageFormat.applyPattern works wrong with illegal patterns. + */ + public void Test4113018() + { + String originalPattern = "initial pattern"; + MessageFormat mf = new MessageFormat(originalPattern); + String illegalPattern = "format: {0, xxxYYY}"; + logln("pattern before: \"" + mf.toPattern() + "\""); + logln("illegal pattern: \"" + illegalPattern + "\""); + try { + mf.applyPattern(illegalPattern); + errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern); + } catch (IllegalArgumentException e) { + if (!originalPattern.equals(mf.toPattern())) + errln("pattern after: \"" + mf.toPattern() + "\""); + } + } + /* @bug 4106661 + * ChoiceFormat is silent about the pattern usage in javadoc. + */ + public void Test4106661() + { + ChoiceFormat fmt = new ChoiceFormat( + "-1#are negative| 0#are no or fraction | 1#is one |1.0 " + + out + "; want \"" + DATA[i+1+j] + '"'); + } + String pat = cf.toPattern(); + String pat2 = new ChoiceFormat(pat).toPattern(); + if (!pat.equals(pat2)) + errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + else + logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + } + catch (IllegalArgumentException e) { + errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e); + } + } + } + + /** + * @bug 4112104 + * MessageFormat.equals(null) throws a NullPointerException. The JLS states + * that it should return false. + */ + public void Test4112104() { + MessageFormat format = new MessageFormat(""); + try { + // This should NOT throw an exception + if (format.equals(null)) { + // It also should return false + errln("MessageFormat.equals(null) returns false"); + } + } + catch (NullPointerException e) { + errln("MessageFormat.equals(null) throws " + e); + } + } + + /** + * @bug 4169959 + * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG. + */ + public void Test4169959() { + // This works + logln(MessageFormat.format( "This will {0}", + new String[]{"work"} ) ); + + // This fails + logln(MessageFormat.format( "This will {0}", + new Object[]{ null } ) ); + } + + public void test4232154() { + boolean gotException = false; + try { + MessageFormat format = new MessageFormat("The date is {0:date}"); + } catch (Exception e) { + gotException = true; + if (!(e instanceof IllegalArgumentException)) { + throw new RuntimeException("got wrong exception type"); + } + if ("argument number too large at ".equals(e.getMessage())) { + throw new RuntimeException("got wrong exception message"); + } + } + if (!gotException) { + throw new RuntimeException("didn't get exception for invalid input"); + } + } + + public void test4293229() { + MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''"); + Object[] args = { null }; + String expected = "'{0}' '{0}'"; + String result = format.format(args); + if (!result.equals(expected)) { + throw new RuntimeException("wrong format result - expected \"" + + expected + "\", got \"" + result + "\""); + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/MessageTest.java b/jdk/test/java/text/Format/MessageFormat/MessageTest.java new file mode 100644 index 00000000000..9234ae90c9f --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/MessageTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1997 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /java/text/testlib + * @summary test MessageFormat + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + + +import java.util.*; +import java.io.*; +import java.text.*; + +public class MessageTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new MessageTest().run(args); + } + + + public void TestMSGPatternTest() { + Object[] testArgs = { + new Double (1), new Double(3456), + "Disk", new Date(10000000000L)}; + + String[] testCases = { + "Quotes '', '{', 'a' {0} '{0}'", + "Quotes '', '{', 'a' {0,number} '{0}'", + "'{'1,number,'#',##} {1,number,'#',##}", + "There are {1} files on {2} at {3}", + "On {2}, there are {1} files, with {0,number,currency}.", + "'{1,number,percent}', {1,number,percent}, ", + "'{1,date,full}', {1,date,full}, ", + "'{3,date,full}', {3,date,full}, ", + "'{1,number,#,##}' {1,number,#,##}", + }; + + for (int i = 0; i < testCases.length; ++i) { + Locale save = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + logln(""); + logln( i + " Pat in: " + testCases[i]); + MessageFormat form = new MessageFormat(testCases[i]); + logln( i + " Pat out: " + form.toPattern()); + String result = form.format(testArgs); + logln( i + " Result: " + result); + Object[] values = form.parse(result); + for (int j = 0; j < testArgs.length; ++j) { + Object testArg = testArgs[j]; + Object value = null; + if (j < values.length) { + value = values[j]; + } + if ((testArg == null && value != null) + || (testArg != null && !testArg.equals(value))) { + logln( i + " " + j + " old: " + testArg); + logln( i + " " + j + " new: " + value); + } + } + } + catch(java.text.ParseException pe ) { + throw new RuntimeException("Error: MessageFormat.parse throws ParseException"); + } + finally{ + Locale.setDefault(save); + } + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/bug4492719.java b/jdk/test/java/text/Format/MessageFormat/bug4492719.java new file mode 100644 index 00000000000..6a1d2184ffe --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/bug4492719.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @bug 4492719 + * @library /java/text/testlib + * @summary Confirm that Message.parse() interprets time zone which uses "GMT+/-" format correctly and doesn't throw ParseException. + */ + +import java.util.*; +import java.text.*; + +public class bug4492719 extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + MessageFormat mf; + boolean err =false; + + String[] formats = { + "short", "medium", "long", "full" + }; + String[] timezones = { + "America/Los_Angeles", "GMT", "GMT+09:00", "GMT-8:00", + "GMT+123", "GMT-1234", "GMT+2", "GMT-13" + }; + String text; + + Locale.setDefault(Locale.US); + + try { + for (int i = 0; i < timezones.length; i++) { + TimeZone.setDefault(TimeZone.getTimeZone(timezones[i])); + + for (int j = 0; j < formats.length; j++) { + mf = new MessageFormat("{0,time," + formats[j] + "} - time"); + text = MessageFormat.format("{0,time," + formats[j] + "} - time", + new Object [] { new Date(123456789012L)}); + Object[] objs = mf.parse(text); + } + } + } catch (ParseException e) { + err = true; + System.err.println("Invalid ParseException occurred : " + + e.getMessage()); + System.err.println(" TimeZone=" + TimeZone.getDefault()); + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + if (err) { + throw new Exception("MessageFormat.parse(\"GMT format\") failed."); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java new file mode 100644 index 00000000000..1a2e7bf3945 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4018937 + * @summary Confirm that DecimalFormat.parse() parses BigDecimal and BigInteger as expected. + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class BigDecimalCompatibilityTest { + + static boolean err = false; + + static final String[] input_data = { + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + }; + static final String[] exponents = { + "E-100", "E100", "E-900", "E900", "" + }; + static final int[] multipliers = { + -1, 1, -100, 100, -9999, 9999 + }; + + public static void main(String[] args) throws Exception { + Locale loc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + testBigDecimal(); + testBigInteger(); + + Locale.setDefault(loc); + + if (err) { + throw new RuntimeException("Error: Unexpected value"); + } + } + + static private void testBigDecimal() { + DecimalFormat df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMaximumFractionDigits(Integer.MAX_VALUE); + + for (int i = 0; i < input_data.length; i++) { + for (int j = 0; j < input_data.length; j++) { + for (int k = 0; k < input_data.length; k++) { + for (int l = 0; l < input_data.length; l++) { + for (int m = 0; m < exponents.length; m++) { + String s = input_data[i] + input_data[j] + '.' + + input_data[k] + input_data[l] + + exponents[m]; + for (int n = 0; n < multipliers.length; n++) { + test(df, s, multipliers[n]); + test(df, '-'+s, multipliers[n]); + } + } + } + } + } + } + } + + static private void testBigInteger() { + DecimalFormat df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMaximumFractionDigits(Integer.MAX_VALUE); + + for (int i = 0; i < input_data.length; i++) { + for (int j = 0; j < input_data.length; j++) { + String s = input_data[i] + input_data[j]; + for (int k = 0; k < multipliers.length; k++) { + test(df, s, multipliers[k]); + test(df, '-'+s, multipliers[k]); + } + } + } + } + + static void test(DecimalFormat df, String s, int multiplier) { + df.setMultiplier(multiplier); + + Number num = null; + try { + num = df.parse(s); + } + catch (ParseException e) { + err = true; + System.err.println("Failed: Exception occurred: " + e.getMessage()); + return; + } + + BigDecimal bd = new BigDecimal(s); + try { + bd = bd.divide(new BigDecimal(multiplier)); + } + catch (ArithmeticException e) { + bd = bd.divide(new BigDecimal(multiplier), BigDecimal.ROUND_HALF_EVEN); + } + check(num, bd, multiplier); + } + + static void check(Number got, BigDecimal expected, int multiplier) { + if (!got.equals(expected)) { + err = true; + System.err.println("Failed: got:" + got + + ", expected: " + expected + + ", multiplier=" + multiplier); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java new file mode 100644 index 00000000000..14b3a9fec62 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java @@ -0,0 +1,1044 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalFormat + */ + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.*; +import java.util.*; + +public class BigDecimalFormat extends IntlTest { + + public static void main(String[] args) throws Exception { + new BigDecimalFormat().run(args); + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + StringBuffer formatted = new StringBuffer(1000); + FieldPosition fp; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Format_in_NumberFormat_BigDecimal() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...789 + // To: 0.000...789 (same as From) + formatted.setLength(0); + from = "0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...789 + // To: -0.000...789 (same as From) + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...789 + // To: 123,4...7,890.012...789 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = nonsep_int + "." + fra; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 479); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...789 + // To: -123,4...7,890.012...789 + // ~~~~~~~~~ : FieldPosition(FRACTION_FIELD) + fp = new FieldPosition(DecimalFormat.FRACTION_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 481, 841); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.000...789 + // To: 123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.000...789 + // To: -123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000 + // To: 123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000 + // To: -123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0000 + // To: 0 + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...00001234 + // To: 1,234 + formatted.setLength(0); + from = nonsep_zero + "1234"; + to = "1,234"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...00001234 + // To: -1,234 + // ~ : FieldPosition(GROUPING_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero + "1234"; + to = "-1,234"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 2, 3); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000.0...0 + // To: 0 + formatted.setLength(0); + from = nonsep_zero + "." + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000.0...0 + // To: 0.0 + formatted.setLength(0); + from = "-" + nonsep_zero + "." + nonsep_zero; + to = "0.0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...7890...0 + // To: 1,234...7,890.0123...789 + formatted.setLength(0); + from = nonsep_int + "." + fra + nonsep_zero; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...7890...0 + // To: -1,234...7,890.0123...789 + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra + nonsep_zero; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 1123...890.012...789 + // To : 1.123...8900123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 726); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789 + // To : -1.123...8900123...789E360 + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...0001123...890.012...789 + // To : 1.123...8900123...789E-360 + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1123...890.012...789000...000 + // To : 1.123...8900123...789E360 + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra + nonsep_zero; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789000...000 + // To : -1.123...8900123...789E360 + // ~ : FieldPosition(EXPONENT_SYMBOL) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SYMBOL); + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra + nonsep_zero; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 724); + + /* ------------------------------------------------------------------ */ + + // From: 0.000...0001123...890.012...789000...000 + // To : 1.123...8900123...789E-360 + // ~ : FieldPosition(EXPONENT_SIGN) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SIGN); + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 364); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789000...000 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC1123...890.012...789 + // To : ABC1.123...890.0123...789 + formatted = new StringBuffer("ABC"); + from = "1" + nonsep_int + "." + fra; + to = "ABC1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC-1123...890.012...789 + // To : ABC-1.123...890.0123...789 + // ~ : FieldPosition(DECIMAL_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted = new StringBuffer("ABC"); + from = "-1" + nonsep_int + "." + fra; + to = "ABC-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 5, 6); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 726, 0); + + // From: 0.000...000012...7890123456789 + // To: 0.000...000012...789012346 (Shorter than From) + formatted.setLength(0); + from = "0." + nonsep_zero + fra + fra; + to = "0." + nonsep_zero + fra + "012346"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 723, 0); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...000012...7890123456789 + // To: -0.000...000012...789012 (Shorter than From) + formatted.setLength(0); + from = "-0." + nonsep_zero + fra + fra; + to = "-0." + nonsep_zero + fra + "012"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, 370, 0); + + // From: 1234567890.012...78901234567890 + // To: 12345.67890012...789012346E5 + formatted.setLength(0); + from = "1234567890." + fra + "0123456789"; + to = "12345.67890" + fra + "01235E5"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 364, 0); + + // From: -0.000...0001012...7890123456789 + // To: -1.012...789012E-361 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + "0123456789"; + to = "-1." + fra + "0123E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 366, 0); + + // From: 1012...78901234567890 + // To: 1.012...789012346E370 + formatted.setLength(0); + from = "1" + fra + "0123456789"; + to = "1." + fra + "012346E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 363, 0); + + // From: -1012...7890123456789 + // To: -1.012...789012E370 + formatted.setLength(0); + from = "-1" + fra + "0123456789"; + to = "-1." + fra + "012E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 720); + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Format_in_NumberFormat_BigDecimal_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: 250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(-250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: -250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Format_in_NumberFormat_BigInteger() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890 + // To: -123,4...7,890 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 480); + + /* ------------------------------------------------------------------ */ + + // From: 000...0001234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_zero + nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0001234...7890 + // To: -123,4...7,890 + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-" + nonsep_zero + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000 + // To: 0.0 + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0.0"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 2); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 10123...789 + // To : 1.0123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + fra; + to = "1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 366); + + /* ------------------------------------------------------------------ */ + + // From: -1012...789 + // To : -1.012...789E360 + formatted.setLength(0); + from = "-1" + fra; + to = "-1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 720); + + // From: 12345012...789000...000 + // To : 12345.012...789000...000E720 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "12345" + fra + nonsep_zero; + to = "12345." + fra + nonsep_zero + "E720"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 727, 730); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 365); + + // From: -1234567890012...789000...000 + // To : -12345.67890012...789E365 + formatted.setLength(0); + from = "-1234567890" + fra; + to = "-12345.67890" + fra + "E365"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Format_in_NumberFormat_BigInteger_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(-250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal Long numbers when maximum and minimum digits are + * specified + */ + void test_Format_in_NumberFormat_Long_checkDigits() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: 1234567890 + // To: 000,0...0,000,123,456,789 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = sep_zero.substring(0, 399) + ",123,456,789"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###"); + ((DecimalFormat)nf).setMultiplier(-1); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: 1234567890 + // To: -0000...0000123456789.000...000 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = "-" + nonsep_zero.substring(0, 300) + "123456789." + + nonsep_zero.substring(0, 340); + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: Long.MAX_VALUE + // To: 000,0...0,000,019,807,040,619,342,712,359,383,728,129 + // --------------- + // 280 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,619,342,712,359,383,728,129"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 360); + + // From: Long.MAX_VALUE + // To: -1.9807040628566084396238503936000...000E28 + // --------- + // 312 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = "-1.9807040628566084396238503936" + + nonsep_zero.substring(0, 312) + "E28"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: -198070406193427123615312117760000...0000.000...000E-280 + // ----------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = "-19807040619342712361531211776" + + nonsep_zero.substring(0, 280) + "." + + nonsep_zero.substring(0, 340) + "E-280"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: 000,0...0,000,019,807,040,628,566,084,398,385,987,584.000...000 + // --------------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,628,566,084,398,385,987,584." + + nonsep_zero.substring(0, 340); + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Format_in_NumberFormat_SpecialNumber() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + double[] numbers = { + -0.0, 0.0, Double.NaN, + Double.POSITIVE_INFINITY, 5.1, 5.0, + Double.NEGATIVE_INFINITY, -5.1, -5.0, + }; + int multipliers[] = {0, 5, -5}; + String[][] expected = { + {"-0", "0", "\ufffd", "\ufffd", "0", "0", "\ufffd", "-0", "-0"}, + {"-0", "0", "\ufffd", "\u221e", "25.5", "25", "-\u221e", "-25.5", + "-25"}, + {"0", "-0", "\ufffd", "-\u221e", "-25.5", "-25", "\u221e", "25.5", + "25"}, + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for Long.MIN_VALUE + * (Formatting Long.MIN_VALUE w/ multiplier=-1 used to return a wrong + * number.) + */ + void test_Format_in_NumberFormat_Other() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + long[] numbers = { + Long.MIN_VALUE, + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9,223,372,036,854,775,808"}, // Long.MIN_VALUE + {"9,223,372,036,854,775,808"}, // Long.MIN_VALUE * (-1) + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for MessageFormat + */ + void test_Format_in_MessageFormat() { + MessageFormat mf = new MessageFormat( + " {0, number}\n" + + " {0, number, integer}\n" + + " {0, number, currency}\n" + + " {0, number, percent}\n" + + " {0, number,0.###########E0}\n" + + + " {1, number}\n" + + " {1, number, integer}\n" + + " {1, number, currency}\n" + + " {1, number, percent}\n" + + " {1, number,0.#######E0}\n", + Locale.US + ); + Object[] testArgs = { + new BigInteger("9876543210987654321098765432109876543210"), + new BigDecimal("-12345678901234567890.98765432109876543210987654321"), + }; + String expected = + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00\n" + + " 987,654,321,098,765,432,109,876,543,210,987,654,321,000%\n" + + " 9.87654321099E39\n" + + + " -12,345,678,901,234,567,890.988\n" + + " -12,345,678,901,234,567,891\n" + + " ($12,345,678,901,234,567,890.99)\n" + + " -1,234,567,890,123,456,789,099%\n" + + " -1.2345679E19\n" + ; + + if (!expected.equals(mf.format(testArgs))) { + errln("Wrong format.\n got:\n" + mf.format(testArgs) + + " expected:\n" + expected); + } + } + + private void setDigits(NumberFormat nf, + int i_max, int i_min, int f_max, int f_min) { + nf.setMaximumIntegerDigits(i_max); + nf.setMinimumIntegerDigits(i_min); + nf.setMaximumFractionDigits(f_max); + nf.setMinimumFractionDigits(f_min); + } + + private void checkFormat(String orig, StringBuffer got, String expected, + int multiplier) { + if (!expected.equals(new String(got))) { + errln("Formatting... failed." + + "\n original: " + orig + + "\n multiplier: " + multiplier + + "\n formatted: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkFieldPosition(String orig, FieldPosition fp, int begin, + int end) { + int position; + + if ((position = fp.getBeginIndex()) != begin) { + errln("Formatting... wrong Begin index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + begin + "\n"); + } + if ((position = fp.getEndIndex()) != end) { + errln("Formatting... wrong End index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + end + "\n"); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java new file mode 100644 index 00000000000..be206052d06 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java @@ -0,0 +1,709 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalParse + */ + +import java.math.BigDecimal; +import java.text.*; +import java.util.*; + +public class BigDecimalParse extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale loc = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new BigDecimalParse().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(loc); + } + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + Number parsed = null; + ParsePosition pp; + boolean exceptionOccurred; + String msg; + DecimalFormat df; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Parse_in_DecimalFormat_BigDecimal() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 1234...7890.012...789 + // To: BigDecimal 1234...7890.012...789 + check(nonsep_int + "." + fra, new BigDecimal(nonsep_int + "." + fra)); + + // From: -1,234...7,890.012...789 + // To: BigDecimal -1234...7890.012...789 + check("-" + sep_int + "." + fra, + new BigDecimal("-" + nonsep_int + "." + fra)); + + // From: 000...0000.0...0 + // To: BigDecimal 0E-360 + check(nonsep_zero + "." + nonsep_zero, + new BigDecimal(nonsep_zero + "." + nonsep_zero)); + + // From: 0.000...0000123...789E370 + // To: BigDecimal 0.0123...789 + check("0.0000000000" + nonsep_zero + fra + "E370", + new BigDecimal("0.0000000000" + nonsep_zero + fra + "E370")); + + // From: 0.1123...890E-360 + // To: BigDecimal 1.123...890E-361 + check("0.1" + nonsep_int + "E-360", + new BigDecimal("0.1" + nonsep_int + "E-360")); + + // From: 000...0000.0...0123...7890 + // To: BigDecimal 1.234...890E-361 + check(nonsep_zero + "." + nonsep_zero + nonsep_int, + new BigDecimal(nonsep_zero + "." + nonsep_zero + nonsep_int)); + + // From: 0.123...890E360 + // To: BigDecimal 123...890 + check("0." + nonsep_int + "E360", + new BigDecimal("0." + nonsep_int + "E360")); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Parse_in_DecimalFormat_BigDecimal_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000.000...000 + // To: 1000...0000.000...000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: -1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: 250,0...0,000.000...000 + // To: -1000...0000.000...000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: 1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that ArithmeticException is handled properly + // From: 1000.000 + // To: 333.333 + df.setMultiplier(3); + check("1000.000", new BigDecimal("333.333")); + + // Confirm that ArithmeticException is handled properly + // From: 10000.0000 + // To: 303.0303 + df.setMultiplier(33); + check("10000.0000", new BigDecimal("303.0303")); + } + + /** + * Test for division by zero (BigDecimal) + */ + void test_Parse_in_DecimalFormat_BigDecimal_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", new Double(Double.NEGATIVE_INFINITY)); + + // From: -0.00 + // To: Double.NaN + check("-0.00", new Double(Double.NaN)); + } + + /** + * Test for division by zero (Double) + */ + void test_Parse_in_DecimalFormat_Double_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000.000 + // To: Double.NEGATIVE_INFINITY + check("-1000.000", new Double(Double.NEGATIVE_INFINITY)); + + // From: 0.0 + // To: Double.NaN + check("0.0", new Double(Double.NaN)); + + // From: -0.0 (Double) + // To: Double.NaN + check("-0.0", new Double(Double.NaN)); + + // From: Double.NaN + // To: Double.NaN + check("\ufffd", new Double(Double.NaN)); + + // From: Double.POSITIVE_INFINITY + // To: Double.NaN + check("\u221e", new Double(Double.POSITIVE_INFINITY)); + + // From: Double.NEGATIVE_INFINITY + // To: Double.NaN + check("-\u221e", new Double(Double.NEGATIVE_INFINITY)); + } + + /** + * Test for division by zero (Long) + */ + void test_Parse_in_DecimalFormat_Long_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000 + // To: Double.POSITIVE_INFINITY + check("1000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", new Double(Double.NEGATIVE_INFINITY)); + + // From: -000 (Long) + // To: Double.NaN + check("-000", new Double(Double.NaN)); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Parse_in_DecimalFormat_BigInteger() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 123...890 + // To: BigDecimal 123...890 + check(nonsep_int + nonsep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: 123,4...7,890 + // To: BigDecimal 1234...7890 + check(sep_int + "," + sep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: -000...000123...890 + // To: BigDecimal -123...890 + check("-" + nonsep_zero + nonsep_int, new BigDecimal("-" + nonsep_int)); + + // From: -000,0...0,000,123,4...7,890 + // To: BigDecimal -123...890 + check("-" + sep_zero + "," + sep_int, new BigDecimal("-" + nonsep_int)); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Parse_in_DecimalFormat_BigInteger_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000 + // To: 1000...0000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: -1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: 250,0...0,000 + // To: -1000...0000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: 1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: 250,0...0,000E-360 + // To: -1000...0000.000...000 + check("250,000,000," + sep_zero + "," + sep_zero + "E-360", + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that a division which results in a irrational number is done + // properly + // From: 1000 + // To: 333 + df.setMultiplier(3); + check("1000", new BigDecimal("333")); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Parse_in_DecimalFormat_SpecialNumber() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "0", "0.0", "25", "25.0", "25.5", "\u221e", "\ufffd", + "-0", "-0.0", "-25", "-25.0", "-25.5", "-\u221e", + }; + int multipliers[] = {5, -5}; + Number[][] expected = { + { + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + new Double(Double.POSITIVE_INFINITY), new Double(Double.NaN), + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN), + }, + { + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN), + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + new Double(Double.POSITIVE_INFINITY), + }, + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), expected[i][j]); + } + } + } + + /** + * Test for special numbers + */ + void test_Parse_in_DecimalFormat_Other() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "-9223372036854775808", // Long.MIN_VALUE + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9223372036854775808"}, // Long.MIN_VALUE + {"9223372036854775808"}, // Long.MAX_VALUE+1 = abs(MIN_VALUE) + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), + new BigDecimal(expected[i][j])); + } + } + } + + static final String[] patterns = { + " {0, number} ", + " {0, number} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + + " {0, number} ", + " {0, number} ", + " {0, number, integer} ", + " {0, number, integer} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + }; + static final String[] from = { + " 12,345,678,901,234,567,890.98765432109876543210987654321 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321 ", + " $12,345,678,901,234,567,890.98765432109876543210987654321 ", + " ($12,345,678,901,234,567,890.98765432109876543210987654321) ", + " 1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " -1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " 12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210E5 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210E-5 ", + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00 ", + " ($9,876,543,210,987,654,321,098,765,432,109,876,543,210.00) ", + " 987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " 98,765,432,109,876,543,210.98765432109876543210E20 ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,000,000,000,000,000,000,000E-20 ", + }; + + static final String[] expected1 = { // isParseIntegerOnly() == false + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "0.1234567890123456789098765432109876543210987654321", + "-0.1234567890123456789098765432109876543210987654321", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210.00", + "-9876543210987654321098765432109876543210.00", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[] parsePosition1 = { + 60, 61, 61, 63, 64, 65, 64, 65, + 57, 58, 59, 61, 61, 63, 60, 61, 54, 88, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(false) + */ + void test_Parse_in_MessageFormat_NotParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != -1) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:-1, got:"+ + pp.getErrorIndex() + " for " + from[i]); + } + if (pp.getIndex() != parsePosition1[i]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition1[i] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + checkType(from[i], getType(new BigDecimal(expected1[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected1[i]), + (Number)parsed[0]); + } + } + + static final String[] expected2 = { // isParseIntegerOnly() == true + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "0", + "0", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[][] parsePosition2 = { // {errorIndex, index} + /* + * Should keep in mind that the expected result is different from + * DecimalFormat.parse() for some cases. + */ + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + + {-1, 57}, {-1, 58}, {-1, 59}, {-1, 61}, + {56, 0}, // parsing stopped at '.' + // because cannot find '%' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {-1, 60}, {-1, 61}, + {28, 0}, // parsing stopped at '.' + {-1, 88}, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_MessageFormat_ParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + ((DecimalFormat)formats[j]).setParseIntegerOnly(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != parsePosition2[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition2[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from[i]); + } + if (pp.getIndex() != parsePosition2[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition2[i][1] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition2[i][0] == -1) { + checkType(from[i], getType(new BigDecimal(expected2[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected2[i]), + (Number)parsed[0]); + } + } + } + + static final String[] from3 = { + "12,345,678,901,234,567,890.98765432109876543210987654321", + "-12,345,678,901,234,567,890.98765432109876543210987654321", + "9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "-9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "1234556790000E-8", + }; + static final String[] expected3 = { + "12345678901234567890", + "-12345678901234567890", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "12345.56790000", + }; + static final int[][] parsePosition3 = { // {errorIndex, index} + {-1, 26}, + {-1, 27}, + {-1, 53}, + {-1, 54}, + {-1, 16}, + }; + + /** + * Test for DecimalFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_DecimalFormat_ParseIntegerOnly() { + DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance(); + df.setParseBigDecimal(true); + + for (int i=0; i < from3.length; i++) { + pp = new ParsePosition(0); + Number parsed = null; + + try { + parsed = df.parse(from3[i], pp); + + if (pp.getErrorIndex() != parsePosition3[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition3[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from3[i]); + } + if (pp.getIndex() != parsePosition3[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition3[i][1] + ", got:"+ pp.getIndex() + + " for " + from3[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition3[i][0] == -1) { + checkType(from3[i], getType(new BigDecimal(expected3[i])), + getType(parsed)); + checkParse(from3[i], new BigDecimal(expected3[i]), parsed); + } + } + } + + protected void check(String from, Number to) { + pp = new ParsePosition(0); + try { + parsed = df.parse(from, pp); + } + catch(Exception e) { + exceptionOccurred = true; + errln(e.getMessage()); + } + if (!exceptionOccurred) { + checkParse(from, to, parsed); + checkType(from, getType(to), getType(parsed)); + checkParsePosition(from, from.length(), pp.getIndex()); + } + } + + private void checkParse(String orig, Number expected, Number got) { + if (!expected.equals(got)) { + errln("Parsing... failed." + + "\n original: " + orig + + "\n parsed: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkType(String orig, String expected, String got) { + if (!expected.equals(got)) { + errln("Parsing... unexpected Class returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkParsePosition(String orig, int expected, int got) { + if (expected != got) { + errln("Parsing... wrong ParsePosition returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private String getType(Number number) { + return number.getClass().getName(); + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4208135.java b/jdk/test/java/text/Format/NumberFormat/Bug4208135.java new file mode 100644 index 00000000000..3f5785b6f6c --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4208135.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Confirm that the decimal separator is shown when explicitly requested. + * @bug 4208135 + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class Bug4208135 { + + static DecimalFormat df; + + static boolean err = false; + + static public void main(String[] args){ + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + df = new DecimalFormat(); + + df.applyPattern("0.#E0"); + + df.setDecimalSeparatorAlwaysShown(true); + checkFormat(new Double(0.0), "0.E0"); + checkFormat(new Double(10.0), "1.E1"); + checkFormat(new Double(1000.0), "1.E3"); + checkFormat(new Long(0), "0.E0"); + checkFormat(new Long(10), "1.E1"); + checkFormat(new Long(1000), "1.E3"); + checkFormat(new BigDecimal("0.0"), "0.E0"); + checkFormat(new BigDecimal("10.0"), "1.E1"); + checkFormat(new BigDecimal("1000.0"), "1.E3"); + checkFormat(new BigInteger("00"), "0.E0"); + checkFormat(new BigInteger("10"), "1.E1"); + checkFormat(new BigInteger("1000"), "1.E3"); + + df.setDecimalSeparatorAlwaysShown(false); + checkFormat(new Double(0.0), "0E0"); + checkFormat(new Double(10.0), "1E1"); + checkFormat(new Double(1000.0), "1E3"); + checkFormat(new Long(0), "0E0"); + checkFormat(new Long(10), "1E1"); + checkFormat(new Long(1000), "1E3"); + checkFormat(new BigDecimal("0.0"), "0E0"); + checkFormat(new BigDecimal("10.0"), "1E1"); + checkFormat(new BigDecimal("1000.0"), "1E3"); + checkFormat(new BigInteger("0"), "0E0"); + checkFormat(new BigInteger("10"), "1E1"); + checkFormat(new BigInteger("1000"), "1E3"); + + df.applyPattern("0.###"); + + df.setDecimalSeparatorAlwaysShown(true); + checkFormat(new Double(0.0), "0."); + checkFormat(new Double(10.0), "10."); + checkFormat(new Double(1000.0), "1000."); + checkFormat(new Long(0), "0."); + checkFormat(new Long(10), "10."); + checkFormat(new Long(1000), "1000."); + checkFormat(new BigDecimal("0.0"), "0."); + checkFormat(new BigDecimal("10.0"), "10."); + checkFormat(new BigDecimal("1000.0"), "1000."); + checkFormat(new BigInteger("0"), "0."); + checkFormat(new BigInteger("10"), "10."); + checkFormat(new BigInteger("1000"), "1000."); + + df.setDecimalSeparatorAlwaysShown(false); + checkFormat(new Double(0.0), "0"); + checkFormat(new Double(10.0), "10"); + checkFormat(new Double(1000.0), "1000"); + checkFormat(new Long(0), "0"); + checkFormat(new Long(10), "10"); + checkFormat(new Long(1000), "1000"); + checkFormat(new BigDecimal("0.0"), "0"); + checkFormat(new BigDecimal("10.0"), "10"); + checkFormat(new BigDecimal("1000.0"), "1000"); + checkFormat(new BigInteger("0"), "0"); + checkFormat(new BigInteger("10"), "10"); + checkFormat(new BigInteger("1000"), "1000"); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format/parse with DecimalFormat"); + } + } + + static void checkFormat(Number num, String expected) { + String got = df.format(num); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error:" + + "\n\tnumber: " + num + + "\n\tSeparatorShown? : " + df.isDecimalSeparatorAlwaysShown() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4833877.java b/jdk/test/java/text/Format/NumberFormat/Bug4833877.java new file mode 100644 index 00000000000..5f3c5056014 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4833877.java @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Confirm that the negative multiplier works as expected. + * @bug 4833877 + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class Bug4833877 { + + static DecimalFormat df; + + static boolean err = false; + + public static void main(String[] args) throws Exception { + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + /* ================================================================ */ + + df = new DecimalFormat(); + df.setMaximumFractionDigits(50); + df.setMultiplier(4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "1,010.10101010101"); + checkParse("-1,010.10101010101", new Double(-252.5252525252525)); + + checkFormat(new Double(-2222.2222), "-8,888.8888"); + checkParse("8888.8888", new Double(2222.2222)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "4,000"); + checkParse("-4,000", new Long(-1000)); + + checkFormat(new Long(-250), "-1,000"); + checkParse("1000", new Long(250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("22222.222222222222222222222"), + "88,888.888888888888888888888"); + checkParse("-88,888.888888888888888888888", + new BigDecimal("-22222.222222222222222222222")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "-4,444,444,444,444,444,444.444444444444444444"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "88,888,888,888,888,888,888,888,888"); + checkParse("-88,888,888,888,888,888,888,888,888", + new BigDecimal("-22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "-4,444,444,444,444,444,444,444,444"); + checkParse("4444444444444444444444444", + new BigDecimal("1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "-1,010.10101010101"); + checkParse("-1,010.10101010101", new Double(252.5252525252525)); + + checkFormat(new Double(-2222.2222), "8,888.8888"); + checkParse("8888.8888", new Double(-2222.2222)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "-4,000"); + checkParse("-4,000", new Long(1000)); + + checkFormat(new Long(-250), "1,000"); + checkParse("1000", new Long(-250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("22222.222222222222222222222"), + "-88,888.888888888888888888888"); + checkParse("-88,888.888888888888888888888", + new BigDecimal("22222.222222222222222222222")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "4,444,444,444,444,444,444.444444444444444444"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("-1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "-88,888,888,888,888,888,888,888,888"); + checkParse("-88,888,888,888,888,888,888,888,888", + new BigDecimal("22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "4,444,444,444,444,444,444,444,444"); + checkParse("4444444444444444444444444", + new BigDecimal("-1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-3); + + /* + * Test for double/Double + */ + checkFormat(new Double(3333.3333333), "-9,999.9999999"); + checkParse("-10,000.00000000000", new Double(3333.3333333333335));// rounding error + + df.setParseIntegerOnly(true); + checkFormat(new Double(-3333.3333333), "9,999.9999999"); + checkParse("10,000.00000000000", new Long(-3333)); + df.setParseIntegerOnly(false); + checkFormat(new Double(-3333.3333333), "9,999.9999999"); + checkParse("10,000.00000000000", new Double(-3333.3333333333335));// rounding error + + /* + * Test for long/Long + */ + checkFormat(new Long(3333), "-9,999"); + df.setParseIntegerOnly(true); + checkParse("-10,000", new Long(3333)); + df.setParseIntegerOnly(false); + checkParse("-10000", new Double(3333.3333333333335));// rounding error + + checkFormat(new Long(-3333), "9,999"); + df.setParseIntegerOnly(true); + checkParse("10,000", new Long(-3333)); + df.setParseIntegerOnly(false); + checkParse("10000", new Double(-3333.3333333333335));// rounding error + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("33333.333333333333333333333"), + "-99,999.999999999999999999999"); + checkParse("-100,000.000000000000000000000", + new BigDecimal("33333.333333333333333333333")); + + checkFormat(new BigDecimal("-33333.333333333333333333333"), + "99,999.999999999999999999999"); + checkParse("100,000.000000000000000000000", + new BigDecimal("-33333.333333333333333333333")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("33333333333333333333333333"), + "-99,999,999,999,999,999,999,999,999"); + checkParse("-100,000,000,000,000,000,000,000,000", + new BigDecimal("33333333333333333333333333")); + + checkFormat(new BigInteger("-33333333333333333333333333"), + "99,999,999,999,999,999,999,999,999"); + df.setParseIntegerOnly(true); + checkParse("100,000,000,000,000,000,000,000,000.000", + new BigDecimal("-33333333333333333333333333")); + df.setParseIntegerOnly(false); + checkParse("100,000,000,000,000,000,000,000,000.000", + new BigDecimal("-33333333333333333333333333.333")); + + /* ================================================================ */ + + df = new DecimalFormat("0.#E0;-0.#E0"); + df.setMaximumFractionDigits(50); + df.setMultiplier(4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "1.01010101010101E3"); + checkParse("-1.01010101010101E3", new Double(-2.525252525252525E2)); + + checkFormat(new Double(-2222.2222), "-8.8888888E3"); + checkParse("8888.8888", new Double(2.2222222E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "4E3"); + checkParse("-4E3", new Long(-1000)); + + checkFormat(new Long(-250), "-1E3"); + checkParse("1000", new Long(250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("22222.222222222222222222222"), + "8.8888888888888888888888888E4"); + checkParse("-8.8888888888888888888888888E4", + new BigDecimal("-2.2222222222222222222222222E4")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "-4.444444444444444444444444444444444444E18"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "8.8888888888888888888888888E25"); + checkParse("-8.8888888888888888888888888E25", + new BigDecimal("-22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "-4.444444444444444444444444E24"); + checkParse("4444444444444444444444444", + new BigDecimal("1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "-1.01010101010101E3"); + checkParse("-1.01010101010101E3", new Double(2.525252525252525E2)); + + checkFormat(new Double(-2222.2222), "8.8888888E3"); + checkParse("8888.8888", new Double(-2.2222222E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "-4E3"); + checkParse("-4E3", new Long(1000)); + + checkFormat(new Long(-250), "1E3"); + checkParse("1000", new Long(-250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("22222.222222222222222222222"), + "-8.8888888888888888888888888E4"); + checkParse("-8.8888888888888888888888888E4", + new BigDecimal("2.2222222222222222222222222E4")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "4.444444444444444444444444444444444444E18"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("-1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "-8.8888888888888888888888888E25"); + checkParse("-8.8888888888888888888888888E25", + new BigDecimal("22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "4.444444444444444444444444E24"); + checkParse("4444444444444444444444444", + new BigDecimal("-1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-3); + + /* + * Test for double/Double + */ + checkFormat(new Double(3333.3333333), "-9.9999999999E3"); + checkParse("-1.00000000000000E3", new Double(3.33333333333333333E2)); + + df.setParseIntegerOnly(true); + checkFormat(new Double(-3333.3333333), "9.9999999999E3"); + checkParse("10.00000000000000E3", new Long(-3)); + df.setParseIntegerOnly(false); + checkFormat(new Double(-3333.3333333), "9.9999999999E3"); + checkParse("10.00000000000000E3", new Double(-3.33333333333333333E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(3333), "-9.999E3"); + df.setParseIntegerOnly(true); + checkParse("-1.0E4", new Long(0)); + df.setParseIntegerOnly(false); + checkParse("-1.0E4", new Double(3333.3333333333335)); + + checkFormat(new Long(-3333), "9.999E3"); + df.setParseIntegerOnly(true); + checkParse("10.0E4", new Long(-3)); + df.setParseIntegerOnly(false); + checkParse("10.0E4", new Double(-33333.3333333333336)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("333.333333333333333333333333"), + "-9.99999999999999999999999999E2"); + checkParse("-1.0000000000000000000000000E3", + new BigDecimal("3.333333333333333333333333E2")); + + df.setParseIntegerOnly(true); + checkFormat(new BigDecimal("-333.333333333333333333333333"), + "9.99999999999999999999999999E2"); + checkParse("10.0000000000000000000000000E3", + new BigDecimal("-3")); + df.setParseIntegerOnly(false); + checkFormat(new BigDecimal("-333.333333333333333333333333"), + "9.99999999999999999999999999E2"); + checkParse("1.0000000000000000000000000E3", + new BigDecimal("-3.333333333333333333333333E2")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("33333333333333333333333333"), + "-9.9999999999999999999999999E25"); + checkParse("-100000000000000000000000000", + new BigDecimal("33333333333333333333333333")); + + checkFormat(new BigInteger("-33333333333333333333333333"), + "9.9999999999999999999999999E25"); + df.setParseIntegerOnly(true); + checkParse("100000000000000000000000000000", + new BigDecimal("-33333333333333333333333333333")); + df.setParseIntegerOnly(false); + checkParse("100000000000000000000000000.000", + new BigDecimal("-33333333333333333333333333.333")); + + /* ================================================================ */ + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format/parse with DecimalFormat"); + } + } + + static void checkFormat(Number num, String expected) { + String got = df.format(num); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error:" + + "\n\tnumber: " + num + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, Double expected) { + Double got = (Double)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(double) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, Long expected) { + Long got = (Long)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(long) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, BigDecimal expected) { + BigDecimal got = (BigDecimal)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(BigDecimal) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4838107.java b/jdk/test/java/text/Format/NumberFormat/Bug4838107.java new file mode 100644 index 00000000000..a15d537d8e6 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4838107.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4838107 8008577 + * @summary Confirm that DecimalFormat can format a number with negative exponent number correctly. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4838107 + */ + +import java.math.*; +import java.util.*; +import java.text.*; + +public class Bug4838107 extends IntlTest { + + static DecimalFormat df; + static DecimalFormatSymbols dfs; + static boolean err = false; + + static public void main(String[] args) { + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + /** + * This bug is about exponential formatting. But I added test cases for: + * - Double and BigDecimal numbers which don't have exponent parts. + * - Long and BigInteger numbers which don't support exponential + * notation. + * because there are few test cases for suffix and prefix. + * And also, I added test cases to guarantee further formatting and + * parsing using the same DecimalFormat instance will not change the + * Number's value anymore. + */ + + test_double(); + test_long(); + test_BigDecimal(); + test_BigInteger(); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format with DecimalFormat"); + } + } + + static void test_double() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new Double(1234), "1,234"); + test(new Double(0.1234), "0.123"); // rounded + test(new Double(-1234), "-1,234"); + test(new Double(-0.1234), "-0.123"); // rounded + + test(new Double(Double.POSITIVE_INFINITY), "\u221e"); + test(new Double(Double.NEGATIVE_INFINITY), "-\u221e"); + test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix + test(new Double(0.0), "0"); + test(new Double(-0.0), "-0"); // with the minus sign + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

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

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

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

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

1.234Em01"); + + prepareFormatter("

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

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

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

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

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

1.234Em01"); + + prepareFormatter("

#.###E00;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#,###;

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

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

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

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

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

#,###;

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

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

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

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

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

+ *   class = className
+ *   args = (arg1 arg2 ...)
+ *   valueClass = className
+ *   valueArgs = (arg1 arg2 ...)
+ * 
+ * The second map dictates what to test, and should consist of the following: + *
+ *   length = lengthOfFormattedString
+ *   text = Result of Formatting
+ *   0...lengthOfFormattedString = (arg1 arg2 ...)
+ *   limits = ( range1 range2 ...)
+ *   fieldPositions = ( fp1 fp2 ...)
+ * 
+ * lengthOfFormattedString indicate the total length of formatted + * string. text indicates the resulting string. + * 0...x where x == lengthOfFormattedString - 1 is + * an array of the attributes that should exist at the particular + * location. limits is an array of maps, where each map + * can be used to test the bounds of a set of attributes. Each map will + * consist of: + *
+ *   attributes = array of attributes
+ *   begin = start location
+ *   begin2 = second start location
+ *   end = limit location
+ *   end2 = second limit location
+ * 
+ * These are tested by iterating from begin to end in the CharacterIterator + * and doing the following at each index: + *
+ *   getRunStart() == begin
+ *   getRunStart(attributes) == begin2
+ *   getRunLimit() == end
+ *   getRunLimit(attributes) == end2
+ * 
+ * fieldPositions is used to test the results of invoking + * format with a FieldPosition. + * fieldPositions is an array of maps, where each map contains + * the following: + *
+ *   field = Integer field reference (optional)
+ *   fieldID = Object reference
+ *   begin = begin index of FieldPosition after formatting
+ *   end = end index of FieldPosition after formatting
+ * 
+ * Any lines starting with {@code '#'} are comment lines and ignored. + */ +public class FormatIteratorTest extends IntlTest { + private static HashMap attrs; + private Format format; + private Object value; + private String text; + + public static final Object ARG0_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG1_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG2_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG3_FIELD_ID = MessageFormat. + Field.ARGUMENT; + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + // The current tests are only appropriate for US. If tests are + // added for other locales are added, then a property should be + // added to each file (test) to be able to specify the locale. + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + new FormatIteratorTest().run(args); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + public FormatIteratorTest() { + } + + public void testDecimalFormat() { + _test(new File(System.getProperty("test.src", "."), + "decimalFormat.props")); + } + + public void testMessageFormat() { + _test(new File(System.getProperty("test.src", "."), + "messageFormat.props")); + } + + public void testDateFormat() { + _test(new File(System.getProperty("test.src", "."), + "dateFormat.props")); + } + + private void _test(File file) { + try { + attrs = new HashMap(); + logln("testing: " + file); + PParser parser = new PParser(); + Hashtable contents = parser.parse(new BufferedReader( + new FileReader(file))); + Vector test = (Vector)contents.get("tests"); + + for (int counter = 0; counter < test.size(); counter++) { + logln("creating: " + (counter / 2)); + + AttributedCharacterIterator iterator = + create((Hashtable)test.get(counter)); + + logln("verifying: " + (counter / 2)); + verify(iterator, (Hashtable)test.get(++counter)); + } + } catch (IOException ioe) { + errln("Error reading: " + ioe); + } + } + + public void verify(AttributedCharacterIterator iterator,Hashtable table) { + int length = Integer.parseInt((String)table.get("length")); + + // Verify the text + if (!getText(iterator).equals( + escapeIfNecessary((String)table.get("text")))) { + String text = getText(iterator); + + errln("text doesn't match, got: " + getText(iterator)); + } + if (iterator.getBeginIndex() != 0) { + errln("Bogus start: " + iterator.getBeginIndex()); + } + if (iterator.getEndIndex() != length) { + errln("Bogus end: " + iterator.getEndIndex()); + } + for (int counter = 0; counter < length; counter++) { + iterator.setIndex(counter); + if (!verifyAttributes(iterator.getAttributes().keySet(), + makeAttributes((Vector)table.get(Integer. + toString(counter))))) { + errln("Attributes don't match at " + counter + " expecting " + + makeAttributes((Vector)table.get(Integer.toString + (counter))) + " got " + + iterator.getAttributes().keySet()); + } + } + for (int counter = length - 1; counter >= 0; counter--) { + iterator.setIndex(counter); + if (!verifyAttributes(iterator.getAttributes().keySet(), + makeAttributes((Vector)table.get(Integer. + toString(counter))))) { + errln("Attributes don't match at " + counter + " expecting " + + makeAttributes((Vector)table.get(Integer.toString + (counter))) + " got " + + iterator.getAttributes().keySet()); + } + } + verifyLimits(iterator, table); + + text = escapeIfNecessary((String)table.get("text")); + Vector fps = (Vector)table.get("fieldPositions"); + + if (fps != null) { + for (int counter = 0; counter < fps.size(); counter++) { + verifyFieldPosition(counter, (Hashtable)fps.get(counter)); + } + } + } + + private void verifyLimits(AttributedCharacterIterator iterator, + Hashtable table) { + Vector limits = (Vector)table.get("limits"); + + if (limits != null) { + for (int counter = 0; counter < limits.size(); counter++) { + verifyLimit(iterator, (Hashtable)limits.get(counter)); + } + } + } + + private void verifyLimit(AttributedCharacterIterator iterator, + Hashtable table) { + int begin = Integer.parseInt((String)table.get("begin")); + int end = Integer.parseInt((String)table.get("end")); + Set attrs = makeAttributes((Vector)table.get("attributes")); + String begin2S = (String)table.get("begin2"); + int begin2 = (begin2S != null) ? Integer.parseInt(begin2S) : begin; + String end2S = (String)table.get("end2"); + int end2 = (end2S != null) ? Integer.parseInt(end2S) : end; + + for (int counter = begin; counter < end; counter++) { + iterator.setIndex(counter); + if (iterator.getRunStart() != begin) { + errln("Begin doesn't match want " + begin + " got " + + iterator.getRunStart() + " at " + counter + " attrs " + + attrs); + } + if (iterator.getRunStart(attrs) != begin2) { + errln("Begin2 doesn't match want " + begin2 + " got " + + iterator.getRunStart(attrs) + " at " + counter + + " attrs " + attrs); + } + if (iterator.getRunLimit() != end) { + errln("End doesn't match want " + end + " got " + + iterator.getRunLimit() + " at " + counter + " attrs " + + attrs); + } + if (iterator.getRunLimit(attrs) != end2) { + errln("End2 doesn't match want " + end2 + " got " + + iterator.getRunLimit(attrs) + " at " + counter + + " attrs " + attrs); + } + } + } + + private boolean verifyAttributes(Set a, Set b) { + boolean aEmpty = (a.size() == 0); + boolean bEmpty = (b.size() == 0); + + if (aEmpty && bEmpty) { + return true; + } + else if (aEmpty || bEmpty) { + return false; + } + return a.equals(b); + } + + private String getText(AttributedCharacterIterator iterator) { + StringBuffer buffer = new StringBuffer(); + + for (int counter = 0; counter < iterator.getEndIndex(); counter++) { + buffer.append(iterator.setIndex(counter)); + } + return buffer.toString(); + } + + private void verifyFieldPosition(int index, Hashtable table) { + Object o = table.get("field"); + int begin = Integer.parseInt((String)table.get("begin")); + int end = Integer.parseInt((String)table.get("end")); + + if (o != null) { + FieldPosition fp = new FieldPosition(((Integer) + lookupField((String)o)).intValue()); + + verifyFieldPosition(fp, begin, end, index); + } + o = table.get("fieldID"); + if (o != null) { + FieldPosition fp = new FieldPosition((Format.Field) + lookupField((String)o)); + verifyFieldPosition(fp, begin, end, index); + } + } + + private void verifyFieldPosition(FieldPosition fp, int begin, int end, + int index) { + StringBuffer buffer = new StringBuffer(); + + format.format(value, buffer, fp); + if (fp.getBeginIndex() != begin) { + errln("bogus begin want " + begin + " got " + fp.getBeginIndex() + + " for " + fp + " at " + index); + } + if (fp.getEndIndex() != end) { + errln("bogus end want " + end + " got " + fp.getEndIndex() + + " for " + fp + " at " + index); + } + if (!buffer.toString().equals(text)) { + errln("Text does not match, want !" + buffer.toString() + + "! got !" + text + "!"); + } + } + + public AttributedCharacterIterator create(Hashtable table) { + format = (Format)createInstance((String)table.get("class"), + ((Vector)table.get("args")).toArray()); + value = createInstance((String)table.get("valueClass"), + ((Vector)table.get("valueArgs")).toArray()); + + logln("Created format: " + format + " value " + value); + AttributedCharacterIterator aci = format. + formatToCharacterIterator(value); + + logln("Obtained Iterator: " + aci); + return aci; + } + + public Format.Field makeAttribute(String name) { + return (Format.Field)lookupField(name); + } + + private Object createInstance(String className, Object[] args) { + if (className.equals("java.lang.reflect.Array")) { + for (int counter = 0; counter < args.length; counter++) { + if (args[counter] instanceof Vector) { + Vector v = (Vector)args[counter]; + + args[counter] = createInstance((String)v.get(0), + ((Vector)v.get(1)).toArray()); + } + } + return args; + } + for (int counter = 0; counter < args.length; counter++) { + args[counter] = escapeIfNecessary((String)args[counter]); + } + try { + if (className.equals("java.util.concurrent.atomic.AtomicInteger")) { + return new AtomicInteger(Integer.valueOf((String)args[0])); + } else if (className.equals("java.util.concurrent.atomic.AtomicLong")) { + return new AtomicLong(Long.valueOf((String)args[0])); + } else { + Class klass = lookupClass(className); + Constructor cons = klass.getConstructor( + new Class[] { String.class }); + Object value = cons.newInstance(args); + + return value; + } + } catch (Throwable th) { + errln("Error creating instance " + th); + return null; + } + } + + private Class lookupClass(String name) throws ClassNotFoundException { + try { + Class klass = Class.forName(name); + + return klass; + } catch (ClassNotFoundException e1) {} + + try { + Class klass = Class.forName("java.lang." + name); + + return klass; + } catch (ClassNotFoundException e1) {} + + Class klass = Class.forName("java.text." + name); + + return klass; + } + + private Object lookupField(String name) { + Throwable error = null; + + try { + int dotIndex = name.indexOf('.'); + Class klass = lookupClass(name.substring(0, dotIndex)); + String fieldName = name.substring(dotIndex + 1); + Field[] fields = klass.getFields(); + + for (int counter = fields.length - 1; counter >= 0; counter--) { + if (fields[counter].getName().equals(fieldName)) { + return fields[counter].get(null); + } + } + } catch (Throwable th) { + error = th; + } + errln("Could not lookup field " + name + " " + error); + return null; + } + + protected String escapeIfNecessary(String string) { + if (string != null) { + int index; + + if ((index = string.indexOf("\\u")) != -1) { + StringBuffer sb = new StringBuffer(string.substring(0, index)); + + sb.append((char)Integer.parseInt( + string.substring(index + 2, index + 6), 16)); + sb.append(string.substring(index + 6)); + string = sb.toString(); + } + } + return string; + } + + public Set makeAttributes(Vector names) { + HashSet set = new HashSet(Math.max(1, names.size())); + + for (int counter = 0; counter < names.size(); counter++) { + set.add(makeAttribute((String)names.get(counter))); + } + return set; + } +} diff --git a/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt b/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt new file mode 100644 index 00000000000..5428b76680c --- /dev/null +++ b/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt @@ -0,0 +1,32 @@ +# +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized MessageFormat.Field for Bug4769840. + +aced00057372001d6a6176612e746578742e4d657373616765466f726d617424 +4669656c646da23d2c7b46bfaa020000787200166a6176612e746578742e466f +726d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e7465 +78742e417474726962757465644368617261637465724974657261746f722441 +7474726962757465811e7426cd47175c0200014c00046e616d657400124c6a61 +76612f6c616e672f537472696e673b78707400166d6573736167652061726775 +6d656e74206669656c64 diff --git a/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt b/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt new file mode 100644 index 00000000000..12851638adf --- /dev/null +++ b/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized NumberFormat.Field for Bug4769840. + +aced00057372001c6a6176612e746578742e4e756d626572466f726d61742446 +69656c646802a038193ff37a020000787200166a6176612e746578742e466f72 +6d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e746578 +742e417474726962757465644368617261637465724974657261746f72244174 +74726962757465811e7426cd47175c0200014c00046e616d657400124c6a6176 +612f6c616e672f537472696e673b7870740007696e7465676572 diff --git a/jdk/test/java/text/Format/common/PParser.java b/jdk/test/java/text/Format/common/PParser.java new file mode 100644 index 00000000000..6ada76b1059 --- /dev/null +++ b/jdk/test/java/text/Format/common/PParser.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; + +/* + * assignment : key = value; + * key : string + * value : string | array | dict + * nValue : , value + * array : ( value nValue ) + * nAssignment: , assignment|value + * dict : { assignment* } + * string : "*" or anything but a ,(){}= + * + * special characters: ,(){}= + */ + +public class PParser { + protected static final int OPEN_PAIR = 1; + protected static final int CLOSE_PAIR = 2; + protected static final int OPEN_ARRAY = 3; + protected static final int CLOSE_ARRAY = 4; + protected static final int MORE = 5; + protected static final int EQUAL = 6; + protected static final int STRING = 7; + protected static final int WS = 8; + + protected Reader reader; + protected boolean bufferedToken; + protected StringBuffer stringBuffer = new StringBuffer(); + protected int lastChar; + protected int lastToken; + protected int lineNumber; + protected int column; + + public PParser() { + } + + public Hashtable parse(Reader r) throws IOException { + this.reader = r; + bufferedToken = false; + lineNumber = 0; + column = 0; + if (getToken() != OPEN_PAIR) { + error("No initial open"); + } + return parsePair(); + } + + protected Object parseValue(int lookAhead) throws IOException { + int token; + + if (lookAhead == -1) { + token = getToken(); + } else { + token = lookAhead; + } + switch (token) { + case STRING: + return stringBuffer.toString(); + case OPEN_ARRAY: + return parseArray(); + case OPEN_PAIR: + return parsePair(); + default: + error("Expecting value"); + } + return null; + } + + protected Object parseArray() throws IOException { + Vector array = new Vector(); + int token; + + while ((token = getToken()) != CLOSE_ARRAY) { + if (token == MORE) { + token = getToken(); + } + if (token != CLOSE_ARRAY) { + array.addElement(parseValue(token)); + } + } + return array; + } + + protected Hashtable parsePair() throws IOException { + Hashtable ht = new Hashtable(11); + int token; + + while ((token = getToken()) != CLOSE_PAIR) { + if (token != STRING) { + error("Pair expecting string got"); + } + String key = stringBuffer.toString(); + + if (getToken() != EQUAL) { + error("Expecting = "); + } + + Object value = parseValue(-1); + ht.put(key, value); + } + return ht; + } + + protected void ungetToken() { + if (bufferedToken) { + error("Can not buffer more than one token"); + } + bufferedToken = true; + } + + protected int getToken() throws IOException { + int token = getToken(false, false); + + return token; + } + + protected int getToken(boolean wantsWS, boolean inString) + throws IOException { + if (bufferedToken) { + bufferedToken = false; + if (lastToken != WS || wantsWS) { + return lastToken; + } + } + while ((lastChar = reader.read()) != -1) { + // If a line starts with '#', skip the line. + if (column == 0 && lastChar == '#') { + while ((lastChar = reader.read()) != -1 + && lastChar != '\n') { + } + if (lastChar == -1) { + break; + } + } + + column++; + switch(lastChar) { + case '\n': + lineNumber++; + column = 0; + case ' ': + case '\r': + case '\t': + if (wantsWS) { + lastToken = WS; + return WS; + } + break; + case ',': + lastToken = MORE; + return MORE; + case '(': + lastToken = OPEN_ARRAY; + return OPEN_ARRAY; + case ')': + lastToken = CLOSE_ARRAY; + return CLOSE_ARRAY; + case '{': + lastToken = OPEN_PAIR; + return OPEN_PAIR; + case '}': + lastToken = CLOSE_PAIR; + return CLOSE_PAIR; + case '=': + lastToken = EQUAL; + return EQUAL; + case '"': + lastToken = STRING; + if (!inString) { + stringBuffer.setLength(0); + while (true) { + getToken(true, true); + if (lastChar == '"') { + lastToken = STRING; + return STRING; + } + stringBuffer.append((char)lastChar); + } + } + return STRING; + default: + lastToken = STRING; + if (!inString) { + stringBuffer.setLength(0); + stringBuffer.append((char)lastChar); + while (getToken(true, true) == STRING) { + if (lastChar == '"') { + error("Unexpected quote"); + } + stringBuffer.append((char)lastChar); + } + ungetToken(); + } + return STRING; + } + } + return -1; + } + + protected void error(String errorString) { + throw new RuntimeException(errorString + " at line " + lineNumber + " column " + column); + } + + public static void dump(Object o) { + if (o instanceof String) { + System.out.print(o); + } else if(o instanceof Vector) { + Enumeration e = ((Vector)o).elements(); + + dump(" ("); + while (e.hasMoreElements()) { + dump(e.nextElement()); + dump(" -- "); + } + dump(" )"); + } else { + Hashtable ht = (Hashtable)o; + Enumeration e = ht.keys(); + + dump(" {"); + while (e.hasMoreElements()) { + Object key = e.nextElement(); + + dump(key); + dump(" = "); + dump(ht.get(key)); + dump(";"); + } + dump(" }"); + } + } + + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("need filename"); + } else { + try { + FileReader fr = new FileReader(args[0]); + PParser parser = new PParser(); + Hashtable ht = parser.parse(fr); + + dump(ht); + System.out.println(); + } + catch (IOException ioe) { + System.out.println("Couldn't parse: " + ioe); + } + } + } +} diff --git a/jdk/test/java/text/Format/common/dateFormat.props b/jdk/test/java/text/Format/common/dateFormat.props new file mode 100644 index 00000000000..22bb9a44d78 --- /dev/null +++ b/jdk/test/java/text/Format/common/dateFormat.props @@ -0,0 +1,333 @@ +# +# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Test data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.SimpleDateFormat + args = ("M/dd/yy") + valueClass = java.util.Date + valueArgs = ("7/10/71") + } + { + length = 7 + text = "7/10/71" + 0 = (DateFormat$Field.MONTH) + 1 = () + 2 = (DateFormat$Field.DAY_OF_MONTH) + 3 = (DateFormat$Field.DAY_OF_MONTH) + 4 = () + 5 = (DateFormat$Field.YEAR) + 6 = (DateFormat$Field.YEAR) + limits = ( { attributes = (DateFormat$Field.MONTH) + begin = 0 end = 1} + { attributes = () + begin = 1 begin2 = 0 end = 2 end2 = 7} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 5 end2 = 7} + { attributes = (DateFormat$Field.YEAR) + begin = 5 end = 7} + ) + fieldPositions = + ( + { + field = DateFormat.MONTH_FIELD + fieldID = DateFormat$Field.MONTH + begin = 0 end = 1 + } + { + field = DateFormat.DATE_FIELD + fieldID = DateFormat$Field.DAY_OF_MONTH + begin = 2 end = 4 + } + { + field = DateFormat.YEAR_FIELD + fieldID = DateFormat$Field.YEAR + begin = 5 end = 7 + } + ) + } + + { + class = java.text.SimpleDateFormat + args = ("EEEEEEE MMMMMMMMMMMMM yyyy GG") + valueClass = java.util.Date + valueArgs = ("12/10/2020") + } + { + length = 25 + text = "Thursday December 2020 AD" + 0 = (DateFormat$Field.DAY_OF_WEEK) + 1 = (DateFormat$Field.DAY_OF_WEEK) + 2 = (DateFormat$Field.DAY_OF_WEEK) + 3 = (DateFormat$Field.DAY_OF_WEEK) + 4 = (DateFormat$Field.DAY_OF_WEEK) + 5 = (DateFormat$Field.DAY_OF_WEEK) + 6 = (DateFormat$Field.DAY_OF_WEEK) + 7 = (DateFormat$Field.DAY_OF_WEEK) + 8 = () + 9 = (DateFormat$Field.MONTH) + 10 = (DateFormat$Field.MONTH) + 11 = (DateFormat$Field.MONTH) + 12 = (DateFormat$Field.MONTH) + 13 = (DateFormat$Field.MONTH) + 14 = (DateFormat$Field.MONTH) + 15 = (DateFormat$Field.MONTH) + 16 = (DateFormat$Field.MONTH) + 17 = () + 18 = (DateFormat$Field.YEAR) + 19 = (DateFormat$Field.YEAR) + 20 = (DateFormat$Field.YEAR) + 21 = (DateFormat$Field.YEAR) + 22 = () + 23 = (DateFormat$Field.ERA) + 24 = (DateFormat$Field.ERA) + limits = ( { attributes = (DateFormat$Field.DAY_OF_WEEK) + begin = 0 end = 8} + { attributes = () + begin = 8 begin2 = 0 end = 9 end2 = 25} + { attributes = (DateFormat$Field.MONTH) + begin = 9 end = 17} + { attributes = () + begin = 17 begin2 = 0 end = 18 end2 = 25} + { attributes = (DateFormat$Field.YEAR) + begin = 18 end = 22} + { attributes = () + begin = 22 begin2 = 0 end = 23 end2 = 25} + { attributes = (DateFormat$Field.ERA) + begin = 23 end = 25} + ) + fieldPositions = + ( + { + field = DateFormat.DAY_OF_WEEK_FIELD + fieldID = DateFormat$Field.DAY_OF_WEEK + begin = 0 end = 8 + } + { + field = DateFormat.MONTH_FIELD + fieldID = DateFormat$Field.MONTH + begin = 9 end = 17 + } + { + field = DateFormat.YEAR_FIELD + fieldID = DateFormat$Field.YEAR + begin = 18 end = 22 + } + { + field = DateFormat.ERA_FIELD + fieldID = DateFormat$Field.ERA + begin = 23 end = 25 + } + ) + } + + { + class = java.text.SimpleDateFormat + args = ("h HH:mm:ss:SSS aa") + valueClass = java.util.Date + valueArgs = ("1/1/2000 2:52:12 PM") + } + { + length = 17 + text = "2 14:52:12:000 PM" + 0 = (DateFormat$Field.HOUR1) + 1 = () + 2 = (DateFormat$Field.HOUR_OF_DAY0) + 3 = (DateFormat$Field.HOUR_OF_DAY0) + 4 = () + 5 = (DateFormat$Field.MINUTE) + 6 = (DateFormat$Field.MINUTE) + 7 = () + 8 = (DateFormat$Field.SECOND) + 9 = (DateFormat$Field.SECOND) + 10 = () + 11 = (DateFormat$Field.MILLISECOND) + 12 = (DateFormat$Field.MILLISECOND) + 13 = (DateFormat$Field.MILLISECOND) + 14 = () + 15 = (DateFormat$Field.AM_PM) + 16 = (DateFormat$Field.AM_PM) + limits = ( { attributes = (DateFormat$Field.HOUR1) + begin = 0 end = 1} + { attributes = () + begin = 1 begin2 = 0 end = 2 end2 = 17} + { attributes = (DateFormat$Field.HOUR_OF_DAY0) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 5 end2 = 17} + { attributes = (DateFormat$Field.MINUTE) + begin = 5 end = 7} + { attributes = () + begin = 7 begin2 = 0 end = 8 end2 = 17} + { attributes = (DateFormat$Field.SECOND) + begin = 8 end = 10} + { attributes = () + begin = 10 begin2 = 0 end = 11 end2 = 17} + { attributes = (DateFormat$Field.MILLISECOND) + begin = 11 end = 14} + { attributes = () + begin = 14 begin2 = 0 end = 15 end2 = 17} + { attributes = (DateFormat$Field.AM_PM) + begin = 15 end = 17} + ) + fieldPositions = + ( + { + field = DateFormat.HOUR1_FIELD + fieldID = DateFormat$Field.HOUR1 + begin = 0 end = 1 + } + { + field = DateFormat.HOUR_OF_DAY0_FIELD + fieldID = DateFormat$Field.HOUR_OF_DAY0 + begin = 2 end = 4 + } + { + field = DateFormat.MINUTE_FIELD + fieldID = DateFormat$Field.MINUTE + begin = 5 end = 7 + } + { + field = DateFormat.SECOND_FIELD + fieldID = DateFormat$Field.SECOND + begin = 8 end = 10 + } + { + field = DateFormat.MILLISECOND_FIELD + fieldID = DateFormat$Field.MILLISECOND + begin = 11 end = 14 + } + { + field = DateFormat.AM_PM_FIELD + fieldID = DateFormat$Field.AM_PM + begin = 15 end = 17 + } + ) + } + + + { + class = java.text.SimpleDateFormat + args = ("kk KK DDD FF ww WW zz") + valueClass = java.util.Date + valueArgs = ("4/26/2031 2:02:52 AM") + } + { + length = 22 + text = "02 02 116 04 17 04 PDT" + 0 = (DateFormat$Field.HOUR_OF_DAY1) + 1 = (DateFormat$Field.HOUR_OF_DAY1) + 2 = () + 3 = (DateFormat$Field.HOUR0) + 4 = (DateFormat$Field.HOUR0) + 5 = () + 6 = (DateFormat$Field.DAY_OF_YEAR) + 7 = (DateFormat$Field.DAY_OF_YEAR) + 8 = (DateFormat$Field.DAY_OF_YEAR) + 9 = () + 10 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + 11 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + 12 = () + 13 = (DateFormat$Field.WEEK_OF_YEAR) + 14 = (DateFormat$Field.WEEK_OF_YEAR) + 15 = () + 16 = (DateFormat$Field.WEEK_OF_MONTH) + 17 = (DateFormat$Field.WEEK_OF_MONTH) + 18 = () + 19 = (DateFormat$Field.TIME_ZONE) + 20 = (DateFormat$Field.TIME_ZONE) + 21 = (DateFormat$Field.TIME_ZONE) + limits = ( { attributes = (DateFormat$Field.HOUR_OF_DAY1) + begin = 0 end = 2} + { attributes = () + begin = 2 begin2 = 0 end = 3 end2 = 22} + { attributes = (DateFormat$Field.HOUR0) + begin = 3 end = 5} + { attributes = () + begin = 5 begin2 = 0 end = 6 end2 = 22} + { attributes = (DateFormat$Field.DAY_OF_YEAR) + begin = 6 end = 9} + { attributes = () + begin = 9 begin2 = 0 end = 10 end2 = 22} + { attributes = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + begin = 10 end = 12} + { attributes = () + begin = 12 begin2 = 0 end = 13 end2 = 22} + { attributes = (DateFormat$Field.WEEK_OF_YEAR) + begin = 13 end = 15} + { attributes = () + begin = 15 begin2 = 0 end = 16 end2 = 22} + { attributes = (DateFormat$Field.WEEK_OF_MONTH) + begin = 16 end = 18} + { attributes = () + begin = 18 begin2 = 0 end = 19 end2 = 22} + { attributes = (DateFormat$Field.TIME_ZONE) + begin = 19 end = 22} + ) + fieldPositions = + ( + { + field = DateFormat.HOUR_OF_DAY1_FIELD + fieldID = DateFormat$Field.HOUR_OF_DAY1 + begin = 0 end = 2 + } + { + field = DateFormat.HOUR0_FIELD + fieldID = DateFormat$Field.HOUR0 + begin = 3 end = 5 + } + { + field = DateFormat.DAY_OF_YEAR_FIELD + fieldID = DateFormat$Field.DAY_OF_YEAR + begin = 6 end = 9 + } + { + field = DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD + fieldID = DateFormat$Field.DAY_OF_WEEK_IN_MONTH + begin = 10 end = 12 + } + { + field = DateFormat.WEEK_OF_YEAR_FIELD + fieldID = DateFormat$Field.WEEK_OF_YEAR + begin = 13 end = 15 + } + { + field = DateFormat.WEEK_OF_MONTH_FIELD + fieldID = DateFormat$Field.WEEK_OF_MONTH + begin = 16 end = 18 + } + { + field = DateFormat.TIMEZONE_FIELD + fieldID = DateFormat$Field.TIME_ZONE + begin = 19 end = 22 + } + ) + } + ) +} diff --git a/jdk/test/java/text/Format/common/decimalFormat.props b/jdk/test/java/text/Format/common/decimalFormat.props new file mode 100644 index 00000000000..e6d9adc7974 --- /dev/null +++ b/jdk/test/java/text/Format/common/decimalFormat.props @@ -0,0 +1,1280 @@ +# +# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Test data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Integer + valueArgs = ("1234567") + } + { + length = 9 + text = "1,234,567" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 9} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 9 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###.##") + valueClass = java.lang.Float + valueArgs = ("567.78") + } + { + length = 6 + text = "567.78" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 4 = (NumberFormat$Field.FRACTION) + 5 = (NumberFormat$Field.FRACTION) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 3 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.FRACTION) + begin = 4 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 3 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 3 end = 4 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 4 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("0.#E00") + valueClass = java.lang.Float + valueArgs = ("1200") + } + { + length = 6 + text = "1.2E03" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 2 = (NumberFormat$Field.FRACTION) + 3 = (NumberFormat$Field.EXPONENT_SYMBOL) + 4 = (NumberFormat$Field.EXPONENT) + 5 = (NumberFormat$Field.EXPONENT) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.FRACTION) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.EXPONENT_SYMBOL) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.EXPONENT) + begin = 4 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 1 end = 2 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 2 end = 3 + } + { + fieldID = NumberFormat$Field.EXPONENT_SYMBOL + begin = 3 end = 4 + } + { + fieldID = NumberFormat$Field.EXPONENT + begin = 4 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("0.#E00") + valueClass = java.lang.Float + valueArgs = ("-.0012") + } + { + length = 8 + text = "-1.2E-03" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 3 = (NumberFormat$Field.FRACTION) + 4 = (NumberFormat$Field.EXPONENT_SYMBOL) + 5 = (NumberFormat$Field.EXPONENT_SIGN) + 6 = (NumberFormat$Field.EXPONENT) + 7 = (NumberFormat$Field.EXPONENT) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.FRACTION) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.EXPONENT_SYMBOL) + begin = 4 end = 5} + { attributes = (NumberFormat$Field.EXPONENT_SIGN) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.EXPONENT) + begin = 6 end = 8} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 2 end = 3 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 3 end = 4 + } + { + fieldID = NumberFormat$Field.EXPONENT_SYMBOL + begin = 4 end = 5 + } + { + fieldID = NumberFormat$Field.EXPONENT_SIGN + begin = 5 end = 6 + } + { + fieldID = NumberFormat$Field.EXPONENT + begin = 6 end = 8 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###;(#,###)") + valueClass = java.lang.Integer + valueArgs = ("-1234") + } + { + length = 7 + text = "(1,234)" + 0 = () + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = () + limits = ( { attributes = () + begin = 0 end = 1 end2 = 7 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = () + begin = 6 begin2 = 0 end = 7} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 6 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###;-#,###") + valueClass = java.lang.Integer + valueArgs = ("-134") + } + { + length = 4 + text = "-134" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 4 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("+#,###") + valueClass = java.lang.Integer + valueArgs = ("134") + } + { + length = 4 + text = "+134" + 0 = () + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end2 = 4 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 4 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("##.0#%") + valueClass = java.lang.Float + valueArgs = (".1234") + } + { + length = 6 + text = "12.34%" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 3 = (NumberFormat$Field.FRACTION) + 4 = (NumberFormat$Field.FRACTION) + 5 = (NumberFormat$Field.PERCENT) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 2 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 2 end = 3 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 3 end = 5 } + { attributes = (NumberFormat$Field.PERCENT) + begin = 5 end = 6 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 2 end = 3 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 3 end = 5 + } + { + fieldID = NumberFormat$Field.PERCENT + begin = 5 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,##.#\u2030") + valueClass = java.lang.Float + valueArgs = (".1234") + } + { + length = 7 + text = "1,23.4\u2030" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.GROUPING_SEPARATOR + NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 5 = (NumberFormat$Field.FRACTION) + 6 = (NumberFormat$Field.PERMILLE) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 4 } + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 4 end = 5 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 5 end = 6 } + { attributes = (NumberFormat$Field.PERMILLE) + begin = 6 end = 7 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 4 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 4 end = 5 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 5 end = 6 + } + { + fieldID = NumberFormat$Field.PERMILLE + begin = 6 end = 7 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("\u00A40,000.00") + valueClass = java.lang.Float + valueArgs = ("12.51") + } + { + length = 9 + text = "$0,012.51" + 0 = (NumberFormat$Field.CURRENCY) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.GROUPING_SEPARATOR + NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 7 = (NumberFormat$Field.FRACTION) + 8 = (NumberFormat$Field.FRACTION) + limits = ( { attributes = (NumberFormat$Field.CURRENCY) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 6 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 3 begin2 = 1 end = 6 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 6 end = 7 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 7 end = 9 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.CURRENCY + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 6 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 6 end = 7 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 7 end = 9 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.math.BigInteger + valueArgs = ("-12345678901234567890123456789012345") + } + { + length = 47 + text = "-12,345,678,901,234,567,890,123,456,789,012,345" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + 26 = (NumberFormat$Field.INTEGER) + 27 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 28 = (NumberFormat$Field.INTEGER) + 29 = (NumberFormat$Field.INTEGER) + 30 = (NumberFormat$Field.INTEGER) + 31 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 32 = (NumberFormat$Field.INTEGER) + 33 = (NumberFormat$Field.INTEGER) + 34 = (NumberFormat$Field.INTEGER) + 35 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 36 = (NumberFormat$Field.INTEGER) + 37 = (NumberFormat$Field.INTEGER) + 38 = (NumberFormat$Field.INTEGER) + 39 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 40 = (NumberFormat$Field.INTEGER) + 41 = (NumberFormat$Field.INTEGER) + 42 = (NumberFormat$Field.INTEGER) + 43 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 44 = (NumberFormat$Field.INTEGER) + 45 = (NumberFormat$Field.INTEGER) + 46 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 3 end2 = 47 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 3 end = 4 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 4 begin2 = 1 end = 7 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 7 end = 8 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 8 begin2 = 1 end = 11 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 11 end = 12 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 12 begin2 = 1 end = 15 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 15 end = 16 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 16 begin2 = 1 end = 19 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 20 begin2 = 1 end = 23 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 23 end = 24 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 24 begin2 = 1 end = 27 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 27 end = 28 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 28 begin2 = 1 end = 31 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 31 end = 32 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 32 begin2 = 1 end = 35 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 35 end = 36 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 36 begin2 = 1 end = 39 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 39 end = 40 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 40 begin2 = 1 end = 43 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 43 begin2 = 43 end = 44 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 44 begin2 = 1 end = 47} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 47 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###.#####################") + valueClass = java.math.BigDecimal + valueArgs = ("-123456789012345678901234567890.12345678901234567890") + } + { + length = 60 + text = "-123,456,789,012,345,678,901,234,567,890.1234567890123456789" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 25 = (NumberFormat$Field.INTEGER) + 26 = (NumberFormat$Field.INTEGER) + 27 = (NumberFormat$Field.INTEGER) + 28 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 29 = (NumberFormat$Field.INTEGER) + 30 = (NumberFormat$Field.INTEGER) + 31 = (NumberFormat$Field.INTEGER) + 32 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 33 = (NumberFormat$Field.INTEGER) + 34 = (NumberFormat$Field.INTEGER) + 35 = (NumberFormat$Field.INTEGER) + 36 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 37 = (NumberFormat$Field.INTEGER) + 38 = (NumberFormat$Field.INTEGER) + 39 = (NumberFormat$Field.INTEGER) + 40 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 41 = (NumberFormat$Field.FRACTION) + 42 = (NumberFormat$Field.FRACTION) + 43 = (NumberFormat$Field.FRACTION) + 44 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 46 = (NumberFormat$Field.FRACTION) + 47 = (NumberFormat$Field.FRACTION) + 48 = (NumberFormat$Field.FRACTION) + 49 = (NumberFormat$Field.FRACTION) + 50 = (NumberFormat$Field.FRACTION) + 51 = (NumberFormat$Field.FRACTION) + 52 = (NumberFormat$Field.FRACTION) + 53 = (NumberFormat$Field.FRACTION) + 54 = (NumberFormat$Field.FRACTION) + 55 = (NumberFormat$Field.FRACTION) + 56 = (NumberFormat$Field.FRACTION) + 57 = (NumberFormat$Field.FRACTION) + 58 = (NumberFormat$Field.FRACTION) + 59 = (NumberFormat$Field.FRACTION) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 end2 = 40 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 4 end = 5 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 5 begin2 = 1 end = 8 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 8 end = 9 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 9 begin2 = 1 end = 12 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 12 end = 13 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 13 begin2 = 1 end = 16 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 16 end = 17 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 17 begin2 = 1 end = 20 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 20 end = 21 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 21 begin2 = 1 end = 24 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 24 end = 25 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 25 begin2 = 1 end = 28 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 28 end = 29 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 29 begin2 = 1 end = 32 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 32 end = 33 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 33 begin2 = 1 end = 36 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 36 end = 37 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 37 begin2 = 1 end = 40 end2 = 40} + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 40 end = 41 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 41 begin2 = 41 end = 60 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 40 end = 41 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 40 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 41 end = 60 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Long + valueArgs = ("9223372036854775807") + } + { + length = 25 + text = "9,223,372,036,854,775,807" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 25} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 25 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicLong + valueArgs = ("9223372036854775807") + } + { + length = 25 + text = "9,223,372,036,854,775,807" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 25} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 25 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Long + valueArgs = ("-9223372036854775808") + } + { + length = 26 + text = "-9,223,372,036,854,775,808" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 26} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 26 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicLong + valueArgs = ("-9223372036854775808") + } + { + length = 26 + text = "-9,223,372,036,854,775,808" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 26} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 26 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicInteger + valueArgs = ("2147483647") + } + { + length = 13 + text = "2,147,483,647" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 13} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 13 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicInteger + valueArgs = ("-2147483648") + } + { + length = 14 + text = "-2,147,483,648" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 14 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + ) +} diff --git a/jdk/test/java/text/Format/common/messageFormat.props b/jdk/test/java/text/Format/common/messageFormat.props new file mode 100644 index 00000000000..c8aaeecfd32 --- /dev/null +++ b/jdk/test/java/text/Format/common/messageFormat.props @@ -0,0 +1,520 @@ +# +# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Test data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.MessageFormat + args = ("0={0} 1={1}") + valueClass = java.lang.reflect.Array + valueArgs = ("zero" "one") + } + { + length = 12 + text = "0=zero 1=one" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = (MessageFormat$Field.ARGUMENT) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = () + 7 = () + 8 = () + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT) + 11 = (MessageFormat$Field.ARGUMENT) + limits = ( { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 6} + { attributes = () + begin = 0 begin2 = 0 end = 2 end2 = 12} + { attributes = () + begin = 6 begin2 = 0 end = 9 end2 = 12} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 9 end = 12} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 6 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0} 1={1} 0={0}") + valueClass = java.lang.reflect.Array + valueArgs = ("ze" "on") + } + { + length = 14 + text = "0=ze 1=on 0=ze" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = () + 5 = () + 6 = () + 7 = (MessageFormat$Field.ARGUMENT) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = () + 10 = () + 11 = () + 12 = (MessageFormat$Field.ARGUMENT) + 13 = (MessageFormat$Field.ARGUMENT) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 7 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 7 end = 9} + { attributes = () + begin = 9 begin2 = 0 end = 12 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 12 end = 14} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 4 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("5/23/2001")) (Integer ("20122"))) + } + { + length = 23 + text = "0=May 23, 2001 1=20,122" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 17 end = 19 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 17 end = 19 end2 = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 20 begin2 = 17 end = 23} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("1/22/2003")) (java.math.BigInteger ("12345678901234567890123456789012345"))) + } + { + length = 63 + text = "0=Jan 22, 2003 1=12,345,678,901,234,567,890,123,456,789,012,345" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 48 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 49 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 50 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 51 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 52 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 53 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 54 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 55 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 56 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 57 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 58 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 59 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 60 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 61 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 62 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 63} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 63} + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 17 end = 19 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 20 begin2 = 17 end = 23 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 23 end = 24 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 24 begin2 = 17 end = 27 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 27 end = 28 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 28 begin2 = 17 end = 31 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 31 end = 32 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 32 begin2 = 17 end = 35 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 35 end = 36 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 36 begin2 = 17 end = 39 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 39 end = 40 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 40 begin2 = 17 end = 43 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 43 end = 44 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 44 begin2 = 17 end = 47 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 47 end = 48 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 48 begin2 = 17 end = 51 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 51 end = 52 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 52 begin2 = 17 end = 55 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 55 end = 56 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 56 begin2 = 17 end = 59 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 59 end = 60 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 60 begin2 = 17 end = 63} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("1/26/2003")) (java.math.BigDecimal ("-12345678901234567890.1239"))) + } + { + length = 48 + text = "0=Jan 26, 2003 1=-12,345,678,901,234,567,890.124" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.SIGN) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.DECIMAL_SEPARATOR) + 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 48} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 48} + + { attributes = (NumberFormat$Field.SIGN) + begin = 17 end = 18 } + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 18 end = 20 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 20 end = 21 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 21 begin2 = 18 end = 24 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 24 end = 25 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 25 begin2 = 18 end = 28 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 28 end = 29 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 29 begin2 = 18 end = 32 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 32 end = 33 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 33 begin2 = 18 end = 36 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 36 end = 37 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 37 begin2 = 18 end = 40 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 40 end = 41 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 41 begin2 = 18 end = 44 end2 = 44} + + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 44 begin2 = 41 end = 45 end2 = 48} + + { attributes = (NumberFormat$Field.FRACTION + MessageFormat$Field.ARGUMENT) + begin = 45 end = 48} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,choice,-1#neg| 0#zero | 1#more}xx") + valueClass = java.lang.reflect.Array + valueArgs = ((Integer ("-11"))) + } + { + length = 7 + text = "0=negxx" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = (MessageFormat$Field.ARGUMENT) + 5 = () + 6 = () + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 7} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5} + { attributes = () + begin = 5 begin2 = 0 end = 7} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 5 + } + ) + } + ) +} + diff --git a/jdk/test/java/text/testlib/HexDumpReader.java b/jdk/test/java/text/testlib/HexDumpReader.java new file mode 100644 index 00000000000..31a820d04d4 --- /dev/null +++ b/jdk/test/java/text/testlib/HexDumpReader.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * HexDumpReader provides utility methods to read a hex dump text file + * and convert to an InputStream. The format supported by the methods + * can be generated by the following command. + * + * $ od -vw -t x1 foo | sed -r -e 's/^[0-9]+ ?//' -e 's/ //g' -e '/^$/d' + */ +public class HexDumpReader { + public static InputStream getStreamFromHexDump(String fileName) { + return getStreamFromHexDump(new File(System.getProperty("test.src", "."), + fileName)); + } + + public static InputStream getStreamFromHexDump(File hexFile) { + ByteArrayBuilder bab = new ByteArrayBuilder(); + int lineNo = 0; + try (BufferedReader reader + = new BufferedReader(new InputStreamReader(new FileInputStream(hexFile), + "us-ascii"))) { + String line; + while ((line = reader.readLine()) != null) { + lineNo++; + line = line.trim(); + // Skip blank and comment lines. + if (line.length() == 0) { + continue; + } + int x = line.indexOf('#'); + if (x == 0) { + continue; + } + if (x > 0) { + line = line.substring(0, x).trim(); + } + int len = line.length(); + for (int i = 0; i < len; i += 2) { + bab.put((byte)Integer.parseInt(line, i, i + 2, 16)); + } + } + } catch (Exception e) { + throw new RuntimeException(hexFile.getName() + ":error:" + lineNo + ": " + e, e); + } + return new ByteArrayInputStream(bab.toArray()); + } + + + private static class ByteArrayBuilder { + private static final int BUFFER_SIZE = 4096; + + private int size; + private List bytes; + private byte[] current; + private int offset; + + ByteArrayBuilder() { + bytes = new ArrayList<>(); + current = new byte[BUFFER_SIZE]; + } + + void put(byte b) { + if (offset == BUFFER_SIZE) { + bytes.add(current); + current = new byte[BUFFER_SIZE]; + offset = 0; + } + current[offset++] = b; + size++; + } + + byte[] toArray() { + byte[] buf = new byte[size]; + int ptr = 0; + for (byte[] ba : bytes) { + System.arraycopy(ba, 0, buf, ptr, ba.length); + ptr += ba.length; + } + System.arraycopy(current, 0, buf, ptr, offset); + assert ptr + offset == size; + return buf; + } + } + +} diff --git a/jdk/test/java/text/testlib/IntlTest.java b/jdk/test/java/text/testlib/IntlTest.java new file mode 100644 index 00000000000..d8ae8572f30 --- /dev/null +++ b/jdk/test/java/text/testlib/IntlTest.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * IntlTest is a base class for tests that can be run conveniently from + * the command line as well as under the Java test harness. + *

+ * Sub-classes implement a set of public void methods named "Test*" or + * "test*" with no arguments. Each of these methods performs some + * test. Test methods should indicate errors by calling either err() or + * errln(). This will increment the errorCount field and may optionally + * print a message to the log. Debugging information may also be added to + * the log via the log and logln methods. These methods will add their + * arguments to the log only if the test is being run in verbose mode. + */ +public abstract class IntlTest { + + //------------------------------------------------------------------------ + // Everything below here is boilerplate code that makes it possible + // to add a new test by simply adding a method to an existing class. + //------------------------------------------------------------------------ + + protected IntlTest() { + // Populate testMethods with all the test methods. + Method[] methods = getClass().getDeclaredMethods(); + for (Method method : methods) { + if (Modifier.isPublic(method.getModifiers()) + && method.getReturnType() == void.class + && method.getParameterCount() == 0) { + String name = method.getName(); + if (name.length() > 4) { + if (name.startsWith("Test") || name.startsWith("test")) { + testMethods.put(name, method); + } + } + } + } + } + + protected void run(String[] args) throws Exception + { + // Set up the log and reference streams. We use PrintWriters in order to + // take advantage of character conversion. The JavaEsc converter will + // convert Unicode outside the ASCII range to Java's \\uxxxx notation. + log = new PrintWriter(System.out, true); + + // Parse the test arguments. They can be either the flag + // "-verbose" or names of test methods. Create a list of + // tests to be run. + List testsToRun = new ArrayList<>(args.length); + for (String arg : args) { + switch (arg) { + case "-verbose": + verbose = true; + break; + case "-prompt": + prompt = true; + break; + case "-nothrow": + nothrow = true; + break; + default: + Method m = testMethods.get(arg); + if (m == null) { + System.out.println("Method " + arg + ": not found"); + usage(); + return; + } + testsToRun.add(m); + break; + } + } + + // If no test method names were given explicitly, run them all. + if (testsToRun.isEmpty()) { + testsToRun.addAll(testMethods.values()); + } + + System.out.println(getClass().getName() + " {"); + indentLevel++; + + // Run the list of tests given in the test arguments + for (Method testMethod : testsToRun) { + int oldCount = errorCount; + + writeTestName(testMethod.getName()); + + try { + testMethod.invoke(this, new Object[0]); + } catch (IllegalAccessException e) { + errln("Can't acces test method " + testMethod.getName()); + } catch (InvocationTargetException e) { + errln("Uncaught exception thrown in test method " + + testMethod.getName()); + e.getTargetException().printStackTrace(this.log); + } + writeTestResult(errorCount - oldCount); + } + indentLevel--; + writeTestResult(errorCount); + + if (prompt) { + System.out.println("Hit RETURN to exit..."); + try { + System.in.read(); + } catch (IOException e) { + System.out.println("Exception: " + e.toString() + e.getMessage()); + } + } + if (nothrow) { + System.exit(errorCount); + } + } + + /** + * Adds the given message to the log if we are in verbose mode. + */ + protected void log(String message) { + logImpl(message, false); + } + + protected void logln(String message) { + logImpl(message, true); + } + + protected void logln() { + logImpl(null, true); + } + + private void logImpl(String message, boolean newline) { + if (verbose) { + if (message != null) { + indent(indentLevel + 1); + log.print(message); + } + if (newline) { + log.println(); + } + } + } + + protected void err(String message) { + errImpl(message, false); + } + + protected void errln(String message) { + errImpl(message, true); + } + + private void errImpl(String message, boolean newline) { + errorCount++; + indent(indentLevel + 1); + log.print(message); + if (newline) { + log.println(); + } + log.flush(); + + if (!nothrow) { + throw new RuntimeException(message); + } + } + + protected int getErrorCount() { + return errorCount; + } + + protected void writeTestName(String testName) { + indent(indentLevel); + log.print(testName); + log.flush(); + needLineFeed = true; + } + + protected void writeTestResult(int count) { + if (!needLineFeed) { + indent(indentLevel); + log.print("}"); + } + needLineFeed = false; + + if (count != 0) { + log.println(" FAILED"); + } else { + log.println(" Passed"); + } + } + + /* + * Returns a spece-delimited hex String. + */ + protected static String toHexString(String s) { + StringBuilder sb = new StringBuilder(" "); + + for (int i = 0; i < s.length(); i++) { + sb.append(Integer.toHexString(s.charAt(i))); + sb.append(' '); + } + + return sb.toString(); + } + + private void indent(int distance) { + if (needLineFeed) { + log.println(" {"); + needLineFeed = false; + } + log.print(SPACES.substring(0, distance * 2)); + } + + /** + * Print a usage message for this test class. + */ + void usage() { + System.out.println(getClass().getName() + + ": [-verbose] [-nothrow] [-prompt] [test names]"); + + System.out.println(" Available test names:"); + for (String methodName : testMethods.keySet()) { + System.out.println("\t" + methodName); + } + } + + private boolean prompt; + private boolean nothrow; + protected boolean verbose; + + private PrintWriter log; + private int indentLevel; + private boolean needLineFeed; + private int errorCount; + + private final Map testMethods = new LinkedHashMap<>(); + + private static final String SPACES = " "; +} diff --git a/jdk/test/java/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"); - } - } -}