undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
213
test/jdk/java/util/AbstractCollection/ToArrayTest.java
Normal file
213
test/jdk/java/util/AbstractCollection/ToArrayTest.java
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 7121314
|
||||
* @summary AbstractCollection.toArray(T[]) doesn't return the given array
|
||||
* in concurrent modification.
|
||||
* @author Ulf Zibis, David Holmes
|
||||
*/
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ToArrayTest {
|
||||
|
||||
static class TestCollection<E> extends AbstractCollection<E> {
|
||||
private final E[] elements;
|
||||
private int[] sizes;
|
||||
private int nextSize;
|
||||
|
||||
public TestCollection(E[] elements) {
|
||||
this.elements = elements;
|
||||
setSizeSequence(new int[] { elements.length });
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the values that size() will return on each use. The next
|
||||
* call to size will return sizes[0], then sizes[1] etc. This allows us
|
||||
* to emulate a concurrent change to the contents of the collection
|
||||
* without having to perform concurrent changes. If sizes[n+1] contains
|
||||
* a larger value, the collection will appear to have shrunk when
|
||||
* iterated; if a smaller value then the collection will appear to have
|
||||
* grown when iterated.
|
||||
*/
|
||||
void setSizeSequence(int... sizes) {
|
||||
this.sizes = sizes;
|
||||
nextSize = 0;
|
||||
}
|
||||
|
||||
/* can change collection's size after each invocation */
|
||||
@Override
|
||||
public int size() {
|
||||
return sizes[nextSize == sizes.length - 1 ? nextSize : nextSize++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
int pos = 0;
|
||||
|
||||
public boolean hasNext() {
|
||||
return pos < sizes[nextSize];
|
||||
}
|
||||
public E next() {
|
||||
return elements[pos++];
|
||||
}
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException(
|
||||
"Not supported yet.");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static final Object[] OBJECTS = { new Object(), new Object(), new Object() };
|
||||
static final TestCollection<?> CANDIDATE = new TestCollection<Object>(OBJECTS);
|
||||
static final int CAP = OBJECTS.length; // capacity of the CANDIDATE
|
||||
static final int LAST = CAP - 1; // last possible array index
|
||||
Object[] a;
|
||||
Object[] res;
|
||||
|
||||
int last() {
|
||||
return a.length - 1;
|
||||
}
|
||||
|
||||
protected void test() throws Throwable {
|
||||
// Check array type conversion
|
||||
res = new TestCollection<>(new Object[] { "1", "2" }).toArray(new String[0]);
|
||||
check(res instanceof String[]);
|
||||
check(res.length == 2);
|
||||
check(res[1] == "2");
|
||||
|
||||
// Check incompatible type of target array
|
||||
try {
|
||||
res = CANDIDATE.toArray(new String[CAP]);
|
||||
check(false);
|
||||
} catch (Throwable t) {
|
||||
check(t instanceof ArrayStoreException);
|
||||
}
|
||||
|
||||
// Check more elements than a.length
|
||||
a = new Object[CAP - 1]; // appears too small
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res != a);
|
||||
check(res[LAST] != null);
|
||||
|
||||
// Check equal elements as a.length
|
||||
a = new Object[CAP]; // appears to match
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res == a);
|
||||
check(res[last()] != null);
|
||||
|
||||
// Check equal elements as a.length
|
||||
a = new Object[CAP + 1]; // appears too big
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res == a);
|
||||
check(res[last()] == null);
|
||||
|
||||
// Check less elements than expected, but more than a.length
|
||||
a = new Object[CAP - 2]; // appears too small
|
||||
CANDIDATE.setSizeSequence(CAP, CAP - 1);
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res != a);
|
||||
check(res.length == CAP - 1);
|
||||
check(res[LAST - 1] != null);
|
||||
|
||||
// Check less elements than expected, but equal as a.length
|
||||
a = Arrays.copyOf(OBJECTS, CAP); // appears to match
|
||||
CANDIDATE.setSizeSequence(CAP, CAP - 1);
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res == a);
|
||||
check(res[last()] == null);
|
||||
|
||||
// Check more elements than expected and more than a.length
|
||||
a = new Object[CAP - 1]; // appears to match
|
||||
CANDIDATE.setSizeSequence(CAP - 1, CAP);
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res != a);
|
||||
check(res[LAST] != null);
|
||||
|
||||
// Check more elements than expected, but equal as a.length
|
||||
a = new Object[CAP - 1]; // appears to match
|
||||
CANDIDATE.setSizeSequence(CAP - 2, CAP - 1);
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res == a);
|
||||
check(res[last()] != null);
|
||||
|
||||
// Check more elements than expected, but less than a.length
|
||||
a = Arrays.copyOf(OBJECTS, CAP); // appears to match
|
||||
CANDIDATE.setSizeSequence(CAP - 2, CAP - 1);
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res == a);
|
||||
check(res[last()] == null);
|
||||
|
||||
test_7121314();
|
||||
}
|
||||
|
||||
/*
|
||||
* Major target of this testcase, bug 7121314.
|
||||
*/
|
||||
protected void test_7121314() throws Throwable {
|
||||
// Check equal elements as a.length, but less than expected
|
||||
a = new Object[CAP - 1]; // appears too small
|
||||
CANDIDATE.setSizeSequence(CAP, CAP - 1);
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res == a);
|
||||
check(res[last()] != null);
|
||||
|
||||
// Check less elements than a.length and less than expected
|
||||
a = Arrays.copyOf(OBJECTS, CAP - 1); // appears too small
|
||||
CANDIDATE.setSizeSequence(CAP, CAP - 2);
|
||||
res = CANDIDATE.toArray(a);
|
||||
check(res == a);
|
||||
check(res[last()] == null);
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ToArrayTest testcase = new ToArrayTest();
|
||||
try {
|
||||
testcase.test();
|
||||
} catch (Throwable t) {
|
||||
unexpected(t);
|
||||
}
|
||||
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new Exception("Some tests failed");
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() { passed++; }
|
||||
static void fail() { failed++; Thread.dumpStack(); }
|
||||
static void fail(String msg) { System.out.println(msg); fail(); }
|
||||
static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
|
||||
static void check(boolean cond) { if (cond) pass(); else fail(); }
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else {System.out.println(x + " not equal to " + y); fail(); }
|
||||
}
|
||||
}
|
||||
84
test/jdk/java/util/AbstractCollection/ToString.java
Normal file
84
test/jdk/java/util/AbstractCollection/ToString.java
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4486049 6282555 6318622
|
||||
* @summary toString method fails if size changes in between a call to size
|
||||
* and an attempt to iterate.
|
||||
* @author Josh Bloch, Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class ToString {
|
||||
private static void realMain(String[] args) {
|
||||
testCollection(new LinkedHashSet<Object>() {
|
||||
public int size() {
|
||||
return super.size() + 1; // Lies, lies, all lies!
|
||||
}});
|
||||
testCollection(new ArrayList<Object>());
|
||||
testCollection(new Vector<Object>());
|
||||
testCollection(new CopyOnWriteArrayList<Object>());
|
||||
testCollection(new CopyOnWriteArraySet<Object>());
|
||||
}
|
||||
|
||||
private static void testCollection(Collection<Object> c) {
|
||||
System.out.println(c.getClass());
|
||||
equal(c.toString(), "[]");
|
||||
check(c.add("x"));
|
||||
equal(c.toString(), "[x]");
|
||||
check(c.add("y"));
|
||||
equal(c.toString(), "[x, y]");
|
||||
check(c.add(null));
|
||||
equal(c.toString(), "[x, y, null]");
|
||||
if (c instanceof AbstractCollection) {
|
||||
check(c.add(c));
|
||||
equal(c.toString(), "[x, y, null, (this Collection)]");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() { passed++; }
|
||||
static void fail() { failed++; Thread.dumpStack(); }
|
||||
static void fail(String msg) { System.out.println(msg); fail(); }
|
||||
static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
|
||||
static void check(boolean cond) { if (cond) pass(); else fail(); }
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else {System.out.println(x + " not equal to " + y); fail(); }}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try { realMain(args); } catch (Throwable t) { unexpected(t); }
|
||||
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new Exception("Some tests failed");
|
||||
}
|
||||
}
|
||||
52
test/jdk/java/util/AbstractList/CheckForComodification.java
Normal file
52
test/jdk/java/util/AbstractList/CheckForComodification.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4902078
|
||||
* @summary concurrent modification not detected on 2nd to last iteration
|
||||
* @author Josh Bloch
|
||||
*
|
||||
* @ignore Bug fix temporarily removed as it uncovered other bugs (4992226)
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.List;
|
||||
|
||||
public class CheckForComodification {
|
||||
private static final int LENGTH = 10;
|
||||
public static void main(String[] args) throws Exception {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (int i = 0; i < LENGTH; i++)
|
||||
list.add(i);
|
||||
try {
|
||||
for (int i : list)
|
||||
if (i == LENGTH - 2)
|
||||
list.remove(i);
|
||||
} catch (ConcurrentModificationException e) {
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("No ConcurrentModificationException");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8161558
|
||||
* @summary ListIterator should not discard cause on exception
|
||||
* @run testng CheckForIndexOutOfBoundsException
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import java.util.AbstractList;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
// Fixed size list containing two elements
|
||||
|
||||
class MyList extends AbstractList<String> {
|
||||
|
||||
private static final int SIZE = 2;
|
||||
|
||||
public String get(int i) {
|
||||
if (i >= 0 && i < SIZE) {
|
||||
return "x";
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException(i);
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public class CheckForIndexOutOfBoundsException {
|
||||
|
||||
List<String> list = new MyList();
|
||||
|
||||
|
||||
@Test
|
||||
public void checkIteratorNext() {
|
||||
var iterator = list.iterator(); // position at start
|
||||
try {
|
||||
for (int i = 0; i <= list.size(); i++) {
|
||||
iterator.next();
|
||||
}
|
||||
fail("Failing checkIteratorNext() - NoSuchElementException should have been thrown");
|
||||
} catch (NoSuchElementException e) {
|
||||
checkAssertOnException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkListIteratorNext() {
|
||||
var iterator = list.listIterator(list.size()); // position at end
|
||||
try {
|
||||
iterator.next();
|
||||
fail("Failing checkListIteratorNext() - NoSuchElementException should have been thrown");
|
||||
} catch (NoSuchElementException e) {
|
||||
checkAssertOnException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkListIteratorPrevious() {
|
||||
var iterator = list.listIterator(0); // position at start
|
||||
try {
|
||||
iterator.previous();
|
||||
fail("Failing checkListIteratorPrevious() - NoSuchElementException should have been thrown");
|
||||
} catch (NoSuchElementException e) {
|
||||
checkAssertOnException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAssertOnException(NoSuchElementException e) {
|
||||
var cause = e.getCause();
|
||||
assertNotNull(cause, "Exception.getCause()");
|
||||
assertTrue(cause instanceof IndexOutOfBoundsException, "Exception.getCause() should be an " +
|
||||
"IndexOutOfBoundsException");
|
||||
var msg = e.getMessage();
|
||||
assertNotNull(msg, "Exception.getMessage()");
|
||||
assertTrue(msg.contains("IndexOutOfBoundsException"), "Exception.getMessage() should " +
|
||||
"contain the string 'IndexOutOfBoundsException'");
|
||||
}
|
||||
}
|
||||
|
||||
78
test/jdk/java/util/AbstractList/FailFastIterator.java
Normal file
78
test/jdk/java/util/AbstractList/FailFastIterator.java
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4189896
|
||||
* @summary AbstractList iterators previously checked for co-modification
|
||||
* *after* the set/add/remove operations were performed.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class FailFastIterator {
|
||||
public static void main(String[] args) throws Exception {
|
||||
List orig = new ArrayList(100);
|
||||
for (int i=0; i<100; i++)
|
||||
orig.add(new Integer(i));
|
||||
|
||||
List copy = new ArrayList(orig);
|
||||
try {
|
||||
ListIterator i = copy.listIterator();
|
||||
i.next();
|
||||
copy.remove(99);
|
||||
copy.add(new Integer(99));
|
||||
i.remove();
|
||||
throw new Exception("remove: iterator didn't fail fast");
|
||||
} catch (ConcurrentModificationException e) {
|
||||
}
|
||||
if (!copy.equals(orig))
|
||||
throw new Exception("remove: iterator didn't fail fast enough");
|
||||
|
||||
try {
|
||||
ListIterator i = copy.listIterator();
|
||||
i.next();
|
||||
copy.remove(99);
|
||||
copy.add(new Integer(99));
|
||||
i.set(new Integer(666));
|
||||
throw new Exception("set: iterator didn't fail fast");
|
||||
} catch (ConcurrentModificationException e) {
|
||||
}
|
||||
if (!copy.equals(orig))
|
||||
throw new Exception("set: iterator didn't fail fast enough");
|
||||
|
||||
try {
|
||||
ListIterator i = copy.listIterator();
|
||||
copy.remove(99);
|
||||
copy.add(new Integer(99));
|
||||
i.add(new Integer(666));
|
||||
throw new Exception("add: iterator didn't fail fast");
|
||||
} catch (ConcurrentModificationException e) {
|
||||
}
|
||||
if (!copy.equals(orig))
|
||||
throw new Exception("add: iterator didn't fail fast enough");
|
||||
}
|
||||
}
|
||||
53
test/jdk/java/util/AbstractList/HasNextAfterException.java
Normal file
53
test/jdk/java/util/AbstractList/HasNextAfterException.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4375048
|
||||
* @summary AbstractList's ListIterator.hasNext() returns
|
||||
* true, after ListIterator.previous() causes
|
||||
* an exception for an empty list.
|
||||
* @author Konstantin Kladko
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class HasNextAfterException {
|
||||
public static void main(String[] args) {
|
||||
List list = new ArrayList();
|
||||
ListIterator i = list.listIterator();
|
||||
try {
|
||||
i.previous();
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
}
|
||||
if (i.hasNext()) {
|
||||
throw new RuntimeException(
|
||||
"ListIterator.hasNext() returns true for an empty "
|
||||
+ "List after ListIterator.previous().");
|
||||
}
|
||||
}
|
||||
}
|
||||
72
test/jdk/java/util/AbstractMap/AbstractMapClone.java
Normal file
72
test/jdk/java/util/AbstractMap/AbstractMapClone.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4328748
|
||||
* @summary AbstractMap's clone() method is implemented to
|
||||
* reset AbstractMap's private fields after super.clone()
|
||||
*
|
||||
* @author Konstantin Kladko
|
||||
*/
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class AbstractMapClone extends AbstractMap implements Cloneable {
|
||||
|
||||
private Map map = new HashMap();
|
||||
|
||||
public Set entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value) {
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
final AbstractMapClone clone;
|
||||
try {
|
||||
clone = (AbstractMapClone)super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
clone.map = (Map)((HashMap)map).clone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
AbstractMapClone m1 = new AbstractMapClone();
|
||||
m1.put("1", "1");
|
||||
Set k1 = m1.keySet();
|
||||
AbstractMapClone m2 = (AbstractMapClone)m1.clone();
|
||||
Set k2 = m2.keySet();
|
||||
m2.put("2","2");
|
||||
if (k1.equals(k2)) {
|
||||
throw new RuntimeException("AbstractMap.clone() failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
61
test/jdk/java/util/AbstractMap/Equals.java
Normal file
61
test/jdk/java/util/AbstractMap/Equals.java
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4503672
|
||||
* @summary AbstractMap.equals and AbstractSet.equals are fragile: they
|
||||
* throw exceptions when they should return false.
|
||||
* @author Josh Bloch
|
||||
*/
|
||||
public class Equals {
|
||||
public static void main(String[] args) {
|
||||
Map m = new HashMap();
|
||||
m.put(null, "");
|
||||
Map h = new Hashtable();
|
||||
h.put("", "");
|
||||
if (m.equals(h))
|
||||
throw new RuntimeException("1");
|
||||
|
||||
Map m1 = new TreeMap();
|
||||
m1.put(new Integer(42), "The Answer");
|
||||
Map m2 = new TreeMap();
|
||||
m2.put("The Answer", new Integer(42));
|
||||
if (m1.equals(m2))
|
||||
throw new RuntimeException("3");
|
||||
|
||||
Set s1 = new TreeSet();
|
||||
s1.add(new Integer(666));
|
||||
Set s2 = new TreeSet();
|
||||
s2.add("Great googly moogly!");
|
||||
if (s1.equals(s2))
|
||||
throw new RuntimeException("2");
|
||||
}
|
||||
}
|
||||
105
test/jdk/java/util/AbstractMap/SimpleEntries.java
Normal file
105
test/jdk/java/util/AbstractMap/SimpleEntries.java
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4904074 6328220 6330389 8308167
|
||||
* @modules java.base/jdk.internal.util
|
||||
* @summary Basic tests for several Map.Entry implementations
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.util.Map;
|
||||
import jdk.internal.util.NullableKeyValueHolder;
|
||||
|
||||
import static java.util.AbstractMap.SimpleEntry;
|
||||
import static java.util.AbstractMap.SimpleImmutableEntry;
|
||||
|
||||
public class SimpleEntries {
|
||||
private static String k = "foo";
|
||||
private static Long v = 1L;
|
||||
private static Long v2 = 2L;
|
||||
private static void realMain(String[] args) throws Throwable {
|
||||
testEntry(new SimpleEntry<String,Long>(k,v));
|
||||
testEntry(new SimpleImmutableEntry<String,Long>(k,v));
|
||||
testEntry(Map.entry(k,v));
|
||||
testEntry(Map.Entry.copyOf(Map.entry(k,v)));
|
||||
testEntry(new NullableKeyValueHolder(k,v));
|
||||
testNullEntry(new SimpleEntry<String,Long>(null,null));
|
||||
testNullEntry(new SimpleImmutableEntry<String,Long>(null,null));
|
||||
testNullEntry(new NullableKeyValueHolder(null,null));
|
||||
}
|
||||
|
||||
private static void testEntry(Map.Entry<String,Long> e) {
|
||||
equal(e.getKey(), k);
|
||||
equal(e.getValue(), v);
|
||||
equal(e, new SimpleEntry<String,Long>(k,v));
|
||||
check(! e.equals(new SimpleEntry<String,Long>(k,v2)));
|
||||
check(! e.equals(null));
|
||||
equal(e, new SimpleImmutableEntry<String,Long>(k,v));
|
||||
equal(e.toString(), k+"="+v);
|
||||
check(e.hashCode() == 101575); // hash("foo") ^ hash(1L)
|
||||
if (e instanceof SimpleEntry) {
|
||||
equal(e.setValue(v2), v);
|
||||
equal(e.getValue(), v2);
|
||||
equal(e.setValue(null), v2);
|
||||
equal(e.getValue(), null);
|
||||
} else {
|
||||
try { e.setValue(v2); fail(); }
|
||||
catch (UnsupportedOperationException t) {}
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
}
|
||||
|
||||
private static void testNullEntry(Map.Entry<String,Long> e) {
|
||||
equal(e.getKey(), null);
|
||||
equal(e.getValue(), null);
|
||||
equal(e, new SimpleEntry<String,Long>(null, null));
|
||||
equal(e, new SimpleImmutableEntry<String,Long>(null, null));
|
||||
equal(e.toString(), "null=null");
|
||||
check(e.hashCode() == 0);
|
||||
if (e instanceof SimpleEntry) {
|
||||
equal(e.setValue(v), null);
|
||||
equal(e.getValue(), v);
|
||||
} else {
|
||||
try { e.setValue(null); fail(); }
|
||||
catch (UnsupportedOperationException t) {}
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
||||
55
test/jdk/java/util/AbstractMap/ToString.java
Normal file
55
test/jdk/java/util/AbstractMap/ToString.java
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4486049
|
||||
* @summary toString method fails if size changes in between a call to size
|
||||
* and an attempt to iterate.
|
||||
* @author Josh Bloch
|
||||
*/
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ToString {
|
||||
public static void main(String[] args) {
|
||||
Map m = new LyingMap();
|
||||
if (!m.toString().equals("{}"))
|
||||
throw new RuntimeException(m.toString() + "!= {}");
|
||||
|
||||
m.put("x", "1");
|
||||
if (!m.toString().equals("{x=1}"))
|
||||
throw new RuntimeException(m.toString() + "!= {x=1}");
|
||||
|
||||
m.put("y", "2");
|
||||
if (!m.toString().equals("{x=1, y=2}"))
|
||||
throw new RuntimeException(m.toString() + "!= {x=1, y=2}");
|
||||
}
|
||||
}
|
||||
|
||||
class LyingMap extends LinkedHashMap {
|
||||
public int size() {
|
||||
return super.size() + 1; // Lies, lies, all lies!
|
||||
}
|
||||
}
|
||||
56
test/jdk/java/util/AbstractSequentialList/AddAll.java
Normal file
56
test/jdk/java/util/AbstractSequentialList/AddAll.java
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4295163
|
||||
* @summary AddAll(int, Collection) intersperses the Collection with this List.
|
||||
*/
|
||||
|
||||
import java.util.AbstractSequentialList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class AddAll {
|
||||
public static void main(String[] args) throws Exception {
|
||||
List t = new FooList();
|
||||
t.add("b"); t.add("a"); t.add("r");
|
||||
t.addAll(0, Arrays.asList(new String[] {"f","o","o"}));
|
||||
if (!t.equals(Arrays.asList(new String[] {"f","o","o","b","a","r"})))
|
||||
throw new Exception("addAll is broken");
|
||||
}
|
||||
}
|
||||
|
||||
class FooList extends AbstractSequentialList {
|
||||
List a = new ArrayList();
|
||||
|
||||
public int size() {
|
||||
return a.size();
|
||||
}
|
||||
|
||||
public ListIterator listIterator(int index) {
|
||||
return a.listIterator(index);
|
||||
}
|
||||
}
|
||||
153
test/jdk/java/util/ArrayDeque/WhiteBox.java
Normal file
153
test/jdk/java/util/ArrayDeque/WhiteBox.java
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 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/
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @modules java.base/java.util:open
|
||||
* @run testng WhiteBox
|
||||
* @summary White box tests of implementation details
|
||||
*/
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Test
|
||||
public class WhiteBox {
|
||||
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
final VarHandle ELEMENTS, HEAD, TAIL;
|
||||
|
||||
WhiteBox() throws ReflectiveOperationException {
|
||||
Class<?> klazz = ArrayDeque.class;
|
||||
MethodHandles.Lookup lookup
|
||||
= MethodHandles.privateLookupIn(klazz, MethodHandles.lookup());
|
||||
ELEMENTS = lookup.findVarHandle(klazz, "elements", Object[].class);
|
||||
HEAD = lookup.findVarHandle(klazz, "head", int.class);
|
||||
TAIL = lookup.findVarHandle(klazz, "tail", int.class);
|
||||
}
|
||||
|
||||
Object[] elements(ArrayDeque d) { return (Object[]) ELEMENTS.get(d); }
|
||||
int head(ArrayDeque d) { return (int) HEAD.get(d); }
|
||||
int tail(ArrayDeque d) { return (int) TAIL.get(d); }
|
||||
|
||||
void checkCapacity(ArrayDeque d, int capacity) {
|
||||
assertTrue(d.isEmpty());
|
||||
assertEquals(0, head(d));
|
||||
assertEquals(0, tail(d));
|
||||
Object[] initialElements = elements(d);
|
||||
|
||||
assertInvariants(d);
|
||||
for (int i = capacity; i--> 0; ) {
|
||||
d.add(rnd.nextInt(42));
|
||||
assertSame(elements(d), initialElements);
|
||||
assertInvariants(d);
|
||||
}
|
||||
|
||||
d.add(rnd.nextInt(42));
|
||||
assertNotSame(elements(d), initialElements);
|
||||
assertInvariants(d);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultConstructor() {
|
||||
checkCapacity(new ArrayDeque(), 16);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotResizeWhenInitialCapacityProvided() {
|
||||
int initialCapacity = rnd.nextInt(20);
|
||||
checkCapacity(new ArrayDeque(initialCapacity), initialCapacity);
|
||||
}
|
||||
|
||||
byte[] serialBytes(Object o) {
|
||||
try {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
oos.writeObject(o);
|
||||
oos.flush();
|
||||
oos.close();
|
||||
return bos.toByteArray();
|
||||
} catch (Exception fail) {
|
||||
throw new AssertionError(fail);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> T serialClone(T o) {
|
||||
try {
|
||||
ObjectInputStream ois = new ObjectInputStream
|
||||
(new ByteArrayInputStream(serialBytes(o)));
|
||||
T clone = (T) ois.readObject();
|
||||
assertNotSame(o, clone);
|
||||
assertSame(o.getClass(), clone.getClass());
|
||||
return clone;
|
||||
} catch (Exception fail) {
|
||||
throw new AssertionError(fail);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerialization() {
|
||||
ArrayDeque[] ds = { new ArrayDeque(), new ArrayDeque(rnd.nextInt(20)) };
|
||||
for (ArrayDeque d : ds) {
|
||||
if (rnd.nextBoolean()) d.add(99);
|
||||
ArrayDeque clone = serialClone(d);
|
||||
assertInvariants(clone);
|
||||
assertNotSame(elements(d), elements(clone));
|
||||
assertEquals(d, clone);
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks conditions which should always be true. */
|
||||
void assertInvariants(ArrayDeque d) {
|
||||
final Object[] elements = elements(d);
|
||||
final int head = head(d);
|
||||
final int tail = tail(d);
|
||||
final int capacity = elements.length;
|
||||
assertTrue(0 <= head && head < capacity);
|
||||
assertTrue(0 <= tail && tail < capacity);
|
||||
assertTrue(capacity > 0);
|
||||
assertTrue(d.size() < capacity);
|
||||
assertTrue((head == tail) ^ (elements[head] != null));
|
||||
assertNull(elements[tail]);
|
||||
assertTrue((head == tail) ^ (elements[Math.floorMod(tail - 1, capacity)] != null));
|
||||
}
|
||||
}
|
||||
88
test/jdk/java/util/ArrayList/AddAll.java
Normal file
88
test/jdk/java/util/ArrayList/AddAll.java
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4715206
|
||||
* @summary Ensure that addAll method can cope with underestimate by size().
|
||||
* @author Josh Bloch
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class AddAll {
|
||||
public static void main(String[] args) {
|
||||
for (int j = 0; j < 1; j++) {
|
||||
Map m = new WeakHashMap(100000);
|
||||
for (int i = 0; i < 100000; i++)
|
||||
m.put(new Object(), Boolean.TRUE);
|
||||
new ArrayList().addAll(m.keySet());
|
||||
}
|
||||
|
||||
for (int j = 0; j < 1; j++) {
|
||||
Map m = new WeakHashMap(100000);
|
||||
for (int i = 0; i < 100000; i++)
|
||||
m.put(new Object(), Boolean.TRUE);
|
||||
new LinkedList().addAll(m.keySet());
|
||||
}
|
||||
|
||||
for (int j = 0; j < 1; j++) {
|
||||
Map m = new WeakHashMap(100000);
|
||||
for (int i = 0; i < 100000; i++)
|
||||
m.put(new Object(), Boolean.TRUE);
|
||||
new Vector().addAll(m.keySet());
|
||||
}
|
||||
|
||||
for (int j = 0; j < 1; j++) {
|
||||
Map m = new WeakHashMap(100000);
|
||||
for (int i = 0; i < 100000; i++)
|
||||
m.put(new Object(), Boolean.TRUE);
|
||||
List list = new ArrayList();
|
||||
list.add("inka"); list.add("dinka"); list.add("doo");
|
||||
list.addAll(1, m.keySet());
|
||||
}
|
||||
|
||||
for (int j = 0; j < 1; j++) {
|
||||
Map m = new WeakHashMap(100000);
|
||||
for (int i = 0; i < 100000; i++)
|
||||
m.put(new Object(), Boolean.TRUE);
|
||||
List list = new LinkedList();
|
||||
list.add("inka"); list.add("dinka"); list.add("doo");
|
||||
list.addAll(1, m.keySet());
|
||||
}
|
||||
|
||||
for (int j = 0; j < 1; j++) {
|
||||
Map m = new WeakHashMap(100000);
|
||||
for (int i = 0; i < 100000; i++)
|
||||
m.put(new Object(), Boolean.TRUE);
|
||||
List list = new ArrayList();
|
||||
list.add("inka"); list.add("dinka"); list.add("doo");
|
||||
list.addAll(1, m.keySet());
|
||||
}
|
||||
}
|
||||
}
|
||||
214
test/jdk/java/util/ArrayList/ArrayManagement.java
Normal file
214
test/jdk/java/util/ArrayList/ArrayManagement.java
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright 2016 Google, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8146568
|
||||
* @summary brittle white box test of internal array management
|
||||
* @modules java.base/java.util:open
|
||||
* @run testng ArrayManagement
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class ArrayManagement {
|
||||
static final int DEFAULT_CAPACITY = 10;
|
||||
static final Field ELEMENT_DATA;
|
||||
static final Field MODCOUNT;
|
||||
static final SplittableRandom rnd = new SplittableRandom();
|
||||
|
||||
static {
|
||||
try {
|
||||
ELEMENT_DATA = ArrayList.class.getDeclaredField("elementData");
|
||||
ELEMENT_DATA.setAccessible(true);
|
||||
MODCOUNT = AbstractList.class.getDeclaredField("modCount");
|
||||
MODCOUNT.setAccessible(true);
|
||||
} catch (ReflectiveOperationException huh) {
|
||||
throw new AssertionError(huh);
|
||||
}
|
||||
}
|
||||
|
||||
static Object[] elementData(ArrayList<?> list) {
|
||||
try {
|
||||
return (Object[]) ELEMENT_DATA.get(list);
|
||||
} catch (ReflectiveOperationException huh) {
|
||||
throw new AssertionError(huh);
|
||||
}
|
||||
}
|
||||
|
||||
static int modCount(ArrayList<?> list) {
|
||||
try {
|
||||
return MODCOUNT.getInt(list);
|
||||
} catch (ReflectiveOperationException huh) {
|
||||
throw new AssertionError(huh);
|
||||
}
|
||||
}
|
||||
|
||||
static int capacity(ArrayList<?> list) {
|
||||
return elementData(list).length;
|
||||
}
|
||||
|
||||
static int newCapacity(int oldCapacity) {
|
||||
return oldCapacity + (oldCapacity >> 1);
|
||||
}
|
||||
|
||||
static void ensureCapacity(ArrayList<Object> list, int capacity) {
|
||||
int oldCapacity = capacity(list);
|
||||
int oldModCount = modCount(list);
|
||||
list.ensureCapacity(capacity);
|
||||
assertTrue(capacity(list) >= capacity || capacity(list) == 0);
|
||||
assertEquals(modCount(list),
|
||||
(capacity(list) == oldCapacity)
|
||||
? oldModCount
|
||||
: oldModCount + 1);
|
||||
}
|
||||
|
||||
static List<Object> singletonList() {
|
||||
return Collections.singletonList(Boolean.TRUE);
|
||||
}
|
||||
|
||||
/** Opportunistically randomly test various add operations. */
|
||||
static void addOneElement(ArrayList<Object> list) {
|
||||
int size = list.size();
|
||||
int modCount = modCount(list);
|
||||
switch (rnd.nextInt(4)) {
|
||||
case 0: assertTrue(list.add(Boolean.TRUE)); break;
|
||||
case 1: list.add(size, Boolean.TRUE); break;
|
||||
case 2: assertTrue(list.addAll(singletonList())); break;
|
||||
case 3: assertTrue(list.addAll(size, singletonList())); break;
|
||||
default: throw new AssertionError();
|
||||
}
|
||||
assertEquals(modCount(list), modCount + 1);
|
||||
assertEquals(list.size(), size + 1);
|
||||
}
|
||||
|
||||
@Test public void defaultCapacity() {
|
||||
ArrayList<Object> list = new ArrayList<>();
|
||||
assertEquals(capacity(new ArrayList<Object>()), 0);
|
||||
for (int i = 0; i < DEFAULT_CAPACITY; i++) {
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), DEFAULT_CAPACITY);
|
||||
}
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), newCapacity(DEFAULT_CAPACITY));
|
||||
}
|
||||
|
||||
@Test public void defaultCapacityEnsureCapacity() {
|
||||
ArrayList<Object> list = new ArrayList<>();
|
||||
for (int i = 0; i <= DEFAULT_CAPACITY; i++) {
|
||||
ensureCapacity(list, i); // no-op!
|
||||
assertEquals(capacity(list), 0);
|
||||
}
|
||||
for (int i = 0; i < DEFAULT_CAPACITY; i++) {
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), DEFAULT_CAPACITY);
|
||||
}
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), newCapacity(DEFAULT_CAPACITY));
|
||||
{
|
||||
int capacity = capacity(list);
|
||||
ensureCapacity(list, capacity + 1);
|
||||
assertEquals(capacity(list), newCapacity(capacity));
|
||||
}
|
||||
{
|
||||
int capacity = capacity(list);
|
||||
ensureCapacity(list, 3 * capacity);
|
||||
assertEquals(capacity(list), 3 * capacity);
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void ensureCapacityBeyondDefaultCapacity() {
|
||||
ArrayList<Object> list = new ArrayList<>();
|
||||
list.ensureCapacity(DEFAULT_CAPACITY + 1);
|
||||
assertEquals(capacity(list), DEFAULT_CAPACITY + 1);
|
||||
for (int i = 0; i < DEFAULT_CAPACITY + 1; i++) {
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), DEFAULT_CAPACITY + 1);
|
||||
}
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), newCapacity(DEFAULT_CAPACITY + 1));
|
||||
}
|
||||
|
||||
@Test public void explicitZeroCapacity() {
|
||||
ArrayList<Object> list = new ArrayList<>(0);
|
||||
assertEquals(capacity(list), 0);
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), 1);
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), 2);
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), 3);
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), 4);
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), 6);
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), 6);
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), 9);
|
||||
list.clear();
|
||||
assertEquals(capacity(list), 9);
|
||||
}
|
||||
|
||||
@Test public void explicitLargeCapacity() {
|
||||
int n = DEFAULT_CAPACITY * 3;
|
||||
ArrayList<Object> list = new ArrayList<>(n);
|
||||
assertEquals(capacity(list), n);
|
||||
ensureCapacity(list, 0);
|
||||
ensureCapacity(list, n);
|
||||
for (int i = 0; i < n; i++) addOneElement(list);
|
||||
assertEquals(capacity(list), n);
|
||||
|
||||
addOneElement(list);
|
||||
assertEquals(capacity(list), newCapacity(n));
|
||||
}
|
||||
|
||||
@Test public void emptyArraysAreShared() {
|
||||
assertSame(elementData(new ArrayList<Object>()),
|
||||
elementData(new ArrayList<Object>()));
|
||||
assertSame(elementData(new ArrayList<Object>(0)),
|
||||
elementData(new ArrayList<Object>(0)));
|
||||
}
|
||||
|
||||
@Test public void emptyArraysDifferBetweenDefaultAndExplicit() {
|
||||
assertNotSame(elementData(new ArrayList<Object>()),
|
||||
elementData(new ArrayList<Object>(0)));
|
||||
}
|
||||
|
||||
@Test public void negativeCapacity() {
|
||||
for (int capacity : new int[] { -1, Integer.MIN_VALUE }) {
|
||||
try {
|
||||
new ArrayList<Object>(capacity);
|
||||
fail("should throw");
|
||||
} catch (IllegalArgumentException success) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
test/jdk/java/util/ArrayList/Bug6533203.java
Normal file
70
test/jdk/java/util/ArrayList/Bug6533203.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 6533203
|
||||
* @summary AbstractList.ListItr.add might corrupt iterator state if enclosing add throws
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
@SuppressWarnings({"serial","unchecked"})
|
||||
public class Bug6533203 {
|
||||
void test(String[] args) throws Throwable {
|
||||
final List<Integer> superstitious = new ArrayList<>() {
|
||||
public void add(int index, Integer i) {
|
||||
if (i == 13) throw new Error("unlucky");
|
||||
else super.add(index, i); }};
|
||||
final ListIterator it = superstitious.listIterator(0);
|
||||
equal(it.nextIndex(), 0);
|
||||
THROWS(Error.class, new F(){void f(){it.add(13);}});
|
||||
equal(it.nextIndex(), 0);
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.out.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new Bug6533203().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
abstract class F {abstract void f() throws Throwable;}
|
||||
void THROWS(Class<? extends Throwable> k, F... fs) {
|
||||
for (F f : fs)
|
||||
try {f.f(); fail("Expected " + k.getName() + " not thrown");}
|
||||
catch (Throwable t) {
|
||||
if (k.isAssignableFrom(t.getClass())) pass();
|
||||
else unexpected(t);}}
|
||||
}
|
||||
43
test/jdk/java/util/ArrayList/Bug8146568.java
Normal file
43
test/jdk/java/util/ArrayList/Bug8146568.java
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2016 Google, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8146568
|
||||
* @summary repro for: NegativeArraySizeException in ArrayList.grow(int)
|
||||
* @run main/manual/othervm -Xmx17g Bug8146568
|
||||
* @requires os.maxMemory>17G
|
||||
*/
|
||||
|
||||
public class Bug8146568 {
|
||||
public static void main(String[] args) {
|
||||
int size = Integer.MAX_VALUE - 2;
|
||||
java.util.ArrayList<Object> huge = new java.util.ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
huge.add(null);
|
||||
try {
|
||||
huge.addAll(huge);
|
||||
throw new Error("expected OutOfMemoryError not thrown");
|
||||
} catch (OutOfMemoryError success) {}
|
||||
}
|
||||
}
|
||||
64
test/jdk/java/util/ArrayList/EnsureCapacity.java
Normal file
64
test/jdk/java/util/ArrayList/EnsureCapacity.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 6992121
|
||||
* @summary Test the ArrayList.ensureCapacity() and Vector.ensureCapacity
|
||||
* method with negative minimumCapacity input argument.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
|
||||
public class EnsureCapacity {
|
||||
public static void main(String[] args) {
|
||||
testArrayList();
|
||||
testVector();
|
||||
}
|
||||
|
||||
private static void checkCapacity(int before, int after) {
|
||||
if (before != after) {
|
||||
throw new RuntimeException("capacity is expected to be unchanged: " +
|
||||
"before=" + before + " after=" + after);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testArrayList() {
|
||||
ArrayList<String> al = new ArrayList<String>();
|
||||
al.add("abc");
|
||||
al.ensureCapacity(Integer.MIN_VALUE);
|
||||
|
||||
// there is no method to query the capacity of ArrayList
|
||||
// so before and after capacity are not checked
|
||||
}
|
||||
|
||||
private static void testVector() {
|
||||
Vector<String> vector = new Vector<String>();
|
||||
vector.add("abc");
|
||||
|
||||
int cap = vector.capacity();
|
||||
vector.ensureCapacity(Integer.MIN_VALUE);
|
||||
checkCapacity(cap, vector.capacity());
|
||||
}
|
||||
}
|
||||
710
test/jdk/java/util/ArrayList/IteratorMicroBenchmark.java
Normal file
710
test/jdk/java/util/ArrayList/IteratorMicroBenchmark.java
Normal file
|
|
@ -0,0 +1,710 @@
|
|||
/*
|
||||
* 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
|
||||
* @summary micro-benchmark correctness mode
|
||||
* @run main IteratorMicroBenchmark iterations=1 size=8 warmup=0
|
||||
*/
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS]
|
||||
*
|
||||
* To run this in micro-benchmark mode, simply run as a normal java program.
|
||||
* Be patient; this program runs for a very long time.
|
||||
* For faster runs, restrict execution using command line args.
|
||||
*
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
public class IteratorMicroBenchmark {
|
||||
abstract static class Job {
|
||||
private final String name;
|
||||
public Job(String name) { this.name = name; }
|
||||
public String name() { return name; }
|
||||
public abstract void work() throws Throwable;
|
||||
}
|
||||
|
||||
static double warmupSeconds;
|
||||
static long warmupNanos;
|
||||
|
||||
// --------------- GC finalization infrastructure ---------------
|
||||
|
||||
/** No guarantees, but effective in practice. */
|
||||
static void forceFullGc() {
|
||||
long timeoutMillis = 1000L;
|
||||
CountDownLatch finalized = new CountDownLatch(1);
|
||||
ReferenceQueue<Object> queue = new ReferenceQueue<>();
|
||||
WeakReference<Object> ref = new WeakReference<>(
|
||||
new Object() { protected void finalize() { finalized.countDown(); }},
|
||||
queue);
|
||||
try {
|
||||
for (int tries = 3; tries--> 0; ) {
|
||||
System.gc();
|
||||
if (finalized.await(timeoutMillis, MILLISECONDS)
|
||||
&& queue.remove(timeoutMillis) != null
|
||||
&& ref.get() == null) {
|
||||
System.runFinalization(); // try to pick up stragglers
|
||||
return;
|
||||
}
|
||||
timeoutMillis *= 4;
|
||||
}
|
||||
} catch (InterruptedException unexpected) {
|
||||
throw new AssertionError("unexpected InterruptedException");
|
||||
}
|
||||
throw new AssertionError("failed to do a \"full\" gc");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs each job for long enough that all the runtime compilers
|
||||
* have had plenty of time to warm up, i.e. get around to
|
||||
* compiling everything worth compiling.
|
||||
* Returns array of average times per job per run.
|
||||
*/
|
||||
private static long[] time0(Job ... jobs) throws Throwable {
|
||||
long[] nanoss = new long[jobs.length];
|
||||
for (int i = 0; i < jobs.length; i++) {
|
||||
if (warmupNanos > 0) forceFullGc();
|
||||
Job job = jobs[i];
|
||||
long totalTime;
|
||||
int runs = 0;
|
||||
long startTime = System.nanoTime();
|
||||
do { job.work(); runs++; }
|
||||
while ((totalTime = System.nanoTime() - startTime) < warmupNanos);
|
||||
nanoss[i] = totalTime/runs;
|
||||
}
|
||||
return nanoss;
|
||||
}
|
||||
|
||||
private static void time(Job ... jobs) throws Throwable {
|
||||
if (warmupSeconds > 0.0) time0(jobs); // Warm up run
|
||||
long[] nanoss = time0(jobs); // Real timing run
|
||||
long[] milliss = new long[jobs.length];
|
||||
double[] ratios = new double[jobs.length];
|
||||
|
||||
final String nameHeader = "Method";
|
||||
final String millisHeader = "Millis";
|
||||
final String ratioHeader = "Ratio";
|
||||
|
||||
int nameWidth = nameHeader.length();
|
||||
int millisWidth = millisHeader.length();
|
||||
int ratioWidth = ratioHeader.length();
|
||||
|
||||
for (int i = 0; i < jobs.length; i++) {
|
||||
nameWidth = Math.max(nameWidth, jobs[i].name().length());
|
||||
|
||||
milliss[i] = nanoss[i]/(1000L * 1000L);
|
||||
millisWidth = Math.max(millisWidth,
|
||||
String.format("%d", milliss[i]).length());
|
||||
|
||||
ratios[i] = (double) nanoss[i] / (double) nanoss[0];
|
||||
ratioWidth = Math.max(ratioWidth,
|
||||
String.format("%.3f", ratios[i]).length());
|
||||
}
|
||||
|
||||
String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
System.out.printf(headerFormat, "Method", "Millis", "Ratio");
|
||||
|
||||
// Print out absolute and relative times, calibrated against first job
|
||||
for (int i = 0; i < jobs.length; i++)
|
||||
System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]);
|
||||
}
|
||||
|
||||
private static String keywordValue(String[] args, String keyword) {
|
||||
for (String arg : args)
|
||||
if (arg.startsWith(keyword))
|
||||
return arg.substring(keyword.length() + 1);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int intArg(String[] args, String keyword, int defaultValue) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? defaultValue : Integer.parseInt(val);
|
||||
}
|
||||
|
||||
private static double doubleArg(String[] args, String keyword, double defaultValue) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? defaultValue : Double.parseDouble(val);
|
||||
}
|
||||
|
||||
private static Pattern patternArg(String[] args, String keyword) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return (val == null) ? null : Pattern.compile(val);
|
||||
}
|
||||
|
||||
private static Job[] filter(Pattern filter, Job[] jobs) {
|
||||
return (filter == null) ? jobs
|
||||
: Arrays.stream(jobs)
|
||||
.filter(job -> filter.matcher(job.name()).find())
|
||||
.collect(toList())
|
||||
.toArray(new Job[0]);
|
||||
}
|
||||
|
||||
private static void deoptimize(int sum) {
|
||||
if (sum == 42)
|
||||
System.out.println("the answer");
|
||||
}
|
||||
|
||||
private static <T> List<T> asSubList(List<T> list) {
|
||||
return list.subList(0, list.size());
|
||||
}
|
||||
|
||||
private static <T> Iterable<T> backwards(final List<T> list) {
|
||||
return new Iterable<T>() {
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
final ListIterator<T> it = list.listIterator(list.size());
|
||||
public boolean hasNext() { return it.hasPrevious(); }
|
||||
public T next() { return it.previous(); }
|
||||
public void remove() { it.remove(); }};}};
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
final int iterations = intArg(args, "iterations", 100_000);
|
||||
final int size = intArg(args, "size", 1000);
|
||||
warmupSeconds = doubleArg(args, "warmup", 7.0);
|
||||
final Pattern filter = patternArg(args, "filter");
|
||||
|
||||
warmupNanos = (long) (warmupSeconds * (1000L * 1000L * 1000L));
|
||||
|
||||
// System.out.printf(
|
||||
// "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
|
||||
// iterations, size, warmupSeconds, filter);
|
||||
|
||||
final ConcurrentSkipListMap<Integer,Integer> m
|
||||
= new ConcurrentSkipListMap<>();
|
||||
final ArrayList<Integer> al = new ArrayList<>(size);
|
||||
|
||||
// Populate collections with random data
|
||||
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
for (int i = 0; i < size; i++) {
|
||||
m.put(rnd.nextInt(size), rnd.nextInt(size));
|
||||
al.add(rnd.nextInt(size));
|
||||
}
|
||||
final Vector<Integer> v = new Vector<>(al);
|
||||
final ArrayDeque<Integer> ad = new ArrayDeque<>(al);
|
||||
// shuffle ArrayDeque elements so they wrap
|
||||
for (int i = 0, n = rnd.nextInt(size); i < n; i++)
|
||||
ad.addLast(ad.removeFirst());
|
||||
|
||||
// Also test "short" collections
|
||||
final int shortSize = 5;
|
||||
final Vector<Integer> sv = new Vector<>(v.subList(0, shortSize));
|
||||
final ArrayList<Integer> sal = new ArrayList<>(sv);
|
||||
|
||||
// Checks for correctness *and* prevents loop optimizations
|
||||
class Check {
|
||||
private int sum;
|
||||
public void sum(int sum) {
|
||||
if (this.sum == 0)
|
||||
this.sum = sum;
|
||||
if (this.sum != sum)
|
||||
throw new AssertionError("Sum mismatch");
|
||||
}
|
||||
}
|
||||
final Check check = new Check();
|
||||
final Check shortCheck = new Check();
|
||||
|
||||
Job[] jobs = {
|
||||
// new Job("Vector iterate desugared") {
|
||||
// public void work() throws Throwable {
|
||||
// for (int i = 0; i < iterations; i++) {
|
||||
// int sum = 0;
|
||||
// for (Iterator<Integer> it = v.iterator(); it.hasNext();)
|
||||
// sum += it.next();
|
||||
// check.sum(sum);}}},
|
||||
new Job("array loop") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] a = al.toArray(new Integer[0]);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
int size = a.length;
|
||||
for (int j = 0; j < size; ++j)
|
||||
sum += a[j];
|
||||
check.sum(sum);}}},
|
||||
new Job("descending array loop") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] a = al.toArray(new Integer[0]);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
int size = a.length;
|
||||
for (int j = size - 1; j >= 0; j--)
|
||||
sum += a[j];
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector get loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
int size = v.size();
|
||||
for (int j = 0; j < size; ++j)
|
||||
sum += v.get(j);
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : v)
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector descending listIterator loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
ListIterator<Integer> it = v.listIterator(al.size());
|
||||
while (it.hasPrevious())
|
||||
sum += it.previous();
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector Enumeration loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
Enumeration<Integer> it = v.elements();
|
||||
while (it.hasMoreElements())
|
||||
sum += it.nextElement();
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector subList iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : asSubList(v))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector subList subList subList iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : asSubList(asSubList(asSubList(v))))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector backwards wrapper ListIterator for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : backwards(v))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("Vector backwards wrapper subList ListIterator for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : backwards(asSubList(v)))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
// new Job("Vector iterate for loop invokeinterface") {
|
||||
// public void work() throws Throwable {
|
||||
// final List<Integer> l = v;
|
||||
// for (int i = 0; i < iterations; i++) {
|
||||
// int sum = 0;
|
||||
// for (Integer n : l)
|
||||
// sum += n;
|
||||
// check.sum(sum);}}},
|
||||
// new Job("Vector subList iterate for loop invokeinterface") {
|
||||
// public void work() throws Throwable {
|
||||
// final List<Integer> l = v;
|
||||
// for (int i = 0; i < iterations; i++) {
|
||||
// int sum = 0;
|
||||
// for (Integer n : asSubList(l))
|
||||
// sum += n;
|
||||
// check.sum(sum);}}},
|
||||
new Job("Short Vector get loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < (iterations * size / shortSize); i++) {
|
||||
int sum = 0;
|
||||
int size = sv.size();
|
||||
for (int j = 0; j < size; ++j)
|
||||
sum += sv.get(j);
|
||||
shortCheck.sum(sum);}}},
|
||||
new Job("Short Vector iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < (iterations * size / shortSize); i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : sv)
|
||||
sum += n;
|
||||
shortCheck.sum(sum);}}},
|
||||
new Job("Short Vector sublist iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < (iterations * size / shortSize); i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : asSubList(sv))
|
||||
sum += n;
|
||||
shortCheck.sum(sum);}}},
|
||||
new Job("ArrayList get loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
int size = al.size();
|
||||
for (int j = 0; j < size; ++j)
|
||||
sum += al.get(j);
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : al)
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayDeque iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : ad)
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList descending listIterator loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
ListIterator<Integer> it = al.listIterator(al.size());
|
||||
while (it.hasPrevious())
|
||||
sum += it.previous();
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList listIterator loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
ListIterator<Integer> it = al.listIterator();
|
||||
while (it.hasNext())
|
||||
sum += it.next();
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayDeque.descendingIterator() loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
Iterator<Integer> it = ad.descendingIterator();
|
||||
while (it.hasNext())
|
||||
sum += it.next();
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList.forEach") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
al.forEach(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.forEach") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
ad.forEach(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("Vector.forEach") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
v.forEach(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList.iterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
al.iterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.descendingIterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
ad.descendingIterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.iterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
ad.iterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("Vector.iterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
v.iterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList.spliterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
al.spliterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.spliterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
ad.spliterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("Vector.spliterator().forEachRemaining()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
v.spliterator().forEachRemaining(n -> sum[0] += n);
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList.spliterator().tryAdvance()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
Spliterator<Integer> spliterator = al.spliterator();
|
||||
do {} while (spliterator.tryAdvance(n -> sum[0] += n));
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.spliterator().tryAdvance()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
Spliterator<Integer> spliterator = ad.spliterator();
|
||||
do {} while (spliterator.tryAdvance(n -> sum[0] += n));
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("Vector.spliterator().tryAdvance()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
Spliterator<Integer> spliterator = v.spliterator();
|
||||
do {} while (spliterator.tryAdvance(n -> sum[0] += n));
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList.removeIf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
al.removeIf(n -> { sum[0] += n; return false; });
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.removeIf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
ad.removeIf(n -> { sum[0] += n; return false; });
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("Vector.removeIf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
v.removeIf(n -> { sum[0] += n; return false; });
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList subList .removeIf") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
List<Integer> sl = asSubList(al);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
sl.removeIf(n -> { sum[0] += n; return false; });
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList subList get loop") {
|
||||
public void work() throws Throwable {
|
||||
List<Integer> sl = asSubList(al);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
int size = sl.size();
|
||||
for (int j = 0; j < size; ++j)
|
||||
sum += sl.get(j);
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList subList iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : asSubList(al))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList subList subList subList iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : asSubList(asSubList(asSubList(al))))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList backwards wrapper ListIterator for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : backwards(al))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
new Job("ArrayList backwards wrapper subList ListIterator for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : backwards(asSubList(al)))
|
||||
sum += n;
|
||||
check.sum(sum);}}},
|
||||
// new Job("ArrayList iterate desugared") {
|
||||
// public void work() throws Throwable {
|
||||
// for (int i = 0; i < iterations; i++) {
|
||||
// int sum = 0;
|
||||
// for (Iterator<Integer> it = al.iterator(); it.hasNext();)
|
||||
// sum += it.next();
|
||||
// check.sum(sum);}}},
|
||||
new Job("Short ArrayList get loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < (iterations * size / shortSize); i++) {
|
||||
int sum = 0;
|
||||
int size = sal.size();
|
||||
for (int j = 0; j < size; ++j)
|
||||
sum += sal.get(j);
|
||||
shortCheck.sum(sum);}}},
|
||||
new Job("Short ArrayList iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < (iterations * size / shortSize); i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : sal)
|
||||
sum += n;
|
||||
shortCheck.sum(sum);}}},
|
||||
new Job("Short ArrayList sublist iterate for loop") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < (iterations * size / shortSize); i++) {
|
||||
int sum = 0;
|
||||
for (Integer n : asSubList(sal))
|
||||
sum += n;
|
||||
shortCheck.sum(sum);}}},
|
||||
new Job("Vector ArrayList alternating iteration") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
Iterator<Integer> it1 = v.iterator();
|
||||
Iterator<Integer> it2 = al.iterator();
|
||||
while (it1.hasNext())
|
||||
sum += it1.next() + it2.next();
|
||||
check.sum(sum/2);}}},
|
||||
new Job("Vector ArrayList alternating invokeVirtual iteration") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
List<Iterator<Integer>> its = new ArrayList<>(2);
|
||||
its.add(v.iterator());
|
||||
its.add(al.iterator());
|
||||
for (int k = 0; its.get(k).hasNext(); k = (k == 0) ? 1 : 0)
|
||||
sum += its.get(k).next();
|
||||
check.sum(sum/2);}}},
|
||||
new Job("ConcurrentSkipListMap entrySet iterate") {
|
||||
public void work() throws Throwable {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
int sum = 0;
|
||||
for (Map.Entry<Integer,Integer> e : m.entrySet())
|
||||
sum += e.getKey();
|
||||
deoptimize(sum);}}},
|
||||
new Job("ArrayList.toArray()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Object o : al.toArray())
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList.toArray(a)") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] a = new Integer[size];
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
al.toArray(a);
|
||||
for (Object o : a)
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList subList .toArray()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Object o : asSubList(al).toArray())
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayList subList .toArray(a)") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] a = new Integer[size];
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
asSubList(al).toArray(a);
|
||||
for (Object o : a)
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.toArray()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Object o : ad.toArray())
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("ArrayDeque.toArray(a)") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] a = new Integer[size];
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
ad.toArray(a);
|
||||
for (Object o : a)
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("Vector.toArray()") {
|
||||
public void work() throws Throwable {
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
for (Object o : v.toArray())
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
new Job("Vector.toArray(a)") {
|
||||
public void work() throws Throwable {
|
||||
Integer[] a = new Integer[size];
|
||||
int[] sum = new int[1];
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
sum[0] = 0;
|
||||
v.toArray(a);
|
||||
for (Object o : a)
|
||||
sum[0] += (Integer) o;
|
||||
check.sum(sum[0]);}}},
|
||||
};
|
||||
|
||||
time(filter(filter, jobs));
|
||||
}
|
||||
}
|
||||
234
test/jdk/java/util/ArrayList/RangeCheckMicroBenchmark.java
Normal file
234
test/jdk/java/util/ArrayList/RangeCheckMicroBenchmark.java
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is not a regression test, but a micro-benchmark.
|
||||
*
|
||||
* I have run this as follows:
|
||||
*
|
||||
* repeat 5 for f in -client -server; do mergeBench dolphin . jr -dsa -da $f RangeCheckMicroBenchmark.java; done
|
||||
*
|
||||
*
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class RangeCheckMicroBenchmark {
|
||||
abstract static class Job {
|
||||
private final String name;
|
||||
Job(String name) { this.name = name; }
|
||||
String name() { return name; }
|
||||
abstract void work() throws Throwable;
|
||||
}
|
||||
|
||||
private static void collectAllGarbage() {
|
||||
final CountDownLatch drained = new CountDownLatch(1);
|
||||
try {
|
||||
System.gc(); // enqueue finalizable objects
|
||||
new Object() { protected void finalize() {
|
||||
drained.countDown(); }};
|
||||
System.gc(); // enqueue detector
|
||||
drained.await(); // wait for finalizer queue to drain
|
||||
System.gc(); // cleanup finalized objects
|
||||
} catch (InterruptedException e) { throw new Error(e); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs each job for long enough that all the runtime compilers
|
||||
* have had plenty of time to warm up, i.e. get around to
|
||||
* compiling everything worth compiling.
|
||||
* Returns array of average times per job per run.
|
||||
*/
|
||||
private static long[] time0(Job ... jobs) throws Throwable {
|
||||
final long warmupNanos = 10L * 1000L * 1000L * 1000L;
|
||||
long[] nanoss = new long[jobs.length];
|
||||
for (int i = 0; i < jobs.length; i++) {
|
||||
collectAllGarbage();
|
||||
long t0 = System.nanoTime();
|
||||
long t;
|
||||
int j = 0;
|
||||
do { jobs[i].work(); j++; }
|
||||
while ((t = System.nanoTime() - t0) < warmupNanos);
|
||||
nanoss[i] = t/j;
|
||||
}
|
||||
return nanoss;
|
||||
}
|
||||
|
||||
private static void time(Job ... jobs) throws Throwable {
|
||||
|
||||
long[] warmup = time0(jobs); // Warm up run
|
||||
long[] nanoss = time0(jobs); // Real timing run
|
||||
long[] milliss = new long[jobs.length];
|
||||
double[] ratios = new double[jobs.length];
|
||||
|
||||
final String nameHeader = "Method";
|
||||
final String millisHeader = "Millis";
|
||||
final String ratioHeader = "Ratio";
|
||||
|
||||
int nameWidth = nameHeader.length();
|
||||
int millisWidth = millisHeader.length();
|
||||
int ratioWidth = ratioHeader.length();
|
||||
|
||||
for (int i = 0; i < jobs.length; i++) {
|
||||
nameWidth = Math.max(nameWidth, jobs[i].name().length());
|
||||
|
||||
milliss[i] = nanoss[i]/(1000L * 1000L);
|
||||
millisWidth = Math.max(millisWidth,
|
||||
String.format("%d", milliss[i]).length());
|
||||
|
||||
ratios[i] = (double) nanoss[i] / (double) nanoss[0];
|
||||
ratioWidth = Math.max(ratioWidth,
|
||||
String.format("%.3f", ratios[i]).length());
|
||||
}
|
||||
|
||||
String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
|
||||
nameWidth, millisWidth, ratioWidth);
|
||||
System.out.printf(headerFormat, "Method", "Millis", "Ratio");
|
||||
|
||||
// Print out absolute and relative times, calibrated against first job
|
||||
for (int i = 0; i < jobs.length; i++)
|
||||
System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]);
|
||||
}
|
||||
|
||||
private static String keywordValue(String[] args, String keyword) {
|
||||
for (String arg : args)
|
||||
if (arg.startsWith(keyword))
|
||||
return arg.substring(keyword.length() + 1);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int intArg(String[] args, String keyword, int defaultValue) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return val == null ? defaultValue : Integer.parseInt(val);
|
||||
}
|
||||
|
||||
private static Pattern patternArg(String[] args, String keyword) {
|
||||
String val = keywordValue(args, keyword);
|
||||
return val == null ? null : Pattern.compile(val);
|
||||
}
|
||||
|
||||
private static Job[] filter(Pattern filter, Job[] jobs) {
|
||||
return (filter == null) ? jobs
|
||||
: Arrays.stream(jobs)
|
||||
.filter(job -> filter.matcher(job.name()).find())
|
||||
.collect(toList())
|
||||
.toArray(new Job[0]);
|
||||
}
|
||||
|
||||
private static void deoptimize(ArrayList<Integer> list) {
|
||||
for (Integer x : list)
|
||||
if (x == null)
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage: [iterations=N] [size=N] [filter=REGEXP]
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
final int iterations = intArg(args, "iterations", 30000);
|
||||
final int size = intArg(args, "size", 1000);
|
||||
final Pattern filter = patternArg(args, "filter");
|
||||
|
||||
final ArrayList<Integer> list = new ArrayList<>();
|
||||
final Random rnd = new Random();
|
||||
for (int i = 0; i < size; i++)
|
||||
list.add(rnd.nextInt());
|
||||
|
||||
final Job[] jobs = {
|
||||
new Job("get") { void work() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size; k++)
|
||||
if (list.get(k) == 42)
|
||||
throw new Error();
|
||||
}
|
||||
deoptimize(list);}},
|
||||
new Job("set") { void work() {
|
||||
Integer[] xs = list.toArray(new Integer[size]);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size; k++)
|
||||
list.set(k, xs[k]);
|
||||
}
|
||||
deoptimize(list);}},
|
||||
new Job("get/set") { void work() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size; k++)
|
||||
list.set(k, list.get(size - k - 1));
|
||||
}
|
||||
deoptimize(list);}},
|
||||
new Job("add/remove at end") { void work() {
|
||||
Integer x = rnd.nextInt();
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size - 1; k++) {
|
||||
list.add(size, x);
|
||||
list.remove(size);
|
||||
}
|
||||
}
|
||||
deoptimize(list);}},
|
||||
new Job("subList get") { void work() {
|
||||
List<Integer> sublist = list.subList(0, list.size());
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size; k++)
|
||||
if (sublist.get(k) == 42)
|
||||
throw new Error();
|
||||
}
|
||||
deoptimize(list);}},
|
||||
new Job("subList set") { void work() {
|
||||
List<Integer> sublist = list.subList(0, list.size());
|
||||
Integer[] xs = sublist.toArray(new Integer[size]);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size; k++)
|
||||
sublist.set(k, xs[k]);
|
||||
}
|
||||
deoptimize(list);}},
|
||||
new Job("subList get/set") { void work() {
|
||||
List<Integer> sublist = list.subList(0, list.size());
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size; k++)
|
||||
sublist.set(k, sublist.get(size - k - 1));
|
||||
}
|
||||
deoptimize(list);}},
|
||||
new Job("subList add/remove at end") { void work() {
|
||||
List<Integer> sublist = list.subList(0, list.size());
|
||||
Integer x = rnd.nextInt();
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
for (int k = 0; k < size - 1; k++) {
|
||||
sublist.add(size, x);
|
||||
sublist.remove(size);
|
||||
}
|
||||
}
|
||||
deoptimize(list);}}
|
||||
};
|
||||
|
||||
time(filter(filter, jobs));
|
||||
}
|
||||
}
|
||||
59
test/jdk/java/util/ArrayList/SortingModCount.java
Normal file
59
test/jdk/java/util/ArrayList/SortingModCount.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8340572
|
||||
* @summary ConcurrentModificationException when sorting ArrayList sublists
|
||||
*/
|
||||
|
||||
public class SortingModCount {
|
||||
public static void main(String[] args) {
|
||||
testSortingSubListsDoesNotIncrementModCount();
|
||||
testSortingListDoesIncrementModCount();
|
||||
}
|
||||
|
||||
private static void testSortingSubListsDoesNotIncrementModCount() {
|
||||
List<Integer> l = new ArrayList<>(List.of(1, 2, 3, 4));
|
||||
var a = l.subList(0, 2);
|
||||
var b = l.subList(2, 4);
|
||||
Collections.sort(a);
|
||||
Collections.sort(b);
|
||||
}
|
||||
|
||||
private static void testSortingListDoesIncrementModCount() {
|
||||
List<Integer> l = new ArrayList<>(List.of(1, 2, 3, 4));
|
||||
var b = l.subList(2, 4);
|
||||
Collections.sort(l);
|
||||
try {
|
||||
Collections.sort(b);
|
||||
throw new Error("expected ConcurrentModificationException not thrown");
|
||||
} catch (ConcurrentModificationException expected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
68
test/jdk/java/util/ArrayList/SubListModCount.java
Normal file
68
test/jdk/java/util/ArrayList/SubListModCount.java
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8234423
|
||||
* @summary Modifying ArrayList.subList().subList() resets modCount of subList
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
public class SubListModCount {
|
||||
public static void main(String[] args) {
|
||||
int failures = 0;
|
||||
var root = new ArrayList<Integer>();
|
||||
var subList = root.subList(0, 0);
|
||||
root.add(42);
|
||||
try {
|
||||
subList.size();
|
||||
failures++;
|
||||
System.out.println("Accessing subList");
|
||||
} catch (ConcurrentModificationException expected) {
|
||||
}
|
||||
var subSubList = subList.subList(0, 0);
|
||||
try {
|
||||
subSubList.size();
|
||||
failures++;
|
||||
System.out.println("Accessing subList.subList");
|
||||
} catch (ConcurrentModificationException expected) {
|
||||
}
|
||||
try {
|
||||
subSubList.add(42);
|
||||
failures++;
|
||||
System.out.println("Modifying subList.subList");
|
||||
} catch (ConcurrentModificationException expected) {
|
||||
}
|
||||
try {
|
||||
subList.size();
|
||||
failures++;
|
||||
System.out.println("Accessing subList again");
|
||||
} catch (ConcurrentModificationException expected) {
|
||||
}
|
||||
if (failures > 0) {
|
||||
throw new AssertionError(failures + " tests failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
506
test/jdk/java/util/Arrays/ArrayObjectMethods.java
Normal file
506
test/jdk/java/util/Arrays/ArrayObjectMethods.java
Normal file
|
|
@ -0,0 +1,506 @@
|
|||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4906359 6239296
|
||||
* @summary Basic test for content-based array object methods
|
||||
* @author Josh Bloch, Martin Buchholz
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
public class ArrayObjectMethods {
|
||||
int[] sizes = {0, 10, 100, 200, 1000};
|
||||
|
||||
void test(String[] args) throws Throwable {
|
||||
equal(Arrays.deepToString(null), "null");
|
||||
equal(Arrays.deepToString(new Object[]{}), "[]");
|
||||
equal(Arrays.deepToString(new Object[]{null}), "[null]");
|
||||
equal(Arrays.deepToString(new Object[]{null, 1}), "[null, 1]");
|
||||
equal(Arrays.deepToString(new Object[]{1, null}), "[1, null]");
|
||||
equal(Arrays.deepToString(new Object[]{new Object[]{}, null}), "[[], null]");
|
||||
|
||||
{
|
||||
Object[] a = {1, null};
|
||||
a[1] = a;
|
||||
equal(Arrays.deepToString(a), "[1, [...]]");
|
||||
a[0] = a;
|
||||
equal(Arrays.deepToString(a), "[[...], [...]]");
|
||||
a[0] = a[1] = new Object[]{1, null, a};
|
||||
equal(Arrays.deepToString(a), "[[1, null, [...]], [1, null, [...]]]");
|
||||
}
|
||||
|
||||
for (int size : sizes) {
|
||||
{
|
||||
long[] a = Rnd.longArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
int[] a = Rnd.intArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
short[] a = Rnd.shortArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
char[] a = Rnd.charArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
byte[] a = Rnd.byteArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
boolean[] a = Rnd.booleanArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
double[] a = Rnd.doubleArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
float[] a = Rnd.floatArray(size);
|
||||
equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
|
||||
}
|
||||
{
|
||||
Object[] a = Rnd.flatObjectArray(size);
|
||||
equal(Arrays.toString(a), Arrays.asList(a).toString());
|
||||
equal(Arrays.deepToString(a), Arrays.asList(a).toString());
|
||||
equal(Arrays.hashCode(a), Arrays.asList(a).hashCode());
|
||||
}
|
||||
|
||||
if (size <= 200) {
|
||||
Object[] a = Rnd.nestedObjectArray(size);
|
||||
List aList = deepToList(a);
|
||||
equal(Arrays.toString(a), Arrays.asList(a).toString());
|
||||
equal(Arrays.deepToString(a), aList.toString());
|
||||
equal(Arrays.deepHashCode(a), aList.hashCode());
|
||||
equal(Arrays.hashCode(a), Arrays.asList(a).hashCode());
|
||||
|
||||
Object[] deepCopy = (Object[]) deepCopy(a);
|
||||
check(Arrays.deepEquals(a, deepCopy));
|
||||
check(Arrays.deepEquals(deepCopy, a));
|
||||
|
||||
// Make deepCopy != a
|
||||
if (size == 0)
|
||||
deepCopy = new Object[] {"foo"};
|
||||
else if (deepCopy[deepCopy.length - 1] == null)
|
||||
deepCopy[deepCopy.length - 1] = "baz";
|
||||
else
|
||||
deepCopy[deepCopy.length - 1] = null;
|
||||
check(! Arrays.deepEquals(a, deepCopy));
|
||||
check(! Arrays.deepEquals(deepCopy, a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utility method to turn an array into a list "deeply," turning
|
||||
// all primitives into objects
|
||||
List<Object> deepToList(Object[] a) {
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
for (Object e : a) {
|
||||
if (e instanceof byte[])
|
||||
result.add(PrimitiveArrays.asList((byte[])e));
|
||||
else if (e instanceof short[])
|
||||
result.add(PrimitiveArrays.asList((short[])e));
|
||||
else if (e instanceof int[])
|
||||
result.add(PrimitiveArrays.asList((int[])e));
|
||||
else if (e instanceof long[])
|
||||
result.add(PrimitiveArrays.asList((long[])e));
|
||||
else if (e instanceof char[])
|
||||
result.add(PrimitiveArrays.asList((char[])e));
|
||||
else if (e instanceof double[])
|
||||
result.add(PrimitiveArrays.asList((double[])e));
|
||||
else if (e instanceof float[])
|
||||
result.add(PrimitiveArrays.asList((float[])e));
|
||||
else if (e instanceof boolean[])
|
||||
result.add(PrimitiveArrays.asList((boolean[])e));
|
||||
else if (e instanceof Object[])
|
||||
result.add(deepToList((Object[])e));
|
||||
else
|
||||
result.add(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Utility method to do a deep copy of an object *very slowly* using
|
||||
// serialization/deserialization
|
||||
Object deepCopy(Object oldObj) {
|
||||
try {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
oos.writeObject(oldObj);
|
||||
oos.flush();
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(
|
||||
bos.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(bin);
|
||||
return ois.readObject();
|
||||
} catch(Exception e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new ArrayObjectMethods().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods to generate "interesting" random primitives and primitive
|
||||
* arrays. Unlike Random.nextXxx, these methods return small values
|
||||
* and boundary values (e.g., 0, -1, NaN) with greater than normal
|
||||
* likelihood.
|
||||
*/
|
||||
|
||||
class Rnd {
|
||||
private static Random rnd = new Random();
|
||||
|
||||
public static long nextLong() {
|
||||
switch(rnd.nextInt(10)) {
|
||||
case 0: return 0;
|
||||
case 1: return Long.MIN_VALUE;
|
||||
case 2: return Long.MAX_VALUE;
|
||||
case 3: case 4: case 5:
|
||||
return (long) (rnd.nextInt(20) - 10);
|
||||
default: return rnd.nextLong();
|
||||
}
|
||||
}
|
||||
|
||||
public static int nextInt() {
|
||||
switch(rnd.nextInt(10)) {
|
||||
case 0: return 0;
|
||||
case 1: return Integer.MIN_VALUE;
|
||||
case 2: return Integer.MAX_VALUE;
|
||||
case 3: case 4: case 5:
|
||||
return rnd.nextInt(20) - 10;
|
||||
default: return rnd.nextInt();
|
||||
}
|
||||
}
|
||||
|
||||
public static short nextShort() {
|
||||
switch(rnd.nextInt(10)) {
|
||||
case 0: return 0;
|
||||
case 1: return Short.MIN_VALUE;
|
||||
case 2: return Short.MAX_VALUE;
|
||||
case 3: case 4: case 5:
|
||||
return (short) (rnd.nextInt(20) - 10);
|
||||
default: return (short) rnd.nextInt();
|
||||
}
|
||||
}
|
||||
|
||||
public static char nextChar() {
|
||||
switch(rnd.nextInt(10)) {
|
||||
case 0: return 0;
|
||||
case 1: return Character.MIN_VALUE;
|
||||
case 2: return Character.MAX_VALUE;
|
||||
case 3: case 4: case 5:
|
||||
return (char) (rnd.nextInt(20) - 10);
|
||||
default: return (char) rnd.nextInt();
|
||||
}
|
||||
}
|
||||
|
||||
public static byte nextByte() {
|
||||
switch(rnd.nextInt(10)) {
|
||||
case 0: return 0;
|
||||
case 1: return Byte.MIN_VALUE;
|
||||
case 2: return Byte.MAX_VALUE;
|
||||
case 3: case 4: case 5:
|
||||
return (byte) (rnd.nextInt(20) - 10);
|
||||
default: return (byte) rnd.nextInt();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean nextBoolean() {
|
||||
return rnd.nextBoolean();
|
||||
}
|
||||
|
||||
public static double nextDouble() {
|
||||
switch(rnd.nextInt(20)) {
|
||||
case 0: return 0;
|
||||
case 1: return -0.0;
|
||||
case 2: return Double.MIN_VALUE;
|
||||
case 3: return Double.MAX_VALUE;
|
||||
case 4: return Double.NaN;
|
||||
case 5: return Double.NEGATIVE_INFINITY;
|
||||
case 6: return Double.POSITIVE_INFINITY;
|
||||
case 7: case 8: case 9:
|
||||
return (rnd.nextInt(20) - 10);
|
||||
default: return rnd.nextDouble();
|
||||
}
|
||||
}
|
||||
|
||||
public static float nextFloat() {
|
||||
switch(rnd.nextInt(20)) {
|
||||
case 0: return 0;
|
||||
case 1: return -0.0f;
|
||||
case 2: return Float.MIN_VALUE;
|
||||
case 3: return Float.MAX_VALUE;
|
||||
case 4: return Float.NaN;
|
||||
case 5: return Float.NEGATIVE_INFINITY;
|
||||
case 6: return Float.POSITIVE_INFINITY;
|
||||
case 7: case 8: case 9:
|
||||
return (rnd.nextInt(20) - 10);
|
||||
default: return rnd.nextFloat();
|
||||
}
|
||||
}
|
||||
|
||||
public static Object nextObject() {
|
||||
switch(rnd.nextInt(10)) {
|
||||
case 0: return null;
|
||||
case 1: return "foo";
|
||||
case 2: case 3: case 4:
|
||||
return Double.valueOf(nextDouble());
|
||||
default: return Integer.valueOf(nextInt());
|
||||
}
|
||||
}
|
||||
|
||||
public static long[] longArray(int length) {
|
||||
long[] result = new long[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextLong();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int[] intArray(int length) {
|
||||
int[] result = new int[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextInt();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static short[] shortArray(int length) {
|
||||
short[] result = new short[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextShort();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static char[] charArray(int length) {
|
||||
char[] result = new char[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextChar();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] byteArray(int length) {
|
||||
byte[] result = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextByte();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean[] booleanArray(int length) {
|
||||
boolean[] result = new boolean[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextBoolean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double[] doubleArray(int length) {
|
||||
double[] result = new double[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextDouble();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float[] floatArray(int length) {
|
||||
float[] result = new float[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextFloat();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Object[] flatObjectArray(int length) {
|
||||
Object[] result = new Object[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
result[i] = Rnd.nextObject();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calling this for length >> 100 is likely to run out of memory! It
|
||||
// should be perhaps be tuned to allow for longer arrays
|
||||
public static Object[] nestedObjectArray(int length) {
|
||||
Object[] result = new Object[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
switch(rnd.nextInt(16)) {
|
||||
case 0: result[i] = nestedObjectArray(length/2);
|
||||
break;
|
||||
case 1: result[i] = longArray(length/2);
|
||||
break;
|
||||
case 2: result[i] = intArray(length/2);
|
||||
break;
|
||||
case 3: result[i] = shortArray(length/2);
|
||||
break;
|
||||
case 4: result[i] = charArray(length/2);
|
||||
break;
|
||||
case 5: result[i] = byteArray(length/2);
|
||||
break;
|
||||
case 6: result[i] = floatArray(length/2);
|
||||
break;
|
||||
case 7: result[i] = doubleArray(length/2);
|
||||
break;
|
||||
case 8: result[i] = longArray(length/2);
|
||||
break;
|
||||
default: result[i] = Rnd.nextObject();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Primitive arrays viewed as lists. Inefficient but cool.
|
||||
* This utility should be generally useful in writing regression/unit/basic
|
||||
* tests.
|
||||
*/
|
||||
|
||||
class PrimitiveArrays {
|
||||
public static List<Long> asList(final long[] a) {
|
||||
return new AbstractList<Long>() {
|
||||
public Long get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Long set(int i, Long e) {
|
||||
long oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Integer> asList(final int[] a) {
|
||||
return new AbstractList<Integer>() {
|
||||
public Integer get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Integer set(int i, Integer e) {
|
||||
int oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Short> asList(final short[] a) {
|
||||
return new AbstractList<Short>() {
|
||||
public Short get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Short set(int i, Short e) {
|
||||
short oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Character> asList(final char[] a) {
|
||||
return new AbstractList<Character>() {
|
||||
public Character get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Character set(int i, Character e) {
|
||||
Character oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Byte> asList(final byte[] a) {
|
||||
return new AbstractList<Byte>() {
|
||||
public Byte get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Byte set(int i, Byte e) {
|
||||
Byte oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Boolean> asList(final boolean[] a) {
|
||||
return new AbstractList<Boolean>() {
|
||||
public Boolean get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Boolean set(int i, Boolean e) {
|
||||
Boolean oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Double> asList(final double[] a) {
|
||||
return new AbstractList<Double>() {
|
||||
public Double get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Double set(int i, Double e) {
|
||||
Double oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Float> asList(final float[] a) {
|
||||
return new AbstractList<Float>() {
|
||||
public Float get(int i) { return a[i]; }
|
||||
public int size() { return a.length; }
|
||||
|
||||
public Float set(int i, Float e) {
|
||||
Float oldVal = a[i];
|
||||
a[i] = e;
|
||||
return oldVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
1125
test/jdk/java/util/Arrays/ArraysEqCmpTest.java
Normal file
1125
test/jdk/java/util/Arrays/ArraysEqCmpTest.java
Normal file
File diff suppressed because it is too large
Load diff
80
test/jdk/java/util/Arrays/AsList.java
Normal file
80
test/jdk/java/util/Arrays/AsList.java
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8155600
|
||||
* @summary Tests for Arrays.asList()
|
||||
* @run junit AsList
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class AsList {
|
||||
/*
|
||||
* Iterator contract test
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("arrays")
|
||||
public void testIterator(Object[] array) {
|
||||
Iterator<Object> itr = Arrays.asList(array).iterator();
|
||||
for (Object o : array) {
|
||||
assertTrue(itr.hasNext());
|
||||
assertTrue(itr.hasNext()); // must be idempotent
|
||||
assertSame(o, itr.next());
|
||||
assertThrows(UnsupportedOperationException.class, itr::remove);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
assertFalse(itr.hasNext());
|
||||
assertThrows(NoSuchElementException.class, itr::next);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object[][] arrays() {
|
||||
return new Object[][] {
|
||||
{ new Object[] { } },
|
||||
{ new Object[] { 1 } },
|
||||
{ new Object[] { null } },
|
||||
{ new Object[] { null, 1 } },
|
||||
{ new Object[] { 1, null } },
|
||||
{ new Object[] { null, null } },
|
||||
{ new Object[] { null, 1, 2 } },
|
||||
{ new Object[] { 1, null, 2 } },
|
||||
{ new Object[] { 1, 2, null } },
|
||||
{ new Object[] { null, null, null } },
|
||||
{ new Object[] { 1, 2, 3, null, 4 } },
|
||||
{ new Object[] { "a", "a", "a", "a" } },
|
||||
{ IntStream.range(0, 100).boxed().toArray() }
|
||||
};
|
||||
}
|
||||
}
|
||||
115
test/jdk/java/util/Arrays/Big.java
Normal file
115
test/jdk/java/util/Arrays/Big.java
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 5045582
|
||||
* @summary arrays larger than 1<<30
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
// A proper regression test for 5045582 requires too much memory.
|
||||
// If you have a really big machine, run like this:
|
||||
// java -Xms25g -Xmx25g Big 30
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Big {
|
||||
|
||||
private static void realMain(String[] args) throws Throwable {
|
||||
final int shift = intArg(args, 0, 10); // "30" is real test
|
||||
final int tasks = intArg(args, 1, ~0); // all tasks
|
||||
final int n = (1<<shift) + 47;
|
||||
|
||||
// To test byte arrays larger than 1<<30, you need 1600MB. Run like:
|
||||
// java -Xms1600m -Xmx1600m Big 30 1
|
||||
if ((tasks & 0x1) != 0) {
|
||||
System.out.println("byte[]");
|
||||
System.gc();
|
||||
byte[] a = new byte[n];
|
||||
a[0] = (byte) -44;
|
||||
a[1] = (byte) -43;
|
||||
a[n-2] = (byte) +43;
|
||||
a[n-1] = (byte) +44;
|
||||
for (int i : new int[] { 0, 1, n-2, n-1 })
|
||||
try { equal(i, Arrays.binarySearch(a, a[i])); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
for (int i : new int[] { n-2, n-1 })
|
||||
try { equal(i, Arrays.binarySearch(a, n-5, n, a[i])); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
|
||||
a[n-19] = (byte) 45;
|
||||
try { Arrays.sort(a, n-29, n); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
equal(a[n-1], (byte) 45);
|
||||
equal(a[n-2], (byte) 44);
|
||||
equal(a[n-3], (byte) 43);
|
||||
equal(a[n-4], (byte) 0);
|
||||
}
|
||||
|
||||
// To test Object arrays larger than 1<<30, you need 13GB. Run like:
|
||||
// java -Xms13g -Xmx13g Big 30 2
|
||||
if ((tasks & 0x2) != 0) {
|
||||
System.out.println("Integer[]");
|
||||
System.gc();
|
||||
Integer[] a = new Integer[n];
|
||||
Integer ZERO = 0;
|
||||
Arrays.fill(a, ZERO);
|
||||
a[0] = -44;
|
||||
a[1] = -43;
|
||||
a[n-2] = +43;
|
||||
a[n-1] = +44;
|
||||
for (int i : new int[] { 0, 1, n-2, n-1 })
|
||||
try { equal(i, Arrays.binarySearch(a, a[i])); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
for (int i : new int[] { n-2, n-1 })
|
||||
try { equal(i, Arrays.binarySearch(a, n-5, n, a[i])); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
|
||||
a[n-19] = 45;
|
||||
try { Arrays.sort(a, n-29, n); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
equal(a[n-1], 45);
|
||||
equal(a[n-2], 44);
|
||||
equal(a[n-3], 43);
|
||||
equal(a[n-4], 0);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
static int intArg(String[] args, int i, int defaultValue) {
|
||||
return args.length > i ? Integer.parseInt(args[i]) : defaultValue;}
|
||||
}
|
||||
425
test/jdk/java/util/Arrays/CopyMethods.java
Normal file
425
test/jdk/java/util/Arrays/CopyMethods.java
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4655503
|
||||
* @summary Test for array cloning and slicing methods.
|
||||
* @author John Rose
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class CopyMethods {
|
||||
static int muzzle; // if !=0, suppresses ("muzzles") messages
|
||||
|
||||
static int maxLen = 40; // maximum length of test arrays
|
||||
static int shortStepsNear = 4; // interesting span near critical values
|
||||
static int downShift = 3;
|
||||
|
||||
static int testCasesRun = 0;
|
||||
static long consing = 0;
|
||||
|
||||
// very simple tests, mainly to test the framework itself
|
||||
static void simpleTests() {
|
||||
int[] a = (int[]) makeArray(3, int.class);
|
||||
if (muzzle == 0)
|
||||
System.out.println("int[] a = "+Arrays.toString(a));
|
||||
check(a.length == 3);
|
||||
check(a[0] == testValues[0]);
|
||||
check(a[1] == testValues[1]);
|
||||
check(a[2] == testValues[2]);
|
||||
checkArray(a, int.class, 3, 0, 3);
|
||||
// negative test of testing framework:
|
||||
for (int bad = -2; bad < a.length; bad++) {
|
||||
try {
|
||||
int[] aa = a.clone();
|
||||
if (bad < 0) aa = new int[4];
|
||||
else aa[bad] = 0;
|
||||
++muzzle;
|
||||
// the following check should fail!
|
||||
if (bad == -2)
|
||||
checkArray(new String[3], int.class, 0, 0, a.length);
|
||||
else
|
||||
checkArray(aa, int.class, 0, 0, a.length);
|
||||
throw new Error("Should Not Reach Here");
|
||||
} catch (RuntimeException ee) {
|
||||
--muzzle;
|
||||
if (muzzle == 0)
|
||||
System.out.println("Expected: "+ee);
|
||||
}
|
||||
}
|
||||
checkArray(Arrays.copyOf(a, 0), int.class, 0, 0, 3);
|
||||
checkArray(Arrays.copyOf(a, 1), int.class, 1, 0, 3);
|
||||
checkArray(Arrays.copyOf(a, 2), int.class, 2, 0, 3);
|
||||
checkArray(Arrays.copyOf(a, 3), int.class, 3, 0, 3);
|
||||
checkArray(Arrays.copyOf(a, 4), int.class, 4, 0, 3);
|
||||
|
||||
// quick test of copyOfRange
|
||||
int[] ar = Arrays.copyOfRange(a, 1, 3);
|
||||
check(ar.length == 2);
|
||||
check(ar[0] == a[1]);
|
||||
check(ar[1] == a[2]);
|
||||
checkArray(ar, int.class, 2, 1, 2);
|
||||
ar = Arrays.copyOfRange(a, 2, 4);
|
||||
check(ar.length == 2);
|
||||
check(ar[0] == a[2]);
|
||||
check(ar[1] == 0);
|
||||
checkArray(ar, int.class, 2, 2, 1);
|
||||
ar = Arrays.copyOfRange(a, 3, 5);
|
||||
check(ar.length == 2);
|
||||
check(ar[0] == 0);
|
||||
check(ar[1] == 0);
|
||||
checkArray(ar, int.class, 2, 3, 0);
|
||||
byte[] ba = (byte[]) makeArray(3, byte.class);
|
||||
if (muzzle == 0)
|
||||
System.out.println("byte[] ba = "+Arrays.toString(ba));
|
||||
for (int j = 0; j <= ba.length+2; j++) {
|
||||
byte[] bb = Arrays.copyOf(ba, j);
|
||||
if (muzzle == 0)
|
||||
System.out.println("copyOf(ba,"+j+") = "+
|
||||
Arrays.toString(bb));
|
||||
checkArray(bb, byte.class, j, 0, ba.length);
|
||||
byte[] bbr = Arrays.copyOfRange(ba, 0, j);
|
||||
check(Arrays.equals(bb, bbr));
|
||||
}
|
||||
for (int i = 0; i <= a.length; i++) {
|
||||
for (int j = i; j <= a.length+2; j++) {
|
||||
byte[] br = Arrays.copyOfRange(ba, i, j);
|
||||
if (muzzle == 0)
|
||||
System.out.println("copyOfRange(ba,"+i+","+j+") = "+
|
||||
Arrays.toString(br));
|
||||
checkArray(br, byte.class, j-i, i, ba.length-i);
|
||||
}
|
||||
}
|
||||
String[] sa = (String[]) makeArray(3, String.class);
|
||||
if (muzzle == 0)
|
||||
System.out.println("String[] sa = "+Arrays.toString(sa));
|
||||
check(sa[0].equals(Integer.toHexString(testValues[0])));
|
||||
check(sa[1].equals(Integer.toHexString(testValues[1])));
|
||||
check(sa[2].equals(Integer.toHexString(testValues[2])));
|
||||
checkArray(sa, String.class, sa.length, 0, sa.length);
|
||||
String[] sa4 = Arrays.copyOf(sa, sa.length+1);
|
||||
check(sa4[0] == sa[0]);
|
||||
check(sa4[1] == sa[1]);
|
||||
check(sa4[2] == sa[2]);
|
||||
check(sa4[sa.length] == null);
|
||||
checkArray(sa4, String.class, sa4.length, 0, sa.length);
|
||||
String[] sr4 = Arrays.copyOfRange(sa, 1, 5);
|
||||
check(sr4[0] == sa[1]);
|
||||
check(sr4[1] == sa[2]);
|
||||
check(sr4[2] == null);
|
||||
check(sr4[3] == null);
|
||||
checkArray(sr4, String.class, 4, 1, sa.length-1);
|
||||
if (muzzle == 0)
|
||||
System.out.println("simpleTests done");
|
||||
}
|
||||
|
||||
// the framework: a fixed series of test values
|
||||
static final int[] testValues;
|
||||
static {
|
||||
testValues = new int[1000];
|
||||
Random r = new Random();
|
||||
for (int i = 0; i < testValues.length; i++) {
|
||||
testValues[i] = r.nextInt();
|
||||
}
|
||||
}
|
||||
/** Return a canonical test value of a desired index and type.
|
||||
* The original test values are random ints. Derive other test
|
||||
* values as follows:
|
||||
* <pre>
|
||||
* int tv = testValues[i]
|
||||
* (C)tv C is byte, short, char, long, float, double
|
||||
* (tv&1)!=0 C is boolean
|
||||
* (Integer)tv C is Object and tv%16 != 0
|
||||
* null C is Object and tv%16 == 0
|
||||
* Integer.toHexString(tv) C is String and tv != 0
|
||||
* null C is String and tv == 0
|
||||
* </pre>
|
||||
* are derived by ordinary Java coercions, except that boolean
|
||||
* samples the LSB of the int value, and String is the hex numeral.
|
||||
*
|
||||
* (Also, the 0th String is null, and the 0th Object mod 16 is null,
|
||||
* regardless of the original int test value.)
|
||||
*/
|
||||
static Object testValue(int i, Class<?> c) {
|
||||
int tv = testValues[i % testValues.length];
|
||||
if (i >= testValues.length) tv ^= i;
|
||||
// Turn the canonical int to a float, boolean, String, whatever:
|
||||
return invoke(coercers.get(c), tv);
|
||||
}
|
||||
/** Build a test array of the given length,
|
||||
* packed with a subsequence of the test values.
|
||||
* The first element of the array is always testValue(0).
|
||||
*/
|
||||
static Object makeArray(int len, Class<?> c) {
|
||||
Object a = Array.newInstance(c, len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Array.set(a, i, testValue(i, c));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
/** Check that the given array has the required length.
|
||||
* Check also that it is packed, up to firstNull, with
|
||||
* a particular subsequence of the canonical test values.
|
||||
* The subsequence must begin with a[0] == testValue(offset).
|
||||
* At a[firstNull] and beyond, the array must contain null values.
|
||||
*/
|
||||
static void checkArray(Object a, Class<?> c, int requiredLen, int offset, int firstNull) {
|
||||
check(c == a.getClass().getComponentType());
|
||||
Object nullValue = nullValues.get(c);
|
||||
// Note: asserts in here are not part of the test program.
|
||||
// They verify the integrity of the test method itself.
|
||||
assert(nullValues.containsKey(c));
|
||||
|
||||
int misses = 0;
|
||||
int firstMiss = -1;
|
||||
// Check required length first.
|
||||
int length = Array.getLength(a);
|
||||
if (length != requiredLen && requiredLen != -1) {
|
||||
if (muzzle == 0)
|
||||
System.out.println("*** a.length = "+length+" != "+requiredLen);
|
||||
++misses;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object tv = (i >= firstNull) ? nullValue : testValue(i+offset, c);
|
||||
Object ai = Array.get(a, i);
|
||||
if (!eq(ai, tv)) {
|
||||
if (muzzle == 0)
|
||||
System.out.println("*** a["+i+"] = "+ai+" != "+tv);
|
||||
if (misses == 0) firstMiss = i;
|
||||
if (++misses > 10) break;
|
||||
}
|
||||
}
|
||||
if (misses != 0) {
|
||||
Method toString = toStrings.get(c);
|
||||
if (toString == null) toString = toStrings.get(Object.class);
|
||||
throw new RuntimeException("checkArray failed at "+firstMiss
|
||||
+" "+c+"[]"
|
||||
+" : "+invoke(toString, a));
|
||||
}
|
||||
}
|
||||
// Typical comparison helper. Why isn't this a method somewhere.
|
||||
static boolean eq(Object x, Object y) {
|
||||
return x == null? y == null: x.equals(y);
|
||||
}
|
||||
// Exception-ignoring invoke function.
|
||||
static Object invoke(Method m, Object... args) {
|
||||
Exception ex;
|
||||
try {
|
||||
return m.invoke(null, args);
|
||||
} catch (InvocationTargetException ee) {
|
||||
ex = ee;
|
||||
} catch (IllegalAccessException ee) {
|
||||
ex = ee;
|
||||
} catch (IllegalArgumentException ee) {
|
||||
ex = ee;
|
||||
}
|
||||
ArrayList<Object> call = new ArrayList<Object>();
|
||||
call.add(m); Collections.addAll(call, args);
|
||||
throw new RuntimeException(call+" : "+ex);
|
||||
}
|
||||
// version of assert() that runs unconditionally
|
||||
static void check(boolean z) {
|
||||
if (!z) throw new RuntimeException("check failed");
|
||||
}
|
||||
|
||||
|
||||
/** Run about 10**5 distinct parameter combinations
|
||||
* on copyOf and copyOfRange. Use all primitive types,
|
||||
* and String and Object.
|
||||
* Try to all critical values, looking for fencepost errors.
|
||||
*/
|
||||
static void fullTests(int maxLen, Class<?> c) {
|
||||
Method cloner = cloners.get(c);
|
||||
assert(cloner != null) : c;
|
||||
Method cloneRanger = cloneRangers.get(c);
|
||||
// Note: asserts in here are not part of the test program.
|
||||
// They verify the integrity of the test method itself.
|
||||
assert(cloneRanger != null) : c;
|
||||
for (int src = 0; src <= maxLen; src = inc(src, 0, maxLen)) {
|
||||
Object a = makeArray(src, c);
|
||||
for (int x : new ArrayList<Integer>()) {}
|
||||
for (int j = 0; j <= maxLen; j = inc(j, src, maxLen)) {
|
||||
// b = Arrays.copyOf(a, j);
|
||||
Object b = invoke(cloner, a, j);
|
||||
checkArray(b, c, j, 0, src);
|
||||
testCasesRun++;
|
||||
consing += j;
|
||||
|
||||
int maxI = Math.min(src, j);
|
||||
for (int i = 0; i <= maxI; i = inc(i, src, maxI)) {
|
||||
// r = Arrays.copyOfRange(a, i, j);
|
||||
Object r = invoke(cloneRanger, a, i, j);
|
||||
checkArray(r, c, j-i, i, src-i);
|
||||
//System.out.println("case c="+c+" src="+src+" i="+i+" j="+j);
|
||||
testCasesRun++;
|
||||
consing += j-i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Increment x by at least one. Increment by a little more unless
|
||||
// it is near a critical value, either zero, crit1, or crit2.
|
||||
static int inc(int x, int crit1, int crit2) {
|
||||
int D = shortStepsNear;
|
||||
if (crit1 > crit2) { int t = crit1; crit1 = crit2; crit2 = t; }
|
||||
assert(crit1 <= crit2);
|
||||
assert(x <= crit2); // next1 or next2 must be the limit value
|
||||
x += 1;
|
||||
if (x > D) {
|
||||
if (x < crit1-D) {
|
||||
x += (x << 1) >> downShift; // giant step toward crit1-D
|
||||
if (x > crit1-D) x = crit1-D;
|
||||
} else if (x >= crit1+D && x < crit2-D) {
|
||||
x += (x << 1) >> downShift; // giant step toward crit2-D
|
||||
if (x > crit2-D) x = crit2-D;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
public static void main(String[] av) {
|
||||
boolean verbose = (av.length != 0);
|
||||
muzzle = (verbose? 0: 1);
|
||||
if (muzzle == 0)
|
||||
System.out.println("test values: "+Arrays.toString(Arrays.copyOf(testValues, 5))+"...");
|
||||
|
||||
simpleTests();
|
||||
|
||||
muzzle = 0; // turn on print statements (affects failures only)
|
||||
|
||||
fullTests();
|
||||
if (verbose)
|
||||
System.out.println("ran "+testCasesRun+" tests, avg len="
|
||||
+(float)consing/testCasesRun);
|
||||
|
||||
// test much larger arrays, more sparsely
|
||||
maxLen = 500;
|
||||
shortStepsNear = 2;
|
||||
downShift = 0;
|
||||
testCasesRun = 0;
|
||||
consing = 0;
|
||||
fullTests();
|
||||
if (verbose)
|
||||
System.out.println("ran "+testCasesRun+" tests, avg len="
|
||||
+(float)consing/testCasesRun);
|
||||
}
|
||||
|
||||
static void fullTests() {
|
||||
for (Class<?> c : allTypes) {
|
||||
fullTests(maxLen, c);
|
||||
}
|
||||
}
|
||||
|
||||
// We must run all the our tests on each of 8 distinct primitive types,
|
||||
// and two reference types (Object, String) for good measure.
|
||||
// This would be a pain to write out by hand, statically typed.
|
||||
// So, use reflection. Following are the tables of methods we use.
|
||||
// (The initial simple tests exercise enough of the static typing
|
||||
// features of the API to ensure that they compile as advertised.)
|
||||
|
||||
static Object coerceToObject(int x) { return (x & 0xF) == 0? null: new Integer(x); }
|
||||
static String coerceToString(int x) { return (x == 0)? null: Integer.toHexString(x); }
|
||||
static Integer coerceToInteger(int x) { return (x == 0)? null: x; }
|
||||
static byte coerceToByte(int x) { return (byte)x; }
|
||||
static short coerceToShort(int x) { return (short)x; }
|
||||
static int coerceToInt(int x) { return x; }
|
||||
static long coerceToLong(int x) { return x; }
|
||||
static char coerceToChar(int x) { return (char)x; }
|
||||
static float coerceToFloat(int x) { return x; }
|
||||
static double coerceToDouble(int x) { return x; }
|
||||
static boolean coerceToBoolean(int x) { return (x&1) != 0; }
|
||||
|
||||
static Integer[] copyOfIntegerArray(Object[] a, int len) {
|
||||
// This guy exercises the API based on a type-token.
|
||||
// Note the static typing.
|
||||
return Arrays.copyOf(a, len, Integer[].class);
|
||||
}
|
||||
static Integer[] copyOfIntegerArrayRange(Object[] a, int m, int n) {
|
||||
// This guy exercises the API based on a type-token.
|
||||
// Note the static typing.
|
||||
return Arrays.copyOfRange(a, m, n, Integer[].class);
|
||||
}
|
||||
|
||||
static final List<Class<?>> allTypes
|
||||
= Arrays.asList(new Class<?>[]
|
||||
{ Object.class, String.class, Integer.class,
|
||||
byte.class, short.class, int.class, long.class,
|
||||
char.class, float.class, double.class,
|
||||
boolean.class
|
||||
});
|
||||
static final HashMap<Class<?>,Method> coercers;
|
||||
static final HashMap<Class<?>,Method> cloners;
|
||||
static final HashMap<Class<?>,Method> cloneRangers;
|
||||
static final HashMap<Class<?>,Method> toStrings;
|
||||
static final HashMap<Class<?>,Object> nullValues;
|
||||
static {
|
||||
coercers = new HashMap<Class<?>,Method>();
|
||||
Method[] testMethods = CopyMethods.class.getDeclaredMethods();
|
||||
Method cia = null, ciar = null;
|
||||
for (int i = 0; i < testMethods.length; i++) {
|
||||
Method m = testMethods[i];
|
||||
if (!Modifier.isStatic(m.getModifiers())) continue;
|
||||
Class<?> rt = m.getReturnType();
|
||||
if (m.getName().startsWith("coerceTo") && allTypes.contains(rt))
|
||||
coercers.put(m.getReturnType(), m);
|
||||
if (m.getName().equals("copyOfIntegerArray"))
|
||||
cia = m;
|
||||
if (m.getName().equals("copyOfIntegerArrayRange"))
|
||||
ciar = m;
|
||||
}
|
||||
Method[] arrayMethods = Arrays.class.getDeclaredMethods();
|
||||
cloners = new HashMap<Class<?>,Method>();
|
||||
cloneRangers = new HashMap<Class<?>,Method>();
|
||||
toStrings = new HashMap<Class<?>,Method>();
|
||||
for (int i = 0; i < arrayMethods.length; i++) {
|
||||
Method m = arrayMethods[i];
|
||||
if (!Modifier.isStatic(m.getModifiers())) continue;
|
||||
Class<?> rt = m.getReturnType();
|
||||
if (m.getName().equals("copyOf")
|
||||
&& m.getParameterTypes().length == 2)
|
||||
cloners.put(rt.getComponentType(), m);
|
||||
if (m.getName().equals("copyOfRange")
|
||||
&& m.getParameterTypes().length == 3)
|
||||
cloneRangers.put(rt.getComponentType(), m);
|
||||
if (m.getName().equals("toString")) {
|
||||
Class<?> pt = m.getParameterTypes()[0];
|
||||
toStrings.put(pt.getComponentType(), m);
|
||||
}
|
||||
}
|
||||
cloners.put(String.class, cloners.get(Object.class));
|
||||
cloneRangers.put(String.class, cloneRangers.get(Object.class));
|
||||
assert(cia != null);
|
||||
cloners.put(Integer.class, cia);
|
||||
assert(ciar != null);
|
||||
cloneRangers.put(Integer.class, ciar);
|
||||
nullValues = new HashMap<Class<?>,Object>();
|
||||
for (Class<?> c : allTypes) {
|
||||
nullValues.put(c, invoke(coercers.get(c), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
149
test/jdk/java/util/Arrays/Correct.java
Normal file
149
test/jdk/java/util/Arrays/Correct.java
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4726380 8037097
|
||||
* @summary Check that different sorts give equivalent results.
|
||||
* @key randomness
|
||||
* @run junit Correct
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class Correct {
|
||||
|
||||
static final Random rnd = new Random();
|
||||
static final int ITERATIONS = 1000;
|
||||
static final int TEST_SIZE = 1000;
|
||||
|
||||
@Test
|
||||
public void testDefaultSort() {
|
||||
for (int i=0; i<ITERATIONS; i++) {
|
||||
int size = rnd.nextInt(TEST_SIZE) + 1;
|
||||
Integer[] array1 = getIntegerArray(size);
|
||||
Integer[] array2 = Arrays.copyOf(array1, array1.length);
|
||||
Arrays.sort(array1, array1.length/3, array1.length/2);
|
||||
stupidSort(array2, array2.length/3, array2.length/2);
|
||||
Assertions.assertArrayEquals(array2, array1, "Arrays did not match. size=" + size);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("comparators")
|
||||
public void testComparatorSort(Comparator<Integer> comparator) {
|
||||
for (int i=0; i<ITERATIONS; i++) {
|
||||
int size = rnd.nextInt(TEST_SIZE) + 1;
|
||||
Integer[] array1 = getIntegerArray(size);
|
||||
Integer[] array2 = Arrays.copyOf(array1, array1.length);
|
||||
Arrays.sort(array1, array1.length/3, array1.length/2, comparator);
|
||||
stupidSort(array2, array2.length/3, array2.length/2, comparator);
|
||||
Assertions.assertArrayEquals(array2, array1, "Arrays did not match. size=" + size);
|
||||
}
|
||||
}
|
||||
|
||||
static Integer[] getIntegerArray(int size) {
|
||||
Integer[] blah = new Integer[size];
|
||||
for (int x=0; x<size; x++) {
|
||||
blah[x] = new Integer(rnd.nextInt());
|
||||
}
|
||||
return blah;
|
||||
}
|
||||
|
||||
static void stupidSort(Integer[] a1, int from, int to) {
|
||||
if (from > to - 1 )
|
||||
return;
|
||||
|
||||
for (int x=from; x<to; x++) {
|
||||
Integer lowest = a1[x];
|
||||
int lowestIndex = x;
|
||||
for (int y=x + 1; y<to; y++) {
|
||||
if (((Comparable)a1[y]).compareTo((Comparable)lowest) < 0) {
|
||||
lowest = a1[y];
|
||||
lowestIndex = y;
|
||||
}
|
||||
}
|
||||
if (lowestIndex != x) {
|
||||
swap(a1, x, lowestIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void stupidSort(Integer[] a1, int from, int to, Comparator<Integer> comparator) {
|
||||
if (from > to - 1 )
|
||||
return;
|
||||
|
||||
for (int x=from; x<to; x++) {
|
||||
Integer lowest = a1[x];
|
||||
int lowestIndex = x;
|
||||
for (int y=x + 1; y<to; y++) {
|
||||
if (comparator.compare(a1[y], lowest) < 0) {
|
||||
lowest = a1[y];
|
||||
lowestIndex = y;
|
||||
}
|
||||
}
|
||||
if (lowestIndex != x) {
|
||||
swap(a1, x, lowestIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static <T> void swap(T[] x, int a, int b) {
|
||||
T t = x[a];
|
||||
x[a] = x[b];
|
||||
x[b] = t;
|
||||
}
|
||||
|
||||
public static Iterator<Object[]> comparators() {
|
||||
Object[][] comparators = new Object[][] {
|
||||
new Object[] { Comparator.naturalOrder() },
|
||||
new Object[] { Comparator.<Integer>naturalOrder().reversed() },
|
||||
new Object[] { STANDARD_ORDER },
|
||||
new Object[] { STANDARD_ORDER.reversed() },
|
||||
new Object[] { REVERSE_ORDER },
|
||||
new Object[] { REVERSE_ORDER.reversed() },
|
||||
new Object[] { Comparator.comparingInt(Integer::intValue) }
|
||||
};
|
||||
|
||||
return Arrays.asList(comparators).iterator();
|
||||
}
|
||||
|
||||
private static final Comparator<Integer> STANDARD_ORDER = new Comparator<Integer>() {
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Comparator<Integer> REVERSE_ORDER = new Comparator<Integer>() {
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return - o1.compareTo(o2);
|
||||
}
|
||||
};
|
||||
}
|
||||
74
test/jdk/java/util/Arrays/Fill.java
Normal file
74
test/jdk/java/util/Arrays/Fill.java
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4229892
|
||||
* @summary Arrays.fill(Object[], ...) should throw ArrayStoreException
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
|
||||
public class Fill {
|
||||
private static void realMain(String[] args) throws Throwable {
|
||||
try {
|
||||
Arrays.fill(new Integer[3], "foo");
|
||||
fail("Expected ArrayStoreException");
|
||||
}
|
||||
catch (ArrayStoreException e) { pass(); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
|
||||
try {
|
||||
Arrays.fill(new Integer[3], 0, 2, "foo");
|
||||
fail("Expected ArrayStoreException");
|
||||
}
|
||||
catch (ArrayStoreException e) { pass(); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
|
||||
try {
|
||||
Arrays.fill(new Integer[3], 0, 4, "foo");
|
||||
fail("Expected ArrayIndexOutOfBoundsException");
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e) { pass(); }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
||||
123
test/jdk/java/util/Arrays/FloatDoubleOrder.java
Normal file
123
test/jdk/java/util/Arrays/FloatDoubleOrder.java
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 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 4143272 6548425
|
||||
* @summary The natural ordering on Float and Double was not even a partial
|
||||
* order (i.e., it violated the contract of Comparable.compareTo).
|
||||
* Now it's a total ordering. Arrays.sort(double[])
|
||||
* and Arrays.sort(double[]) reflect the new ordering. Also,
|
||||
* Arrays.equals(double[], double[]) and
|
||||
* Arrays.equals(float[], float[]) reflect the definition of
|
||||
* equality used by Float and Double.
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class FloatDoubleOrder {
|
||||
void test(String[] args) throws Throwable {
|
||||
double[] unsortedDbl = new double[] {1.0d, 3.7d, Double.NaN, -2.0d,
|
||||
Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0d, -0.0d};
|
||||
|
||||
double[] sortedDbl = new double[] {Double.NEGATIVE_INFINITY, -2.0d,
|
||||
-0.0d, 0.0d, 1.0d, 3.7d, Double.POSITIVE_INFINITY, Double.NaN};
|
||||
|
||||
List list = new ArrayList();
|
||||
for (int i=0; i<unsortedDbl.length; i++)
|
||||
list.add(new Double(unsortedDbl[i]));
|
||||
Collections.sort(list);
|
||||
|
||||
List sortedList = new ArrayList();
|
||||
for (int i=0; i<sortedDbl.length; i++)
|
||||
sortedList.add(new Double(sortedDbl[i]));
|
||||
|
||||
check(list.equals(sortedList));
|
||||
|
||||
Arrays.sort(unsortedDbl);
|
||||
check(Arrays.equals(unsortedDbl, sortedDbl));
|
||||
|
||||
double negNan = Double.longBitsToDouble(0xfff8000000000000L);
|
||||
for (int i = 0; i < sortedDbl.length; i++) {
|
||||
equal(Arrays.binarySearch(sortedDbl, sortedDbl[i]), i);
|
||||
if (Double.isNaN(sortedDbl[i]))
|
||||
equal(Arrays.binarySearch(sortedDbl, negNan), i);
|
||||
}
|
||||
|
||||
float[] unsortedFlt = new float[] {1.0f, 3.7f, Float.NaN, -2.0f,
|
||||
Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0f, -0.0f};
|
||||
|
||||
float[] sortedFlt = new float[] {Float.NEGATIVE_INFINITY, -2.0f,
|
||||
-0.0f, 0.0f, 1.0f, 3.7f, Float.POSITIVE_INFINITY, Float.NaN};
|
||||
|
||||
list.clear();
|
||||
for (int i=0; i<unsortedFlt.length; i++)
|
||||
list.add(new Float(unsortedFlt[i]));
|
||||
Collections.sort(list);
|
||||
|
||||
sortedList.clear();
|
||||
for (int i=0; i<sortedFlt.length; i++)
|
||||
sortedList.add(new Float(sortedFlt[i]));
|
||||
|
||||
check(list.equals(sortedList));
|
||||
|
||||
Arrays.sort(unsortedFlt);
|
||||
check(Arrays.equals(unsortedFlt, sortedFlt));
|
||||
|
||||
float negNaN = Float.intBitsToFloat(0xFfc00000);
|
||||
for (int i = 0; i < sortedDbl.length; i++) {
|
||||
equal(Arrays.binarySearch(sortedFlt, sortedFlt[i]), i);
|
||||
if (Float.isNaN(sortedFlt[i]))
|
||||
equal(Arrays.binarySearch(sortedFlt, negNaN), i);
|
||||
}
|
||||
|
||||
|
||||
// 6548425: Arrays.sort incorrectly sorts a double array
|
||||
// containing negative zeros
|
||||
double[] da = {-0.0d, -0.0d, 0.0d, -0.0d};
|
||||
Arrays.sort(da, 1, 4);
|
||||
check(Arrays.equals(da, new double[] {-0.0d, -0.0d, -0.0d, 0.0d}));
|
||||
|
||||
float[] fa = {-0.0f, -0.0f, 0.0f, -0.0f};
|
||||
Arrays.sort(fa, 1, 4);
|
||||
check(Arrays.equals(fa, new float[] {-0.0f, -0.0f, -0.0f, 0.0f}));
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new FloatDoubleOrder().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
||||
174
test/jdk/java/util/Arrays/HashCode.java
Normal file
174
test/jdk/java/util/Arrays/HashCode.java
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 Basic array hashCode functionality
|
||||
* @run main/othervm --add-exports java.base/jdk.internal.util=ALL-UNNAMED
|
||||
* --add-opens java.base/jdk.internal.util=ALL-UNNAMED -Xcomp -Xbatch HashCode
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class HashCode {
|
||||
private static String[] tests = { "", " ", "a", "abcdefg",
|
||||
"It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only. -- Charles Dickens, Tale of Two Cities",
|
||||
"C'était le meilleur des temps, c'était le pire des temps, c'était l'âge de la sagesse, c'était l'âge de la folie, c'était l'époque de la croyance, c'était l'époque de l'incrédulité, c'était la saison de la Lumière, c'était C'était la saison des Ténèbres, c'était le printemps de l'espoir, c'était l'hiver du désespoir, nous avions tout devant nous, nous n'avions rien devant nous, nous allions tous directement au Ciel, nous allions tous directement dans l'autre sens bref, la période ressemblait tellement à la période actuelle, que certaines de ses autorités les plus bruyantes ont insisté pour qu'elle soit reçue, pour le bien ou pour le mal, au degré superlatif de la comparaison seulement. -- Charles Dickens, Tale of Two Cities (in French)",
|
||||
"禅道修行を志した雲水は、一般に参禅のしきたりを踏んだうえで一人の師につき、各地にある専門道場と呼ばれる養成寺院に入門し、与えられた公案に取り組むことになる。公案は、師家(老師)から雲水が悟りの境地へと進んで行くために手助けとして課す問題であり、悟りの境地に達していない人には容易に理解し難い難問だが、屁理屈や詭弁が述べられているわけではなく、頓知や謎かけとも異なる。"
|
||||
};
|
||||
|
||||
byte[][] zeroes = new byte[64][];
|
||||
private static byte[][] testBytes = new byte[tests.length][];
|
||||
private static short[][] testShorts = new short[tests.length][];
|
||||
private static char[][] testChars = new char[tests.length][];
|
||||
private static int[][] testInts = new int[tests.length][];
|
||||
|
||||
private static int[] expected = { 1, 63, 128, 536518979, -1174896354, -1357593156, 428276276};
|
||||
private static int[] expectedUnsigned = { 1, 63, 128, 536518979, -1174896354, 584369596, -2025326028};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Deep introspection into range-based hash functions
|
||||
Class<?> arraysSupport = Class.forName("jdk.internal.util.ArraysSupport");
|
||||
Method vectorizedHashCode = arraysSupport.getDeclaredMethod("vectorizedHashCode", Object.class, int.class, int.class, int.class, int.class);
|
||||
vectorizedHashCode.setAccessible(true);
|
||||
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
testBytes[i] = tests[i].getBytes("UTF-8");
|
||||
int len = testBytes[i].length;
|
||||
testChars[i] = new char[len];
|
||||
testShorts[i] = new short[len];
|
||||
testInts[i] = new int[len];
|
||||
for (int j = 0; j < len; j++) {
|
||||
testChars[i][j] = (char) testBytes[i][j];
|
||||
testShorts[i][j] = testBytes[i][j];
|
||||
testInts[i][j] = testBytes[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
boolean failed = false;
|
||||
try {
|
||||
int zeroResult = 1;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
byte[] zeroes = new byte[i];
|
||||
byte[] extraZeroes = new byte[i + 47];
|
||||
for (int j = 0; j < 10_000; j++) {
|
||||
int hashCode = Arrays.hashCode(zeroes);
|
||||
if (hashCode != zeroResult) {
|
||||
throw new RuntimeException("byte[] \"" + Arrays.toString(zeroes) + "\": "
|
||||
+ " e = " + zeroResult
|
||||
+ ", hashCode = " + hashCode
|
||||
+ ", repetition = " + j);
|
||||
}
|
||||
hashCode = (int) vectorizedHashCode.invoke(null, extraZeroes, 17, i, 1, /* ArraysSupport.T_BYTE */ 8);
|
||||
if (hashCode != zeroResult) {
|
||||
throw new RuntimeException("byte[] subrange \"" + Arrays.toString(extraZeroes)
|
||||
+ "\" at offset 17, limit " + i + ": "
|
||||
+ " e = " + zeroResult
|
||||
+ ", hashCode = " + hashCode
|
||||
+ ", repetition = " + j);
|
||||
}
|
||||
}
|
||||
zeroResult *= 31;
|
||||
}
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
for (int j = 0; j < 64; j++) {
|
||||
int e = expected[i];
|
||||
int hashCode = Arrays.hashCode(testBytes[i]);
|
||||
if (hashCode != e) {
|
||||
throw new RuntimeException("byte[] \"" + Arrays.toString(testBytes[i]) + "\": "
|
||||
+ " e = " + e
|
||||
+ ", hashCode = " + hashCode
|
||||
+ ", repetition = " + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("byte[] tests passed");
|
||||
} catch (RuntimeException e) {
|
||||
System.out.println(e.getMessage());
|
||||
failed = true;
|
||||
}
|
||||
|
||||
try {
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
for (int j = 0; j < 64; j++) {
|
||||
int e = expected[i];
|
||||
int hashCode = Arrays.hashCode(testShorts[i]);
|
||||
if (hashCode != e) {
|
||||
throw new RuntimeException("short[] \"" + Arrays.toString(testShorts[i]) + "\": "
|
||||
+ " e = " + e
|
||||
+ ", hashCode = " + hashCode
|
||||
+ ", repetition = " + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("short[] tests passed");
|
||||
} catch (RuntimeException e) {
|
||||
System.out.println(e.getMessage());
|
||||
failed = true;
|
||||
}
|
||||
|
||||
try {
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
for (int j = 0; j < 64; j++) {
|
||||
int e = expected[i];
|
||||
int hashCode = Arrays.hashCode(testInts[i]);
|
||||
if (hashCode != e) {
|
||||
throw new RuntimeException("int[] \"" + Arrays.toString(testInts[i]) + "\": "
|
||||
+ " e = " + e
|
||||
+ ", hashCode = " + hashCode
|
||||
+ ", repetition = " + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("int[] tests passed");
|
||||
} catch (RuntimeException e) {
|
||||
System.out.println(e.getMessage());
|
||||
failed = true;
|
||||
}
|
||||
|
||||
try {
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
for (int j = 0; j < 64; j++) {
|
||||
int e = expectedUnsigned[i];
|
||||
int hashCode = Arrays.hashCode(testChars[i]);
|
||||
if (hashCode != e) {
|
||||
throw new RuntimeException("char[] \"" + Arrays.toString(testChars[i]) + "\": "
|
||||
+ " e = " + e
|
||||
+ ", hashCode = " + hashCode
|
||||
+ ", repetition = " + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("char[] tests passed");
|
||||
} catch (RuntimeException e) {
|
||||
System.out.println(e.getMessage());
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
throw new RuntimeException("Some tests failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
282
test/jdk/java/util/Arrays/SetAllTest.java
Normal file
282
test/jdk/java/util/Arrays/SetAllTest.java
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8012650
|
||||
* @summary Unit test for setAll, parallelSetAll variants
|
||||
* @run junit SetAllTest
|
||||
*/
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.IntToDoubleFunction;
|
||||
import java.util.function.IntToLongFunction;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class SetAllTest {
|
||||
private static final IntFunction<String> toString = i -> "N" + Integer.valueOf(i);
|
||||
private static final IntFunction<String> fillString = i -> "X";
|
||||
private static final String[] r0 = {};
|
||||
private static final String[] r1 = { "N0" };
|
||||
private static final String[] r10 = { "N0", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N8", "N9" };
|
||||
|
||||
private Object[][] stringData = new Object[][] {
|
||||
{ "empty", 0, toString, r0 },
|
||||
{ "one", 1, toString, r1 },
|
||||
{ "ten", 10, toString, r10 },
|
||||
{ "fill", 3, fillString, new String[] { "X", "X", "X" }}
|
||||
};
|
||||
|
||||
private static final IntUnaryOperator toInt = i -> i << 1;
|
||||
private static final IntUnaryOperator fillInt = i -> 99;
|
||||
private static final int[] ir0 = {};
|
||||
private static final int[] ir1 = { 0 };
|
||||
private static final int[] ir10 = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 };
|
||||
private Object[][] intData = new Object[][] {
|
||||
{ "empty", 0, toInt, ir0 },
|
||||
{ "one", 1, toInt, ir1 },
|
||||
{ "ten", 10, toInt, ir10 },
|
||||
{ "fill", 3, fillInt, new int[] { 99, 99, 99 }}
|
||||
};
|
||||
|
||||
private static final IntToLongFunction toLong = i -> i << 1;
|
||||
private static final IntToLongFunction fillLong = i -> 9999L;
|
||||
private static final long[] lr0 = {};
|
||||
private static final long[] lr1 = { 0L };
|
||||
private static final long[] lr10 = { 0L, 2L, 4L, 6L, 8L, 10L, 12L, 14L, 16L, 18L };
|
||||
private Object[][] longData = new Object[][] {
|
||||
{ "empty", 0, toLong, lr0 },
|
||||
{ "one", 1, toLong, lr1 },
|
||||
{ "ten", 10, toLong, lr10 },
|
||||
{ "fill", 3, fillLong, new long[] { 9999L, 9999L, 9999L }}
|
||||
};
|
||||
|
||||
private static final IntToDoubleFunction toDouble = i -> i * 1.1;
|
||||
private static final IntToDoubleFunction fillDouble = i -> 3.14;
|
||||
private static final double[] dr0 = {};
|
||||
private static final double[] dr1 = { 0.0 };
|
||||
private static final double[] dr10 = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
|
||||
private Object[][] doubleData = new Object[][] {
|
||||
{ "empty", 0, toDouble, dr0 },
|
||||
{ "one", 1, toDouble, dr1 },
|
||||
{ "ten", 10, toDouble, dr10 },
|
||||
{ "fill", 3, fillDouble, new double[] { 3.14, 3.14, 3.14 }}
|
||||
};
|
||||
|
||||
public Object[][] stringTests() { return stringData; }
|
||||
|
||||
public Object[][] intTests() { return intData; }
|
||||
|
||||
public Object[][] longTests() { return longData; }
|
||||
|
||||
public Object[][] doubleTests() { return doubleData; }
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("stringTests")
|
||||
public void testSetAllString(String name, int size, IntFunction<String> generator, String[] expected) {
|
||||
String[] result = new String[size];
|
||||
Arrays.setAll(result, generator);
|
||||
Assertions.assertArrayEquals(expected, result, "setAll(String[], IntFunction<String>) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new String[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
Assertions.assertArrayEquals(expected, result, "parallelSetAll(String[], IntFunction<String>) case " + name + " failed.");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("intTests")
|
||||
public void testSetAllInt(String name, int size, IntUnaryOperator generator, int[] expected) {
|
||||
int[] result = new int[size];
|
||||
Arrays.setAll(result, generator);
|
||||
Assertions.assertArrayEquals(expected, result, "setAll(int[], IntUnaryOperator) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new int[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
Assertions.assertArrayEquals(expected, result, "parallelSetAll(int[], IntUnaryOperator) case " + name + " failed.");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("longTests")
|
||||
public void testSetAllLong(String name, int size, IntToLongFunction generator, long[] expected) {
|
||||
long[] result = new long[size];
|
||||
Arrays.setAll(result, generator);
|
||||
Assertions.assertArrayEquals(expected, result, "setAll(long[], IntToLongFunction) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new long[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
Assertions.assertArrayEquals(expected, result, "parallelSetAll(long[], IntToLongFunction) case " + name + " failed.");
|
||||
}
|
||||
|
||||
private void assertDoubleArrayEquals(double[] actual, double[] expected, double delta, String msg) {
|
||||
if (actual.length != expected.length) {
|
||||
fail(msg + ": length mismatch, expected " + expected.length + ", got " + actual.length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < actual.length; i++) {
|
||||
assertEquals(actual[i], expected[i], delta, msg + "(mismatch at index " + i + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("doubleTests")
|
||||
public void testSetAllDouble(String name, int size, IntToDoubleFunction generator, double[] expected) {
|
||||
double[] result = new double[size];
|
||||
Arrays.setAll(result, generator);
|
||||
assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new double[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringSetNulls() {
|
||||
String[] ar = new String[2];
|
||||
try {
|
||||
Arrays.setAll(null, (IntFunction<String>) i -> "X");
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, (IntFunction<String>) i -> "X");
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntSetNulls() {
|
||||
int[] ar = new int[2];
|
||||
try {
|
||||
Arrays.setAll(null, (IntUnaryOperator) i -> i);
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, (IntUnaryOperator) i -> i);
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongSetNulls() {
|
||||
long[] ar = new long[2];
|
||||
try {
|
||||
Arrays.setAll(null, (IntToLongFunction) i -> Long.MAX_VALUE);
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, (IntToLongFunction) i -> Long.MAX_VALUE);
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleSetNulls() {
|
||||
double[] ar = new double[2];
|
||||
try {
|
||||
Arrays.setAll(null, (IntToDoubleFunction) i -> Math.E);
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, (IntToDoubleFunction) i -> Math.E);
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
2017
test/jdk/java/util/Arrays/Sorting.java
Normal file
2017
test/jdk/java/util/Arrays/Sorting.java
Normal file
File diff suppressed because it is too large
Load diff
708
test/jdk/java/util/Arrays/SortingIntBenchmarkTestJMH.java
Normal file
708
test/jdk/java/util/Arrays/SortingIntBenchmarkTestJMH.java
Normal file
|
|
@ -0,0 +1,708 @@
|
|||
/*
|
||||
* Copyright 2015 Goldman Sachs.
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@State(Scope.Thread)
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public class SortingIntBenchmarkTestJMH {
|
||||
private static final int QUICKSORT_THRESHOLD = 286;
|
||||
private static final int MAX_RUN_COUNT = 67;
|
||||
private static final int INSERTION_SORT_THRESHOLD = 47;
|
||||
public static final int MAX_VALUE = 1_000_000;
|
||||
|
||||
@Param({"pairFlipZeroPairFlip", "pairFlipOneHundredPairFlip"
|
||||
, "zeroHi", "hiZeroLow", "hiFlatLow", "identical",
|
||||
"randomDups", "randomNoDups", "sortedReversedSorted", "pairFlip", "endLessThan"})
|
||||
|
||||
public String listType;
|
||||
|
||||
private int[] array;
|
||||
private static final int LIST_SIZE = 10_000_000;
|
||||
public static final int NUMBER_OF_ITERATIONS = 10;
|
||||
|
||||
@Setup
|
||||
public void setUp() {
|
||||
Random random = new Random(123456789012345L);
|
||||
this.array = new int[LIST_SIZE];
|
||||
int threeQuarters = (int) (LIST_SIZE * 0.75);
|
||||
if ("zeroHi".equals(this.listType)) {
|
||||
for (int i = 0; i < threeQuarters; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
int k = 1;
|
||||
for (int i = threeQuarters; i < LIST_SIZE; i++) {
|
||||
this.array[i] = k;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
else if ("hiFlatLow".equals(this.listType)) {
|
||||
int oneThird = LIST_SIZE / 3;
|
||||
for (int i = 0; i < oneThird; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
int twoThirds = oneThird * 2;
|
||||
int constant = oneThird - 1;
|
||||
for (int i = oneThird; i < twoThirds; i++) {
|
||||
this.array[i] = constant;
|
||||
}
|
||||
for (int i = twoThirds; i < LIST_SIZE; i++) {
|
||||
this.array[i] = constant - i + twoThirds;
|
||||
}
|
||||
}
|
||||
else if ("hiZeroLow".equals(this.listType)) {
|
||||
int oneThird = LIST_SIZE / 3;
|
||||
for (int i = 0; i < oneThird; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
int twoThirds = oneThird * 2;
|
||||
for (int i = oneThird; i < twoThirds; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
for (int i = twoThirds; i < LIST_SIZE; i++) {
|
||||
this.array[i] = oneThird - i + twoThirds;
|
||||
}
|
||||
}
|
||||
else if ("identical".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
}
|
||||
else if ("randomDups".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = random.nextInt(1000);
|
||||
}
|
||||
}
|
||||
else if ("randomNoDups".equals(this.listType)) {
|
||||
Set<Integer> set = new HashSet();
|
||||
while (set.size() < LIST_SIZE + 1) {
|
||||
set.add(random.nextInt());
|
||||
}
|
||||
List<Integer> list = new ArrayList<>(LIST_SIZE);
|
||||
list.addAll(set);
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = list.get(i);
|
||||
}
|
||||
}
|
||||
else if ("sortedReversedSorted".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE / 2; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = LIST_SIZE / 2; i < LIST_SIZE; i++) {
|
||||
this.array[i] = LIST_SIZE - num;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
else if ("pairFlip".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
for (int i = 0; i < LIST_SIZE; i += 2) {
|
||||
int temp = this.array[i];
|
||||
this.array[i] = this.array[i + 1];
|
||||
this.array[i + 1] = temp;
|
||||
}
|
||||
}
|
||||
else if ("endLessThan".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE - 1; i++) {
|
||||
this.array[i] = 3;
|
||||
}
|
||||
this.array[LIST_SIZE - 1] = 1;
|
||||
}
|
||||
else if ("pairFlipZeroPairFlip".equals(this.listType)) {
|
||||
//pairflip
|
||||
for (int i = 0; i < 64; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
for (int i = 0; i < 64; i += 2) {
|
||||
int temp = this.array[i];
|
||||
this.array[i] = this.array[i + 1];
|
||||
this.array[i + 1] = temp;
|
||||
}
|
||||
//zero
|
||||
for (int i = 64; i < this.array.length - 64; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
//pairflip
|
||||
for (int i = this.array.length - 64; i < this.array.length; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
for (int i = this.array.length - 64; i < this.array.length; i += 2) {
|
||||
int temp = this.array[i];
|
||||
this.array[i] = this.array[i + 1];
|
||||
this.array[i + 1] = temp;
|
||||
}
|
||||
}
|
||||
else if ("pairFlipOneHundredPairFlip".equals(this.listType)) {
|
||||
//10, 5
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (i % 2 == 0) {
|
||||
this.array[i] = 10;
|
||||
}
|
||||
else {
|
||||
this.array[i] = 5;
|
||||
}
|
||||
}
|
||||
|
||||
//100
|
||||
for (int i = 64; i < this.array.length - 64; i++) {
|
||||
this.array[i] = 100;
|
||||
}
|
||||
|
||||
//10, 5
|
||||
for (int i = this.array.length - 64; i < this.array.length; i++) {
|
||||
if (i % 2 == 0) {
|
||||
this.array[i] = 10;
|
||||
}
|
||||
else {
|
||||
this.array[i] = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 20)
|
||||
@Measurement(iterations = 10)
|
||||
@Benchmark
|
||||
public void sortNewWay() {
|
||||
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
|
||||
SortingIntTestJMH.sort(this.array, 0, this.array.length - 1, null, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 20)
|
||||
@Measurement(iterations = 10)
|
||||
@Benchmark
|
||||
public void sortCurrentWay() {
|
||||
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
|
||||
Arrays.sort(this.array);
|
||||
}
|
||||
}
|
||||
|
||||
static void sort(int[] a, int left, int right,
|
||||
int[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
SortingIntTestJMH.sort(a, left, right, true);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Index run[i] is the start of i-th run
|
||||
* (ascending or descending sequence).
|
||||
*/
|
||||
int[] run = new int[MAX_RUN_COUNT + 1];
|
||||
int count = 0;
|
||||
run[0] = left;
|
||||
|
||||
// Check if the array is nearly sorted
|
||||
for (int k = left; k < right; run[count] = k) {
|
||||
while (k < right && a[k] == a[k + 1])
|
||||
k++;
|
||||
if (k == right) break;
|
||||
if (a[k] < a[k + 1]) { // ascending
|
||||
while (++k <= right && a[k - 1] <= a[k]) ;
|
||||
}
|
||||
else if (a[k] > a[k + 1]) { // descending
|
||||
while (++k <= right && a[k - 1] >= a[k]) ;
|
||||
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
|
||||
int t = a[lo];
|
||||
a[lo] = a[hi];
|
||||
a[hi] = t;
|
||||
}
|
||||
}
|
||||
if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
|
||||
count--;
|
||||
}
|
||||
/*
|
||||
* The array is not highly structured,
|
||||
* use Quicksort instead of merge sort.
|
||||
*/
|
||||
if (++count == MAX_RUN_COUNT) {
|
||||
sort(a, left, right, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) {
|
||||
run[++count] = right;
|
||||
}
|
||||
if (count <= 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1) {
|
||||
}
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
int[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new int[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
}
|
||||
else {
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
for (int last; count > 1; count = last) {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
}
|
||||
else {
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i + bo] = a[i + ao]
|
||||
) {
|
||||
}
|
||||
run[++last] = right;
|
||||
}
|
||||
int[] t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
int o = ao;
|
||||
ao = bo;
|
||||
bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
private static void sort(int[] a, int left, int right, boolean leftmost) {
|
||||
int length = right - left + 1;
|
||||
|
||||
// Use insertion sort on tiny arrays
|
||||
if (length < INSERTION_SORT_THRESHOLD) {
|
||||
if (leftmost) {
|
||||
/*
|
||||
* Traditional (without sentinel) insertion sort,
|
||||
* optimized for server VM, is used in case of
|
||||
* the leftmost part.
|
||||
*/
|
||||
for (int i = left, j = i; i < right; j = ++i) {
|
||||
int ai = a[i + 1];
|
||||
while (ai < a[j]) {
|
||||
a[j + 1] = a[j];
|
||||
if (j-- == left) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
a[j + 1] = ai;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Skip the longest ascending sequence.
|
||||
*/
|
||||
do {
|
||||
if (left >= right) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (a[++left] >= a[left - 1]);
|
||||
|
||||
/*
|
||||
* Every element from adjoining part plays the role
|
||||
* of sentinel, therefore this allows us to avoid the
|
||||
* left range check on each iteration. Moreover, we use
|
||||
* the more optimized algorithm, so called pair insertion
|
||||
* sort, which is faster (in the context of Quicksort)
|
||||
* than traditional implementation of insertion sort.
|
||||
*/
|
||||
for (int k = left; ++left <= right; k = ++left) {
|
||||
int a1 = a[k], a2 = a[left];
|
||||
|
||||
if (a1 < a2) {
|
||||
a2 = a1;
|
||||
a1 = a[left];
|
||||
}
|
||||
while (a1 < a[--k]) {
|
||||
a[k + 2] = a[k];
|
||||
}
|
||||
a[++k + 1] = a1;
|
||||
|
||||
while (a2 < a[--k]) {
|
||||
a[k + 1] = a[k];
|
||||
}
|
||||
a[k + 1] = a2;
|
||||
}
|
||||
int last = a[right];
|
||||
|
||||
while (last < a[--right]) {
|
||||
a[right + 1] = a[right];
|
||||
}
|
||||
a[right + 1] = last;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Inexpensive approximation of length / 7
|
||||
int seventh = (length >> 3) + (length >> 6) + 1;
|
||||
|
||||
/*
|
||||
* Sort five evenly spaced elements around (and including) the
|
||||
* center element in the range. These elements will be used for
|
||||
* pivot selection as described below. The choice for spacing
|
||||
* these elements was empirically determined to work well on
|
||||
* a wide variety of inputs.
|
||||
*/
|
||||
int e3 = (left + right) >>> 1; // The midpoint
|
||||
int e2 = e3 - seventh;
|
||||
int e1 = e2 - seventh;
|
||||
int e4 = e3 + seventh;
|
||||
int e5 = e4 + seventh;
|
||||
|
||||
// Sort these elements using insertion sort
|
||||
if (a[e2] < a[e1]) {
|
||||
int t = a[e2];
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
|
||||
if (a[e3] < a[e2]) {
|
||||
int t = a[e3];
|
||||
a[e3] = a[e2];
|
||||
a[e2] = t;
|
||||
if (t < a[e1]) {
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
}
|
||||
if (a[e4] < a[e3]) {
|
||||
int t = a[e4];
|
||||
a[e4] = a[e3];
|
||||
a[e3] = t;
|
||||
if (t < a[e2]) {
|
||||
a[e3] = a[e2];
|
||||
a[e2] = t;
|
||||
if (t < a[e1]) {
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[e5] < a[e4]) {
|
||||
int t = a[e5];
|
||||
a[e5] = a[e4];
|
||||
a[e4] = t;
|
||||
if (t < a[e3]) {
|
||||
a[e4] = a[e3];
|
||||
a[e3] = t;
|
||||
if (t < a[e2]) {
|
||||
a[e3] = a[e2];
|
||||
a[e2] = t;
|
||||
if (t < a[e1]) {
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pointers
|
||||
int less = left; // The index of the first element of center part
|
||||
int great = right; // The index before the first element of right part
|
||||
|
||||
if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
|
||||
/*
|
||||
* Use the second and fourth of the five sorted elements as pivots.
|
||||
* These values are inexpensive approximations of the first and
|
||||
* second terciles of the array. Note that pivot1 <= pivot2.
|
||||
*/
|
||||
int pivot1 = a[e2];
|
||||
int pivot2 = a[e4];
|
||||
|
||||
/*
|
||||
* The first and the last elements to be sorted are moved to the
|
||||
* locations formerly occupied by the pivots. When partitioning
|
||||
* is complete, the pivots are swapped back into their final
|
||||
* positions, and excluded from subsequent sorting.
|
||||
*/
|
||||
a[e2] = a[left];
|
||||
a[e4] = a[right];
|
||||
|
||||
/*
|
||||
* Skip elements, which are less or greater than pivot values.
|
||||
*/
|
||||
while (a[++less] < pivot1) {
|
||||
}
|
||||
while (a[--great] > pivot2) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Partitioning:
|
||||
*
|
||||
* left part center part right part
|
||||
* +--------------------------------------------------------------+
|
||||
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
|
||||
* +--------------------------------------------------------------+
|
||||
* ^ ^ ^
|
||||
* | | |
|
||||
* less k great
|
||||
*
|
||||
* Invariants:
|
||||
*
|
||||
* all in (left, less) < pivot1
|
||||
* pivot1 <= all in [less, k) <= pivot2
|
||||
* all in (great, right) > pivot2
|
||||
*
|
||||
* Pointer k is the first index of ?-part.
|
||||
*/
|
||||
outer:
|
||||
for (int k = less - 1; ++k <= great; ) {
|
||||
int ak = a[k];
|
||||
if (ak < pivot1) { // Move a[k] to left part
|
||||
a[k] = a[less];
|
||||
/*
|
||||
* Here and below we use "a[i] = b; i++;" instead
|
||||
* of "a[i++] = b;" due to performance issue.
|
||||
*/
|
||||
a[less] = ak;
|
||||
++less;
|
||||
}
|
||||
else if (ak > pivot2) { // Move a[k] to right part
|
||||
while (a[great] > pivot2) {
|
||||
if (great-- == k) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
if (a[great] < pivot1) { // a[great] <= pivot2
|
||||
a[k] = a[less];
|
||||
a[less] = a[great];
|
||||
++less;
|
||||
}
|
||||
else { // pivot1 <= a[great] <= pivot2
|
||||
a[k] = a[great];
|
||||
}
|
||||
/*
|
||||
* Here and below we use "a[i] = b; i--;" instead
|
||||
* of "a[i--] = b;" due to performance issue.
|
||||
*/
|
||||
a[great] = ak;
|
||||
--great;
|
||||
}
|
||||
}
|
||||
|
||||
// Swap pivots into their final positions
|
||||
a[left] = a[less - 1];
|
||||
a[less - 1] = pivot1;
|
||||
a[right] = a[great + 1];
|
||||
a[great + 1] = pivot2;
|
||||
|
||||
// Sort left and right parts recursively, excluding known pivots
|
||||
SortingIntTestJMH.sort(a, left, less - 2, leftmost);
|
||||
SortingIntTestJMH.sort(a, great + 2, right, false);
|
||||
|
||||
/*
|
||||
* If center part is too large (comprises > 4/7 of the array),
|
||||
* swap internal pivot values to ends.
|
||||
*/
|
||||
if (less < e1 && e5 < great) {
|
||||
/*
|
||||
* Skip elements, which are equal to pivot values.
|
||||
*/
|
||||
while (a[less] == pivot1) {
|
||||
++less;
|
||||
}
|
||||
|
||||
while (a[great] == pivot2) {
|
||||
--great;
|
||||
}
|
||||
|
||||
/*
|
||||
* Partitioning:
|
||||
*
|
||||
* left part center part right part
|
||||
* +----------------------------------------------------------+
|
||||
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
|
||||
* +----------------------------------------------------------+
|
||||
* ^ ^ ^
|
||||
* | | |
|
||||
* less k great
|
||||
*
|
||||
* Invariants:
|
||||
*
|
||||
* all in (*, less) == pivot1
|
||||
* pivot1 < all in [less, k) < pivot2
|
||||
* all in (great, *) == pivot2
|
||||
*
|
||||
* Pointer k is the first index of ?-part.
|
||||
*/
|
||||
outer:
|
||||
for (int k = less - 1; ++k <= great; ) {
|
||||
int ak = a[k];
|
||||
if (ak == pivot1) { // Move a[k] to left part
|
||||
a[k] = a[less];
|
||||
a[less] = ak;
|
||||
++less;
|
||||
}
|
||||
else if (ak == pivot2) { // Move a[k] to right part
|
||||
while (a[great] == pivot2) {
|
||||
if (great-- == k) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
if (a[great] == pivot1) { // a[great] < pivot2
|
||||
a[k] = a[less];
|
||||
/*
|
||||
* Even though a[great] equals to pivot1, the
|
||||
* assignment a[less] = pivot1 may be incorrect,
|
||||
* if a[great] and pivot1 are floating-point zeros
|
||||
* of different signs. Therefore in float and
|
||||
* double sorting methods we have to use more
|
||||
* accurate assignment a[less] = a[great].
|
||||
*/
|
||||
a[less] = pivot1;
|
||||
++less;
|
||||
}
|
||||
else { // pivot1 < a[great] < pivot2
|
||||
a[k] = a[great];
|
||||
}
|
||||
a[great] = ak;
|
||||
--great;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort center part recursively
|
||||
SortingIntTestJMH.sort(a, less, great, false);
|
||||
}
|
||||
else { // Partitioning with one pivot
|
||||
/*
|
||||
* Use the third of the five sorted elements as pivot.
|
||||
* This value is inexpensive approximation of the median.
|
||||
*/
|
||||
int pivot = a[e3];
|
||||
|
||||
/*
|
||||
* Partitioning degenerates to the traditional 3-way
|
||||
* (or "Dutch National Flag") schema:
|
||||
*
|
||||
* left part center part right part
|
||||
* +-------------------------------------------------+
|
||||
* | < pivot | == pivot | ? | > pivot |
|
||||
* +-------------------------------------------------+
|
||||
* ^ ^ ^
|
||||
* | | |
|
||||
* less k great
|
||||
*
|
||||
* Invariants:
|
||||
*
|
||||
* all in (left, less) < pivot
|
||||
* all in [less, k) == pivot
|
||||
* all in (great, right) > pivot
|
||||
*
|
||||
* Pointer k is the first index of ?-part.
|
||||
*/
|
||||
for (int k = less; k <= great; ++k) {
|
||||
if (a[k] == pivot) {
|
||||
continue;
|
||||
}
|
||||
int ak = a[k];
|
||||
if (ak < pivot) { // Move a[k] to left part
|
||||
a[k] = a[less];
|
||||
a[less] = ak;
|
||||
++less;
|
||||
}
|
||||
else { // a[k] > pivot - Move a[k] to right part
|
||||
while (a[great] > pivot) {
|
||||
--great;
|
||||
}
|
||||
if (a[great] < pivot) { // a[great] <= pivot
|
||||
a[k] = a[less];
|
||||
a[less] = a[great];
|
||||
++less;
|
||||
}
|
||||
else { // a[great] == pivot
|
||||
/*
|
||||
* Even though a[great] equals to pivot, the
|
||||
* assignment a[k] = pivot may be incorrect,
|
||||
* if a[great] and pivot are floating-point
|
||||
* zeros of different signs. Therefore in float
|
||||
* and double sorting methods we have to use
|
||||
* more accurate assignment a[k] = a[great].
|
||||
*/
|
||||
a[k] = pivot;
|
||||
}
|
||||
a[great] = ak;
|
||||
--great;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort left and right parts recursively.
|
||||
* All elements from center part are equal
|
||||
* and, therefore, already sorted.
|
||||
*/
|
||||
SortingIntTestJMH.sort(a, left, less - 1, leftmost);
|
||||
SortingIntTestJMH.sort(a, great + 1, right, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void swap(int[] arr, int i, int j) {
|
||||
int tmp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
arr[j] = tmp;
|
||||
}
|
||||
}
|
||||
725
test/jdk/java/util/Arrays/SortingLongBenchmarkTestJMH.java
Normal file
725
test/jdk/java/util/Arrays/SortingLongBenchmarkTestJMH.java
Normal file
|
|
@ -0,0 +1,725 @@
|
|||
/*
|
||||
* Copyright 2015 Goldman Sachs.
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@State(Scope.Thread)
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public class SortingLongBenchmarkTestJMH {
|
||||
private static final int QUICKSORT_THRESHOLD = 286;
|
||||
private static final int MAX_RUN_COUNT = 67;
|
||||
private static final int INSERTION_SORT_THRESHOLD = 47;
|
||||
public static final int MAX_VALUE = 1_000_000;
|
||||
|
||||
@Param({"pairFlipZeroPairFlip", "descendingAscending", "zeroHi", "hiZeroLow", "hiFlatLow", "identical",
|
||||
"randomDups", "randomNoDups", "sortedReversedSorted", "pairFlip", "endLessThan"})
|
||||
public String listType;
|
||||
|
||||
private long[] array;
|
||||
private static final int LIST_SIZE = 10_000_000;
|
||||
public static final int NUMBER_OF_ITERATIONS = 10;
|
||||
|
||||
@Setup
|
||||
public void setUp() {
|
||||
Random random = new Random(123456789012345L);
|
||||
this.array = new long[LIST_SIZE];
|
||||
int threeQuarters = (int) (LIST_SIZE * 0.75);
|
||||
if ("zeroHi".equals(this.listType)) {
|
||||
for (int i = 0; i < threeQuarters; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
int k = 1;
|
||||
for (int i = threeQuarters; i < LIST_SIZE; i++) {
|
||||
this.array[i] = k;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
else if ("hiFlatLow".equals(this.listType)) {
|
||||
int oneThird = LIST_SIZE / 3;
|
||||
for (int i = 0; i < oneThird; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
int twoThirds = oneThird * 2;
|
||||
int constant = oneThird - 1;
|
||||
for (int i = oneThird; i < twoThirds; i++) {
|
||||
this.array[i] = constant;
|
||||
}
|
||||
for (int i = twoThirds; i < LIST_SIZE; i++) {
|
||||
this.array[i] = constant - i + twoThirds;
|
||||
}
|
||||
}
|
||||
else if ("hiZeroLow".equals(this.listType)) {
|
||||
int oneThird = LIST_SIZE / 3;
|
||||
for (int i = 0; i < oneThird; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
int twoThirds = oneThird * 2;
|
||||
for (int i = oneThird; i < twoThirds; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
for (int i = twoThirds; i < LIST_SIZE; i++) {
|
||||
this.array[i] = oneThird - i + twoThirds;
|
||||
}
|
||||
}
|
||||
else if ("identical".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
}
|
||||
else if ("randomDups".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = random.nextInt(1000);
|
||||
}
|
||||
}
|
||||
else if ("randomNoDups".equals(this.listType)) {
|
||||
Set<Integer> set = new HashSet<>();
|
||||
while (set.size() < LIST_SIZE + 1) {
|
||||
set.add(random.nextInt());
|
||||
}
|
||||
List<Integer> list = new ArrayList<>(LIST_SIZE);
|
||||
list.addAll(set);
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = list.get(i);
|
||||
}
|
||||
}
|
||||
else if ("sortedReversedSorted".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE / 2; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = LIST_SIZE / 2; i < LIST_SIZE; i++) {
|
||||
this.array[i] = LIST_SIZE - num;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
else if ("pairFlip".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
for (int i = 0; i < LIST_SIZE; i += 2) {
|
||||
long temp = this.array[i];
|
||||
this.array[i] = this.array[i + 1];
|
||||
this.array[i + 1] = temp;
|
||||
}
|
||||
}
|
||||
else if ("endLessThan".equals(this.listType)) {
|
||||
for (int i = 0; i < LIST_SIZE - 1; i++) {
|
||||
this.array[i] = 3;
|
||||
}
|
||||
this.array[LIST_SIZE - 1] = 1;
|
||||
}
|
||||
else if ("pairFlipZeroPairFlip".equals(this.listType)) {
|
||||
//pairflip
|
||||
for (int i = 0; i < 64; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
for (int i = 0; i < 64; i += 2) {
|
||||
long temp = this.array[i];
|
||||
this.array[i] = this.array[i + 1];
|
||||
this.array[i + 1] = temp;
|
||||
}
|
||||
//zero
|
||||
for (int i = 64; i < this.array.length - 64; i++) {
|
||||
this.array[i] = 0;
|
||||
}
|
||||
//pairflip
|
||||
for (int i = this.array.length - 64; i < this.array.length; i++) {
|
||||
this.array[i] = i;
|
||||
}
|
||||
for (int i = this.array.length - 64; i < this.array.length; i += 2) {
|
||||
long temp = this.array[i];
|
||||
this.array[i] = this.array[i + 1];
|
||||
this.array[i + 1] = temp;
|
||||
}
|
||||
}
|
||||
else if ("pairFlipOneHundredPairFlip".equals(this.listType)) {
|
||||
//10, 5
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (i % 2 == 0) {
|
||||
this.array[i] = 10;
|
||||
}
|
||||
else {
|
||||
this.array[i] = 5;
|
||||
}
|
||||
}
|
||||
|
||||
//100
|
||||
for (int i = 64; i < this.array.length - 64; i++) {
|
||||
this.array[i] = 100;
|
||||
}
|
||||
|
||||
//10, 5
|
||||
for (int i = this.array.length - 64; i < this.array.length; i++) {
|
||||
if (i % 2 == 0) {
|
||||
this.array[i] = 10;
|
||||
}
|
||||
else {
|
||||
this.array[i] = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 20)
|
||||
@Measurement(iterations = 10)
|
||||
@Benchmark
|
||||
public void sortNewWay() {
|
||||
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
|
||||
SortingLongTestJMH.sort(this.array, 0, this.array.length - 1, null, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 20)
|
||||
@Measurement(iterations = 10)
|
||||
@Benchmark
|
||||
public void sortOldWay() {
|
||||
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
|
||||
Arrays.sort(this.array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array using the given
|
||||
* workspace array slice if possible for merging
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
static void sort(long[] a, int left, int right,
|
||||
long[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
SortingLongTestJMH.sort(a, left, right, true);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Index run[i] is the start of i-th run
|
||||
* (ascending or descending sequence).
|
||||
*/
|
||||
int[] run = new int[MAX_RUN_COUNT + 1];
|
||||
int count = 0;
|
||||
run[0] = left;
|
||||
|
||||
// Check if the array is nearly sorted
|
||||
for (int k = left; k < right; run[count] = k) {
|
||||
while (k < right && a[k] == a[k + 1])
|
||||
k++;
|
||||
if (k == right) break;
|
||||
if (a[k] < a[k + 1]) { // ascending
|
||||
while (++k <= right && a[k - 1] <= a[k]) ;
|
||||
}
|
||||
else if (a[k] > a[k + 1]) { // descending
|
||||
while (++k <= right && a[k - 1] >= a[k]) ;
|
||||
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
|
||||
long t = a[lo];
|
||||
a[lo] = a[hi];
|
||||
a[hi] = t;
|
||||
}
|
||||
}
|
||||
if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
|
||||
count--;
|
||||
}
|
||||
/*
|
||||
* The array is not highly structured,
|
||||
* use Quicksort instead of merge sort.
|
||||
*/
|
||||
if (++count == MAX_RUN_COUNT) {
|
||||
sort(a, left, right, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) {
|
||||
run[++count] = right;
|
||||
}
|
||||
if (count <= 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1) {
|
||||
}
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
long[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new long[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
}
|
||||
else {
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
for (int last; count > 1; count = last) {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
}
|
||||
else {
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i + bo] = a[i + ao]
|
||||
) {
|
||||
}
|
||||
run[++last] = right;
|
||||
}
|
||||
long[] t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
int o = ao;
|
||||
ao = bo;
|
||||
bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array by Dual-Pivot Quicksort.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param leftmost indicates if this part is the leftmost in the range
|
||||
*/
|
||||
private static void sort(long[] a, int left, int right, boolean leftmost) {
|
||||
int length = right - left + 1;
|
||||
|
||||
// Use insertion sort on tiny arrays
|
||||
if (length < INSERTION_SORT_THRESHOLD) {
|
||||
if (leftmost) {
|
||||
/*
|
||||
* Traditional (without sentinel) insertion sort,
|
||||
* optimized for server VM, is used in case of
|
||||
* the leftmost part.
|
||||
*/
|
||||
for (int i = left, j = i; i < right; j = ++i) {
|
||||
long ai = a[i + 1];
|
||||
while (ai < a[j]) {
|
||||
a[j + 1] = a[j];
|
||||
if (j-- == left) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
a[j + 1] = ai;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Skip the longest ascending sequence.
|
||||
*/
|
||||
do {
|
||||
if (left >= right) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (a[++left] >= a[left - 1]);
|
||||
|
||||
/*
|
||||
* Every element from adjoining part plays the role
|
||||
* of sentinel, therefore this allows us to avoid the
|
||||
* left range check on each iteration. Moreover, we use
|
||||
* the more optimized algorithm, so called pair insertion
|
||||
* sort, which is faster (in the context of Quicksort)
|
||||
* than traditional implementation of insertion sort.
|
||||
*/
|
||||
for (int k = left; ++left <= right; k = ++left) {
|
||||
long a1 = a[k], a2 = a[left];
|
||||
|
||||
if (a1 < a2) {
|
||||
a2 = a1;
|
||||
a1 = a[left];
|
||||
}
|
||||
while (a1 < a[--k]) {
|
||||
a[k + 2] = a[k];
|
||||
}
|
||||
a[++k + 1] = a1;
|
||||
|
||||
while (a2 < a[--k]) {
|
||||
a[k + 1] = a[k];
|
||||
}
|
||||
a[k + 1] = a2;
|
||||
}
|
||||
long last = a[right];
|
||||
|
||||
while (last < a[--right]) {
|
||||
a[right + 1] = a[right];
|
||||
}
|
||||
a[right + 1] = last;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Inexpensive approximation of length / 7
|
||||
int seventh = (length >> 3) + (length >> 6) + 1;
|
||||
|
||||
/*
|
||||
* Sort five evenly spaced elements around (and including) the
|
||||
* center element in the range. These elements will be used for
|
||||
* pivot selection as described below. The choice for spacing
|
||||
* these elements was empirically determined to work well on
|
||||
* a wide variety of inputs.
|
||||
*/
|
||||
int e3 = (left + right) >>> 1; // The midpoint
|
||||
int e2 = e3 - seventh;
|
||||
int e1 = e2 - seventh;
|
||||
int e4 = e3 + seventh;
|
||||
int e5 = e4 + seventh;
|
||||
|
||||
// Sort these elements using insertion sort
|
||||
if (a[e2] < a[e1]) {
|
||||
long t = a[e2];
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
|
||||
if (a[e3] < a[e2]) {
|
||||
long t = a[e3];
|
||||
a[e3] = a[e2];
|
||||
a[e2] = t;
|
||||
if (t < a[e1]) {
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
}
|
||||
if (a[e4] < a[e3]) {
|
||||
long t = a[e4];
|
||||
a[e4] = a[e3];
|
||||
a[e3] = t;
|
||||
if (t < a[e2]) {
|
||||
a[e3] = a[e2];
|
||||
a[e2] = t;
|
||||
if (t < a[e1]) {
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[e5] < a[e4]) {
|
||||
long t = a[e5];
|
||||
a[e5] = a[e4];
|
||||
a[e4] = t;
|
||||
if (t < a[e3]) {
|
||||
a[e4] = a[e3];
|
||||
a[e3] = t;
|
||||
if (t < a[e2]) {
|
||||
a[e3] = a[e2];
|
||||
a[e2] = t;
|
||||
if (t < a[e1]) {
|
||||
a[e2] = a[e1];
|
||||
a[e1] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pointers
|
||||
int less = left; // The index of the first element of center part
|
||||
int great = right; // The index before the first element of right part
|
||||
|
||||
if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
|
||||
/*
|
||||
* Use the second and fourth of the five sorted elements as pivots.
|
||||
* These values are inexpensive approximations of the first and
|
||||
* second terciles of the array. Note that pivot1 <= pivot2.
|
||||
*/
|
||||
long pivot1 = a[e2];
|
||||
long pivot2 = a[e4];
|
||||
|
||||
/*
|
||||
* The first and the last elements to be sorted are moved to the
|
||||
* locations formerly occupied by the pivots. When partitioning
|
||||
* is complete, the pivots are swapped back into their final
|
||||
* positions, and excluded from subsequent sorting.
|
||||
*/
|
||||
a[e2] = a[left];
|
||||
a[e4] = a[right];
|
||||
|
||||
/*
|
||||
* Skip elements, which are less or greater than pivot values.
|
||||
*/
|
||||
while (a[++less] < pivot1) {
|
||||
}
|
||||
while (a[--great] > pivot2) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Partitioning:
|
||||
*
|
||||
* left part center part right part
|
||||
* +--------------------------------------------------------------+
|
||||
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
|
||||
* +--------------------------------------------------------------+
|
||||
* ^ ^ ^
|
||||
* | | |
|
||||
* less k great
|
||||
*
|
||||
* Invariants:
|
||||
*
|
||||
* all in (left, less) < pivot1
|
||||
* pivot1 <= all in [less, k) <= pivot2
|
||||
* all in (great, right) > pivot2
|
||||
*
|
||||
* Pointer k is the first index of ?-part.
|
||||
*/
|
||||
outer:
|
||||
for (int k = less - 1; ++k <= great; ) {
|
||||
long ak = a[k];
|
||||
if (ak < pivot1) { // Move a[k] to left part
|
||||
a[k] = a[less];
|
||||
/*
|
||||
* Here and below we use "a[i] = b; i++;" instead
|
||||
* of "a[i++] = b;" due to performance issue.
|
||||
*/
|
||||
a[less] = ak;
|
||||
++less;
|
||||
}
|
||||
else if (ak > pivot2) { // Move a[k] to right part
|
||||
while (a[great] > pivot2) {
|
||||
if (great-- == k) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
if (a[great] < pivot1) { // a[great] <= pivot2
|
||||
a[k] = a[less];
|
||||
a[less] = a[great];
|
||||
++less;
|
||||
}
|
||||
else { // pivot1 <= a[great] <= pivot2
|
||||
a[k] = a[great];
|
||||
}
|
||||
/*
|
||||
* Here and below we use "a[i] = b; i--;" instead
|
||||
* of "a[i--] = b;" due to performance issue.
|
||||
*/
|
||||
a[great] = ak;
|
||||
--great;
|
||||
}
|
||||
}
|
||||
|
||||
// Swap pivots into their final positions
|
||||
a[left] = a[less - 1];
|
||||
a[less - 1] = pivot1;
|
||||
a[right] = a[great + 1];
|
||||
a[great + 1] = pivot2;
|
||||
|
||||
// Sort left and right parts recursively, excluding known pivots
|
||||
SortingLongTestJMH.sort(a, left, less - 2, leftmost);
|
||||
SortingLongTestJMH.sort(a, great + 2, right, false);
|
||||
|
||||
/*
|
||||
* If center part is too large (comprises > 4/7 of the array),
|
||||
* swap internal pivot values to ends.
|
||||
*/
|
||||
if (less < e1 && e5 < great) {
|
||||
/*
|
||||
* Skip elements, which are equal to pivot values.
|
||||
*/
|
||||
while (a[less] == pivot1) {
|
||||
++less;
|
||||
}
|
||||
|
||||
while (a[great] == pivot2) {
|
||||
--great;
|
||||
}
|
||||
|
||||
/*
|
||||
* Partitioning:
|
||||
*
|
||||
* left part center part right part
|
||||
* +----------------------------------------------------------+
|
||||
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
|
||||
* +----------------------------------------------------------+
|
||||
* ^ ^ ^
|
||||
* | | |
|
||||
* less k great
|
||||
*
|
||||
* Invariants:
|
||||
*
|
||||
* all in (*, less) == pivot1
|
||||
* pivot1 < all in [less, k) < pivot2
|
||||
* all in (great, *) == pivot2
|
||||
*
|
||||
* Pointer k is the first index of ?-part.
|
||||
*/
|
||||
outer:
|
||||
for (int k = less - 1; ++k <= great; ) {
|
||||
long ak = a[k];
|
||||
if (ak == pivot1) { // Move a[k] to left part
|
||||
a[k] = a[less];
|
||||
a[less] = ak;
|
||||
++less;
|
||||
}
|
||||
else if (ak == pivot2) { // Move a[k] to right part
|
||||
while (a[great] == pivot2) {
|
||||
if (great-- == k) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
if (a[great] == pivot1) { // a[great] < pivot2
|
||||
a[k] = a[less];
|
||||
/*
|
||||
* Even though a[great] equals to pivot1, the
|
||||
* assignment a[less] = pivot1 may be incorrect,
|
||||
* if a[great] and pivot1 are floating-point zeros
|
||||
* of different signs. Therefore in float and
|
||||
* double sorting methods we have to use more
|
||||
* accurate assignment a[less] = a[great].
|
||||
*/
|
||||
a[less] = pivot1;
|
||||
++less;
|
||||
}
|
||||
else { // pivot1 < a[great] < pivot2
|
||||
a[k] = a[great];
|
||||
}
|
||||
a[great] = ak;
|
||||
--great;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort center part recursively
|
||||
SortingLongTestJMH.sort(a, less, great, false);
|
||||
}
|
||||
else { // Partitioning with one pivot
|
||||
/*
|
||||
* Use the third of the five sorted elements as pivot.
|
||||
* This value is inexpensive approximation of the median.
|
||||
*/
|
||||
long pivot = a[e3];
|
||||
|
||||
/*
|
||||
* Partitioning degenerates to the traditional 3-way
|
||||
* (or "Dutch National Flag") schema:
|
||||
*
|
||||
* left part center part right part
|
||||
* +-------------------------------------------------+
|
||||
* | < pivot | == pivot | ? | > pivot |
|
||||
* +-------------------------------------------------+
|
||||
* ^ ^ ^
|
||||
* | | |
|
||||
* less k great
|
||||
*
|
||||
* Invariants:
|
||||
*
|
||||
* all in (left, less) < pivot
|
||||
* all in [less, k) == pivot
|
||||
* all in (great, right) > pivot
|
||||
*
|
||||
* Pointer k is the first index of ?-part.
|
||||
*/
|
||||
for (int k = less; k <= great; ++k) {
|
||||
if (a[k] == pivot) {
|
||||
continue;
|
||||
}
|
||||
long ak = a[k];
|
||||
if (ak < pivot) { // Move a[k] to left part
|
||||
a[k] = a[less];
|
||||
a[less] = ak;
|
||||
++less;
|
||||
}
|
||||
else { // a[k] > pivot - Move a[k] to right part
|
||||
while (a[great] > pivot) {
|
||||
--great;
|
||||
}
|
||||
if (a[great] < pivot) { // a[great] <= pivot
|
||||
a[k] = a[less];
|
||||
a[less] = a[great];
|
||||
++less;
|
||||
}
|
||||
else { // a[great] == pivot
|
||||
/*
|
||||
* Even though a[great] equals to pivot, the
|
||||
* assignment a[k] = pivot may be incorrect,
|
||||
* if a[great] and pivot are floating-point
|
||||
* zeros of different signs. Therefore in float
|
||||
* and double sorting methods we have to use
|
||||
* more accurate assignment a[k] = a[great].
|
||||
*/
|
||||
a[k] = pivot;
|
||||
}
|
||||
a[great] = ak;
|
||||
--great;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort left and right parts recursively.
|
||||
* All elements from center part are equal
|
||||
* and, therefore, already sorted.
|
||||
*/
|
||||
SortingLongTestJMH.sort(a, left, less - 1, leftmost);
|
||||
SortingLongTestJMH.sort(a, great + 1, right, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void swap(long[] arr, int i, int j) {
|
||||
long tmp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
arr[j] = tmp;
|
||||
}
|
||||
}
|
||||
358
test/jdk/java/util/Arrays/SortingNearlySortedPrimitive.java
Normal file
358
test/jdk/java/util/Arrays/SortingNearlySortedPrimitive.java
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Copyright 2015 Goldman Sachs.
|
||||
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8154049
|
||||
* @summary Tests the sorting of a large array of sorted primitive values,
|
||||
* predominently for cases where the array is nearly sorted. This tests
|
||||
* code that detects patterns in the array to determine if it is nearly
|
||||
* sorted and if so employs and optimizes merge sort rather than a
|
||||
* Dual-Pivot QuickSort.
|
||||
*
|
||||
* @run junit SortingNearlySortedPrimitive
|
||||
*/
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class SortingNearlySortedPrimitive {
|
||||
|
||||
static final int BASE = 3;
|
||||
static final int WIDTH = 4;
|
||||
// Should be > DualPivotQuicksort.QUICKSORT_THRESHOLD
|
||||
static final int PAD = 300;
|
||||
|
||||
Stream<int[]> createCombinations() {
|
||||
// Create all combinations for the BASE value and double the WIDTH
|
||||
// elements
|
||||
// This is create various combinations of ascending, descending and
|
||||
// equal runs to exercise the nearly sorted code paths
|
||||
return IntStream.range(0, (int) Math.pow(BASE, 2 * WIDTH)).
|
||||
mapToObj(this::createArray);
|
||||
}
|
||||
|
||||
// Create an array which at either end is filled with -ve and +ve elements
|
||||
// according to the base value and padded with zeros in between
|
||||
int[] createArray(int v) {
|
||||
int[] a = new int[WIDTH + PAD + WIDTH];
|
||||
|
||||
// Fill head of array
|
||||
for (int j = 0; j < WIDTH; j++) {
|
||||
a[j] = (v % BASE) - (BASE / 2);
|
||||
v /= BASE;
|
||||
}
|
||||
// Fill tail of array
|
||||
for (int j = 0; j < WIDTH; j++) {
|
||||
a[WIDTH + PAD + j] = (v % BASE) - (BASE / 2);
|
||||
v /= BASE;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCombination() {
|
||||
createCombinations().forEach(a -> {
|
||||
try {
|
||||
// Clone source array to ensure it is not modified
|
||||
this.sortAndAssert(a.clone());
|
||||
this.sortAndAssert(floatCopyFromInt(a));
|
||||
this.sortAndAssert(doubleCopyFromInt(a));
|
||||
this.sortAndAssert(longCopyFromInt(a));
|
||||
this.sortAndAssert(shortCopyFromInt(a));
|
||||
this.sortAndAssert(charCopyFromInt(a));
|
||||
} catch (AssertionError sae) {
|
||||
AssertionError ae = new AssertionError("Sort failed for " + arrayToString(a));
|
||||
ae.addSuppressed(sae);
|
||||
throw ae;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String arrayToString(int[] a) {
|
||||
int[] l = Arrays.copyOfRange(a, 0, WIDTH + 2);
|
||||
int[] r = Arrays.copyOfRange(a, a.length - (WIDTH + 2), a.length);
|
||||
StringJoiner sj = new StringJoiner(",", "[", "]");
|
||||
for (int i : l) {
|
||||
sj.add(Integer.toString(i));
|
||||
}
|
||||
sj.add("...");
|
||||
for (int i : r) {
|
||||
sj.add(Integer.toString(i));
|
||||
}
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
|
||||
public Object[][] createShapes() {
|
||||
Stream<List<Object>> baseCases = Stream.of(
|
||||
List.of("hiZeroLowTest", (IntFunction<int[]>) this::hiZeroLowData),
|
||||
List.of("endLessThanTest", (IntFunction<int[]>) this::endLessThanData),
|
||||
List.of("highFlatLowTest", (IntFunction<int[]>) this::highFlatLowData),
|
||||
List.of("identicalTest", (IntFunction<int[]>) this::identicalData),
|
||||
List.of("sortedReversedSortedTest", (IntFunction<int[]>) this::sortedReversedSortedData),
|
||||
List.of("pairFlipTest", (IntFunction<int[]>) this::pairFlipData),
|
||||
List.of("zeroHiTest", (IntFunction<int[]>) this::zeroHiData)
|
||||
);
|
||||
|
||||
// Ensure the following inequality holds for certain sizes
|
||||
// DualPivotQuicksort.QUICKSORT_THRESHOLD <= size - 1
|
||||
// < DualPivotQuicksort.COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
|
||||
// This guarantees that code paths are taken for checking nearly sorted
|
||||
// arrays for all primitive types
|
||||
List<Integer> sizes = List.of(100, 1_000, 10_000, 1_000_000);
|
||||
return baseCases.
|
||||
flatMap(l -> sizes.stream().map(s -> append(l, s))).
|
||||
toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
Object[] append(List<Object> l, Object value) {
|
||||
List<Object> nl = new ArrayList<>(l);
|
||||
nl.add(value);
|
||||
return nl.toArray();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("createShapes")
|
||||
public void testShapes(String testName, IntFunction<int[]> dataMethod, int size) {
|
||||
int[] intSourceArray = dataMethod.apply(size);
|
||||
|
||||
// Clone source array to ensure it is not modified
|
||||
this.sortAndAssert(intSourceArray.clone());
|
||||
this.sortAndAssert(floatCopyFromInt(intSourceArray));
|
||||
this.sortAndAssert(doubleCopyFromInt(intSourceArray));
|
||||
this.sortAndAssert(longCopyFromInt(intSourceArray));
|
||||
this.sortAndAssert(shortCopyFromInt(intSourceArray));
|
||||
this.sortAndAssert(charCopyFromInt(intSourceArray));
|
||||
}
|
||||
|
||||
private float[] floatCopyFromInt(int[] src) {
|
||||
float[] result = new float[src.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = src[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private double[] doubleCopyFromInt(int[] src) {
|
||||
double[] result = new double[src.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = src[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private long[] longCopyFromInt(int[] src) {
|
||||
long[] result = new long[src.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = src[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private short[] shortCopyFromInt(int[] src) {
|
||||
short[] result = new short[src.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = (short) src[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private char[] charCopyFromInt(int[] src) {
|
||||
char[] result = new char[src.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = (char) src[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void sortAndAssert(int[] array) {
|
||||
Arrays.sort(array);
|
||||
for (int i = 1; i < array.length; i++) {
|
||||
if (array[i] < array[i - 1]) {
|
||||
throw new AssertionError("not sorted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sortAndAssert(char[] array) {
|
||||
Arrays.sort(array);
|
||||
for (int i = 1; i < array.length; i++) {
|
||||
if (array[i] < array[i - 1]) {
|
||||
throw new AssertionError("not sorted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sortAndAssert(short[] array) {
|
||||
Arrays.sort(array);
|
||||
for (int i = 1; i < array.length; i++) {
|
||||
if (array[i] < array[i - 1]) {
|
||||
throw new AssertionError("not sorted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sortAndAssert(double[] array) {
|
||||
Arrays.sort(array);
|
||||
for (int i = 1; i < array.length; i++) {
|
||||
if (array[i] < array[i - 1]) {
|
||||
throw new AssertionError("not sorted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sortAndAssert(float[] array) {
|
||||
Arrays.sort(array);
|
||||
for (int i = 1; i < array.length; i++) {
|
||||
if (array[i] < array[i - 1]) {
|
||||
throw new AssertionError("not sorted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sortAndAssert(long[] array) {
|
||||
Arrays.sort(array);
|
||||
for (int i = 1; i < array.length; i++) {
|
||||
if (array[i] < array[i - 1]) {
|
||||
throw new AssertionError("not sorted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int[] zeroHiData(int size) {
|
||||
int[] array = new int[size];
|
||||
|
||||
int threeQuarters = (int) (size * 0.75);
|
||||
for (int i = 0; i < threeQuarters; i++) {
|
||||
array[i] = 0;
|
||||
}
|
||||
int k = 1;
|
||||
for (int i = threeQuarters; i < size; i++) {
|
||||
array[i] = k;
|
||||
k++;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private int[] hiZeroLowData(int size) {
|
||||
int[] array = new int[size];
|
||||
|
||||
int oneThird = size / 3;
|
||||
for (int i = 0; i < oneThird; i++) {
|
||||
array[i] = i;
|
||||
}
|
||||
int twoThirds = oneThird * 2;
|
||||
for (int i = oneThird; i < twoThirds; i++) {
|
||||
array[i] = 0;
|
||||
}
|
||||
for (int i = twoThirds; i < size; i++) {
|
||||
array[i] = oneThird - i + twoThirds;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private int[] highFlatLowData(int size) {
|
||||
int[] array = new int[size];
|
||||
|
||||
int oneThird = size / 3;
|
||||
for (int i = 0; i < oneThird; i++) {
|
||||
array[i] = i;
|
||||
}
|
||||
int twoThirds = oneThird * 2;
|
||||
int constant = oneThird - 1;
|
||||
for (int i = oneThird; i < twoThirds; i++) {
|
||||
array[i] = constant;
|
||||
}
|
||||
for (int i = twoThirds; i < size; i++) {
|
||||
array[i] = constant - i + twoThirds;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private int[] identicalData(int size) {
|
||||
int[] array = new int[size];
|
||||
int listNumber = 24;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
array[i] = listNumber;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private int[] endLessThanData(int size) {
|
||||
int[] array = new int[size];
|
||||
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
array[i] = 3;
|
||||
}
|
||||
array[size - 1] = 1;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private int[] sortedReversedSortedData(int size) {
|
||||
int[] array = new int[size];
|
||||
|
||||
for (int i = 0; i < size / 2; i++) {
|
||||
array[i] = i;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = size / 2; i < size; i++) {
|
||||
array[i] = size - num;
|
||||
num++;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private int[] pairFlipData(int size) {
|
||||
int[] array = new int[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
array[i] = i;
|
||||
}
|
||||
for (int i = 0; i < size; i += 2) {
|
||||
int temp = array[i];
|
||||
array[i] = array[i + 1];
|
||||
array[i + 1] = temp;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
136
test/jdk/java/util/Arrays/StreamAndSpliterator.java
Normal file
136
test/jdk/java/util/Arrays/StreamAndSpliterator.java
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8037857
|
||||
* @summary tests for stream and spliterator factory methods
|
||||
* @run junit StreamAndSpliterator
|
||||
*/
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Spliterators;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
|
||||
public class StreamAndSpliterator {
|
||||
@Test
|
||||
public void testStreamNPEs() {
|
||||
assertThrowsNPE(() -> Arrays.stream((int[]) null, 0, 0));
|
||||
assertThrowsNPE(() -> Arrays.stream((long[]) null, 0, 0));
|
||||
assertThrowsNPE(() -> Arrays.stream((double[]) null, 0, 0));
|
||||
assertThrowsNPE(() -> Arrays.stream((String[]) null, 0, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStreamAIOBEs() {
|
||||
// origin > fence
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 1, 0));
|
||||
|
||||
// bad origin
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, -1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, -1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, -1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, -1, 0));
|
||||
|
||||
// bad fence
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 0, 1));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 0, 1));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 0, 1));
|
||||
assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 0, 1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSpliteratorNPEs() {
|
||||
assertThrowsNPE(() -> Arrays.spliterator((int[]) null, 0, 0));
|
||||
assertThrowsNPE(() -> Arrays.spliterator((long[]) null, 0, 0));
|
||||
assertThrowsNPE(() -> Arrays.spliterator((double[]) null, 0, 0));
|
||||
assertThrowsNPE(() -> Arrays.spliterator((String[]) null, 0, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpliteratorAIOBEs() {
|
||||
// origin > fence
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 1, 0));
|
||||
|
||||
// bad origin
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, -1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, -1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, -1, 0));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, -1, 0));
|
||||
|
||||
// bad fence
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 0, 1));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 0, 1));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 0, 1));
|
||||
assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 0, 1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSpliteratorNPEsFromSpliterators() {
|
||||
assertThrowsNPE(() -> Spliterators.spliterator((int[]) null, 0, 0, 0));
|
||||
assertThrowsNPE(() -> Spliterators.spliterator((long[]) null, 0, 0, 0));
|
||||
assertThrowsNPE(() -> Spliterators.spliterator((double[]) null, 0, 0, 0));
|
||||
assertThrowsNPE(() -> Spliterators.spliterator((String[]) null, 0, 0, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpliteratorAIOBEsFromSpliterators() {
|
||||
// origin > fence
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 1, 0, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 1, 0, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 1, 0, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 1, 0, 0));
|
||||
|
||||
// bad origin
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, -1, 0, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, -1, 0, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, -1, 0, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, -1, 0, 0));
|
||||
|
||||
// bad fence
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 0, 1, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 0, 1, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 0, 1, 0));
|
||||
assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 0, 1, 0));
|
||||
}
|
||||
|
||||
void assertThrowsNPE(Executable r) {
|
||||
assertThrows(NullPointerException.class, r);
|
||||
}
|
||||
|
||||
void assertThrowsAIOOB(Executable r) {
|
||||
assertThrows(ArrayIndexOutOfBoundsException.class, r);
|
||||
}
|
||||
}
|
||||
1
test/jdk/java/util/Arrays/TEST.properties
Normal file
1
test/jdk/java/util/Arrays/TEST.properties
Normal file
|
|
@ -0,0 +1 @@
|
|||
disallowedActions=testng
|
||||
116
test/jdk/java/util/Arrays/TimSortStackSize.java
Normal file
116
test/jdk/java/util/Arrays/TimSortStackSize.java
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8011944
|
||||
* @summary Test TimSort stack size
|
||||
*/
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public class TimSortStackSize {
|
||||
|
||||
public static void main(String[] args) {
|
||||
testComparableTimSort();
|
||||
testTimSort();
|
||||
}
|
||||
|
||||
static void testComparableTimSort() {
|
||||
System.out.printf("testComparableTimSort()%n");
|
||||
Arrays.sort(genData());
|
||||
}
|
||||
|
||||
static void testTimSort() {
|
||||
System.out.printf("testTimSort()%n");
|
||||
Arrays.sort(genData(), Integer::compare);
|
||||
}
|
||||
|
||||
private static final int MIN = 16;
|
||||
|
||||
private static final int BOUND1 = 2 * MIN + 1;
|
||||
private static final int BOUND2 = BOUND1 + MIN + 2;
|
||||
private static final int BOUND3 = BOUND1 + 1 + BOUND2;
|
||||
private static final int BOUND4 = BOUND2 + 1 + BOUND3;
|
||||
private static final int BOUND5 = BOUND3 + 1 + BOUND4;
|
||||
|
||||
static int build(int size, int B, ArrayDeque<Integer> chunks) {
|
||||
chunks.addFirst(B);
|
||||
if (size < BOUND1) {
|
||||
chunks.addFirst(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
int asize = (size + 2) / 2;
|
||||
if (size >= BOUND2 && asize < BOUND1) {
|
||||
asize = BOUND1;
|
||||
} else if (size >= BOUND3 && asize < BOUND2) {
|
||||
asize = BOUND2;
|
||||
} else if (size >= BOUND4 && asize < BOUND3) {
|
||||
asize = BOUND3;
|
||||
} else if (size >= BOUND5 && asize < BOUND4) {
|
||||
asize = BOUND4;
|
||||
}
|
||||
if (size - asize >= B) {
|
||||
throw new AssertionError(" " + size + " , " + asize + " , " + B);
|
||||
}
|
||||
return build(asize, size - asize, chunks);
|
||||
}
|
||||
|
||||
static Integer[] genData() {
|
||||
ArrayDeque<Integer> chunks = new ArrayDeque<Integer>();
|
||||
chunks.addFirst(MIN);
|
||||
|
||||
int B = MIN + 4;
|
||||
int A = B + MIN + 1;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int eps = build(A, B, chunks);
|
||||
B = B + A + 1;
|
||||
A = B + eps + 1;
|
||||
}
|
||||
chunks.addFirst(B);
|
||||
chunks.addFirst(A);
|
||||
int total = 0;
|
||||
for (Integer len : chunks) {
|
||||
total += len;
|
||||
}
|
||||
int pow = MIN;
|
||||
while (pow < total) {
|
||||
pow += pow;
|
||||
}
|
||||
chunks.addLast(pow - total);
|
||||
System.out.println(" Total: " + total);
|
||||
Integer[] array = new Integer[pow];
|
||||
int off = 0;
|
||||
int pos = 0;
|
||||
for (Integer len : chunks) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
array[pos++] = Integer.valueOf(i == 0 ? 0 : 1);
|
||||
}
|
||||
off++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
||||
214
test/jdk/java/util/Arrays/TimSortStackSize2.java
Normal file
214
test/jdk/java/util/Arrays/TimSortStackSize2.java
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8072909
|
||||
* @summary Test TimSort stack size on big arrays
|
||||
* @library /test/lib
|
||||
* @modules java.management
|
||||
* @requires (vm.debug == false)
|
||||
* @build TimSortStackSize2
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI TimSortStackSize2
|
||||
*/
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.whitebox.WhiteBox;
|
||||
|
||||
public class TimSortStackSize2 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
if ( args == null || args.length == 0 ){
|
||||
startMeWithArgs();
|
||||
} else {
|
||||
doTestOfTwoTimSorts(Integer.parseInt(args[0]));
|
||||
}
|
||||
}
|
||||
|
||||
private static void startMeWithArgs(){
|
||||
/*
|
||||
* big tests not for regular execution on all platforms:
|
||||
* run main/othervm -Xmx8g TimSortStackSize2 1073741824
|
||||
* run main/othervm -Xmx16g TimSortStackSize2 2147483644
|
||||
*/
|
||||
try {
|
||||
Boolean compressedOops = WhiteBox.getWhiteBox()
|
||||
.getBooleanVMFlag("UseCompressedOops");
|
||||
long memory = (compressedOops == null || compressedOops) ? 385 : 770;
|
||||
final String xmsValue = "-Xms" + memory + "m";
|
||||
final String xmxValue = "-Xmx" + 2 * memory + "m";
|
||||
|
||||
System.out.printf("compressedOops: %s; Test will be started with \"%s %s\"%n",
|
||||
compressedOops, xmsValue, xmxValue);
|
||||
OutputAnalyzer output = ProcessTools.executeTestJava(xmsValue,
|
||||
xmxValue,
|
||||
"TimSortStackSize2",
|
||||
"67108864");
|
||||
System.out.println(output.getOutput());
|
||||
output.shouldHaveExitValue(0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doTestOfTwoTimSorts(final int lengthOfTest){
|
||||
boolean passed = doTest("TimSort", lengthOfTest,
|
||||
(Integer [] a) -> Arrays.sort(a));
|
||||
passed = doTest("ComparableTimSort", lengthOfTest, (Integer [] a) ->
|
||||
Arrays.sort(a, (Object first, Object second) -> {
|
||||
return ((Comparable<Object>)first).compareTo(second);
|
||||
}))
|
||||
&& passed;
|
||||
if ( !passed ){
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean doTest(final String msg, final int lengthOfTest,
|
||||
final Consumer<Integer[]> c){
|
||||
Integer [] a = null;
|
||||
try {
|
||||
a = new TimSortStackSize2(lengthOfTest).createArray();
|
||||
long begin = System.nanoTime();
|
||||
c.accept(a);
|
||||
long end = System.nanoTime();
|
||||
System.out.println(msg + " OK. Time: " + (end - begin) + "ns");
|
||||
} catch (ArrayIndexOutOfBoundsException e){
|
||||
System.out.println(msg + " broken:");
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} finally {
|
||||
a = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final int MIN_MERGE = 32;
|
||||
private final int minRun;
|
||||
private final int length;
|
||||
private final List<Long> runs = new ArrayList<Long>();
|
||||
|
||||
public TimSortStackSize2(final int len) {
|
||||
this.length = len;
|
||||
minRun = minRunLength(len);
|
||||
fillRunsJDKWorstCase();
|
||||
}
|
||||
|
||||
private static int minRunLength(int n) {
|
||||
assert n >= 0;
|
||||
int r = 0; // Becomes 1 if any 1 bits are shifted off
|
||||
while (n >= MIN_MERGE) {
|
||||
r |= (n & 1);
|
||||
n >>= 1;
|
||||
}
|
||||
return n + r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sequence x_1, ..., x_n of run lengths to <code>runs</code> such that:<br>
|
||||
* 1. X = x_1 + ... + x_n <br>
|
||||
* 2. x_j >= minRun for all j <br>
|
||||
* 3. x_1 + ... + x_{j-2} < x_j < x_1 + ... + x_{j-1} for all j <br>
|
||||
* These conditions guarantee that TimSort merges all x_j's one by one
|
||||
* (resulting in X) using only merges on the second-to-last element.
|
||||
* @param X The sum of the sequence that should be added to runs.
|
||||
*/
|
||||
private void generateJDKWrongElem(long X) {
|
||||
for(long newTotal; X >= 2 * minRun + 1; X = newTotal) {
|
||||
//Default strategy
|
||||
newTotal = X / 2 + 1;
|
||||
//Specialized strategies
|
||||
if(3 * minRun + 3 <= X && X <= 4*minRun+1) {
|
||||
// add x_1=MIN+1, x_2=MIN, x_3=X-newTotal to runs
|
||||
newTotal = 2 * minRun + 1;
|
||||
} else if (5 * minRun + 5 <= X && X <= 6 * minRun + 5) {
|
||||
// add x_1=MIN+1, x_2=MIN, x_3=MIN+2, x_4=X-newTotal to runs
|
||||
newTotal = 3 * minRun + 3;
|
||||
} else if (8 * minRun + 9 <= X && X <= 10 * minRun + 9) {
|
||||
// add x_1=MIN+1, x_2=MIN, x_3=MIN+2, x_4=2MIN+2, x_5=X-newTotal to runs
|
||||
newTotal = 5 * minRun + 5;
|
||||
} else if (13 * minRun + 15 <= X && X <= 16 * minRun + 17) {
|
||||
// add x_1=MIN+1, x_2=MIN, x_3=MIN+2, x_4=2MIN+2, x_5=3MIN+4, x_6=X-newTotal to runs
|
||||
newTotal = 8 * minRun + 9;
|
||||
}
|
||||
runs.add(0, X - newTotal);
|
||||
}
|
||||
runs.add(0, X);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills <code>runs</code> with a sequence of run lengths of the form<br>
|
||||
* Y_n x_{n,1} x_{n,2} ... x_{n,l_n} <br>
|
||||
* Y_{n-1} x_{n-1,1} x_{n-1,2} ... x_{n-1,l_{n-1}} <br>
|
||||
* ... <br>
|
||||
* Y_1 x_{1,1} x_{1,2} ... x_{1,l_1}<br>
|
||||
* The Y_i's are chosen to satisfy the invariant throughout execution,
|
||||
* but the x_{i,j}'s are merged (by <code>TimSort.mergeCollapse</code>)
|
||||
* into an X_i that violates the invariant.
|
||||
* X is the sum of all run lengths that will be added to <code>runs</code>.
|
||||
*/
|
||||
private void fillRunsJDKWorstCase() {
|
||||
long runningTotal = 0;
|
||||
long Y = minRun + 4;
|
||||
long X = minRun;
|
||||
|
||||
while (runningTotal + Y + X <= length) {
|
||||
runningTotal += X + Y;
|
||||
generateJDKWrongElem(X);
|
||||
runs.add(0, Y);
|
||||
|
||||
// X_{i+1} = Y_i + x_{i,1} + 1, since runs.get(1) = x_{i,1}
|
||||
X = Y + runs.get(1) + 1;
|
||||
|
||||
// Y_{i+1} = X_{i+1} + Y_i + 1
|
||||
Y += X + 1;
|
||||
}
|
||||
|
||||
if (runningTotal + X <= length) {
|
||||
runningTotal += X;
|
||||
generateJDKWrongElem(X);
|
||||
}
|
||||
|
||||
runs.add(length - runningTotal);
|
||||
}
|
||||
|
||||
private Integer [] createArray() {
|
||||
Integer [] a = new Integer[length];
|
||||
Arrays.fill(a, 0);
|
||||
int endRun = -1;
|
||||
for (long len : runs) {
|
||||
a[endRun += len] = 1;
|
||||
}
|
||||
a[length - 1] = 0;
|
||||
return a;
|
||||
}
|
||||
|
||||
}
|
||||
350
test/jdk/java/util/Arrays/java.base/java/util/SortingHelper.java
Normal file
350
test/jdk/java/util/Arrays/java.base/java/util/SortingHelper.java
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 java.util;
|
||||
|
||||
/**
|
||||
* This class provides access to package-private
|
||||
* methods of DualPivotQuicksort class.
|
||||
*
|
||||
* @author Vladimir Yaroslavskiy
|
||||
*
|
||||
* @version 2019.09.19
|
||||
*
|
||||
* @since 14
|
||||
*/
|
||||
public enum SortingHelper {
|
||||
|
||||
DUAL_PIVOT_QUICKSORT("Dual-Pivot Quicksort") {
|
||||
|
||||
@Override
|
||||
public void sort(Object a) {
|
||||
if (a instanceof int[]) {
|
||||
DualPivotQuicksort.sort((int[]) a, SEQUENTIAL, 0, ((int[]) a).length);
|
||||
} else if (a instanceof long[]) {
|
||||
DualPivotQuicksort.sort((long[]) a, SEQUENTIAL, 0, ((long[]) a).length);
|
||||
} else if (a instanceof byte[]) {
|
||||
DualPivotQuicksort.sort((byte[]) a, 0, ((byte[]) a).length);
|
||||
} else if (a instanceof char[]) {
|
||||
DualPivotQuicksort.sort((char[]) a, SEQUENTIAL, 0, ((char[]) a).length);
|
||||
} else if (a instanceof short[]) {
|
||||
DualPivotQuicksort.sort((short[]) a, SEQUENTIAL, 0, ((short[]) a).length);
|
||||
} else if (a instanceof float[]) {
|
||||
DualPivotQuicksort.sort((float[]) a, SEQUENTIAL, 0, ((float[]) a).length);
|
||||
} else if (a instanceof double[]) {
|
||||
DualPivotQuicksort.sort((double[]) a, SEQUENTIAL, 0, ((double[]) a).length);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object a, int low, int high) {
|
||||
if (a instanceof int[]) {
|
||||
DualPivotQuicksort.sort((int[]) a, SEQUENTIAL, low, high);
|
||||
} else if (a instanceof long[]) {
|
||||
DualPivotQuicksort.sort((long[]) a, SEQUENTIAL, low, high);
|
||||
} else if (a instanceof byte[]) {
|
||||
DualPivotQuicksort.sort((byte[]) a, low, high);
|
||||
} else if (a instanceof char[]) {
|
||||
DualPivotQuicksort.sort((char[]) a, SEQUENTIAL, low, high);
|
||||
} else if (a instanceof short[]) {
|
||||
DualPivotQuicksort.sort((short[]) a, SEQUENTIAL, low, high);
|
||||
} else if (a instanceof float[]) {
|
||||
DualPivotQuicksort.sort((float[]) a, SEQUENTIAL, low, high);
|
||||
} else if (a instanceof double[]) {
|
||||
DualPivotQuicksort.sort((double[]) a, SEQUENTIAL, low, high);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object[] a) {
|
||||
fail(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object[] a, Comparator comparator) {
|
||||
fail(a);
|
||||
}
|
||||
},
|
||||
|
||||
PARALLEL_SORT("Parallel sort") {
|
||||
|
||||
@Override
|
||||
public void sort(Object a) {
|
||||
if (a instanceof int[]) {
|
||||
DualPivotQuicksort.sort((int[]) a, PARALLEL, 0, ((int[]) a).length);
|
||||
} else if (a instanceof long[]) {
|
||||
DualPivotQuicksort.sort((long[]) a, PARALLEL, 0, ((long[]) a).length);
|
||||
} else if (a instanceof byte[]) {
|
||||
DualPivotQuicksort.sort((byte[]) a, 0, ((byte[]) a).length);
|
||||
} else if (a instanceof char[]) {
|
||||
DualPivotQuicksort.sort((char[]) a, PARALLEL, 0, ((char[]) a).length);
|
||||
} else if (a instanceof short[]) {
|
||||
DualPivotQuicksort.sort((short[]) a, PARALLEL, 0, ((short[]) a).length);
|
||||
} else if (a instanceof float[]) {
|
||||
DualPivotQuicksort.sort((float[]) a, PARALLEL, 0, ((float[]) a).length);
|
||||
} else if (a instanceof double[]) {
|
||||
DualPivotQuicksort.sort((double[]) a, PARALLEL, 0, ((double[]) a).length);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object a, int low, int high) {
|
||||
if (a instanceof int[]) {
|
||||
DualPivotQuicksort.sort((int[]) a, PARALLEL, low, high);
|
||||
} else if (a instanceof long[]) {
|
||||
DualPivotQuicksort.sort((long[]) a, PARALLEL, low, high);
|
||||
} else if (a instanceof byte[]) {
|
||||
DualPivotQuicksort.sort((byte[]) a, low, high);
|
||||
} else if (a instanceof char[]) {
|
||||
DualPivotQuicksort.sort((char[]) a, PARALLEL, low, high);
|
||||
} else if (a instanceof short[]) {
|
||||
DualPivotQuicksort.sort((short[]) a, PARALLEL, low, high);
|
||||
} else if (a instanceof float[]) {
|
||||
DualPivotQuicksort.sort((float[]) a, PARALLEL, low, high);
|
||||
} else if (a instanceof double[]) {
|
||||
DualPivotQuicksort.sort((double[]) a, PARALLEL, low, high);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object[] a) {
|
||||
fail(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object[] a, Comparator comparator) {
|
||||
fail(a);
|
||||
}
|
||||
},
|
||||
|
||||
HEAP_SORT("Heap sort") {
|
||||
|
||||
@Override
|
||||
public void sort(Object a) {
|
||||
if (a instanceof int[]) {
|
||||
DualPivotQuicksort.sort(null, (int[]) a, BIG_DEPTH, 0, ((int[]) a).length);
|
||||
} else if (a instanceof long[]) {
|
||||
DualPivotQuicksort.sort(null, (long[]) a, BIG_DEPTH, 0, ((long[]) a).length);
|
||||
} else if (a instanceof byte[]) {
|
||||
DualPivotQuicksort.sort((byte[]) a, 0, ((byte[]) a).length);
|
||||
} else if (a instanceof char[]) {
|
||||
DualPivotQuicksort.sort((char[]) a, BIG_DEPTH, 0, ((char[]) a).length);
|
||||
} else if (a instanceof short[]) {
|
||||
DualPivotQuicksort.sort((short[]) a, BIG_DEPTH, 0, ((short[]) a).length);
|
||||
} else if (a instanceof float[]) {
|
||||
DualPivotQuicksort.sort(null, (float[]) a, BIG_DEPTH, 0, ((float[]) a).length);
|
||||
} else if (a instanceof double[]) {
|
||||
DualPivotQuicksort.sort(null, (double[]) a, BIG_DEPTH, 0, ((double[]) a).length);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object a, int low, int high) {
|
||||
if (a instanceof int[]) {
|
||||
DualPivotQuicksort.sort(null, (int[]) a, BIG_DEPTH, low, high);
|
||||
} else if (a instanceof long[]) {
|
||||
DualPivotQuicksort.sort(null, (long[]) a, BIG_DEPTH, low, high);
|
||||
} else if (a instanceof byte[]) {
|
||||
DualPivotQuicksort.sort((byte[]) a, low, high);
|
||||
} else if (a instanceof char[]) {
|
||||
DualPivotQuicksort.sort((char[]) a, BIG_DEPTH, low, high);
|
||||
} else if (a instanceof short[]) {
|
||||
DualPivotQuicksort.sort((short[]) a, BIG_DEPTH, low, high);
|
||||
} else if (a instanceof float[]) {
|
||||
DualPivotQuicksort.sort(null, (float[]) a, BIG_DEPTH, low, high);
|
||||
} else if (a instanceof double[]) {
|
||||
DualPivotQuicksort.sort(null, (double[]) a, BIG_DEPTH, low, high);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object[] a) {
|
||||
fail(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object[] a, Comparator comparator) {
|
||||
fail(a);
|
||||
}
|
||||
},
|
||||
|
||||
ARRAYS_SORT("Arrays.sort") {
|
||||
|
||||
@Override
|
||||
public void sort(Object a) {
|
||||
if (a instanceof int[]) {
|
||||
Arrays.sort((int[]) a);
|
||||
} else if (a instanceof long[]) {
|
||||
Arrays.sort((long[]) a);
|
||||
} else if (a instanceof byte[]) {
|
||||
Arrays.sort((byte[]) a);
|
||||
} else if (a instanceof char[]) {
|
||||
Arrays.sort((char[]) a);
|
||||
} else if (a instanceof short[]) {
|
||||
Arrays.sort((short[]) a);
|
||||
} else if (a instanceof float[]) {
|
||||
Arrays.sort((float[]) a);
|
||||
} else if (a instanceof double[]) {
|
||||
Arrays.sort((double[]) a);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object a, int low, int high) {
|
||||
if (a instanceof int[]) {
|
||||
Arrays.sort((int[]) a, low, high);
|
||||
} else if (a instanceof long[]) {
|
||||
Arrays.sort((long[]) a, low, high);
|
||||
} else if (a instanceof byte[]) {
|
||||
Arrays.sort((byte[]) a, low, high);
|
||||
} else if (a instanceof char[]) {
|
||||
Arrays.sort((char[]) a, low, high);
|
||||
} else if (a instanceof short[]) {
|
||||
Arrays.sort((short[]) a, low, high);
|
||||
} else if (a instanceof float[]) {
|
||||
Arrays.sort((float[]) a, low, high);
|
||||
} else if (a instanceof double[]) {
|
||||
Arrays.sort((double[]) a, low, high);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object[] a) {
|
||||
Arrays.sort(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void sort(Object[] a, Comparator comparator) {
|
||||
Arrays.sort(a, comparator);
|
||||
}
|
||||
},
|
||||
|
||||
ARRAYS_PARALLEL_SORT("Arrays.parallelSort") {
|
||||
|
||||
@Override
|
||||
public void sort(Object a) {
|
||||
if (a instanceof int[]) {
|
||||
Arrays.parallelSort((int[]) a);
|
||||
} else if (a instanceof long[]) {
|
||||
Arrays.parallelSort((long[]) a);
|
||||
} else if (a instanceof byte[]) {
|
||||
Arrays.parallelSort((byte[]) a);
|
||||
} else if (a instanceof char[]) {
|
||||
Arrays.parallelSort((char[]) a);
|
||||
} else if (a instanceof short[]) {
|
||||
Arrays.parallelSort((short[]) a);
|
||||
} else if (a instanceof float[]) {
|
||||
Arrays.parallelSort((float[]) a);
|
||||
} else if (a instanceof double[]) {
|
||||
Arrays.parallelSort((double[]) a);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Object a, int low, int high) {
|
||||
if (a instanceof int[]) {
|
||||
Arrays.parallelSort((int[]) a, low, high);
|
||||
} else if (a instanceof long[]) {
|
||||
Arrays.parallelSort((long[]) a, low, high);
|
||||
} else if (a instanceof byte[]) {
|
||||
Arrays.parallelSort((byte[]) a, low, high);
|
||||
} else if (a instanceof char[]) {
|
||||
Arrays.parallelSort((char[]) a, low, high);
|
||||
} else if (a instanceof short[]) {
|
||||
Arrays.parallelSort((short[]) a, low, high);
|
||||
} else if (a instanceof float[]) {
|
||||
Arrays.parallelSort((float[]) a, low, high);
|
||||
} else if (a instanceof double[]) {
|
||||
Arrays.parallelSort((double[]) a, low, high);
|
||||
} else {
|
||||
fail(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void sort(Object[] a) {
|
||||
Arrays.parallelSort((Comparable[]) a);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void sort(Object[] a, Comparator comparator) {
|
||||
Arrays.parallelSort(a, comparator);
|
||||
}
|
||||
};
|
||||
|
||||
abstract public void sort(Object a);
|
||||
|
||||
abstract public void sort(Object a, int low, int high);
|
||||
|
||||
abstract public void sort(Object[] a);
|
||||
|
||||
abstract public void sort(Object[] a, Comparator comparator);
|
||||
|
||||
private SortingHelper(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private static void fail(Object a) {
|
||||
throw new RuntimeException("Unexpected type of array: " + a.getClass().getName());
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Parallelism level for sequential and parallel sorting.
|
||||
*/
|
||||
private static final int SEQUENTIAL = 0;
|
||||
private static final int PARALLEL = 87;
|
||||
|
||||
/**
|
||||
* Heap sort will be invoked, if recursion depth is too big.
|
||||
* Value is taken from DualPivotQuicksort.MAX_RECURSION_DEPTH.
|
||||
*/
|
||||
private static final int BIG_DEPTH = 64 * (3 << 1);
|
||||
}
|
||||
313
test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java
Normal file
313
test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8014076 8025067
|
||||
* @summary unit test for Arrays.ParallelPrefix().
|
||||
* @modules java.management jdk.management
|
||||
* @run junit/othervm -Xms256m -Xmx1024m ParallelPrefix
|
||||
*/
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.DoubleBinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class ParallelPrefix {
|
||||
//Array size less than MIN_PARTITION
|
||||
private static final int SMALL_ARRAY_SIZE = 1 << 3;
|
||||
|
||||
//Array size equals MIN_PARTITION
|
||||
private static final int THRESHOLD_ARRAY_SIZE = 1 << 4;
|
||||
|
||||
//Array size greater than MIN_PARTITION
|
||||
private static final int MEDIUM_ARRAY_SIZE = 1 << 8;
|
||||
|
||||
//Array size much greater than MIN_PARTITION
|
||||
private static final int LARGE_ARRAY_SIZE = 1 << 14;
|
||||
|
||||
private static int[] arraySizeCollection;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
java.lang.management.OperatingSystemMXBean bean =
|
||||
ManagementFactory.getOperatingSystemMXBean();
|
||||
if (bean instanceof OperatingSystemMXBean) {
|
||||
OperatingSystemMXBean os = (OperatingSystemMXBean)bean;
|
||||
long physicalMemorySize = os.getTotalPhysicalMemorySize() / (1024 * 1024);
|
||||
System.out.println("System memory size: " + physicalMemorySize + "M");
|
||||
// when we can get system memory size, and it's larger than 2G,
|
||||
// then we enable large array size test below,
|
||||
// else disable large array size test below.
|
||||
if (physicalMemorySize > (2 * 1024)) {
|
||||
arraySizeCollection = new int[]{
|
||||
SMALL_ARRAY_SIZE,
|
||||
THRESHOLD_ARRAY_SIZE,
|
||||
MEDIUM_ARRAY_SIZE,
|
||||
LARGE_ARRAY_SIZE
|
||||
};
|
||||
System.out.println("System memory is large enough, add large array size test");
|
||||
return;
|
||||
}
|
||||
}
|
||||
arraySizeCollection = new int[]{
|
||||
SMALL_ARRAY_SIZE,
|
||||
THRESHOLD_ARRAY_SIZE,
|
||||
MEDIUM_ARRAY_SIZE
|
||||
};
|
||||
System.out.println("System memory is not large enough, remove large array size test");
|
||||
}
|
||||
|
||||
public static Object[][] intSet(){
|
||||
return genericData(size -> IntStream.range(0, size).toArray(),
|
||||
new IntBinaryOperator[]{
|
||||
Integer::sum,
|
||||
Integer::min});
|
||||
}
|
||||
|
||||
public static Object[][] longSet(){
|
||||
return genericData(size -> LongStream.range(0, size).toArray(),
|
||||
new LongBinaryOperator[]{
|
||||
Long::sum,
|
||||
Long::min});
|
||||
}
|
||||
|
||||
public static Object[][] doubleSet(){
|
||||
return genericData(size -> IntStream.range(0, size).mapToDouble(i -> (double)i).toArray(),
|
||||
new DoubleBinaryOperator[]{
|
||||
Double::sum,
|
||||
Double::min});
|
||||
}
|
||||
|
||||
public static Object[][] stringSet(){
|
||||
Function<Integer, String[]> stringsFunc = size ->
|
||||
IntStream.range(0, size).mapToObj(Integer::toString).toArray(String[]::new);
|
||||
BinaryOperator<String> concat = String::concat;
|
||||
return genericData(stringsFunc,
|
||||
(BinaryOperator<String>[]) new BinaryOperator[]{
|
||||
concat });
|
||||
}
|
||||
|
||||
private static <T, OPS> Object[][] genericData(Function<Integer, T> generateFunc, OPS[] ops) {
|
||||
//test arrays which size is equals n-1, n, n+1, test random data
|
||||
Object[][] data = new Object[arraySizeCollection.length * 3 * ops.length][4];
|
||||
for(int n = 0; n < arraySizeCollection.length; n++ ) {
|
||||
for(int testValue = -1 ; testValue <= 1; testValue++) {
|
||||
int array_size = arraySizeCollection[n] + testValue;
|
||||
for(int opsN = 0; opsN < ops.length; opsN++) {
|
||||
int index = n * 3 * ops.length + (testValue + 1) * ops.length + opsN;
|
||||
data[index][0] = generateFunc.apply(array_size);
|
||||
data[index][1] = array_size / 3;
|
||||
data[index][2] = 2 * array_size / 3;
|
||||
data[index][3] = ops[opsN];
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("intSet")
|
||||
public void testParallelPrefixForInt(int[] data, int fromIndex, int toIndex, IntBinaryOperator op) {
|
||||
int[] sequentialResult = data.clone();
|
||||
for (int index = fromIndex + 1; index < toIndex; index++) {
|
||||
sequentialResult[index ] = op.applyAsInt(sequentialResult[index - 1], sequentialResult[index]);
|
||||
}
|
||||
|
||||
int[] parallelResult = data.clone();
|
||||
Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op);
|
||||
assertArraysEqual(sequentialResult, parallelResult);
|
||||
|
||||
int[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex);
|
||||
Arrays.parallelPrefix(parallelRangeResult, op);
|
||||
assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("longSet")
|
||||
public void testParallelPrefixForLong(long[] data, int fromIndex, int toIndex, LongBinaryOperator op) {
|
||||
long[] sequentialResult = data.clone();
|
||||
for (int index = fromIndex + 1; index < toIndex; index++) {
|
||||
sequentialResult[index ] = op.applyAsLong(sequentialResult[index - 1], sequentialResult[index]);
|
||||
}
|
||||
|
||||
long[] parallelResult = data.clone();
|
||||
Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op);
|
||||
assertArraysEqual(sequentialResult, parallelResult);
|
||||
|
||||
long[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex);
|
||||
Arrays.parallelPrefix(parallelRangeResult, op);
|
||||
assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("doubleSet")
|
||||
public void testParallelPrefixForDouble(double[] data, int fromIndex, int toIndex, DoubleBinaryOperator op) {
|
||||
double[] sequentialResult = data.clone();
|
||||
for (int index = fromIndex + 1; index < toIndex; index++) {
|
||||
sequentialResult[index ] = op.applyAsDouble(sequentialResult[index - 1], sequentialResult[index]);
|
||||
}
|
||||
|
||||
double[] parallelResult = data.clone();
|
||||
Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op);
|
||||
assertArraysEqual(sequentialResult, parallelResult);
|
||||
|
||||
double[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex);
|
||||
Arrays.parallelPrefix(parallelRangeResult, op);
|
||||
assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("stringSet")
|
||||
public void testParallelPrefixForStringr(String[] data , int fromIndex, int toIndex, BinaryOperator<String> op) {
|
||||
String[] sequentialResult = data.clone();
|
||||
for (int index = fromIndex + 1; index < toIndex; index++) {
|
||||
sequentialResult[index ] = op.apply(sequentialResult[index - 1], sequentialResult[index]);
|
||||
}
|
||||
|
||||
String[] parallelResult = data.clone();
|
||||
Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op);
|
||||
assertArraysEqual(sequentialResult, parallelResult);
|
||||
|
||||
String[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex);
|
||||
Arrays.parallelPrefix(parallelRangeResult, op);
|
||||
assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNPEs() {
|
||||
// null array
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((int[]) null, Integer::max));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((long []) null, Long::max));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((double []) null, Double::max));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((String []) null, String::concat));
|
||||
|
||||
// null array w/ range
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((int[]) null, 0, 0, Integer::max));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((long []) null, 0, 0, Long::max));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((double []) null, 0, 0, Double::max));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix((String []) null, 0, 0, String::concat));
|
||||
|
||||
// null op
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new int[] {}, null));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new long[] {}, null));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new double[] {}, null));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new String[] {}, null));
|
||||
|
||||
// null op w/ range
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new int[] {}, 0, 0, null));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new long[] {}, 0, 0, null));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new double[] {}, 0, 0, null));
|
||||
assertThrowsNPE(() -> Arrays.parallelPrefix(new String[] {}, 0, 0, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIAEs() {
|
||||
assertThrowsIAE(() -> Arrays.parallelPrefix(new int[] {}, 1, 0, Integer::max));
|
||||
assertThrowsIAE(() -> Arrays.parallelPrefix(new long[] {}, 1, 0, Long::max));
|
||||
assertThrowsIAE(() -> Arrays.parallelPrefix(new double[] {}, 1, 0, Double::max));
|
||||
assertThrowsIAE(() -> Arrays.parallelPrefix(new String[] {}, 1, 0, String::concat));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAIOOBEs() {
|
||||
// bad "fromIndex"
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new int[] {}, -1, 0, Integer::max));
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new long[] {}, -1, 0, Long::max));
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new double[] {}, -1, 0, Double::max));
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new String[] {}, -1, 0, String::concat));
|
||||
|
||||
// bad "toIndex"
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new int[] {}, 0, 1, Integer::max));
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new long[] {}, 0, 1, Long::max));
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new double[] {}, 0, 1, Double::max));
|
||||
assertThrowsAIOOB(() -> Arrays.parallelPrefix(new String[] {}, 0, 1, String::concat));
|
||||
}
|
||||
|
||||
// "library" code
|
||||
|
||||
private void assertThrowsNPE(Executable r) {
|
||||
assertThrows(NullPointerException.class, r);
|
||||
}
|
||||
|
||||
private void assertThrowsIAE(Executable r) {
|
||||
assertThrows(IllegalArgumentException.class, r);
|
||||
}
|
||||
|
||||
private void assertThrowsAIOOB(Executable r) {
|
||||
assertThrows(ArrayIndexOutOfBoundsException.class, r);
|
||||
}
|
||||
|
||||
static void assertArraysEqual(int[] expected, int[] actual) {
|
||||
try {
|
||||
assertArrayEquals(expected, actual, "");
|
||||
} catch (AssertionError x) {
|
||||
throw new AssertionError(String.format("Expected:%s, actual:%s",
|
||||
Arrays.toString(expected), Arrays.toString(actual)), x);
|
||||
}
|
||||
}
|
||||
|
||||
static void assertArraysEqual(long[] expected, long[] actual) {
|
||||
try {
|
||||
assertArrayEquals(expected, actual, "");
|
||||
} catch (AssertionError x) {
|
||||
throw new AssertionError(String.format("Expected:%s, actual:%s",
|
||||
Arrays.toString(expected), Arrays.toString(actual)), x);
|
||||
}
|
||||
}
|
||||
|
||||
static void assertArraysEqual(double[] expected, double[] actual) {
|
||||
try {
|
||||
assertArrayEquals(expected, actual, "");
|
||||
} catch (AssertionError x) {
|
||||
throw new AssertionError(String.format("Expected:%s, actual:%s",
|
||||
Arrays.toString(expected), Arrays.toString(actual)), x);
|
||||
}
|
||||
}
|
||||
|
||||
static void assertArraysEqual(String[] expected, String[] actual) {
|
||||
try {
|
||||
assertArrayEquals(expected, actual, "");
|
||||
} catch (AssertionError x) {
|
||||
throw new AssertionError(String.format("Expected:%s, actual:%s",
|
||||
Arrays.toString(expected), Arrays.toString(actual)), x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
137
test/jdk/java/util/Base64/Base64GetEncoderTest.java
Normal file
137
test/jdk/java/util/Base64/Base64GetEncoderTest.java
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8007799 8176379
|
||||
* @summary test Encoder with linemax == 0, line separator should not appear in encoded data
|
||||
*/
|
||||
|
||||
public class Base64GetEncoderTest {
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
|
||||
for (int maxlen = -4; maxlen < 4; maxlen++) {
|
||||
|
||||
final Base64.Encoder encoder = Base64.getMimeEncoder(maxlen, "$$$".getBytes(US_ASCII));
|
||||
|
||||
testEncodeToString(encoder);
|
||||
testWrapEncode1(encoder);
|
||||
testEncodeToStringWithLongInputData(encoder);
|
||||
testWrapEncode2(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testWrapEncode2(final Base64.Encoder encoder)
|
||||
throws IOException {
|
||||
System.err.println("\nEncoder.wrap test II ");
|
||||
final byte[] secondTestBuffer =
|
||||
"api/java_util/Base64/index.html#GetEncoderMimeCustom[noLineSeparatorInEncodedString]"
|
||||
.getBytes(US_ASCII);
|
||||
String base64EncodedString;
|
||||
ByteArrayOutputStream secondEncodingStream = new ByteArrayOutputStream();
|
||||
OutputStream base64EncodingStream = encoder.wrap(secondEncodingStream);
|
||||
base64EncodingStream.write(secondTestBuffer);
|
||||
base64EncodingStream.close();
|
||||
|
||||
final byte[] encodedByteArray = secondEncodingStream.toByteArray();
|
||||
|
||||
System.err.print("result = " + new String(encodedByteArray, US_ASCII)
|
||||
+ " after wrap Base64 encoding of string");
|
||||
|
||||
base64EncodedString = new String(encodedByteArray, US_ASCII);
|
||||
|
||||
if (base64EncodedString.contains("$$$")) {
|
||||
throw new RuntimeException(
|
||||
"Base64 encoding contains line separator after wrap 2 invoked ... \n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testEncodeToStringWithLongInputData(
|
||||
final Base64.Encoder encoder) {
|
||||
System.err.println("\n\nEncoder.encodeToStringWithLongInputData test ");
|
||||
|
||||
final byte[] secondTestBuffer =
|
||||
"api/java_util/Base64/index.html#GetEncoderMimeCustom[noLineSeparatorInEncodedString]"
|
||||
.getBytes(US_ASCII);
|
||||
String base64EncodedString;
|
||||
base64EncodedString = encoder.encodeToString(secondTestBuffer);
|
||||
|
||||
System.err.println("Second Base64 encoded string is "
|
||||
+ base64EncodedString);
|
||||
|
||||
if (base64EncodedString.contains("$$$")) {
|
||||
throw new RuntimeException(
|
||||
"Base64 encoding contains line separator after encodeToString invoked ... \n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testWrapEncode1(final Base64.Encoder encoder)
|
||||
throws IOException {
|
||||
System.err.println("\nEncoder.wrap test I ");
|
||||
|
||||
final byte[] bytesIn = "fo".getBytes(US_ASCII);
|
||||
String base64EncodedString;
|
||||
ByteArrayOutputStream encodingStream = new ByteArrayOutputStream();
|
||||
OutputStream encoding = encoder.wrap(encodingStream);
|
||||
encoding.write(bytesIn);
|
||||
encoding.close();
|
||||
|
||||
final byte[] encodedBytes = encodingStream.toByteArray();
|
||||
|
||||
System.err.print("result = " + new String(encodedBytes, US_ASCII)
|
||||
+ " after the Base64 encoding \n");
|
||||
|
||||
base64EncodedString = new String(encodedBytes, US_ASCII);
|
||||
|
||||
if (base64EncodedString.contains("$$$")) {
|
||||
throw new RuntimeException(
|
||||
"Base64 encoding contains line separator after wrap I test ... \n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testEncodeToString(final Base64.Encoder encoder) {
|
||||
final byte[] bytesIn = "fo".getBytes(US_ASCII);
|
||||
|
||||
System.err.println("\nEncoder.encodeToString test ");
|
||||
|
||||
String base64EncodedString = encoder.encodeToString(bytesIn);
|
||||
|
||||
System.err.println("Base64 encoded string is " + base64EncodedString);
|
||||
|
||||
if (base64EncodedString.contains("$$$")) {
|
||||
throw new RuntimeException("Base64 encoding contains line separator after Encoder.encodeToString invoked ... \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
636
test/jdk/java/util/Base64/TestBase64.java
Normal file
636
test/jdk/java/util/Base64/TestBase64.java
Normal file
|
|
@ -0,0 +1,636 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4235519 8004212 8005394 8007298 8006295 8006315 8006530 8007379 8008925
|
||||
* 8014217 8025003 8026330 8028397 8129544 8165243 8176379 8222187
|
||||
* @summary tests java.util.Base64
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run main TestBase64
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import jdk.test.lib.RandomFactory;
|
||||
|
||||
public class TestBase64 {
|
||||
|
||||
private static final Random rnd = RandomFactory.getRandom();
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
int numRuns = 10;
|
||||
int numBytes = 200;
|
||||
if (args.length > 1) {
|
||||
numRuns = Integer.parseInt(args[0]);
|
||||
numBytes = Integer.parseInt(args[1]);
|
||||
}
|
||||
|
||||
test(Base64.getEncoder(), Base64.getDecoder(), numRuns, numBytes);
|
||||
test(Base64.getUrlEncoder(), Base64.getUrlDecoder(), numRuns, numBytes);
|
||||
test(Base64.getMimeEncoder(), Base64.getMimeDecoder(), numRuns, numBytes);
|
||||
|
||||
byte[] nl_1 = new byte[] {'\n'};
|
||||
byte[] nl_2 = new byte[] {'\n', '\r'};
|
||||
byte[] nl_3 = new byte[] {'\n', '\r', '\n'};
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int len = rnd.nextInt(200) + 4;
|
||||
test(Base64.getMimeEncoder(len, nl_1),
|
||||
Base64.getMimeDecoder(),
|
||||
numRuns, numBytes);
|
||||
test(Base64.getMimeEncoder(len, nl_2),
|
||||
Base64.getMimeDecoder(),
|
||||
numRuns, numBytes);
|
||||
test(Base64.getMimeEncoder(len, nl_3),
|
||||
Base64.getMimeDecoder(),
|
||||
numRuns, numBytes);
|
||||
}
|
||||
|
||||
// test mime case with < 4 length
|
||||
for (int len = 0; len < 4; len++) {
|
||||
test(Base64.getMimeEncoder(len, nl_1),
|
||||
Base64.getMimeDecoder(),
|
||||
numRuns, numBytes);
|
||||
|
||||
test(Base64.getMimeEncoder(len, nl_2),
|
||||
Base64.getMimeDecoder(),
|
||||
numRuns, numBytes);
|
||||
|
||||
test(Base64.getMimeEncoder(len, nl_3),
|
||||
Base64.getMimeDecoder(),
|
||||
numRuns, numBytes);
|
||||
}
|
||||
|
||||
testNull(Base64.getEncoder());
|
||||
testNull(Base64.getUrlEncoder());
|
||||
testNull(Base64.getMimeEncoder());
|
||||
testNull(Base64.getMimeEncoder(10, new byte[]{'\n'}));
|
||||
testNull(Base64.getDecoder());
|
||||
testNull(Base64.getUrlDecoder());
|
||||
testNull(Base64.getMimeDecoder());
|
||||
checkNull(() -> Base64.getMimeEncoder(10, null));
|
||||
|
||||
testIOE(Base64.getEncoder());
|
||||
testIOE(Base64.getUrlEncoder());
|
||||
testIOE(Base64.getMimeEncoder());
|
||||
testIOE(Base64.getMimeEncoder(10, new byte[]{'\n'}));
|
||||
|
||||
byte[] src = new byte[1024];
|
||||
rnd.nextBytes(src);
|
||||
final byte[] decoded = Base64.getEncoder().encode(src);
|
||||
testIOE(Base64.getDecoder(), decoded);
|
||||
testIOE(Base64.getMimeDecoder(), decoded);
|
||||
testIOE(Base64.getUrlDecoder(), Base64.getUrlEncoder().encode(src));
|
||||
|
||||
// illegal line separator
|
||||
checkIAE(() -> Base64.getMimeEncoder(10, new byte[]{'\r', 'N'}));
|
||||
|
||||
// malformed padding/ending
|
||||
testMalformedPadding();
|
||||
|
||||
// illegal base64 character
|
||||
decoded[2] = (byte)0xe0;
|
||||
checkIAE(() -> Base64.getDecoder().decode(decoded));
|
||||
checkIAE(() -> Base64.getDecoder().decode(decoded, new byte[1024]));
|
||||
checkIAE(() -> Base64.getDecoder().decode(ByteBuffer.wrap(decoded)));
|
||||
|
||||
// test single-non-base64 character for mime decoding
|
||||
testSingleNonBase64MimeDec();
|
||||
|
||||
// test decoding of unpadded data
|
||||
testDecodeUnpadded();
|
||||
|
||||
// test mime decoding with ignored character after padding
|
||||
testDecodeIgnoredAfterPadding();
|
||||
|
||||
// given invalid args, encoder should not produce output
|
||||
testEncoderKeepsSilence(Base64.getEncoder());
|
||||
testEncoderKeepsSilence(Base64.getUrlEncoder());
|
||||
testEncoderKeepsSilence(Base64.getMimeEncoder());
|
||||
|
||||
// given invalid args, decoder should not consume input
|
||||
testDecoderKeepsAbstinence(Base64.getDecoder());
|
||||
testDecoderKeepsAbstinence(Base64.getUrlDecoder());
|
||||
testDecoderKeepsAbstinence(Base64.getMimeDecoder());
|
||||
|
||||
// tests patch addressing JDK-8222187
|
||||
// https://bugs.openjdk.org/browse/JDK-8222187
|
||||
testJDK_8222187();
|
||||
}
|
||||
|
||||
private static void test(Base64.Encoder enc, Base64.Decoder dec,
|
||||
int numRuns, int numBytes) throws Throwable {
|
||||
enc.encode(new byte[0]);
|
||||
dec.decode(new byte[0]);
|
||||
|
||||
for (boolean withoutPadding : new boolean[] { false, true}) {
|
||||
if (withoutPadding) {
|
||||
enc = enc.withoutPadding();
|
||||
}
|
||||
for (int i=0; i<numRuns; i++) {
|
||||
for (int j=1; j<numBytes; j++) {
|
||||
byte[] orig = new byte[j];
|
||||
rnd.nextBytes(orig);
|
||||
|
||||
// --------testing encode/decode(byte[])--------
|
||||
byte[] encoded = enc.encode(orig);
|
||||
byte[] decoded = dec.decode(encoded);
|
||||
|
||||
checkEqual(orig, decoded,
|
||||
"Base64 array encoding/decoding failed!");
|
||||
if (withoutPadding) {
|
||||
if (encoded[encoded.length - 1] == '=')
|
||||
throw new RuntimeException(
|
||||
"Base64 enc.encode().withoutPadding() has padding!");
|
||||
}
|
||||
// --------testing encodetoString(byte[])/decode(String)--------
|
||||
String str = enc.encodeToString(orig);
|
||||
if (!Arrays.equals(str.getBytes("ASCII"), encoded)) {
|
||||
throw new RuntimeException(
|
||||
"Base64 encodingToString() failed!");
|
||||
}
|
||||
byte[] buf = dec.decode(new String(encoded, "ASCII"));
|
||||
checkEqual(buf, orig, "Base64 decoding(String) failed!");
|
||||
|
||||
//-------- testing encode/decode(Buffer)--------
|
||||
testEncode(enc, ByteBuffer.wrap(orig), encoded);
|
||||
ByteBuffer bin = ByteBuffer.allocateDirect(orig.length);
|
||||
bin.put(orig).flip();
|
||||
testEncode(enc, bin, encoded);
|
||||
|
||||
testDecode(dec, ByteBuffer.wrap(encoded), orig);
|
||||
bin = ByteBuffer.allocateDirect(encoded.length);
|
||||
bin.put(encoded).flip();
|
||||
testDecode(dec, bin, orig);
|
||||
|
||||
// --------testing decode.wrap(input stream)--------
|
||||
// 1) random buf length
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
|
||||
InputStream is = dec.wrap(bais);
|
||||
buf = new byte[orig.length + 10];
|
||||
int len = orig.length;
|
||||
int off = 0;
|
||||
while (true) {
|
||||
int n = rnd.nextInt(len);
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
n = is.read(buf, off, n);
|
||||
if (n == -1) {
|
||||
checkEqual(off, orig.length,
|
||||
"Base64 stream decoding failed");
|
||||
break;
|
||||
}
|
||||
off += n;
|
||||
len -= n;
|
||||
if (len == 0)
|
||||
break;
|
||||
}
|
||||
buf = Arrays.copyOf(buf, off);
|
||||
checkEqual(buf, orig, "Base64 stream decoding failed!");
|
||||
|
||||
// 2) read one byte each
|
||||
bais.reset();
|
||||
is = dec.wrap(bais);
|
||||
buf = new byte[orig.length + 10];
|
||||
off = 0;
|
||||
int b;
|
||||
while ((b = is.read()) != -1) {
|
||||
buf[off++] = (byte)b;
|
||||
}
|
||||
buf = Arrays.copyOf(buf, off);
|
||||
checkEqual(buf, orig, "Base64 stream decoding failed!");
|
||||
|
||||
// --------testing encode.wrap(output stream)--------
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream((orig.length + 2) / 3 * 4 + 10);
|
||||
OutputStream os = enc.wrap(baos);
|
||||
off = 0;
|
||||
len = orig.length;
|
||||
for (int k = 0; k < 5; k++) {
|
||||
if (len == 0)
|
||||
break;
|
||||
int n = rnd.nextInt(len);
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
os.write(orig, off, n);
|
||||
off += n;
|
||||
len -= n;
|
||||
}
|
||||
if (len != 0)
|
||||
os.write(orig, off, len);
|
||||
os.close();
|
||||
buf = baos.toByteArray();
|
||||
checkEqual(buf, encoded, "Base64 stream encoding failed!");
|
||||
|
||||
// 2) write one byte each
|
||||
baos.reset();
|
||||
os = enc.wrap(baos);
|
||||
off = 0;
|
||||
while (off < orig.length) {
|
||||
os.write(orig[off++]);
|
||||
}
|
||||
os.close();
|
||||
buf = baos.toByteArray();
|
||||
checkEqual(buf, encoded, "Base64 stream encoding failed!");
|
||||
|
||||
// --------testing encode(in, out); -> bigger buf--------
|
||||
buf = new byte[encoded.length + rnd.nextInt(100)];
|
||||
int ret = enc.encode(orig, buf);
|
||||
checkEqual(ret, encoded.length,
|
||||
"Base64 enc.encode(src, null) returns wrong size!");
|
||||
buf = Arrays.copyOf(buf, ret);
|
||||
checkEqual(buf, encoded,
|
||||
"Base64 enc.encode(src, dst) failed!");
|
||||
|
||||
// --------testing decode(in, out); -> bigger buf--------
|
||||
buf = new byte[orig.length + rnd.nextInt(100)];
|
||||
ret = dec.decode(encoded, buf);
|
||||
checkEqual(ret, orig.length,
|
||||
"Base64 enc.encode(src, null) returns wrong size!");
|
||||
buf = Arrays.copyOf(buf, ret);
|
||||
checkEqual(buf, orig,
|
||||
"Base64 dec.decode(src, dst) failed!");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final byte[] ba_null = null;
|
||||
private static final String str_null = null;
|
||||
private static final ByteBuffer bb_null = null;
|
||||
|
||||
private static void testNull(Base64.Encoder enc) {
|
||||
checkNull(() -> enc.encode(ba_null));
|
||||
checkNull(() -> enc.encodeToString(ba_null));
|
||||
checkNull(() -> enc.encode(ba_null, new byte[10]));
|
||||
checkNull(() -> enc.encode(new byte[10], ba_null));
|
||||
checkNull(() -> enc.encode(bb_null));
|
||||
checkNull(() -> enc.wrap((OutputStream)null));
|
||||
}
|
||||
|
||||
private static void testNull(Base64.Decoder dec) {
|
||||
checkNull(() -> dec.decode(ba_null));
|
||||
checkNull(() -> dec.decode(str_null));
|
||||
checkNull(() -> dec.decode(ba_null, new byte[10]));
|
||||
checkNull(() -> dec.decode(new byte[10], ba_null));
|
||||
checkNull(() -> dec.decode(bb_null));
|
||||
checkNull(() -> dec.wrap((InputStream)null));
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private static interface Testable {
|
||||
public void test() throws Throwable;
|
||||
}
|
||||
|
||||
private static void testIOE(Base64.Encoder enc) throws Throwable {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
|
||||
OutputStream os = enc.wrap(baos);
|
||||
os.write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9});
|
||||
os.close();
|
||||
checkIOE(() -> os.write(10));
|
||||
checkIOE(() -> os.write(new byte[] {10}));
|
||||
checkIOE(() -> os.write(new byte[] {10}, 1, 4));
|
||||
}
|
||||
|
||||
private static void testIOE(Base64.Decoder dec, byte[] decoded) throws Throwable {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(decoded);
|
||||
InputStream is = dec.wrap(bais);
|
||||
is.read(new byte[10]);
|
||||
is.close();
|
||||
checkIOE(() -> is.read());
|
||||
checkIOE(() -> is.read(new byte[] {10}));
|
||||
checkIOE(() -> is.read(new byte[] {10}, 1, 4));
|
||||
checkIOE(() -> is.available());
|
||||
checkIOE(() -> is.skip(20));
|
||||
}
|
||||
|
||||
private static final void checkNull(Runnable r) {
|
||||
try {
|
||||
r.run();
|
||||
throw new RuntimeException("NPE is not thrown as expected");
|
||||
} catch (NullPointerException npe) {}
|
||||
}
|
||||
|
||||
private static final void checkIOE(Testable t) throws Throwable {
|
||||
try {
|
||||
t.test();
|
||||
throw new RuntimeException("IOE is not thrown as expected");
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
|
||||
private static final void checkIAE(Runnable r) throws Throwable {
|
||||
try {
|
||||
r.run();
|
||||
throw new RuntimeException("IAE is not thrown as expected");
|
||||
} catch (IllegalArgumentException iae) {}
|
||||
}
|
||||
|
||||
private static void testDecodeIgnoredAfterPadding() throws Throwable {
|
||||
for (byte nonBase64 : new byte[] {'#', '(', '!', '\\', '-', '_', '\n', '\r'}) {
|
||||
byte[][] src = new byte[][] {
|
||||
"A".getBytes("ascii"),
|
||||
"AB".getBytes("ascii"),
|
||||
"ABC".getBytes("ascii"),
|
||||
"ABCD".getBytes("ascii"),
|
||||
"ABCDE".getBytes("ascii")
|
||||
};
|
||||
Base64.Encoder encM = Base64.getMimeEncoder();
|
||||
Base64.Decoder decM = Base64.getMimeDecoder();
|
||||
Base64.Encoder enc = Base64.getEncoder();
|
||||
Base64.Decoder dec = Base64.getDecoder();
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
// decode(byte[])
|
||||
byte[] encoded = encM.encode(src[i]);
|
||||
encoded = Arrays.copyOf(encoded, encoded.length + 1);
|
||||
encoded[encoded.length - 1] = nonBase64;
|
||||
checkEqual(decM.decode(encoded), src[i], "Non-base64 char is not ignored");
|
||||
byte[] decoded = new byte[src[i].length];
|
||||
decM.decode(encoded, decoded);
|
||||
checkEqual(decoded, src[i], "Non-base64 char is not ignored");
|
||||
|
||||
try {
|
||||
dec.decode(encoded);
|
||||
throw new RuntimeException("No IAE for non-base64 char");
|
||||
} catch (IllegalArgumentException iae) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testMalformedPadding() throws Throwable {
|
||||
Object[] data = new Object[] {
|
||||
"$=#", "", 0, // illegal ending unit
|
||||
"A", "", 0, // dangling single byte
|
||||
"A=", "", 0,
|
||||
"A==", "", 0,
|
||||
"QUJDA", "ABC", 4,
|
||||
"QUJDA=", "ABC", 4,
|
||||
"QUJDA==", "ABC", 4,
|
||||
|
||||
"=", "", 0, // unnecessary padding
|
||||
"QUJD=", "ABC", 4, //"ABC".encode() -> "QUJD"
|
||||
|
||||
"AA=", "", 0, // incomplete padding
|
||||
"QQ=", "", 0,
|
||||
"QQ=N", "", 0, // incorrect padding
|
||||
"QQ=?", "", 0,
|
||||
"QUJDQQ=", "ABC", 4,
|
||||
"QUJDQQ=N", "ABC", 4,
|
||||
"QUJDQQ=?", "ABC", 4,
|
||||
};
|
||||
|
||||
Base64.Decoder[] decs = new Base64.Decoder[] {
|
||||
Base64.getDecoder(),
|
||||
Base64.getUrlDecoder(),
|
||||
Base64.getMimeDecoder()
|
||||
};
|
||||
|
||||
for (Base64.Decoder dec : decs) {
|
||||
for (int i = 0; i < data.length; i += 3) {
|
||||
final String srcStr = (String)data[i];
|
||||
final byte[] srcBytes = srcStr.getBytes("ASCII");
|
||||
final ByteBuffer srcBB = ByteBuffer.wrap(srcBytes);
|
||||
byte[] expected = ((String)data[i + 1]).getBytes("ASCII");
|
||||
int pos = (Integer)data[i + 2];
|
||||
|
||||
// decode(byte[])
|
||||
checkIAE(() -> dec.decode(srcBytes));
|
||||
|
||||
// decode(String)
|
||||
checkIAE(() -> dec.decode(srcStr));
|
||||
|
||||
// decode(ByteBuffer)
|
||||
checkIAE(() -> dec.decode(srcBB));
|
||||
|
||||
// wrap stream
|
||||
checkIOE(new Testable() {
|
||||
public void test() throws IOException {
|
||||
try (InputStream is = dec.wrap(new ByteArrayInputStream(srcBytes))) {
|
||||
while (is.read() != -1);
|
||||
}
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
// anything left after padding is "invalid"/IAE, if
|
||||
// not MIME. In case of MIME, non-base64 character(s)
|
||||
// is ignored.
|
||||
checkIAE(() -> Base64.getDecoder().decode("AA==\u00D2"));
|
||||
checkIAE(() -> Base64.getUrlDecoder().decode("AA==\u00D2"));
|
||||
Base64.getMimeDecoder().decode("AA==\u00D2");
|
||||
}
|
||||
|
||||
private static void testDecodeUnpadded() throws Throwable {
|
||||
byte[] srcA = new byte[] { 'Q', 'Q' };
|
||||
byte[] srcAA = new byte[] { 'Q', 'Q', 'E'};
|
||||
Base64.Decoder dec = Base64.getDecoder();
|
||||
byte[] ret = dec.decode(srcA);
|
||||
if (ret[0] != 'A')
|
||||
throw new RuntimeException("Decoding unpadding input A failed");
|
||||
ret = dec.decode(srcAA);
|
||||
if (ret[0] != 'A' && ret[1] != 'A')
|
||||
throw new RuntimeException("Decoding unpadding input AA failed");
|
||||
ret = new byte[10];
|
||||
if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 &&
|
||||
ret[0] != 'A')
|
||||
throw new RuntimeException("Decoding unpadding input A from stream failed");
|
||||
if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 &&
|
||||
ret[0] != 'A' && ret[1] != 'A')
|
||||
throw new RuntimeException("Decoding unpadding input AA from stream failed");
|
||||
}
|
||||
|
||||
// single-non-base64-char should be ignored for mime decoding, but
|
||||
// iae for basic decoding
|
||||
private static void testSingleNonBase64MimeDec() throws Throwable {
|
||||
for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) {
|
||||
if (Base64.getMimeDecoder().decode(nonBase64).length != 0) {
|
||||
throw new RuntimeException("non-base64 char is not ignored");
|
||||
}
|
||||
try {
|
||||
Base64.getDecoder().decode(nonBase64);
|
||||
throw new RuntimeException("No IAE for single non-base64 char");
|
||||
} catch (IllegalArgumentException iae) {}
|
||||
}
|
||||
}
|
||||
|
||||
private static final void testEncode(Base64.Encoder enc, ByteBuffer bin, byte[] expected)
|
||||
throws Throwable {
|
||||
|
||||
ByteBuffer bout = enc.encode(bin);
|
||||
byte[] buf = new byte[bout.remaining()];
|
||||
bout.get(buf);
|
||||
if (bin.hasRemaining()) {
|
||||
throw new RuntimeException(
|
||||
"Base64 enc.encode(ByteBuffer) failed!");
|
||||
}
|
||||
checkEqual(buf, expected, "Base64 enc.encode(bf, bf) failed!");
|
||||
}
|
||||
|
||||
private static final void testDecode(Base64.Decoder dec, ByteBuffer bin, byte[] expected)
|
||||
throws Throwable {
|
||||
|
||||
ByteBuffer bout = dec.decode(bin);
|
||||
byte[] buf = new byte[bout.remaining()];
|
||||
bout.get(buf);
|
||||
checkEqual(buf, expected, "Base64 dec.decode(bf) failed!");
|
||||
}
|
||||
|
||||
private static final void checkEqual(int v1, int v2, String msg)
|
||||
throws Throwable {
|
||||
if (v1 != v2) {
|
||||
System.out.printf(" v1=%d%n", v1);
|
||||
System.out.printf(" v2=%d%n", v2);
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private static final void checkEqual(byte[] r1, byte[] r2, String msg)
|
||||
throws Throwable {
|
||||
if (!Arrays.equals(r1, r2)) {
|
||||
System.out.printf(" r1[%d]=[%s]%n", r1.length, new String(r1));
|
||||
System.out.printf(" r2[%d]=[%s]%n", r2.length, new String(r2));
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// remove line feeds,
|
||||
private static final byte[] normalize(byte[] src) {
|
||||
int n = 0;
|
||||
boolean hasUrl = false;
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
if (src[i] == '\r' || src[i] == '\n')
|
||||
n++;
|
||||
if (src[i] == '-' || src[i] == '_')
|
||||
hasUrl = true;
|
||||
}
|
||||
if (n == 0 && hasUrl == false)
|
||||
return src;
|
||||
byte[] ret = new byte[src.length - n];
|
||||
int j = 0;
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
if (src[i] == '-')
|
||||
ret[j++] = '+';
|
||||
else if (src[i] == '_')
|
||||
ret[j++] = '/';
|
||||
else if (src[i] != '\r' && src[i] != '\n')
|
||||
ret[j++] = src[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void testEncoderKeepsSilence(Base64.Encoder enc)
|
||||
throws Throwable {
|
||||
List<Integer> vals = new ArrayList<>(List.of(Integer.MIN_VALUE,
|
||||
Integer.MIN_VALUE + 1, -1111, -2, -1, 0, 1, 2, 3, 1111,
|
||||
Integer.MAX_VALUE - 1, Integer.MAX_VALUE));
|
||||
vals.addAll(List.of(rnd.nextInt(), rnd.nextInt(), rnd.nextInt(),
|
||||
rnd.nextInt()));
|
||||
byte[] buf = new byte[] {1, 0, 91};
|
||||
for (int off : vals) {
|
||||
for (int len : vals) {
|
||||
if (off >= 0 && len >= 0 && off <= buf.length - len) {
|
||||
// valid args, skip them
|
||||
continue;
|
||||
}
|
||||
// invalid args, test them
|
||||
System.out.println("testing off=" + off + ", len=" + len);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
|
||||
try (OutputStream os = enc.wrap(baos)) {
|
||||
os.write(buf, off, len);
|
||||
throw new RuntimeException("Expected IOOBEx was not thrown");
|
||||
} catch (IndexOutOfBoundsException expected) {
|
||||
}
|
||||
if (baos.size() > 0)
|
||||
throw new RuntimeException("No output was expected, but got "
|
||||
+ baos.size() + " bytes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testDecoderKeepsAbstinence(Base64.Decoder dec)
|
||||
throws Throwable {
|
||||
List<Integer> vals = new ArrayList<>(List.of(Integer.MIN_VALUE,
|
||||
Integer.MIN_VALUE + 1, -1111, -2, -1, 0, 1, 2, 3, 1111,
|
||||
Integer.MAX_VALUE - 1, Integer.MAX_VALUE));
|
||||
vals.addAll(List.of(rnd.nextInt(), rnd.nextInt(), rnd.nextInt(),
|
||||
rnd.nextInt()));
|
||||
byte[] buf = new byte[3];
|
||||
for (int off : vals) {
|
||||
for (int len : vals) {
|
||||
if (off >= 0 && len >= 0 && off <= buf.length - len) {
|
||||
// valid args, skip them
|
||||
continue;
|
||||
}
|
||||
// invalid args, test them
|
||||
System.out.println("testing off=" + off + ", len=" + len);
|
||||
|
||||
String input = "AAAAAAAAAAAAAAAAAAAAAA";
|
||||
ByteArrayInputStream bais =
|
||||
new ByteArrayInputStream(input.getBytes("Latin1"));
|
||||
try (InputStream is = dec.wrap(bais)) {
|
||||
is.read(buf, off, len);
|
||||
throw new RuntimeException("Expected IOOBEx was not thrown");
|
||||
} catch (IndexOutOfBoundsException expected) {
|
||||
}
|
||||
if (bais.available() != input.length())
|
||||
throw new RuntimeException("No input should be consumed, "
|
||||
+ "but consumed " + (input.length() - bais.available())
|
||||
+ " bytes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testJDK_8222187() throws Throwable {
|
||||
byte[] orig = "12345678".getBytes("US-ASCII");
|
||||
byte[] encoded = Base64.getEncoder().encode(orig);
|
||||
// decode using different buffer sizes, up to a longer one than needed
|
||||
for (int bufferSize = 1; bufferSize <= encoded.length + 1; bufferSize++) {
|
||||
try (
|
||||
InputStream in = Base64.getDecoder().wrap(
|
||||
new ByteArrayInputStream(encoded));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
) {
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int read;
|
||||
while ((read = in.read(buffer, 0, bufferSize)) >= 0) {
|
||||
baos.write(buffer, 0, read);
|
||||
}
|
||||
// compare result, output info if lengths do not match
|
||||
byte[] decoded = baos.toByteArray();
|
||||
checkEqual(decoded, orig, "Base64 stream decoding failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
181
test/jdk/java/util/Base64/TestBase64Golden.java
Normal file
181
test/jdk/java/util/Base64/TestBase64Golden.java
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4235519
|
||||
* @author Eric Wang <yiming.wang@oracle.com>
|
||||
* @summary tests java.util.Base64
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Base64;
|
||||
import java.util.Base64.Decoder;
|
||||
import java.util.Base64.Encoder;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
public class TestBase64Golden {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test0(Base64Type.BASIC, Base64.getEncoder(), Base64.getDecoder(),
|
||||
"plain.txt", "baseEncode.txt");
|
||||
|
||||
test0(Base64Type.URLSAFE, Base64.getUrlEncoder(), Base64.getUrlDecoder(),
|
||||
"plain.txt", "urlEncode.txt");
|
||||
|
||||
test0(Base64Type.MIME, Base64.getMimeEncoder(), Base64.getMimeDecoder(),
|
||||
"plain.txt", "mimeEncode.txt");
|
||||
test1();
|
||||
}
|
||||
|
||||
public static void test0(Base64Type type, Encoder encoder, Decoder decoder,
|
||||
String srcFile, String encodedFile) throws Exception {
|
||||
|
||||
String[] srcLns = Files.readAllLines(Paths.get(SRCDIR, srcFile), DEF_CHARSET)
|
||||
.toArray(new String[0]);
|
||||
String[] encodedLns = Files.readAllLines(Paths.get(SRCDIR, encodedFile),
|
||||
DEF_CHARSET)
|
||||
.toArray(new String[0]);
|
||||
int lns = 0;
|
||||
for (String srcStr : srcLns) {
|
||||
String encodedStr = null;
|
||||
if (type != Base64Type.MIME) {
|
||||
encodedStr = encodedLns[lns++];
|
||||
} else {
|
||||
while (lns < encodedLns.length) {
|
||||
String s = encodedLns[lns++];
|
||||
if (s.length() == 0)
|
||||
break;
|
||||
if (encodedStr != null) {
|
||||
encodedStr += DEFAULT_CRLF + s;
|
||||
} else {
|
||||
encodedStr = s;
|
||||
}
|
||||
}
|
||||
if (encodedStr == null && srcStr.length() == 0) {
|
||||
encodedStr = "";
|
||||
}
|
||||
}
|
||||
System.out.printf("%n src[%d]: %s%n", srcStr.length(), srcStr);
|
||||
System.out.printf("encoded[%d]: %s%n", encodedStr.length(), encodedStr);
|
||||
|
||||
byte[] srcArr = srcStr.getBytes(DEF_CHARSET);
|
||||
byte[] encodedArr = encodedStr.getBytes(DEF_CHARSET);
|
||||
|
||||
ByteBuffer srcBuf = ByteBuffer.wrap(srcArr);
|
||||
ByteBuffer encodedBuf = ByteBuffer.wrap(encodedArr);
|
||||
byte[] resArr = new byte[encodedArr.length];
|
||||
|
||||
// test int encode(byte[], byte[])
|
||||
int len = encoder.encode(srcArr, resArr);
|
||||
assertEqual(len, encodedArr.length);
|
||||
assertEqual(resArr, encodedArr);
|
||||
|
||||
// test byte[] encode(byte[])
|
||||
resArr = encoder.encode(srcArr);
|
||||
assertEqual(resArr, encodedArr);
|
||||
|
||||
// test ByteBuffer encode(ByteBuffer)
|
||||
int limit = srcBuf.limit();
|
||||
ByteBuffer resBuf = encoder.encode(srcBuf);
|
||||
assertEqual(srcBuf.position(), limit);
|
||||
assertEqual(srcBuf.limit(), limit);
|
||||
assertEqual(resBuf, encodedBuf);
|
||||
srcBuf.rewind(); // reset for next test
|
||||
|
||||
// test String encodeToString(byte[])
|
||||
String resEncodeStr = encoder.encodeToString(srcArr);
|
||||
assertEqual(resEncodeStr, encodedStr);
|
||||
|
||||
// test int decode(byte[], byte[])
|
||||
resArr = new byte[srcArr.length];
|
||||
len = decoder.decode(encodedArr, resArr);
|
||||
assertEqual(len, srcArr.length);
|
||||
assertEqual(resArr, srcArr);
|
||||
|
||||
// test byte[] decode(byte[])
|
||||
resArr = decoder.decode(encodedArr);
|
||||
assertEqual(resArr, srcArr);
|
||||
|
||||
// test ByteBuffer decode(ByteBuffer)
|
||||
limit = encodedBuf.limit();
|
||||
resBuf = decoder.decode(encodedBuf);
|
||||
assertEqual(encodedBuf.position(), limit);
|
||||
assertEqual(encodedBuf.limit(), limit);
|
||||
assertEqual(resBuf, srcBuf);
|
||||
encodedBuf.rewind(); // reset for next test
|
||||
|
||||
// test byte[] decode(String)
|
||||
resArr = decoder.decode(encodedStr);
|
||||
assertEqual(resArr, srcArr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void test1() throws Exception {
|
||||
byte[] src = new byte[] {
|
||||
46, -97, -35, -44, 127, -60, -39, -4, -112, 34, -57, 47, -14, 67,
|
||||
40, 18, 90, -59, 68, 112, 23, 121, -91, 94, 35, 49, 104, 17, 30,
|
||||
-80, -104, -3, -53, 27, 38, -72, -47, 113, -52, 18, 5, -126 };
|
||||
Encoder encoder = Base64.getMimeEncoder(49, new byte[] { 0x7e });
|
||||
byte[] encoded = encoder.encode(src);
|
||||
Decoder decoder = Base64.getMimeDecoder();
|
||||
byte[] decoded = decoder.decode(encoded);
|
||||
if (!Objects.deepEquals(src, decoded)) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
// helper
|
||||
enum Base64Type {
|
||||
BASIC, URLSAFE, MIME
|
||||
}
|
||||
|
||||
private static final String SRCDIR = System.getProperty("test.src", ".");
|
||||
private static final Charset DEF_CHARSET = StandardCharsets.US_ASCII;
|
||||
private static final String DEF_EXCEPTION_MSG =
|
||||
"Assertion failed! The result is not same as expected";
|
||||
private static final String DEFAULT_CRLF = "\r\n";
|
||||
|
||||
private static void assertEqual(Object result, Object expect) {
|
||||
if (!Objects.deepEquals(result, expect)) {
|
||||
String resultStr = result.toString();
|
||||
String expectStr = expect.toString();
|
||||
if (result instanceof byte[]) {
|
||||
resultStr = new String((byte[]) result, DEF_CHARSET);
|
||||
}
|
||||
if (expect instanceof byte[]) {
|
||||
expectStr = new String((byte[]) expect, DEF_CHARSET);
|
||||
}
|
||||
throw new RuntimeException(DEF_EXCEPTION_MSG +
|
||||
" result: " + resultStr + " expected: " + expectStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
117
test/jdk/java/util/Base64/TestEncodingDecodingLength.java
Normal file
117
test/jdk/java/util/Base64/TestEncodingDecodingLength.java
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 jdk.internal.util.ArraysSupport;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Base64;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8210583 8217969 8218265 8295153
|
||||
* @summary White-box test that effectively checks Base64.Encoder.encode and
|
||||
* Base64.Decoder.decode behavior with large, (Integer.MAX_VALUE) sized
|
||||
* input array/buffer. Tests the private methods "encodedOutLength" and
|
||||
* "decodedOutLength".
|
||||
* @modules java.base/jdk.internal.util
|
||||
* @run junit/othervm --add-opens java.base/java.util=ALL-UNNAMED TestEncodingDecodingLength
|
||||
*/
|
||||
|
||||
// We perform a white-box test due to the heavy memory usage that testing
|
||||
// the public API would require which has shown to cause intermittent issues
|
||||
public class TestEncodingDecodingLength {
|
||||
|
||||
// A value large enough to test the desired memory conditions in encode and decode
|
||||
private static final int LARGE_MEM_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
|
||||
private static final Base64.Decoder DECODER = Base64.getDecoder();
|
||||
private static final Base64.Encoder ENCODER = Base64.getEncoder();
|
||||
|
||||
// Effectively tests that encode(byte[] src, byte[] dst) throws an
|
||||
// IllegalArgumentException with array sized near Integer.MAX_VALUE. All the
|
||||
// encode() methods call encodedOutLength(), which is where the OOME is expected
|
||||
@Test
|
||||
public void largeEncodeIAETest() throws IllegalAccessException,
|
||||
InvocationTargetException, NoSuchMethodException {
|
||||
Method m = getMethod(ENCODER,
|
||||
"encodedOutLength", int.class, boolean.class);
|
||||
// When throwOOME param is false, encodedOutLength should return -1 in
|
||||
// this situation, which encode() uses to throw IAE
|
||||
assertEquals(-1, m.invoke(ENCODER, LARGE_MEM_SIZE, false));
|
||||
}
|
||||
|
||||
// Effectively tests that the overloaded encode() and encodeToString() methods
|
||||
// throw OutOfMemoryError with array/buffer sized near Integer.MAX_VALUE
|
||||
@Test
|
||||
public void largeEncodeOOMETest() throws IllegalAccessException, NoSuchMethodException {
|
||||
Method m = getMethod(ENCODER,
|
||||
"encodedOutLength", int.class, boolean.class);
|
||||
try {
|
||||
m.invoke(ENCODER, LARGE_MEM_SIZE, true);
|
||||
} catch (InvocationTargetException ex) {
|
||||
Throwable rootEx = ex.getCause();
|
||||
assertEquals(OutOfMemoryError.class, rootEx.getClass(),
|
||||
"OOME should be thrown with Integer.MAX_VALUE input");
|
||||
assertEquals("Encoded size is too large", rootEx.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Effectively tests that the overloaded decode() methods do not throw
|
||||
// OOME nor NASE with array/buffer sized near Integer.MAX_VALUE All the decode
|
||||
// methods call decodedOutLength(), which is where the previously thrown
|
||||
// OOME or NASE would occur at.
|
||||
@Test
|
||||
public void largeDecodeTest() throws IllegalAccessException, NoSuchMethodException {
|
||||
Method m = getMethod(DECODER,
|
||||
"decodedOutLength", byte[].class, int.class, int.class);
|
||||
byte[] src = {1};
|
||||
try {
|
||||
/*
|
||||
decodedOutLength() takes the src array, position, and limit as params.
|
||||
The src array will be indexed at limit-1 to search for padding.
|
||||
To avoid passing an array with Integer.MAX_VALUE memory allocated, we
|
||||
set position param to be -size. Since the initial length
|
||||
is calculated as limit - position. This mocks the potential overflow
|
||||
calculation and still allows the array to be indexed without an AIOBE.
|
||||
*/
|
||||
m.invoke(DECODER, src, -LARGE_MEM_SIZE + 1, 1);
|
||||
} catch (InvocationTargetException ex) {
|
||||
// 8210583 - decode no longer throws NASE
|
||||
// 8217969 - decode no longer throws OOME
|
||||
fail("Decode threw an unexpected exception with " +
|
||||
"Integer.MAX_VALUE sized input: " + ex.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
// Utility to get the private visibility method
|
||||
private static Method getMethod(Object obj, String methodName, Class<?>... params)
|
||||
throws NoSuchMethodException {
|
||||
Method m = obj.getClass().getDeclaredMethod(methodName, params);
|
||||
m.setAccessible(true);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
183
test/jdk/java/util/Base64/baseEncode.txt
Normal file
183
test/jdk/java/util/Base64/baseEncode.txt
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFyYWN0ZXJzIGF+eiBBflosIDB+OSBhbmQgYWxsIHN5bWJvbHMs
|
||||
SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUgZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh
|
||||
dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDFd
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQgMTU5MCwgd2hpY2g=
|
||||
ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBhcHBlbmRpeCBpbiBSRkM=
|
||||
ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2ZXJzaW9ucy4=
|
||||
|
||||
VGFibGUgb2YgQ29udGVudHM=
|
||||
|
||||
ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDM=
|
||||
ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAuLi4uICAgIDU=
|
||||
ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg=
|
||||
ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg=
|
||||
ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMTA=
|
||||
ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uICAgMTQ=
|
||||
ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjY=
|
||||
ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjg=
|
||||
ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjk=
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDdd
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
My4gIE1JTUUgSGVhZGVyIEZpZWxkcw==
|
||||
|
||||
ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhhdCBhcmUgdXNlZCB0bw==
|
||||
ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBmaWVsZHMgb2NjdXIgaW4=
|
||||
ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg==
|
||||
|
||||
ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu
|
||||
|
||||
ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA==
|
||||
ICAgICAgICAgIGNvbnN0cnVjdC4=
|
||||
|
||||
ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9sbG93czo=
|
||||
|
||||
ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM=
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY=
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu
|
||||
|
||||
ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg=
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5lZA==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu
|
||||
|
||||
ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMgd2lsbCBiZQ==
|
||||
ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMTFd
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk
|
||||
|
||||
ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5cGUgaGVhZGVyIGZpZWxk
|
||||
ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg==
|
||||
|
||||
ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl
|
||||
ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik=
|
||||
ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ==
|
||||
ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu
|
||||
|
||||
ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ==
|
||||
|
||||
ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVvIiAv
|
||||
ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4=
|
||||
|
||||
ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lvbi10b2tlbg==
|
||||
|
||||
ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4=
|
||||
|
||||
ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh
|
||||
ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk
|
||||
ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg==
|
||||
|
||||
ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2VkLCB3aXRo
|
||||
ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2VuPg==
|
||||
|
||||
ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4=
|
||||
|
||||
ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBUb2tlbnM=
|
||||
ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGggSUFOQQ==
|
||||
ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg==
|
||||
|
||||
ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ==
|
||||
|
||||
ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4=
|
||||
ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz
|
||||
ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4=
|
||||
|
||||
ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc=
|
||||
|
||||
ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw=
|
||||
ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM+
|
||||
|
||||
ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI+IiAvICJAIiAv
|
||||
ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg==
|
||||
ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI/IiAvICI9Ig==
|
||||
ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA==
|
||||
ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz
|
||||
|
||||
ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0
|
||||
|
||||
ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlzbQ==
|
||||
|
||||
ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ==
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ==
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ==
|
||||
ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk=
|
||||
|
||||
ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAiRSIgLyAiRiIp
|
||||
ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcsID0s
|
||||
ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5kIGlz
|
||||
ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVkIGlu
|
||||
ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4=
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFjdGVyIG9uIGE=
|
||||
ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAoInNvZnQiKQ==
|
||||
ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4=
|
||||
|
||||
ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29kZWQgbGluZSB0aGF0
|
||||
ICAgc2F5czo=
|
||||
|
||||
ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku
|
||||
|
||||
ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29kaW5nLCBhczo=
|
||||
|
||||
ICAgICBOb3cncyB0aGUgdGltZSA9
|
||||
ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0=
|
||||
ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg==
|
||||
|
||||
ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFzIGl0c2VsZiBpbiB0aGU=
|
||||
ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVuY2Fwc3VsYXRpbmcgYQ==
|
||||
ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRpcGFydCBlbnRpdGllcyw=
|
||||
ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIgYW55d2hlcmUgaW4gdGhl
|
||||
ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFyeSB0aGF0IGluY2x1ZGVz
|
||||
ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBlYXIgaW4gYQ==
|
||||
ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFydCBtZXNzYWdlcyBpbg==
|
||||
ICAgUkZDIDIwNDYuKQ==
|
||||
|
||||
ICAgICAhIiMkQFtcXV5ge3x9fiU=
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMjRd
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0
|
||||
|
||||
ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1ZSBFbmNvZGluZw==
|
||||
ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1MSB6
|
||||
ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1MiAw
|
||||
ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1MyAx
|
||||
ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1NCAy
|
||||
ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1NSAz
|
||||
ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1NiA0
|
||||
ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1NyA1
|
||||
ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1OCA2
|
||||
ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1OSA3
|
||||
ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2MCA4
|
||||
ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2MSA5
|
||||
ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2MiAr
|
||||
ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2MyAv
|
||||
ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY=
|
||||
ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFkKSA9
|
||||
ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg=
|
||||
ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk=
|
||||
391
test/jdk/java/util/Base64/mimeEncode.txt
Normal file
391
test/jdk/java/util/Base64/mimeEncode.txt
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFy
|
||||
YWN0ZXJzIGF+eiBBflosIDB+OSBhbmQgYWxsIHN5bWJvbHMs
|
||||
|
||||
SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUg
|
||||
ZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh
|
||||
|
||||
dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7
|
||||
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg
|
||||
ICAgICAgIFtQYWdlIDFd
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg
|
||||
ICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
|
||||
ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQg
|
||||
MTU5MCwgd2hpY2g=
|
||||
|
||||
ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBh
|
||||
cHBlbmRpeCBpbiBSRkM=
|
||||
|
||||
ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2
|
||||
ZXJzaW9ucy4=
|
||||
|
||||
|
||||
VGFibGUgb2YgQ29udGVudHM=
|
||||
|
||||
|
||||
ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgIDM=
|
||||
|
||||
ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAu
|
||||
Li4uICAgIDU=
|
||||
|
||||
ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgIDg=
|
||||
|
||||
ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgIDg=
|
||||
|
||||
ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMTA=
|
||||
|
||||
ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMTQ=
|
||||
|
||||
ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMjY=
|
||||
|
||||
ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMjc=
|
||||
|
||||
ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMjc=
|
||||
|
||||
ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMjc=
|
||||
|
||||
ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMjc=
|
||||
|
||||
ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMjg=
|
||||
|
||||
ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
|
||||
Li4uICAgMjk=
|
||||
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg
|
||||
ICAgICAgIFtQYWdlIDdd
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg
|
||||
ICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
|
||||
My4gIE1JTUUgSGVhZGVyIEZpZWxkcw==
|
||||
|
||||
|
||||
ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhh
|
||||
dCBhcmUgdXNlZCB0bw==
|
||||
|
||||
ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBm
|
||||
aWVsZHMgb2NjdXIgaW4=
|
||||
|
||||
ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg==
|
||||
|
||||
|
||||
ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu
|
||||
|
||||
|
||||
ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA==
|
||||
|
||||
ICAgICAgICAgIGNvbnN0cnVjdC4=
|
||||
|
||||
|
||||
ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9s
|
||||
bG93czo=
|
||||
|
||||
|
||||
ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM=
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY=
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9y
|
||||
ZWQu
|
||||
|
||||
|
||||
ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg=
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5l
|
||||
ZA==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu
|
||||
|
||||
|
||||
ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMg
|
||||
d2lsbCBiZQ==
|
||||
|
||||
ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu
|
||||
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg
|
||||
ICAgICAgW1BhZ2UgMTFd
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg
|
||||
ICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
|
||||
NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk
|
||||
|
||||
|
||||
ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5
|
||||
cGUgaGVhZGVyIGZpZWxk
|
||||
|
||||
ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg==
|
||||
|
||||
|
||||
ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl
|
||||
|
||||
ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik=
|
||||
|
||||
ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ==
|
||||
|
||||
ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu
|
||||
|
||||
|
||||
ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ==
|
||||
|
||||
|
||||
ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVv
|
||||
IiAv
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4=
|
||||
|
||||
|
||||
ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lv
|
||||
bi10b2tlbg==
|
||||
|
||||
|
||||
ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4=
|
||||
|
||||
|
||||
ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg==
|
||||
|
||||
|
||||
ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2Vk
|
||||
LCB3aXRo
|
||||
|
||||
ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2Vu
|
||||
Pg==
|
||||
|
||||
|
||||
ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4=
|
||||
|
||||
|
||||
ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBU
|
||||
b2tlbnM=
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGgg
|
||||
SUFOQQ==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg==
|
||||
|
||||
|
||||
ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ==
|
||||
|
||||
|
||||
ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4=
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4=
|
||||
|
||||
|
||||
ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc=
|
||||
|
||||
|
||||
ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw=
|
||||
|
||||
ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM+
|
||||
|
||||
|
||||
ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI+IiAvICJAIiAv
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI/IiAvICI9Ig==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz
|
||||
|
||||
|
||||
ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0
|
||||
|
||||
|
||||
ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlz
|
||||
bQ==
|
||||
|
||||
|
||||
ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ==
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk=
|
||||
|
||||
|
||||
ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAi
|
||||
RSIgLyAiRiIp
|
||||
|
||||
ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcs
|
||||
ID0s
|
||||
|
||||
ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5k
|
||||
IGlz
|
||||
|
||||
ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVk
|
||||
IGlu
|
||||
|
||||
ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4=
|
||||
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg
|
||||
ICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
|
||||
ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFj
|
||||
dGVyIG9uIGE=
|
||||
|
||||
ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAo
|
||||
InNvZnQiKQ==
|
||||
|
||||
ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4=
|
||||
|
||||
|
||||
ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29k
|
||||
ZWQgbGluZSB0aGF0
|
||||
|
||||
ICAgc2F5czo=
|
||||
|
||||
|
||||
ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRo
|
||||
ZWlyIGNvdW50cnku
|
||||
|
||||
|
||||
ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29k
|
||||
aW5nLCBhczo=
|
||||
|
||||
|
||||
ICAgICBOb3cncyB0aGUgdGltZSA9
|
||||
|
||||
ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0=
|
||||
|
||||
ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg==
|
||||
|
||||
|
||||
ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFz
|
||||
IGl0c2VsZiBpbiB0aGU=
|
||||
|
||||
ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVu
|
||||
Y2Fwc3VsYXRpbmcgYQ==
|
||||
|
||||
ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRp
|
||||
cGFydCBlbnRpdGllcyw=
|
||||
|
||||
ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIg
|
||||
YW55d2hlcmUgaW4gdGhl
|
||||
|
||||
ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFy
|
||||
eSB0aGF0IGluY2x1ZGVz
|
||||
|
||||
ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBl
|
||||
YXIgaW4gYQ==
|
||||
|
||||
ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFy
|
||||
dCBtZXNzYWdlcyBpbg==
|
||||
|
||||
ICAgUkZDIDIwNDYuKQ==
|
||||
|
||||
|
||||
ICAgICAhIiMkQFtcXV5ge3x9fiU=
|
||||
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg
|
||||
ICAgICAgW1BhZ2UgMjRd
|
||||
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg
|
||||
ICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0
|
||||
|
||||
|
||||
ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1
|
||||
ZSBFbmNvZGluZw==
|
||||
|
||||
ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1
|
||||
MSB6
|
||||
|
||||
ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1
|
||||
MiAw
|
||||
|
||||
ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1
|
||||
MyAx
|
||||
|
||||
ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1
|
||||
NCAy
|
||||
|
||||
ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1
|
||||
NSAz
|
||||
|
||||
ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1
|
||||
NiA0
|
||||
|
||||
ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1
|
||||
NyA1
|
||||
|
||||
ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1
|
||||
OCA2
|
||||
|
||||
ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1
|
||||
OSA3
|
||||
|
||||
ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2
|
||||
MCA4
|
||||
|
||||
ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2
|
||||
MSA5
|
||||
|
||||
ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2
|
||||
MiAr
|
||||
|
||||
ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2
|
||||
MyAv
|
||||
|
||||
ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY=
|
||||
|
||||
ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFk
|
||||
KSA9
|
||||
|
||||
ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg=
|
||||
|
||||
ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk=
|
||||
|
||||
183
test/jdk/java/util/Base64/plain.txt
Normal file
183
test/jdk/java/util/Base64/plain.txt
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
This test data is part of rfc2045 which includes all characters a~z A~Z, 0~9 and all symbols,
|
||||
It is used to test java.util.Base64.Encoder, and will be encoded by org.apache.commons.codec.binary.Base64.java
|
||||
to test java.util.Base64.Decoder;
|
||||
|
||||
Freed & Borenstein Standards Track [Page 1]
|
||||
RFC 2045 Internet Message Bodies November 1996
|
||||
|
||||
These documents are revisions of RFCs 1521, 1522, and 1590, which
|
||||
themselves were revisions of RFCs 1341 and 1342. An appendix in RFC
|
||||
2049 describes differences and changes from previous versions.
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ......................................... 3
|
||||
2. Definitions, Conventions, and Generic BNF Grammar .... 5
|
||||
3. MIME Header Fields ................................... 8
|
||||
4. MIME-Version Header Field ............................ 8
|
||||
5. Content-Type Header Field ............................ 10
|
||||
6. Content-Transfer-Encoding Header Field ............... 14
|
||||
7. Content-ID Header Field .............................. 26
|
||||
8. Content-Description Header Field ..................... 27
|
||||
9. Additional MIME Header Fields ........................ 27
|
||||
10. Summary ............................................. 27
|
||||
11. Security Considerations ............................. 27
|
||||
12. Authors' Addresses .................................. 28
|
||||
A. Collected Grammar .................................... 29
|
||||
|
||||
Freed & Borenstein Standards Track [Page 7]
|
||||
RFC 2045 Internet Message Bodies November 1996
|
||||
|
||||
3. MIME Header Fields
|
||||
|
||||
MIME defines a number of new RFC 822 header fields that are used to
|
||||
describe the content of a MIME entity. These header fields occur in
|
||||
at least two contexts:
|
||||
|
||||
(1) As part of a regular RFC 822 message header.
|
||||
|
||||
(2) In a MIME body part header within a multipart
|
||||
construct.
|
||||
|
||||
The formal definition of these header fields is as follows:
|
||||
|
||||
MIME-message-headers := entity-headers
|
||||
fields
|
||||
version CRLF
|
||||
; The ordering of the header
|
||||
; fields implied by this BNF
|
||||
; definition should be ignored.
|
||||
|
||||
MIME-part-headers := entity-headers
|
||||
[ fields ]
|
||||
; Any field not beginning with
|
||||
; "content-" can have no defined
|
||||
; meaning and may be ignored.
|
||||
; The ordering of the header
|
||||
; fields implied by this BNF
|
||||
; definition should be ignored.
|
||||
|
||||
The syntax of the various specific MIME header fields will be
|
||||
described in the following sections.
|
||||
|
||||
Freed & Borenstein Standards Track [Page 11]
|
||||
RFC 2045 Internet Message Bodies November 1996
|
||||
|
||||
5.1. Syntax of the Content-Type Header Field
|
||||
|
||||
In the Augmented BNF notation of RFC 822, a Content-Type header field
|
||||
value is defined as follows:
|
||||
|
||||
content := "Content-Type" ":" type "/" subtype
|
||||
*(";" parameter)
|
||||
; Matching of media type and subtype
|
||||
; is ALWAYS case-insensitive.
|
||||
|
||||
type := discrete-type / composite-type
|
||||
|
||||
discrete-type := "text" / "image" / "audio" / "video" /
|
||||
"application" / extension-token
|
||||
|
||||
composite-type := "message" / "multipart" / extension-token
|
||||
|
||||
extension-token := ietf-token / x-token
|
||||
|
||||
ietf-token := <An extension token defined by a
|
||||
standards-track RFC and registered
|
||||
with IANA.>
|
||||
|
||||
x-token := <The two characters "X-" or "x-" followed, with
|
||||
no intervening white space, by any token>
|
||||
|
||||
subtype := extension-token / iana-token
|
||||
|
||||
iana-token := <A publicly-defined extension token. Tokens
|
||||
of this form must be registered with IANA
|
||||
as specified in RFC 2048.>
|
||||
|
||||
parameter := attribute "=" value
|
||||
|
||||
attribute := token
|
||||
; Matching of attributes
|
||||
; is ALWAYS case-insensitive.
|
||||
|
||||
value := token / quoted-string
|
||||
|
||||
token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
|
||||
or tspecials>
|
||||
|
||||
tspecials := "(" / ")" / "<" / ">" / "@" /
|
||||
"," / ";" / ":" / "\" / <">
|
||||
"/" / "[" / "]" / "?" / "="
|
||||
; Must be in quoted-string,
|
||||
; to use within parameter values
|
||||
|
||||
description := "Content-Description" ":" *text
|
||||
|
||||
encoding := "Content-Transfer-Encoding" ":" mechanism
|
||||
|
||||
entity-headers := [ content CRLF ]
|
||||
[ encoding CRLF ]
|
||||
[ id CRLF ]
|
||||
[ description CRLF ]
|
||||
*( MIME-extension-field CRLF )
|
||||
|
||||
hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F")
|
||||
; Octet must be used for characters > 127, =,
|
||||
; SPACEs or TABs at the ends of lines, and is
|
||||
; recommended for any character not listed in
|
||||
; RFC 2049 as "mail-safe".
|
||||
|
||||
RFC 2045 Internet Message Bodies November 1996
|
||||
|
||||
must be used. An equal sign as the last character on a
|
||||
encoded line indicates such a non-significant ("soft")
|
||||
line break in the encoded text.
|
||||
|
||||
Thus if the "raw" form of the line is a single unencoded line that
|
||||
says:
|
||||
|
||||
Now's the time for all folk to come to the aid of their country.
|
||||
|
||||
This can be represented, in the Quoted-Printable encoding, as:
|
||||
|
||||
Now's the time =
|
||||
for all folk to come=
|
||||
to the aid of their country.
|
||||
|
||||
Since the hyphen character ("-") may be represented as itself in the
|
||||
Quoted-Printable encoding, care must be taken, when encapsulating a
|
||||
quoted-printable encoded body inside one or more multipart entities,
|
||||
to ensure that the boundary delimiter does not appear anywhere in the
|
||||
encoded body. (A good strategy is to choose a boundary that includes
|
||||
a character sequence such as "=_" which can never appear in a
|
||||
quoted-printable body. See the definition of multipart messages in
|
||||
RFC 2046.)
|
||||
|
||||
!"#$@[\]^`{|}~%
|
||||
|
||||
Freed & Borenstein Standards Track [Page 24]
|
||||
|
||||
RFC 2045 Internet Message Bodies November 1996
|
||||
|
||||
|
||||
Table 1: The Base64 Alphabet
|
||||
|
||||
Value Encoding Value Encoding Value Encoding Value Encoding
|
||||
0 A 17 R 34 i 51 z
|
||||
1 B 18 S 35 j 52 0
|
||||
2 C 19 T 36 k 53 1
|
||||
3 D 20 U 37 l 54 2
|
||||
4 E 21 V 38 m 55 3
|
||||
5 F 22 W 39 n 56 4
|
||||
6 G 23 X 40 o 57 5
|
||||
7 H 24 Y 41 p 58 6
|
||||
8 I 25 Z 42 q 59 7
|
||||
9 J 26 a 43 r 60 8
|
||||
10 K 27 b 44 s 61 9
|
||||
11 L 28 c 45 t 62 +
|
||||
12 M 29 d 46 u 63 /
|
||||
13 N 30 e 47 v
|
||||
14 O 31 f 48 w (pad) =
|
||||
15 P 32 g 49 x
|
||||
16 Q 33 h 50 y
|
||||
183
test/jdk/java/util/Base64/urlEncode.txt
Normal file
183
test/jdk/java/util/Base64/urlEncode.txt
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFyYWN0ZXJzIGF-eiBBflosIDB-OSBhbmQgYWxsIHN5bWJvbHMs
|
||||
SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUgZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh
|
||||
dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDFd
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQgMTU5MCwgd2hpY2g=
|
||||
ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBhcHBlbmRpeCBpbiBSRkM=
|
||||
ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2ZXJzaW9ucy4=
|
||||
|
||||
VGFibGUgb2YgQ29udGVudHM=
|
||||
|
||||
ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDM=
|
||||
ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAuLi4uICAgIDU=
|
||||
ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg=
|
||||
ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg=
|
||||
ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMTA=
|
||||
ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uICAgMTQ=
|
||||
ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjY=
|
||||
ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc=
|
||||
ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjg=
|
||||
ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjk=
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDdd
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
My4gIE1JTUUgSGVhZGVyIEZpZWxkcw==
|
||||
|
||||
ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhhdCBhcmUgdXNlZCB0bw==
|
||||
ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBmaWVsZHMgb2NjdXIgaW4=
|
||||
ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg==
|
||||
|
||||
ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu
|
||||
|
||||
ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA==
|
||||
ICAgICAgICAgIGNvbnN0cnVjdC4=
|
||||
|
||||
ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9sbG93czo=
|
||||
|
||||
ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM=
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY=
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu
|
||||
|
||||
ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg=
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5lZA==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg==
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu
|
||||
|
||||
ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMgd2lsbCBiZQ==
|
||||
ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMTFd
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk
|
||||
|
||||
ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5cGUgaGVhZGVyIGZpZWxk
|
||||
ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg==
|
||||
|
||||
ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl
|
||||
ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik=
|
||||
ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ==
|
||||
ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu
|
||||
|
||||
ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ==
|
||||
|
||||
ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVvIiAv
|
||||
ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4=
|
||||
|
||||
ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lvbi10b2tlbg==
|
||||
|
||||
ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4=
|
||||
|
||||
ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh
|
||||
ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk
|
||||
ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg==
|
||||
|
||||
ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2VkLCB3aXRo
|
||||
ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2VuPg==
|
||||
|
||||
ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4=
|
||||
|
||||
ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBUb2tlbnM=
|
||||
ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGggSUFOQQ==
|
||||
ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg==
|
||||
|
||||
ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ==
|
||||
|
||||
ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4=
|
||||
ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz
|
||||
ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4=
|
||||
|
||||
ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc=
|
||||
|
||||
ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw=
|
||||
ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM-
|
||||
|
||||
ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI-IiAvICJAIiAv
|
||||
ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg==
|
||||
ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI_IiAvICI9Ig==
|
||||
ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA==
|
||||
ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz
|
||||
|
||||
ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0
|
||||
|
||||
ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlzbQ==
|
||||
|
||||
ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ==
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ==
|
||||
ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ==
|
||||
ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk=
|
||||
|
||||
ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAiRSIgLyAiRiIp
|
||||
ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcsID0s
|
||||
ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5kIGlz
|
||||
ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVkIGlu
|
||||
ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4=
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFjdGVyIG9uIGE=
|
||||
ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAoInNvZnQiKQ==
|
||||
ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4=
|
||||
|
||||
ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29kZWQgbGluZSB0aGF0
|
||||
ICAgc2F5czo=
|
||||
|
||||
ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku
|
||||
|
||||
ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29kaW5nLCBhczo=
|
||||
|
||||
ICAgICBOb3cncyB0aGUgdGltZSA9
|
||||
ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0=
|
||||
ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg==
|
||||
|
||||
ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFzIGl0c2VsZiBpbiB0aGU=
|
||||
ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVuY2Fwc3VsYXRpbmcgYQ==
|
||||
ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRpcGFydCBlbnRpdGllcyw=
|
||||
ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIgYW55d2hlcmUgaW4gdGhl
|
||||
ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFyeSB0aGF0IGluY2x1ZGVz
|
||||
ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBlYXIgaW4gYQ==
|
||||
ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFydCBtZXNzYWdlcyBpbg==
|
||||
ICAgUkZDIDIwNDYuKQ==
|
||||
|
||||
ICAgICAhIiMkQFtcXV5ge3x9fiU=
|
||||
|
||||
RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMjRd
|
||||
|
||||
UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2
|
||||
|
||||
|
||||
ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0
|
||||
|
||||
ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1ZSBFbmNvZGluZw==
|
||||
ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1MSB6
|
||||
ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1MiAw
|
||||
ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1MyAx
|
||||
ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1NCAy
|
||||
ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1NSAz
|
||||
ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1NiA0
|
||||
ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1NyA1
|
||||
ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1OCA2
|
||||
ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1OSA3
|
||||
ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2MCA4
|
||||
ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2MSA5
|
||||
ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2MiAr
|
||||
ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2MyAv
|
||||
ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY=
|
||||
ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFkKSA9
|
||||
ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg=
|
||||
ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk=
|
||||
43
test/jdk/java/util/BitSet/And.java
Normal file
43
test/jdk/java/util/BitSet/And.java
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4201163
|
||||
* @summary test the BitSet.and() method
|
||||
*/
|
||||
import java.util.BitSet;
|
||||
|
||||
public final class And {
|
||||
public static void main(String[] args) throws Exception {
|
||||
BitSet a = new BitSet();
|
||||
BitSet b = new BitSet();
|
||||
|
||||
a.set(0);
|
||||
a.set(70);
|
||||
b.set(40);
|
||||
a.and(b);
|
||||
if (a.length() != 0)
|
||||
throw new RuntimeException("Incorrect length after and().");
|
||||
}
|
||||
}
|
||||
986
test/jdk/java/util/BitSet/BSMethods.java
Normal file
986
test/jdk/java/util/BitSet/BSMethods.java
Normal file
|
|
@ -0,0 +1,986 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4098239 4107540 4080736 4261102 4274710 4305272
|
||||
* 4979017 4979028 4979031 5030267 6222207 8040806
|
||||
* @summary Test the operation of the methods of BitSet class
|
||||
* @author Mike McCloskey, Martin Buchholz
|
||||
* @run main/othervm BSMethods
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This is a simple test class created to run tests on the BitSet class.
|
||||
*
|
||||
*/
|
||||
public class BSMethods {
|
||||
|
||||
private static Random generator = new Random();
|
||||
private static boolean failure = false;
|
||||
|
||||
private static void fail(String diagnostic) {
|
||||
new Error(diagnostic).printStackTrace();
|
||||
failure = true;
|
||||
}
|
||||
|
||||
private static void check(boolean condition) {
|
||||
check(condition, "something's fishy");
|
||||
}
|
||||
|
||||
private static void check(boolean condition, String diagnostic) {
|
||||
if (! condition)
|
||||
fail(diagnostic);
|
||||
}
|
||||
|
||||
private static void checkEmpty(BitSet s) {
|
||||
check(s.isEmpty(), "isEmpty");
|
||||
check(s.length() == 0, "length");
|
||||
check(s.cardinality() == 0, "cardinality");
|
||||
check(s.equals(new BitSet()) , "equals");
|
||||
check(s.equals(new BitSet(0)) , "equals");
|
||||
check(s.equals(new BitSet(127)), "equals");
|
||||
check(s.equals(new BitSet(128)), "equals");
|
||||
check(s.nextSetBit(0) == -1, "nextSetBit");
|
||||
check(s.nextSetBit(127) == -1, "nextSetBit");
|
||||
check(s.nextSetBit(128) == -1, "nextSetBit");
|
||||
check(s.nextClearBit(0) == 0, "nextClearBit");
|
||||
check(s.nextClearBit(127) == 127, "nextClearBit");
|
||||
check(s.nextClearBit(128) == 128, "nextClearBit");
|
||||
check(s.toString().equals("{}"), "toString");
|
||||
check(! s.get(0), "get");
|
||||
}
|
||||
|
||||
private static BitSet makeSet(int... elts) {
|
||||
BitSet s = new BitSet();
|
||||
for (int elt : elts)
|
||||
s.set(elt);
|
||||
return s;
|
||||
}
|
||||
|
||||
private static void checkEquality(BitSet s, BitSet t) {
|
||||
checkSanity(s, t);
|
||||
check(s.equals(t), "equals");
|
||||
check(s.toString().equals(t.toString()), "equal strings");
|
||||
check(s.length() == t.length(), "equal lengths");
|
||||
check(s.cardinality() == t.cardinality(), "equal cardinalities");
|
||||
}
|
||||
|
||||
private static void checkSanity(BitSet... sets) {
|
||||
for (BitSet s : sets) {
|
||||
int len = s.length();
|
||||
int cardinality1 = s.cardinality();
|
||||
int cardinality2 = 0;
|
||||
for (int i = s.nextSetBit(0); i >= 0; i = s.nextSetBit(i+1)) {
|
||||
check(s.get(i));
|
||||
cardinality2++;
|
||||
}
|
||||
check(s.nextSetBit(len) == -1, "last set bit");
|
||||
check(s.nextClearBit(len) == len, "last set bit");
|
||||
check(s.isEmpty() == (len == 0), "emptiness");
|
||||
check(cardinality1 == cardinality2, "cardinalities");
|
||||
check(len <= s.size(), "length <= size");
|
||||
check(len >= 0, "length >= 0");
|
||||
check(cardinality1 >= 0, "cardinality >= 0");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
//testFlipTime();
|
||||
|
||||
// These are the single bit versions
|
||||
testSetGetClearFlip();
|
||||
|
||||
// Test the ranged versions
|
||||
testClear();
|
||||
|
||||
testFlip();
|
||||
testSet();
|
||||
testGet();
|
||||
|
||||
// BitSet interaction calls
|
||||
testAndNot();
|
||||
testAnd();
|
||||
testOr();
|
||||
testXor();
|
||||
|
||||
// Miscellaneous calls
|
||||
testLength();
|
||||
testEquals();
|
||||
testNextSetBit();
|
||||
testNextClearBit();
|
||||
testIntersects();
|
||||
testCardinality();
|
||||
testEmpty();
|
||||
testEmpty2();
|
||||
testToString();
|
||||
testLogicalIdentities();
|
||||
|
||||
if (failure)
|
||||
throw new RuntimeException("One or more BitSet failures.");
|
||||
}
|
||||
|
||||
private static void report(String testName, int failCount) {
|
||||
System.err.println(testName+": " +
|
||||
(failCount==0 ? "Passed":"Failed("+failCount+")"));
|
||||
if (failCount > 0)
|
||||
failure = true;
|
||||
}
|
||||
|
||||
private static void testFlipTime() {
|
||||
// Make a fairly random bitset
|
||||
BitSet b1 = new BitSet();
|
||||
b1.set(1000);
|
||||
long startTime = System.currentTimeMillis();
|
||||
for(int x=0; x<100000; x++) {
|
||||
b1.flip(100, 900);
|
||||
}
|
||||
long endTime = System.currentTimeMillis();
|
||||
long total = endTime - startTime;
|
||||
System.out.println("Multiple word flip Time "+total);
|
||||
|
||||
startTime = System.currentTimeMillis();
|
||||
for(int x=0; x<100000; x++) {
|
||||
b1.flip(2, 44);
|
||||
}
|
||||
endTime = System.currentTimeMillis();
|
||||
total = endTime - startTime;
|
||||
System.out.println("Single word flip Time "+total);
|
||||
}
|
||||
|
||||
private static void testNextSetBit() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
BitSet testSet = new BitSet();
|
||||
int[] history = new int[numberOfSetBits];
|
||||
|
||||
// Set some random bits and remember them
|
||||
int nextBitToSet = 0;
|
||||
for (int x=0; x<numberOfSetBits; x++) {
|
||||
nextBitToSet += generator.nextInt(30)+1;
|
||||
history[x] = nextBitToSet;
|
||||
testSet.set(nextBitToSet);
|
||||
}
|
||||
|
||||
// Verify their retrieval using nextSetBit()
|
||||
int historyIndex = 0;
|
||||
for(int x=testSet.nextSetBit(0); x>=0; x=testSet.nextSetBit(x+1)) {
|
||||
if (x != history[historyIndex++])
|
||||
failCount++;
|
||||
}
|
||||
|
||||
checkSanity(testSet);
|
||||
}
|
||||
|
||||
report("NextSetBit ", failCount);
|
||||
}
|
||||
|
||||
private static void testNextClearBit() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<1000; i++) {
|
||||
BitSet b = new BitSet(256);
|
||||
int[] history = new int[10];
|
||||
|
||||
// Set all the bits
|
||||
for (int x=0; x<256; x++)
|
||||
b.set(x);
|
||||
|
||||
// Clear some random bits and remember them
|
||||
int nextBitToClear = 0;
|
||||
for (int x=0; x<10; x++) {
|
||||
nextBitToClear += generator.nextInt(24)+1;
|
||||
history[x] = nextBitToClear;
|
||||
b.clear(nextBitToClear);
|
||||
}
|
||||
|
||||
// Verify their retrieval using nextClearBit()
|
||||
int historyIndex = 0;
|
||||
for(int x=b.nextClearBit(0); x<256; x=b.nextClearBit(x+1)) {
|
||||
if (x != history[historyIndex++])
|
||||
failCount++;
|
||||
}
|
||||
|
||||
checkSanity(b);
|
||||
}
|
||||
|
||||
// regression test for 4350178
|
||||
BitSet bs = new BitSet();
|
||||
if (bs.nextClearBit(0) != 0)
|
||||
failCount++;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
bs.set(i);
|
||||
if (bs.nextClearBit(0) != i+1)
|
||||
failCount++;
|
||||
}
|
||||
|
||||
checkSanity(bs);
|
||||
|
||||
report("NextClearBit ", failCount);
|
||||
}
|
||||
|
||||
private static void testSetGetClearFlip() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet testSet = new BitSet();
|
||||
HashSet<Integer> history = new HashSet<Integer>();
|
||||
|
||||
// Set a random number of bits in random places
|
||||
// up to a random maximum
|
||||
int nextBitToSet = 0;
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
for (int x=0; x<numberOfSetBits; x++) {
|
||||
nextBitToSet = generator.nextInt(highestPossibleSetBit);
|
||||
history.add(new Integer(nextBitToSet));
|
||||
testSet.set(nextBitToSet);
|
||||
}
|
||||
|
||||
// Make sure each bit is set appropriately
|
||||
for (int x=0; x<highestPossibleSetBit; x++) {
|
||||
if (testSet.get(x) != history.contains(new Integer(x)))
|
||||
failCount++;
|
||||
}
|
||||
|
||||
// Clear the bits
|
||||
Iterator<Integer> setBitIterator = history.iterator();
|
||||
while (setBitIterator.hasNext()) {
|
||||
Integer setBit = setBitIterator.next();
|
||||
testSet.clear(setBit.intValue());
|
||||
}
|
||||
|
||||
// Verify they were cleared
|
||||
for (int x=0; x<highestPossibleSetBit; x++)
|
||||
if (testSet.get(x))
|
||||
failCount++;
|
||||
if(testSet.length() != 0)
|
||||
failCount++;
|
||||
|
||||
// Set them with set(int, boolean)
|
||||
setBitIterator = history.iterator();
|
||||
while (setBitIterator.hasNext()) {
|
||||
Integer setBit = setBitIterator.next();
|
||||
testSet.set(setBit.intValue(), true);
|
||||
}
|
||||
|
||||
// Make sure each bit is set appropriately
|
||||
for (int x=0; x<highestPossibleSetBit; x++) {
|
||||
if (testSet.get(x) != history.contains(new Integer(x)))
|
||||
failCount++;
|
||||
}
|
||||
|
||||
// Clear them with set(int, boolean)
|
||||
setBitIterator = history.iterator();
|
||||
while (setBitIterator.hasNext()) {
|
||||
Integer setBit = (Integer)setBitIterator.next();
|
||||
testSet.set(setBit.intValue(), false);
|
||||
}
|
||||
|
||||
// Verify they were cleared
|
||||
for (int x=0; x<highestPossibleSetBit; x++)
|
||||
if (testSet.get(x))
|
||||
failCount++;
|
||||
if(testSet.length() != 0)
|
||||
failCount++;
|
||||
|
||||
// Flip them on
|
||||
setBitIterator = history.iterator();
|
||||
while (setBitIterator.hasNext()) {
|
||||
Integer setBit = (Integer)setBitIterator.next();
|
||||
testSet.flip(setBit.intValue());
|
||||
}
|
||||
|
||||
// Verify they were flipped
|
||||
for (int x=0; x<highestPossibleSetBit; x++) {
|
||||
if (testSet.get(x) != history.contains(new Integer(x)))
|
||||
failCount++;
|
||||
}
|
||||
|
||||
// Flip them off
|
||||
setBitIterator = history.iterator();
|
||||
while (setBitIterator.hasNext()) {
|
||||
Integer setBit = (Integer)setBitIterator.next();
|
||||
testSet.flip(setBit.intValue());
|
||||
}
|
||||
|
||||
// Verify they were flipped
|
||||
for (int x=0; x<highestPossibleSetBit; x++)
|
||||
if (testSet.get(x))
|
||||
failCount++;
|
||||
if(testSet.length() != 0)
|
||||
failCount++;
|
||||
|
||||
checkSanity(testSet);
|
||||
}
|
||||
|
||||
report("SetGetClearFlip ", failCount);
|
||||
}
|
||||
|
||||
private static void testAndNot() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
BitSet b2 = new BitSet(256);
|
||||
|
||||
// Set some random bits in first set and remember them
|
||||
int nextBitToSet = 0;
|
||||
for (int x=0; x<10; x++)
|
||||
b1.set(generator.nextInt(255));
|
||||
|
||||
// Set some random bits in second set and remember them
|
||||
for (int x=10; x<20; x++)
|
||||
b2.set(generator.nextInt(255));
|
||||
|
||||
// andNot the sets together
|
||||
BitSet b3 = (BitSet)b1.clone();
|
||||
b3.andNot(b2);
|
||||
|
||||
// Examine each bit of b3 for errors
|
||||
for(int x=0; x<256; x++) {
|
||||
boolean bit1 = b1.get(x);
|
||||
boolean bit2 = b2.get(x);
|
||||
boolean bit3 = b3.get(x);
|
||||
if (!(bit3 == (bit1 & (!bit2))))
|
||||
failCount++;
|
||||
}
|
||||
checkSanity(b1, b2, b3);
|
||||
}
|
||||
|
||||
report("AndNot ", failCount);
|
||||
}
|
||||
|
||||
private static void testAnd() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
BitSet b2 = new BitSet(256);
|
||||
|
||||
// Set some random bits in first set and remember them
|
||||
int nextBitToSet = 0;
|
||||
for (int x=0; x<10; x++)
|
||||
b1.set(generator.nextInt(255));
|
||||
|
||||
// Set more random bits in second set and remember them
|
||||
for (int x=10; x<20; x++)
|
||||
b2.set(generator.nextInt(255));
|
||||
|
||||
// And the sets together
|
||||
BitSet b3 = (BitSet)b1.clone();
|
||||
b3.and(b2);
|
||||
|
||||
// Examine each bit of b3 for errors
|
||||
for(int x=0; x<256; x++) {
|
||||
boolean bit1 = b1.get(x);
|
||||
boolean bit2 = b2.get(x);
|
||||
boolean bit3 = b3.get(x);
|
||||
if (!(bit3 == (bit1 & bit2)))
|
||||
failCount++;
|
||||
}
|
||||
checkSanity(b1, b2, b3);
|
||||
}
|
||||
|
||||
// `and' that happens to clear the last word
|
||||
BitSet b4 = makeSet(2, 127);
|
||||
b4.and(makeSet(2, 64));
|
||||
checkSanity(b4);
|
||||
if (!(b4.equals(makeSet(2))))
|
||||
failCount++;
|
||||
|
||||
report("And ", failCount);
|
||||
}
|
||||
|
||||
private static void testOr() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
BitSet b2 = new BitSet(256);
|
||||
int[] history = new int[20];
|
||||
|
||||
// Set some random bits in first set and remember them
|
||||
int nextBitToSet = 0;
|
||||
for (int x=0; x<10; x++) {
|
||||
nextBitToSet = generator.nextInt(255);
|
||||
history[x] = nextBitToSet;
|
||||
b1.set(nextBitToSet);
|
||||
}
|
||||
|
||||
// Set more random bits in second set and remember them
|
||||
for (int x=10; x<20; x++) {
|
||||
nextBitToSet = generator.nextInt(255);
|
||||
history[x] = nextBitToSet;
|
||||
b2.set(nextBitToSet);
|
||||
}
|
||||
|
||||
// Or the sets together
|
||||
BitSet b3 = (BitSet)b1.clone();
|
||||
b3.or(b2);
|
||||
|
||||
// Verify the set bits of b3 from the history
|
||||
int historyIndex = 0;
|
||||
for(int x=0; x<20; x++) {
|
||||
if (!b3.get(history[x]))
|
||||
failCount++;
|
||||
}
|
||||
|
||||
// Examine each bit of b3 for errors
|
||||
for(int x=0; x<256; x++) {
|
||||
boolean bit1 = b1.get(x);
|
||||
boolean bit2 = b2.get(x);
|
||||
boolean bit3 = b3.get(x);
|
||||
if (!(bit3 == (bit1 | bit2)))
|
||||
failCount++;
|
||||
}
|
||||
checkSanity(b1, b2, b3);
|
||||
}
|
||||
|
||||
report("Or ", failCount);
|
||||
}
|
||||
|
||||
private static void testXor() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
BitSet b2 = new BitSet(256);
|
||||
|
||||
// Set some random bits in first set and remember them
|
||||
int nextBitToSet = 0;
|
||||
for (int x=0; x<10; x++)
|
||||
b1.set(generator.nextInt(255));
|
||||
|
||||
// Set more random bits in second set and remember them
|
||||
for (int x=10; x<20; x++)
|
||||
b2.set(generator.nextInt(255));
|
||||
|
||||
// Xor the sets together
|
||||
BitSet b3 = (BitSet)b1.clone();
|
||||
b3.xor(b2);
|
||||
|
||||
// Examine each bit of b3 for errors
|
||||
for(int x=0; x<256; x++) {
|
||||
boolean bit1 = b1.get(x);
|
||||
boolean bit2 = b2.get(x);
|
||||
boolean bit3 = b3.get(x);
|
||||
if (!(bit3 == (bit1 ^ bit2)))
|
||||
failCount++;
|
||||
}
|
||||
checkSanity(b1, b2, b3);
|
||||
b3.xor(b3); checkEmpty(b3);
|
||||
}
|
||||
|
||||
// xor that happens to clear the last word
|
||||
BitSet b4 = makeSet(2, 64, 127);
|
||||
b4.xor(makeSet(64, 127));
|
||||
checkSanity(b4);
|
||||
if (!(b4.equals(makeSet(2))))
|
||||
failCount++;
|
||||
|
||||
report("Xor ", failCount);
|
||||
}
|
||||
|
||||
private static void testEquals() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
// Create BitSets of different sizes
|
||||
BitSet b1 = new BitSet(generator.nextInt(1000)+1);
|
||||
BitSet b2 = new BitSet(generator.nextInt(1000)+1);
|
||||
|
||||
// Set some random bits
|
||||
int nextBitToSet = 0;
|
||||
for (int x=0; x<10; x++) {
|
||||
nextBitToSet += generator.nextInt(50)+1;
|
||||
b1.set(nextBitToSet);
|
||||
b2.set(nextBitToSet);
|
||||
}
|
||||
|
||||
// Verify their equality despite different storage sizes
|
||||
if (!b1.equals(b2))
|
||||
failCount++;
|
||||
checkEquality(b1,b2);
|
||||
}
|
||||
|
||||
report("Equals ", failCount);
|
||||
}
|
||||
|
||||
private static void testLength() {
|
||||
int failCount = 0;
|
||||
|
||||
// Test length after set
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
int highestSetBit = 0;
|
||||
|
||||
for(int x=0; x<100; x++) {
|
||||
int nextBitToSet = generator.nextInt(255);
|
||||
if (nextBitToSet > highestSetBit)
|
||||
highestSetBit = nextBitToSet;
|
||||
b1.set(nextBitToSet);
|
||||
if (b1.length() != highestSetBit + 1)
|
||||
failCount++;
|
||||
}
|
||||
checkSanity(b1);
|
||||
}
|
||||
|
||||
// Test length after flip
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
for(int x=0; x<100; x++) {
|
||||
// Flip a random range twice
|
||||
int rangeStart = generator.nextInt(100);
|
||||
int rangeEnd = rangeStart + generator.nextInt(100);
|
||||
b1.flip(rangeStart);
|
||||
b1.flip(rangeStart);
|
||||
if (b1.length() != 0)
|
||||
failCount++;
|
||||
b1.flip(rangeStart, rangeEnd);
|
||||
b1.flip(rangeStart, rangeEnd);
|
||||
if (b1.length() != 0)
|
||||
failCount++;
|
||||
}
|
||||
checkSanity(b1);
|
||||
}
|
||||
|
||||
// Test length after or
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
BitSet b2 = new BitSet(256);
|
||||
int bit1 = generator.nextInt(100);
|
||||
int bit2 = generator.nextInt(100);
|
||||
int highestSetBit = (bit1 > bit2) ? bit1 : bit2;
|
||||
b1.set(bit1);
|
||||
b2.set(bit2);
|
||||
b1.or(b2);
|
||||
if (b1.length() != highestSetBit + 1)
|
||||
failCount++;
|
||||
checkSanity(b1, b2);
|
||||
}
|
||||
|
||||
report("Length ", failCount);
|
||||
}
|
||||
|
||||
private static void testClear() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<1000; i++) {
|
||||
BitSet b1 = new BitSet();
|
||||
|
||||
// Make a fairly random bitset
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
|
||||
for (int x=0; x<numberOfSetBits; x++)
|
||||
b1.set(generator.nextInt(highestPossibleSetBit));
|
||||
|
||||
BitSet b2 = (BitSet)b1.clone();
|
||||
|
||||
// Clear out a random range
|
||||
int rangeStart = generator.nextInt(100);
|
||||
int rangeEnd = rangeStart + generator.nextInt(100);
|
||||
|
||||
// Use the clear(int, int) call on b1
|
||||
b1.clear(rangeStart, rangeEnd);
|
||||
|
||||
// Use a loop on b2
|
||||
for (int x=rangeStart; x<rangeEnd; x++)
|
||||
b2.clear(x);
|
||||
|
||||
// Verify their equality
|
||||
if (!b1.equals(b2)) {
|
||||
System.out.println("rangeStart = " + rangeStart);
|
||||
System.out.println("rangeEnd = " + rangeEnd);
|
||||
System.out.println("b1 = " + b1);
|
||||
System.out.println("b2 = " + b2);
|
||||
failCount++;
|
||||
}
|
||||
checkEquality(b1,b2);
|
||||
}
|
||||
|
||||
report("Clear ", failCount);
|
||||
}
|
||||
|
||||
private static void testSet() {
|
||||
int failCount = 0;
|
||||
|
||||
// Test set(int, int)
|
||||
for (int i=0; i<1000; i++) {
|
||||
BitSet b1 = new BitSet();
|
||||
|
||||
// Make a fairly random bitset
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
|
||||
for (int x=0; x<numberOfSetBits; x++)
|
||||
b1.set(generator.nextInt(highestPossibleSetBit));
|
||||
|
||||
BitSet b2 = (BitSet)b1.clone();
|
||||
|
||||
// Set a random range
|
||||
int rangeStart = generator.nextInt(100);
|
||||
int rangeEnd = rangeStart + generator.nextInt(100);
|
||||
|
||||
// Use the set(int, int) call on b1
|
||||
b1.set(rangeStart, rangeEnd);
|
||||
|
||||
// Use a loop on b2
|
||||
for (int x=rangeStart; x<rangeEnd; x++)
|
||||
b2.set(x);
|
||||
|
||||
// Verify their equality
|
||||
if (!b1.equals(b2)) {
|
||||
System.out.println("Set 1");
|
||||
System.out.println("rangeStart = " + rangeStart);
|
||||
System.out.println("rangeEnd = " + rangeEnd);
|
||||
System.out.println("b1 = " + b1);
|
||||
System.out.println("b2 = " + b2);
|
||||
failCount++;
|
||||
}
|
||||
checkEquality(b1,b2);
|
||||
}
|
||||
|
||||
// Test set(int, int, boolean)
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet();
|
||||
|
||||
// Make a fairly random bitset
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
|
||||
for (int x=0; x<numberOfSetBits; x++)
|
||||
b1.set(generator.nextInt(highestPossibleSetBit));
|
||||
|
||||
BitSet b2 = (BitSet)b1.clone();
|
||||
boolean setOrClear = generator.nextBoolean();
|
||||
|
||||
// Set a random range
|
||||
int rangeStart = generator.nextInt(100);
|
||||
int rangeEnd = rangeStart + generator.nextInt(100);
|
||||
|
||||
// Use the set(int, int, boolean) call on b1
|
||||
b1.set(rangeStart, rangeEnd, setOrClear);
|
||||
|
||||
// Use a loop on b2
|
||||
for (int x=rangeStart; x<rangeEnd; x++)
|
||||
b2.set(x, setOrClear);
|
||||
|
||||
// Verify their equality
|
||||
if (!b1.equals(b2)) {
|
||||
System.out.println("Set 2");
|
||||
System.out.println("b1 = " + b1);
|
||||
System.out.println("b2 = " + b2);
|
||||
failCount++;
|
||||
}
|
||||
checkEquality(b1,b2);
|
||||
}
|
||||
|
||||
report("Set ", failCount);
|
||||
}
|
||||
|
||||
private static void testFlip() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<1000; i++) {
|
||||
BitSet b1 = new BitSet();
|
||||
|
||||
// Make a fairly random bitset
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
|
||||
for (int x=0; x<numberOfSetBits; x++)
|
||||
b1.set(generator.nextInt(highestPossibleSetBit));
|
||||
|
||||
BitSet b2 = (BitSet)b1.clone();
|
||||
|
||||
// Flip a random range
|
||||
int rangeStart = generator.nextInt(100);
|
||||
int rangeEnd = rangeStart + generator.nextInt(100);
|
||||
|
||||
// Use the flip(int, int) call on b1
|
||||
b1.flip(rangeStart, rangeEnd);
|
||||
|
||||
// Use a loop on b2
|
||||
for (int x=rangeStart; x<rangeEnd; x++)
|
||||
b2.flip(x);
|
||||
|
||||
// Verify their equality
|
||||
if (!b1.equals(b2))
|
||||
failCount++;
|
||||
checkEquality(b1,b2);
|
||||
}
|
||||
|
||||
report("Flip ", failCount);
|
||||
}
|
||||
|
||||
private static void testGet() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<1000; i++) {
|
||||
BitSet b1 = new BitSet();
|
||||
|
||||
// Make a fairly random bitset
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
|
||||
for (int x=0; x<numberOfSetBits; x++)
|
||||
b1.set(generator.nextInt(highestPossibleSetBit));
|
||||
|
||||
// Get a new set from a random range
|
||||
int rangeStart = generator.nextInt(100);
|
||||
int rangeEnd = rangeStart + generator.nextInt(100);
|
||||
|
||||
BitSet b2 = b1.get(rangeStart, rangeEnd);
|
||||
|
||||
BitSet b3 = new BitSet();
|
||||
for(int x=rangeStart; x<rangeEnd; x++)
|
||||
b3.set(x-rangeStart, b1.get(x));
|
||||
|
||||
// Verify their equality
|
||||
if (!b2.equals(b3)) {
|
||||
System.out.println("start="+rangeStart);
|
||||
System.out.println("end="+rangeEnd);
|
||||
System.out.println(b1);
|
||||
System.out.println(b2);
|
||||
System.out.println(b3);
|
||||
failCount++;
|
||||
}
|
||||
checkEquality(b2,b3);
|
||||
}
|
||||
|
||||
report("Get ", failCount);
|
||||
}
|
||||
|
||||
|
||||
private static void testIntersects() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
BitSet b2 = new BitSet(256);
|
||||
|
||||
// Set some random bits in first set
|
||||
int nextBitToSet = 0;
|
||||
for (int x=0; x<30; x++) {
|
||||
nextBitToSet = generator.nextInt(255);
|
||||
b1.set(nextBitToSet);
|
||||
}
|
||||
|
||||
// Set more random bits in second set
|
||||
for (int x=0; x<30; x++) {
|
||||
nextBitToSet = generator.nextInt(255);
|
||||
b2.set(nextBitToSet);
|
||||
}
|
||||
|
||||
// Make sure they intersect
|
||||
nextBitToSet = generator.nextInt(255);
|
||||
b1.set(nextBitToSet);
|
||||
b2.set(nextBitToSet);
|
||||
|
||||
if (!b1.intersects(b2))
|
||||
failCount++;
|
||||
|
||||
// Remove the common set bits
|
||||
b1.andNot(b2);
|
||||
|
||||
// Make sure they don't intersect
|
||||
if (b1.intersects(b2))
|
||||
failCount++;
|
||||
|
||||
checkSanity(b1, b2);
|
||||
}
|
||||
|
||||
report("Intersects ", failCount);
|
||||
}
|
||||
|
||||
private static void testCardinality() {
|
||||
int failCount = 0;
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
BitSet b1 = new BitSet(256);
|
||||
|
||||
// Set a random number of increasing bits
|
||||
int nextBitToSet = 0;
|
||||
int iterations = generator.nextInt(20)+1;
|
||||
for (int x=0; x<iterations; x++) {
|
||||
nextBitToSet += generator.nextInt(20)+1;
|
||||
b1.set(nextBitToSet);
|
||||
}
|
||||
|
||||
if (b1.cardinality() != iterations) {
|
||||
System.out.println("Iterations is "+iterations);
|
||||
System.out.println("Cardinality is "+b1.cardinality());
|
||||
failCount++;
|
||||
}
|
||||
|
||||
checkSanity(b1);
|
||||
}
|
||||
|
||||
report("Cardinality ", failCount);
|
||||
}
|
||||
|
||||
private static void testEmpty() {
|
||||
int failCount = 0;
|
||||
|
||||
BitSet b1 = new BitSet();
|
||||
if (!b1.isEmpty())
|
||||
failCount++;
|
||||
|
||||
int nextBitToSet = 0;
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
for (int x=0; x<numberOfSetBits; x++) {
|
||||
nextBitToSet = generator.nextInt(highestPossibleSetBit);
|
||||
b1.set(nextBitToSet);
|
||||
if (b1.isEmpty())
|
||||
failCount++;
|
||||
b1.clear(nextBitToSet);
|
||||
if (!b1.isEmpty())
|
||||
failCount++;
|
||||
}
|
||||
|
||||
report("Empty ", failCount);
|
||||
}
|
||||
|
||||
private static void testEmpty2() {
|
||||
{BitSet t = new BitSet(); t.set(100); t.clear(3,600); checkEmpty(t);}
|
||||
checkEmpty(new BitSet(0));
|
||||
checkEmpty(new BitSet(342));
|
||||
BitSet s = new BitSet(0);
|
||||
checkEmpty(s);
|
||||
s.clear(92); checkEmpty(s);
|
||||
s.clear(127,127); checkEmpty(s);
|
||||
s.set(127,127); checkEmpty(s);
|
||||
s.set(128,128); checkEmpty(s);
|
||||
BitSet empty = new BitSet();
|
||||
{BitSet t = new BitSet(); t.and (empty); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.or (empty); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.xor (empty); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.andNot(empty); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.and (t); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.or (t); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.xor (t); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.andNot(t); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.and(makeSet(1)); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.and(makeSet(127)); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.and(makeSet(128)); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); t.flip(7);t.flip(7); checkEmpty(t);}
|
||||
{BitSet t = new BitSet(); checkEmpty(t.get(200,300));}
|
||||
{BitSet t = makeSet(2,5); check(t.get(2,6).equals(makeSet(0,3)),"");}
|
||||
}
|
||||
|
||||
private static void testToString() {
|
||||
check(new BitSet().toString().equals("{}"));
|
||||
check(makeSet(2,3,42,43,234).toString().equals("{2, 3, 42, 43, 234}"));
|
||||
|
||||
final long MB = 1024*1024;
|
||||
if (Runtime.getRuntime().maxMemory() >= 512*MB) {
|
||||
// only run it if we have enough memory
|
||||
try {
|
||||
check(makeSet(Integer.MAX_VALUE-1).toString().equals(
|
||||
"{" + (Integer.MAX_VALUE-1) + "}"));
|
||||
check(makeSet(Integer.MAX_VALUE).toString().equals(
|
||||
"{" + Integer.MAX_VALUE + "}"));
|
||||
check(makeSet(0, 1, Integer.MAX_VALUE-1, Integer.MAX_VALUE).toString().equals(
|
||||
"{0, 1, " + (Integer.MAX_VALUE-1) + ", " + Integer.MAX_VALUE + "}"));
|
||||
} catch (IndexOutOfBoundsException exc) {
|
||||
fail("toString() with indices near MAX_VALUE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testLogicalIdentities() {
|
||||
int failCount = 0;
|
||||
|
||||
// Verify that (!b1)|(!b2) == !(b1&b2)
|
||||
for (int i=0; i<50; i++) {
|
||||
// Construct two fairly random bitsets
|
||||
BitSet b1 = new BitSet();
|
||||
BitSet b2 = new BitSet();
|
||||
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
|
||||
for (int x=0; x<numberOfSetBits; x++) {
|
||||
b1.set(generator.nextInt(highestPossibleSetBit));
|
||||
b2.set(generator.nextInt(highestPossibleSetBit));
|
||||
}
|
||||
|
||||
BitSet b3 = (BitSet) b1.clone();
|
||||
BitSet b4 = (BitSet) b2.clone();
|
||||
|
||||
for (int x=0; x<highestPossibleSetBit; x++) {
|
||||
b1.flip(x);
|
||||
b2.flip(x);
|
||||
}
|
||||
b1.or(b2);
|
||||
b3.and(b4);
|
||||
for (int x=0; x<highestPossibleSetBit; x++)
|
||||
b3.flip(x);
|
||||
if (!b1.equals(b3))
|
||||
failCount++;
|
||||
checkSanity(b1, b2, b3, b4);
|
||||
}
|
||||
|
||||
// Verify that (b1&(!b2)|(b2&(!b1) == b1^b2
|
||||
for (int i=0; i<50; i++) {
|
||||
// Construct two fairly random bitsets
|
||||
BitSet b1 = new BitSet();
|
||||
BitSet b2 = new BitSet();
|
||||
|
||||
int numberOfSetBits = generator.nextInt(100) + 1;
|
||||
int highestPossibleSetBit = generator.nextInt(1000) + 1;
|
||||
|
||||
for (int x=0; x<numberOfSetBits; x++) {
|
||||
b1.set(generator.nextInt(highestPossibleSetBit));
|
||||
b2.set(generator.nextInt(highestPossibleSetBit));
|
||||
}
|
||||
|
||||
BitSet b3 = (BitSet) b1.clone();
|
||||
BitSet b4 = (BitSet) b2.clone();
|
||||
BitSet b5 = (BitSet) b1.clone();
|
||||
BitSet b6 = (BitSet) b2.clone();
|
||||
|
||||
for (int x=0; x<highestPossibleSetBit; x++)
|
||||
b2.flip(x);
|
||||
b1.and(b2);
|
||||
for (int x=0; x<highestPossibleSetBit; x++)
|
||||
b3.flip(x);
|
||||
b3.and(b4);
|
||||
b1.or(b3);
|
||||
b5.xor(b6);
|
||||
if (!b1.equals(b5))
|
||||
failCount++;
|
||||
checkSanity(b1, b2, b3, b4, b5, b6);
|
||||
}
|
||||
report("Logical Identities ", failCount);
|
||||
}
|
||||
|
||||
}
|
||||
45
test/jdk/java/util/BitSet/HugeToString.java
Normal file
45
test/jdk/java/util/BitSet/HugeToString.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8225397
|
||||
* @summary Integer value miscalculation in toString() method of BitSet
|
||||
* @run main/othervm -Xms250m HugeToString
|
||||
*/
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
public final class HugeToString {
|
||||
|
||||
public static void main(String[] args) {
|
||||
BitSet bs = new BitSet(500_000_000);
|
||||
bs.flip(0, 500_000_000);
|
||||
try {
|
||||
bs.toString();
|
||||
} catch (OutOfMemoryError expected) {
|
||||
} catch (Throwable t) {
|
||||
throw new AssertionError("Unexpected exception", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
100
test/jdk/java/util/BitSet/ImmutableBitSet.java
Normal file
100
test/jdk/java/util/BitSet/ImmutableBitSet.java
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 Basic tests of immutable BitSets
|
||||
* @modules java.base/jdk.internal.util
|
||||
* @run junit ImmutableBitSet
|
||||
*/
|
||||
|
||||
import jdk.internal.util.ImmutableBitSetPredicate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Random;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ImmutableBitSet {
|
||||
|
||||
@Test
|
||||
void empty() {
|
||||
BitSet bs = new BitSet();
|
||||
IntPredicate ibs = ImmutableBitSetPredicate.of(bs);
|
||||
test(bs, ibs);
|
||||
}
|
||||
|
||||
@Test
|
||||
void negativeIndex() {
|
||||
IntStream.of(0, 127, 128, 129, 143, 4711).forEach(k -> {
|
||||
BitSet bs = new BitSet(k);
|
||||
IntPredicate ibs = ImmutableBitSetPredicate.of(bs);
|
||||
assertFalse(ibs.test(-1));
|
||||
assertFalse(ibs.test(Integer.MIN_VALUE));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void basic() {
|
||||
IntStream.of(0, 16, 127, 128, 129, 143, 4711).forEach(k -> basic(k));
|
||||
}
|
||||
|
||||
void basic(int length) {
|
||||
BitSet bs = createReference(length);
|
||||
IntPredicate ibs = ImmutableBitSetPredicate.of(bs);
|
||||
test(bs, ibs);
|
||||
}
|
||||
|
||||
@Test
|
||||
void clearedAtTheTail() {
|
||||
IntStream.of(0, 16, 127, 128, 129, 143, 4711).forEach(k -> {
|
||||
for (int i = Long.BYTES - 1; i < Long.BYTES + 2; i++) {
|
||||
BitSet bs = createReference(k + i);
|
||||
for (int j = bs.length() - 1; j > Long.BYTES - 1; j--) {
|
||||
bs.clear(j);
|
||||
}
|
||||
IntPredicate ibs = ImmutableBitSetPredicate.of(bs);
|
||||
test(bs, ibs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void test(BitSet expected, IntPredicate actual) {
|
||||
for (int i = 0; i < expected.length() + 17; i++) {
|
||||
assertEquals(expected.get(i), actual.test(i), "at index " + i);
|
||||
}
|
||||
}
|
||||
|
||||
private static BitSet createReference(int length) {
|
||||
BitSet result = new BitSet(length);
|
||||
Random random = new Random(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
result.set(i, random.nextBoolean());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
156
test/jdk/java/util/BitSet/ImportExport.java
Normal file
156
test/jdk/java/util/BitSet/ImportExport.java
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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 5037068
|
||||
* @summary Test import/export constructors and methods
|
||||
* @author Martin Buchholz
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
|
||||
public class ImportExport {
|
||||
final Random rnd = new Random();
|
||||
|
||||
void equal(byte[] x, byte[] y) {
|
||||
check(Arrays.equals(x, y));
|
||||
}
|
||||
|
||||
void equal(long[] x, long[] y) {
|
||||
check(Arrays.equals(x, y));
|
||||
}
|
||||
|
||||
void equal(byte[] bytes, BitSet s) {
|
||||
equal(s, BitSet.valueOf(bytes));
|
||||
equal(s, BitSet.valueOf(ByteBuffer.wrap(bytes)));
|
||||
equal(s, BitSet.valueOf(
|
||||
ByteBuffer.wrap(
|
||||
Arrays.copyOf(bytes, bytes.length + 8 + rnd.nextInt(8)))
|
||||
.order(ByteOrder.LITTLE_ENDIAN)
|
||||
.asLongBuffer()));
|
||||
}
|
||||
|
||||
void checkEmptyBitSet(BitSet s) {
|
||||
equal(s.toByteArray(), new byte[0]);
|
||||
equal(s.toLongArray(), new long[0]);
|
||||
check(s.isEmpty());
|
||||
}
|
||||
|
||||
void test(String[] args) throws Throwable {
|
||||
for (int i = 0; i < 17; i++) {
|
||||
byte[] bytes = new byte[i];
|
||||
BitSet s = new BitSet();
|
||||
equal(bytes, s);
|
||||
equal(BitSet.valueOf(bytes).toByteArray(), new byte[0]);
|
||||
if (i > 0) {
|
||||
int k = rnd.nextInt(i);
|
||||
for (int j = 0; j < 8; j++) {
|
||||
bytes[k] |= 1 << j;
|
||||
s.set(8*k+j);
|
||||
equal(bytes, s);
|
||||
byte[] expected = new byte[k+1]; expected[k] = bytes[k];
|
||||
equal(BitSet.valueOf(bytes).toByteArray(), expected);
|
||||
ByteBuffer bb = ByteBuffer.wrap(bytes);
|
||||
bb.position(k);
|
||||
equal(BitSet.valueOf(bb).toByteArray(),
|
||||
new byte[]{bytes[k]});
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 100; i++) {
|
||||
byte[] bytes = new byte[rnd.nextInt(17)];
|
||||
for (int j = 0; j < bytes.length; j++)
|
||||
bytes[j] = (byte) rnd.nextInt(0x100);
|
||||
BitSet s = BitSet.valueOf(bytes);
|
||||
byte[] expected = s.toByteArray();
|
||||
equal(expected.length, (s.length()+7)/8);
|
||||
if (bytes.length == 0)
|
||||
continue;
|
||||
if (expected.length > 0)
|
||||
check(expected[expected.length-1] != 0);
|
||||
if (bytes[bytes.length-1] != 0)
|
||||
equal(bytes, expected);
|
||||
int n = rnd.nextInt(8 * bytes.length);
|
||||
equal(s.get(n), ((bytes[n/8] & (1<<(n%8))) != 0));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
checkEmptyBitSet(BitSet.valueOf(new byte[i]));
|
||||
checkEmptyBitSet(BitSet.valueOf(ByteBuffer.wrap(new byte[i])));
|
||||
checkEmptyBitSet(BitSet.valueOf(new byte[i*64]));
|
||||
checkEmptyBitSet(BitSet.valueOf(ByteBuffer.wrap(new byte[i*64])));
|
||||
checkEmptyBitSet(BitSet.valueOf(new long[i]));
|
||||
checkEmptyBitSet(BitSet.valueOf(LongBuffer.wrap(new long[i])));
|
||||
}
|
||||
|
||||
{
|
||||
long[] longs = new long[rnd.nextInt(10)];
|
||||
for (int i = 0; i < longs.length; i++)
|
||||
longs[i] = rnd.nextLong();
|
||||
LongBuffer b1 = LongBuffer.wrap(longs);
|
||||
LongBuffer b2 = LongBuffer.allocate(longs.length + 10);
|
||||
for (int i = 0; i < b2.limit(); i++)
|
||||
b2.put(i, rnd.nextLong());
|
||||
int beg = rnd.nextInt(10);
|
||||
b2.position(beg);
|
||||
b2.put(longs);
|
||||
b2.limit(b2.position());
|
||||
b2.position(beg);
|
||||
BitSet s1 = BitSet.valueOf(longs);
|
||||
BitSet s2 = BitSet.valueOf(b1);
|
||||
BitSet s3 = BitSet.valueOf(b2);
|
||||
equal(s1, s2);
|
||||
equal(s1, s3);
|
||||
if (longs.length > 0 && longs[longs.length -1] != 0) {
|
||||
equal(longs, s1.toLongArray());
|
||||
equal(longs, s2.toLongArray());
|
||||
equal(longs, s3.toLongArray());
|
||||
}
|
||||
for (int i = 0; i < 64 * longs.length; i++) {
|
||||
equal(s1.get(i), ((longs [i/64] & (1L<<(i%64))) != 0));
|
||||
equal(s2.get(i), ((b1.get(i/64) & (1L<<(i%64))) != 0));
|
||||
equal(s3.get(i), ((b2.get(b2.position()+i/64) & (1L<<(i%64))) != 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new ImportExport().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
||||
56
test/jdk/java/util/BitSet/MemoryLeak.java
Normal file
56
test/jdk/java/util/BitSet/MemoryLeak.java
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4091185
|
||||
* @summary Repeatedly OR BitSets; No OutOfMemoryException should result
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This is a simple test class that repeatedly ORs two
|
||||
* BitSets of unequal size together. Previously this
|
||||
* caused an exponential growth in the memory underlying
|
||||
* the BitSets quickly using all available memory
|
||||
*/
|
||||
public class MemoryLeak {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
//create 2 test bitsets
|
||||
BitSet setOne = new BitSet();
|
||||
BitSet setTwo = new BitSet();
|
||||
|
||||
setOne.set(64);
|
||||
setTwo.set(129);
|
||||
|
||||
//test for bug #4091185
|
||||
//exponential set growth causing memory depletion
|
||||
for (int i = 0; i < 50; i++) {
|
||||
setOne.or(setTwo);
|
||||
setTwo.or(setOne);
|
||||
}
|
||||
}
|
||||
}
|
||||
158
test/jdk/java/util/BitSet/PreviousBits.java
Normal file
158
test/jdk/java/util/BitSet/PreviousBits.java
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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 6410729 6586631
|
||||
* @summary Test previousClearBit, previousSetBit
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PreviousBits {
|
||||
|
||||
void testHashCode(final BitSet s) {
|
||||
long h = 1234;
|
||||
long[] words = s.toLongArray();
|
||||
for (int i = words.length; --i >= 0; )
|
||||
h ^= words[i] * (i + 1);
|
||||
equal((int)((h >> 32) ^ h), s.hashCode());
|
||||
}
|
||||
|
||||
void testOutOfBounds(final BitSet s) {
|
||||
THROWS(IndexOutOfBoundsException.class,
|
||||
new F(){void f(){ s.previousSetBit(-2);}},
|
||||
new F(){void f(){ s.previousClearBit(-2);}},
|
||||
new F(){void f(){ s.previousSetBit(Integer.MIN_VALUE);}},
|
||||
new F(){void f(){ s.previousClearBit(Integer.MIN_VALUE);}},
|
||||
new F(){void f(){ s.nextSetBit(-1);}},
|
||||
new F(){void f(){ s.nextClearBit(-1);}},
|
||||
new F(){void f(){ s.nextSetBit(Integer.MIN_VALUE);}},
|
||||
new F(){void f(){ s.nextClearBit(Integer.MIN_VALUE);}});
|
||||
}
|
||||
|
||||
void test(String[] args) throws Throwable {
|
||||
final BitSet s = new BitSet();
|
||||
|
||||
// Test empty bitset
|
||||
testOutOfBounds(s);
|
||||
testHashCode(s);
|
||||
|
||||
for (int i = -1; i < 93;) {
|
||||
equal(-1, s.previousSetBit(i));
|
||||
equal( i, s.previousClearBit(i));
|
||||
i++;
|
||||
equal(-1, s.nextSetBit(i));
|
||||
equal( i, s.nextClearBit(i));
|
||||
}
|
||||
|
||||
// Test "singleton" bitsets
|
||||
for (int j = 0; j < 161; j++) {
|
||||
s.clear();
|
||||
s.set(j);
|
||||
testOutOfBounds(s);
|
||||
testHashCode(s);
|
||||
|
||||
for (int i = -1; i < j; i++) {
|
||||
equal(-1, s.previousSetBit(i));
|
||||
equal( i, s.previousClearBit(i));
|
||||
if (i >= 0) {
|
||||
equal(j, s.nextSetBit(i));
|
||||
equal(i, s.nextClearBit(i));
|
||||
}
|
||||
}
|
||||
|
||||
equal(j, s.previousSetBit(j));
|
||||
equal(j-1, s.previousClearBit(j));
|
||||
equal(j, s.nextSetBit(j));
|
||||
equal(j+1, s.nextClearBit(j));
|
||||
|
||||
for (int i = j+1; i < j+100; i++) {
|
||||
equal(j, s.previousSetBit(i));
|
||||
equal(i, s.previousClearBit(i));
|
||||
equal(-1, s.nextSetBit(i));
|
||||
equal(i, s.nextClearBit(i));
|
||||
}
|
||||
}
|
||||
|
||||
// set even bits
|
||||
s.clear();
|
||||
for (int i = 0; i <= 128; i+=2)
|
||||
s.set(i);
|
||||
testHashCode(s);
|
||||
for (int i = 1; i <= 128; i++) {
|
||||
equal(s.previousSetBit(i),
|
||||
((i & 1) == 0) ? i : i - 1);
|
||||
equal(s.previousClearBit(i),
|
||||
((i & 1) == 0) ? i - 1 : i);
|
||||
}
|
||||
|
||||
// set odd bits as well
|
||||
for (int i = 1; i <= 128; i+=2)
|
||||
s.set(i);
|
||||
testHashCode(s);
|
||||
for (int i = 1; i <= 128; i++) {
|
||||
equal(s.previousSetBit(i), i);
|
||||
equal(s.previousClearBit(i), -1);
|
||||
}
|
||||
|
||||
// Test loops documented in javadoc
|
||||
Random rnd = new Random();
|
||||
s.clear();
|
||||
for (int i = 0; i < 10; i++)
|
||||
s.set(rnd.nextInt(1066));
|
||||
List<Integer> down = new ArrayList<Integer>();
|
||||
for (int i = s.length(); (i = s.previousSetBit(i-1)) >= 0; )
|
||||
down.add(i);
|
||||
List<Integer> up = new ArrayList<Integer>();
|
||||
for (int i = s.nextSetBit(0); i >= 0; i = s.nextSetBit(i+1))
|
||||
up.add(i);
|
||||
Collections.reverse(up);
|
||||
equal(up, down);
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new PreviousBits().instanceMain(args);}
|
||||
void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
abstract class F {abstract void f() throws Throwable;}
|
||||
void THROWS(Class<? extends Throwable> k, F... fs) {
|
||||
for (F f : fs)
|
||||
try {f.f(); fail("Expected " + k.getName() + " not thrown");}
|
||||
catch (Throwable t) {
|
||||
if (k.isAssignableFrom(t.getClass())) pass();
|
||||
else unexpected(t);}}
|
||||
}
|
||||
103
test/jdk/java/util/BitSet/StickySize.java
Normal file
103
test/jdk/java/util/BitSet/StickySize.java
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 6404711
|
||||
* @summary Check capacity management
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class StickySize {
|
||||
static void equalClones(BitSet s, int expectedSize) {
|
||||
equal(expectedSize, clone(s).size());
|
||||
equal(expectedSize, serialClone(s).size());
|
||||
equal(expectedSize, s.size());
|
||||
equal(clone(s), serialClone(s));
|
||||
}
|
||||
|
||||
private static void realMain(String[] args) {
|
||||
BitSet s;
|
||||
|
||||
s = new BitSet(); // non-sticky
|
||||
equal(s.size(), 64);
|
||||
equalClones(s, 0);
|
||||
s.set(3*64);
|
||||
s.set(7*64);
|
||||
equal(s.size(), 8*64);
|
||||
equalClones(s, 8*64);
|
||||
s.clear(7*64);
|
||||
equal(s.size(), 8*64);
|
||||
equalClones(s, 4*64);
|
||||
|
||||
s = new BitSet(8*64); // sticky
|
||||
equalClones(s, 8*64);
|
||||
s.set(3*64);
|
||||
s.set(7*64);
|
||||
equalClones(s, 8*64);
|
||||
s.clear(7*64);
|
||||
equalClones(s, 8*64);
|
||||
equalClones(clone(s), 8*64);
|
||||
equalClones(serialClone(s), 8*64);
|
||||
s.set(17*64); // Expand beyond sticky size
|
||||
equalClones(s, 18*64);
|
||||
s.clear(17*64);
|
||||
equalClones(s, 4*64);
|
||||
}
|
||||
|
||||
static BitSet clone(BitSet s) {
|
||||
return (BitSet) s.clone();
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
static byte[] serializedForm(Object obj) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
new ObjectOutputStream(baos).writeObject(obj);
|
||||
return baos.toByteArray();
|
||||
} catch (IOException e) { throw new RuntimeException(e); }}
|
||||
static Object readObject(byte[] bytes)
|
||||
throws IOException, ClassNotFoundException {
|
||||
InputStream is = new ByteArrayInputStream(bytes);
|
||||
return new ObjectInputStream(is).readObject();}
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T serialClone(T obj) {
|
||||
try { return (T) readObject(serializedForm(obj)); }
|
||||
catch (Exception e) { throw new RuntimeException(e); }}
|
||||
}
|
||||
241
test/jdk/java/util/BitSet/stream/BitSetStreamTest.java
Normal file
241
test/jdk/java/util/BitSet/stream/BitSetStreamTest.java
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Random;
|
||||
import java.util.Spliterator;
|
||||
import java.util.SpliteratorOfIntDataBuilder;
|
||||
import java.util.SpliteratorTestHelper;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary test BitSet stream
|
||||
* @bug 8012645 8076442
|
||||
* @requires os.maxMemory >= 2g
|
||||
* @library /lib/testlibrary/bootlib
|
||||
* @build java.base/java.util.SpliteratorTestHelper
|
||||
* java.base/java.util.SpliteratorOfIntDataBuilder
|
||||
* @run testng/othervm -Xms512m -Xmx1024m BitSetStreamTest
|
||||
*/
|
||||
public class BitSetStreamTest extends SpliteratorTestHelper {
|
||||
static class Fibs implements IntSupplier {
|
||||
private int n1 = 0;
|
||||
private int n2 = 1;
|
||||
|
||||
static int fibs(int n) {
|
||||
Fibs f = new Fibs();
|
||||
while (n-- > 0) f.getAsInt();
|
||||
return f.getAsInt();
|
||||
}
|
||||
|
||||
public int getAsInt() { int s = n1; n1 = n2; n2 = s + n1; return s; }
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFibs() {
|
||||
Fibs f = new Fibs();
|
||||
assertEquals(0, f.getAsInt());
|
||||
assertEquals(1, f.getAsInt());
|
||||
assertEquals(1, f.getAsInt());
|
||||
assertEquals(2, f.getAsInt());
|
||||
assertEquals(3, f.getAsInt());
|
||||
assertEquals(5, f.getAsInt());
|
||||
assertEquals(8, f.getAsInt());
|
||||
assertEquals(13, f.getAsInt());
|
||||
assertEquals(987, Fibs.fibs(16));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "cases")
|
||||
public static Object[][] produceCases() {
|
||||
return new Object[][] {
|
||||
{ "none", IntStream.empty() },
|
||||
{ "index 0", IntStream.of(0) },
|
||||
{ "index 255", IntStream.of(255) },
|
||||
{ "index 0 and 255", IntStream.of(0, 255) },
|
||||
{ "index Integer.MAX_VALUE", IntStream.of(Integer.MAX_VALUE) },
|
||||
{ "index Integer.MAX_VALUE - 1", IntStream.of(Integer.MAX_VALUE - 1) },
|
||||
{ "index 0 and Integer.MAX_VALUE", IntStream.of(0, Integer.MAX_VALUE) },
|
||||
{ "every bit", IntStream.range(0, 255) },
|
||||
{ "step 2", IntStream.range(0, 255).map(f -> f * 2) },
|
||||
{ "step 3", IntStream.range(0, 255).map(f -> f * 3) },
|
||||
{ "step 5", IntStream.range(0, 255).map(f -> f * 5) },
|
||||
{ "step 7", IntStream.range(0, 255).map(f -> f * 7) },
|
||||
{ "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000) },
|
||||
{ "25 fibs", IntStream.generate(new Fibs()).limit(25) }
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "cases")
|
||||
public void testBitsetStream(String name, IntStream data) {
|
||||
BitSet bs = data.collect(BitSet::new, BitSet::set, BitSet::or);
|
||||
|
||||
assertEquals(bs.cardinality(), bs.stream().count());
|
||||
|
||||
int[] indexHolder = new int[] { -1 };
|
||||
bs.stream().forEach(i -> {
|
||||
int ei = indexHolder[0];
|
||||
indexHolder[0] = bs.nextSetBit(ei + 1);
|
||||
assertEquals(i, indexHolder[0]);
|
||||
});
|
||||
|
||||
PrimitiveIterator.OfInt it = bs.stream().iterator();
|
||||
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(it.nextInt(), i);
|
||||
if (i == Integer.MAX_VALUE)
|
||||
break; // or (i + 1) would overflow
|
||||
}
|
||||
assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
static Object[][] spliteratorOfIntDataProvider;
|
||||
|
||||
@DataProvider(name = "BitSet.stream.spliterator")
|
||||
public static Object[][] spliteratorOfIntDataProvider() {
|
||||
if (spliteratorOfIntDataProvider != null) {
|
||||
return spliteratorOfIntDataProvider;
|
||||
}
|
||||
|
||||
List<Object[]> data = new ArrayList<>();
|
||||
|
||||
Object[][] bitStreamTestcases = new Object[][] {
|
||||
{ "none", IntStream.empty().toArray() },
|
||||
{ "index 0", IntStream.of(0).toArray() },
|
||||
{ "index 255", IntStream.of(255).toArray() },
|
||||
{ "index 0 and 255", IntStream.of(0, 255).toArray() },
|
||||
{ "index Integer.MAX_VALUE", IntStream.of(Integer.MAX_VALUE).toArray() },
|
||||
{ "index Integer.MAX_VALUE - 1", IntStream.of(Integer.MAX_VALUE - 1).toArray() },
|
||||
{ "index 0 and Integer.MAX_VALUE", IntStream.of(0, Integer.MAX_VALUE).toArray() },
|
||||
{ "every bit", IntStream.range(0, 255).toArray() },
|
||||
{ "step 2", IntStream.range(0, 255).map(f -> f * 2).toArray() },
|
||||
{ "step 3", IntStream.range(0, 255).map(f -> f * 3).toArray() },
|
||||
{ "step 5", IntStream.range(0, 255).map(f -> f * 5).toArray() },
|
||||
{ "step 7", IntStream.range(0, 255).map(f -> f * 7).toArray() },
|
||||
{ "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000).toArray() },
|
||||
};
|
||||
for (Object[] tc : bitStreamTestcases) {
|
||||
String description = (String)tc[0];
|
||||
int[] exp = (int[])tc[1];
|
||||
SpliteratorOfIntDataBuilder db = new SpliteratorOfIntDataBuilder(
|
||||
data, IntStream.of(exp).boxed().collect(toList()));
|
||||
|
||||
db.add("BitSet.stream.spliterator() {" + description + "}", () ->
|
||||
IntStream.of(exp).collect(BitSet::new, BitSet::set, BitSet::or).
|
||||
stream().spliterator()
|
||||
);
|
||||
}
|
||||
return spliteratorOfIntDataProvider = data.toArray(new Object[0][]);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntNullPointerException(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
assertThrows(NullPointerException.class, () -> s.get().forEachRemaining((IntConsumer) null));
|
||||
assertThrows(NullPointerException.class, () -> s.get().tryAdvance((IntConsumer) null));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntForEach(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testForEach(exp, s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntTryAdvance(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testTryAdvance(exp, s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntMixedTryAdvanceForEach(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testMixedTryAdvanceForEach(exp, s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntMixedTraverseAndSplit(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testMixedTraverseAndSplit(exp, s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntSplitAfterFullTraversal(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testSplitAfterFullTraversal(s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntSplitOnce(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testSplitOnce(exp, s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntSplitSixDeep(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testSplitSixDeep(exp, s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "BitSet.stream.spliterator")
|
||||
public void testIntSplitUntilNull(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
|
||||
testSplitUntilNull(exp, s, intBoxingConsumer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandomStream() {
|
||||
final int size = 1024 * 1024;
|
||||
final int[] seeds = {
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
|
||||
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
|
||||
final byte[] bytes = new byte[size];
|
||||
for (int seed : seeds) {
|
||||
final Random random = new Random(seed);
|
||||
random.nextBytes(bytes);
|
||||
|
||||
BitSet bitSet = BitSet.valueOf(bytes);
|
||||
testBitSetContents(bitSet, bitSet.stream().toArray());
|
||||
testBitSetContents(bitSet, bitSet.stream().parallel().toArray());
|
||||
}
|
||||
}
|
||||
|
||||
void testBitSetContents(BitSet bitSet, int[] array) {
|
||||
int cardinality = bitSet.cardinality();
|
||||
assertEquals(array.length, cardinality);
|
||||
int nextSetBit = -1;
|
||||
for (int i = 0; i < cardinality; i++) {
|
||||
nextSetBit = bitSet.nextSetBit(nextSetBit + 1);
|
||||
assertEquals(array[i], nextSetBit);
|
||||
}
|
||||
}
|
||||
}
|
||||
244
test/jdk/java/util/Calendar/BuddhistCalendarTest.java
Normal file
244
test/jdk/java/util/Calendar/BuddhistCalendarTest.java
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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(), set(), and toString()
|
||||
* work correctly with Buddhist Era years.
|
||||
* @run junit BuddhistCalendarTest
|
||||
*/
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Calendar.APRIL;
|
||||
import static java.util.Calendar.DATE;
|
||||
import static java.util.Calendar.DECEMBER;
|
||||
import static java.util.Calendar.ERA;
|
||||
import static java.util.Calendar.FEBRUARY;
|
||||
import static java.util.Calendar.JANUARY;
|
||||
import static java.util.Calendar.MAY;
|
||||
import static java.util.Calendar.MONTH;
|
||||
import static java.util.Calendar.WEEK_OF_YEAR;
|
||||
import static java.util.Calendar.YEAR;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class BuddhistCalendarTest {
|
||||
|
||||
private static final Locale THAI_LOCALE = Locale.of("th", "TH");
|
||||
|
||||
/*
|
||||
* Test some add values for the BuddhistCalendar. This test compares the same field
|
||||
* as the one added.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("addDataProvider")
|
||||
public void buddhistAddTest(Calendar cal, int amount, int fieldToAdd) {
|
||||
int base = cal.get(YEAR);
|
||||
cal.add(fieldToAdd, amount);
|
||||
int yearAfterRoll = cal.get(YEAR);
|
||||
assertEquals(yearAfterRoll, base+amount, String.format(
|
||||
"Added: %s to field: %s", amount, fieldToAdd));
|
||||
}
|
||||
|
||||
/*
|
||||
* Given in the format: Calendar, amount to add, and field to add.
|
||||
* Test adding of positive and negative year values.
|
||||
*/
|
||||
private static Stream<Arguments> addDataProvider() {
|
||||
return Stream.of(
|
||||
Arguments.of(getBuddhistCalendar(), 1, YEAR),
|
||||
Arguments.of(getBuddhistCalendar(), -3, YEAR)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test some add values for the BuddhistCalendar. Compare a bigger field
|
||||
* (year) than the one added (month). Larger field should roll over.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("alternateAddDataProvider")
|
||||
public void buddhistAlternateAddTest(Calendar cal, int amount, int fieldToAdd) {
|
||||
int base = cal.get(YEAR);
|
||||
cal.add(fieldToAdd, amount);
|
||||
int yearAfterRoll = cal.get(YEAR);
|
||||
assertEquals(yearAfterRoll, (amount>0) ? (base+1): (base-1), String.format(
|
||||
"Added: %s to field: %s", amount, fieldToAdd));
|
||||
}
|
||||
|
||||
/*
|
||||
* Given in the format: Calendar, amount to add, and field to add.
|
||||
* Test adding of positive and negative month values.
|
||||
*/
|
||||
private static Stream<Arguments> alternateAddDataProvider() {
|
||||
return Stream.of(
|
||||
Arguments.of(getBuddhistCalendarBuilder().set(MONTH, DECEMBER).build(), 2, MONTH),
|
||||
Arguments.of(getBuddhistCalendarBuilder().set(MONTH, FEBRUARY).build(), -4, MONTH)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test some roll values for the BuddhistCalendar. Compare same field
|
||||
* that was rolled, value should change.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("rollProvider")
|
||||
public void buddhistRollTest(Calendar cal, int amount, int fieldToRoll) {
|
||||
int base = cal.get(YEAR);
|
||||
cal.roll(fieldToRoll, amount);
|
||||
int year = cal.get(YEAR);
|
||||
assertEquals(year, base+amount, "Rolling field should change value");
|
||||
}
|
||||
|
||||
/*
|
||||
* Given in the format: Calendar, amount to roll, and field to roll.
|
||||
* Test rolling of positive and negative year values.
|
||||
*/
|
||||
private static Stream<Arguments> rollProvider() {
|
||||
return Stream.of(
|
||||
Arguments.of(getBuddhistCalendar(), 2, YEAR),
|
||||
Arguments.of(getBuddhistCalendar(), -4, YEAR)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set some calendar values and roll, however, measure a different
|
||||
* field than the field that was rolled. Rolling should not change the
|
||||
* larger field.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("alternateRollProvider")
|
||||
public void buddhistAlternateRollTest(Calendar cal, int amount, int fieldToRoll) {
|
||||
int base = cal.get(YEAR);
|
||||
cal.roll(fieldToRoll, amount);
|
||||
int year = cal.get(YEAR);
|
||||
assertEquals(year, base, "Rolling smaller field should not change bigger field");
|
||||
}
|
||||
|
||||
/*
|
||||
* Given in the format: Calendar, amount to roll, and field to roll.
|
||||
* Test rolling of positive and negative week_of_year values.
|
||||
*/
|
||||
private static Stream<Arguments> alternateRollProvider() {
|
||||
return Stream.of(
|
||||
Arguments.of(getBuddhistCalendarBuilder().set(YEAR, 2543)
|
||||
.set(MONTH, DECEMBER).set(DATE, 31).build(), 10, WEEK_OF_YEAR),
|
||||
Arguments.of(getBuddhistCalendarBuilder().set(YEAR, 2543)
|
||||
.set(MONTH, JANUARY).set(DATE, 1).build(), -10, WEEK_OF_YEAR)
|
||||
);
|
||||
}
|
||||
|
||||
// Test the overloaded set() methods. Check year value.
|
||||
@Test
|
||||
public void buddhistSetTest() {
|
||||
Calendar cal = getBuddhistCalendar();
|
||||
cal.set(3001, APRIL, 10);
|
||||
assertEquals(cal.get(YEAR), 3001);
|
||||
cal.set(3020, MAY, 20, 9, 10);
|
||||
assertEquals(cal.get(YEAR), 3020);
|
||||
cal.set(3120, MAY, 20, 9, 10, 52 );
|
||||
assertEquals(cal.get(YEAR), 3120);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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() and get().
|
||||
*/
|
||||
@Test
|
||||
public void buddhistActualMaximumTest() {
|
||||
Calendar cal = getBuddhistCalendar();
|
||||
int base = cal.get(YEAR);
|
||||
int ignored = cal.getActualMaximum(YEAR);
|
||||
int year = cal.get(YEAR);
|
||||
assertEquals(year, base, "BuddhistCalendar.getActualMaximum(YEAR)");
|
||||
}
|
||||
|
||||
// Test BuddhistCalendar.getActualMinimum(YEAR), doesn't call set(YEAR) nor get(YEAR).
|
||||
@Test
|
||||
public void buddhistActualMinimumTest() {
|
||||
Calendar cal = getBuddhistCalendar();
|
||||
int base = cal.get(YEAR);
|
||||
int ignored = cal.getActualMinimum(YEAR);
|
||||
int year = cal.get(YEAR);
|
||||
assertEquals(year, base, "BuddhistCalendar.getActualMinimum(YEAR)");
|
||||
}
|
||||
|
||||
// 4847186: BuddhistCalendar: toString() returns Gregorian year
|
||||
@Test
|
||||
public void buddhistToStringTest() {
|
||||
Calendar cal = getBuddhistCalendar();
|
||||
int year = cal.get(YEAR);
|
||||
String s = cal.toString();
|
||||
String y = s.replaceAll(".+,YEAR=(\\d+),.+", "$1");
|
||||
assertEquals(year, Integer.parseInt(y), "Wrong year value");
|
||||
}
|
||||
|
||||
// 4956479: BuddhistCalendar methods may return wrong values after exception
|
||||
@Test
|
||||
public void buddhistValuesAfterExceptionTest() {
|
||||
Calendar cal = getBuddhistCalendar();
|
||||
int year = cal.get(YEAR);
|
||||
assertThrows(IllegalArgumentException.class, ()-> cal.add(100, +1));
|
||||
int year2 = cal.get(YEAR);
|
||||
assertEquals(year2, year, "Wrong year value after exception thrown");
|
||||
}
|
||||
|
||||
// 4956227: getLeastMaximum(WEEK_OF_MONTH) return diff. val. for Greg. and Buddhist Calendar
|
||||
@Test
|
||||
public void buddhistLeastMaximumTest() {
|
||||
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);
|
||||
assertEquals(bn, gn, "Inconsistent Least Max value for " + Koyomi.getFieldName(f));
|
||||
}
|
||||
}
|
||||
|
||||
// Utility to get a new Buddhist Calendar Builder (to allow setting of other values)
|
||||
private static Calendar.Builder getBuddhistCalendarBuilder() {
|
||||
return new Calendar.Builder().setLocale(THAI_LOCALE);
|
||||
}
|
||||
|
||||
// Utility to get a new Buddhist calendar
|
||||
private static Calendar getBuddhistCalendar() {
|
||||
return Calendar.getInstance(THAI_LOCALE);
|
||||
}
|
||||
}
|
||||
47
test/jdk/java/util/Calendar/Bug4302966.java
Normal file
47
test/jdk/java/util/Calendar/Bug4302966.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8176841
|
||||
* @modules jdk.localedata
|
||||
* @summary In Czech Republic first day of week is Monday not Sunday
|
||||
* @run junit Bug4302966
|
||||
*/
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class Bug4302966 {
|
||||
|
||||
// Specific day of week test for Czech locale
|
||||
public void czechDayOfWeekTest() {
|
||||
Calendar czechCalendar = Calendar.getInstance(Locale.of("cs", "CZ"));
|
||||
int firstDayOfWeek = czechCalendar.getFirstDayOfWeek();
|
||||
assertEquals(firstDayOfWeek, Calendar.MONDAY);
|
||||
}
|
||||
}
|
||||
58
test/jdk/java/util/Calendar/Bug4766302.java
Normal file
58
test/jdk/java/util/Calendar/Bug4766302.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 calling computeTime doesn't reset the isTimeSet value.
|
||||
* @run junit Bug4766302
|
||||
*/
|
||||
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class Bug4766302 {
|
||||
|
||||
// Extend GregorianCalendar to check the protected value of isTimeSet
|
||||
@SuppressWarnings("serial")
|
||||
static class MyCalendar extends GregorianCalendar {
|
||||
boolean isTimeStillSet() {
|
||||
return isTimeSet;
|
||||
}
|
||||
|
||||
protected void computeTime() {
|
||||
super.computeTime();
|
||||
}
|
||||
}
|
||||
|
||||
// Check the value of isTimeStillSet() after calling computeTime()
|
||||
@Test
|
||||
public void validateIsTimeSetTest() {
|
||||
MyCalendar cal = new MyCalendar();
|
||||
cal.computeTime();
|
||||
assertTrue(cal.isTimeStillSet(), "computeTime() call reset isTimeSet.");
|
||||
}
|
||||
}
|
||||
59
test/jdk/java/util/Calendar/Bug4851640.java
Normal file
59
test/jdk/java/util/Calendar/Bug4851640.java
Normal file
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
257
test/jdk/java/util/Calendar/Bug4958050.java
Normal file
257
test/jdk/java/util/Calendar/Bug4958050.java
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* 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(" + Koyomi.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(" + Koyomi.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(" + Koyomi.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(" + Koyomi.getFieldName(weekFields[i]) + ", +1)\n"
|
||||
+ cal.getMessage() + " " + cal.toDateTimeString());
|
||||
}
|
||||
}
|
||||
|
||||
// Test the day fields
|
||||
int[] dayFields = {DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK};
|
||||
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(" + Koyomi.getFieldName(field) + ", +1)\n"
|
||||
+ cal.getMessage() + " " + cal.toDateTimeString());
|
||||
}
|
||||
cal.clear();
|
||||
cal.set(1919, DECEMBER, 14, 00, 00, 00);
|
||||
cal.add(field, -1);
|
||||
if (!cal.checkDate(1919, DECEMBER, 13)) {
|
||||
error("1919/12/14: add(" + Koyomi.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(" + Koyomi.getFieldName(field) + ", +1)\n"
|
||||
+ cal.getMessage() + cal.toDateTimeString());
|
||||
}
|
||||
cal.clear();
|
||||
cal.set(1930, JUNE, 21, 01, 00, 00);
|
||||
cal.add(field, -1);
|
||||
if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) {
|
||||
error("1930/6/21: add(" + Koyomi.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(" + Koyomi.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(" + Koyomi.getFieldName(field) + ", " + amount + ")\n"
|
||||
+ cal.getMessage() + " " + cal.toDateTimeString());
|
||||
}
|
||||
}
|
||||
|
||||
// Test the AM_PM field
|
||||
// add()
|
||||
cal.clear();
|
||||
cal.set(1919, DECEMBER, 14 - 1, 23, 50, 00);
|
||||
cal.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)");
|
||||
}
|
||||
}
|
||||
}
|
||||
100
test/jdk/java/util/Calendar/Bug5078053.java
Normal file
100
test/jdk/java/util/Calendar/Bug5078053.java
Normal file
|
|
@ -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)");
|
||||
}
|
||||
}
|
||||
}
|
||||
50
test/jdk/java/util/Calendar/Bug6178071.java
Normal file
50
test/jdk/java/util/Calendar/Bug6178071.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
97
test/jdk/java/util/Calendar/Bug6234795.java
Normal file
97
test/jdk/java/util/Calendar/Bug6234795.java
Normal file
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
58
test/jdk/java/util/Calendar/Bug6448234.java
Normal file
58
test/jdk/java/util/Calendar/Bug6448234.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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(Locale.of("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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
test/jdk/java/util/Calendar/Bug6645263.java
Normal file
47
test/jdk/java/util/Calendar/Bug6645263.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 6645263
|
||||
* @summary Test field normalization in non-lenient from the partially normalized state
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Bug6645263 {
|
||||
public static void main(String[] args) {
|
||||
Calendar cal = new GregorianCalendar(Locale.US);
|
||||
cal.setLenient(false);
|
||||
cal.set(Calendar.YEAR, 2007);
|
||||
cal.set(Calendar.MONTH, Calendar.NOVEMBER);
|
||||
cal.set(Calendar.WEEK_OF_MONTH, 4);
|
||||
cal.set(Calendar.DAY_OF_WEEK, 1);
|
||||
// Let cal calculate the time from the given fields
|
||||
cal.getTime();
|
||||
|
||||
// Change DAY_OF_MONTH
|
||||
cal.set(Calendar.DAY_OF_MONTH, 1);
|
||||
// The following line shouldn't throw an IllegalArgumentException.
|
||||
cal.getTime();
|
||||
}
|
||||
}
|
||||
70
test/jdk/java/util/Calendar/Bug6902861.java
Normal file
70
test/jdk/java/util/Calendar/Bug6902861.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 6902861
|
||||
* @summary Test for a workaround when WEEK_OF_YEAR and YEAR are out of sync.
|
||||
* @modules jdk.localedata
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import static java.util.GregorianCalendar.*;
|
||||
|
||||
public class Bug6902861 {
|
||||
static int errors = 0;
|
||||
|
||||
public static void main(String [] args) {
|
||||
Locale loc = Locale.getDefault();
|
||||
try {
|
||||
Locale.setDefault(Locale.GERMANY);
|
||||
test(2010, JANUARY, 1, +1, 1);
|
||||
test(2010, JANUARY, 1, +2, 2);
|
||||
test(2010, JANUARY, 1, -1, 52);
|
||||
test(2010, JANUARY, 1, -2, 51);
|
||||
test(2008, DECEMBER, 31, +1, 1);
|
||||
test(2008, DECEMBER, 31, +2, 2);
|
||||
test(2008, DECEMBER, 31, -1, 52);
|
||||
test(2008, DECEMBER, 31, -2, 51);
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException("Failed");
|
||||
}
|
||||
} finally {
|
||||
Locale.setDefault(loc);
|
||||
}
|
||||
}
|
||||
|
||||
static void test(int year, int month, int dayOfMonth, int amount, int expected) {
|
||||
Calendar calendar = new GregorianCalendar(year, month, dayOfMonth);
|
||||
int week = calendar.get(WEEK_OF_YEAR); // fix the date
|
||||
calendar.roll(WEEK_OF_YEAR, amount);
|
||||
int got = calendar.get(WEEK_OF_YEAR);
|
||||
int y = calendar.get(YEAR);
|
||||
if (got != expected || y != year) {
|
||||
String date = String.format("%04d-%02d-%02d", year, month+1, dayOfMonth);
|
||||
System.err.printf("%s: roll %+d: got: %d,%2d; expected: %d,%2d%n",
|
||||
date, amount, y, got, year, expected);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
125
test/jdk/java/util/Calendar/Bug7017458.java
Normal file
125
test/jdk/java/util/Calendar/Bug7017458.java
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 7017458
|
||||
* @summary Test of multithreaded serialization/deserialization of Calendar.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Bug7017458 {
|
||||
|
||||
static volatile boolean err = false;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
new Bug7017458().perform();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
err = true;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
throw new RuntimeException("Multithreaded serialization/deserialization test failed.");
|
||||
} else {
|
||||
System.out.println("Multithreaded serialization/deserialization test passed.");
|
||||
}
|
||||
}
|
||||
|
||||
public void perform() throws Exception {
|
||||
int nbThreads = 8;
|
||||
Calendar cal = Calendar.getInstance();
|
||||
SerializationThread[] threads = new SerializationThread[nbThreads];
|
||||
for (int i = 0; i < nbThreads; i++) {
|
||||
threads[i] = new SerializationThread(cal);
|
||||
}
|
||||
for (int i = 0; i < nbThreads; i++) {
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < nbThreads; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
DeserializationThread[] threads2 = new DeserializationThread[nbThreads];
|
||||
for (int i = 0; i < nbThreads; i++) {
|
||||
threads2[i] = new DeserializationThread(threads[i].data);
|
||||
}
|
||||
for (int i = 0; i < nbThreads; i++) {
|
||||
threads2[i].start();
|
||||
}
|
||||
for (int i = 0; i < nbThreads; i++) {
|
||||
threads2[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializationThread extends Thread {
|
||||
private Calendar cal;
|
||||
public byte[] data;
|
||||
|
||||
public SerializationThread(Calendar cal) {
|
||||
this.cal = cal;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(cal);
|
||||
oos.flush();
|
||||
oos.close();
|
||||
data = baos.toByteArray();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DeserializationThread extends Thread {
|
||||
public Calendar cal;
|
||||
public byte[] data;
|
||||
|
||||
public DeserializationThread(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
cal = (Calendar) ois.readObject();
|
||||
ois.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
111
test/jdk/java/util/Calendar/Bug8007038.java
Normal file
111
test/jdk/java/util/Calendar/Bug8007038.java
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8007038 8247781 8174269
|
||||
* @summary Verify ArrayIndexOutOfBoundsException is not thrown
|
||||
* on calling localizedDateTime().print() with JapaneseChrono
|
||||
* @modules java.base/sun.util.locale.provider
|
||||
* @modules jdk.localedata
|
||||
* @compile -XDignore.symbol.file Bug8007038.java
|
||||
* @run main Bug8007038 CLDR
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import static java.util.Calendar.*;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
|
||||
public class Bug8007038 {
|
||||
private static final String[] calTypes = {
|
||||
"gregory",
|
||||
"buddhist",
|
||||
"japanese",
|
||||
"roc",
|
||||
"islamic",
|
||||
};
|
||||
private static final int[][] eraMinMax = {
|
||||
{GregorianCalendar.BC, GregorianCalendar.AD},
|
||||
{0, 1},
|
||||
{0, 5},
|
||||
{0, 1},
|
||||
{0, 1},
|
||||
{0, 1},
|
||||
};
|
||||
private static final Locale[] testLocs = {
|
||||
Locale.ROOT,
|
||||
Locale.forLanguageTag("ja-JP-u-ca-japanese"),
|
||||
Locale.forLanguageTag("th-TH"),
|
||||
Locale.forLanguageTag("th-TH-u-ca-buddhist"),
|
||||
Locale.forLanguageTag("zh-TW-u-ca-roc"),
|
||||
Locale.forLanguageTag("ar-EG-u-ca-islamic"),
|
||||
Locale.forLanguageTag("xx-YY-u-ca-bogus"),
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int calIdx = 0; calIdx < calTypes.length; calIdx++) {
|
||||
for (int locIdx = 0; locIdx < testLocs.length; locIdx++) {
|
||||
// era
|
||||
for (int fieldIdx = eraMinMax[calIdx][0]; fieldIdx <= eraMinMax[calIdx][1]; fieldIdx++) {
|
||||
checkValueRange(calTypes[calIdx], ERA, fieldIdx, LONG, testLocs[locIdx], true);
|
||||
}
|
||||
checkValueRange(calTypes[calIdx], ERA, eraMinMax[calIdx][0]-1, LONG,
|
||||
testLocs[locIdx], false);
|
||||
checkValueRange(calTypes[calIdx], ERA, eraMinMax[calIdx][1]+1,
|
||||
LONG, testLocs[locIdx], false);
|
||||
|
||||
// month
|
||||
for (int fieldIdx = JANUARY; fieldIdx <= UNDECIMBER ; fieldIdx++) {
|
||||
checkValueRange(calTypes[calIdx], MONTH, fieldIdx, LONG, testLocs[locIdx], true);
|
||||
}
|
||||
checkValueRange(calTypes[calIdx], MONTH, JANUARY-1, LONG, testLocs[locIdx], false);
|
||||
checkValueRange(calTypes[calIdx], MONTH, UNDECIMBER+1, LONG, testLocs[locIdx], false);
|
||||
|
||||
// day-of-week
|
||||
for (int fieldIdx = SUNDAY; fieldIdx <= SATURDAY; fieldIdx++) {
|
||||
checkValueRange(calTypes[calIdx], DAY_OF_WEEK, fieldIdx, LONG, testLocs[locIdx], true);
|
||||
}
|
||||
checkValueRange(calTypes[calIdx], DAY_OF_WEEK, SUNDAY-1, LONG, testLocs[locIdx], false);
|
||||
checkValueRange(calTypes[calIdx], DAY_OF_WEEK, SATURDAY+1, LONG, testLocs[locIdx], false);
|
||||
|
||||
// am/pm
|
||||
int lastIndex = args[0].equals("CLDR") ? 11 : PM;
|
||||
for (int fieldIdx = AM; fieldIdx <= lastIndex; fieldIdx++) {
|
||||
checkValueRange(calTypes[calIdx], AM_PM, fieldIdx, LONG, testLocs[locIdx], true);
|
||||
}
|
||||
checkValueRange(calTypes[calIdx], AM_PM, AM-1, LONG, testLocs[locIdx], false);
|
||||
checkValueRange(calTypes[calIdx], AM_PM, lastIndex+1, LONG, testLocs[locIdx], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkValueRange(String calType, int field, int value, int style, Locale l, boolean isNonNull) {
|
||||
String ret = CalendarDataUtility.retrieveJavaTimeFieldValueName(calType, field, value, style, l);
|
||||
System.out.print("retrieveFieldValueName("+calType+", "+field+", "+value+", "+style+", "+l+")");
|
||||
if ((ret != null) == isNonNull) {
|
||||
System.out.println(" returned "+ret);
|
||||
} else {
|
||||
throw new RuntimeException("The call returned "+ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
108
test/jdk/java/util/Calendar/Bug8075548.java
Normal file
108
test/jdk/java/util/Calendar/Bug8075548.java
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8075548
|
||||
* @summary Make sure that the format form of month names are produced when there are
|
||||
* no stand-alone ones available.
|
||||
*/
|
||||
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import static java.util.Calendar.*;
|
||||
|
||||
public class Bug8075548 {
|
||||
static int errors = 0;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.US).parse("2010-09-15");
|
||||
String[][] FORMAT_PAIRS = {
|
||||
{ "LLLL", "MMMM" },
|
||||
{ "LLL", "MMM" }
|
||||
};
|
||||
Locale[] LOCALES = {
|
||||
Locale.ENGLISH, Locale.JAPANESE
|
||||
};
|
||||
|
||||
for (Locale locale : LOCALES) {
|
||||
for (String[] formats : FORMAT_PAIRS) {
|
||||
String el = new SimpleDateFormat(formats[0], locale).format(date);
|
||||
String em = new SimpleDateFormat(formats[1], locale).format(date);
|
||||
if (!el.equals(em)) {
|
||||
errors++;
|
||||
System.err.println(locale + ": " +
|
||||
formats[0] + " -> " + el + ", " +
|
||||
formats[1] + " -> " + em);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test Calendar.getDisplayName() and .getDisplayNames().
|
||||
for (Locale locale : LOCALES) {
|
||||
testDisplayNames(locale, LONG_FORMAT, LONG_STANDALONE);
|
||||
testDisplayNames(locale, SHORT_FORMAT, SHORT_STANDALONE);
|
||||
testDisplayNames(locale, NARROW_FORMAT, NARROW_STANDALONE);
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException("Failed");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testDisplayNames(Locale locale, int formatStyle, int standaloneStyle) {
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
for (int month = JANUARY; month <= DECEMBER; month++) {
|
||||
Calendar cal = new GregorianCalendar(2015, month, 1);
|
||||
String format = cal.getDisplayName(MONTH, formatStyle, locale);
|
||||
String standalone = cal.getDisplayName(MONTH, standaloneStyle, locale);
|
||||
if (!format.equals(standalone)) {
|
||||
System.err.println("Calendar.getDisplayName: " + (month+1) +
|
||||
", locale=" + locale +
|
||||
", format=" + format + ", standalone=" + standalone);
|
||||
errors++;
|
||||
}
|
||||
if (standalone != null) {
|
||||
map.put(standalone, month);
|
||||
}
|
||||
}
|
||||
if (formatStyle == NARROW_FORMAT) {
|
||||
// Narrow styles don't support unique names.
|
||||
// (e.g., "J" for JANUARY, JUNE, and JULY)
|
||||
return;
|
||||
}
|
||||
Calendar cal = new GregorianCalendar(2015, JANUARY, 1);
|
||||
Map<String, Integer> mapStandalone = cal.getDisplayNames(MONTH, standaloneStyle, locale);
|
||||
if (!map.equals(mapStandalone)) {
|
||||
System.err.printf("Calendar.getDisplayNames: locale=%s%n map=%s%n mapStandalone=%s%n",
|
||||
locale, map, mapStandalone);
|
||||
errors++;
|
||||
}
|
||||
Map<String, Integer> mapAll = cal.getDisplayNames(MONTH, ALL_STYLES, locale);
|
||||
if (!mapAll.entrySet().containsAll(map.entrySet())) {
|
||||
System.err.printf("Calendar.getDisplayNames: locale=%s%n map=%s%n mapAll=%s%n",
|
||||
locale, map, mapAll);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
135
test/jdk/java/util/Calendar/Bug8152077.java
Normal file
135
test/jdk/java/util/Calendar/Bug8152077.java
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8152077
|
||||
* @summary Make sure that roll() with HOUR/HOUR_OF_DAY works around standard/daylight
|
||||
* time transitions
|
||||
*/
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
import static java.util.Calendar.*;
|
||||
|
||||
public class Bug8152077 {
|
||||
private static final TimeZone LA = TimeZone.getTimeZone("America/Los_Angeles");
|
||||
private static final TimeZone BR = TimeZone.getTimeZone("America/Sao_Paulo");
|
||||
|
||||
private static final int[] ALLDAY_HOURS = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
|
||||
};
|
||||
private static final int[] AM_HOURS = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
||||
};
|
||||
private static final int[] PM_HOURS = { // in 24-hour clock
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
|
||||
};
|
||||
|
||||
private static int errors;
|
||||
|
||||
public static void main(String[] args) {
|
||||
TimeZone initialTz = TimeZone.getDefault();
|
||||
try {
|
||||
testRoll(LA, new int[] { 2016, MARCH, 13 },
|
||||
new int[] { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 });
|
||||
testRoll(LA, new int[] { 2016, MARCH, 13 },
|
||||
new int[] { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11 });
|
||||
testRoll(LA, new int[] { 2016, MARCH, 13 }, PM_HOURS);
|
||||
|
||||
testRoll(LA, new int[] { 2016, NOVEMBER, 6 }, ALLDAY_HOURS);
|
||||
testRoll(LA, new int[] { 2016, NOVEMBER, 6 }, AM_HOURS);
|
||||
testRoll(LA, new int[] { 2016, NOVEMBER, 6 }, PM_HOURS);
|
||||
|
||||
testRoll(BR, new int[] { 2016, FEBRUARY, 21 }, ALLDAY_HOURS);
|
||||
testRoll(BR, new int[] { 2016, FEBRUARY, 21 }, AM_HOURS);
|
||||
testRoll(BR, new int[] { 2016, FEBRUARY, 21 }, PM_HOURS);
|
||||
|
||||
testRoll(BR, new int[] { 2016, OCTOBER, 15 }, ALLDAY_HOURS);
|
||||
testRoll(BR, new int[] { 2016, OCTOBER, 15 }, PM_HOURS);
|
||||
testRoll(BR, new int[] { 2016, OCTOBER, 16 },
|
||||
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 });
|
||||
testRoll(BR, new int[] { 2016, OCTOBER, 16 },
|
||||
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 });
|
||||
testRoll(BR, new int[] { 2016, OCTOBER, 16 }, PM_HOURS);
|
||||
} finally {
|
||||
TimeZone.setDefault(initialTz);
|
||||
}
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testRoll(TimeZone tz, int[] params, int[] sequence) {
|
||||
TimeZone.setDefault(tz);
|
||||
for (int i = 0; i < sequence.length; i++) {
|
||||
testRoll(+1, params, sequence, i);
|
||||
testRoll(-1, params, sequence, i);
|
||||
}
|
||||
}
|
||||
|
||||
// amount must be 1 or -1.
|
||||
private static void testRoll(int amount, int[] params, int[] sequence, int startIndex) {
|
||||
int year = params[0];
|
||||
int month = params[1];
|
||||
int dayOfMonth = params[2];
|
||||
int hourOfDay = sequence[startIndex];
|
||||
Calendar cal = new GregorianCalendar(year, month, dayOfMonth,
|
||||
hourOfDay, 0, 0);
|
||||
int ampm = cal.get(AM_PM);
|
||||
|
||||
int length = sequence.length;
|
||||
int count = length * 2;
|
||||
int field = (length > 12) ? HOUR_OF_DAY : HOUR;
|
||||
|
||||
System.out.printf("roll(%s, %2d) starting from %s%n",
|
||||
(field == HOUR) ? "HOUR" : "HOUR_OF_DAY", amount, cal.getTime());
|
||||
for (int i = 0; i < count; i++) {
|
||||
int index = (amount > 0) ? (startIndex + i + 1) % length
|
||||
: Math.floorMod(startIndex - i - 1, length);
|
||||
int expected = sequence[index];
|
||||
if (field == HOUR) {
|
||||
expected %= 12;
|
||||
}
|
||||
cal.roll(field, amount);
|
||||
int value = cal.get(field);
|
||||
if (value != expected) {
|
||||
System.out.println("Unexpected field value: got=" + value
|
||||
+ ", expected=" + expected);
|
||||
errors++;
|
||||
}
|
||||
if (cal.get(DAY_OF_MONTH) != dayOfMonth) {
|
||||
System.out.println("DAY_OF_MONTH changed: " + dayOfMonth
|
||||
+ " to " + cal.get(DAY_OF_MONTH));
|
||||
}
|
||||
if (field == HOUR && cal.get(AM_PM) != ampm) {
|
||||
System.out.println("AM_PM changed: " + ampm + " to " + cal.get(AM_PM));
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
153
test/jdk/java/util/Calendar/Bug8167273.java
Normal file
153
test/jdk/java/util/Calendar/Bug8167273.java
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8167273 8251317 8258794 8174269
|
||||
* @summary Test
|
||||
* Era names retrieved from Calendar and DateFormatSymbols class
|
||||
* should match for default providers preference
|
||||
* Empty era names are not retrieved from DateFormatSymbols class.
|
||||
* Equivalent locales specified for [zh-HK, no-NO, no] for
|
||||
* CLDR Provider works correctly.
|
||||
* Implicit COMPAT Locale nb is reflected in available locales
|
||||
* @modules java.base/sun.util.locale.provider
|
||||
* java.base/sun.util.spi
|
||||
* jdk.localedata
|
||||
* @run main Bug8167273 testEraName
|
||||
* @run main Bug8167273 testCldr
|
||||
* @run main Bug8167273 testEmptyEraNames
|
||||
*/
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter.Type;
|
||||
|
||||
public class Bug8167273 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
switch (args[0]) {
|
||||
case "testEraName":
|
||||
testEraName();
|
||||
break;
|
||||
case "testEmptyEraNames":
|
||||
testEmptyEraNames();
|
||||
break;
|
||||
case "testCldr":
|
||||
testCldrSupportedLocales();
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("no test was specified.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tests that era names retrieved from Calendar.getDisplayNames map should
|
||||
* match with that of Era names retrieved from DateFormatSymbols.getEras()
|
||||
* method for all Gregorian Calendar locales .
|
||||
*/
|
||||
public static void testEraName() {
|
||||
Set<Locale> allLocales = Set.of(Locale.getAvailableLocales());
|
||||
Set<Locale> JpThlocales = Set.of(
|
||||
Locale.of("th", "TH"), Locale.forLanguageTag("th-Thai-TH"),
|
||||
Locale.of("ja", "JP", "JP"), Locale.of("th", "TH", "TH")
|
||||
);
|
||||
Set<Locale> allLocs = new HashSet<>(allLocales);
|
||||
// Removing Japanese and Thai Locales to check Gregorian Calendar Locales
|
||||
allLocs.removeAll(JpThlocales);
|
||||
allLocs.forEach((locale) -> {
|
||||
Calendar cal = Calendar.getInstance(locale);
|
||||
Map<String, Integer> names = cal.getDisplayNames(Calendar.ERA, Calendar.ALL_STYLES, locale);
|
||||
DateFormatSymbols symbols = new DateFormatSymbols(locale);
|
||||
String[] eras = symbols.getEras();
|
||||
for (String era : eras) {
|
||||
if (!names.containsKey(era)) {
|
||||
reportMismatch(names.keySet(), eras, locale);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void reportMismatch(Set<String> CalendarEras, String[] dfsEras, Locale locale) {
|
||||
System.out.println("For Locale " + locale + "era names in calendar map are " + CalendarEras);
|
||||
for (String era : dfsEras) {
|
||||
System.out.println("For Locale " + locale + " era names in DateFormatSymbols era array are " + era);
|
||||
}
|
||||
throw new RuntimeException(" Era name retrieved from Calendar class do not match with"
|
||||
+ " retrieved from DateFormatSymbols for Locale " + locale);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* tests that Eras names returned from DateFormatSymbols.getEras()
|
||||
* and Calendar.getDisplayNames() should not be empty for any Locale.
|
||||
*/
|
||||
private static void testEmptyEraNames() {
|
||||
Set<Locale> allLocales = Set.of(Locale.getAvailableLocales());
|
||||
allLocales.forEach((loc) -> {
|
||||
DateFormatSymbols dfs = new DateFormatSymbols(loc);
|
||||
Calendar cal = Calendar.getInstance(loc);
|
||||
Map<String, Integer> names = cal.getDisplayNames(Calendar.ERA, Calendar.ALL_STYLES, loc);
|
||||
Set<String> CalendarEraNames = names.keySet();
|
||||
String[] eras = dfs.getEras();
|
||||
for (String era : eras) {
|
||||
if (era.isEmpty()) {
|
||||
throw new RuntimeException("Empty era names retrieved for DateFomatSymbols.getEras"
|
||||
+ " for locale " + loc);
|
||||
}
|
||||
}
|
||||
CalendarEraNames.stream().filter((erakey) -> (erakey.isEmpty())).forEachOrdered((l) -> {
|
||||
throw new RuntimeException("Empty era names retrieved for Calendar.getDisplayName"
|
||||
+ " for locale " + loc);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* tests that CLDR provider should return true for locale zh_HK, no-NO and
|
||||
* no.
|
||||
*/
|
||||
private static void testCldrSupportedLocales() {
|
||||
Set<Locale> locales = Set.of(Locale.forLanguageTag("zh-HK"),
|
||||
Locale.forLanguageTag("no-NO"),
|
||||
Locale.forLanguageTag("no"));
|
||||
LocaleProviderAdapter cldr = LocaleProviderAdapter.forType(Type.CLDR);
|
||||
Set<Locale> availableLocs = Set.of(cldr.getAvailableLocales());
|
||||
Set<String> langtags = new HashSet<>();
|
||||
availableLocs.forEach((loc) -> {
|
||||
langtags.add(loc.toLanguageTag());
|
||||
});
|
||||
|
||||
locales.stream().filter((loc) -> (!cldr.isSupportedProviderLocale(loc, langtags))).forEachOrdered((loc) -> {
|
||||
throw new RuntimeException("Locale " + loc + " is not supported by CLDR Locale Provider");
|
||||
});
|
||||
}
|
||||
}
|
||||
52
test/jdk/java/util/Calendar/Bug8176847.java
Normal file
52
test/jdk/java/util/Calendar/Bug8176847.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8176847
|
||||
* @summary Make sure that style value of '3' throws IllegalArgumentException
|
||||
* in Calendar.getDisplayName(s) methods.
|
||||
*/
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
public class Bug8176847 {
|
||||
public static void main(String[] args) {
|
||||
Calendar c = new Calendar.Builder().build();
|
||||
|
||||
try {
|
||||
c.getDisplayName(Calendar.MONTH, 3, Locale.US);
|
||||
throw new RuntimeException("IllegalArgumentException was not thrown");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// success
|
||||
}
|
||||
|
||||
try {
|
||||
c.getDisplayNames(Calendar.MONTH, 3, Locale.US);
|
||||
throw new RuntimeException("IllegalArgumentException was not thrown");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
}
|
||||
300
test/jdk/java/util/Calendar/Builder/BuilderTest.java
Normal file
300
test/jdk/java/util/Calendar/Builder/BuilderTest.java
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 4745761 8350646
|
||||
* @summary Unit test for Calendar.Builder.
|
||||
* @run main BuilderTest
|
||||
*/
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import static java.util.Calendar.*;
|
||||
|
||||
public class BuilderTest {
|
||||
private static final Locale jaJPJP = Locale.of("ja", "JP", "JP");
|
||||
private static final Locale thTH = Locale.of("th", "TH");
|
||||
private static final TimeZone LA = TimeZone.getTimeZone("America/Los_Angeles");
|
||||
private static final TimeZone TOKYO = TimeZone.getTimeZone("Asia/Tokyo");
|
||||
private static int error;
|
||||
|
||||
public static void main(String[] args) {
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
Locale loc = Locale.getDefault();
|
||||
try {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
|
||||
Locale.setDefault(Locale.US);
|
||||
Calendar.Builder calb;
|
||||
Calendar cal, expected;
|
||||
|
||||
// set instant
|
||||
calb = builder();
|
||||
long time = System.currentTimeMillis();
|
||||
cal = calb.setInstant(time).build();
|
||||
expected = new GregorianCalendar();
|
||||
expected.setTimeInMillis(time);
|
||||
check(cal, expected);
|
||||
|
||||
calb = builder();
|
||||
cal = calb.setInstant(new Date(time)).build();
|
||||
check(cal, expected);
|
||||
|
||||
// set time zone
|
||||
calb = builder();
|
||||
cal = calb.setTimeZone(LA).setInstant(time).build();
|
||||
expected = new GregorianCalendar(LA, Locale.US);
|
||||
expected.setTimeInMillis(time);
|
||||
check(cal, expected);
|
||||
|
||||
calb = builder();
|
||||
cal = calb.setTimeZone(TOKYO).setInstant(time).build();
|
||||
expected = new GregorianCalendar(TOKYO, Locale.US);
|
||||
expected.setTimeInMillis(time);
|
||||
check(cal, expected);
|
||||
|
||||
// set vs. setFields
|
||||
calb = builder();
|
||||
cal = calb.set(YEAR, 2013).set(MONTH, JANUARY).set(DAY_OF_MONTH, 31)
|
||||
.set(HOUR_OF_DAY, 10).set(MINUTE, 20).set(SECOND, 30).set(MILLISECOND, 40).build();
|
||||
expected = new GregorianCalendar(2013, JANUARY, 31, 10, 20, 30);
|
||||
expected.set(MILLISECOND, 40);
|
||||
check(cal, expected);
|
||||
|
||||
calb = builder();
|
||||
cal = calb.setFields(YEAR, 2013, MONTH, JANUARY, DAY_OF_MONTH, 31,
|
||||
HOUR_OF_DAY, 10, MINUTE, 20, SECOND, 30, MILLISECOND, 40).build();
|
||||
check(cal, expected);
|
||||
|
||||
// field resolution
|
||||
calb = builder();
|
||||
cal = calb.setFields(YEAR, 2013, MONTH, DECEMBER, DAY_OF_MONTH, 31,
|
||||
HOUR_OF_DAY, 10, MINUTE, 20, SECOND, 30, MILLISECOND, 40)
|
||||
.set(DAY_OF_YEAR, 31).build(); // DAY_OF_YEAR wins.
|
||||
check(cal, expected);
|
||||
|
||||
// setDate/setTimeOfDay
|
||||
calb = builder();
|
||||
cal = calb.setDate(2013, JANUARY, 31).setTimeOfDay(10, 20, 30, 40).build();
|
||||
check(cal, expected);
|
||||
|
||||
// week date (ISO 8601)
|
||||
calb = builder().setCalendarType("iso8601");
|
||||
cal = calb.setWeekDate(2013, 1, MONDAY).setTimeOfDay(10, 20, 30).build();
|
||||
expected = getISO8601();
|
||||
expected.set(2012, DECEMBER, 31, 10, 20, 30);
|
||||
check(cal, expected);
|
||||
|
||||
// default YEAR == 1970
|
||||
cal = builder().setFields(MONTH, JANUARY,
|
||||
DAY_OF_MONTH, 9).build();
|
||||
check(cal, new GregorianCalendar(1970, JANUARY, 9));
|
||||
|
||||
// no parameters are given.
|
||||
calb = builder();
|
||||
cal = calb.build();
|
||||
expected = new GregorianCalendar();
|
||||
expected.clear();
|
||||
check(cal, expected);
|
||||
|
||||
// Thai Buddhist calendar
|
||||
calb = builder();
|
||||
cal = calb.setCalendarType("buddhist").setDate(2556, JANUARY, 31).build();
|
||||
expected = Calendar.getInstance(thTH);
|
||||
expected.clear();
|
||||
expected.set(2556, JANUARY, 31);
|
||||
check(cal, expected);
|
||||
// setLocale
|
||||
calb = builder();
|
||||
cal = calb.setLocale(thTH).setDate(2556, JANUARY, 31).build();
|
||||
check(cal, expected);
|
||||
|
||||
// Japanese Imperial calendar
|
||||
cal = builder().setCalendarType("japanese")
|
||||
.setFields(YEAR, 1, DAY_OF_YEAR, 1).build();
|
||||
expected = Calendar.getInstance(jaJPJP);
|
||||
expected.clear();
|
||||
if (LocalDateTime.now().isBefore(LocalDateTime.of(2019, 5, 1, 0, 0))) {
|
||||
expected.set(1, JANUARY, 8);
|
||||
} else {
|
||||
expected.set(1, MAY, 1);
|
||||
}
|
||||
check(cal, expected);
|
||||
// setLocale
|
||||
calb = builder();
|
||||
cal = calb.setLocale(jaJPJP).setFields(YEAR, 1, DAY_OF_YEAR, 1).build();
|
||||
check(cal, expected);
|
||||
|
||||
testExceptions();
|
||||
} finally {
|
||||
// Restore default Locale and TimeZone
|
||||
Locale.setDefault(loc);
|
||||
TimeZone.setDefault(tz);
|
||||
}
|
||||
if (error > 0) {
|
||||
throw new RuntimeException("Failed");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testExceptions() {
|
||||
Calendar.Builder calb;
|
||||
Calendar cal;
|
||||
|
||||
// NPE
|
||||
try {
|
||||
calb = builder().setInstant((Date)null);
|
||||
noException("setInstant((Date)null)");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
try {
|
||||
calb = builder().setCalendarType(null);
|
||||
noException("setCalendarType(null)");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
try {
|
||||
calb = builder().setLocale(null);
|
||||
noException("setLocale(null)");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
try {
|
||||
calb = builder().setTimeZone(null);
|
||||
noException("setTimeZone(null)");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
|
||||
// IllegalArgumentException
|
||||
try {
|
||||
// invalid field index in set
|
||||
calb = builder().set(100, 2013);
|
||||
noException("set(100, 2013)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
// invalid field index in setField
|
||||
calb = builder().setFields(100, 2013);
|
||||
noException("setFields(100, 2013)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
// odd number of arguments
|
||||
calb = builder().setFields(YEAR, 2013, MONTH);
|
||||
noException("setFields(YEAR, 2013, MONTH)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
// unknown calendar type
|
||||
calb = builder().setCalendarType("foo");
|
||||
noException("setCalendarType(\"foo\")");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
// invalid week definition parameter
|
||||
calb = builder().setWeekDefinition(8, 1);
|
||||
noException("setWeekDefinition(8, 1)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
// invalid week definition parameter
|
||||
calb = builder().setWeekDefinition(SUNDAY, 0);
|
||||
noException("setWeekDefinition(8, 1)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
// sets both instant and field parameters
|
||||
calb = builder().setInstant(new Date()).setDate(2013, JANUARY, 1);
|
||||
noException("setInstant(new Date()).setDate(2013, JANUARY, 1)");
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
try {
|
||||
// sets both field parameters and instant
|
||||
calb = builder().setDate(2013, JANUARY, 1).setInstant(new Date());
|
||||
noException("setDate(2013, JANUARY, 1).setInstant(new Date())");
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
try {
|
||||
// sets inconsistent calendar types
|
||||
calb = builder().setCalendarType("iso8601").setCalendarType("japanese");
|
||||
noException("setCalendarType(\"iso8601\").setCalendarType(\"japanese\")");
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
// IllegalArgumentException in build()
|
||||
calb = nonLenientBuilder().set(MONTH, 100);
|
||||
checkException(calb, IllegalArgumentException.class);
|
||||
calb = nonLenientBuilder().setTimeOfDay(23, 59, 70);
|
||||
checkException(calb, IllegalArgumentException.class);
|
||||
calb = builder().setCalendarType("japanese").setWeekDate(2013, 1, MONDAY);
|
||||
checkException(calb, IllegalArgumentException.class);
|
||||
// JDK-8350646 : Ensure IAE (instead of AIOOBE) for ERA over largest supported
|
||||
calb = builder().setCalendarType("japanese").setFields(ERA, 6);
|
||||
checkException(calb, IllegalArgumentException.class);
|
||||
// Note that we don't check ERAs under BEFORE_MEIJI, i.e. -1, -2, ... as
|
||||
// historically JapaneseImperialCalendar ignores such values when normalizing
|
||||
}
|
||||
|
||||
private static Calendar.Builder builder() {
|
||||
return new Calendar.Builder();
|
||||
}
|
||||
|
||||
private static Calendar.Builder nonLenientBuilder() {
|
||||
return builder().setLenient(false);
|
||||
}
|
||||
|
||||
private static Calendar getISO8601() {
|
||||
GregorianCalendar cal = new GregorianCalendar();
|
||||
cal.setFirstDayOfWeek(MONDAY);
|
||||
cal.setMinimalDaysInFirstWeek(4);
|
||||
cal.setGregorianChange(new Date(Long.MIN_VALUE));
|
||||
cal.clear();
|
||||
return cal;
|
||||
}
|
||||
|
||||
private static void check(Calendar cal, Calendar expected) {
|
||||
if (!cal.equals(expected)) {
|
||||
error++;
|
||||
System.err.println("FAILED:");
|
||||
System.err.println("\t cal = "+cal.getTime());
|
||||
System.err.println("\texpected = "+expected.getTime());
|
||||
System.err.printf("\tcal = %s%n\texp = %s%n", cal, expected);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkException(Calendar.Builder calb, Class<? extends Exception> exception) {
|
||||
try {
|
||||
Calendar cal = calb.build();
|
||||
error++;
|
||||
System.err.println("expected exception: " + exception);
|
||||
} catch (Exception e) {
|
||||
if (!e.getClass().equals(exception)) {
|
||||
error++;
|
||||
System.err.println("unexpected exception: " + e.getClass() + ", expected: " + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void noException(String msg) {
|
||||
error++;
|
||||
System.err.println("no exception with "+msg);
|
||||
}
|
||||
}
|
||||
109
test/jdk/java/util/Calendar/CalendarDataTest.java
Normal file
109
test/jdk/java/util/Calendar/CalendarDataTest.java
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8190918 8202537 8221432 8231273 8265315 8284840 8333582
|
||||
* 8354548
|
||||
* @summary Tests for region dependent calendar data, i.e.,
|
||||
* firstDayOfWeek and minimalDaysInFirstWeek.
|
||||
* @modules jdk.localedata
|
||||
* @run main CalendarDataTest
|
||||
*/
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class CalendarDataTest {
|
||||
|
||||
// golden data from CLDR
|
||||
private static final List<List<String>> FIRSTDAYDATA = List.of(
|
||||
List.of("1", "AG AS BD BR BS BT BW BZ CA CO DM DO ET GT " +
|
||||
"GU HK HN ID IL IN IS JM JP KE KH KR LA MH MM MO MT MX MZ " +
|
||||
"NI NP PA PE PH PK PR PT PY SA SG SV TH TT TW UM US VE " +
|
||||
"VI WS YE ZA ZW"),
|
||||
List.of("2", "001 AD AE AI AL AM AN AR AT AU AX AZ BA BE BG BM BN BY " +
|
||||
"CH CL CM CN CR CY CZ DE DK EC EE ES FI FJ FO FR GB GE GF GP " +
|
||||
"GR HR HU IE IT KG KZ LB LI LK LT LU LV MC MD ME MK MN MQ " +
|
||||
"MY NL NO NZ PL RE RO RS RU SE SI SK SM TJ TM TR UA UY UZ " +
|
||||
"VA VN XK"),
|
||||
List.of("6", "MV"),
|
||||
List.of("7", "AF BH DJ DZ EG IQ IR JO KW LY OM QA SD SY"));
|
||||
|
||||
private static final List<List<String>> MINDAYSDATA = List.of(
|
||||
List.of("1", "001 GU UM US VI"),
|
||||
List.of("4", "AD AN AT AX BE BG CH CZ DE DK EE ES FI FJ FO FR " +
|
||||
"GB GF GG GI GP GR HU IE IM IS IT JE LI LT LU MC MQ NL NO " +
|
||||
"PL PT RE RU SE SJ SK SM VA"));
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
// world
|
||||
Calendar cal = Calendar.getInstance(Locale.of("", "001"));
|
||||
checkResult("001",
|
||||
cal.getFirstDayOfWeek(),
|
||||
cal.getMinimalDaysInFirstWeek());
|
||||
|
||||
// two letter country codes
|
||||
IntStream.range(0x41, 0x5b)
|
||||
.forEach(c1 -> {
|
||||
IntStream.range(0x41, 0x5b)
|
||||
.mapToObj(c2 -> String.valueOf((char)c1) + String.valueOf((char)c2))
|
||||
.forEach(region -> {
|
||||
Calendar c = Calendar.getInstance(Locale.of("", region));
|
||||
checkResult(region,
|
||||
c.getFirstDayOfWeek(),
|
||||
c.getMinimalDaysInFirstWeek());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static void checkResult(String region, int firstDay, int minDays) {
|
||||
// first day of week
|
||||
int expected = Integer.parseInt(findEntry(region, FIRSTDAYDATA)
|
||||
.orElse(findEntry("001", FIRSTDAYDATA).orElse(List.of("1")))
|
||||
.get(0));
|
||||
if (firstDay != expected) {
|
||||
throw new RuntimeException("firstDayOfWeek is incorrect for the region: " +
|
||||
region + ". Returned: " + firstDay + ", Expected: " + expected);
|
||||
}
|
||||
|
||||
// minimal days in first week
|
||||
expected = Integer.parseInt(findEntry(region, MINDAYSDATA)
|
||||
.orElse(findEntry("001", MINDAYSDATA).orElse(List.of("1")))
|
||||
.get(0));
|
||||
if (minDays != expected) {
|
||||
throw new RuntimeException("minimalDaysInFirstWeek is incorrect for the region: " +
|
||||
region + ". Returned: " + minDays + ", Expected: " + expected);
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<List<String>> findEntry(String region, List<List<String>> data) {
|
||||
return data.stream()
|
||||
.filter(l -> l.get(1).contains(region))
|
||||
.findAny();
|
||||
}
|
||||
}
|
||||
|
||||
65
test/jdk/java/util/Calendar/CalendarDisplayNamesTest.java
Normal file
65
test/jdk/java/util/Calendar/CalendarDisplayNamesTest.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8262108 8174269
|
||||
* @summary Verify the results returned by Calendar.getDisplayNames() API
|
||||
* @comment Locale providers: CLDR,SPI
|
||||
* @run junit/othervm -Djava.locale.providers=CLDR,SPI CalendarDisplayNamesTest
|
||||
* @comment Locale providers: default
|
||||
* @run junit CalendarDisplayNamesTest
|
||||
*/
|
||||
public class CalendarDisplayNamesTest {
|
||||
|
||||
/**
|
||||
* Test that the {@link Calendar#getDisplayNames(int, int, Locale)} returns valid field values
|
||||
* for the {@link Calendar#AM_PM} field in various locales and styles
|
||||
*/
|
||||
@Test
|
||||
public void testAM_PMDisplayNameValues() {
|
||||
final int[] styles = new int[]{Calendar.ALL_STYLES, Calendar.SHORT_FORMAT, Calendar.LONG_FORMAT,
|
||||
Calendar.SHORT_STANDALONE, Calendar.LONG_STANDALONE, Calendar.SHORT, Calendar.LONG};
|
||||
for (final Locale locale : Locale.getAvailableLocales()) {
|
||||
for (final int style : styles) {
|
||||
final Calendar cal = Calendar.getInstance();
|
||||
final Map<String, Integer> names = cal.getDisplayNames(Calendar.AM_PM, style, locale);
|
||||
if (names == null) {
|
||||
continue;
|
||||
}
|
||||
for (final Integer fieldValue : names.values()) {
|
||||
Assertions.assertTrue(fieldValue == Calendar.AM || fieldValue == Calendar.PM,
|
||||
"Invalid field value " + fieldValue + " for calendar field AM_PM, in locale "
|
||||
+ locale + " with style " + style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
test/jdk/java/util/Calendar/CalendarLeapYearAddTest.java
Normal file
129
test/jdk/java/util/Calendar/CalendarLeapYearAddTest.java
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8331646
|
||||
* @summary confirm that Calendar.add() works correctly with leap year calculations
|
||||
* @run junit CalendarLeapYearAddTest
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Calendar.APRIL;
|
||||
import static java.util.Calendar.DATE;
|
||||
import static java.util.Calendar.DAY_OF_MONTH;
|
||||
import static java.util.Calendar.DAY_OF_WEEK;
|
||||
import static java.util.Calendar.DAY_OF_WEEK_IN_MONTH;
|
||||
import static java.util.Calendar.DAY_OF_YEAR;
|
||||
import static java.util.Calendar.FEBRUARY;
|
||||
import static java.util.Calendar.LONG;
|
||||
import static java.util.Calendar.MARCH;
|
||||
import static java.util.Calendar.MONTH;
|
||||
import static java.util.Calendar.WEEK_OF_YEAR;
|
||||
import static java.util.Calendar.YEAR;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class CalendarLeapYearAddTest {
|
||||
|
||||
/**
|
||||
* 8331646 Calendar add for leap year
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("calendarAddSource")
|
||||
public void testAddLeapYear(String testName, int calendarDate, int calendarMonth, int calendarYear,
|
||||
int value, int calendarField, int expectedDate, int expectedMonth,
|
||||
int expectedYear) {
|
||||
Calendar calendar = new GregorianCalendar(calendarYear, calendarMonth, calendarDate);
|
||||
calendar.add(calendarField, value);
|
||||
assertEquals(expectedDate, calendar.get(DATE), testName
|
||||
+ " Expected " + expectedDate + " of " + expectedMonth + expectedYear + " but got " + calendar.getTime());
|
||||
assertEquals(expectedMonth, calendar.get(MONTH), testName
|
||||
+ " Expected " + expectedMonth + " but got " + calendar.getDisplayName(MONTH, LONG, Locale.getDefault()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 8331646 Calendar month and year add/subtract for leap/non-leap year
|
||||
*/
|
||||
@Test
|
||||
public void testMonthYearAddSubtractNonLeapYear() {
|
||||
Calendar calendar = new GregorianCalendar(2024, FEBRUARY, 29);
|
||||
calendar.add(MONTH, 1);
|
||||
calendar.add(YEAR, -1);
|
||||
calendar.add(MONTH, -1);
|
||||
/* When month added date jumps to 29th of March 2024, after year subtracted date jumps to 29th of March 2023
|
||||
after month subtracted date jumps to 28th of Feb 2023 as non leap year
|
||||
*/
|
||||
assertEquals(28, calendar.get(DATE),
|
||||
"testMonthYearAddSubtractNonLeapYear Expected 28th of February 2024 but got " + calendar.getTime());
|
||||
assertEquals(FEBRUARY, calendar.get(MONTH),
|
||||
" testMonthYearAddSubtractNonLeapYear Expected February but got " + calendar.getDisplayName(MONTH, LONG, Locale.getDefault()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 8331646 Calendar add/subtract for leap year
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("calendarAddSubtractSource")
|
||||
public void testAddSubtractLeapYear(String testName, int calendarDate, int calendarMonth, int calendarYear,
|
||||
int firstValue, int secondValue, int calendarField, int expectedDate,
|
||||
int expectedMonth, int expectedYear) {
|
||||
Calendar calendar = new GregorianCalendar(calendarYear, calendarMonth, calendarDate);
|
||||
calendar.add(calendarField, firstValue);
|
||||
calendar.add(calendarField, secondValue);
|
||||
assertEquals(expectedDate, calendar.get(DATE), testName
|
||||
+ " Expected " + expectedDate + " of " + expectedMonth + expectedYear + " but got " + calendar.getTime());
|
||||
assertEquals(expectedMonth, calendar.get(MONTH), testName
|
||||
+ " Expected " + expectedMonth + " but got " + calendar.getDisplayName(MONTH, LONG, Locale.getDefault()));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> calendarAddSubtractSource() {
|
||||
return Stream.of(
|
||||
Arguments.of("testMonthAddSubtractLeapYearReversed", 31, MARCH, 2024, -1, 1, MONTH, 29, MARCH, 2024),
|
||||
Arguments.of("testMonthAddSubtractLeapYear", 29, FEBRUARY, 2024, 1, -1, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testYearAddSubtractLeapYear", 29, FEBRUARY, 2024, 1, -1, YEAR, 28, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfYearAddSubtractLeapYear", 29, FEBRUARY, 2024, 365, -365, DAY_OF_YEAR, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDateAddSubtractLeapYear", 29, FEBRUARY, 2024, 365, -365, DATE, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testWeekOfYearAddSubtractLeapYear", 29, FEBRUARY, 2024, 52, -52, WEEK_OF_YEAR, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfMonthAddSubtractLeapYear", 29, FEBRUARY, 2024, 31, -31, DAY_OF_MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfWeekInMonthAddSubtractLeapYear", 29, FEBRUARY, 2024, 6, -6, DAY_OF_WEEK_IN_MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfWeekAddSubtractLeapYear", 29, FEBRUARY, 2024, 6, -6, DAY_OF_WEEK, 29, FEBRUARY, 2024)
|
||||
);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> calendarAddSource() {
|
||||
return Stream.of(
|
||||
Arguments.of("testMonthAddLeapYear", 29, FEBRUARY, 2024, 1, MONTH, 29, MARCH, 2024),
|
||||
Arguments.of("testOneMonthSubtractLeapYear", 31, MARCH, 2024, -1, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testTwoMonthSubtractLeapYear", 30, APRIL, 2024, -2, MONTH, 29, FEBRUARY, 2024)
|
||||
);
|
||||
}
|
||||
}
|
||||
190
test/jdk/java/util/Calendar/CalendarLeapYearRollTest.java
Normal file
190
test/jdk/java/util/Calendar/CalendarLeapYearRollTest.java
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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 8331851
|
||||
* @summary confirm that Calendar.roll() works correctly with leap year calculations
|
||||
* @run junit CalendarLeapYearRollTest
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Calendar.APRIL;
|
||||
import static java.util.Calendar.DATE;
|
||||
import static java.util.Calendar.DAY_OF_MONTH;
|
||||
import static java.util.Calendar.DAY_OF_WEEK;
|
||||
import static java.util.Calendar.DAY_OF_WEEK_IN_MONTH;
|
||||
import static java.util.Calendar.DAY_OF_YEAR;
|
||||
import static java.util.Calendar.FEBRUARY;
|
||||
import static java.util.Calendar.LONG;
|
||||
import static java.util.Calendar.MARCH;
|
||||
import static java.util.Calendar.MONTH;
|
||||
import static java.util.Calendar.WEEK_OF_YEAR;
|
||||
import static java.util.Calendar.YEAR;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class CalendarLeapYearRollTest {
|
||||
|
||||
/**
|
||||
* 8331851 Calendar roll for leap year
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("calendarRollSource")
|
||||
public void testRollLeapYear(String testName, int calendarDate, int calendarMonth, int calendarYear,
|
||||
int value, int calendarField, int expectedDate, int expectedMonth,
|
||||
int expectedYear) {
|
||||
Calendar calendar = new GregorianCalendar(calendarYear, calendarMonth, calendarDate);
|
||||
calendar.roll(calendarField, value);
|
||||
assertEquals(expectedDate, calendar.get(DATE), testName
|
||||
+ " Expected " + expectedDate + " of " + expectedMonth + expectedYear + " but got " + calendar.getTime());
|
||||
assertEquals(expectedMonth, calendar.get(MONTH), testName
|
||||
+ " Expected " + expectedMonth + " but got " + calendar.getDisplayName(MONTH, LONG, Locale.getDefault()));
|
||||
assertEquals(expectedYear, calendar.get(YEAR), testName
|
||||
+ " Expected " + expectedYear + " but got " + calendar.get(YEAR));
|
||||
}
|
||||
|
||||
/**
|
||||
* 8331851 Calendar roll up/down for leap year
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("calendarRollUpDownSource")
|
||||
public void testRollUpDownLeapYear(String testName, int calendarDate, int calendarMonth, int calendarYear,
|
||||
int firstValue, int secondValue, int calendarField, int expectedDate,
|
||||
int expectedMonth, int expectedYear) {
|
||||
Calendar calendar = new GregorianCalendar(calendarYear, calendarMonth, calendarDate);
|
||||
calendar.roll(calendarField, firstValue);
|
||||
calendar.roll(calendarField, secondValue);
|
||||
assertEquals(expectedDate, calendar.get(DATE), testName
|
||||
+ " Expected " + expectedDate + " of " + expectedMonth + expectedYear + " but got " + calendar.getTime());
|
||||
assertEquals(expectedMonth, calendar.get(MONTH), testName
|
||||
+ " Expected " + expectedMonth + " but got " + calendar.getDisplayName(MONTH, LONG, Locale.getDefault()));
|
||||
assertEquals(expectedYear, calendar.get(YEAR), testName
|
||||
+ " Expected " + expectedYear + " but got " + calendar.get(YEAR));
|
||||
}
|
||||
|
||||
/**
|
||||
* 8331851 Calendar roll boolean for leap year
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("calendarBooleanRollSource")
|
||||
public void testBooleanRollLeapYear(String testName, int calendarDate, int calendarMonth, int calendarYear,
|
||||
boolean value, int calendarField, int expectedDate,
|
||||
int expectedMonth, int expectedYear) {
|
||||
Calendar calendar = new GregorianCalendar(calendarYear, calendarMonth, calendarDate);
|
||||
calendar.roll(calendarField, value);
|
||||
assertEquals(expectedDate, calendar.get(DATE), testName
|
||||
+ " Expected " + expectedDate + " of " + expectedMonth + expectedYear + " but got " + calendar.getTime());
|
||||
assertEquals(expectedMonth, calendar.get(MONTH), testName
|
||||
+ " Expected " + expectedMonth + " but got " + calendar.getDisplayName(MONTH, LONG, Locale.getDefault()));
|
||||
assertEquals(expectedYear, calendar.get(YEAR), testName
|
||||
+ " Expected " + expectedYear + " but got " + calendar.get(YEAR));
|
||||
}
|
||||
|
||||
/**
|
||||
* 8331851 Calendar month and year roll for leap/non-leap year
|
||||
*/
|
||||
@Test
|
||||
public void testMonthYearRollUpDownNonLeapYear() {
|
||||
Calendar calendar = new GregorianCalendar(2024, FEBRUARY, 29);
|
||||
calendar.roll(MONTH, 1);
|
||||
calendar.roll(YEAR, -1);
|
||||
calendar.roll(MONTH, -1);
|
||||
assertEquals(28, calendar.get(DATE),
|
||||
"testMonthYearRollUpDownNonLeapYear Expected 28th of February 2024 but got " + calendar.getTime());
|
||||
assertEquals(FEBRUARY, calendar.get(MONTH),
|
||||
"testMonthYearRollUpDownNonLeapYear Expected February but got " + calendar.getDisplayName(MONTH, LONG, Locale.getDefault()));
|
||||
assertEquals(2023, calendar.get(YEAR),
|
||||
"testMonthYearRollUpDownNonLeapYear Expected 2023 but got " + calendar.get(YEAR));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> calendarRollUpDownSource() {
|
||||
return Stream.of(
|
||||
Arguments.of("testMonthRollDownUpLeapYearReversed", 31, MARCH, 2024, -1, 1, MONTH, 29, MARCH, 2024),
|
||||
Arguments.of("testMonthRollUpDownLeapYearReversed", 29, FEBRUARY, 2024, 1, -1, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testYearRollUpDownLeapYear", 29, FEBRUARY, 2024, 1, -1, YEAR, 1, MARCH, 2024),
|
||||
Arguments.of("testFourYearRollUpDownLeapYear", 29, FEBRUARY, 2024, 4, -4, YEAR, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfYearRollUpDownLeapYear", 29, FEBRUARY, 2024, 365, -365, DAY_OF_YEAR, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDateRollUpDownLeapYear", 29, FEBRUARY, 2024, 365, -365, DATE, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testWeekOfYearRollUpDownLeapYear", 29, FEBRUARY, 2024, 52, -52, WEEK_OF_YEAR, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfMonthRollUpDownLeapYear", 29, FEBRUARY, 2024, 31, -31, DAY_OF_MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfWeekInMonthRollUpDownLeapYear", 29, FEBRUARY, 2024, 6, -6, DAY_OF_WEEK_IN_MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfWeekRollUpDownLeapYear", 29, FEBRUARY, 2024, 6, -6, DAY_OF_WEEK, 29, FEBRUARY, 2024)
|
||||
);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> calendarRollSource() {
|
||||
return Stream.of(
|
||||
Arguments.of("testMonthRollUpLeapYear", 29, FEBRUARY, 2024, 1, MONTH, 29, MARCH, 2024),
|
||||
Arguments.of("testOneMonthRollDownLeapYear", 31, MARCH, 2024, -1, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testTwoMonthDownEndOfMonthLeapYear", 30, APRIL, 2024, -2, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testTwoMonthDownSameDateLeapYear", 29, APRIL, 2024, -2, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testFourYearRollUpLeapYear", 29, FEBRUARY, 2024, 4, YEAR, 29, FEBRUARY, 2028),
|
||||
Arguments.of("testTwelveMonthRollDownLeapYear", 29, FEBRUARY, 2024, 12, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testYearRollUpLeapYear", 29, FEBRUARY, 2024, 1, YEAR, 1, MARCH, 2025),
|
||||
Arguments.of("testYearRollDownLeapYear", 29, FEBRUARY, 2024, -1, YEAR, 1, MARCH, 2023),
|
||||
Arguments.of("testDayOfYearRollDownLeapYear", 29, FEBRUARY, 2024, -1, DAY_OF_YEAR, 28, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfYearRollUpLeapYear", 29, FEBRUARY, 2024, 1, DAY_OF_YEAR, 1, MARCH, 2024),
|
||||
Arguments.of("testDateRollDownLeapYear", 29, FEBRUARY, 2024, -1, DATE, 28, FEBRUARY, 2024),
|
||||
Arguments.of("testDateRollUpLeapYear", 29, FEBRUARY, 2024, 1, DATE, 1, FEBRUARY, 2024),
|
||||
Arguments.of("testWeekOfYearRollUpLeapYear", 29, FEBRUARY, 2024, 1, WEEK_OF_YEAR, 7, MARCH, 2024),
|
||||
Arguments.of("testWeekOfYearRollDownLeapYear", 29, FEBRUARY, 2024, -1, WEEK_OF_YEAR, 22, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfMonthRollUpLeapYear", 29, FEBRUARY, 2024, 1, DAY_OF_MONTH, 1, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfMonthRollDownLeapYear", 29, FEBRUARY, 2024, -1, DAY_OF_MONTH, 28, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfWeekInMonthRollUpLeapYear", 29, FEBRUARY, 2024, 1, DAY_OF_WEEK_IN_MONTH, 1, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfWeekInMonthRollDownLeapYear", 29, FEBRUARY, 2024, -1, DAY_OF_WEEK_IN_MONTH, 22, FEBRUARY, 2024),
|
||||
Arguments.of("testDayOfWeekRollUpLeapYear", 29, FEBRUARY, 2024, 1, DAY_OF_WEEK, 1, MARCH, 2024),
|
||||
Arguments.of("testDayOfWeekRollDownLeapYear", 29, FEBRUARY, 2024, -1, DAY_OF_WEEK, 28, FEBRUARY, 2024)
|
||||
);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> calendarBooleanRollSource() {
|
||||
return Stream.of(
|
||||
Arguments.of("testBooleanMonthRollDownLeapYear", 31, MARCH, 2024, false, MONTH, 29, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanMonthRollUpLeapYear", 29, FEBRUARY, 2024, true, MONTH, 29, MARCH, 2024),
|
||||
Arguments.of("testBooleanYearRollUpLeapYear", 29, FEBRUARY, 2024, true, YEAR, 1, MARCH, 2025),
|
||||
Arguments.of("testBooleanYearRollDownLeapYear", 29, FEBRUARY, 2024, false, YEAR, 1, MARCH, 2023),
|
||||
Arguments.of("testBooleanDayOfYearRollDownLeapYear", 29, FEBRUARY, 2024, false, DAY_OF_YEAR, 28, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanDayOfYearRollUpLeapYear", 29, FEBRUARY, 2024, true, DAY_OF_YEAR, 1, MARCH, 2024),
|
||||
Arguments.of("testBooleanDateRollDownLeapYear", 29, FEBRUARY, 2024, false, DATE, 28, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanDateRollUpLeapYear", 29, FEBRUARY, 2024, true, DATE, 1, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanWeekOfYearRollUpLeapYear", 29, FEBRUARY, 2024, true, WEEK_OF_YEAR, 7, MARCH, 2024),
|
||||
Arguments.of("testBooleanWeekOfYearRollDownLeapYear", 29, FEBRUARY, 2024, false, WEEK_OF_YEAR, 22, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanDayOfMonthRollUpLeapYear", 29, FEBRUARY, 2024, true, DAY_OF_MONTH, 1, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanDayOfMonthRollDownLeapYear", 29, FEBRUARY, 2024, false, DAY_OF_MONTH, 28, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanDayOfWeekInMonthRollUpLeapYear", 29, FEBRUARY, 2024, true, DAY_OF_WEEK_IN_MONTH, 1, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanDayOfWeekInMonthRollDownLeapYear", 29, FEBRUARY, 2024, false, DAY_OF_WEEK_IN_MONTH, 22, FEBRUARY, 2024),
|
||||
Arguments.of("testBooleanDayOfWeekRollUpLeapYear", 29, FEBRUARY, 2024, true, DAY_OF_WEEK, 1, MARCH, 2024),
|
||||
Arguments.of("testBooleanDayOfWeekRollDownLeapYear", 29, FEBRUARY, 2024, false, DAY_OF_WEEK, 28, FEBRUARY, 2024)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
207
test/jdk/java/util/Calendar/CalendarLimitTest.java
Normal file
207
test/jdk/java/util/Calendar/CalendarLimitTest.java
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact 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
|
||||
* @summary test for limit on Calendar
|
||||
* @library /java/text/testlib
|
||||
* @run junit CalendarLimitTest
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.text.*;
|
||||
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
// 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
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
fail("FAIL: Exception " + s);
|
||||
ok = false;
|
||||
}
|
||||
if (((millis >= ORIGIN) && (era != GregorianCalendar.AD)) ||
|
||||
((millis < ORIGIN) && (era != GregorianCalendar.BC)) ||
|
||||
(year < 1)) {
|
||||
fail("FAIL: Bad year/era " + s);
|
||||
ok = false;
|
||||
}
|
||||
if (dom<1 || dom>31) {
|
||||
fail("FAIL: Bad DOM " + s);
|
||||
ok = false;
|
||||
}
|
||||
if (Math.abs(millis - rt.getTime()) > ONE_DAY) {
|
||||
fail("FAIL: RT fail " + s + " -> 0x" +
|
||||
Long.toHexString(rt.getTime()) + " " +
|
||||
fmt.format(rt));
|
||||
ok = false;
|
||||
}
|
||||
if (ok) System.out.println(s);
|
||||
if (era==GregorianCalendar.BC) year = 1-year;
|
||||
return year;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCalendarLimit()
|
||||
{
|
||||
Locale locale = Locale.getDefault();
|
||||
Assumptions.assumeTrue(TestUtils.usesGregorianCalendar(locale),
|
||||
locale + " does not use a Gregorian calendar");
|
||||
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)
|
||||
fail("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)
|
||||
fail("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);
|
||||
System.out.println("" + 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));
|
||||
System.out.println("0x" + Long.toHexString(t) + " -> " +
|
||||
dateFormat.format(cal.getTime()));
|
||||
t -= ONE_HOUR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//eof
|
||||
2599
test/jdk/java/util/Calendar/CalendarRegression.java
Normal file
2599
test/jdk/java/util/Calendar/CalendarRegression.java
Normal file
File diff suppressed because it is too large
Load diff
1225
test/jdk/java/util/Calendar/CalendarTest.java
Normal file
1225
test/jdk/java/util/Calendar/CalendarTest.java
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,437 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.Calendar;
|
||||
import sun.util.calendar.CalendarUtils;
|
||||
|
||||
public class CalendarAdapter extends Calendar {
|
||||
public static enum Type {
|
||||
GREGORIAN, BUDDHIST, JAPANESE;
|
||||
}
|
||||
|
||||
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"
|
||||
};
|
||||
|
||||
Calendar cal;
|
||||
GregorianAdapter gcal;
|
||||
private Type type;
|
||||
|
||||
public CalendarAdapter(Calendar cal) {
|
||||
if (cal == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
this.cal = cal;
|
||||
if (cal instanceof sun.util.BuddhistCalendar) {
|
||||
type = Type.BUDDHIST;
|
||||
} else if (cal instanceof GregorianAdapter) {
|
||||
type = Type.GREGORIAN;
|
||||
gcal = (GregorianAdapter) cal;
|
||||
} else {
|
||||
type = Type.JAPANESE;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFirstDayOfWeek(int w) {
|
||||
cal.setFirstDayOfWeek(w);
|
||||
}
|
||||
|
||||
public int getFirstDayOfWeek() {
|
||||
return cal.getFirstDayOfWeek();
|
||||
}
|
||||
|
||||
public void setMinimalDaysInFirstWeek(int value) {
|
||||
cal.setMinimalDaysInFirstWeek(value);
|
||||
}
|
||||
|
||||
public int getMinimalDaysInFirstWeek() {
|
||||
return getMinimalDaysInFirstWeek();
|
||||
}
|
||||
|
||||
public long getTimeInMillis() {
|
||||
return cal.getTimeInMillis();
|
||||
}
|
||||
|
||||
public void setTimeInMillis(long millis) {
|
||||
cal.setTimeInMillis(millis);
|
||||
}
|
||||
|
||||
public int get(int field) {
|
||||
return cal.get(field);
|
||||
}
|
||||
|
||||
public void set(int field, int value) {
|
||||
cal.set(field, value);
|
||||
}
|
||||
|
||||
public void add(int field, int amount) {
|
||||
cal.add(field, amount);
|
||||
}
|
||||
|
||||
public void roll(int field, boolean dir) {
|
||||
cal.roll(field, dir);
|
||||
}
|
||||
|
||||
public void roll(int field, int amount) {
|
||||
cal.roll(field, amount);
|
||||
}
|
||||
|
||||
public void setDate(int year, int month, int date)
|
||||
{
|
||||
cal.set(year, month, date);
|
||||
}
|
||||
|
||||
public void setDate(int era, int year, int month, int date) {
|
||||
cal.set(ERA, era);
|
||||
cal.set(year, month, date);
|
||||
}
|
||||
|
||||
public void setDateTime(int year, int month, int date, int hourOfDay, int minute, int second)
|
||||
{
|
||||
cal.set(year, month, date, hourOfDay, minute, second);
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
cal.clear();
|
||||
}
|
||||
|
||||
public void clearField(int field)
|
||||
{
|
||||
cal.clear(field);
|
||||
}
|
||||
|
||||
public boolean isSetField(int field)
|
||||
{
|
||||
return cal.isSet(field);
|
||||
}
|
||||
|
||||
public int getMaximum(int field) {
|
||||
return cal.getMaximum(field);
|
||||
}
|
||||
|
||||
public int getLeastMaximum(int field) {
|
||||
return cal.getLeastMaximum(field);
|
||||
}
|
||||
|
||||
public int getActualMaximum(int field) {
|
||||
return cal.getActualMaximum(field);
|
||||
}
|
||||
|
||||
public int getMinimum(int field) {
|
||||
return cal.getMinimum(field);
|
||||
}
|
||||
|
||||
public int getGreatestMinimum(int field) {
|
||||
return cal.getGreatestMinimum(field);
|
||||
}
|
||||
|
||||
public int getActualMinimum(int field) {
|
||||
return cal.getActualMinimum(field);
|
||||
}
|
||||
|
||||
public void setLenient(boolean lenient) {
|
||||
cal.setLenient(lenient);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return cal.toString();
|
||||
}
|
||||
|
||||
protected void computeFields() {
|
||||
}
|
||||
|
||||
protected void computeTime() {
|
||||
}
|
||||
|
||||
void setTimeOfDay(int hourOfDay, int minute, int second, int ms) {
|
||||
cal.set(HOUR_OF_DAY, hourOfDay);
|
||||
cal.set(MINUTE, minute);
|
||||
cal.set(SECOND, second);
|
||||
cal.set(MILLISECOND, ms);
|
||||
}
|
||||
|
||||
// GregorianAdapter specific methods
|
||||
|
||||
// When gcal is null, the methods throw a NPE.
|
||||
|
||||
int getSetStateFields() {
|
||||
return gcal.getSetStateFields();
|
||||
}
|
||||
|
||||
int[] getFields() {
|
||||
return gcal.getFields();
|
||||
}
|
||||
|
||||
boolean checkInternalDate(int year, int month, int dayOfMonth) {
|
||||
return gcal.checkInternalDate(year, month, dayOfMonth);
|
||||
}
|
||||
|
||||
boolean checkInternalDate(int year, int month, int dayOfMonth, int dayOfWeek) {
|
||||
return gcal.checkInternalDate(year, month, dayOfMonth, dayOfWeek);
|
||||
}
|
||||
|
||||
boolean checkInternalField(int field, int expectedValue) {
|
||||
return checkInternalField(field, expectedValue);
|
||||
}
|
||||
|
||||
// check methods
|
||||
|
||||
boolean checkAllSet() {
|
||||
initTest();
|
||||
for (int i = 0; i < FIELD_COUNT; i++) {
|
||||
checkFieldState(i, true);
|
||||
}
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkMaximum(int field, int expectedValue) {
|
||||
int val;
|
||||
if ((val = getMaximum(field)) != expectedValue) {
|
||||
appendMessage("getMaximum("+FIELD_NAMES[field]+"): got " + val
|
||||
+ " expected " + expectedValue);
|
||||
}
|
||||
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 checkMinimum(int field, int expectedValue) {
|
||||
int val;
|
||||
if ((val = getMinimum(field)) != expectedValue) {
|
||||
appendMessage("getMinimum("+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();
|
||||
checkField(YEAR, year);
|
||||
checkField(MONTH, month);
|
||||
checkField(DAY_OF_MONTH, dayOfMonth);
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkDate(int era, int year, int month, int dayOfMonth) {
|
||||
initTest();
|
||||
checkField(ERA, era);
|
||||
checkField(YEAR, year);
|
||||
checkField(MONTH, month);
|
||||
checkField(DAY_OF_MONTH, dayOfMonth);
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkDateTime(int year, int month, int dayOfMonth,
|
||||
int hourOfDay, int minute, int second) {
|
||||
initTest();
|
||||
checkField(YEAR, year);
|
||||
checkField(MONTH, month);
|
||||
checkField(DAY_OF_MONTH, dayOfMonth);
|
||||
checkField(HOUR_OF_DAY, hourOfDay);
|
||||
checkField(MINUTE, minute);
|
||||
checkField(SECOND, second);
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkDateTime(int year, int month, int dayOfMonth,
|
||||
int hourOfDay, int minute, int second, int ms) {
|
||||
initTest();
|
||||
checkField(YEAR, year);
|
||||
checkField(MONTH, month);
|
||||
checkField(DAY_OF_MONTH, dayOfMonth);
|
||||
checkField(HOUR_OF_DAY, hourOfDay);
|
||||
checkField(MINUTE, minute);
|
||||
checkField(SECOND, second);
|
||||
checkField(MILLISECOND, ms);
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkTimeOfDay(int hourOfDay, int minute, int second, int ms) {
|
||||
initTest();
|
||||
checkField(HOUR_OF_DAY, hourOfDay);
|
||||
checkField(MINUTE, minute);
|
||||
checkField(SECOND, second);
|
||||
checkField(MILLISECOND, ms);
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkMillis(long millis) {
|
||||
initTest();
|
||||
long t = cal.getTimeInMillis();
|
||||
if (t != millis) {
|
||||
appendMessage("wrong millis: got " + t + ", expected " + millis);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkFieldState(int field, boolean expectedState) {
|
||||
if (isSet(field) != expectedState) {
|
||||
appendMessage(FIELD_NAMES[field] + " state is not " + expectedState + "; ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkField(int field, int expectedValue) {
|
||||
int val;
|
||||
if ((val = get(field)) != expectedValue) {
|
||||
appendMessage("get(" + FIELD_NAMES[field] + "): got " + val +
|
||||
", expected " + expectedValue + "; ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static final String fieldName(int field) {
|
||||
return FIELD_NAMES[field];
|
||||
}
|
||||
|
||||
String toDateString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String[] eraNames = null;
|
||||
switch (type) {
|
||||
case GREGORIAN:
|
||||
eraNames = new String[] { "BCE", "" };
|
||||
break;
|
||||
|
||||
case BUDDHIST:
|
||||
eraNames = new String[] { "Before BE", "BE"};
|
||||
break;
|
||||
|
||||
case JAPANESE:
|
||||
eraNames = new String[] {
|
||||
"BeforeMeiji",
|
||||
"Meiji",
|
||||
"Taisho",
|
||||
"Showa",
|
||||
"Heisei",
|
||||
"Reiwa"
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
sb.append(eraNames[cal.get(ERA)]);
|
||||
if (sb.length() > 0)
|
||||
sb.append(' ');
|
||||
CalendarUtils.sprintf0d(sb, cal.get(YEAR), 4).append('-');
|
||||
CalendarUtils.sprintf0d(sb, cal.get(MONTH)+1, 2).append('-');
|
||||
CalendarUtils.sprintf0d(sb, cal.get(DAY_OF_MONTH), 2);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
String toTimeString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
CalendarUtils.sprintf0d(sb, cal.get(HOUR_OF_DAY), 2).append(':');
|
||||
CalendarUtils.sprintf0d(sb, cal.get(MINUTE), 2).append(':');
|
||||
CalendarUtils.sprintf0d(sb, cal.get(SECOND),2 ).append('.');
|
||||
CalendarUtils.sprintf0d(sb, cal.get(MILLISECOND), 3);
|
||||
int zoneOffset = cal.get(ZONE_OFFSET) + cal.get(DST_OFFSET);
|
||||
if (zoneOffset == 0) {
|
||||
sb.append('Z');
|
||||
} else {
|
||||
int offset;
|
||||
char sign;
|
||||
if (zoneOffset > 0) {
|
||||
offset = zoneOffset;
|
||||
sign = '+';
|
||||
} else {
|
||||
offset = -zoneOffset;
|
||||
sign = '-';
|
||||
}
|
||||
offset /= 60000;
|
||||
sb.append(sign);
|
||||
CalendarUtils.sprintf0d(sb, offset / 60, 2);
|
||||
CalendarUtils.sprintf0d(sb, offset % 60, 2);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
String toDateTimeString() {
|
||||
return toDateString() + "T" + toTimeString();
|
||||
}
|
||||
|
||||
// Message handling
|
||||
|
||||
StringBuffer msg = new StringBuffer();
|
||||
|
||||
private void initTest() {
|
||||
msg = new StringBuffer();
|
||||
}
|
||||
|
||||
String getMessage() {
|
||||
String s = msg.toString();
|
||||
msg = new StringBuffer();
|
||||
return " " + s;
|
||||
}
|
||||
|
||||
private void setMessage(String msg) {
|
||||
this.msg = new StringBuffer(msg);
|
||||
}
|
||||
|
||||
private void appendMessage(String msg) {
|
||||
this.msg.append(msg);
|
||||
}
|
||||
|
||||
boolean getStatus() {
|
||||
return msg.length() == 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,782 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
|
||||
public class CalendarTestEngine {
|
||||
private static File file;
|
||||
private static BufferedReader in;
|
||||
private static int testCount;
|
||||
private static int lineno;
|
||||
private static Locale locale;
|
||||
private static TimeZone timezone;
|
||||
private static boolean leniency = true;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Locale loc = Locale.getDefault();
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
locale = loc;
|
||||
timezone = tz;
|
||||
try {
|
||||
for (String arg : args) {
|
||||
file = new File(arg);
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
System.out.println("Starting " + file.getName() + "...");
|
||||
in = new BufferedReader(new InputStreamReader(fis));
|
||||
testCount = lineno = 0;
|
||||
run();
|
||||
System.out.println("Completed " + file.getName());
|
||||
}
|
||||
} finally {
|
||||
Locale.setDefault(loc);
|
||||
TimeZone.setDefault(tz);
|
||||
}
|
||||
}
|
||||
|
||||
private static void run() throws Exception {
|
||||
String line;
|
||||
int section = 0;
|
||||
Map<String, CalendarAdapter> cals = new HashMap<String, CalendarAdapter>();
|
||||
CalendarAdapter calendar = null;
|
||||
Result result = new Result();
|
||||
|
||||
while ((line = in.readLine()) != null) {
|
||||
lineno++;
|
||||
line = line.trim();
|
||||
// Skip blank and comment lines
|
||||
if (line.length() == 0 || line.charAt(0) == '#') {
|
||||
continue;
|
||||
}
|
||||
int comment = line.indexOf('#');
|
||||
if (comment != -1) {
|
||||
line = line.substring(0, comment).trim();
|
||||
}
|
||||
Scanner sc = new Scanner(line);
|
||||
String token = sc.next();
|
||||
Symbol operation = symbol(token);
|
||||
if (operation == null) {
|
||||
throw new RuntimeException(lineno() + "wrong op? " + token);
|
||||
}
|
||||
|
||||
|
||||
if (operation.type == Symbol.Type.EXCEPTION) {
|
||||
String className = sc.next();
|
||||
Class clazz = Exceptions.get(className);
|
||||
Exception e = result.getException();
|
||||
if (!clazz.isInstance(e)) {
|
||||
throw new RuntimeException(lineno() + "unexpected exception: got: " + e
|
||||
+ ", expected=" + clazz);
|
||||
}
|
||||
}
|
||||
|
||||
Exception x = result.getException();
|
||||
if (x != null) {
|
||||
throw new RuntimeException(lineno(result.getLineno()) + "Unexpected exception", x);
|
||||
}
|
||||
|
||||
try {
|
||||
switch (operation.type) {
|
||||
case LOCALE:
|
||||
{
|
||||
String lang = sc.next();
|
||||
String country = "", var = "";
|
||||
if (sc.hasNext()) {
|
||||
country = sc.next();
|
||||
if (sc.hasNext()) {
|
||||
var = sc.next();
|
||||
}
|
||||
}
|
||||
locale = Locale.of(lang, country, var);
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMEZONE:
|
||||
{
|
||||
if (sc.hasNext()) {
|
||||
String id = sc.next();
|
||||
timezone = TimeZone.getTimeZone(id);
|
||||
if (!timezone.getID().equals(id)) {
|
||||
System.err.printf("Warning: line %d: may get wrong time zone? "
|
||||
+"(specified: %s vs. actual: %s)%n",
|
||||
lineno, id, timezone.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NEW:
|
||||
{
|
||||
Symbol op = symbol(sc.next());
|
||||
Calendar cal = null;
|
||||
switch (op.type) {
|
||||
case INSTANCE:
|
||||
cal = Calendar.getInstance(timezone, locale);
|
||||
break;
|
||||
case GREGORIAN:
|
||||
cal = new GregorianAdapter(timezone, locale);
|
||||
break;
|
||||
default:
|
||||
symbolError(op);
|
||||
break;
|
||||
}
|
||||
cal.setLenient(leniency);
|
||||
calendar = new CalendarAdapter(cal);
|
||||
if (sc.hasNext()) {
|
||||
String name = sc.next();
|
||||
cals.put(name.toLowerCase(Locale.ROOT), calendar);
|
||||
if (!leniency) {
|
||||
System.out.printf("%s%s is non-lenient%n", lineno(), name);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(lineno() + "Missing associated name");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TEST:
|
||||
testCount++;
|
||||
if (sc.hasNext()) {
|
||||
System.out.printf("Test#%d:%s%n", testCount, sc.findInLine(".+"));
|
||||
} else {
|
||||
System.out.printf("Test#%d:%n", testCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case USE:
|
||||
{
|
||||
String name = sc.next().toLowerCase(Locale.ROOT);
|
||||
CalendarAdapter c = cals.get(name);
|
||||
if (c == null) {
|
||||
throw new CalendarTestException(lineno() + "calendar " + name
|
||||
+ " not found.");
|
||||
}
|
||||
calendar = c;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASSIGN:
|
||||
{
|
||||
long v = getLong(sc);
|
||||
String to = sc.next().toLowerCase(Locale.ROOT);
|
||||
boolean assign = true;
|
||||
if (sc.hasNext()) {
|
||||
Symbol condition = symbol(sc.next());
|
||||
if (condition.type == Symbol.Type.IF) {
|
||||
long v1 = getLong(sc);
|
||||
Symbol op = symbol(sc.next());
|
||||
long v2 = getLong(sc);
|
||||
assign = relation(v1, op, v2);
|
||||
} else {
|
||||
symbolError(condition);
|
||||
}
|
||||
}
|
||||
if (assign)
|
||||
Variable.newVar(to, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVAL:
|
||||
{
|
||||
long v1 = getLong(sc);
|
||||
String op = sc.next();
|
||||
Symbol operator = symbol(op);
|
||||
if (operator == null) {
|
||||
throw new RuntimeException("op " + op + " invalid");
|
||||
}
|
||||
long v2 = getLong(sc);
|
||||
if (operator.isArithmetic()) {
|
||||
long value = 0;
|
||||
switch (operator.type) {
|
||||
case PLUS:
|
||||
value = v1 + v2;
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
value = v1 - v2;
|
||||
break;
|
||||
|
||||
case MULTIPLY:
|
||||
value = v1 * v2;
|
||||
break;
|
||||
|
||||
case DIVIDE:
|
||||
value = v1 / v2;
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
value = v1 % v2;
|
||||
break;
|
||||
|
||||
default:
|
||||
symbolError(operator);
|
||||
break;
|
||||
}
|
||||
result.setValue(value);
|
||||
} else {
|
||||
if (!relation(v1, operator, v2)) {
|
||||
throw new RuntimeException("not " + v1 + " " + op + " " + v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CLEAR:
|
||||
{
|
||||
Symbol sym = symbol(sc.next());
|
||||
if (sym.type == Symbol.Type.ALL) {
|
||||
calendar.clearAll();
|
||||
} else if (sym.type == Symbol.Type.FIELD) {
|
||||
int f = sym.value();
|
||||
calendar.clearField(f);
|
||||
} else {
|
||||
symbolError(sym);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET:
|
||||
{
|
||||
Symbol sym = symbol(sc.next());
|
||||
switch (sym.type) {
|
||||
case FIELD:
|
||||
{
|
||||
int f = sym.value();
|
||||
int v = calendar.get(f);
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case MILLIS:
|
||||
{
|
||||
long v = calendar.getTimeInMillis();
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case MINIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = calendar.getMinimum(f);
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case GREATESTMINIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = calendar.getGreatestMinimum(f);
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTUALMINIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = calendar.getActualMinimum(f);
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAXIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = calendar.getMaximum(f);
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case LEASTMAXIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = calendar.getLeastMaximum(f);
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTUALMAXIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = calendar.getActualMaximum(f);
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRSTDAYOFWEEK:
|
||||
{
|
||||
result.setValue(calendar.getFirstDayOfWeek());
|
||||
}
|
||||
break;
|
||||
|
||||
case MINIMALDAYSINFIRSTWEEK:
|
||||
{
|
||||
int v = calendar.getMinimalDaysInFirstWeek();
|
||||
result.setValue(v);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
symbolError(sym);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ADD:
|
||||
case ROLL:
|
||||
{
|
||||
Symbol sym = symbol(sc.next());
|
||||
if (sym.type == Symbol.Type.FIELD) {
|
||||
int f = sym.value();
|
||||
int v = sc.nextInt();
|
||||
switch (operation.type) {
|
||||
case ADD:
|
||||
calendar.add(f, v);
|
||||
break;
|
||||
|
||||
case ROLL:
|
||||
calendar.roll(f, v);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
symbolError(sym);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET:
|
||||
{
|
||||
Symbol sym = symbol(sc.next());
|
||||
switch (sym.type) {
|
||||
case FIELD:
|
||||
{
|
||||
int f = sym.value();
|
||||
int v = getInt(sc);
|
||||
calendar.set(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case MILLIS:
|
||||
{
|
||||
long v = getLong(sc);
|
||||
calendar.setTimeInMillis(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case DATE:
|
||||
{
|
||||
int a = getInt(sc);
|
||||
int b = getInt(sc);
|
||||
int c = getInt(sc);
|
||||
if (sc.hasNext()) {
|
||||
int d = getInt(sc);
|
||||
// era, year, month, dayOfMonth
|
||||
calendar.setDate(a, b, c, d);
|
||||
} else {
|
||||
// year, month, dayOfMonth
|
||||
calendar.setDate(a, b, c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DATETIME:
|
||||
{
|
||||
int y = getInt(sc);
|
||||
int m = getInt(sc);
|
||||
int d = getInt(sc);
|
||||
int hh = getInt(sc);
|
||||
int mm = getInt(sc);
|
||||
int ss = getInt(sc);
|
||||
calendar.setDateTime(y, m, d, hh, mm, ss);
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMEOFDAY:
|
||||
{
|
||||
int hh = getInt(sc);
|
||||
int mm = getInt(sc);
|
||||
int ss = getInt(sc);
|
||||
int ms = getInt(sc);
|
||||
calendar.setTimeOfDay(hh, mm, ss, ms);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRSTDAYOFWEEK:
|
||||
{
|
||||
int v = getInt(sc);
|
||||
calendar.setFirstDayOfWeek(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case MINIMALDAYSINFIRSTWEEK:
|
||||
{
|
||||
int v = getInt(sc);
|
||||
calendar.setMinimalDaysInFirstWeek(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case LENIENT:
|
||||
if (calendar != null) {
|
||||
calendar.setLenient(true);
|
||||
}
|
||||
leniency = true;
|
||||
break;
|
||||
|
||||
case NONLENIENT:
|
||||
if (calendar != null) {
|
||||
calendar.setLenient(false);
|
||||
}
|
||||
leniency = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
symbolError(sym);
|
||||
}
|
||||
if (sc.hasNext()) {
|
||||
throw new RuntimeException(lineno() + "extra param(s) "
|
||||
+ sc.findInLine(".+"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CHECK:
|
||||
{
|
||||
Symbol sym = symbol(sc.next());
|
||||
boolean stat = false;
|
||||
switch (sym.type) {
|
||||
case MILLIS:
|
||||
{
|
||||
long millis = getLong(sc);
|
||||
stat = calendar.checkMillis(millis);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIELD:
|
||||
{
|
||||
int f = sym.value();
|
||||
int v = getInt(sc);
|
||||
stat = calendar.checkField(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case DATE:
|
||||
{
|
||||
int a = getInt(sc);
|
||||
int b = getInt(sc);
|
||||
int c = getInt(sc);
|
||||
if (sc.hasNext()) {
|
||||
int d = getInt(sc);
|
||||
// era year month dayOfMonth
|
||||
stat = calendar.checkDate(a, b, c, d);
|
||||
} else {
|
||||
// year month dayOfMonth
|
||||
stat = calendar.checkDate(a, b, c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DATETIME:
|
||||
{
|
||||
int y = getInt(sc);
|
||||
int m = getInt(sc);
|
||||
int d = getInt(sc);
|
||||
int hh = getInt(sc);
|
||||
int mm = getInt(sc);
|
||||
int ss = getInt(sc);
|
||||
if (sc.hasNext()) {
|
||||
int ms = getInt(sc);
|
||||
stat = calendar.checkDateTime(y, m, d, hh, mm, ss, ms);
|
||||
} else {
|
||||
stat = calendar.checkDateTime(y, m, d, hh, mm, ss);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMEOFDAY:
|
||||
{
|
||||
int hh = sc.nextInt();
|
||||
int mm = sc.nextInt();
|
||||
int ss = sc.nextInt();
|
||||
int millis = sc.nextInt();
|
||||
stat = calendar.checkTimeOfDay(hh, mm, ss, millis);
|
||||
}
|
||||
break;
|
||||
|
||||
case MINIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = getInt(sc);
|
||||
stat = calendar.checkMinimum(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case GREATESTMINIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = getInt(sc);
|
||||
stat = calendar.checkGreatestMinimum(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTUALMINIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = getInt(sc);
|
||||
stat = calendar.checkActualMinimum(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAXIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = getInt(sc);
|
||||
stat = calendar.checkMaximum(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case LEASTMAXIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = getInt(sc);
|
||||
stat = calendar.checkLeastMaximum(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTUALMAXIMUM:
|
||||
{
|
||||
int f = getInt(sc);
|
||||
int v = getInt(sc);
|
||||
stat = calendar.checkActualMaximum(f, v);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException(lineno() + "Unknown operand");
|
||||
}
|
||||
if (!stat) {
|
||||
throw new RuntimeException(lineno() + calendar.getMessage());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINT:
|
||||
{
|
||||
String s = sc.next();
|
||||
if (s.charAt(0) == '$') {
|
||||
Variable var = variable(s);
|
||||
if (var == null)
|
||||
throw new RuntimeException(lineno() + "Unknown token: " + s);
|
||||
System.out.printf("%s%s=%d%n", lineno(), s, var.longValue());
|
||||
break;
|
||||
}
|
||||
|
||||
Symbol sym = symbol(s);
|
||||
switch (sym.type) {
|
||||
case INSTANCE:
|
||||
{
|
||||
Calendar cal = calendar;
|
||||
String name = "current";
|
||||
if (sc.hasNext()) {
|
||||
name = sc.next();
|
||||
cal = cals.get(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
System.out.printf("%s%s=%s%n", lineno(), name, cal);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIELD:
|
||||
{
|
||||
int f = sym.value();
|
||||
String remark = "";
|
||||
if (sc.hasNext()) {
|
||||
remark = sc.findInLine(".+");
|
||||
}
|
||||
System.out.printf("%s%s=%d %s%n", lineno(), calendar.fieldName(f),
|
||||
calendar.get(f), remark);
|
||||
}
|
||||
break;
|
||||
|
||||
case MILLIS:
|
||||
{
|
||||
String remark = "";
|
||||
if (sc.hasNext()) {
|
||||
remark = sc.findInLine(".+");
|
||||
}
|
||||
System.out.printf("%sMillis=%d %s%n", lineno(),
|
||||
calendar.getTimeInMillis(), remark);
|
||||
}
|
||||
break;
|
||||
|
||||
case MINIMUM:
|
||||
System.out.printf("%s%s=%d%n", lineno(),
|
||||
s, calendar.getMinimum(getInt(sc)));
|
||||
break;
|
||||
|
||||
case GREATESTMINIMUM:
|
||||
System.out.printf("%s%s=%d%n", lineno(),
|
||||
s, calendar.getGreatestMinimum(getInt(sc)));
|
||||
break;
|
||||
|
||||
case ACTUALMINIMUM:
|
||||
System.out.printf("%s%s=%d%n", lineno(),
|
||||
s, calendar.getActualMinimum(getInt(sc)));
|
||||
break;
|
||||
|
||||
case MAXIMUM:
|
||||
System.out.printf("%s%s=%d%n", lineno(),
|
||||
s, calendar.getMaximum(getInt(sc)));
|
||||
break;
|
||||
|
||||
case LEASTMAXIMUM:
|
||||
System.out.printf("%s%s=%d%n", lineno(),
|
||||
s, calendar.getLeastMaximum(getInt(sc)));
|
||||
break;
|
||||
|
||||
case ACTUALMAXIMUM:
|
||||
System.out.printf("%s%s=%d%n", lineno(),
|
||||
s, calendar.getActualMaximum(getInt(sc)));
|
||||
break;
|
||||
|
||||
case DATE:
|
||||
System.out.println(lineno() + calendar.toDateString());
|
||||
break;
|
||||
|
||||
case DATETIME:
|
||||
System.out.println(lineno() + calendar.toDateTimeString());
|
||||
break;
|
||||
|
||||
case TIMEZONE:
|
||||
System.out.println(lineno() + "timezone=" + timezone);
|
||||
break;
|
||||
|
||||
case LOCALE:
|
||||
System.out.println(lineno() + "locale=" + locale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CalendarTestException cte) {
|
||||
throw cte;
|
||||
} catch (NoSuchElementException nsee) {
|
||||
throw new NoSuchElementException(lineno() + "syntax error");
|
||||
} catch (Exception e) {
|
||||
result.setException(e);
|
||||
result.setLineno(lineno);
|
||||
}
|
||||
}
|
||||
Exception x = result.getException();
|
||||
if (x != null) {
|
||||
throw new RuntimeException(lineno(result.getLineno()) + "Unexpected exception", x);
|
||||
}
|
||||
}
|
||||
|
||||
private static Symbol symbol(String s) {
|
||||
return Symbol.get(s.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
private static Variable variable(String s) {
|
||||
return Variable.get(s.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
private static int getInt(Scanner sc) {
|
||||
if (sc.hasNextInt()) {
|
||||
return sc.nextInt();
|
||||
}
|
||||
|
||||
String s = sc.next();
|
||||
if (s.charAt(0) == '$') {
|
||||
Variable var = variable(s);
|
||||
if (var == null)
|
||||
throw new RuntimeException(lineno() + "Unknown token: " + s);
|
||||
return var.intValue();
|
||||
}
|
||||
Symbol sym = symbol(s);
|
||||
if (sym == null)
|
||||
throw new RuntimeException(lineno() + "Unknown token: " + s);
|
||||
return sym.value();
|
||||
}
|
||||
|
||||
private static long getLong(Scanner sc) {
|
||||
if (sc.hasNextLong()) {
|
||||
return sc.nextLong();
|
||||
}
|
||||
|
||||
String s = sc.next();
|
||||
if (s.charAt(0) == '$') {
|
||||
Variable var = variable(s);
|
||||
if (var == null)
|
||||
throw new RuntimeException(lineno() + "Unknown token: " + s);
|
||||
return var.longValue();
|
||||
}
|
||||
Symbol sym = symbol(s);
|
||||
if (sym == null)
|
||||
throw new RuntimeException(lineno() + "Unknown token: " + s);
|
||||
return sym.value();
|
||||
}
|
||||
|
||||
private static boolean relation(long v1, Symbol relop, long v2) {
|
||||
boolean result = false;
|
||||
switch (relop.type) {
|
||||
case GT:
|
||||
result = v1 > v2;
|
||||
break;
|
||||
|
||||
case GE:
|
||||
result = v1 >= v2;
|
||||
break;
|
||||
|
||||
case EQ:
|
||||
result = v1 == v2;
|
||||
break;
|
||||
|
||||
case NEQ:
|
||||
result = v1 != v2;
|
||||
break;
|
||||
|
||||
case LE:
|
||||
result = v1 <= v2;
|
||||
break;
|
||||
|
||||
case LT:
|
||||
result = v1 < v2;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String lineno() {
|
||||
return lineno(lineno);
|
||||
}
|
||||
|
||||
private static String lineno(int ln) {
|
||||
return file.getName() + ":" + ln + ": ";
|
||||
}
|
||||
|
||||
private static void symbolError(Symbol sym) {
|
||||
throw new RuntimeException(lineno + ": unexpected symbol: " + sym);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
public class CalendarTestException extends RuntimeException {
|
||||
public CalendarTestException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CalendarTestException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public CalendarTestException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class Exceptions {
|
||||
private static Map<String, Class> exceptions = new HashMap<String, Class>();
|
||||
|
||||
static {
|
||||
put("nullpointerexception", NullPointerException.class);
|
||||
put("illegalargumentexception", IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
private static void put(String key, Class clazz) {
|
||||
Class c = exceptions.put(key, clazz);
|
||||
if (c != null) {
|
||||
throw new RuntimeException(key + " already exisits");
|
||||
}
|
||||
}
|
||||
|
||||
public static Class get(String key) {
|
||||
return exceptions.get(key.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class GregorianAdapter extends GregorianCalendar {
|
||||
static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1;
|
||||
|
||||
public GregorianAdapter() {
|
||||
super();
|
||||
}
|
||||
|
||||
public GregorianAdapter(TimeZone tz) {
|
||||
super(tz);
|
||||
}
|
||||
|
||||
public GregorianAdapter(Locale loc) {
|
||||
super(loc);
|
||||
}
|
||||
|
||||
public GregorianAdapter(TimeZone tz, Locale loc) {
|
||||
super(tz, loc);
|
||||
}
|
||||
|
||||
public void computeTime() {
|
||||
super.computeTime();
|
||||
}
|
||||
|
||||
public void computeFields() {
|
||||
super.computeFields();
|
||||
}
|
||||
|
||||
public void complete() {
|
||||
super.complete();
|
||||
}
|
||||
|
||||
StringBuffer msg = new StringBuffer();
|
||||
|
||||
void initTest() {
|
||||
msg = new StringBuffer();
|
||||
}
|
||||
|
||||
String getMessage() {
|
||||
String s = msg.toString();
|
||||
msg = new StringBuffer();
|
||||
return " " + s;
|
||||
}
|
||||
|
||||
void setMessage(String msg) {
|
||||
this.msg = new StringBuffer(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 checkInternalDate(int year, int month, int dayOfMonth) {
|
||||
initTest();
|
||||
checkInternalField(YEAR, year);
|
||||
checkInternalField(MONTH, month);
|
||||
checkInternalField(DAY_OF_MONTH, dayOfMonth);
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkInternalDate(int year, int month, int dayOfMonth, int dayOfWeek) {
|
||||
initTest();
|
||||
checkInternalField(YEAR, year);
|
||||
checkInternalField(MONTH, month);
|
||||
checkInternalField(DAY_OF_MONTH, dayOfMonth);
|
||||
checkInternalField(DAY_OF_WEEK, dayOfWeek);
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
boolean checkInternalField(int field, int expectedValue) {
|
||||
int val;
|
||||
if ((val = internalGet(field)) != expectedValue) {
|
||||
appendMessage("internalGet(" + CalendarAdapter.FIELD_NAMES[field] + "): got " + val +
|
||||
", expected " + expectedValue + "; ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import static java.util.Calendar.*;
|
||||
|
||||
|
||||
public class JapaneseRollDayOfWeekTestGenerator {
|
||||
private static final String[] ERAS = {
|
||||
"BeforeMeiji", "Meiji", "Taisho", "Showa", "Heisei"
|
||||
};
|
||||
|
||||
private static final String[] DAYOFWEEK = {
|
||||
null, "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
|
||||
private static final int[] DAYOFMONTH = {
|
||||
25, 26, 27, 28, 29, 30, 31,
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
};
|
||||
|
||||
private static final int DOM_BASE = 7;
|
||||
|
||||
//Usage: JapaneseRollDayOfWeekTestGenerator will generate test script into
|
||||
// file rolldow.cts.
|
||||
public static void generateTestScript(String[] args) throws Exception{
|
||||
Locale.setDefault(Locale.ROOT);
|
||||
|
||||
//This test generator assumes that Heisei has (nYears - 1) or more years.
|
||||
int nYears = (args.length == 1) ?
|
||||
Math.max(3, Math.min(Integer.parseInt(args[0]), 40)) : 28;
|
||||
|
||||
// Start from Showa 63
|
||||
int era = 3;
|
||||
int year = 63;
|
||||
Path testPath = Paths.get(System.getProperty("test.classes"));
|
||||
String scFileName = testPath + "/rolldow.cts";
|
||||
|
||||
try (PrintWriter out = new PrintWriter(scFileName)){
|
||||
out.println("locale ja JP JP\n" + "new instance jcal\n" + "use jcal");
|
||||
for (int y = 0; y < nYears; y++) {
|
||||
out.printf("\nTest %s %d\n", ERAS[era], year);
|
||||
for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) {
|
||||
int endFdw = fdw + 6;
|
||||
if (endFdw > SATURDAY) {
|
||||
endFdw -= 7;
|
||||
}
|
||||
for (int mdifw = 1; mdifw <= 7; mdifw++) {
|
||||
int domIndex = DOM_BASE;
|
||||
out.println(" clear all");
|
||||
out.printf(" set FirstDayOfWeek %s\n", DAYOFWEEK[fdw]);
|
||||
out.printf(" set MinimalDaysInFirstWeek %d\n", mdifw);
|
||||
out.printf(" set date %s %d Jan 1\n", ERAS[era], year);
|
||||
out.println(" get week_of_year\n" + " assign $result $woy");
|
||||
out.println(" get day_of_week\n" + " assign $result $doy");
|
||||
|
||||
int gyear = year + (year >= 60 ? 1925 : 1988);
|
||||
int next = new GregorianCalendar(gyear, JANUARY, 1).get(DAY_OF_WEEK);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
||||
out.println(" roll day_of_week 1");
|
||||
next = nextFdw(next, fdw, endFdw);
|
||||
if (next == fdw) {
|
||||
domIndex -= 6;
|
||||
} else {
|
||||
domIndex++;
|
||||
}
|
||||
int dom = DAYOFMONTH[domIndex];
|
||||
out.printf("\tcheck date %d %s %d%n", (dom >= 25) ? year - 1 : year,
|
||||
(dom >= 25) ? "Dec" : "Jan", dom);
|
||||
out.println("\teval $doy + 1");
|
||||
out.println("\tassign $result $doy");
|
||||
out.println("\tassign Sun $doy if $doy > Sat");
|
||||
out.println("\tcheck day_of_week $doy");
|
||||
out.println("\tcheck week_of_year $woy");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
out.println("\troll day_of_week -1");
|
||||
out.println("\teval $doy - 1");
|
||||
out.println("\tassign $result $doy");
|
||||
out.println("\tassign Sat $doy if $doy < Sun");
|
||||
out.println("\tcheck day_of_week $doy");
|
||||
out.println("\tcheck week_of_year $woy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (year == 64 && era == 3) {
|
||||
era++;
|
||||
year = 2;
|
||||
} else {
|
||||
year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int nextFdw(int x, int start, int end) {
|
||||
if (x == end)
|
||||
return start;
|
||||
x++;
|
||||
if (x > SATURDAY)
|
||||
x = SUNDAY;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary tests Japanese Calendar.
|
||||
* @bug 4609228
|
||||
* @modules java.base/sun.util
|
||||
* java.base/sun.util.calendar
|
||||
* @compile
|
||||
* CalendarAdapter.java
|
||||
* CalendarTestEngine.java
|
||||
* CalendarTestException.java
|
||||
* Exceptions.java
|
||||
* GregorianAdapter.java
|
||||
* Result.java
|
||||
* Symbol.java
|
||||
* Variable.java
|
||||
* JapaneseRollDayOfWeekTestGenerator.java
|
||||
* @run main/timeout=120/othervm JapaneseRollTests
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class JapaneseRollTests {
|
||||
private static List<String> TZ_TEST_LIST = Arrays.asList(
|
||||
"tz_japan.cts", "tz_pst.cts");
|
||||
private static Path srcPath = Paths.get(System.getProperty("test.src"));
|
||||
private static Path testPath = Paths.get(System.getProperty("test.classes"));
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
List<String> modeList = getFileNameList("params");
|
||||
//Test only 3 years by default
|
||||
String[] jpyear ={"3"};
|
||||
JapaneseRollDayOfWeekTestGenerator.generateTestScript(jpyear);
|
||||
|
||||
for (String tz : TZ_TEST_LIST) {
|
||||
for(String mode:modeList){
|
||||
String[] ts = { srcPath + "/timezones/" + tz,
|
||||
srcPath + "/params/" + mode,
|
||||
testPath + "/rolldow.cts"};
|
||||
|
||||
CalendarTestEngine.main(ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> getFileNameList(String type ){
|
||||
List<String> fileList = new ArrayList<>();
|
||||
File dir = new File(srcPath + "/"+ type);
|
||||
File[] testFiles = dir.listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.toLowerCase().endsWith(".cts");
|
||||
}
|
||||
});
|
||||
for (File f:testFiles) {
|
||||
fileList.add(f.getName());
|
||||
}
|
||||
|
||||
return fileList;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary tests Japanese Calendar.
|
||||
* @bug 4609228 8187649 8273924
|
||||
* @modules java.base/sun.util
|
||||
* java.base/sun.util.calendar
|
||||
* @compile
|
||||
* CalendarAdapter.java
|
||||
* CalendarTestEngine.java
|
||||
* CalendarTestException.java
|
||||
* Exceptions.java
|
||||
* GregorianAdapter.java
|
||||
* Result.java
|
||||
* Symbol.java
|
||||
* Variable.java
|
||||
* @run main/othervm/timeout=120 JapaneseTests
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class JapaneseTests {
|
||||
|
||||
private static List<String> SET_LENIENT = Arrays.asList(
|
||||
"japanese_minmax.cts",
|
||||
"japanese_add.cts",
|
||||
"japanese_roll.cts",
|
||||
"japanese_exceptions.cts");
|
||||
private static List<String> DEFAULT_LENIENT = Arrays.asList(
|
||||
"japanese.cts",
|
||||
"japanese_normalization.cts");
|
||||
|
||||
private static Path srcPath = Paths.get(System.getProperty("test.src"));
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
List<String> tzList = getFileNameList("timezones");
|
||||
List<String> modeList = getFileNameList("params");
|
||||
|
||||
for (String jaTest: DEFAULT_LENIENT) {
|
||||
for (String tz : tzList) {
|
||||
String[] ts = { srcPath + "/timezones/" + tz,
|
||||
srcPath + "/japanese/" + jaTest};
|
||||
CalendarTestEngine.main(ts);
|
||||
}
|
||||
}
|
||||
|
||||
for (String jaTest: SET_LENIENT) {
|
||||
for (String tz : tzList) {
|
||||
for (String mode : modeList) {
|
||||
String[] ts = { srcPath + "/timezones/" + tz,
|
||||
srcPath + "/params/" + mode,
|
||||
srcPath + "/japanese/" + jaTest };
|
||||
CalendarTestEngine.main(ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> getFileNameList(String type ){
|
||||
List<String> fileList = new ArrayList<>();
|
||||
File dir = new File(srcPath + "/"+ type);
|
||||
File[] testFiles = dir.listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.toLowerCase().endsWith(".cts");
|
||||
}
|
||||
});
|
||||
for (File f:testFiles) {
|
||||
fileList.add(f.getName());
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
}
|
||||
566
test/jdk/java/util/Calendar/CalendarTestScripts/README
Normal file
566
test/jdk/java/util/Calendar/CalendarTestScripts/README
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
|
||||
This code is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License version 2 only, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
version 2 for more details (a copy is included in the LICENSE file that
|
||||
accompanied this code).
|
||||
|
||||
You should have received a copy of the GNU General Public License version
|
||||
2 along with this work; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
or visit www.oracle.com if you need additional information or have any
|
||||
questions.
|
||||
|
||||
CALENDAR TEST SCRIPT
|
||||
|
||||
Masayoshi Okutsu
|
||||
2005-03-18
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Calendar Test Script is a simple scripting language to describe test cases
|
||||
for java.util.Calendar and its subclasses. It should be much more
|
||||
productive to use this script language than writing test programs in Java.
|
||||
|
||||
A script looks like below.
|
||||
|
||||
1 locale ja JP JP
|
||||
2 timezone Asia/Tokyo
|
||||
3 new instance jcal
|
||||
4 test day of week on Heisei 1 Jan 8
|
||||
5 use jcal
|
||||
6 clear all
|
||||
7 set date Heisei 1 Jan 8
|
||||
8 check day_of_week Sun
|
||||
|
||||
The first line defines a Locale to be used for creating Calendar
|
||||
instances. Line 2 defines the current TimeZone to be Asia/Tokyo that is
|
||||
used creating Calendar instances. Line 3 creates a Calendar instance with
|
||||
the Locale and TimeZone instances. Its reference name is `jcal'. Line 4
|
||||
indicates a start point for a test case with a short test case
|
||||
description. Line 5 designates `jcal' as the current Calendar
|
||||
instance. All calendar operation commands are applied to the current
|
||||
Calendar instance. Line 6 clears all of the calendar fields (e.g., ERA,
|
||||
YEAR, MONTH, etc.). Line 7 sets the ERA, YEAR, MONTH and DAY_OF_MONTH
|
||||
fields to Heisei, 1, JANUARY and 8, respectively. Line 8 checks if the
|
||||
DAY_OF_WEEK value is SUNDAY. If it's not, then a RuntimeException is
|
||||
thrown.
|
||||
|
||||
Script Grammar
|
||||
--------------
|
||||
|
||||
A line is a comment, blank or command line. Any text after '#' is always
|
||||
treated as a comment and ignored, like a shell script.
|
||||
|
||||
# This is a comment line.
|
||||
|
||||
A command line consists of a command and its parameters, optionally
|
||||
followed by a comment. For example,
|
||||
|
||||
set date Heisei 1 Jan 8 # The first day of Heisei
|
||||
|
||||
`set' is a command to set `date' to Heisei year 1 January 8th. `Heisei' is
|
||||
a constant for the Japanese Heisei era value which is consistent with the
|
||||
Japanese imperial calendar implementation. `Jan' is a constant for
|
||||
Calendar.SUNDAY. The text after '#' is ignored.
|
||||
|
||||
Keywords are case-insensitive.
|
||||
|
||||
set DAY_OF_WEEK MON
|
||||
SET day_of_week Mon
|
||||
|
||||
are the same thing.
|
||||
|
||||
Lexical analysis is very simple. A command must be complete in a single
|
||||
line. Keywords and symbols must be separated by white space. For example,
|
||||
"$result+1" is parsed as one token. It must be written as "$result + 1".
|
||||
|
||||
Variables
|
||||
---------
|
||||
|
||||
Variables can be used in any context to store an integer value and are
|
||||
referenced in any contexts where an integer value is required. A variable
|
||||
name must start with a '$', such as `$maxyear'. The integer value is
|
||||
handled as a long.
|
||||
|
||||
`$result' is reserved for storing a result of a get commend operation. For
|
||||
example, executing the following command:
|
||||
|
||||
get day_of_month
|
||||
|
||||
sets $result to the get(Calendar.DAY_OF_MONTH) value of the current
|
||||
Calendar instance. (See NEW and USE commands for the current Calendar
|
||||
instance.)
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
The following defines each command and its syntax. Keywords are described
|
||||
in upper case below.
|
||||
|
||||
LOCALE language [country [variant]]
|
||||
|
||||
Creates a Locale instance by calling new Locale(language, country,
|
||||
variant). country and variant are optional. Defining LOCALE overrides
|
||||
the previously defined Locale value if any. The initial Locale value
|
||||
is Locale.getDefault().
|
||||
|
||||
TIMEZONE tzid
|
||||
|
||||
Creates a TimeZone instance by calling
|
||||
TimeZone.getTimeZone(tzid). Defining TIMEZONE overrides the previously
|
||||
defined Locale value if any. The initial TimeZone value is
|
||||
TimeZone.getDefault().
|
||||
|
||||
NEW INSTANCE calendarname
|
||||
|
||||
Creates a Calendar instance by calling Calendar.getInstance(TimeZone,
|
||||
Locale). TimeZone and Locale are those defined by TIMEZONE and LOCALE
|
||||
commands (or their initial values), respectively. The instance is
|
||||
associated with `calendarname' and becomes the current Calendar
|
||||
instance to be used for testing.
|
||||
|
||||
NEW GREGORIAN calendarname
|
||||
|
||||
Creates a Calendar instance by calling new GregorianCalendar(TimeZone,
|
||||
Locale). TimeZone and Locale are those defined by TIMEZONE and LOCALE
|
||||
commands (or their initial values), respectively. The instance is
|
||||
associated with `calendarname' and becomes the current Calendar
|
||||
instance to be used for testing.
|
||||
|
||||
TEST [comments...]
|
||||
|
||||
Declares the beginning of a test case. `comments...' gives a short
|
||||
description of a test case. (Multiple lines are not supported.) The
|
||||
test system displays `comments...' to System.out. For example, the
|
||||
following command:
|
||||
|
||||
test A test case for non-lenient mode
|
||||
|
||||
will output:
|
||||
|
||||
Test #n: A test case for non-lenient mode
|
||||
|
||||
where `n' is a sequence number of TEST command lines appeared in a
|
||||
test script file.
|
||||
|
||||
USE calendarname
|
||||
|
||||
Specifies the current Calendar instance to use for testing by
|
||||
`calendarname'. If you need to use more than one Calendar instances,
|
||||
then you have to switch those Calendar instances by the USE command.
|
||||
|
||||
ASSIGN value variable
|
||||
|
||||
Assigns `value' to `variable'. `value' can be an integer literal, a
|
||||
variable name or a constant. Examples are:
|
||||
|
||||
assign 2005 $year
|
||||
assign $result $temp
|
||||
assign Sun $Microsystems
|
||||
|
||||
ASSIGN value variable IF condition
|
||||
|
||||
Assigns `value' to `variable' if `condition' is true. `condition' is a
|
||||
relational expression as:
|
||||
|
||||
value1 relOp value2
|
||||
|
||||
`relOp' must be one of >, >=, ==, !=, <=, <.
|
||||
|
||||
EVAL expression
|
||||
|
||||
Evaluates the given *simple* expression and assigns the expression
|
||||
value to $result if `op' is one of the arithmetic operators (+, -, *,
|
||||
/, %). If `op' is one of the relational operators (>, >=, ==, !=, <=,
|
||||
<), then EVAL throws an exception if the expression value is false, or
|
||||
does nothing if the value is true. Note that an operator and values
|
||||
must be separated by white space.
|
||||
|
||||
The following is an example of the ASSIGN and EVAL commands usage to
|
||||
get the next day of week value. Then, it's used to check the
|
||||
roll(DAY_OF_WEEK) result.
|
||||
|
||||
get day_of_week
|
||||
eval $result + 1
|
||||
assign $result $nextDayOfWeek
|
||||
assign Sun $nextDayOfWeek if $nextDayOfWeek > Sat
|
||||
roll day_of_week 1
|
||||
check day_of_week $nextDayOfWeek
|
||||
|
||||
CLEAR ALL
|
||||
|
||||
Clears all the calendar fields of the current Calendar instance by
|
||||
calling Calendar.clear().
|
||||
|
||||
CLEAR field
|
||||
|
||||
Clears the specified calendar `field' of the current Calendar instance
|
||||
by calling Calendar.clear(field).`field' must be one of the Calendar
|
||||
field indices, ERA, YEAR, MONTH, DAY_OF_MONTH, WEEK_OF_YEAR, etc.
|
||||
|
||||
GET MILLIS
|
||||
|
||||
Gets the millisecond value of the current Calendar instance by calling
|
||||
Calendar.getTimeInMillis(). The value is assigned to $result.
|
||||
|
||||
GET field
|
||||
|
||||
Gets the `field' value specified of the current Calendar instance by
|
||||
calling Calendar.get(field). The value is assigned to $result.
|
||||
|
||||
GET MIN field
|
||||
|
||||
Gets the minimum value of the specified `field' of the current
|
||||
Calendar instance by calling Calendar.getMinimum(field). The value is
|
||||
assigned to $result.
|
||||
|
||||
GET GREATESTMIN field
|
||||
|
||||
Gets the greatest minimum value of the specified `field' of the
|
||||
current Calendar instance by calling
|
||||
Calendar.getGreatestMinimum(field). The value is assigned to $result.
|
||||
|
||||
GET ACTUALMIN field
|
||||
|
||||
Gets the actual minimum value of the specified `field' of the current
|
||||
Calendar instance by calling Calendar.getActualMinimum(field). The
|
||||
value is assigned to $result.
|
||||
|
||||
GET MAX field
|
||||
|
||||
Gets the maximum value of the specified `field' of the current
|
||||
Calendar instance by calling Calendar.getMaximum(field). The value is
|
||||
assigned to $result.
|
||||
|
||||
GET LEASTMAX field
|
||||
|
||||
Gets the least maximum value of the specified `field' of the current
|
||||
Calendar instance by calling Calendar.getLeastMaximum(field). The
|
||||
value is assigned to $result.
|
||||
|
||||
GET ACTUALMAX field
|
||||
|
||||
Gets the actual maximum value of the specified `field' of the current
|
||||
Calendar instance by calling Calendar.getActualMaximum(field). The
|
||||
value is assigned to $result.
|
||||
|
||||
GET FIRSTDAYOFWEEK
|
||||
|
||||
Gets the first day of week value of the current Calendar instance by
|
||||
calling Calendar.getFirstDayOfWeek(). The value is assigned to
|
||||
$result.
|
||||
|
||||
GET MINIMALDAYSINFIRSTWEEK
|
||||
|
||||
Gets the minimal days in first week value of the current Calendar
|
||||
instance by calling Calendar.getMinimalDaysInFirstWeek(). The value is
|
||||
assigned to $result.
|
||||
|
||||
ADD field amount
|
||||
|
||||
Adds `amount' to the specified `field' of the current Calendar
|
||||
instance by calling Calendar.add(field, amount).
|
||||
|
||||
ROLL field amount
|
||||
|
||||
Rolls `amount' of the specified `field' of the current Calendar
|
||||
instance by calling Calendar.roll(field, amount).
|
||||
|
||||
SET MILLIS value
|
||||
|
||||
Sets the millisecond value of the current Calendar instance to `value'
|
||||
by calling Calendar.setTimeInMillis(value).
|
||||
|
||||
SET field value
|
||||
|
||||
Sets the `field' value of the current Calendar instance to `value' by
|
||||
calling Calendar.set(field, value).
|
||||
|
||||
SET DATE era year month dayOfMonth
|
||||
|
||||
Sets the date of the current Calendar instance to the date specified
|
||||
by `era', `year', `month' and `dayOfMonth' by calling
|
||||
Calendar.set(ERA, era) and Calendar.set(year, month,
|
||||
dayOfMonth). Please note that `month' follows the Calendar convention
|
||||
and is 0-based. (e.g., JANUARY is 0)
|
||||
|
||||
SET DATE year month dayOfMonth
|
||||
|
||||
Sets the date of the current Calendar instance to the date specified
|
||||
by `year', `month' and `dayOfMonth' by calling
|
||||
Calendar.set(year, month, dayOfMont). Please note that `month'
|
||||
follows the Calendar convention and is 0-based. (e.g., JANUARY is 0)
|
||||
|
||||
SET DATETIME year month dayOfMonth hourOfDay minute second
|
||||
|
||||
Sets the date and time of the current Calendar instance to the date
|
||||
and time specified by `year', `month', `dayOfMonth', `hourOfDay',
|
||||
`minute', and `second' by calling Calendar.set(year, month,
|
||||
dayOfMonth, hourOfDay, minute, second). Please note that `hourOfDay'
|
||||
is the 24-hour clock.
|
||||
|
||||
SET TIMEOFDAY hourOfDay minute second millisecond
|
||||
|
||||
Sets the date and time of the current Calendar instance to the date
|
||||
and time specified by `year', `month', `dayOfMonth', `hourOfDay',
|
||||
`minute', and `second' by calling Calendar.set(HOUR_OF_DAY,
|
||||
hourOfDay), Calendar.set(MINUTE, minute), and Calendar.set(SECOND,
|
||||
second).
|
||||
|
||||
SET FIRSTDAYOFWEEK value
|
||||
|
||||
Sets the first day of week value of the current Calendar instance to
|
||||
`value' by calling Calendar.setFirstDayOfWeek(value).
|
||||
|
||||
SET MINIMALDAYSINFIRSTWEEK value
|
||||
|
||||
Sets the minimal days in the first week value of the current Calendar
|
||||
instance to `value' by calling Calendar.setMinimalDaysInFirstWeek(value).
|
||||
|
||||
SET LENIENT
|
||||
|
||||
Sets the lenient mode in the current Calendar instance by calling
|
||||
Calendar.setLenient(true).
|
||||
|
||||
SET NON-LENIENT
|
||||
|
||||
Sets the non-lenient mode in the current Calendar instance by calling
|
||||
Calendar.setLenient(false).
|
||||
|
||||
CHECK MILLIS value
|
||||
|
||||
Checks if the specified `value' is the same as the millisecond value
|
||||
of the current Calendar instance given by calling
|
||||
Calendar.getTimeInMillis(). If the values are different, an exception
|
||||
is thrown.
|
||||
|
||||
CHECK DATE era year month dayOfMonth
|
||||
|
||||
Checks if the date specified by `era', `year', `month' and
|
||||
`dayOfMonth' is the same date of the current Calendar instance. The
|
||||
calendar date is given by calling Calendar.get(ERA),
|
||||
Calendar.get(YEAR), Calendar.get(MONTH), and
|
||||
Calendar.get(DAY_OF_MONTH). If the dates are different, an exception
|
||||
is thrown.
|
||||
|
||||
CHECK DATE year month dayOfMonth
|
||||
|
||||
Checks if the date specified by `year', `month' and `dayOfMonth' is
|
||||
the same date of the current Calendar instance. The calendar date is
|
||||
given by calling Calendar.get(YEAR), Calendar.get(MONTH), and
|
||||
Calendar.get(DAY_OF_MONTH). If the dates are different, an exception
|
||||
is thrown.
|
||||
|
||||
CHECK DATETIME year month dayOfMonth hourOfDay minute second
|
||||
|
||||
Checks if the date and time specified by `year', `month',
|
||||
`dayOfMonth', `hourOfDay', `minute', and `second' are the same ones of
|
||||
the current Calendar instance. The calendar date and time are given by
|
||||
calling Calendar.get(YEAR), Calendar.get(MONTH),
|
||||
Calendar.get(DAY_OF_MONTH), Calendar.get(HOUR_OF_DAY),
|
||||
Calendar.get(MINUTE) and Calendar.get(SECOND). If the dates or times
|
||||
are different, an exception is thrown.
|
||||
|
||||
CHECK DATETIME year month dayOfMonth hourOfDay minute second millisecond
|
||||
|
||||
Checks if the date and time specified by `year', `month',
|
||||
`dayOfMonth', `hourOfDay', `minute', `second' and `millisecond' are
|
||||
the same ones of the current Calendar instance. The calendar date and
|
||||
time are given by calling Calendar.get(YEAR), Calendar.get(MONTH),
|
||||
Calendar.get(DAY_OF_MONTH), Calendar.get(HOUR_OF_DAY),
|
||||
Calendar.get(MINUTE), Calendar.get(SECOND) and
|
||||
Calendar.get(MILLISECOND). If the dates or times are different, an
|
||||
exception is thrown.
|
||||
|
||||
CHECK TIMEOFDAY hourOfDay minute second millisecond
|
||||
|
||||
Checks if the time of day specified by `hourOfDay', `minute', `second'
|
||||
and `millisecond' are the same ones of the current Calendar
|
||||
instance. The calendar date and time are given by calling
|
||||
Calendar.get(HOUR_OF_DAY), Calendar.get(MINUTE), Calendar.get(SECOND)
|
||||
and Calendar.get(MILLISECOND). If the times are different, an
|
||||
exception is thrown.
|
||||
|
||||
CHECK field value
|
||||
|
||||
Checks if the value of the given `field' of the current Calendar
|
||||
instance is equal to the given `value'. If it doesn't, an exception is
|
||||
thrown.
|
||||
|
||||
CHECK MIN field value
|
||||
|
||||
Checks if the minimum value of the specified `field' of the current
|
||||
Calendar instance is equal to the specified `value'. If not, an
|
||||
exception is thrown.
|
||||
|
||||
CHECK GREATESTMIN field value
|
||||
|
||||
Checks if the greatest minimum value of the specified `field' of the
|
||||
current Calendar instance is equal to the specified `value'. If not,
|
||||
an exception is thrown.
|
||||
|
||||
CHECK ACTUALMIN field value
|
||||
|
||||
Checks if the actual minimum value of the specified `field' of the
|
||||
current Calendar instance is equal to the specified `value'. If not,
|
||||
an exception is thrown.
|
||||
|
||||
CHECK MAX field value
|
||||
|
||||
Checks if the maximum value of the specified `field' of the current
|
||||
Calendar instance is equal to the specified `value'. If not, an
|
||||
exception is thrown.
|
||||
|
||||
CHECK LEASTMAX field value
|
||||
|
||||
Checks if the least maximum value of the specified `field' of the
|
||||
current Calendar instance is equal to the specified `value'. If not,
|
||||
an exception is thrown.
|
||||
|
||||
CHECK ACTUALMAX field value
|
||||
|
||||
Checks if the actual maximum value of the specified `field' of the
|
||||
current Calendar instance is equal to the specified `value'. If not,
|
||||
an exception is thrown.
|
||||
|
||||
EXCEPTION exceptionname
|
||||
|
||||
Checks if the previous command threw the specified exception by
|
||||
`exceptionname'. For example, the following tests invalid date
|
||||
detection in non-lenient.
|
||||
|
||||
set non-lenient
|
||||
set date 2005 Feb 29 # 2005 isn't a leap year.
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
PRINT variable
|
||||
|
||||
Prints the value of `variable'.
|
||||
|
||||
PRINT INSTANCE [calendarname]
|
||||
|
||||
Prints the Calendar.toString() value of the current Calendar instance
|
||||
or the instance given by `calendarname'.
|
||||
|
||||
PRINT field
|
||||
|
||||
Prints the value of the specified `field' of the current Calendar
|
||||
instance. The value is obtained by calling Calendar.get(field).
|
||||
|
||||
PRINT MILLIS
|
||||
|
||||
Prints the millisecond value of the current Calendar instance. The
|
||||
value is obtained by calling Calendar.getTimeInMillis().
|
||||
|
||||
PRINT MIN field
|
||||
|
||||
Prints the minimum value of the specified field by `field' of the
|
||||
current Calendar instance. The value is obtained by calling
|
||||
Calendar.getMinimum(field).
|
||||
|
||||
PRINT GREATESTMIN field
|
||||
|
||||
Prints the greatest minimum value of the specified field by `field' of
|
||||
the current Calendar instance. The value is obtained by calling
|
||||
Calendar.getGreatestMinimum(field).
|
||||
|
||||
PRINT ACTUALMIN field
|
||||
|
||||
Prints the actual minimum value of the specified field by `field' of
|
||||
the current Calendar instance by calling
|
||||
Calendar.getActualMinimum(field).
|
||||
|
||||
PRINT MAX field
|
||||
|
||||
Prints the maximum value of the specified field by `field' of the
|
||||
current Calendar instance. The value is obtained by calling
|
||||
Calendar.getMaximum(field).
|
||||
|
||||
PRINT LEASTMAX field
|
||||
|
||||
Prints the least maximum value of the specified field by `field' of
|
||||
the current Calendar instance. The value is obtained by calling
|
||||
Calendar.getLeastMaximum(field).
|
||||
|
||||
PRINT ACTUALMAX field
|
||||
|
||||
Prints the actual maximum value of the specified field by `field' of
|
||||
the current Calendar instance. The value is obtained by calling
|
||||
Calendar.getActualMaximum(field).
|
||||
|
||||
PRINT DATE
|
||||
|
||||
Prints the date of the current Calendar instance in format
|
||||
"[ERA] yyyy-MM-dd". The date is obtained by calling Calendar.get(ERA),
|
||||
Calendar.get(YEAR), Calendar.get(MONTH), and
|
||||
Calendar.get(DAY_OF_MONTH).
|
||||
|
||||
PRINT DATETIME
|
||||
|
||||
Prints the date and time of the current Calendar instance in an ISO
|
||||
8601-style format "[ERA] yyyy-MM-ddTHH:mm:ss.SSS{Z|{+|-}hhmm}". The
|
||||
date and time are obtained by calling Calendar.get(ERA),
|
||||
Calendar.get(YEAR), Calendar.get(MONTH), Calendar.get(DAY_OF_MONTH),
|
||||
Calendar.get(HOUR_OF_DAY), Calendar.get(MINUTE), Calendar.get(SECOND),
|
||||
Calendar.get(MILLISECOND), Calendar.get(ZONE_OFFSET), and
|
||||
Calendar.get(DST_OFFSET).
|
||||
|
||||
PRINT TIMEZONE
|
||||
|
||||
Prints the toString() value of the current TimeZone.
|
||||
|
||||
PRINT LOCALE
|
||||
|
||||
Prints the toString() value of the current Locale.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The usage of the test script system at this directory is:
|
||||
|
||||
$ javac -d classes --add-exports java.base/sun.util=ALL-UNNAMED --add-exports java.base/sun.util.calendar=ALL-UNNAMED *.java
|
||||
$ java -cp classes CalendarTestEngine scriptfiles...
|
||||
|
||||
A script file has suffix ".cts" by convention. If multiple script files
|
||||
are specified. Those files are sequentially executed as if those are a
|
||||
single test script. For example, if we have the following script files:
|
||||
|
||||
file1.cts:
|
||||
locale ja JP JP
|
||||
timezone Asia/Tokyo
|
||||
file2.cts:
|
||||
new instance jcal
|
||||
new gregorian gcal
|
||||
test example
|
||||
use jcal
|
||||
print datetime
|
||||
get millis
|
||||
print $result
|
||||
use gcal
|
||||
set millis $result
|
||||
print datetime
|
||||
|
||||
running CalendarTestEngine with those files will produce:
|
||||
|
||||
$ java -cp classes CalendarTestEngine file1.cts file2.cts
|
||||
Starting file1.cts...
|
||||
Completed file1.cts
|
||||
Starting file2.cts...
|
||||
Test #1: example
|
||||
file2.cts:5: Heisei 0017-03-18T20:00:25.402+0900
|
||||
file2.cts:7: $result=1111143625402
|
||||
file2.cts:10: 2005-03-18T20:00:25.402+0900
|
||||
Completed file2.cts
|
||||
|
||||
[end of README]
|
||||
53
test/jdk/java/util/Calendar/CalendarTestScripts/Result.java
Normal file
53
test/jdk/java/util/Calendar/CalendarTestScripts/Result.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
public class Result extends Variable {
|
||||
private Exception e;
|
||||
private int lineno;
|
||||
|
||||
public Result() {
|
||||
super("$result", 0);
|
||||
put("$result", this);
|
||||
}
|
||||
|
||||
public void setLineno(int lineno) {
|
||||
this.lineno = lineno;
|
||||
}
|
||||
|
||||
public int getLineno() {
|
||||
return lineno;
|
||||
}
|
||||
|
||||
public void setException(Exception e) {
|
||||
if (this.e != null) {
|
||||
throw new RuntimeException("existing exception: " + e, e);
|
||||
}
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
Exception e = this.e;
|
||||
this.e = null;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
327
test/jdk/java/util/Calendar/CalendarTestScripts/Symbol.java
Normal file
327
test/jdk/java/util/Calendar/CalendarTestScripts/Symbol.java
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.GregorianCalendar.*;
|
||||
|
||||
public class Symbol {
|
||||
|
||||
private static Map<String, Symbol> symbols;
|
||||
|
||||
String name;
|
||||
Type type;
|
||||
int value;
|
||||
boolean isArithmetic;
|
||||
|
||||
private Symbol(Type type, Integer value) {
|
||||
this(type, value, false);
|
||||
}
|
||||
|
||||
private Symbol(Type type) {
|
||||
this(type, null, false);
|
||||
}
|
||||
|
||||
private Symbol(Type type, boolean isArithmetic) {
|
||||
this(type, null, isArithmetic);
|
||||
}
|
||||
|
||||
private Symbol(Type type, Integer value, boolean isArithmetic) {
|
||||
this.name = type.toString().toLowerCase(Locale.ROOT);
|
||||
this.type = type;
|
||||
if (value != null)
|
||||
this.value = value;
|
||||
this.isArithmetic = isArithmetic;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type.name();
|
||||
}
|
||||
|
||||
public boolean isArithmetic() {
|
||||
return isArithmetic;
|
||||
}
|
||||
|
||||
public static Symbol get(String s) {
|
||||
return symbols.get(s);
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
// Directives
|
||||
TEST,
|
||||
// Commands
|
||||
LOCALE, TIMEZONE, NEW, USE, ASSIGN, EVAL,
|
||||
CLEAR, SET, GET, ADD, ROLL, CHECK, PRINT, EXCEPTION,
|
||||
IF,
|
||||
// Operands
|
||||
INSTANCE, GREGORIAN, ALL, MILLIS, DATE, DATETIME, TIMEOFDAY,
|
||||
LENIENT, NONLENIENT,
|
||||
MINIMUM, GREATESTMINIMUM, ACTUALMINIMUM,
|
||||
MAXIMUM, LEASTMAXIMUM, ACTUALMAXIMUM,
|
||||
FIRSTDAYOFWEEK, MINIMALDAYSINFIRSTWEEK,
|
||||
// Arithmetic operators
|
||||
PLUS, MINUS, MULTIPLY, DIVIDE, MOD,
|
||||
// Relational operators
|
||||
GT, GE, EQ, NEQ, LE, LT,
|
||||
// Calendar field indices
|
||||
FIELD,
|
||||
// Day of week
|
||||
DAYOFWEEK,
|
||||
// Month
|
||||
MONTH,
|
||||
// AM/PM
|
||||
AMPM,
|
||||
// Era values
|
||||
ERA;
|
||||
}
|
||||
|
||||
private static final void put(String key, Symbol sym) {
|
||||
Symbol s = symbols.put(key, sym);
|
||||
if (s != null) {
|
||||
throw new RuntimeException("duplicated key: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
symbols = new HashMap<String, Symbol>();
|
||||
Symbol sym;
|
||||
// Directives
|
||||
put("test", new Symbol(Type.TEST));
|
||||
|
||||
// Commands
|
||||
put("locale", new Symbol(Type.LOCALE));
|
||||
sym = new Symbol(Type.TIMEZONE);
|
||||
put("tz", sym);
|
||||
put("timezone", sym);
|
||||
put("new", new Symbol(Type.NEW));
|
||||
put("use", new Symbol(Type.USE));
|
||||
put("assign", new Symbol(Type.ASSIGN));
|
||||
put("eval", new Symbol(Type.EVAL));
|
||||
put("clear", new Symbol(Type.CLEAR));
|
||||
put("set", new Symbol(Type.SET));
|
||||
put("get", new Symbol(Type.GET));
|
||||
put("add", new Symbol(Type.ADD));
|
||||
put("roll", new Symbol(Type.ROLL));
|
||||
put("check", new Symbol(Type.CHECK));
|
||||
put("print", new Symbol(Type.PRINT));
|
||||
put("exception", new Symbol(Type.EXCEPTION));
|
||||
put("throw", get("exception"));
|
||||
put("if", new Symbol(Type.IF));
|
||||
|
||||
// Operands
|
||||
put("instance", new Symbol(Type.INSTANCE));
|
||||
put("gregorian", new Symbol(Type.GREGORIAN));
|
||||
put("all", new Symbol(Type.ALL));
|
||||
put("millis", new Symbol(Type.MILLIS));
|
||||
put("date", new Symbol(Type.DATE));
|
||||
put("datetime", new Symbol(Type.DATETIME));
|
||||
put("timeofday", new Symbol(Type.TIMEOFDAY));
|
||||
put("lenient", new Symbol(Type.LENIENT));
|
||||
sym = new Symbol(Type.NONLENIENT);
|
||||
put("non-lenient", sym);
|
||||
put("nonlenient", sym);
|
||||
put("firstdayofweek", new Symbol(Type.FIRSTDAYOFWEEK));
|
||||
put("minimaldaysinfirstweek", new Symbol(Type.MINIMALDAYSINFIRSTWEEK));
|
||||
|
||||
sym = new Symbol(Type.MINIMUM);
|
||||
put("minimum", sym);
|
||||
put("min", sym);
|
||||
sym = new Symbol(Type.GREATESTMINIMUM);
|
||||
put("greatestminimum", sym);
|
||||
put("greatestmin", sym);
|
||||
sym = new Symbol(Type.ACTUALMINIMUM);
|
||||
put("actualminimum", sym);
|
||||
put("actualmin", sym);
|
||||
sym = new Symbol(Type.MAXIMUM);
|
||||
put("maximum", sym);
|
||||
put("max", sym);
|
||||
sym = new Symbol(Type.LEASTMAXIMUM);
|
||||
put("leastmaximum", sym);
|
||||
put("leastmax", sym);
|
||||
sym = new Symbol(Type.ACTUALMAXIMUM);
|
||||
put("actualmaximum", sym);
|
||||
put("actualmax", sym);
|
||||
|
||||
// Arithmetic operators
|
||||
put("+", new Symbol(Type.PLUS, true));
|
||||
put("-", new Symbol(Type.MINUS, true));
|
||||
put("*", new Symbol(Type.MULTIPLY, true));
|
||||
put("/", new Symbol(Type.DIVIDE, true));
|
||||
put("%", new Symbol(Type.MOD, true));
|
||||
|
||||
// Relational operators
|
||||
put(">", new Symbol(Type.GT, false));
|
||||
put(">=", new Symbol(Type.GE, false));
|
||||
put("==", new Symbol(Type.EQ, false));
|
||||
put("!=", new Symbol(Type.NEQ, false));
|
||||
put("<=", new Symbol(Type.LE, false));
|
||||
put("<", new Symbol(Type.LT, false));
|
||||
|
||||
// Calendar Fields
|
||||
put("era", new Symbol(Type.FIELD, ERA));
|
||||
put("year", new Symbol(Type.FIELD, YEAR));
|
||||
put("month", new Symbol(Type.FIELD, MONTH));
|
||||
sym = new Symbol(Type.FIELD, WEEK_OF_YEAR);
|
||||
put("week_of_year", sym);
|
||||
put("weekofyear", sym);
|
||||
put("woy", sym);
|
||||
sym = new Symbol(Type.FIELD, WEEK_OF_MONTH);
|
||||
put("week_of_month", sym);
|
||||
put("weekofmonth", sym);
|
||||
put("wom", sym);
|
||||
sym = new Symbol(Type.FIELD, DAY_OF_MONTH);
|
||||
put("day_of_month", sym);
|
||||
put("dayofmonth", sym);
|
||||
put("dom", sym);
|
||||
sym = new Symbol(Type.FIELD, DAY_OF_YEAR);
|
||||
put("day_of_year", sym);
|
||||
put("dayofyear", sym);
|
||||
put("doy", sym);
|
||||
|
||||
sym = new Symbol(Type.FIELD, DAY_OF_WEEK);
|
||||
put("day_of_week", sym);
|
||||
put("dayofweek", sym);
|
||||
put("dow", sym);
|
||||
sym = new Symbol(Type.FIELD, DAY_OF_WEEK_IN_MONTH);
|
||||
put("day_of_week_in_month", sym);
|
||||
put("dayofweekinmonth", sym);
|
||||
put("dowim", sym);
|
||||
sym = new Symbol(Type.FIELD, AM_PM);
|
||||
put("am_pm", sym);
|
||||
put("ampm", sym);
|
||||
put("hour", new Symbol(Type.FIELD, HOUR));
|
||||
sym = new Symbol(Type.FIELD, HOUR_OF_DAY);
|
||||
put("hour_of_day", sym);
|
||||
put("hourofday", sym);
|
||||
put("hod", sym);
|
||||
put("minute", new Symbol(Type.FIELD, MINUTE));
|
||||
put("second", new Symbol(Type.FIELD, SECOND));
|
||||
put("millisecond", new Symbol(Type.FIELD, MILLISECOND));
|
||||
sym = new Symbol(Type.FIELD, ZONE_OFFSET);
|
||||
put("zone_offset", sym);
|
||||
put("zoneoffset", sym);
|
||||
put("zo", sym);
|
||||
sym = new Symbol(Type.FIELD, DST_OFFSET);
|
||||
put("dst_offset", sym);
|
||||
put("dstoffset", sym);
|
||||
put("do", sym);
|
||||
|
||||
// Day of week
|
||||
sym = new Symbol(Type.DAYOFWEEK, SUNDAY);
|
||||
put("sunday", sym);
|
||||
put("sun", sym);
|
||||
sym = new Symbol(Type.DAYOFWEEK, MONDAY);
|
||||
put("monday", sym);
|
||||
put("mon", sym);
|
||||
sym = new Symbol(Type.DAYOFWEEK, TUESDAY);
|
||||
put("tuesday", sym);
|
||||
put("tue", sym);
|
||||
sym = new Symbol(Type.DAYOFWEEK, WEDNESDAY);
|
||||
put("wednesday", sym);
|
||||
put("wed", sym);
|
||||
sym = new Symbol(Type.DAYOFWEEK, THURSDAY);
|
||||
put("thursday", sym);
|
||||
put("thu", sym);
|
||||
sym = new Symbol(Type.DAYOFWEEK, FRIDAY);
|
||||
put("friday", sym);
|
||||
put("fri", sym);
|
||||
sym = new Symbol(Type.DAYOFWEEK, SATURDAY);
|
||||
put("saturday", sym);
|
||||
put("sat", sym);
|
||||
|
||||
|
||||
// Month
|
||||
sym = new Symbol(Type.MONTH, JANUARY);
|
||||
put("january", sym);
|
||||
put("jan", sym);
|
||||
sym = new Symbol(Type.MONTH, FEBRUARY);
|
||||
put("february", sym);
|
||||
put("feb", sym);
|
||||
sym = new Symbol(Type.MONTH, MARCH);
|
||||
put("march", sym);
|
||||
put("mar", sym);
|
||||
sym = new Symbol(Type.MONTH, APRIL);
|
||||
put("april", sym);
|
||||
put("apr", sym);
|
||||
sym = new Symbol(Type.MONTH, MAY);
|
||||
put("may", sym);
|
||||
sym = new Symbol(Type.MONTH, JUNE);
|
||||
put("june", sym);
|
||||
put("jun", sym);
|
||||
sym = new Symbol(Type.MONTH, JULY);
|
||||
put("july", sym);
|
||||
put("jul", sym);
|
||||
sym = new Symbol(Type.MONTH, AUGUST);
|
||||
put("august", sym);
|
||||
put("aug", sym);
|
||||
sym = new Symbol(Type.MONTH, SEPTEMBER);
|
||||
put("september", sym);
|
||||
put("sep", sym);
|
||||
sym = new Symbol(Type.MONTH, OCTOBER);
|
||||
put("octobwe", sym);
|
||||
put("oct", sym);
|
||||
sym = new Symbol(Type.MONTH, NOVEMBER);
|
||||
put("november", sym);
|
||||
put("nov", sym);
|
||||
sym = new Symbol(Type.MONTH, DECEMBER);
|
||||
put("december", sym);
|
||||
put("dec", sym);
|
||||
sym = new Symbol(Type.MONTH, UNDECIMBER);
|
||||
put("undecimber", sym);
|
||||
|
||||
// AM/PM
|
||||
put("am", new Symbol(Type.AMPM, AM));
|
||||
put("pm", new Symbol(Type.AMPM, PM));
|
||||
|
||||
// Eras
|
||||
|
||||
// Julian eras
|
||||
sym = new Symbol(Type.ERA, BC);
|
||||
put("bc", sym);
|
||||
put("bce", sym);
|
||||
sym = new Symbol(Type.ERA, AD);
|
||||
put("ad", sym);
|
||||
put("ce", sym);
|
||||
|
||||
// Buddhist era
|
||||
put("be", new Symbol(Type.ERA, 1));
|
||||
|
||||
// Japanese imperial eras
|
||||
sym = new Symbol(Type.ERA, 0);
|
||||
put("before_meiji", sym);
|
||||
put("beforemeiji", sym);
|
||||
put("meiji", new Symbol(Type.ERA, 1));
|
||||
put("taisho", new Symbol(Type.ERA, 2));
|
||||
put("showa", new Symbol(Type.ERA, 3));
|
||||
put("heisei", new Symbol(Type.ERA, 4));
|
||||
put("reiwa", new Symbol(Type.ERA, 5));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class Variable {
|
||||
private static Map<String,Variable> vars = new HashMap<String,Variable>();
|
||||
|
||||
private String name;
|
||||
private long value;
|
||||
|
||||
Variable(String name, long value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int intValue() {
|
||||
if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
|
||||
throw new RuntimeException("Overflow/Underflow: " + value);
|
||||
}
|
||||
return (int) value;
|
||||
}
|
||||
|
||||
public long longValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(int v) { value = v; }
|
||||
public void setValue(long v) { value = v; }
|
||||
|
||||
// static methods
|
||||
|
||||
public static Variable newVar(String name, long value) {
|
||||
if (name.charAt(0) != '$') {
|
||||
throw new RuntimeException("wrong var name: " + name);
|
||||
}
|
||||
String s = name.toLowerCase(Locale.ROOT);
|
||||
Variable v = new Variable(name, value);
|
||||
put(name, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
static void put(String s, Variable var) {
|
||||
vars.put(s, var);
|
||||
}
|
||||
|
||||
public static Variable get(String name) {
|
||||
return vars.get(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
|
||||
locale ja JP JP
|
||||
new instance jcal
|
||||
new gregorian gcal
|
||||
|
||||
test Default dates
|
||||
# Default for all unset fields
|
||||
# 1970-01-01T00:00:00.000 local time (Gregorian)
|
||||
# which is equivalent to Showa 45.
|
||||
use gcal
|
||||
clear all
|
||||
get millis
|
||||
# get the default milliseconds from the Epoch. It's time zone
|
||||
# dependent.
|
||||
assign $result $defmillis
|
||||
use jcal
|
||||
clear all
|
||||
get millis
|
||||
eval $result == $defmillis
|
||||
check era Showa
|
||||
check datetime 45 Jan 1 0 0 0
|
||||
check millisecond 0
|
||||
|
||||
# If each era is set, then January 1 of each Gan-nen is the
|
||||
# default.
|
||||
clear all
|
||||
set era BeforeMeiji
|
||||
check era BeforeMeiji
|
||||
check datetime 1 Jan 1 0 0 0
|
||||
check millisecond 0
|
||||
|
||||
clear all
|
||||
set era Meiji
|
||||
check era Meiji
|
||||
check datetime 1 Jan 1 0 0 0
|
||||
check millisecond 0
|
||||
|
||||
clear all
|
||||
set era Taisho
|
||||
check era Meiji
|
||||
check datetime 45 Jan 1 0 0 0
|
||||
check millisecond 0
|
||||
|
||||
clear all
|
||||
set era Showa
|
||||
check era Taisho
|
||||
check datetime 15 Jan 1 0 0 0
|
||||
check millisecond 0
|
||||
|
||||
clear all
|
||||
set era Heisei
|
||||
check era Showa
|
||||
check datetime 64 Jan 1 0 0 0
|
||||
check millisecond 0
|
||||
|
||||
clear all
|
||||
set era Reiwa
|
||||
check era Heisei
|
||||
check datetime 31 Jan 1 0 0 0
|
||||
check millisecond 0
|
||||
|
||||
#
|
||||
# Field resolution tests
|
||||
#
|
||||
clear all
|
||||
get firstdayofweek
|
||||
# The test cases below assume that the first day of week is
|
||||
# Sunday. So we should make sure it is.
|
||||
eval $result == Sun
|
||||
assign $result $fdow
|
||||
|
||||
test Field resolution: YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
|
||||
set era Showa
|
||||
set year 64
|
||||
set week_of_month 1
|
||||
check day_of_week $fdow
|
||||
check date 64 Jan 1
|
||||
|
||||
clear all
|
||||
set era Showa
|
||||
set year 64
|
||||
set week_of_month 1
|
||||
set day_of_week Thu
|
||||
check era Showa
|
||||
check day_of_week Thu
|
||||
check date 64 Jan 5
|
||||
|
||||
clear all
|
||||
# Heise 1 January and Showa 64 January are the same month. Its
|
||||
# first week should be the same week. (January is the default
|
||||
# month.)
|
||||
set era Heisei
|
||||
set year 1
|
||||
set week_of_month 1
|
||||
check day_of_week $fdow
|
||||
check era Showa
|
||||
check date 64 Jan 1
|
||||
|
||||
# Test aggregation
|
||||
clear all
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_month 1
|
||||
set day_of_week Tue
|
||||
check date Heisei 17 Mar 1
|
||||
|
||||
clear all
|
||||
set week_of_month 1
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_week Tue
|
||||
check date Heisei 17 Mar 1
|
||||
|
||||
clear all
|
||||
set day_of_week Tue
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_month 1
|
||||
check date Heisei 17 Mar 1
|
||||
|
||||
clear all
|
||||
set day_of_week Tue
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_year 10
|
||||
set week_of_month 1
|
||||
check date Heisei 17 Mar 1
|
||||
|
||||
clear all
|
||||
set day_of_week Tue
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_year 300
|
||||
set week_of_month 1
|
||||
check date Heisei 17 Mar 1
|
||||
|
||||
test Field resolution: YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
|
||||
clear all
|
||||
set era Meiji
|
||||
set year 45
|
||||
set month Jul
|
||||
set day_of_week_in_month 5
|
||||
set day_of_week Mon
|
||||
check date Meiji 45 Jul 29
|
||||
|
||||
clear all
|
||||
set era Meiji
|
||||
set year 45
|
||||
set month Jul
|
||||
set day_of_week_in_month 4
|
||||
check date Meiji 45 Jul 28
|
||||
|
||||
clear all
|
||||
set era Meiji
|
||||
set year 45
|
||||
set month Jul
|
||||
set day_of_week_in_month 5
|
||||
set day_of_week Tue
|
||||
check date Taisho 1 Jul 30
|
||||
|
||||
clear all
|
||||
set era Taisho
|
||||
set year 1
|
||||
set month Jul
|
||||
set day_of_week_in_month 1
|
||||
set day_of_week Tue
|
||||
check date Meiji 45 Jul 2
|
||||
|
||||
# Test aggregation
|
||||
clear all
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_week_in_month 1
|
||||
set day_of_week Wed
|
||||
check date Heisei 17 Mar 2
|
||||
|
||||
clear all
|
||||
set day_of_week_in_month 1
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_week Wed
|
||||
check date Heisei 17 Mar 2
|
||||
|
||||
clear all
|
||||
set day_of_week Wed
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_week_in_month 1
|
||||
check date Heisei 17 Mar 2
|
||||
|
||||
clear all
|
||||
set day_of_week Wed
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_month 4
|
||||
set day_of_week_in_month 1
|
||||
check date Heisei 17 Mar 2
|
||||
|
||||
clear all
|
||||
set day_of_week Wed
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_year 365
|
||||
set day_of_week_in_month 1
|
||||
check date Heisei 17 Mar 2
|
||||
|
||||
clear all
|
||||
set day_of_week Wed
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_year 50
|
||||
set day_of_week_in_month 1
|
||||
check date Heisei 17 Mar 2
|
||||
|
||||
test Field resolution: YEAR + DAY_OF_YEAR
|
||||
clear all
|
||||
set era Showa
|
||||
set year 64
|
||||
set day_of_year 7
|
||||
check date Showa 64 Jan 7
|
||||
|
||||
clear all
|
||||
set era Showa
|
||||
set year 64
|
||||
set day_of_year 10
|
||||
check date Heisei 1 Jan 10
|
||||
|
||||
clear all
|
||||
set era Showa
|
||||
set year 64
|
||||
check date Showa 64 Jan 1
|
||||
check day_of_year 1
|
||||
|
||||
clear all
|
||||
set era Heisei
|
||||
set year 1
|
||||
set day_of_year 10
|
||||
check date Heisei 1 Jan 17
|
||||
|
||||
clear all
|
||||
set era Heisei
|
||||
set year 1
|
||||
set day_of_year 1
|
||||
check date Heisei 1 Jan 8
|
||||
|
||||
clear all
|
||||
set era Heisei
|
||||
set year 1
|
||||
set day_of_year -1
|
||||
check date Showa 64 Jan 6
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_year 31
|
||||
check date Heisei 17 Jan 31
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_year 50
|
||||
set day_of_week Wed
|
||||
set day_of_year 31
|
||||
check date Heisei 17 Jan 31
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_month 5
|
||||
set day_of_week Wed
|
||||
set day_of_year 31
|
||||
check date Heisei 17 Jan 31
|
||||
|
||||
test Field resolution: YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
|
||||
clear all
|
||||
set era Showa
|
||||
set year 64
|
||||
set week_of_year 1
|
||||
check day_of_week $fdow
|
||||
check date 64 Jan 1
|
||||
|
||||
clear all
|
||||
set era Showa
|
||||
set year 64
|
||||
set week_of_year 1
|
||||
set day_of_week Wed
|
||||
check date Showa 64 Jan 4
|
||||
|
||||
clear all
|
||||
set era Heisei
|
||||
set year 1
|
||||
set week_of_year 1
|
||||
check day_of_week $fdow
|
||||
check date 1 Jan 8
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_year 2
|
||||
set day_of_week Thu
|
||||
check date Heisei 17 Jan 6
|
||||
|
||||
clear all
|
||||
set week_of_year 2
|
||||
set date Heisei 17 Mar 16
|
||||
set day_of_week Thu
|
||||
check date Heisei 17 Jan 6
|
||||
|
||||
clear all
|
||||
set day_of_week Thu
|
||||
set date Heisei 17 Mar 16
|
||||
set week_of_year 2
|
||||
check date Heisei 17 Jan 6
|
||||
|
||||
test zone offsets
|
||||
# Tests here depend on the GMT offset.
|
||||
timezone GMT+09:00
|
||||
new instance cal0900
|
||||
use cal0900
|
||||
clear all
|
||||
set date Heisei 17 Mar 12
|
||||
get millis
|
||||
assign $result $H17Mar12
|
||||
clear all
|
||||
set date Heisei 17 Mar 12
|
||||
set zone_offset 0
|
||||
get millis
|
||||
eval $result - 32400000 # -9 hours
|
||||
eval $result == $H17Mar12
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Mar 12
|
||||
set zone_offset 28800000 # 8 hours
|
||||
set dst_offset 3600000 # 1 hour
|
||||
get millis
|
||||
eval $result == $H17Mar12
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Mar 12
|
||||
set zone_offset 18000000 # 5 hours
|
||||
set dst_offset 14400000 # 4 hours
|
||||
get millis
|
||||
eval $result == $H17Mar12
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
#
|
||||
# %i%
|
||||
#
|
||||
|
||||
# The test cases in this file assume the first day of week is Sunday
|
||||
# and the minimal days in the first week is 1.
|
||||
|
||||
locale ja JP JP
|
||||
new instance jcal
|
||||
|
||||
timezone Asia/Tokyo
|
||||
new instance tokyocal
|
||||
|
||||
set non-lenient
|
||||
|
||||
test add ERA
|
||||
use jcal
|
||||
clear all
|
||||
set date Reiwa 17 Mar 8
|
||||
add era 10
|
||||
# as of Reiwa 17 March 8
|
||||
check era Reiwa
|
||||
add era -100
|
||||
check era BeforeMeiji
|
||||
|
||||
test add HOUR_OF_DAY
|
||||
use jcal
|
||||
clear all
|
||||
set era Heisei
|
||||
set datetime 1 Jan 8 23 59 59
|
||||
add hour_of_day 1
|
||||
check datetime 1 Jan 9 0 59 59
|
||||
check ampm AM
|
||||
check hour 0
|
||||
add hour_of_day -1
|
||||
check datetime 1 Jan 8 23 59 59
|
||||
add hour_of_day 24
|
||||
check datetime 1 Jan 9 23 59 59
|
||||
add hour_of_day -24
|
||||
check datetime 1 Jan 8 23 59 59
|
||||
|
||||
test add HOUR
|
||||
use jcal
|
||||
clear all
|
||||
set era Showa
|
||||
set datetime 64 Jan 7 11 59 59
|
||||
check era Showa
|
||||
check hour 11
|
||||
check ampm AM
|
||||
add hour 1
|
||||
check hour 0
|
||||
check ampm PM
|
||||
check datetime 64 Jan 7 12 59 59
|
||||
add hour -1
|
||||
check datetime 64 Jan 7 11 59 59
|
||||
add hour 240
|
||||
check era Heisei
|
||||
check datetime 1 Jan 17 11 59 59
|
||||
add hour -240
|
||||
check era Showa
|
||||
check datetime 64 Jan 7 11 59 59
|
||||
|
||||
clear all
|
||||
set era Showa
|
||||
set datetime 64 Jan 7 23 59 59
|
||||
check era Showa
|
||||
check hour 11
|
||||
check ampm PM
|
||||
add hour 1
|
||||
check hour 0
|
||||
check ampm AM
|
||||
check era Heisei
|
||||
check datetime 1 Jan 8 0 59 59
|
||||
add hour -1
|
||||
check datetime 64 Jan 7 23 59 59
|
||||
add hour 240
|
||||
check era Heisei
|
||||
check datetime 1 Jan 17 23 59 59
|
||||
add hour -240
|
||||
check era Showa
|
||||
check datetime 64 Jan 7 23 59 59
|
||||
|
||||
clear all
|
||||
set era Heisei
|
||||
set datetime 1 Jan 8 23 59 59
|
||||
check date Heisei 1 Jan 8
|
||||
check hour 11
|
||||
check ampm PM
|
||||
add hour 1
|
||||
check hour 0
|
||||
check ampm AM
|
||||
check era Heisei
|
||||
check datetime 1 Jan 9 0 59 59
|
||||
add hour -1
|
||||
check datetime 1 Jan 8 23 59 59
|
||||
add hour 240
|
||||
check datetime 1 Jan 18 23 59 59
|
||||
add hour -240
|
||||
check datetime 1 Jan 8 23 59 59
|
||||
|
||||
test add YEAR
|
||||
use jcal
|
||||
clear all
|
||||
# check if pinDayOfMonth works correctly.
|
||||
# Heisei 12 (Y2K) is a leap year.
|
||||
set date Heisei 12 Feb 29
|
||||
add year 5
|
||||
check date Heisei 17 Feb 28
|
||||
add year -5
|
||||
check date Heisei 12 Feb 28 # not 29!
|
||||
|
||||
clear all
|
||||
set date BeforeMeiji 1867 Jan 1
|
||||
add year 1
|
||||
check date Meiji 1 Jan 1
|
||||
add year -1
|
||||
check date BeforeMeiji 1867 Jan 1
|
||||
|
||||
clear all
|
||||
set date Meiji 45 Jul 29
|
||||
add year 1
|
||||
check date Taisho 2 Jul 29
|
||||
add year -1
|
||||
check date Meiji 45 Jul 29
|
||||
|
||||
clear all
|
||||
set date Meiji 44 Jul 30
|
||||
add year 1
|
||||
check date Taisho 1 Jul 30
|
||||
add year -1
|
||||
check date Meiji 44 Jul 30
|
||||
|
||||
clear all
|
||||
set date Taisho 15 Aug 1
|
||||
add year 1
|
||||
check date Showa 2 Aug 1
|
||||
add year -1
|
||||
check date Taisho 15 Aug 1
|
||||
|
||||
clear all
|
||||
set date Taisho 14 Dec 31
|
||||
add year 1
|
||||
check date Showa 1 Dec 31
|
||||
add year -1
|
||||
check date Taisho 14 Dec 31
|
||||
|
||||
clear all
|
||||
set date Showa 63 Feb 1
|
||||
add year 1
|
||||
check date Heisei 1 Feb 1
|
||||
add year -1
|
||||
check date Showa 63 Feb 1
|
||||
|
||||
set date Showa 63 Dec 30
|
||||
add year 1
|
||||
check date Heisei 1 Dec 30
|
||||
add year -1
|
||||
check date Showa 63 Dec 30
|
||||
|
||||
set date Showa 64 Jan 7
|
||||
add year 1
|
||||
check date Heisei 2 Jan 7
|
||||
add year -1
|
||||
check date Showa 64 Jan 7
|
||||
|
||||
set date Heisei 2 Jan 7
|
||||
add year -1
|
||||
check date Showa 64 Jan 7
|
||||
add year 1
|
||||
check date Heisei 2 Jan 7
|
||||
|
||||
test add MONTH
|
||||
clear all
|
||||
# Check pinDayOfMonth works correctly.
|
||||
# Heisei 12 is a leap year.
|
||||
set date Heisei 12 Jan 31
|
||||
add month 1
|
||||
check date Heisei 12 Feb 29
|
||||
add month -1
|
||||
check date Heisei 12 Jan 29
|
||||
|
||||
# Another leap year
|
||||
set date Showa 63 Jan 31
|
||||
add month 1
|
||||
check date Showa 63 Feb 29
|
||||
add month -1
|
||||
check date Showa 63 Jan 29
|
||||
|
||||
# Non leap year
|
||||
set date Heisei 15 Jan 31
|
||||
add month 1
|
||||
check date Heisei 15 Feb 28
|
||||
add month -1
|
||||
check date Heisei 15 Jan 28
|
||||
|
||||
set date Heisei 15 Mar 31
|
||||
add month 1
|
||||
check date Heisei 15 Apr 30
|
||||
add month -1
|
||||
check date Heisei 15 Mar 30
|
||||
|
||||
set date Heisei 15 May 31
|
||||
add month 1
|
||||
check date Heisei 15 Jun 30
|
||||
add month -1
|
||||
check date Heisei 15 May 30
|
||||
|
||||
set date Heisei 15 Aug 31
|
||||
add month 1
|
||||
check date Heisei 15 Sep 30
|
||||
add month -1
|
||||
check date Heisei 15 Aug 30
|
||||
|
||||
set date Heisei 15 Oct 31
|
||||
add month 1
|
||||
check date Heisei 15 Nov 30
|
||||
add month -1
|
||||
check date Heisei 15 Oct 30
|
||||
|
||||
set date Heisei 15 Dec 31
|
||||
add month -1
|
||||
check date Heisei 15 Nov 30
|
||||
add month 1
|
||||
check date Heisei 15 Dec 30
|
||||
|
||||
set date Heisei 15 Dec 31
|
||||
add month 2
|
||||
check date Heisei 16 Feb 29
|
||||
add month -1
|
||||
check date Heisei 16 Jan 29
|
||||
|
||||
# end of pinDayOfMonth tests
|
||||
|
||||
set date BeforeMeiji 1867 Dec 1
|
||||
add month 1
|
||||
check date Meiji 1 Jan 1
|
||||
add month -1
|
||||
check date BeforeMeiji 1867 Dec 1
|
||||
add month 14
|
||||
check date Meiji 2 Feb 1
|
||||
add month -14
|
||||
check date BeforeMeiji 1867 Dec 1
|
||||
|
||||
set date Meiji 1 Dec 1
|
||||
add month 1
|
||||
check date Meiji 2 Jan 1
|
||||
add month -1
|
||||
check date Meiji 1 Dec 1
|
||||
add month 13
|
||||
check date Meiji 3 Jan 1
|
||||
add month -13
|
||||
check date Meiji 1 Dec 1
|
||||
|
||||
set date Meiji 45 Jun 30
|
||||
add month 1
|
||||
check date Taisho 1 Jul 30
|
||||
add month -1
|
||||
check date Meiji 45 Jun 30
|
||||
|
||||
set date Meiji 45 Jun 30
|
||||
add month 14
|
||||
check date Taisho 2 Aug 30
|
||||
add month -14
|
||||
check date Meiji 45 Jun 30
|
||||
|
||||
# Taisho Gan-nen (year 1) has only 6 months.
|
||||
set date Taisho 1 Jul 30
|
||||
add month -1
|
||||
check date Meiji 45 Jun 30
|
||||
add month 1
|
||||
check date Taisho 1 Jul 30
|
||||
add month -18
|
||||
check date Meiji 44 Jan 30
|
||||
add month 18
|
||||
check date Taisho 1 Jul 30
|
||||
|
||||
set date Taisho 15 Jan 20
|
||||
add month 11
|
||||
check date Taisho 15 Dec 20
|
||||
|
||||
set date Taisho 15 Jan 25
|
||||
add month 11
|
||||
check date Showa 1 Dec 25
|
||||
|
||||
set date Showa 1 Dec 25
|
||||
add month 1
|
||||
check date Showa 2 Jan 25
|
||||
add month -1
|
||||
check date Showa 1 Dec 25
|
||||
add month 17
|
||||
check date Showa 3 May 25
|
||||
add month -17
|
||||
check date Showa 1 Dec 25
|
||||
|
||||
set date Showa 64 Jan 7
|
||||
add month 1
|
||||
check date Heisei 1 Feb 7
|
||||
|
||||
set date Heisei 1 Feb 1
|
||||
add month -1
|
||||
# Heisei starts from Jan 8.
|
||||
check date Showa 64 Jan 1
|
||||
add month 1
|
||||
check date Heisei 1 Feb 1
|
||||
|
||||
set date Heisei 1 Feb 8
|
||||
add month -1
|
||||
check date Heisei 1 Jan 8
|
||||
|
||||
set date Heisei 1 Dec 1
|
||||
add month 1
|
||||
check date Heisei 2 Jan 1
|
||||
add month -1
|
||||
check date Heisei 1 Dec 1
|
||||
|
||||
set date Heisei 1 Dec 8
|
||||
add month 1
|
||||
check date Heisei 2 Jan 8
|
||||
add month -1
|
||||
check date Heisei 1 Dec 8
|
||||
|
||||
# time zone dependent tests
|
||||
use tokyocal
|
||||
clear all
|
||||
|
||||
set date BeforeMeiji 1 Jan 1
|
||||
get min year
|
||||
assign $result $minyear
|
||||
# actual min date: -292275055.05.17T01:47:04.192+0900
|
||||
|
||||
set date BeforeMeiji $minyear Dec 17
|
||||
set timeofday 1 47 4 192
|
||||
add month -7
|
||||
check date BeforeMeiji $minyear May 17
|
||||
check timeofday 1 47 4 192
|
||||
add month 7
|
||||
check date BeforeMeiji $minyear Dec 17
|
||||
check timeofday 1 47 4 192
|
||||
set date BeforeMeiji $minyear Dec 17
|
||||
set timeofday 1 47 4 191
|
||||
add month -7
|
||||
check date BeforeMeiji $minyear May 18
|
||||
check timeofday 1 47 4 191
|
||||
|
||||
set date Reiwa 17 Jan 1
|
||||
get max year
|
||||
assign $result $max
|
||||
set date Reiwa $max Jul 17
|
||||
add month 1
|
||||
check date Reiwa $max Aug 17
|
||||
# set date Heisei $max Jul 28
|
||||
# set timeofday 23 59 59 999
|
||||
# add month 1
|
||||
# check date Heisei $max Aug 16
|
||||
# check timeofday 23 59 59 999
|
||||
|
||||
# JDK-8273924
|
||||
set date Reiwa 2 Mar 1
|
||||
add month -10
|
||||
check date Reiwa 1 May 1
|
||||
set date Reiwa 2 Mar 1
|
||||
add month -11
|
||||
check date Heisei 31 Apr 1
|
||||
set date Reiwa 2 Mar 1
|
||||
add month -12
|
||||
check date Heisei 31 Mar 1
|
||||
set date Reiwa 2 Mar 1
|
||||
add month -13
|
||||
check date Heisei 31 Feb 1
|
||||
set date Reiwa 2 Mar 1
|
||||
add month -14
|
||||
check date Heisei 31 Jan 1
|
||||
set date Reiwa 2 Mar 1
|
||||
add month -15
|
||||
check date Heisei 30 Dec 1
|
||||
|
||||
test add WEEK_OF_YEAR
|
||||
use jcal
|
||||
clear all
|
||||
# 1867 Dec 23 is Monday.
|
||||
set date BeforeMeiji 1867 Dec 23
|
||||
add week_of_year 2
|
||||
check day_of_week Mon
|
||||
check date Meiji 1 Jan 6
|
||||
add week_of_year -2
|
||||
check day_of_week Mon
|
||||
check date BeforeMeiji 1867 Dec 23
|
||||
|
||||
# 1867 Dec 23 is Wednesday.
|
||||
set date Meiji 1 Dec 23
|
||||
add week_of_year 2
|
||||
check day_of_week Wed
|
||||
check date Meiji 2 Jan 6
|
||||
add week_of_year -2
|
||||
check day_of_week Wed
|
||||
check date Meiji 1 Dec 23
|
||||
|
||||
# Meiji 45 July 23 is Tuesday.
|
||||
set date Meiji 45 Jul 23
|
||||
add week_of_year 1
|
||||
check day_of_week Tue
|
||||
check date Taisho 1 Jul 30
|
||||
add week_of_year -1
|
||||
check day_of_week Tue
|
||||
check date Meiji 45 Jul 23
|
||||
|
||||
# Taisho 15 December 23 is Thursday.
|
||||
set date Taisho 15 Dec 23
|
||||
add week_of_year 1
|
||||
check day_of_week Thu
|
||||
check date Showa 1 Dec 30
|
||||
add week_of_year -1
|
||||
check day_of_week Thu
|
||||
check date Taisho 15 Dec 23
|
||||
|
||||
# Showa Gan-nen December 30 is Thursday. Showa Gan-nen has
|
||||
# only one week. Rolling any number of weeks brings to the
|
||||
# same date.
|
||||
set date Showa 1 Dec 30
|
||||
add week_of_year 1
|
||||
check day_of_week Thu
|
||||
check date Showa 2 Jan 6
|
||||
add week_of_year -1
|
||||
check day_of_week Thu
|
||||
check date Showa 1 Dec 30
|
||||
|
||||
# Showa 64 January 7 is Saturday. The year has only one week.
|
||||
set date Showa 64 Jan 7
|
||||
add week_of_year 1
|
||||
check day_of_week Sat
|
||||
check date Heisei 1 Jan 14
|
||||
add week_of_year -1
|
||||
check day_of_week Sat
|
||||
check date Showa 64 Jan 7
|
||||
|
||||
use tokyocal
|
||||
clear all
|
||||
|
||||
set date BeforeMeiji $minyear Dec 25
|
||||
check day_of_week Sat
|
||||
eval $minyear + 1
|
||||
assign $result $minyear_plus_1
|
||||
add week_of_year 1
|
||||
check day_of_week Sat
|
||||
check date BeforeMeiji $minyear_plus_1 Jan 1
|
||||
add week_of_year -1
|
||||
check day_of_week Sat
|
||||
check date BeforeMeiji $minyear Dec 25
|
||||
|
||||
test WEEK_OF_MONTH
|
||||
use jcal
|
||||
clear all
|
||||
|
||||
test DAY_OF_MONTH
|
||||
use jcal
|
||||
clear all
|
||||
|
||||
test DAY_OF_YEAR
|
||||
use jcal
|
||||
clear all
|
||||
|
||||
# 1867 is a regular Gregorian year.
|
||||
set date BeforeMeiji 1867 Dec 31
|
||||
add day_of_year 1
|
||||
check date Meiji 1 Jan 1
|
||||
add day_of_year -1
|
||||
check date BeforeMeiji 1867 Dec 31
|
||||
add day_of_year 26
|
||||
check date Meiji 1 Jan 26
|
||||
add day_of_year -26
|
||||
check date BeforeMeiji 1867 Dec 31
|
||||
|
||||
# Meiji 1 starts from Jan 1. It's a regular year as well.
|
||||
set date Meiji 1 Dec 31
|
||||
add day_of_year 1
|
||||
check date Meiji 2 Jan 1
|
||||
add day_of_year -1
|
||||
check date Meiji 1 Dec 31
|
||||
add day_of_year 26
|
||||
check date Meiji 2 Jan 26
|
||||
add day_of_year -26
|
||||
check date Meiji 1 Dec 31
|
||||
|
||||
# The last year of Meiji (45) has an irregularity. Meiji 45
|
||||
# July 30 is actually Taisho 1 July 30.
|
||||
set date Meiji 45 Jul 29
|
||||
add day_of_year 1
|
||||
check date Taisho 1 Jul 30
|
||||
add day_of_year -1
|
||||
check date Meiji 45 Jul 29
|
||||
|
||||
# The first day of Taisho, July 30.
|
||||
set date Taisho 1 Jul 30
|
||||
add day_of_year -1
|
||||
check date Meiji 45 Jul 29
|
||||
add day_of_year 1
|
||||
check date Taisho 1 Jul 30
|
||||
|
||||
set date Taisho 15 Dec 24
|
||||
add day_of_year 1
|
||||
check date Showa 1 Dec 25
|
||||
add day_of_year -1
|
||||
check date Taisho 15 Dec 24
|
||||
|
||||
set date Showa 1 Dec 31
|
||||
add day_of_year 1
|
||||
check date Showa 2 Jan 1
|
||||
add day_of_year -1
|
||||
check date Showa 1 Dec 31
|
||||
add day_of_year 25
|
||||
check date Showa 2 Jan 25
|
||||
add day_of_year -25
|
||||
check date Showa 1 Dec 31
|
||||
|
||||
set date Showa 64 Jan 7
|
||||
add day_of_year 1
|
||||
check date Heisei 1 Jan 8
|
||||
add day_of_year -1
|
||||
check date Showa 64 Jan 7
|
||||
|
||||
set date Heisei 1 Dec 31
|
||||
add day_of_year 5
|
||||
check date Heisei 2 Jan 5
|
||||
add day_of_year -5
|
||||
check date Heisei 1 Dec 31
|
||||
|
||||
use tokyocal
|
||||
clear all
|
||||
|
||||
set date BeforeMeiji $minyear Dec 31
|
||||
set timeofday 1 47 4 192
|
||||
add day_of_year 1
|
||||
check date BeforeMeiji $minyear_plus_1 Jan 1
|
||||
check timeofday 1 47 4 192
|
||||
add day_of_year -1
|
||||
check date BeforeMeiji $minyear Dec 31
|
||||
check timeofday 1 47 4 192
|
||||
|
||||
test DAY_OF_WEEK_IN_MONTH
|
||||
use jcal
|
||||
clear all
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
|
||||
locale ja JP JP
|
||||
|
||||
# Use jcal in non-lenient mode for all test cases.
|
||||
set non-lenient
|
||||
new instance jcal
|
||||
|
||||
use jcal
|
||||
clear all
|
||||
|
||||
test Invalid BeforeMeiji dates
|
||||
set date BeforeMeiji 1868 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date BeforeMeiji 1868 Jan 32
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date BeforeMeiji 2005 Mar 9
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid Meiji dates
|
||||
set date Meiji -1 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Meiji 1 Feb 30
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Meiji 45 Jul 30
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Meiji 46 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid Taisho dates
|
||||
set date Taisho -1 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Taisho 1 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Taisho 1 Apr 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Taisho 15 Dec 30
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Taisho 15 Feb 29
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid Showa dates
|
||||
set date Showa -11 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Showa 1 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Showa 1 Jun 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Showa 1 Jul 29
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Showa 64 Jan 8
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Showa 64 Dec 8
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Showa 65 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid Heisei dates
|
||||
clear all
|
||||
set date Heisei -1 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Heisei 1 Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Heisei 1 Jan 7
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set date Heisei 1 Jan 8
|
||||
get max year
|
||||
eval $result + 1
|
||||
set date Heisei $result Jan 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid ERA
|
||||
get max era
|
||||
eval $result + 1
|
||||
set era $result # max era + 1
|
||||
get era
|
||||
exception IllegalArgumentException
|
||||
set era 100
|
||||
get era
|
||||
exception IllegalArgumentException
|
||||
set era -100
|
||||
get era
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid HOUR_OF_DAY
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set hour_of_day 25
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set hour_of_day -9
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid AMPM
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set ampm -1
|
||||
set hour 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set ampm 5
|
||||
set hour 1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid HOUR
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set ampm AM
|
||||
set hour 13
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set ampm PM
|
||||
set hour -1
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid MINUTE
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set minute 61
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set minute -2
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid SECOND
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set second 61
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set second -2
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid MILLISECOND
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set millisecond 1000
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set millisecond -2
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid ZONE_OFFSET
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set zone_offset -360000000
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set zone_offset -360000000
|
||||
get year
|
||||
exception IllegalArgumentException
|
||||
set zone_offset 360000000
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set zone_offset 360000000
|
||||
get year
|
||||
exception IllegalArgumentException
|
||||
|
||||
test Invalid DST_OFFSET
|
||||
clear all
|
||||
set date Heisei 17 Mar 14
|
||||
set dst_offset -360000000
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set dst_offset -360000000
|
||||
get year
|
||||
exception IllegalArgumentException
|
||||
set dst_offset 360000000
|
||||
get millis
|
||||
exception IllegalArgumentException
|
||||
set dst_offset 360000000
|
||||
get year
|
||||
exception IllegalArgumentException
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
|
||||
locale ja JP JP
|
||||
new instance jcal
|
||||
new gregorian gcal
|
||||
|
||||
# Use GMT+09:00 for max day of year test which depends on time zone
|
||||
# offsets.
|
||||
|
||||
timezone GMT+09:00
|
||||
new instance tokyocal
|
||||
|
||||
test Make sure that the maximum year value doesn't depent on era
|
||||
use jcal
|
||||
# Note: the max year value is as of Reiwa
|
||||
assign 292276976 $max
|
||||
clear all
|
||||
set date Reiwa 1 May 1
|
||||
get millis
|
||||
check max year $max
|
||||
assign $max $maxyear
|
||||
|
||||
clear all
|
||||
set date Heisei 20 May 5
|
||||
get millis
|
||||
check max year $maxyear
|
||||
|
||||
clear all
|
||||
set date Showa 35 May 5
|
||||
get millis
|
||||
check max year $maxyear
|
||||
|
||||
clear all
|
||||
set date BeforeMeiji 1 Jun 1
|
||||
get millis
|
||||
check max year $max
|
||||
|
||||
test Max of ERA
|
||||
use jcal
|
||||
# Assumption: Reiwa is the current era
|
||||
check maximum era Reiwa
|
||||
check leastmax era Reiwa
|
||||
|
||||
test Actual max MONTH
|
||||
use jcal
|
||||
clear all
|
||||
set date BeforeMeiji 1867 Jan 31
|
||||
check actualmax month Dec
|
||||
# Make sure that the same value is returned after
|
||||
# normalization.
|
||||
get millis
|
||||
check actualmax month Dec
|
||||
|
||||
clear all
|
||||
set date Meiji 45 Mar 31
|
||||
check actualmax month Jul
|
||||
get millis
|
||||
check actualmax month Jul
|
||||
|
||||
clear all
|
||||
set date Taisho 15 June 1
|
||||
check actualmax month Dec
|
||||
get millis
|
||||
check actualmax month Dec
|
||||
|
||||
clear all
|
||||
set date Showa 64 Jan 4
|
||||
check actualmax month Jan
|
||||
get millis
|
||||
check actualmax month Jan
|
||||
|
||||
clear all
|
||||
set date Heisei 31 Jan 4
|
||||
check actualmax month Apr
|
||||
get millis
|
||||
check actualmax month Apr
|
||||
|
||||
clear all
|
||||
set date Reiwa 2 Jan 1
|
||||
set year $maxyear
|
||||
check actualmax month Aug
|
||||
get millis
|
||||
check actualmax month Aug
|
||||
|
||||
clear all
|
||||
set date 17 Mar 1
|
||||
check actualmax month Dec
|
||||
get millis
|
||||
check actualmax month Dec
|
||||
|
||||
test Actual max DAY_OF_YEAR
|
||||
use jcal
|
||||
clear all
|
||||
set date Meiji 1 Dec 31
|
||||
# Meiji Gan-nen is a leap year.
|
||||
check actualmax day_of_year 366
|
||||
check day_of_year 366
|
||||
|
||||
clear all
|
||||
set date Meiji 45 Jan 1
|
||||
# Meiji 45 or Taishi Gan-nen is also a leap year.
|
||||
check actualmax day_of_year 211 # 31+29+31+30+31+30+29
|
||||
set date Meiji 45 Jul 29
|
||||
check day_of_year 211
|
||||
set date Taisho 1 Jul 31
|
||||
get millis
|
||||
check actualmax day_of_year 155 # 366 - 211
|
||||
set date Taisho 1 Dec 31
|
||||
check day_of_year 155
|
||||
|
||||
clear all
|
||||
set date Taisho 15 Sep 23
|
||||
check actualmax day_of_year 358 # 365 - 7
|
||||
set date Taisho 15 Dec 24
|
||||
check day_of_year 358
|
||||
set date Showa 1 Dec 25
|
||||
check actualmax day_of_year 7
|
||||
set date Showa 1 Dec 31
|
||||
check day_of_year 7
|
||||
|
||||
clear all
|
||||
set date Showa 64 Jan 3
|
||||
check actualmax day_of_year 7
|
||||
set date Showa 64 Jan 7
|
||||
check day_of_year 7
|
||||
set date Heisei 1 Aug 9
|
||||
check actualmax day_of_year 358 # 365 - 7
|
||||
set date Heisei 1 Dec 31
|
||||
check day_of_year 358
|
||||
|
||||
# time zone dependent
|
||||
use tokyocal
|
||||
clear all
|
||||
set date Reiwa $maxyear Jan 1
|
||||
# the last date of Reiwa is R292276976.08.17T16:12:55.807+0900
|
||||
check actualmax day_of_year 229 # 31+28+31+30+31+30+31+17
|
||||
|
||||
test Actual max WEEK_OF_YEAR
|
||||
use jcal
|
||||
clear all
|
||||
set date Meiji 1 Jan 1
|
||||
# Meiji gan-nen is a leap year.
|
||||
check actualmax week_of_year 52
|
||||
|
||||
clear all
|
||||
set date Meiji 45 Jan 1
|
||||
check actualmax week_of_year 30
|
||||
set date Taisho 1 July 31
|
||||
check actualmax week_of_year 22
|
||||
|
||||
clear all
|
||||
set date Taisho 15 Sep 23
|
||||
check actualmax week_of_year 51
|
||||
set date Showa 1 Dec 25
|
||||
check actualmax week_of_year 1
|
||||
|
||||
clear all
|
||||
set date Showa 64 Jan 3
|
||||
check actualmax week_of_year 1
|
||||
set date Heisei 1 Aug 9
|
||||
check actualmax week_of_year 51
|
||||
|
||||
clear all
|
||||
set date Heisei 31 Apr 28
|
||||
check actualmax week_of_year 17
|
||||
set date Reiwa 1 Aug 9
|
||||
check actualmax week_of_year 35
|
||||
|
||||
use tokyocal
|
||||
set date Reiwa $maxyear Jan 1
|
||||
# the last date of Reiwa is R292276976.08.17T16:12:55.807+0900 (Sunday)
|
||||
# The year is equivalent to 2003 (Gregorian).
|
||||
check actualmax week_of_year 34
|
||||
|
||||
test Actual max WEEK_OF_MONTH
|
||||
use jcal
|
||||
clear all
|
||||
set date Meiji 45 Jul 1
|
||||
check actualmax week_of_month 5
|
||||
set date Taisho 1 Jul 31
|
||||
check actualmax week_of_month 5
|
||||
|
||||
clear all
|
||||
set date Taisho 15 Dec 1
|
||||
check actualmax week_of_month 5
|
||||
set date Showa 1 Dec 25
|
||||
check actualmax week_of_month 5
|
||||
|
||||
clear all
|
||||
set date Showa 64 Jan 1
|
||||
check actualmax week_of_month 5
|
||||
set date Heisei 1 Jan 8
|
||||
check actualmax week_of_month 5
|
||||
|
||||
clear all
|
||||
set date Heisei 31 Apr 30
|
||||
check actualmax week_of_month 5
|
||||
set date Reiwa 1 May 1
|
||||
check actualmax week_of_month 5
|
||||
|
||||
use tokyocal
|
||||
set date Reiwa $maxyear Jan 1
|
||||
# the last date of Reiwa is R292276976.08.17T16:12:55.807+0900 (Sunday)
|
||||
# The year is equivalent to 2003 (Gregorian).
|
||||
check actualmax week_of_month 4
|
||||
|
||||
test Actual max DAY_OF_WEEK_IN_MONTH
|
||||
use jcal
|
||||
clear all
|
||||
set date Meiji 45 Jul 1
|
||||
check actualmax week_of_month 5
|
||||
set date Taisho 1 Jul 31
|
||||
check actualmax week_of_month 5
|
||||
|
||||
clear all
|
||||
set date Taisho 15 Dec 1
|
||||
check actualmax week_of_month 5
|
||||
set date Showa 1 Dec 25
|
||||
check actualmax week_of_month 5
|
||||
|
||||
clear all
|
||||
set date Showa 64 Jan 1
|
||||
check actualmax week_of_month 5
|
||||
set date Heisei 1 Jan 8
|
||||
check actualmax week_of_month 5
|
||||
|
||||
clear all
|
||||
set date Heisei 31 Apr 30
|
||||
check actualmax week_of_month 5
|
||||
set date Reiwa 1 May 1
|
||||
check actualmax week_of_month 5
|
||||
|
||||
use tokyocal
|
||||
clear all
|
||||
set date Reiwa $maxyear Jan 1
|
||||
# the last date of Reiwa is R292276976.08.17T16:12:55.807+0900 (Sunday)
|
||||
# The year is equivalent to 2003 (Gregorian).
|
||||
check actualmax week_of_month 4
|
||||
|
||||
test Actual max YEAR
|
||||
use jcal
|
||||
clear all
|
||||
set date BeforeMeiji 1 Jan 1
|
||||
check actualmax year 1867
|
||||
|
||||
set date Meiji 1 Jan 1
|
||||
check actualmax year 45
|
||||
|
||||
set date Meiji 1 Jul 30
|
||||
check actualmax year 44
|
||||
|
||||
set date Taisho 1 Jul 30
|
||||
check actualmax year 15
|
||||
|
||||
set date Taisho 1 Dec 25
|
||||
check actualmax year 14
|
||||
|
||||
set date Showa 2 Jan 1
|
||||
check actualmax year 64
|
||||
|
||||
set date Showa 1 Dec 25
|
||||
check actualmax year 63
|
||||
|
||||
set date Heisei 1 Jan 7
|
||||
check actualmax year 64
|
||||
|
||||
set date Heisei 1 Aug 18
|
||||
check actualmax year 30
|
||||
|
||||
set date Reiwa 1 Apr 30
|
||||
check actualmax year 31
|
||||
|
||||
# Date/time beyond the last date in the max year.
|
||||
set date Reiwa 1 Aug 18
|
||||
check actualmax year 292276975
|
||||
|
||||
test Least max YEAR
|
||||
set date Heisei 17 Mar 1
|
||||
# Taisho is the shortest era, 14 years.
|
||||
# (See above actual max YEAR case.)
|
||||
check leastmax year 14
|
||||
|
||||
test Acutual min YEAR
|
||||
# Get minimum values for comparison
|
||||
clear all
|
||||
set era BeforeMeiji
|
||||
get min year
|
||||
assign $result $minyear
|
||||
set date $minyear Dec 31
|
||||
eval $minyear + 1
|
||||
assign $result $minyear_plus_one
|
||||
|
||||
# BeforeMeiji 1 Dec 31 should exist in the minimum year which
|
||||
# should be the same value as the getMinimum() value.
|
||||
set date BeforeMeiji 1 Dec 31
|
||||
check actualmin year $minyear
|
||||
|
||||
# Jan 1 shouldn't exist in the same year. So the actual minimum is
|
||||
# $minyear + 1.
|
||||
set date 1 Jan 1
|
||||
check actualmin year $minyear_plus_one
|
||||
|
||||
# 1 should be returned if it's on a date of the last
|
||||
# year which also exists in the first year of each era.
|
||||
clear all
|
||||
set date Meiji 45 Jan 1
|
||||
check actualmin year 1
|
||||
|
||||
clear all
|
||||
set date Taisho 14 Jul 30
|
||||
check actualmin year 1
|
||||
|
||||
clear all
|
||||
set date Showa 60 Dec 25
|
||||
check actualmin year 1
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Jan 8
|
||||
check actualmin year 1
|
||||
|
||||
# 2 should be returned if it's on a date of the last year which
|
||||
# doesn't exist in the first year of each era. (Meiji is an
|
||||
# exception.)
|
||||
clear all
|
||||
set date Taisho 14 Jul 29
|
||||
check actualmin year 2
|
||||
|
||||
clear all
|
||||
set date Showa 60 Dec 23
|
||||
check actualmin year 2
|
||||
|
||||
clear all
|
||||
set date Heisei 17 Jan 7
|
||||
check actualmin year 2
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
|
||||
locale ja JP JP
|
||||
tz Asia/Tokyo
|
||||
new instance jcal
|
||||
new gregorian gcal
|
||||
|
||||
test Normalize year 0 and -1 (Showa)
|
||||
use jcal
|
||||
clear all
|
||||
set date Showa 1 Jan 1
|
||||
check date Taisho 15 Jan 1
|
||||
|
||||
clear all
|
||||
set date Showa 0 Jan 1
|
||||
check era Taisho
|
||||
check date 14 Jan 1
|
||||
|
||||
clear all
|
||||
set date Showa -1 Jan 1
|
||||
check era Taisho
|
||||
check date 13 Jan 1
|
||||
|
||||
test Normalize year max and max+1 (Showa)
|
||||
clear all
|
||||
set date Showa 64 Aug 9
|
||||
check date Heisei 1 Aug 9
|
||||
|
||||
clear all
|
||||
set date Showa 65 Aug 9
|
||||
check date Heisei 2 Aug 9
|
||||
|
||||
test Normalize year 0 and -1 (Heisei)
|
||||
use jcal
|
||||
clear all
|
||||
set date Heisei 1 Jan 1
|
||||
check date Showa 64 Jan 1
|
||||
|
||||
clear all
|
||||
set date Heisei 0 Jan 1
|
||||
check date Showa 63 Jan 1
|
||||
|
||||
clear all
|
||||
set date Heisei -1 Jan 1
|
||||
check date Showa 62 Jan 1
|
||||
|
||||
test Normalize year max and max+1 (Taisho)
|
||||
clear all
|
||||
set date Taisho 15 Dec 25
|
||||
check date Showa 1 Dec 25
|
||||
|
||||
clear all
|
||||
set date Taisho 16 Dec 25
|
||||
check date Showa 2 Dec 25
|
||||
|
||||
test Normalize day of month 0 and -1 (Heisei)
|
||||
use jcal
|
||||
clear all
|
||||
set date Heisei 1 Jan 1
|
||||
check date Showa 64 Jan 1
|
||||
|
||||
clear all
|
||||
set date Heisei 1 Jan 0
|
||||
check date Showa 63 Dec 31
|
||||
|
||||
clear all
|
||||
set date Heisei 1 Jan -1
|
||||
check date Showa 63 Dec 30
|
||||
|
||||
test Normalize hour of day -1:00 (Heisei)
|
||||
clear all
|
||||
set era Heisei
|
||||
set datetime 1 Jan 1 0 0 0
|
||||
check era Showa
|
||||
check datetime 64 Jan 1 0 0 0
|
||||
|
||||
clear all
|
||||
set era Heisei
|
||||
set datetime 1 Jan 1 -1 0 0
|
||||
check era Showa
|
||||
check datetime 63 Dec 31 23 0 0
|
||||
|
||||
test Normalize hour of day 25:00 (Taisho)
|
||||
clear all
|
||||
set era Taisho
|
||||
set datetime 15 Dec 25 25 0 0
|
||||
check era Showa
|
||||
check datetime 1 Dec 26 1 0 0
|
||||
|
||||
test Normalize hour of day 25:00 (Showa)
|
||||
clear all
|
||||
set era Showa
|
||||
set datetime 64 Jan 7 25 0 0
|
||||
check era Heisei
|
||||
check datetime 1 Jan 8 1 0 0
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue