# HG changeset patch # User henryjen # Date 1384240650 28800 # Node ID 99dd9e50f37e3401aa05d91b50938be7f1ab6bde # Parent f82b730c798b6bf38946baaba8a7d80fd5efaa70# Parent ed09558136be7b67736c694ba7b9b06858ba748e Merge diff -r f82b730c798b -r 99dd9e50f37e .hgignore --- a/.hgignore Thu Oct 31 16:44:18 2013 -0700 +++ b/.hgignore Mon Nov 11 23:17:30 2013 -0800 @@ -5,3 +5,19 @@ ^make/netbeans/.*/dist/ ^.hgtip .DS_Store +^test-ng/gen-separate/ +^test-ng/lib/ +^.idea/ +^combo-tests/gen/ +^combo-tests/build/ +^out/ +.*\.rej$ +.*\.orig$ +.*\.iml$ +.*~$ +^webrev/ +webrev.zip$ +^.classpath +^.project +JTreport +JTwork diff -r f82b730c798b -r 99dd9e50f37e .hgtags --- a/.hgtags Thu Oct 31 16:44:18 2013 -0700 +++ b/.hgtags Mon Nov 11 23:17:30 2013 -0800 @@ -167,16 +167,20 @@ b3246687c3695dff6f461bb407f9db88f7d072e7 jdk8-b43 db471a7af03168e4441c245b1d9976f720a7cb77 jdk8-b44 b92353a01aa049bc508fc56f0347d5934b7c4390 jdk8-b45 +077225955d5722f0fbd780650178c5931693c07e lambda-b45 8d2ed9d58453c8049715a72a6d26b6b66b37a94c jdk8-b46 00b22b23269a57d0bb46c57753be2fe9a9d2c1a3 jdk8-b47 3e4ab821f46166fcf63e8fe5c8046216003c941f jdk8-b48 +b3b65a3d441e7f39cb68140d2db547704ea0a670 lambda-b48 51707c3b75c0f521794d9ab425f4e5b2351c70c1 jdk8-b49 e4bae5c53fca8fcb9393d47fd36a34b9e2e8d4ec jdk8-b50 +958eaa191b79bf79be82979240903199791ed9f7 lambda-b50 e865efbc71059a414b3b2dd2e0adfcb3d2ab6ff9 jdk8-b51 e8569a473cee7f4955bd9e76a9bdf6c6a07ced27 jdk8-b52 2c6933c5106b81a8578b70996fe5b735fb3adb60 jdk8-b53 70ad0ed1d6cef0e7712690d1bab21e4769708aad jdk8-b54 1f3f4b333341873f00da3dee85e4879f0e89c9bb jdk8-b55 +2e6170973d921fe4b8d2dfd6032f5aaf4150a542 lambda-b56 2e9eeef2909b33c9224a024afddb61ccb0b77f14 jdk8-b56 51594d095a4bcffac4a314bf6e148214501399e0 jdk8-b57 d94613ac03d8de375ef60493e2bb76dbd30d875d jdk8-b58 diff -r f82b730c798b -r 99dd9e50f37e .jcheck/conf --- a/.jcheck/conf Thu Oct 31 16:44:18 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -project=jdk8 diff -r f82b730c798b -r 99dd9e50f37e README diff -r f82b730c798b -r 99dd9e50f37e combo-tests/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/build.xml Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/BridgeMethodTestCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/BridgeMethodTestCase.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,423 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.testng.Assert.fail; + +/** + * BridgeMethodTestCase -- used for asserting linkage to bridges under separate compilation. + * + * Example test case: + * public void test1() throws IOException, ReflectiveOperationException { + * compileSpec("C(Bc1(A))"); + * assertLinkage("C", LINKAGE_ERROR, "B1"); + * recompileSpec("C(Bc1(Ac0))", "A"); + * assertLinkage("C", "A0", "B1"); + * } + * + * This compiles A, B, and C, asserts that C.m()Object does not exist, asserts + * that C.m()Number eventually invokes B.m()Number, recompiles B, and then asserts + * that the result of calling C.m()Object now arrives at A. + * + * @author Brian Goetz + */ + +@Test +public abstract class BridgeMethodTestCase extends JavacTemplateTestBase { + + private static final String TYPE_LETTERS = "ABCDIJK"; + + private static final String BASE_INDEX_CLASS = "class C0 {\n" + + " int val;\n" + + " C0(int val) { this.val = val; }\n" + + " public int getVal() { return val; }\n" + + "}\n"; + + private static final String INDEX_CLASS_TEMPLATE = "class C#ID extends C#PREV {\n" + + " C#ID(int val) { super(val); }\n" + + "}\n"; + + + + protected static String LINKAGE_ERROR = "-1"; + + private List compileDirs = new ArrayList<>(); + + /** + * Compile all the classes in a class spec, and put them on the classpath. + * + * The spec is the specification for a nest of classes, using the following notation + * A, B represent abstract classes + * C represents a concrete class + * I, J, K represent interfaces + * Lowercase 'c' following a class means that the method m() is concrete + * Lowercase 'a' following a class or interface means that the method m() is abstract + * Lowercase 'd' following an interface means that the method m() is default + * A number 0, 1, or 2 following the lowercase letter indicates the return type of that method + * 0 = Object, 1 = Number, 2 = Integer (these form an inheritance chain so bridges are generated) + * A classes supertypes follow its method spec, in parentheses + * Examples: + * C(Ia0, Jd0) -- C extends I and J, I has abstract m()Object, J has default m()Object + * Cc1(Ia0) -- C has concrete m()Number, extends I with abstract m()Object + * If a type must appear multiple times, its full spec must be in the first occurrence + * Example: + * C(I(Kd0), J(K)) + */ + protected void compileSpec(String spec) throws IOException { + compileSpec(spec, false); + } + + /** + * Compile all the classes in a class spec, and assert that there were compilation errors. + */ + protected void compileSpec(String spec, String... errorKeys) throws IOException { + compileSpec(spec, false, errorKeys); + } + + protected void compileSpec(String spec, boolean debug, String... errorKeys) throws IOException { + ClassModel cm = new Parser(spec).parseClassModel(); + for (int i = 0; i <= cm.maxIndex() ; i++) { + if (debug) System.out.println(indexClass(i)); + addSourceFile(String.format("C%d.java", i), new StringTemplate(indexClass(i))); + } + for (Map.Entry e : classes(cm).entrySet()) { + if (debug) System.out.println(e.getValue().toSource()); + addSourceFile(e.getKey() + ".java", new StringTemplate(e.getValue().toSource())); + } + compileDirs.add(compile(true)); + resetSourceFiles(); + if (errorKeys.length == 0) + assertCompileSucceeded(); + else + assertCompileErrors(errorKeys); + } + + /** + * Recompile only a subset of classes in the class spec, as named by names, + * and put them on the classpath such that they shadow earlier versions of that class. + */ + protected void recompileSpec(String spec, String... names) throws IOException { + List nameList = Arrays.asList(names); + ClassModel cm = new Parser(spec).parseClassModel(); + for (int i = 0; i <= cm.maxIndex() ; i++) { + addSourceFile(String.format("C%d.java", i), new StringTemplate(indexClass(i))); + } + for (Map.Entry e : classes(cm).entrySet()) + if (nameList.contains(e.getKey())) + addSourceFile(e.getKey() + ".java", new StringTemplate(e.getValue().toSource())); + compileDirs.add(compile(Arrays.asList(classPaths()), true)); + resetSourceFiles(); + assertCompileSucceeded(); + } + + protected void assertLinkage(String name, String... expected) throws ReflectiveOperationException { + for (int i=0; i classes(ClassModel cm) { + HashMap m = new HashMap<>(); + classesHelper(cm, m); + return m; + } + + private String indexClass(int index) { + if (index == 0) { + return BASE_INDEX_CLASS; + } else { + return INDEX_CLASS_TEMPLATE + .replace("#ID", String.valueOf(index)) + .replace("#PREV", String.valueOf(index - 1)); + } + } + + private static String overrideName(int index) { + return "C" + index; + } + + private void classesHelper(ClassModel cm, Map m) { + if (!m.containsKey(cm.name)) + m.put(cm.name, cm); + for (ClassModel s : cm.supertypes) + classesHelper(s, m); + } + + private static String fromNum(int num) { + return String.format("%c%d", TYPE_LETTERS.charAt(num / 10), num % 10); + } + + private static int toNum(String name, int index) { + return 10*(TYPE_LETTERS.indexOf(name.charAt(0))) + index; + } + + private static int toNum(String string) { + return 10*(TYPE_LETTERS.indexOf(string.charAt(0))) + Integer.parseInt(string.substring(1, 2)); + } + + private int invoke(String name, int index) throws ReflectiveOperationException { + File[] files = classPaths(); + Class clazz = loadClass(name, files); + Method[] ms = clazz.getMethods(); + for (Method m : ms) { + if (m.getName().equals("m") && m.getReturnType().getName().equals(overrideName(index))) { + m.setAccessible(true); + Object instance = clazz.newInstance(); + Object c0 = m.invoke(instance); + Method getVal = c0.getClass().getMethod("getVal"); + getVal.setAccessible(true); + return (int)getVal.invoke(c0); + } + } + throw new NoSuchMethodError("cannot find method m()" + index + " in class " + name); + } + + private File[] classPaths() { + File[] files = new File[compileDirs.size()]; + for (int i=0; i supertypes; + private final MethodType methodType; + private final int methodIndex; + + private ClassModel(String name, + boolean anInterface, + List supertypes, + MethodType methodType, + int methodIndex) { + this.name = name; + isInterface = anInterface; + this.supertypes = supertypes; + this.methodType = methodType; + this.methodIndex = methodIndex; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(name); + if (methodType != null) { + sb.append(methodType.designator); + sb.append(methodIndex); + } + if (!supertypes.isEmpty()) { + sb.append("("); + for (int i=0; i 0) + sb.append(","); + sb.append(supertypes.get(i).toString()); + } + sb.append(")"); + } + return sb.toString(); + } + + int maxIndex() { + int maxSoFar = methodIndex; + for (ClassModel cm : supertypes) { + maxSoFar = Math.max(cm.maxIndex(), maxSoFar); + } + return maxSoFar; + } + + public String toSource() { + String extendsClause = ""; + String implementsClause = ""; + String methodBody = ""; + boolean isAbstract = "AB".contains(name); + + for (ClassModel s : supertypes) { + if (!s.isInterface) { + extendsClause = String.format("extends %s", s.name); + break; + } + } + + StringJoiner sj = new StringJoiner(", "); + for (ClassModel s : supertypes) + if (s.isInterface) + sj.add(s.name); + if (sj.length() > 0) { + if (isInterface) + implementsClause = "extends " + sj.toString(); + else + implementsClause = "implements " + sj.toString(); + } + if (methodType != null) { + switch (methodType) { + case ABSTRACT: + methodBody = String.format("public abstract %s m();", overrideName(methodIndex)); + break; + case CONCRETE: + methodBody = String.format("public %s m() { return new %s(%d); };", + overrideName(methodIndex), overrideName(methodIndex), toNum(name, methodIndex)); + break; + case DEFAULT: + methodBody = String.format("public default %s m() { return new %s(%d); };", + overrideName(methodIndex), overrideName(methodIndex), toNum(name, methodIndex)); + break; + + } + } + + return String.format("public %s %s %s %s %s { %s }", isAbstract ? "abstract" : "", + isInterface ? "interface" : "class", + name, extendsClause, implementsClause, methodBody); + } + } + + private static class Parser { + private final String input; + private final char[] chars; + private int index; + + private Parser(String s) { + input = s; + chars = s.toCharArray(); + } + + private char peek() { + return index < chars.length ? chars[index] : 0; + } + + private boolean peek(String validChars) { + return validChars.indexOf(peek()) >= 0; + } + + private char advanceIf(String validChars) { + if (peek(validChars)) + return chars[index++]; + else + return 0; + } + + private char advanceIfDigit() { + return advanceIf("0123456789"); + } + + private int index() { + StringBuilder buf = new StringBuilder(); + char c = advanceIfDigit(); + while (c != 0) { + buf.append(c); + c = advanceIfDigit(); + } + return Integer.valueOf(buf.toString()); + } + + private char advance() { + return chars[index++]; + } + + private char expect(String validChars) { + char c = advanceIf(validChars); + if (c == 0) + throw new IllegalArgumentException(String.format("Expecting %s at position %d of %s", validChars, index, input)); + return c; + } + + public ClassModel parseClassModel() { + List supers = new ArrayList<>(); + char name = expect(TYPE_LETTERS); + boolean isInterface = "IJK".indexOf(name) >= 0; + ClassModel.MethodType methodType = peek(isInterface ? "ad" : "ac") ? ClassModel.MethodType.find(advance()) : null; + int methodIndex = 0; + if (methodType != null) { + methodIndex = index(); + } + if (peek() == '(') { + advance(); + supers.add(parseClassModel()); + while (peek() == ',') { + advance(); + supers.add(parseClassModel()); + } + expect(")"); + } + return new ClassModel(new String(new char[]{ name }), isInterface, supers, methodType, methodIndex); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/BridgeMethodsLinearTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/BridgeMethodsLinearTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,1083 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.io.IOException; + +import org.testng.annotations.Test; + +/** + * BridgeMethodsLinearTest + * + * @author Brian Goetz + */ +@Test +public class BridgeMethodsLinearTest extends BridgeMethodTestCase { + + /* + * Cc1(A) -> Cc1(Ac0) + * + * 0*: Inherited from A + * 1: Declared in C + */ + public void test1() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(A)"); + assertLinkage("C", LINKAGE_ERROR, "C1"); + recompileSpec("Cc1(Ac0)", "A"); + assertLinkage("C", "A0", "C1"); + } + + /* + * Cc1(I) -> Cc1(Id0) + * + * 0*: Inherited default from I + * 1: Declared in C + */ + public void test2() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(I)"); + assertLinkage("C", LINKAGE_ERROR, "C1"); + recompileSpec("Cc1(Id0)", "I"); + assertLinkage("C", "I0", "C1"); + } + + /* + * C(Bc1(A)) -> C(Bc1(Ac0)) + * + * 0*: Inherited from A + * 1: Inherited from B + */ + public void test3() throws IOException, ReflectiveOperationException { + compileSpec("C(Bc1(A))"); + assertLinkage("C", LINKAGE_ERROR, "B1"); + recompileSpec("C(Bc1(Ac0))", "A"); + assertLinkage("C", "A0", "B1"); + } + + /* + * C(B(Ac0)) -> C(Bc1(Ac0)) + * + * 0: Inherited from B (through bridge) + * 1: Inherited from B + */ + public void test4() throws IOException, ReflectiveOperationException { + compileSpec("C(B(Ac0))"); + assertLinkage("C", "A0", LINKAGE_ERROR); + recompileSpec("C(Bc1(Ac0))", "B"); + assertLinkage("C", "B1", "B1"); + } + + /* + * C(B(A)) -> C(Bc1(Ac0)) + * + * 0: Inherited from B (through bridge) + * 1: Inherited from B + */ + public void test5() throws IOException, ReflectiveOperationException { + compileSpec("C(B(A))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Bc1(Ac0))", "A", "B"); + assertLinkage("C", "B1", "B1"); + } + + /* + * C(Ac1(I)) -> C(Ac1(Id0)) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test6() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac1(I))"); + assertLinkage("C", LINKAGE_ERROR, "A1"); + recompileSpec("C(Ac1(Id0))", "I"); + assertLinkage("C", "I0", "A1"); + } + + /* + * C(A(Id0)) -> C(Ac1(Id0)) + * + * 0: Inherited from A (through bridge) + * 1: Inherited from A + */ + public void test7() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac1(Id0))", "A"); + assertLinkage("C", "A1", "A1"); + } + + /* + * C(A(I)) -> C(Ac1(Id0)) + * + * 0*: Inherited from A (through bridge) + * 1*: Inherited from A + */ + public void test8() throws IOException, ReflectiveOperationException { + compileSpec("C(A(I))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Ac1(Id0))", "A", "I"); + assertLinkage("C", "A1", "A1"); + } + + /* + * C(Id1(J)) -> C(Id1(Jd0)) + * + * 0*: Inherited default from J + * 1: Inherited default from I + */ + public void test9() throws IOException, ReflectiveOperationException { + compileSpec("C(Id1(J))"); + assertLinkage("C", LINKAGE_ERROR, "I1"); + recompileSpec("C(Id1(Jd0))", "J"); + assertLinkage("C", "J0", "I1"); + } + + /* + * C(I(Jd0)) -> C(Id1(Jd0)) + * + * 0: Inherited default from I (through bridge) + * 1: Inherited default from I + */ + public void test10() throws IOException, ReflectiveOperationException { + compileSpec("C(I(Jd0))"); + assertLinkage("C", "J0", LINKAGE_ERROR); + recompileSpec("C(Id1(Jd0))", "I"); + assertLinkage("C", "I1", "I1"); + } + + /* + * C(I(J)) -> C(Id1(Jd0)) + * + * 0: Inherited default from I (through bridge) + * 1: Inherited default from I + */ + public void test11() throws IOException, ReflectiveOperationException { + compileSpec("C(I(J))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Id1(Jd0))", "I", "J"); + assertLinkage("C", "I1", "I1"); + } + + /* + * Cc2(B(Ac0)) -> Cc2(Bc1(Ac0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from B + * 2: Declared in C + */ + public void test12() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(B(Ac0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Bc1(Ac0))", "B"); + assertLinkage("C", "C2", "B1", "C2"); + } + + /* + * Cc2(B(Aa0)) -> Cc2(Bc1(Aa0)) + * + * 0: Bridge in C (through bridge) + * 1*: Inherited from B + * 2: Declared in C + */ + public void test13() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(B(Aa0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Bc1(Aa0))", "B"); + assertLinkage("C", "C2", "B1", "C2"); + } + + /* + * Cc2(Bc1(A)) -> Cc2(Bc1(Ac0)) + * + * 0*: Inherited from A + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test14() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Bc1(A))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Bc1(Ac0))", "A"); + assertLinkage("C", "A0", "C2", "C2"); + } + + /* + * Cc2(Ba1(A)) -> Cc2(Ba1(Ac0)) + * + * 0*: Inherited from A + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test15() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ba1(A))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ba1(Ac0))", "A"); + assertLinkage("C", "A0", "C2", "C2"); + } + + /* + * Cc2(B(A)) -> Cc2(Bc1(Ac0)) + * + * 0*: Inherited from B (through bridge) + * 1*: Inherited from B + * 2: Declared in C + */ + public void test16() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(B(A))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Bc1(Ac0))", "B", "A"); + assertLinkage("C", "B1", "B1", "C2"); + } + + /* + * Cc2(A(Id0)) -> Cc2(Ac1(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test17() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Id0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A(Ia0)) -> Cc2(Ac1(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test18() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Ia0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(Ac1(I)) -> Cc2(Ac1(Id0)) + * + * 0*: Inherited from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test19() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ac1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ac1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(Aa1(I)) -> Cc2(Aa1(Id0)) + * + * 0*: Inherited from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test20() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Aa1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Aa1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(A(I)) -> Cc2(Ac1(Id0)) + * + * 0*: Inherited from A (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test21() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(I))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Id0))", "A", "I"); + assertLinkage("C", "A1", "A1", "C2"); + } + + /* + * Cc2(J(Id0)) -> Cc2(Jd1(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test22() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Id0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(J(Ia0)) -> Cc2(Jd1(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test23() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Ia0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(Jd1(I)) -> Cc2(Jd1(Id0)) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test24() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Jd1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Jd1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(Ja1(I)) -> Cc2(Ja1(Id0)) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test25() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ja1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ja1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(J(I)) -> Cc2(Jd1(Id0)) + * + * 0*: Inherited default from J (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test26() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(I))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Id0))", "J", "I"); + assertLinkage("C", "J1", "J1", "C2"); + } + + /* + * C(Ac1, I) -> C(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test27() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac1,I)"); + assertLinkage("C", LINKAGE_ERROR, "A1"); + recompileSpec("C(Ac1,Id0)", "I"); + assertLinkage("C", "I0", "A1"); + } + + /* + * C(A, Id0) -> C(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test28() throws IOException, ReflectiveOperationException { + compileSpec("C(A,Id0)"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac1,Id0)", "A"); + assertLinkage("C", "I0", "A1"); + } + + /* + * C(A, I) -> C(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test29() throws IOException, ReflectiveOperationException { + compileSpec("C(A,I)"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Ac1,Id0)", "A", "I"); + assertLinkage("C", "I0", "A1"); + } + + /* + * Cc2(Ac1, I) -> Cc2(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test30() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ac1,I)"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ac1,Id0)", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(Aa1, I) -> Cc2(Aa1, Id0) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test31() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Aa1,I)"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Aa1,Id0)", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(A, Id0) -> Cc2(Ac1, Id0) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test32() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A,Id0)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1,Id0)", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A, Ia0) -> Cc2(Ac1, Ia0) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test33() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A,Ia0)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1,Ia0)", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A, I) -> Cc2(Ac1, Id0) + * + * 0*: Inherited from A + * 1*: Inherited default from I + * 2: Declared in C + */ + public void test34() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A,I)"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1,Id0)", "A", "I"); + assertLinkage("C", "I0", "A1", "C2"); + } + + /* + * Cc2(Id0, J) -> Cc2(Id0, Jd1) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test35() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Id0,J)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Id0,Jd1)", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(Ia0, J) -> Cc2(Ia0, Jd1) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test36() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ia0,J)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ia0,Jd1)", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(I, J) -> Cc2(Id0, Jd1) + * + * 0*: Inherited default from I + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test37() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(I,J)"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Id0,Jd1)", "I", "J"); + assertLinkage("C", "I0", "J1", "C2"); + } + + /* + * C(A(Id0), J(Id0)) -> C(Ac1(Id0), J(Id0)) + * + * 0: Inherited default from I + * 0*: Inherited from A (through bridge) + * 1*: Inherited from A + */ + public void test38() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac1(Id0),J(Id0))", "A"); + assertLinkage("C", "A1", "A1"); + } + + /* + * C(A(Id0), J(Id0)) -> C(A(Id0), Jd1(Id0)) + * + * 0: Inherited default from I + * 0: Inherited default from J (through bridge) + * 1*: Inherited default from J + */ + public void test39() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(A(Id0),Jd1(Id0))", "J"); + assertLinkage("C", "J1", "J1"); + } + + /* + * C(A(Id0), J(Id0)) -> C(Ac2(Id0), Jd1(Id0)) + * + * 0: Inherited default from I + * 0*: Inherited from A (new bridge in A beats new bridge in J) + * 1*: Inherited default from J + * 2: Inherited from A + */ + public void test40() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac2(Id0),Jd1(Id0))", "A", "J"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(J(Id0), K(Id0)) -> C(Jd1(Id0), K(Id0)) + * + * 0: Inherited from I + * 0*: Inherited default from J (through bridge) + * 1: Inherited default from J + */ + public void test41() throws IOException, ReflectiveOperationException { + compileSpec("C(J(Id0),K(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Jd1(Id0),K(Id0))", "J"); + assertLinkage("C", "J1", "J1"); + } + + /* + * C(Ac2(Id0), J(Id0)) -> C(Ac2(Id0), Jd1(Id0)) + * + * 0: Inherited from A (bridge in A beats new bridge in J) + * 1*: Inherited default from J + * 2: Inherited from A + */ + public void test42() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac2(Id0),J(Id0))"); + assertLinkage("C", "A2", LINKAGE_ERROR, "A2"); + recompileSpec("C(Ac2(Id0),Jd1(Id0))", "J"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(Ac2(Ia0), J(Ia0)) -> C(Ac2(Ia0), Jd1(Ia0)) + * + * 0: Inherited from A (bridge in A beats new bridge in J) + * 1*: Inherited default from J + * 2: Inherited from A + */ + public void test43() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac2(Ia0),J(Ia0))"); + assertLinkage("C", "A2", LINKAGE_ERROR, "A2"); + recompileSpec("C(Ac2(Ia0),Jd1(Ia0))", "J"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(A(Id0), Jd1(Id0)) -> C(Ac2(Id0), Jd1(Id0)) + * + * 0: Inherited from J + * 0*: Inherited from A (new bridge in A beats bridge in J) + * 1: Inherited default from J + * 2*: Inherited from A + */ + public void test44() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),Jd1(Id0))"); + assertLinkage("C", "J1", "J1", LINKAGE_ERROR); + recompileSpec("C(Ac2(Id0),Jd1(Id0))", "A"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(A(Ia0), Jd1(Ia0)) -> C(Ac2(Ia0), Jd1(Ia0)) + * + * 0: Inherited from J + * 0*: Inherited from A (new bridge in A beats bridge in J) + * 1: Inherited default from J + * 2*: Inherited from A + */ + public void test45() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Ia0),Jd1(Ia0))"); + assertLinkage("C", "J1", "J1", LINKAGE_ERROR); + recompileSpec("C(Ac2(Ia0),Jd1(Ia0))", "A"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * Cc2(A(Id0), J(Id0)) -> Cc2(Ac1(Id0), J(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test46() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Id0),J(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Id0),J(Id0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A(Ia0), J(Ia0)) -> Cc2(Ac1(Ia0), J(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test47() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Ia0),J(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Ia0),J(Ia0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A(Id0), J(Id0)) -> Cc2(A(Id0), Jd1(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test48() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Id0),J(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(A(Id0),Jd1(Id0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(A(Ia0), J(Ia0)) -> Cc2(A(Ia0), Jd1(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test49() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Ia0),J(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(A(Ia0),Jd1(Ia0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + + /* + * Cc3(A(Id0), J(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0)) + * + * 0: Bridge in C + * 1*: Inherited from A + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test50() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Id0),J(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "A", "J"); + assertLinkage("C", "C3", "A1", "J2", "C3"); + } + + /* + * Cc3(A(Ia0), J(Ia0)) -> Cc3(Ac1(Ia0), Jd2(Ia0)) + * + * 0: Bridge in C + * 1*: Inherited from A + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test51() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Ia0),J(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "A", "J"); + assertLinkage("C", "C3", "A1", "J2", "C3"); + } + + /* + * Cc2(J(Id0), K(Id0)) -> Cc2(Jd1(Id0), K(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test52() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Id0),K(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Id0),K(Id0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(J(Ia0), K(Ia0)) -> Cc2(Jd1(Ia0), K(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test53() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Ia0),K(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Ia0),K(Ia0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc3(J(Id0), K(Id0)) -> Cc3(Jd1(Id0), Kd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test54() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(J(Id0),K(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "J", "K"); + assertLinkage("C", "C3", "J1", "K2", "C3"); + } + + /* + * Cc3(J(Ia0), K(Ia0)) -> Cc3(Jd1(Ia0), Kd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test55() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(J(Ia0),K(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "J", "K"); + assertLinkage("C", "C3", "J1", "K2", "C3"); + } + + /* + * Cc3(Ac1(Id0), J(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test56() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Ac1(Id0),J(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(Ac1(Ia0), J(Ia0)) -> Cc3(Ac1(Ia0), Jd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test57() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Ac1(Ia0),J(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(Aa1(Id0), J(Id0)) -> Cc3(Aa1(Id0), Jd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test58() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Aa1(Id0),J(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Aa1(Id0),Jd2(Id0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(Aa1(Ia0), J(Ia0)) -> Cc3(Aa1(Ia0), Jd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test59() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Aa1(Ia0),J(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Aa1(Ia0),Jd2(Ia0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(A(Id0), Jd2(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test60() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Id0),Jd2(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(A(Im0), Jd2(Ia0)) -> Cc3(Ac1(Im0), Jd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test61() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Ia0),Jd2(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(A(Im0), Ja2(Id0)) -> Cc3(Ac1(Id0), Ja2(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test62() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Id0),Ja2(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Id0),Ja2(Id0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(A(Im0), Ja2(Ia0)) -> Cc3(Ac1(Ia0), Ja2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test63() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Ia0),Ja2(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Ia0),Ja2(Ia0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(Jd1(Id0), K(Id0)) -> Cc3(Jd1(Id0), Kd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test64() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Id0),K(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + /* + * Cc3(Jd1(Ia0), K(Ia0)) -> Cc3(Jd1(Ia0), Kd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test65() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Ia0),K(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + /* + * Cc3(Ja1(Id0), K(Id0)) -> Cc3(Ja1(Id0), Kd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test66() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Id0),K(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + /* + * Cc3(Ja1(Ia0), K(Ia0)) -> Cc3(Ja1(Ia0), Kd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test67() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Ia0),K(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + // Dan's set A + public void testA1() throws IOException, ReflectiveOperationException { + compileSpec("C(Id0)"); + assertLinkage("C", "I0"); + } + + public void testA2() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0))"); + assertLinkage("C", "I0"); + } + + public void testA3() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J)"); + assertLinkage("C", "I0"); + } + + public void testA4() throws IOException, ReflectiveOperationException { + compileSpec("D(C(Id0),Jd0(Id0))"); + assertLinkage("D", "J0"); + assertLinkage("C", "I0"); + } + /* Doesn't compile + public void testA5() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),Jd0)"); + assertLinkage("C", "J0"); + assertLinkage("A", "I0"); + } + */ + /* Doesn't compile + public void testA6() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0,Jd0))"); + assertLinkage("C", "J0"); + assertLinkage("A", "I0"); + } + */ + /* Doesn't compile + public void testA7() throws IOException, ReflectiveOperationException { + compileSpec("C(A(I0,Jd0))"); + assertLinkage("C", "J0"); + assertLinkage("A", "I0"); + } + */ + public void testA8() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac0(Id0))"); + assertLinkage("C", "A0"); + } + + /* Doesn't compile + public void testA9() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac0,Id0)"); + assertLinkage("C", "A0"); + } + */ + + // Dan's set B + + /* B1 can't be done, needs a second concrete class D + public void testB1() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Dc0)"); + assertLinkage("C", "C1", "C1"); + assertLinkage("D", "A0", LINKAGE_ERROR); + } + */ + + public void testB2() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Ac0)"); + assertLinkage("C", "C1", "C1"); + } + + //??? B3 seems to suggest that we should create an abstract class + //public void testB3() throws IOException, ReflectiveOperationException { + // compileSpec("Ba1(Cc0)"); + // assertLinkage("B", "C0", "A1"); + //} + + // B4 needs too many classes + + public void testB5() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Aa1(Id0))"); + assertLinkage("C", "C1", "C1"); + } + + public void testB6() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac1(Id0))"); + assertLinkage("C", "A1", "A1"); + } + + public void testB7() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Id0)"); + assertLinkage("C", "C1", "C1"); + } + + public void testB8() throws IOException, ReflectiveOperationException { + compileSpec("C(Jd1(Id0))"); + assertLinkage("C", "J1", "J1"); + } + + // B9 needs too many classes + + // The rest of Dan's tests need generics +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/ComboTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/ComboTestBase.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,273 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import com.sun.tools.javac.util.Pair; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.Test; + +import java.io.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/** + * ComboTestBase + * + * @author Brian Goetz + */ +public abstract class ComboTestBase> extends JavacTemplateTestBase { + private final static Map metadataMap = new HashMap<>(); + private final static boolean DEBUG_PROPERTY_SET = !System.getProperty("combo.debug", "").equals(""); + private final static long timestamp = System.currentTimeMillis(); + private final static Map, /* data */ Map>> debugInfo + = new HashMap<>(); + + protected final ComboTestMetadata metadata; + protected final Object[] comboArgs; + private boolean debugOnly = false; + + // This class cannot have a constructor; it interferes with testng's ability to find the factory method + //in subclasses. Anything that would be done by a constructor should insteady be done by init blocks + //or the pseudoConstructor() method. + + /* init */ { + metadata = getMetadata((Class) getClass()); + comboArgs = new Object[metadata.dimensions.length]; + } + + /** + * This method is meant to be called from an @Factory method in the subclass, passing its own class literal + * as the clazz argument. It will introspect over the provided class, find the dimension variables, and + * generate the combinatorial explosion of test cases. (It consults shouldSkip() to determine if a particular + * combination should be skipped.) + */ + public static Object[] factory(Class clazz) throws ReflectiveOperationException { + int index = 0; + try { + ComboTestMetadata md = getMetadata(clazz); + List list = new ArrayList<>(); + for (Object[] args : md.makeLoop()) { + T instance = md.makeInstance(args); + if (!instance.shouldSkip()) { + instance.pseudoConstructor(args); + list.add(instance); + instance.templates.put("__INDEX__", instance.new StringTemplate(Integer.toString(index++))); + if (DEBUG_PROPERTY_SET) + ((ComboTestBase) instance).debugOnly = true; + } + } + + return list.toArray(); + } catch (Throwable t) { + // This is a needed annoyance; TestNG swallows exception data from exceptions thrown from @Factory methods + t.printStackTrace(System.err); + t.printStackTrace(System.out); + throw t; + } + } + + /** For debugging of test cases -- sets tests into debug-only mode, where we print out the instantiations of + * the dimension variables and the templates. + */ + public static Object[] debugFactory(Class clazz) throws ReflectiveOperationException { + Object[] results = factory(clazz); + for (Object o : results) + ((ComboTestBase) o).debugOnly = true; + return results; + } + + private static> ComboTestMetadata getMetadata(Class clazz) { + try { + ComboTestMetadata md = metadataMap.get(clazz); + if (md == null) { + md = new ComboTestMetadata(clazz); + metadataMap.put(clazz, md); + } + return md; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + // Should be private, but can't be + void pseudoConstructor(Object[] args) throws ReflectiveOperationException { + System.arraycopy(args, 0, comboArgs, 0, args.length); + } + + private void addTemplates() throws ReflectiveOperationException { + for (int i=0; i m : metadata.templateFields) + addTemplate(m.name, asTemplate(m.member.get(this))); + + for (ComboTestMetadata.TemplateMember m : metadata.templateMethods) + addTemplate(m.name, asTemplate(m.member.invoke(this))); + } + + private void addAllSourceFiles() throws ReflectiveOperationException { + for (ComboTestMetadata.TemplateMember m : metadata.sourceFields) + addSourceFile(m.name, asTemplate(m.member.get(this))); + + for (ComboTestMetadata.TemplateMember m : metadata.sourceMethods) + addSourceFile(m.name, asTemplate(m.member.invoke(this))); + } + + private void addSourceFiles(String group) throws ReflectiveOperationException { + for (ComboTestMetadata.TemplateMember m : metadata.sourceFields) + if (group.equals(m.annotation.group())) + addSourceFile(m.name, asTemplate(m.member.get(this))); + + for (ComboTestMetadata.TemplateMember m : metadata.sourceMethods) + if (group.equals(m.annotation.group())) + addSourceFile(m.name, asTemplate(m.member.invoke(this))); + } + + /** + * Should the current combination of inputs be skipped? Default implementation returns false for + * all combinations (indicating all combinations are valid.) + */ + protected boolean shouldSkip() { + return false; + } + + protected boolean shouldRun() { + return false; + } + + /** + * Called after test() compiles, allowing subclass an opportunity to examine diagonstics and assert + * their properties. Default implementation calls assertCompileSucceeded(). + * @param group + */ + protected void postCompile(String group) { + assertCompileSucceeded(); + } + + protected String[] getCompileOptions(String group) { + return new String[0]; + } + + /** + * Called before test() compiles, allowing subclass an opportunity to set compilation options. + */ + protected void preCompile(String group) { + } + + @Test + public void test() throws Exception { + if (debugOnly) { + addTemplates(); + addAllSourceFiles(); + System.out.println("Test case : " + getTestCaseDescription()); + for (Pair e : sourceFiles) + System.out.println("Source file " + e.fst + ": " + e.snd); + + String testFile = getClass().getName(); + Map, Map> testCaseMap = debugInfo.get(testFile); + if (testCaseMap == null) { + testCaseMap = new HashMap<>(); + debugInfo.put(testFile, testCaseMap); + } + + Map comboKeys = new HashMap<>(); + for (int i=0; i data = new HashMap<>(); + int count = 0; + for (Pair e : sourceFiles) { + count++; + data.put("File." + count + ".FileName", e.fst); + data.put("File." + count + ".Source", e.snd.toString()); + data.put("File." + count + ".Group", ""); + data.put("File." + count + ".CompileOptions", compileOptions); + } + Object prev = testCaseMap.put(comboKeys, data); + if (prev != null) + fail(String.format("Duplicate key for file %s, keys %s", testFile, comboKeys.toString())); + } + else { + boolean generate = shouldRun(); + boolean errors = false; + List files = new ArrayList<>(); + List groupsReversed = new ArrayList<>(metadata.groups); + Collections.reverse(groupsReversed); + for (String g : groupsReversed) { + addTemplates(); + addSourceFiles(g); + preCompile(g); + addCompileOptions(getCompileOptions(g)); + for (File f : files) + addClassPath(f); + files.add(0, compile(generate)); + errors |= diags.errorsFound(); + postCompile(g); + reset(); + } + + if (generate && !errors) { + run(loadClass("Main", files.toArray(new File[files.size()]))); + } + } + } + + @AfterSuite + public void dumpDebug() throws IOException { + if (DEBUG_PROPERTY_SET) { + for (Map.Entry, Map>> f : debugInfo.entrySet()) { + File out = new File(String.format("ComboLog-%s-%d.ser", f.getKey(), timestamp)); + try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(out))) { + os.writeObject(f.getValue()); + } + } + } + } + + protected void run(Class clazz) throws ReflectiveOperationException { + assertTrue(clazz != null); + } + + protected String getTestCaseDescription() { + StringBuilder sb = new StringBuilder(); + sb.append("ComboTest[").append(getClass().getName()).append(": "); + for (int i=0; i files = new ArrayList<>(); + public static boolean compare; + + private static void compareFiles(String s1, String s2) throws IOException, ClassNotFoundException { + Map, + /* data */ Map> f1, f2; + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s1))) { + f1 = (Map, Map>) ois.readObject(); + } + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s2))) { + f2 = (Map, Map>) ois.readObject(); + } + + if (f1.size() != f2.size()) + System.out.printf("Number of test cases differ: %d, %d%n", f1.size(), f2.size()); + + if (!f1.keySet().equals(f2.keySet())) { + System.out.printf("Test cases differ%n"); + for (Map k : f1.keySet()) { + if (!f2.containsKey(k)) + System.out.printf("Only in file 1: test case %s%n", k); + } + for (Map k : f2.keySet()) { + if (!f1.containsKey(k)) + System.out.printf("Only in file 2: test case %s%n", k); + } + } + + for (Map k : f1.keySet()) { + if (!f2.keySet().contains(k)) + continue; + Map d1 = f1.get(k); + Map d2 = f2.get(k); + if (!d1.equals(d2)) { + System.out.printf("Test case %s%n", k); + for (String s : d1.keySet()) + if (!d2.containsKey(s)) + System.out.printf(" Only in file 1: key %s%n", s); + else { + if (!d1.get(s).equals(d2.get(s))) { + System.out.printf(" Key values differ for key %s: [%s] [%s]%n", s, d1.get(s), d2.get(s)); + } + } + for (String s : d2.keySet()) + if (!d1.containsKey(s)) + System.out.printf(" Only in file 2: key %s%n", s); + System.out.println(); + } + } + } + + private static void dumpFile(String s) throws IOException, ClassNotFoundException { + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s))) { + Map, + /* data */ Map> debugInfo; + + debugInfo = (Map, Map>) ois.readObject(); + System.out.printf("%d test cases%n%n", debugInfo.size()); + for (Map.Entry, Map> e : debugInfo.entrySet()) { + System.out.println("Test case: " + e.getKey()); + for (Map.Entry de : new TreeMap<>(e.getValue()).entrySet()) + System.out.printf(" %s = %s%n", de.getKey(), de.getValue()); + System.out.println(); + } + } + + } + + public static void main(String[] args) throws IOException, ClassNotFoundException { + for (String a : args) { + if (a.equals("-c")) + compare = true; + else if (a.startsWith("-")) + usage(); + else + files.add(a); + } + + if (compare) { + if (files.size() != 2) + usage(); + compareFiles(files.get(0), files.get(1)); + } + else { + for (String f : files) + dumpFile(f); + } + } + + public static void usage() { + System.out.println("Usage: ComboTestDebug [ -c ] files..."); + System.exit(0); + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/ComboTestMetadata.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/ComboTestMetadata.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,190 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.*; + +/** + * ComboTestMetadata + * + * @author Brian Goetz*/ +class ComboTestMetadata { + public final Class clazz; + public final Constructor ctor; + public final List> templateFields = new ArrayList<>(); + public final List> templateMethods = new ArrayList<>(); + public final List> sourceFields = new ArrayList<>(); + public final List> sourceMethods = new ArrayList<>(); + public final Set groups = new TreeSet<>(); + public final Dimension[] dimensions; + + public ComboTestMetadata(Class clazz) throws ReflectiveOperationException { + this.clazz = clazz; + Constructor[] constructors = clazz.getConstructors(); + ctor = (constructors.length == 1 && constructors[0].getParameterTypes().length > 0) ? constructors[0] : null; + + Map tmpDimFields = new LinkedHashMap<>(); + for (Field f : clazz.getDeclaredFields()) { + TemplateVar template = f.getAnnotation(TemplateVar.class); + if (template != null) { + if (!Template.class.isAssignableFrom(f.getType()) && !String.class.isAssignableFrom(f.getType())) + throw new AssertionError(String.format("Found @TemplateVar on field %s whose type is not Template or String", f)); + f.setAccessible(true); + templateFields.add(new TemplateMember<>(template.value(), template, f)); + } + + SourceFile source = f.getAnnotation(SourceFile.class); + if (source != null) { + if (!Template.class.isAssignableFrom(f.getType()) && !String.class.isAssignableFrom(f.getType())) + throw new AssertionError(String.format("Found @SourceFile on field %s whose type is not Template or String", f)); + f.setAccessible(true); + sourceFields.add(new TemplateMember<>(source.value(), source, f)); + groups.add(source.group()); + } + + DimensionVar dim = f.getAnnotation(DimensionVar.class); + if (dim != null) + tmpDimFields.put(dim, f); + } + + for (Method m : clazz.getDeclaredMethods()) { + TemplateVar template = m.getAnnotation(TemplateVar.class); + if (template != null) { + if (!Template.class.isAssignableFrom(m.getReturnType()) && !String.class.isAssignableFrom(m.getReturnType())) + throw new AssertionError(String.format("Found @TemplateVar on method %s whose return type is not Template or String", m)); + m.setAccessible(true); + templateMethods.add(new TemplateMember<>(template.value(), template, m)); + } + + SourceFile source = m.getAnnotation(SourceFile.class); + if (source != null) { + if (!Template.class.isAssignableFrom(m.getReturnType()) && !String.class.isAssignableFrom(m.getReturnType())) + throw new AssertionError(String.format("Found @SourceFile on method %s whose return type is not Template or String ", m)); + sourceMethods.add(new TemplateMember<>(source.value(), source, m)); + groups.add(source.group()); + } + } + + if (constructors.length > 1) + throw new AssertionError(String.format("Multiple constructors for class %s", clazz)); + else if (ctor != null && !tmpDimFields.isEmpty()) + throw new AssertionError(String.format("Class %s has both constructors and fields with @DimensionVar", clazz)); + else if (constructors.length == 0 && tmpDimFields.isEmpty()) + throw new AssertionError(String.format("Class %s has neither constructors nor fields with @DimensionVar", clazz)); + else if (ctor != null) { + Class[] argTypes = ctor.getParameterTypes(); + Annotation[][] paramAnnotations = ctor.getParameterAnnotations(); + dimensions = new Dimension[argTypes.length]; + for (int i = 0, argTypesLength = argTypes.length; i < argTypesLength; i++) { + DimensionVar cd = null; + for (Annotation a : paramAnnotations[i]) + if (a instanceof DimensionVar) { + cd = (DimensionVar) a; + break; + } + if (cd == null) + throw new AssertionError(String.format("Parameter %d of constructor %s does not have @DimensionVar annotation", i, ctor)); + dimensions[i] = new Dimension(cd, argTypes[i], String.format("Parameter %d of constructor %s", i, ctor)); + } + } + else { + dimensions = new Dimension[tmpDimFields.size()]; + int i = 0; + for (Map.Entry e : tmpDimFields.entrySet()) + dimensions[i++] = new Dimension(e.getKey(), e.getValue()); + } + } + + public T makeInstance(Object[] args) throws ReflectiveOperationException { + if (ctor != null) + return ctor.newInstance(args); + else { + T t = clazz.newInstance(); + for (int i=0; i< dimensions.length; i++) + dimensions[i].field.set(t, args[i]); + return t; + } + } + + public SyntheticLoop makeLoop() { + int n = dimensions.length; + Object[][] dimValues = new Object[n][]; + for (int i=0; i paramType, String descr) throws ReflectiveOperationException { + field = null; + name = dv.value(); + values = getValues(dv, paramType, descr); + } + + private Object[] getValues(DimensionVar dv, Class clazz, String descr) throws ReflectiveOperationException { + if (Enum.class.isAssignableFrom(clazz) && Template.class.isAssignableFrom(clazz)) { + Method m = clazz.getDeclaredMethod("values"); + m.setAccessible(true); + return (Template[]) m.invoke(null); + } + else if (int.class.isAssignableFrom(clazz)) { + Object[] ts = new Object[dv.rangeUpper() - dv.rangeLower() + 1]; + for (int i=dv.rangeLower(); i <= dv.rangeUpper(); i++) + ts[i-dv.rangeLower()] = i; + return ts; + } + else + throw new AssertionError(String.format("Invalid type %s for %s", clazz.getName(), descr)); + } + } + + static class TemplateMember { + public final String name; + public final A annotation; + public final M member; + + TemplateMember(String name, A annotation, M member) { + this.name = name; + this.annotation = annotation; + this.member = member; + } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/Diagnostics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/Diagnostics.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,84 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import java.util.ArrayList; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +/** +* A container for compiler diagnostics, separated into errors and warnings, + * used by JavacTemplateTestBase. + * + * @author Brian Goetz +*/ +public class Diagnostics implements javax.tools.DiagnosticListener { + + protected List> diags = new ArrayList<>(); + protected boolean foundErrors = false; + + public void report(Diagnostic diagnostic) { + diags.add(diagnostic); + foundErrors = foundErrors || diagnostic.getKind() == Diagnostic.Kind.ERROR; + } + + /** Were there any errors found? */ + public boolean errorsFound() { + return foundErrors; + } + + /** Get all diagnostic keys */ + public List keys() { + return diags.stream() + .map(Diagnostic::getCode) + .collect(toList()); + } + + /** Do the diagnostics contain the specified error key? */ + public boolean containsErrorKey(String key) { + return diags.stream() + .filter(d -> d.getKind() == Diagnostic.Kind.ERROR) + .anyMatch(d -> d.getCode().equals(key)); + } + + /** Get the error keys */ + public List errorKeys() { + return diags.stream() + .filter(d -> d.getKind() == Diagnostic.Kind.ERROR) + .map(Diagnostic::getCode) + .collect(toList()); + } + + public String toString() { return keys().toString(); } + + /** Clear all diagnostic state */ + public void reset() { + diags.clear(); + foundErrors = false; + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/DimensionVar.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/DimensionVar.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,40 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** +* DimensionVar +*/ +@Retention(RetentionPolicy.RUNTIME) +@java.lang.annotation.Target({ElementType.PARAMETER, ElementType.FIELD}) +public @interface DimensionVar { + String value(); + int rangeLower() default 0; + int rangeUpper() default 0; +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/JavacTemplateTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/JavacTemplateTestBase.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,364 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.util.Pair; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.testng.Assert.fail; + +/** + * Base class for template-driven TestNG javac tests that support on-the-fly + * source file generation, compilation, classloading, execution, and separate + * compilation. + * + *

Manages a set of templates (which have embedded tags of the form + * {@code #\{NAME\}}), source files (which are also templates), and compile + * options. Test cases can register templates and source files, cause them to + * be compiled, validate whether the set of diagnostic messages output by the + * compiler is correct, and optionally load and run the compiled classes. + * + * @author Brian Goetz + */ +@Test +public abstract class JavacTemplateTestBase { + private static final Set suiteErrors = Collections.synchronizedSet(new HashSet<>()); + private static final AtomicInteger counter = new AtomicInteger(); + private static final File root = new File(System.getProperty("user.dir"), "gen"); + private static final File nullDir = new File(System.getProperty("user.dir"), "empty"); + + protected final Map templates = new HashMap<>(); + protected final Diagnostics diags = new Diagnostics(); + protected final List> sourceFiles = new ArrayList<>(); + protected final List compileOptions = new ArrayList<>(); + protected final List classpaths = new ArrayList<>(); + protected final Template.Resolver defaultResolver = new MapResolver(templates); + + private Template.Resolver currentResolver = defaultResolver; + + /** Add a template with a specified name */ + protected void addTemplate(String name, Template t) { + templates.put(name, t); + } + + /** Add a template with a specified name */ + protected void addTemplate(String name, String s) { + templates.put(name, new StringTemplate(s)); + } + + /** Add a source file */ + protected void addSourceFile(String name, Template t) { + sourceFiles.add(new Pair<>(name, t)); + } + + /** Add a File to the class path to be used when loading classes; File values + * will generally be the result of a previous call to {@link #compile()}. + * This enables testing of separate compilation scenarios if the class path + * is set up properly. + */ + protected void addClassPath(File path) { + classpaths.add(path); + } + + /** + * Add a set of compilation command-line options + */ + protected void addCompileOptions(String... opts) { + Collections.addAll(compileOptions, opts); + } + + /** Reset the compile options to the default (empty) value */ + protected void resetCompileOptions() { compileOptions.clear(); } + + /** Remove all templates */ + protected void resetTemplates() { templates.clear(); } + + /** Remove accumulated diagnostics */ + protected void resetDiagnostics() { diags.reset(); } + + /** Remove all source files */ + protected void resetSourceFiles() { sourceFiles.clear(); } + + /** Remove registered class paths */ + protected void resetClassPaths() { classpaths.clear(); } + + // Before each test method, reset everything + @BeforeMethod + public void reset() { + resetCompileOptions(); + resetDiagnostics(); + resetSourceFiles(); + resetTemplates(); + resetClassPaths(); + } + + // After each test method, if the test failed, capture source files and diagnostics and put them in the log + @AfterMethod + public void copyErrors(ITestResult result) { + if (!result.isSuccess()) { + suiteErrors.addAll(diags.errorKeys()); + + List list = new ArrayList<>(); + Collections.addAll(list, result.getParameters()); + list.add("Test case: " + getTestCaseDescription()); + for (Pair e : sourceFiles) + list.add("Source file " + e.fst + ": " + e.snd); + if (diags.errorsFound()) + list.add("Compile diagnostics: " + diags.toString()); + result.setParameters(list.toArray(new Object[list.size()])); + } + } + + @AfterSuite + // After the suite is done, dump any errors to output + public void dumpErrors() { + if (!suiteErrors.isEmpty()) + System.err.println("Errors found in test suite: " + suiteErrors); + } + + /** + * Get a description of this test case; since test cases may be combinatorially + * generated, this should include all information needed to describe the test case + */ + protected String getTestCaseDescription() { + return this.toString(); + } + + /** Assert that all previous calls to compile() succeeded */ + protected void assertCompileSucceeded() { + if (diags.errorsFound()) + fail("Expected successful compilation"); + } + + /** + * If the provided boolean is true, assert all previous compiles succeeded, + * otherwise assert that a compile failed. + * */ + protected void assertCompileSucceededIff(boolean b) { + if (b) + assertCompileSucceeded(); + else + assertCompileFailed(); + } + + /** Assert that a previous call to compile() failed */ + protected void assertCompileFailed() { + if (!diags.errorsFound()) + fail("Expected failed compilation"); + } + + /** Assert that a previous call to compile() failed with a specific error key */ + protected void assertCompileFailed(String message) { + if (!diags.errorsFound()) + fail("Expected failed compilation: " + message); + } + + /** Assert that a previous call to compile() failed with all of the specified error keys */ + protected void assertCompileErrors(String... keys) { + if (!diags.errorsFound()) + fail("Expected failed compilation"); + for (String k : keys) + if (!diags.containsErrorKey(k)) + fail("Expected compilation error " + k); + } + + /** Convert an object, which may be a Template or a String, into a Template */ + protected Template asTemplate(Object o) { + if (o instanceof Template) + return (Template) o; + else if (o instanceof String) + return new StringTemplate((String) o); + else + return new StringTemplate(o.toString()); + } + + /** Compile all registered source files */ + protected void compile() throws IOException { + compile(false); + } + + /** Compile all registered source files, optionally generating class files + * and returning a File describing the directory to which they were written */ + protected File compile(boolean generate) throws IOException { + List files = new ArrayList<>(); + for (Pair e : sourceFiles) + files.add(new FileAdapter(e.fst, asTemplate(e.snd))); + return compile(classpaths, files, generate); + } + + /** Compile all registered source files, using the provided list of class paths + * for finding required classfiles, optionally generating class files + * and returning a File describing the directory to which they were written */ + protected File compile(List classpaths, boolean generate) throws IOException { + List files = new ArrayList<>(); + for (Pair e : sourceFiles) + files.add(new FileAdapter(e.fst, asTemplate(e.snd))); + return compile(classpaths, files, generate); + } + + private File compile(List classpaths, List files, boolean generate) throws IOException { + JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = systemJavaCompiler.getStandardFileManager(null, null, null); + if (classpaths.size() > 0) + fm.setLocation(StandardLocation.CLASS_PATH, classpaths); + JavacTask ct = (JavacTask) systemJavaCompiler.getTask(null, fm, diags, compileOptions, null, files); + if (generate) { + File destDir = new File(root, Integer.toString(counter.incrementAndGet())); + // @@@ Assert that this directory didn't exist, or start counter at max+1 + destDir.mkdirs(); + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); + ct.generate(); + return destDir; + } + else { + ct.analyze(); + return nullDir; + } + } + + /** Load the given class using the provided list of class paths */ + protected Class loadClass(String className, File... destDirs) { + try { + List list = new ArrayList<>(); + for (File f : destDirs) + list.add(new URL("file:" + f.toString().replace("\\", "/") + "/")); + return Class.forName(className, true, new URLClassLoader(list.toArray(new URL[list.size()]))); + } catch (ClassNotFoundException | MalformedURLException e) { + throw new RuntimeException("Error loading class " + className, e); + } + } + + /** An implementation of Template which is backed by a String */ + protected class StringTemplate implements Template { + protected final String template; + + public StringTemplate(String template) { + this.template = template; + } + + public String expand(String selector) { + return Behavior.expandTemplate(template, currentResolver); + } + + public String toString() { + return expand(""); + } + + public StringTemplate with(final String key, final String value) { + return new StringTemplateWithResolver(template, new KeyResolver(key, value)); + } + + } + + /** An implementation of Template which is backed by a String and which + * encapsulates a Resolver for resolving embedded tags. */ + protected class StringTemplateWithResolver extends StringTemplate { + private final Resolver localResolver; + + public StringTemplateWithResolver(String template, Resolver localResolver) { + super(template); + this.localResolver = localResolver; + } + + @Override + public String expand(String selector) { + Resolver saved = currentResolver; + currentResolver = new ChainedResolver(currentResolver, localResolver); + try { + return super.expand(selector); + } + finally { + currentResolver = saved; + } + } + + @Override + public StringTemplate with(String key, String value) { + return new StringTemplateWithResolver(template, new ChainedResolver(localResolver, new KeyResolver(key, value))); + } + } + + /** A Resolver which uses a Map to resolve tags */ + private class KeyResolver implements Template.Resolver { + private final String key; + private final String value; + + public KeyResolver(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public Template lookup(String k) { + return key.equals(k) ? new StringTemplate(value) : null; + } + } + + private class FileAdapter extends SimpleJavaFileObject { + private final String filename; + private final Template template; + + public FileAdapter(String filename, Template template) { + super(URI.create("myfo:/" + filename), Kind.SOURCE); + this.template = template; + this.filename = filename; + } + + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return toString(); + } + + public String toString() { + return Template.Behavior.expandTemplate(template.expand(filename), defaultResolver); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/SeparateCompilationComboTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/SeparateCompilationComboTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,66 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import org.testng.annotations.Factory; + +import java.lang.reflect.Method; + +import static org.testng.Assert.assertEquals; + +/** + * SeparateCompilationComboTest + */ +public class SeparateCompilationComboTest extends ComboTestBase { + @Factory + public static Object[] testCombo() throws Exception { + return factory(SeparateCompilationComboTest.class); + } + + @DimensionVar("FOO") Dummy dummy; + + @SourceFile(value="Main.java", group="B") String a2 = "public class Main { public String main() { return Other.b(); } }"; + @SourceFile(value="Other.java", group="B") String b2 = "public class Other { public static String b() { return \"1\"; } }"; + @SourceFile(value="Other.java", group="A") String b1 = "public class Other { public static String b() { return \"2\"; } }"; + + @Override + protected boolean shouldRun() { + return true; + } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Object obj = clazz.newInstance(); + Method m = clazz.getMethod("main"); + String result = (String) m.invoke(obj); + assertEquals("2", result); + } + + static enum Dummy implements Template { + A(); + + public String expand(String selector) { return toString(); } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/SeparateCompilationComboTest2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/SeparateCompilationComboTest2.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,69 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import org.testng.annotations.Factory; + +import java.lang.reflect.Method; + +import static org.testng.Assert.assertEquals; + +/** + * SeparateCompilationComboTest2 + */ +public class SeparateCompilationComboTest2 extends ComboTestBase { + @Factory + public static Object[] testCombo() throws Exception { + return factory(SeparateCompilationComboTest2.class); + } + + @DimensionVar("FOO") Dummy dummy; + + @SourceFile(value="Main.java", group="A" ) + String main = "public class Main { public String main() { return new B().x(); } }"; + @SourceFile(value="B.java", group="B" ) + String b = "public class B extends C { public String x() { return \"2\"; } }"; + @SourceFile(value="C.java", group="C" ) + String c = "public class C { public String x() { return \"1\"; } }"; + + @Override + protected boolean shouldRun() { + return true; + } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Object obj = clazz.newInstance(); + Method m = clazz.getMethod("main"); + String result = (String) m.invoke(obj); + assertEquals("2", result); + } + + static enum Dummy implements Template { + A(); + + public String expand(String selector) { return toString(); } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/SeparateCompilationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/SeparateCompilationTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,100 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * SeparateCompilationTest -- test of test framework to do separate compilation + */ +@Test +public class SeparateCompilationTest extends JavacTemplateTestBase { + + public void testCompletelySeparate() throws ReflectiveOperationException, IOException { + addSourceFile("A.java", new StringTemplate("public class A { public String a() throws Throwable { return Class.forName(\"B\").getName(); } }")); + File aFile = compile(true); + assertCompileSucceeded(); + reset(); + + addSourceFile("B.java", new StringTemplate("public class B { }")); + File bFile = compile(true); + assertCompileSucceeded(); + + Class clazz = loadClass("A", aFile, bFile); + Method m = clazz.getMethod("a"); + Object instance = clazz.newInstance(); + String x = (String) m.invoke(instance); + assertEquals("B", x); + } + + public void testIdenticalRecompile() throws ReflectiveOperationException, IOException { + addSourceFile("A.java", new StringTemplate("public class A { public String a() { return B.b(); } }")); + addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"1\"; } }")); + File aFile = compile(true); + assertCompileSucceeded(); + // Deleting B.class is not generally needed for test cases that simply replace B, but here we're testing the framework's ability to find B elsewhere + File bClass = new File(aFile, "B.class"); + assertTrue(bClass.exists()); + boolean deleted = bClass.delete(); + assertTrue(deleted); + reset(); + + addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"1\"; } }")); + File bFile = compile(true); + assertCompileSucceeded(); + + Class clazz = loadClass("A", bFile, aFile); + Method m = clazz.getMethod("a"); + Object instance = clazz.newInstance(); + String x = (String) m.invoke(instance); + assertEquals("1", x); + } + + public void testConsistentRecompile() throws ReflectiveOperationException, IOException { + addSourceFile("A.java", new StringTemplate("public class A { public String a() { return B.b(); } }")); + addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"1\"; } }")); + File aFile = compile(true); + assertCompileSucceeded(); + reset(); + + addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"2\"; } }")); + File bFile = compile(true); + assertCompileSucceeded(); + + Class clazz = loadClass("A", bFile, aFile); + Method m = clazz.getMethod("a"); + Object instance = clazz.newInstance(); + String x = (String) m.invoke(instance); + assertEquals("2", x); + } + +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/SourceFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/SourceFile.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,39 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * SourceFile + */ +@Retention(RetentionPolicy.RUNTIME) +@java.lang.annotation.Target({ElementType.METHOD, ElementType.FIELD}) +public @interface SourceFile { + String value(); + String group() default ""; +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/StackProcessingUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/StackProcessingUtils.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,81 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +/** + * Utility class for defining stack processing-like operations + * + * @author Maurizio Cimadamore + */ +public class StackProcessingUtils { + + /** + * interface representing a stack item - each item has an arity --- + * if arity is > 0 - then the item is an operator + */ + public interface StackItem> { + int arity(); + } + + /** + * A reducer takes an element of the stack and produces a result of a given + * type by applying the stack item to zero or more operands + */ + public interface StackReducer, T, O> { + T reduce(I item, T[] operands, O o); + Class resultToken(); + O reducerArg(I item, int i); + } + + static class StackResult { + T result; + int nextPos; + + StackResult(T result, int nextPos) { + this.result = result; + this.nextPos = nextPos; + } + } + + public static , T, O> T process(I[] elems, StackReducer reducer, O o) { + StackResult result = processInternal(0, elems, reducer, o); + assert result.nextPos == elems.length; + return result.result; + } + + private static , T, O> StackResult processInternal(int start, I[] elems, StackReducer reducer, O o) { + @SuppressWarnings("unchecked") + I head = elems[start]; + T[] operands = (T[])java.lang.reflect.Array.newInstance(reducer.resultToken(), head.arity()); + int nextPos = start + 1; + for (int i = 0 ; i < head.arity() ; i++) { + StackResult partialResult = processInternal(nextPos, elems, reducer, reducer.reducerArg(head, i)); + nextPos = partialResult.nextPos; + operands[i] = partialResult.result; + } + return new StackResult(reducer.reduce(head, operands, o), nextPos); + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/StringTemplateTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/StringTemplateTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,66 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * StringTemplateTest + */ +@Test +public class StringTemplateTest extends JavacTemplateTestBase { + private void assertTemplate(String expected, Template template) { + String result = template.expand(""); + assertEquals(result, expected, "for " + template); + } + + public void testStringTemplate() { + assertTemplate("XYZ", new StringTemplate("XYZ")); + addTemplate("NONE", "SOME"); + assertTemplate("SOME", new StringTemplate("#{NONE}")); + + addTemplate("A", "#{B}"); + addTemplate("B", "C"); + assertTemplate("C", new StringTemplate("#{A}")); + } + + public void testChainedTemplate() { + assertTemplate("A", new StringTemplate("#{A}").with("A", "A")); + assertTemplate("AB", new StringTemplate("#{A}#{B}").with("A", "A").with("B", "B")); + assertTemplate("TWO", new StringTemplate("#{A}").with("A", "ONE").with("A", "TWO")); + addTemplate("A", "BASE_A"); + addTemplate("AA", "#{A}"); + assertTemplate("FAKE_A", new StringTemplate("#{A}").with("A", "FAKE_A")); + assertTemplate("BASE_A", new StringTemplate("#{AA}")); + assertTemplate("FAKE_A", new StringTemplate("#{AA}").with("A", "FAKE_A")); + + addTemplate("X", new StringTemplate("#{A}").with("A", "intercepted")); + assertTemplate("intercepted", new StringTemplate("#{B}").with("B", "#{X}")); + addTemplate("Y", new StringTemplate("#{A}")); + assertTemplate("again", new StringTemplate("#{B}").with("B", "#{Y}").with("A", "again")); + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/SyntheticLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/SyntheticLoop.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,88 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.util.Iterator; + +/** + * SyntheticLoop -- exhaustively generate a set of combinations of variables + * + * @author Brian Goetz + */ +public class SyntheticLoop implements Iterable { + final int dimensions; + final int[] maxs; + final Object[][] values; + + /** Simple version -- generate the cartesian product of the provided sets of axis values */ + public SyntheticLoop(Object[][] dimValues) { + dimensions = dimValues.length; + maxs = new int[dimensions]; + values = new Object[dimensions][]; + for (int i=0; i iterator() { + return new Iterator() { + final int[] idxs = new int[dimensions]; + boolean hasNext = (dimensions > 0); + + public boolean hasNext() { + return hasNext; + } + + public Object[] next() { + Object[] ret = new Object[dimensions]; + for (int i=0; i it = sl.iterator(); + assertTrue(!it.hasNext()); + } + + private void assertSL(String expected, SyntheticLoop sl) { + StringBuilder sb = new StringBuilder(); + for (Object[] row : sl) { + for (Object o : row) { + sb.append(o); + } + sb.append(" "); + } + assertEquals(sb.toString(), expected); + } + + private void assertSL(int size, SyntheticLoop sl) { + int count = 0; + for (Object row : sl) { + ++count; + } + assertEquals(count, size); + } + + public void testSimple() { + Object[] abc = {"A", "B", "C"}; + assertSL("A B C ", new SyntheticLoop(new Object[][] {abc})); + assertSL("AA AB AC BA BB BC CA CB CC ", new SyntheticLoop(new Object[][] {abc, abc})); + assertSL(9, new SyntheticLoop(new Object[][] {abc, abc})); + assertSL(9, new SyntheticLoop(new Object[][] {abc, abc, new Object[] { "X" }})); + assertSL(27, new SyntheticLoop(new Object[][] {abc, abc, abc})); + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/Template.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/Template.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,114 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A template into which tags of the form {@code #\{KEY\}} or + * {@code #\{KEY.SUBKEY\}} can be expanded. + */ +public interface Template { + String expand(String selector); + + interface Resolver { + public Template lookup(String key); + } + + public static class Behavior { + /* Looks for expandable keys. An expandable key can take the form: + * #{MAJOR} + * #{MAJOR.MINOR} + * where MAJOR can be IDENTIFIER or IDENTIFIER[NUMERIC_INDEX] + * and MINOR can be an identifier + */ + private static final Pattern pattern = Pattern.compile("#\\{([A-Z_][A-Z0-9_]*(?:\\[\\d+\\])?)(?:\\.([A-Z0-9_]*))?\\}"); + + public static String expandTemplate(String template, final Map vars) { + return expandTemplate(template, new MapResolver(vars)); + } + + public static String expandTemplate(String template, Resolver res) { + CharSequence in = template; + StringBuffer out = new StringBuffer(); + while (true) { + boolean more = false; + Matcher m = pattern.matcher(in); + while (m.find()) { + String major = m.group(1); + String minor = m.group(2); + Template key = res.lookup(major); + if (key == null) + throw new IllegalStateException("Unknown major key " + major); + + String replacement = key.expand(minor == null ? "" : minor); + more |= pattern.matcher(replacement).find(); + m.appendReplacement(out, replacement); + } + m.appendTail(out); + if (!more) + return out.toString(); + else { + in = out; + out = new StringBuffer(); + } + } + } + + } +} + +class MapResolver implements Template.Resolver { + private final Map vars; + + public MapResolver(Map vars) {this.vars = vars;} + + public Template lookup(String key) { + return vars.get(key); + } +} + +class ChainedResolver implements Template.Resolver { + private final Template.Resolver upstreamResolver, thisResolver; + + public ChainedResolver(Template.Resolver upstreamResolver, Template.Resolver thisResolver) { + this.upstreamResolver = upstreamResolver; + this.thisResolver = thisResolver; + } + + public Template.Resolver getUpstreamResolver() { + return upstreamResolver; + } + + @Override + public Template lookup(String key) { + Template result = thisResolver.lookup(key); + if (result == null) + result = upstreamResolver.lookup(key); + return result; + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/TemplateTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/TemplateTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,95 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.testng.Assert.assertEquals; + +/** + * TemplateTest + */ +@Test +public class TemplateTest { + Map vars = new HashMap<>(); + + @BeforeTest + void before() { vars.clear(); } + + private void assertTemplate(String expected, String template) { + String result = Template.Behavior.expandTemplate(template, vars); + assertEquals(result, expected, "for " + template); + } + + private String dotIf(String s) { + return s == null || s.isEmpty() ? "" : "." + s; + } + + public void testTemplateExpansion() { + vars.put("A", s -> "a" + dotIf(s)); + vars.put("B", s -> "b" + dotIf(s)); + vars.put("C", s -> "#{A}#{B}"); + vars.put("D", s -> "#{A" + dotIf(s) + "}#{B" + dotIf(s) + "}"); + vars.put("_D", s -> "d"); + + assertTemplate("", ""); + assertTemplate("foo", "foo"); + assertTemplate("a", "#{A}"); + assertTemplate("a", "#{A.}"); + assertTemplate("a.FOO", "#{A.FOO}"); + assertTemplate("aa", "#{A}#{A}"); + assertTemplate("ab", "#{C}"); + assertTemplate("ab", "#{C.FOO}"); + assertTemplate("ab", "#{C.}"); + assertTemplate("a.FOOb.FOO", "#{D.FOO}"); + assertTemplate("ab", "#{D}"); + assertTemplate("d", "#{_D}"); + assertTemplate("#{A", "#{A"); + } + + public void testIndexedTemplate() { + vars.put("A[0]", s -> "a" ); + vars.put("A[1]", s -> "b" ); + vars.put("A[2]", s -> "c" ); + vars.put("X", s -> "0"); + assertTemplate("a", "#{A[0]}"); + assertTemplate("b", "#{A[1]}"); + assertTemplate("c", "#{A[2]}"); + } + + public void testAngleBrackets() { + vars.put("X", s -> "xyz"); + assertTemplate("List ls = xyz;", "List ls = #{X};"); + } + + @Test(expectedExceptions = IllegalStateException.class ) + public void testUnknownKey() { + assertTemplate("#{Q}", "#{Q}"); + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/combo/TemplateVar.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/combo/TemplateVar.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,38 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.combo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * ComboTemplate + */ +@Retention(RetentionPolicy.RUNTIME) +@java.lang.annotation.Target({ElementType.METHOD, ElementType.FIELD}) +public @interface TemplateVar { + String value(); +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/ConditionalExpressionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/ConditionalExpressionTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,271 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import org.testng.annotations.Factory; +import tools.javac.combo.ComboTestBase; +import tools.javac.combo.DimensionVar; +import tools.javac.combo.SourceFile; +import tools.javac.combo.Template; +import tools.javac.combo.TemplateVar; + +/** + * ConditionalExpressionTest + */ +public class ConditionalExpressionTest extends ComboTestBase { + @Factory + public static Object[] testConditionalExpression() throws Exception { + return factory(ConditionalExpressionTest.class); + } + + @DimensionVar("TYPE1") Type type1; + @DimensionVar("TYPE2") Type type2; + @DimensionVar("TARGET") Type target; + @DimensionVar("STMT") Statement stmt; + + @SourceFile("Main.java") + String clientFile = "public class Main {\n" + + " #{STMT_DECL};\n" + + " #{DECL.1};\n" + + " #{DECL.2};\n" + + " void test(boolean cond) { \n" + + " #{STMT};" + + " }\n" + +"}"; + + @Override + protected void postCompile(String grp) { + CondResult res = Type.condType(type1, type2); + if (!res.check(type1, type2, target)) { + assertCompileFailed(); + } else { + assertCompileSucceeded(); + } + } + + @Override + protected boolean shouldSkip() { + return target == Type.INT_CONST; + } + + interface CondResult { + boolean check(Type op1, Type op2, Type target); + } + + static CondResult ERR = new CondResult() { + public boolean check(Type op1, Type op2, Type target) { return false; } + }; + + static CondResult TARGET = new CondResult() { + public boolean check(Type op1, Type op2, Type target) { + return op1.compatibleWith(target) && op2.compatibleWith(target); + } + }; + + enum TypeKind { + NUMERIC, + BOOLEAN, + OTHER; + } + + enum Type implements Template, CondResult { + BYTE("byte", "0", TypeKind.NUMERIC), + SHORT("short", "0", TypeKind.NUMERIC), + INT("int", "0", TypeKind.NUMERIC), + INT_CONST("int", "0", TypeKind.NUMERIC), + LONG("long", "0", TypeKind.NUMERIC), + FLOAT("float", "0", TypeKind.NUMERIC), + DOUBLE("double", "0", TypeKind.NUMERIC), + CHAR("char", "'0'", TypeKind.NUMERIC), + BOOLEAN("boolean", "false", TypeKind.BOOLEAN), + J_L_BYTE("Byte", "null", TypeKind.NUMERIC), + J_L_SHORT("Short", "null", TypeKind.NUMERIC), + J_L_INT("Integer", "null", TypeKind.NUMERIC), + J_L_LONG("Long", "null", TypeKind.NUMERIC), + J_L_FLOAT("Float", "null", TypeKind.NUMERIC), + J_L_DOUBLE("Double", "null", TypeKind.NUMERIC), + J_L_CHAR("Character", "null", TypeKind.NUMERIC), + J_L_BOOLEAN("Boolean", "null", TypeKind.BOOLEAN), + NUMBER("Number", "null", TypeKind.OTHER), + SERIAL("java.io.Serializable", "null", TypeKind.OTHER); + + public boolean check(Type op1, Type op2, Type target) { + return compatibleWith(target); + } + + public boolean isErroneous() { + return false; + } + + public String expand(String qualifier) { + return typeStr; + } + + boolean compatibleWith(Type that) { + return that.anyOf(compatibleWith[this.ordinal()]); + } + + boolean anyOf(Type... ts) { + for (Type t : ts) { + if (t == this) return true; + } + return false; + } + + Type unbox() { + switch (this) { + case BYTE: + case J_L_BYTE: return BYTE; + case SHORT: + case J_L_SHORT: return SHORT; + case INT: + case INT_CONST: + case J_L_INT: return INT; + case LONG: + case J_L_LONG: return LONG; + case FLOAT: + case J_L_FLOAT: return FLOAT; + case DOUBLE: + case J_L_DOUBLE: return DOUBLE; + case BOOLEAN: + case J_L_BOOLEAN: return BOOLEAN; + case CHAR: + case J_L_CHAR: return CHAR; + default: + return null; + } + } + + String typeStr; + String defaultVal; + TypeKind kind; + + Type(String typeStr, String defaultVal, TypeKind kind) { + this.typeStr = typeStr; + this.defaultVal = defaultVal; + this.kind = kind; + } + + static CondResult condType(Type type1, Type type2) { + if (type1.kind == TypeKind.BOOLEAN && type2.kind == TypeKind.BOOLEAN) { + //boolean conditional + return BOOLEAN; + } else if (type1.kind == TypeKind.NUMERIC && type2.kind == TypeKind.NUMERIC) { + //numeric conditional + Type unbox1 = type1.unbox(); + Type unbox2 = type2.unbox(); + if (type1 == INT_CONST && + unbox2.anyOf(CHAR, BYTE, SHORT)) { + return unbox2; + } + if (type2 == INT_CONST && + unbox1.anyOf(CHAR, BYTE, SHORT)) { + return unbox1; + } + if (unbox1 == unbox2) { + return unbox1; + } + if (unbox1 == CHAR) { + return condType(INT, unbox2); + } + if (unbox2 == CHAR) { + return condType(unbox1, INT); + } + if (unbox1.compatibleWith(unbox2)) { + return unbox2; + } else if (unbox2.compatibleWith(unbox1)) { + return unbox1; + } else { + return ERR; + } + } else { + //reference conditional + return TARGET; + } + } + + static Type[][] compatibleWith = new Type[][] { + /* BYTE */ { BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, J_L_BYTE, NUMBER, SERIAL }, + /* SHORT */ { SHORT, INT, LONG, FLOAT, DOUBLE, J_L_SHORT, NUMBER, SERIAL }, + /* INT */ { INT, LONG, FLOAT, DOUBLE, J_L_INT, NUMBER, SERIAL }, + /* INT_CONST */ { INT, LONG, FLOAT, DOUBLE, J_L_INT, NUMBER, SERIAL }, + /* LONG */ { LONG, FLOAT, DOUBLE, J_L_LONG, NUMBER, SERIAL }, + /* FLOAT */ { FLOAT, DOUBLE, J_L_FLOAT, NUMBER, SERIAL }, + /* DOUBLE */ { DOUBLE, J_L_DOUBLE, NUMBER, SERIAL }, + /* CHAR */ { CHAR, INT, LONG, FLOAT, DOUBLE, J_L_CHAR, SERIAL }, + /* BOOLEAN */ { BOOLEAN, J_L_BOOLEAN, SERIAL }, + /* J_L_BYTE */ { J_L_BYTE, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, NUMBER, SERIAL }, + /* J_L_SHORT */ { J_L_SHORT, SHORT, INT, LONG, FLOAT, DOUBLE, NUMBER, SERIAL }, + /* J_L_INT */ { J_L_INT, INT, LONG, FLOAT, DOUBLE, NUMBER, SERIAL }, + /* J_L_LONG */ { J_L_LONG, LONG, FLOAT, DOUBLE, NUMBER, SERIAL }, + /* J_L_FLOAT */ { J_L_FLOAT, FLOAT, DOUBLE, NUMBER, SERIAL }, + /* J_L_DOUBLE */ { J_L_DOUBLE, DOUBLE, NUMBER, SERIAL }, + /* J_L_CHAR */ { J_L_CHAR, CHAR, INT, LONG, FLOAT, DOUBLE, SERIAL }, + /* J_L_BOOLEAN */ { J_L_BOOLEAN, BOOLEAN, SERIAL }, + /* NUMBER */ { NUMBER, SERIAL }, + /* SERIAL */ { SERIAL } }; + } + + enum Statement implements Template { + ASSIGN("#{TARGET} t = cond ? #{EXPR.1} : #{EXPR.2}"), + METHOD("m(cond ? #{EXPR.1} : #{EXPR.2})"); + + String stmtStr; + + Statement(String stmtStr) { + this.stmtStr = stmtStr; + } + + public String expand(String qual) { + return stmtStr; + } + } + + @TemplateVar("STMT_DECL") + Template stmt_decl = new Template() { + public String expand(String selector) { + return stmt == Statement.ASSIGN ? "" : "void m(#{TARGET} arg) { }"; + } + }; + + @TemplateVar("DECL") + Template decl = new Template() { + public String expand(String selector) { + int sel = Integer.valueOf(selector); + Type t = sel == 1 ? type1 : type2; + return t == Type.INT_CONST ? "" : String.format("#{TYPE%d} m%d() { return %s; }", sel, sel, t.defaultVal); + } + }; + + @TemplateVar("EXPR") + Template expr = new Template() { + public String expand(String selector) { + int sel = Integer.valueOf(selector); + Type t = sel == 1 ? type1 : type2; + return t == Type.INT_CONST ? t.defaultVal : String.format("m%d()", sel); + } + }; +} + diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/DefaultMethodAddTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/DefaultMethodAddTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,170 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +import org.testng.annotations.Factory; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import tools.javac.combo.*; + +/** + * DefaultMethodAddTest: Test default method by running bytecode compiled at different times + * where conflicting default methods are added or declared + */ +public class DefaultMethodAddTest extends ComboTestBase { + @Factory + public static Object[] testDefaultMethodAdd() throws Exception { + return factory(DefaultMethodAddTest.class); + } + + @DimensionVar("SHAPE") CShapes shapeType; + + /** + * The separate-compilation operation to be performed, such as adding a default method, + * adding an abstract itnerface method, redeclaring an inherited default method as + * abstract interface method, etc + */ + @DimensionVar("ADD") AddType addType; + + @SourceFile(value="B.java", group="A") + String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{ADD} }"; + + @SourceFile(value="B.java", group="B") + String interfaceB = "interface B #{SHAPE.B_DECL} {}"; + + @SourceFile(value="A.java", group="B") + String interfaceA = "interface A { default String m() { return \"A\"; } }"; + + @SourceFile(value="C.java", group="B") + String classC = "#{SHAPE.C}"; + + @SourceFile(value="Main.java", group="B") + String classMain = "public class Main {\n" + + " public String main() {\n" + + " return new C().m();\n" + + " }\n" + + "}"; + + @Override + protected boolean shouldRun() { return true; } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Method m = clazz.getMethod("main"); + Object obj = clazz.newInstance(); + String result = null, output = null; + try { + result = (String) m.invoke(obj); + } catch (InvocationTargetException ex) { + output = ex.getCause().toString(); + } + if(shapeType == CShapes.C_B_A) { + if(addType == AddType.ADD) { + assertEquals(output, null); + assertEquals(result, "B"); + } + else //redeclare + assertEquals(output, "java.lang.AbstractMethodError: Method B.m()Ljava/lang/String; is abstract"); + } + else if(shapeType == CShapes.C_I_AB2) { + assertEquals(output, null); + assertEquals(result, "A"); + } + else if(shapeType == CShapes.C_CI) { + assertEquals(output, null); + assertEquals(result, "D"); + } + else if(shapeType == CShapes.C_I_AB3) { + assertEquals(output, null); + assertEquals(result, "AB"); + } + else + assertTrue(output.matches("java.lang.AbstractMethodError: Conflicting default methods: .+[.]m .+[.]m")); + } + + enum CShapes implements Template { //shapes of class hirarchy + //class C implements interface A, B + C_AB("", + "class C implements A, B {}"), + //class C implments interface B, B extends interface A + C_B_A("extends A", + "class C implements B {}"), + //class C implments interface AB, AB extends interface A, B + C_I_AB("", + "interface AB extends A, B { }\n" + + "class C implements AB {}"), + //class C implments interface AB, AB extends interface A, B and explicitly inherits the default method in A + C_I_AB2("", + "interface AB extends A, B { default String m() { return A.super.m(); } }\n" + + "class C implements AB {}"), + //class C implments interface AB, AB extends interface A, B and overrides the default method inherited + C_I_AB3("", + "interface AB extends A, B { default String m() { return \"AB\"; } }\n" + + "class C implements AB {}"), + //class C extends Class D implements Interface B + C_CI("", + "class D { public String m() { return \"D\"; } }\n" + + "class C extends D implements B {}"); + + private final String sB_DECL; + private final String sC; + + CShapes(String sB_DECL, String sC) { + this.sB_DECL = sB_DECL; + this.sC = sC; + } + + public String expand(String selector) { + switch(selector) { + case "B_DECL": return sB_DECL; + case "C": return sC; + default: return toString(); + } + } + } + + enum AddType implements Template { // add by adding default method or abstract interface method + ADD("default String m() { return \"B\"; }"), + REDECLARE("String m();"); + + final String newCode; + + AddType(String str) { + newCode = str; + } + + public String expand(String selector) { + return newCode; + } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/DefaultMethodRemoveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/DefaultMethodRemoveTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,165 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +import org.testng.annotations.Factory; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import tools.javac.combo.*; + +/** + * DefaultMethodRemoveTest: Test default method by running bytecode compiled at different times + * where default methods are removed or redeclared + */ +public class DefaultMethodRemoveTest extends ComboTestBase { + @Factory + public static Object[] testDefalutMethodRemove() throws Exception { + return factory(DefaultMethodRemoveTest.class); + } + + @DimensionVar("SHAPE") CShapes shapeType; + + /** + * The separate-compilation operation to be performed, such as removing a default method, + * redeclaring as abstract interface method, etc + */ + @DimensionVar("REMOVE") RemoveType removeType; + + @SourceFile(value="B.java", group="A") + String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{REMOVE} }"; + + @SourceFile(value="A.java", group="B") + String interfaceA = "interface A { default String m() { return \"A\"; } }"; + + @SourceFile(value="B.java", group="B") + String interfaceB = "interface B #{SHAPE.B_DECL} { default String m() { return \"B\"; } }"; + + @SourceFile(value="C.java", group="B") + String classC = "#{SHAPE.C}"; + + @SourceFile(value="Main.java", group="B") + String classMain = "public class Main {\n" + + " public String main() {\n" + + " return new C().m();\n" + + " }\n" + + "}"; + + @Override + protected boolean shouldRun() { return true; } + + @Override + protected void postCompile(String group) { + if( group.equals("A") && shapeType == CShapes.C_B_AD && removeType == RemoveType.REMOVE ) + assertCompileErrors("compiler.err.types.incompatible.unrelated.defaults"); + } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Method m = clazz.getMethod("main"); + Object obj = clazz.newInstance(); + String result = null, output = null; + try { + result = (String) m.invoke(obj); + } catch (InvocationTargetException ex) { + output = ex.getCause().toString(); + } + if(shapeType == CShapes.C_B_A) { + if(removeType == RemoveType.REMOVE) + assertEquals(result, "A"); + else + assertEquals(output, "java.lang.AbstractMethodError: Method B.m()Ljava/lang/String; is abstract"); + } + else if(shapeType == CShapes.C_CI) + assertEquals(result, "D"); + else if(shapeType == CShapes.C_B_AD) { + if(removeType == RemoveType.REMOVE) + assertEquals(output, "java.lang.AbstractMethodError: C.m()Ljava/lang/String;"); + else + assertEquals(output, "java.lang.AbstractMethodError: Method B.m()Ljava/lang/String; is abstract"); + } + else { //C_B + if( removeType == RemoveType.REMOVE) + assertEquals(output, "java.lang.NoSuchMethodError: C.m()Ljava/lang/String;"); + else + assertEquals(output, "java.lang.AbstractMethodError: C.m()Ljava/lang/String;"); + } + } + + enum CShapes implements Template { //shapes of class hirarchy + //class C implements interface B + C_B("", + "class C implements B {}"), + //class C implments interface B, B extends interface A + C_B_A("extends A", + "class C implements B {}"), + //class C implments interface B, B extends interface A, D + C_B_AD("extends A, D", + "interface D { default String m() { return \"D\"; } }\n" + + "class C implements B {}"), + //class C extends Class D implements Interface B + C_CI("", + "class D { public String m() { return \"D\"; } }\n" + + "class C extends D implements B {}"); + + private final String sB_DECL; + private final String sC; + + CShapes(String sB_DECL, String sC) { + this.sB_DECL = sB_DECL; + this.sC = sC; + } + + public String expand(String selector) { + switch(selector) { + case "B_DECL": return sB_DECL; + case "C": return sC; + default: return toString(); + } + } + } + + enum RemoveType implements Template { //remove by removing default method code or redeclaring the interface method + REMOVE(""), + REDECLARE("String m();"); + + final String newCode; + + RemoveType(String str) { + newCode = str; + } + + public String expand(String selector) { + return newCode; + } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/LambdaArgAdaptationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/LambdaArgAdaptationTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,176 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import org.testng.annotations.Factory; +import tools.javac.combo.ComboTestBase; +import tools.javac.combo.DimensionVar; +import tools.javac.combo.SourceFile; +import tools.javac.combo.Template; + +import java.lang.reflect.Method; +import java.util.EnumMap; +import java.util.EnumSet; + +import static org.testng.Assert.assertEquals; + +/** + * LambdaArgAdaptationTest + */ +public class LambdaArgAdaptationTest extends ComboTestBase { + @Factory + public static Object[] testArgAdaptation() throws Exception { + return factory(LambdaArgAdaptationTest.class); + } + + @DimensionVar("FROM") Types fromType; + @DimensionVar("TO") Types toType; + + @SourceFile("Sam.java") + String samFile = "public interface Sam { String m(#{FROM} arg); }"; + + @SourceFile("Main.java") + String clientFile = "public class Main {\n" + +" static String m(#{TO} arg) { \n" + +" return String.valueOf(arg);\n" + +" }\n" + +" public String main() { \n" + + " Sam s = Main::m;\n" + + " return s.m(#{FROM.ARG});\n" + + " }\n" + +"}"; + + + @Override + protected String[] getCompileOptions(String group) { + return new String[] { "-XDlambdaToMethod" }; + } + + @Override + protected void postCompile(String group) { + if (fromType == Types.VOID || toType == Types.VOID) + assertCompileFailed(); + else if (fromType.pr == PR.REF && toType.pr == PR.REF) + assertCompileSucceededIff(toType.clazz.isAssignableFrom(fromType.clazz)); + else if (fromType.pr == PR.PRIM && toType.pr == PR.REF) + assertCompileSucceededIff(toType.clazz.isAssignableFrom(Types.boxMap.get(fromType).clazz)); + else if (fromType.pr == PR.REF && toType.pr == PR.PRIM) + assertCompileSucceededIff(fromType.unboxed != null && Types.widenMap.get(fromType.unboxed).contains(toType)); + else if (fromType.pr == PR.PRIM && toType.pr == PR.PRIM) + assertCompileSucceededIff(Types.widenMap.get(fromType).contains(toType)); + else + assertCompileSucceeded(); + } + + @Override + protected boolean shouldRun() { return true; } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Method m = clazz.getMethod("main"); + Object obj = clazz.newInstance(); + String result = (String) m.invoke(obj); + String formatted = fromType.asObject.toString(); + if (fromType == Types.CHAR || fromType == Types.BOXED_CHAR) { + result = result.replace("A", "65"); + formatted = formatted.replace("A", "65"); + } + assertEquals(result.replace(".0", ""), formatted.replace(".0", "")); + } +} + +enum PR {PRIM, REF} + +enum Types implements Template { + BYTE(PR.PRIM, "byte", byte.class, "(byte) 1", (byte) 1), + SHORT(PR.PRIM, "short", short.class, "(short) 2", (short) 2), + CHAR(PR.PRIM, "char", char.class, "'A'", 'A'), + INT(PR.PRIM, "int", int.class, "3", 3), + LONG(PR.PRIM, "long", long.class, "4L", 4L), + FLOAT(PR.PRIM, "float", float.class, "5.0f", 5.0f), + DOUBLE(PR.PRIM, "double", double.class, "6.0", 6.0), + BOOLEAN(PR.PRIM, "boolean", boolean.class, "true", true), + VOID(PR.PRIM, "void", void.class, "null", null), + BOXED_BYTE(PR.REF, "Byte", Byte.class, "Byte.valueOf((byte) 1)", (byte) 1, BYTE), + BOXED_SHORT(PR.REF, "Short", Short.class, "Short.valueOf((short) 2)", (short) 2, SHORT), + BOXED_CHAR(PR.REF, "Character", Character.class, "Character.valueOf('A')", 'A', CHAR), + BOXED_INT(PR.REF, "Integer", Integer.class, "Integer.valueOf(3)", 3, INT), + BOXED_LONG(PR.REF, "Long", Long.class, "Long.valueOf(4)", (long) 4, LONG), + BOXED_FLOAT(PR.REF, "Float", Float.class, "Float.valueOf(5.0f)", 5.0f, FLOAT), + BOXED_DOUBLE(PR.REF, "Double", Double.class, "Double.valueOf(6.0)", 6.0, DOUBLE), + BOXED_BOOLEAN(PR.REF, "Boolean", Boolean.class, "Boolean.valueOf(true)", true, BOOLEAN), + NUMBER(PR.REF, "Number", Number.class, "9", 9), + OBJECT(PR.REF, "Object", Object.class, "10", 10), + STRING(PR.REF, "String", String.class, "\"foo\"", "foo"); + + public static EnumMap boxMap = new EnumMap<>(Types.class); + public static EnumMap unboxMap = new EnumMap<>(Types.class); + public static EnumMap> widenMap = new EnumMap<>(Types.class); + + static { + for (Types t : values()) { + if (t.unboxed != null) { + boxMap.put(t.unboxed, t); + unboxMap.put(t, t.unboxed); + } + } + + widenMap.put(BYTE, EnumSet.of(BYTE, SHORT, INT, LONG, FLOAT, DOUBLE)); + widenMap.put(SHORT, EnumSet.of(SHORT, INT, LONG, FLOAT, DOUBLE)); + widenMap.put(CHAR, EnumSet.of(CHAR, INT, LONG, FLOAT, DOUBLE)); + widenMap.put(INT, EnumSet.of(INT, LONG, FLOAT, DOUBLE)); + widenMap.put(LONG, EnumSet.of(LONG, FLOAT, DOUBLE)); + widenMap.put(FLOAT, EnumSet.of(FLOAT, DOUBLE)); + widenMap.put(DOUBLE, EnumSet.of(DOUBLE)); + widenMap.put(BOOLEAN, EnumSet.of(BOOLEAN)); + } + + final PR pr; + final String name; + final Class clazz; + final String valueString; + final Object asObject; + final Types unboxed; + + Types(PR pr, String name, Class clazz, String valueString, Object asObject) { + this (pr, name, clazz, valueString, asObject, null); + } + + Types(PR pr, String name, Class clazz, String valueString, Object asObject, Types unboxed) { + this.pr = pr; + this.name = name; + this.clazz = clazz; + this.valueString = valueString; + this.asObject = asObject; + this.unboxed = unboxed; + } + + public String expand(String selector) { + switch (selector) { + case "ARG": return valueString; + default: return name; + } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/LambdaCaptureTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/LambdaCaptureTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,261 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import org.testng.annotations.Factory; +import org.testng.annotations.Test; +import tools.javac.combo.*; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import static org.testng.Assert.assertEquals; + +/** + * LambdaCaptureTest + * + * @author Brian Goetz + */ +public class LambdaCaptureTest extends ComboTestBase { + @Factory + public static Object[] testCombo() throws Exception { + return factory(LambdaCaptureTest.class); + } + + final int arity; + final ArgType[] argTypes; + final int capArity; + final CapType[] capTypes; + final boolean shouldSkip; + + public LambdaCaptureTest(@DimensionVar(value = "ARITY", rangeLower = 0, rangeUpper = 2) int arity, + @DimensionVar("ARGTYPE1") ArgType argType1, + @DimensionVar("ARGTYPE2") ArgType argType2, + @DimensionVar(value = "CAP_ARITY", rangeLower = 0, rangeUpper = 2) int capArity, + @DimensionVar("CAPTYPE1") CapType capType1, + @DimensionVar("CAPTYPE2") CapType capType2) { + this.arity = arity; + this.capArity = capArity; + this.argTypes = new ArgType[] { argType1, argType2 }; + this.capTypes = new CapType[] { capType1, capType2 }; + shouldSkip = skipConstrained(arity, argTypes) || skipConstrained(capArity, capTypes); + } + + @Override + protected String[] getCompileOptions(String group) { + return new String[] { "-XDlambdaToMethod" }; + } + + @SourceFile("Main.java") String test + = "public class Main {\n" + + " #{CAPTYPE1} f0 = #{CAPV.1};\n" + + " #{CAPTYPE2} f1 = #{CAPV.2};\n" + + " interface Target { String m(#{SAM_FORMALS}); }\n" + + " public String convert() { #{CAPTYPE1} loc0 = #{CAPV.1};\n" + + " #{CAPTYPE2} loc1 = #{CAPV.2};\n" + + " Target lambda = (#{LAMBDA_FORMALS}) -> String.format(\"#{FORMAT_STRING}\" #{FORMAT_ARGS});\n" + + " return lambda.m(#{INVOKE_ARGS}); }\n" + + "}"; + + @TemplateVar("LAMBDA_FORMALS") Template formalArgs = new Template() { + public String expand(String selector) { + List list = new ArrayList<>(); + for (int i=0; i list = new ArrayList<>(); + for (int i=0; i list = new ArrayList<>(); + for (int i=0; i list = new ArrayList<>(); + for (int i=0; i 0 ? ", " : "") + intersperse(list, ", "); + } + }; + + @TemplateVar("INVOKE_ARGS") Template invokeArgs = new Template() { + public String expand(String selector) { + List list = new ArrayList<>(); + for (int i=0; i list, String delim) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (String s : list) { + if (!first) + sb.append(delim); + first = false; + sb.append(s); + } + return sb.toString(); + } + + @Override + protected boolean shouldSkip() { + return shouldSkip; + } + + @Override + protected boolean shouldRun() { + return true; + } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Object obj = clazz.newInstance(); + Method m = clazz.getMethod("convert"); + Object o = m.invoke(obj); + + List list = new ArrayList<>(); + for (int i=0; i { + + @Factory + public static Object[] testCombo() throws Exception { + return factory(LambdaConversionTest.class); + } + + @DimensionVar("PACKAGE") PackageKind samPkg; + @DimensionVar("MODIFIER") ModifierKind modKind; + @DimensionVar("CLASS") SamKind samKind; + @DimensionVar("METH") MethodKind meth; + @DimensionVar("RET") TypeKind retType; + @DimensionVar("ARG") TypeKind argType; + @DimensionVar("THROWN") TypeKind thrownType; + + @SourceFile("Sam.java") + String samSource = "#{PACKAGE.PACKAGE_DECL} \n #{CLASS}"; + + @SourceFile("PackageClass.java") + String packageSource = "#{PACKAGE.PACKAGE_DECL}\n #{MODIFIER} class PackageClass extends Exception { }"; + + @SourceFile("Client.java") + String clientSource = "#{PACKAGE.IMPORT_STATEMENT}\n class Client { Sam s = x -> null; }"; + + @Override + protected void postCompile(String group) { + if (samKind != SamKind.INTERFACE) { + assertCompileFailed("SAM type must be an interface"); + } else if (meth != MethodKind.NON_GENERIC) { + assertCompileFailed("target method must be non-generic"); + } else if (samPkg != PackageKind.NO_PKG && + modKind != ModifierKind.PUBLIC && + (retType == TypeKind.PKG_CLASS + || argType == TypeKind.PKG_CLASS + || thrownType == TypeKind.PKG_CLASS)) { + assertCompileFailed("target must not contain inaccessible types"); + } else { + assertCompileSucceeded(); + } + } + + static enum PackageKind implements Template { + NO_PKG(""), + PKG_A("a"); + + String pkg; + + PackageKind(String pkg) { + this.pkg = pkg; + } + + public String expand(String selector) { + if (this == NO_PKG) + return ""; + switch (selector) { + case "PACKAGE_DECL": return String.format("package %s;", pkg); + case "IMPORT_STATEMENT": return String.format("import %s.*;", pkg); + default: throw new IllegalArgumentException(selector); + } + } + } + + static enum SamKind implements Template { + CLASS("public class Sam { }"), + ABSTRACT_CLASS("public abstract class Sam { }"), + ANNOTATION("public @interface Sam { }"), + ENUM("public enum Sam { }"), + INTERFACE("public interface Sam { \n #{METH}; \n }"); + + String template; + + SamKind(String template) { this.template = template; } + + public String expand(String selector) { return template; } + } + + static enum ModifierKind implements Template { + PUBLIC("public"), + PACKAGE(""); + + String template; + + ModifierKind(String template) { this.template = template; } + + public String expand(String selector) { return template; } + } + + static enum TypeKind implements Template { + EXCEPTION("Exception"), + PKG_CLASS("PackageClass"); + + String template; + + private TypeKind(String template) { this.template = template; } + + public String expand(String selector) { return template; } + } + + static enum MethodKind implements Template { + NONE(""), + NON_GENERIC("public #{RET} m(#{ARG} s) throws #{THROWN};"), + GENERIC("public #{RET} m(#{ARG} s) throws #{THROWN};"); + + String template; + + private MethodKind(String template) { this.template = template; } + + public String expand(String selector) { return template; } + } + +} + diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/LambdaExpressionTypeInferenceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/LambdaExpressionTypeInferenceTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,423 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import org.testng.annotations.Factory; +import tools.javac.combo.ComboTestBase; +import tools.javac.combo.DimensionVar; +import tools.javac.combo.SourceFile; +import tools.javac.combo.Template; + +import static tools.javac.combo.StackProcessingUtils.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * LambdaExpressionTypeInferenceTest + */ +public class LambdaExpressionTypeInferenceTest extends ComboTestBase { + @Factory + public static Object[] testLambdaExpressionInference() throws Exception { + return factory(LambdaExpressionTypeInferenceTest.class); + } + + @DimensionVar("FORMAL_SHAPE") FormalTypeShape formalShape; + @DimensionVar("TREE_SHAPE") TreeShape treeShape; + @DimensionVar("ARG_SHAPE_1") ArgTypeShape argShape1; + @DimensionVar("ARG_SHAPE_2") ArgTypeShape argShape2; + @DimensionVar("ARG_SHAPE_3") ArgTypeShape argShape3; + + @SourceFile("SAM.java") + String samFile = "public interface SAM {\n" + +" Y apply(X x);\n" + +"}"; + + + @SourceFile("Main.java") + String clientFile = "import java.util.*;\n" + +"public class Main {\n" + +" void m(#{FORMAL_SHAPE} x) { }\n" + +" void test() {\n" + +" m(#{TREE_SHAPE});\n" + +" }\n" + +"}"; + + @Override + protected void postCompile(String grp) { + if (treeShape.compute().typeCheck(formalShape.compute(), new Type[] { argShape1.compute(), argShape2.compute(), argShape3.compute() }).isErroneous()) { + assertCompileFailed(); + } else { + assertCompileSucceeded(); + } + } + + @Override + protected boolean shouldSkip() { + return argShape2.ordinal() != 0 && treeShape.depth < 2 || argShape3.ordinal() != 0 && treeShape.depth < 3; + } + + static class Tree { + TreeTag treeTag; + Tree[] subtrees; + + Tree(TreeTag treeTag, Tree... subtrees) { + this.treeTag = treeTag; + this.subtrees = subtrees; + } + + public String toString() { + Object[] substrings = new Object[subtrees.length]; + for (int i = 0; i < subtrees.length; i++) { + substrings[i] = subtrees[i].toString(); + } + return String.format(treeTag.treeStr, substrings); + } + + Type typeCheck(Type target, Type[] argtypes) { + switch (treeTag) { + case INT: + Type type = new Type(TypeToken.INTEGER); + return type.compatibleWith(target) ? type : errType; + case STRING: + type = new Type(TypeToken.STRING); + return type.compatibleWith(target) ? type : errType; + case EXPR_LAMBDA: + Type restype = target.getReturnType(); + if (restype == null) { + return errType; + } + Type argtype = target.getArgType(); + int idx = subtrees[0].treeTag.argIndex(); + if (idx >= 0 && !argtypes[idx].compatibleWith(argtype)) { + //arg type mismatch + return errType; + } + + for (int i = 1; i < subtrees.length; i++) { + if (subtrees[i].typeCheck(restype, argtypes).isErroneous()) { + return errType; + } + } + return target; + case COND: + Type typeToCheck = target; + if (subtrees[0].treeTag == TreeTag.INT && subtrees[1].treeTag == TreeTag.INT) { + Type owntype = new Type(TypeToken.INTEGER); + return owntype.compatibleWith(target) ? owntype : errType; + } else { + for (int i = 0; i < subtrees.length; i++) { + if (subtrees[i].typeCheck(target, argtypes).isErroneous()) { + return errType; + } + } + return target; + } + default: + throw new AssertionError(); + } + } + } + + enum TreeTag implements StackItem { + INT("1", 0), + STRING("\"\"", 0), + COND("true ? %s : %s", 2), + EXPR_LAMBDA("(%s)->%s", 2), + IMPLICIT_1("x1", 0), + IMPLICIT_2("x2", 0), + IMPLICIT_3("x3", 0), + EXPLICIT_1("#{ARG_SHAPE_1} x1", 0), + EXPLICIT_2("#{ARG_SHAPE_2} x2", 0), + EXPLICIT_3("#{ARG_SHAPE_3} x3", 0); + + String treeStr; + int arity; + + TreeTag(String treeStr, int arity) { + this.treeStr = treeStr; + this.arity = arity; + } + + public int arity() { + return arity; + } + + Tree apply(Tree... args) { + return new Tree(this, args); + } + + int argIndex() { + switch (this) { + case EXPLICIT_1: + return 0; + case EXPLICIT_2: + return 1; + case EXPLICIT_3: + return 2; + default: + return -1; + } + } + } + + enum TreeShape implements Template, StackReducer { + LAMBDA_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.INT), + LAMBDA_STRING(1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.STRING), + LAMBDA_COND_INT_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.INT, TreeTag.INT), + IMPL_LAMBDA_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_1, TreeTag.INT), + IMPL_LAMBDA_STRING(1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_1, TreeTag.STRING), + IMPL_LAMBDA_COND_INT_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_1, TreeTag.COND, TreeTag.INT, TreeTag.INT), + LAMBDA_LAMBDA_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.INT), + LAMBDA_LAMBDA_STRING(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.STRING), + LAMBDA_LAMBDA_COND_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT), + LAMBDA_IMPL_LAMBDA_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.INT), + LAMBDA_IMPL_LAMBDA_STRING(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.STRING), + LAMBDA_IMPL_LAMBDA_COND_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT), + LAMBDA_COND_LAMBDA_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.INT, TreeTag.INT), + LAMBDA_COND_LAMBDA_STRING_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.STRING, TreeTag.INT), + LAMBDA_COND_LAMBDA_COND_INT_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT, TreeTag.INT), + LAMBDA_COND_IMPL_LAMBDA_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.INT, TreeTag.INT), + LAMBDA_COND_IMPL_LAMBDA_STRING_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.STRING, TreeTag.INT), + LAMBDA_COND_IMPL_LAMBDA_COND_INT_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT, TreeTag.INT), + LAMBDA_LAMBDA_LAMBDA_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_3, TreeTag.INT), + LAMBDA_LAMBDA_LAMBDA_STRING(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_3, TreeTag.STRING), + LAMBDA_LAMBDA_LAMBDA_COND_INT_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_3, TreeTag.COND, TreeTag.INT, TreeTag.INT), + LAMBDA_LAMBDA_IMPL_LAMBDA_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_3, TreeTag.INT), + LAMBDA_LAMBDA_IMPL_LAMBDA_STRING(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_3, TreeTag.STRING), + LAMBDA_LAMBDA_IMPL_LAMBDA_COND_INT_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_3, TreeTag.COND, TreeTag.INT, TreeTag.INT); + + TreeTag[] treeTags; + int depth; + + TreeShape(int depth, TreeTag... treeTags) { + this.depth = depth; + this.treeTags = treeTags; + } + + Tree compute() { + return process(treeTags, this, null); + } + + public String expand(String selector) { + return compute().toString(); + } + + public Tree reduce(TreeTag tag, Tree[] args, Void _unused) { + return new Tree(tag, args); + } + + public Void reducerArg(TreeTag item, int i) { return null; } + + public Class resultToken() { + return Tree.class; + } + } + + static class Type { + TypeToken typeToken; + Type[] typeargs; + + Type(TypeToken typeToken, Type... typeargs) { + this.typeToken = typeToken; + this.typeargs = typeargs; + } + + public String toString() { + Object[] typeargStrings = new Object[typeargs.length]; + for (int i = 0; i < typeargs.length; i++) { + typeargStrings[i] = typeargs[i].toString(); + } + return String.format(typeToken.tokenStr, typeargStrings); + } + + boolean isErroneous() { return false; } + + Type getReturnType() { + return typeToken == TypeToken.SAM ? + typeargs[1] : null; + } + + Type getArgType() { + return typeToken == TypeToken.SAM ? + typeargs[0] : null; + } + + boolean isFree() { + switch (typeToken) { + case A: + case R: + return true; + default: + for (Type t : typeargs) { + if (t.isFree()) return true; + } + return false; + } + } + + boolean isFreeVar() { + switch (typeToken) { + case A: + case R: + return true; + default: + return false; + } + } + + boolean compatibleWith(Type that) { + if (that.isFreeVar()) { + return true; + } else { + if (typeToken != that.typeToken) + return false; + if (typeargs.length != that.typeargs.length) { + return false; + } + for (int i = 0; i < typeargs.length ; i++) { + if (!typeargs[i].compatibleWith(that.typeargs[i])) + return false; + } + return true; + } + } + } + + static Type errType = new Type(null) { + boolean isErroneous() { + return true; + } + }; + + enum TypeToken implements StackItem { + STRING("String", 0), + INTEGER("Integer", 0), + A("A", 0), + R("R", 0), + LIST("List<%s>", 1), + SAM("SAM<%s,%s>", 2); + + int arity; + String tokenStr; + + TypeToken(String tokenStr, int arity) { + this.tokenStr = tokenStr; + this.arity = arity; + } + + public int arity() { + return arity; + } + } + + enum ArgTypeShape implements Template, StackReducer { + STRING(TypeToken.STRING), + INTEGER(TypeToken.INTEGER), + LIST_STRING(TypeToken.LIST, TypeToken.STRING), + LIST_INTEGER(TypeToken.LIST, TypeToken.INTEGER); + + TypeToken[] tokens; + + ArgTypeShape(TypeToken... tokens) { + this.tokens = tokens; + } + + Type compute() { + return process(tokens, this, null); + } + + public String expand(String selector) { + return compute().toString(); + } + + public Type reduce(TypeToken token, Type[] args, Void _unused) { + return new Type(token, args); + } + + public Void reducerArg(TypeToken item, int i) { return null; } + + public Class resultToken() { + return Type.class; + } + } + + enum FormalTypeShape implements Template, StackReducer { + SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.STRING), + SAM_Integer_String(TypeToken.SAM, TypeToken.INTEGER, TypeToken.STRING), + SAM_List_String_String(TypeToken.SAM, TypeToken.LIST, TypeToken.STRING, TypeToken.STRING), + SAM_List_Integer_String(TypeToken.SAM, TypeToken.LIST, TypeToken.INTEGER, TypeToken.STRING), + SAM_A_String(TypeToken.SAM, TypeToken.A, TypeToken.STRING), + SAM_List_A_String(TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.STRING), + SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.R), + SAM_A_R(TypeToken.SAM, TypeToken.A, TypeToken.R), + SAM_List_A_R(TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.R), + SAM_String_SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING), + SAM_String_SAM_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.INTEGER, TypeToken.STRING), + SAM_String_SAM_List_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.STRING, TypeToken.STRING), + SAM_String_SAM_List_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.INTEGER, TypeToken.STRING), + SAM_String_SAM_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.STRING), + SAM_String_SAM_List_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.STRING), + SAM_String_SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.R), + SAM_String_SAM_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.R), + SAM_String_SAM_List_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.R), + SAM_A_SAM_String_String(TypeToken.SAM, TypeToken.A, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING), + SAM_String_SAM_String_SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING), + SAM_String_SAM_String_SAM_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.INTEGER, TypeToken.STRING), + SAM_String_SAM_String_SAM_List_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.STRING, TypeToken.STRING), + SAM_String_SAM_String_SAM_List_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.INTEGER, TypeToken.STRING), + SAM_String_SAM_String_SAM_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.STRING), + SAM_String_SAM_String_SAM_List_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.STRING), + SAM_String_SAM_String_SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.R), + SAM_String_SAM_String_SAM_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.R), + SAM_String_SAM_String_SAM_List_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.R), + SAM_String_SAM_A_SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING), + SAM_String_SAM_A_SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.SAM, TypeToken.STRING, TypeToken.R); + + TypeToken[] tokens; + + FormalTypeShape(TypeToken... tokens) { + this.tokens = tokens; + } + + Type compute() { + return process(tokens, this, null); + } + + public String expand(String selector) { + return compute().toString(); + } + + public Type reduce(TypeToken token, Type[] args, Void _unused) { + return new Type(token, args); + } + + public Void reducerArg(TypeToken item, int i) { return null; } + + public Class resultToken() { + return Type.class; + } + } +} + diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/LambdaReturnAdaptationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/LambdaReturnAdaptationTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import org.testng.annotations.Factory; +import tools.javac.combo.*; + +import java.lang.reflect.Method; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * LambaReturnAdaptationTest + */ +public class LambdaReturnAdaptationTest extends ComboTestBase { + @Factory + public static Object[] testReturnAdaptation() throws Exception { + return factory(LambdaReturnAdaptationTest.class); + } + + @DimensionVar("FROM") Types fromType; + @DimensionVar("TO") Types toType; + + @SourceFile("Sam.java") + String samFile = "public interface Sam { #{TO} m(int arg); }"; + + @SourceFile("Main.java") + String clientFile = "public class Main {\n" + +" static #{FROM} m(int arg) { \n" + +" #{RET};\n" + +" }\n" + +" public #{TO} main() { \n" + + " Sam s = Main::m;\n" + + " #{RET_MAIN};\n" + + " }\n" + +"}"; + + @TemplateVar("RET") + Template retTemplate = new Template() { + public String expand(String selector) { + if (fromType == Types.VOID) + return ""; + else if (fromType == Types.STRING) + return "return \"66\""; + else if (fromType == Types.BOOLEAN || fromType == Types.BOXED_BOOLEAN) + return "return true"; + else if (fromType.unboxed != null) + return "return (" + fromType.unboxed.name + ") arg"; + else + return "return (" + fromType.name + ") arg"; + } + }; + + @TemplateVar("RET_MAIN") + Template retMainTemplate = new Template() { + public String expand(String selector) { + return toType == Types.VOID ? "s.m(66)" : "return s.m(66)"; + } + }; + + @Override + protected String[] getCompileOptions(String group) { + return new String[] { "-XDlambdaToMethod" }; + } + + @Override + protected void postCompile(String group) { + if (fromType != Types.VOID && toType == Types.VOID) + assertCompileSucceeded(); + else if (fromType == Types.VOID && toType != Types.VOID) + assertCompileFailed(); + else if (fromType == Types.VOID && toType == Types.VOID) + assertCompileSucceeded(); + else if (fromType.pr == PR.REF && toType.pr == PR.REF) + assertCompileSucceededIff(toType.clazz.isAssignableFrom(fromType.clazz)); + else if (fromType.pr == PR.PRIM && toType.pr == PR.REF) + assertCompileSucceededIff(toType.clazz.isAssignableFrom(Types.boxMap.get(fromType).clazz)); + else if (fromType.pr == PR.REF && toType.pr == PR.PRIM) + assertCompileSucceededIff(fromType.unboxed != null && Types.widenMap.get(fromType.unboxed).contains(toType)); + else if (fromType.pr == PR.PRIM && toType.pr == PR.PRIM) + assertCompileSucceededIff(Types.widenMap.get(fromType).contains(toType)); + else + assertCompileSucceeded(); + } + + @Override + protected boolean shouldRun() { return true; } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Method m = clazz.getMethod("main"); + Object obj = clazz.newInstance(); + Object in = 66; + Object out = m.invoke(obj); + if (toType == Types.VOID) + assertTrue(out == null); + else if (fromType == Types.BOOLEAN || fromType == Types.BOXED_BOOLEAN) + assertEquals("true", out.toString()); + else + assertEquals(in.toString(), out.toString().replace("B", "66").replace(".0", "")); + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/MethodRefCaptureTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/MethodRefCaptureTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,165 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import org.testng.annotations.Factory; +import tools.javac.combo.*; + +/** + * MethodRefCaptureTest + * + * @author Brian Goetz + */ +public class MethodRefCaptureTest extends ComboTestBase { + @Factory + public static Object[] testCombo() throws Exception { + return factory(MethodRefCaptureTest.class); + } + + @DimensionVar("VAR") ContextKind context; + @DimensionVar("LOCATION") LocationKind location; + @DimensionVar("ACC") AccessibilityKind accessibility; + @DimensionVar("METHOD") RefKind ref; + + @TemplateVar("PACKAGE") + String makePackage() { + return location == LocationKind.OTHER_PACKAGE ? "package a;" : ""; + } + + // @@@ not yet used + @TemplateVar("MAIN") String main = "public static void main(String[] args) { #{METHOD.SAMTYPE} x = #{VAR.REF}"; + + @SourceFile("Sam1.java") String sam1 = "#{PACKAGE} \npublic interface Sam1 { public String get(String s); }"; + @SourceFile("Sam2.java") String sam2 = "#{PACKAGE} \npublic interface Sam2 { public String get(T target, String s); }"; + @SourceFile("Sam3.java") String sam3 = "#{PACKAGE} \npublic interface Sam3 { public T get(String s); }"; + @SourceFile("A.java") String mainFile = "#{LOCATION.CAPTURING_CLASS}"; + @SourceFile("Target.java") String extFile = "#{LOCATION.EXT_CLASS}"; + + @Override + protected String[] getCompileOptions(String group) { + return new String[] { "-XDlambdaToMethod" }; + } + + @Override + protected void postCompile(String group) { + if (location == LocationKind.OTHER_FILE && accessibility == AccessibilityKind.PRIVATE) + assertCompileFailed(); + else if (location == LocationKind.OTHER_PACKAGE && accessibility != AccessibilityKind.PUBLIC) + assertCompileFailed(); + else + assertCompileSucceeded(); + } + + + static enum ContextKind implements Template { + STATIC_FIELD_INIT("static #{METHOD.SAMTYPE} var = #{METHOD.MREF};"), + STATIC_FIELD_CLINIT("static #{METHOD.SAMTYPE} var; static { var = #{METHOD.MREF}; };"), + INSTANCE_FIELD_INIT("#{METHOD.SAMTYPE} var = #{METHOD.MREF};"), + LOCAL_VAR("void m() { #{METHOD.SAMTYPE} var = #{METHOD.MREF}; };"), + METHOD_CALL("static void m(#{METHOD.SAMTYPE} s) { }; static void m() { m(#{METHOD.MREF}); };"), + RETURN("#{METHOD.SAMTYPE} m() { return #{METHOD.MREF}; };"), + ARRAY_INITIALIZER("#{METHOD.SAMTYPE}[] var = (#{METHOD.SAMTYPE}[]) new #{METHOD.ERASED_SAMTYPE}[] { (#{METHOD.SAMTYPE}) #{METHOD.MREF} };"), + CONDITIONAL("#{METHOD.SAMTYPE} var = new Object().equals(new Object()) ? #{METHOD.MREF} : #{METHOD.MREF};"), + CAST("#{METHOD.SAMTYPE} var = (#{METHOD.SAMTYPE}) #{METHOD.MREF};"); + + private final String t1; + + ContextKind(String t1) { this.t1 = t1; } + + public String expand(String selector) { + switch (selector) { + case "DECL": return t1; + default: throw new IllegalArgumentException(selector); + } + } + } + + static enum LocationKind implements Template { + SAME_CLASS("class Target { \n#{VAR.DECL} \n#{METHOD.DECL} }"), + ENCLOSING_CLASS("class Target { \n#{METHOD.DECL} \nstatic class Capturing { #{VAR.DECL} } }"), + SIBLING_INNER_CLASS("class Outer { \nstatic class Capturing { #{VAR.DECL} } \nstatic class Target { #{METHOD.DECL} } }"), + NESTED_CLASS("class Capturing { \n#{VAR.DECL} \nstatic class Target { #{METHOD.DECL} } }"), + OTHER_FILE("class Capturing { \n#{VAR.DECL} }", "class Target { \n#{METHOD.DECL} }"), + OTHER_PACKAGE("package a; \nimport b.*; \nclass Capturing { \n#{VAR.DECL} }", + "package b; \npublic class Target { \n#{METHOD.DECL} }"); + + private final String t1, t2; + + LocationKind(String t1, String t2) { + this.t1 = t1; + this.t2 = t2; + } + LocationKind(String t1) { this(t1, "class Unused {}"); } + + public String expand(String selector) { + switch (selector) { + case "CAPTURING_CLASS": return t1; + case "EXT_CLASS": return t2; + default: throw new IllegalArgumentException(selector); + } + } + } + + static enum AccessibilityKind implements Template { + PUBLIC("public"), + PROTECTED("protected"), + PACKAGE(""), + PRIVATE("private"); + + private final String template; + + AccessibilityKind(String template) { this.template = template; } + + public String expand(String selector) { return template; } + } + + static enum RefKind implements Template { + STATIC(0, "Target::staticMethod", "static #{ACC} String staticMethod(String s) { return \"1\"; }"), + UNBOUND_INSTANCE(1, "Target::instanceMethod", "#{ACC} String instanceMethod(String s) { return \"2\"; }"), + BOUND_INSTANCE(0, "(new Target())::instanceMethod", "#{ACC} String instanceMethod(String s) { return \"3\"; }"), + CTOR(2, "Target::new", "#{ACC} Target(String s) { }"), +// UNBOUND_INNER_CTOR, +// BOUND_INNER_CTOR +// , SUPER + ; + + private static final String[] sams = { "Sam1", "Sam2", "Sam3" }; + private final int samNo; + private final String t1, t2; + + RefKind(int samNo, String t1, String t2) { this.samNo = samNo; this.t1 = t1; this.t2 = t2; } + + public String expand(String selector) { + switch (selector) { + case "MREF": return t1; + case "DECL": return t2; + case "SAMTYPE": return sams[samNo]; + case "ERASED_SAMTYPE": return sams[samNo].replaceAll("", ""); + default: throw new IllegalArgumentException(selector); + } + } + } +} + diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/NestedGenericMethodCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/NestedGenericMethodCallTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,410 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import org.testng.annotations.Factory; +import org.testng.annotations.Test; +import tools.javac.combo.ComboTestBase; +import tools.javac.combo.DimensionVar; +import tools.javac.combo.SourceFile; +import tools.javac.combo.Template; + +import static tools.javac.combo.StackProcessingUtils.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * NestedGenericMethodCallTest + */ +public class NestedGenericMethodCallTest extends ComboTestBase { + @Factory + public static Object[] testNestedGenericMethodCallType() throws Exception { + return factory(NestedGenericMethodCallTest.class); + } + + @Test(enabled=false) + public void test() throws Exception { + //disabled as the test has never been updated to support graph inference + super.test(); + } + + @DimensionVar("ID_METHOD") IdMethod idMethod; + @DimensionVar("NIL_METHOD") NilMethod nilMethod; + @DimensionVar("CONS_METHOD") ConsMethod consMethod; + @DimensionVar("SHAPE") Shape shape; + @DimensionVar("TARGET") Type target; + + @SourceFile("Main.java") + String clientFile = "import java.util.*;\n" + +"public class Main {\n" + +" #{ID_METHOD}\n" + +" #{NIL_METHOD}\n" + +" #{CONS_METHOD}\n" + +" void test() { \n" + + " #{TARGET} t = #{SHAPE};\n" + + " }\n" + +"}"; + + @Override + protected void postCompile(String grp) { + Type res = shape.compile(idMethod, nilMethod, consMethod, target); + if (res.asSubtypeOf(target).isError()) { + assertCompileFailed("Bad result = " + res); + } else { + assertCompileSucceeded(); + } + } + + @Override + protected boolean shouldSkip() { + return target.free || target == Type.ERROR; + } + + enum Type implements Template { + Z("Z", true), + OBJECT("Object", false), + STRING("String", false), + LIST_Z("List", true), + LIST_OBJECT("List", false), + LIST_STRING("List", false), + ERROR("", false); + + String typeStr; + boolean free; + + Type(String typeStr, boolean free) { + this.typeStr = typeStr; + this.free = free; + } + + boolean isError() { + return this == ERROR; + } + + Type asSubtypeOf(Type that) { + return asSubtypeMap[this.ordinal()][that.ordinal()]; + } + + boolean isSubtypeOf(Type that) { + return !asSubtypeOf(that).isError(); + } + + public String expand(String selector) { + return typeStr; + } + + enum ConstraintKind { + Z_EXT_OBJ(false, OBJECT), + Z_EXT_STRING(false, STRING), + Z_EXT_LIST_OBJECT(false, LIST_OBJECT), + Z_EXT_LIST_STRING(false, STRING), + Z_SUP_OBJECT(true, OBJECT), + Z_SUP_STRING(true, STRING), + Z_SUP_LIST_OBJECT(true, LIST_OBJECT), + Z_SUP_LIST_STRING(true, LIST_STRING), + ERROR(false, Type.ERROR); + + boolean isSuper; + Type type; + + ConstraintKind(boolean isSuper, Type type) { + this.isSuper = isSuper; + this.type = type; + } + } + + static Type[][] asSubtypeMap = new Type[][] { + // Z OBJECT STRING LIST_Z LIST_OBJECT LIST_STRING ERROR + { /* Z */ OBJECT ,OBJECT ,STRING ,ERROR ,LIST_OBJECT ,LIST_STRING ,ERROR }, + { /* OBJECT */ OBJECT ,OBJECT ,ERROR ,ERROR ,ERROR ,ERROR ,ERROR }, + { /* STRING */ STRING ,STRING ,STRING ,ERROR ,ERROR ,ERROR ,ERROR }, + { /* LIST_Z */ LIST_OBJECT,LIST_OBJECT,ERROR ,LIST_OBJECT,LIST_OBJECT ,LIST_STRING ,ERROR }, + { /* LIST_OBJECT */ LIST_OBJECT,LIST_OBJECT,ERROR ,LIST_OBJECT,LIST_OBJECT ,ERROR ,ERROR }, + { /* LIST_STRING */ LIST_STRING,LIST_STRING,ERROR ,LIST_STRING,ERROR ,LIST_STRING ,ERROR }, + { /* ERROR */ ERROR ,ERROR ,ERROR ,ERROR ,ERROR ,ERROR ,ERROR }}; + + static boolean isSubtypes(Type[] ts1, Type[] ts2) { + assertEquals(ts1.length, ts2.length); + for (int i = 0; i < ts1.length ; i++) { + if (!ts1[i].isSubtypeOf(ts2[i])) return false; + } + return true; + } + + static Type listOf(Type t) { + switch (t) { + case OBJECT: return LIST_OBJECT; + case STRING: return LIST_STRING; + case Z: return LIST_Z; + default: return ERROR; + } + } + + static Type elemtype(Type t) { + switch (t) { + case LIST_OBJECT: return OBJECT; + case LIST_STRING: return STRING; + case LIST_Z: return Z; + default: return ERROR; + } + } + + static Type lub(Type t1, Type t2) { + if (!t1.asSubtypeOf(t2).isError()) { + return t2; + } else if (!t2.asSubtypeOf(t1).isError()) { + return t1; + } else { + return Type.ERROR; + } + } + } + + interface MethodSig { + Type apply(Type target, Type... argTypes); + Type[] getFormals(); + } + + enum IdMethod implements Template, MethodSig { + NON_GENERIC_1("String id(String s) { return null; };", Type.STRING), + NON_GENERIC_2("List id(List s) { return null; };", Type.LIST_STRING), + GENERIC_1(" Z id(Z z) { return null; };", Type.Z), + GENERIC_2(" List id(List z) { return null; };", Type.LIST_Z); + + String sig; + Type formal; + + IdMethod(String sig, Type formal) { + this.sig = sig; + this.formal = formal; + } + + public String expand(String selector) { + return sig; + } + + public Type apply(Type target, Type... argTypes) { + return argTypes[0].asSubtypeOf(formal); + } + + public Type[] getFormals() { + return new Type[] { formal }; + } + } + + enum NilMethod implements Template, MethodSig { + NON_GENERIC("List nil() { return null; }", Type.LIST_STRING), + GENERIC(" List nil() { return null; }", Type.LIST_Z); + + String sig; + Type returnType; + + NilMethod(String sig, Type returnType) { + this.sig = sig; + this.returnType = returnType; + } + + public String expand(String selector) { + return sig; + } + + public Type apply(Type target, Type... argTypes) { + return this == NON_GENERIC ? + Type.LIST_STRING : + returnType.asSubtypeOf(target); + } + + public Type[] getFormals() { + return null; + } + } + + enum ConsMethod implements Template, MethodSig { + NON_GENERIC("List cons(String s, List ls) { return null; }", Type.STRING, Type.LIST_STRING) { + Type getReturnType(Type target, Type... argTypes) { return Type.LIST_STRING; } + }, + GENERIC_1(" List cons(Z z, List ls) { return null; }", Type.Z, Type.LIST_STRING) { + Type getReturnType(Type target, Type... argTypes) { + switch (target) { + case LIST_OBJECT: + case LIST_STRING: + return Type.LIST_Z.asSubtypeOf(target); + default: + return Type.listOf(argTypes[0].asSubtypeOf(Type.Z)); + } + } + }, + GENERIC_2(" List cons(String s, List lz) { return null; }", Type.STRING, Type.LIST_Z) { + Type getReturnType(Type target, Type... argTypes) { return Type.listOf(Type.elemtype(argTypes[1].asSubtypeOf(Type.LIST_Z))); } + }, + GENERIC_3(" List cons(Z z, List lz) { return null; }", Type.Z, Type.LIST_Z) { + Type getReturnType(Type target, Type... argTypes) { + Type lub = Type.lub(argTypes[0], Type.elemtype(argTypes[1].asSubtypeOf(Type.LIST_Z))); + return lub.isError() ? lub : Type.listOf(lub); + } + }, + GENERIC_4(" List cons(U z, List lz) { return null; }", Type.Z, Type.LIST_Z) { + Type getReturnType(Type target, Type... argTypes) { + switch (target) { + case LIST_OBJECT: + case LIST_STRING: + return Type.LIST_Z.asSubtypeOf(target); + default: + return Type.listOf(argTypes[0].asSubtypeOf(Type.Z)); + } + } + }; + + String sig; + Type[] formals; + + ConsMethod(String sig, Type... formals) { + this.sig = sig; + this.formals = formals; + } + + public String expand(String selector) { + return sig; + } + + public Type apply(Type target, Type... argTypes) { + return Type.isSubtypes(argTypes, formals) ? + getReturnType(target, argTypes) : Type.ERROR; + } + + abstract Type getReturnType(Type target, Type... argTypes); + + public Type[] getFormals() { + return formals; + } + } + + enum Token implements StackItem { + NIL(0, "nil"), + DIAMOND(0, "new ArrayList<>"), + STRING(0, "\"\""), + ID(1, "id"), + CONS(2, "cons"); + + int arity; + String tokenStr; + + Token(int arity, String tokenStr) { + this.arity = arity; + this.tokenStr = tokenStr; + } + + public int arity() { return arity; } + } + + enum Shape implements Template { + NIL(Token.NIL), + ID_NIL(Token.ID, Token.NIL), + ID_ID_NIL(Token.ID, Token.ID, Token.NIL), + CONS_STRING_NIL(Token.CONS, Token.STRING, Token.NIL), + CONS_STRING_ID_NIL(Token.CONS, Token.STRING, Token.ID, Token.NIL), + CONS_ID_STRING_NIL(Token.CONS, Token.ID, Token.STRING, Token.NIL), + CONS_ID_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL), + CONS_ID_STRING_CONS_STRING_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.NIL), + CONS_ID_STRING_CONS_ID_STRING_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.NIL), + CONS_ID_STRING_CONS_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.ID, Token.NIL), + CONS_ID_STRING_CONS_ID_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL), + CONS_ID_STRING_ID_CONS_ID_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL), + ID_CONS_ID_STRING_ID_CONS_ID_STRING_ID_NIL(Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL), + DIAMOND(Token.DIAMOND), + ID_DIAMOND(Token.ID, Token.DIAMOND), + CONS_STRING_DIAMOND(Token.CONS, Token.STRING, Token.DIAMOND), + CONS_STRING_ID_DIAMOND(Token.CONS, Token.STRING, Token.ID, Token.DIAMOND), + CONS_ID_STRING_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.DIAMOND), + CONS_ID_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND), + CONS_ID_STRING_CONS_STRING_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.DIAMOND), + CONS_ID_STRING_CONS_ID_STRING_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.DIAMOND), + CONS_ID_STRING_CONS_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.ID, Token.DIAMOND), + CONS_ID_STRING_CONS_ID_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND), + CONS_ID_STRING_ID_CONS_ID_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND), + ID_CONS_ID_STRING_ID_CONS_ID_STRING_ID_DIAMOND(Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND); + + Token[] tokens; + + Shape(Token... tokens) { + this.tokens = tokens; + } + + Type compile(final IdMethod idMethod, final NilMethod nilMethod, final ConsMethod consMethod, Type target) { + return process(tokens, new StackReducer() { + public Type reduce(Token t, Type[] operands, Type target) { + switch (t) { + case DIAMOND: return Type.LIST_Z.asSubtypeOf(target); + case NIL: return nilMethod.apply(target, operands); + case STRING: return Type.STRING; + case ID: return idMethod.apply(target, operands); + case CONS: return consMethod.apply(target, operands); + default: throw new AssertionError(); + } + } + public Class resultToken() { return Type.class; } + public Type reducerArg(Token item, int i) { + switch (item) { + case ID: + return idMethod.getFormals()[i]; + case CONS: + return consMethod.getFormals()[i]; + default: return Type.OBJECT; + } + } + }, target); + } + + public String expand(String selector) { + return process(tokens, new StackReducer() { + public String reduce(Token t, String[] operands, Void _unused) { + switch (t) { + case DIAMOND: + case NIL: + case ID: + case CONS: + StringBuilder buf = new StringBuilder(); + String sep = ""; + for (int i = 0; i < t.arity; i ++) { + buf.append(sep); + buf.append(operands[i]); + sep = ","; + } + buf.insert(0, "("); + buf.insert(0, t.tokenStr); + buf.append(")"); + return buf.toString(); + case STRING: + return t.tokenStr; + default: throw new AssertionError(); + } + } + public Class resultToken() { return String.class; } + public Void reducerArg(Token item, int i) { return null; } + }, null); + } + } +} + diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/SourceTargetVersionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/SourceTargetVersionTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,180 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.testng.annotations.Factory; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import tools.javac.combo.*; + +/** + * SourceTargetVersionTest: + * Test source and class file compatibility by compiling and running lambda specific code + * against some class files compiled separately with different source and target option + * (1.5, 1.6, and 1.7). + * The goal is achieved by putting source files in different groups (A, B, C..,), each group + * is set with its own compile options, and we compile in the reverse alphebetic order for the + * groups (..., C, B, A) to set a previously compiled group of files as classpath for the next group. + * And when executing, we Run class Main with classpath A:B:C... in the order. + * + */ +public class SourceTargetVersionTest extends ComboTestBase { + @Factory + public static Object[] testSourceTarget() throws Exception { + return factory(SourceTargetVersionTest.class); + } + + @DimensionVar("SHAPE") CShapes shapeType; + @DimensionVar("CLIENT_CODE") ClientType clientType; + @DimensionVar("RELEASE") ReleaseVersion rv; + + @SourceFile(value="A.java", group="B") + String interfaceA = "interface A { #{SHAPE.METHOD} }"; + + @SourceFile(value="B.java", group="A") + String interfaceB = "interface B #{SHAPE.EXTEND} { default String m() { return \"B\"; } }"; + + @SourceFile(value="C.java", group="A") + String classC = "class C #{SHAPE.IMPLEMENT} {\n" + + " #{CLIENT_CODE}\n" + + "}"; + + @SourceFile(value="Main.java", group="A") + String classMain = "public class Main {\n" + + " public String main() {\n" + + " return new C().m();\n" + + " }\n" + + "}"; + + @TemplateVar("LAMBDA_EXP") String le = "public String m() {\n" + + " A a = () -> \"A\";\n" + + " return a.m();\n" + + "}"; + @TemplateVar("METHOD_REF") String mr = "String foo() {\n" + + " return \"foo\";\n" + + "}\n\n" + + + "public String m() {\n" + + " A a = this::foo;\n" + + " return a.m();\n" + + "}"; + + @Override + protected boolean shouldSkip() { + return (shapeType == CShapes.C_AB && clientType != ClientType.DEF_MED) || + (shapeType == CShapes.C && clientType == ClientType.DEF_MED); + } + + @Override + protected boolean shouldRun() { return true; } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Method m = clazz.getMethod("main"); + Object obj = clazz.newInstance(); + String result = (String) m.invoke(obj); + String expected = clientType.returnValue; + assertEquals(result, expected); + } + + @Override + protected String[] getCompileOptions(String group) { + switch(group) { + case "B": return new String[]{"-source", rv.versionStr, "-target", rv.versionStr}; + default: return new String[0]; + } + } + + enum CShapes implements Template { //shapes of class hirarchy + //class C implements interface A, B + C_AB("", "", "implements A, B"), + //class C implments interface B, B extends interface A + C_B_A("String m();", "extends A", "implements B"), + //class C + C("String m();", "", ""); + + private final String absMethod; + private final String extend; + private final String implement; + + CShapes(String absMethod, String extend, String implement) { + this.absMethod = absMethod; + this.extend = extend; + this.implement = implement; + } + + public String expand(String selector) { + switch(selector) { + case "METHOD": return absMethod; + case "EXTEND": return extend; + case "IMPLEMENT": return implement; + default: return toString(); + } + } + } + + enum ClientType implements Template { // jdk8 specific code in client program + LAMBDA_EXP("#{LAMBDA_EXP}", "A"), // lambda expressions + METHOD_REF("#{METHOD_REF}", "foo"), // method references + DEF_MED("", "B"); // default method inheritance + + private final String clientCode; + private final String returnValue; + + ClientType(String str, String ret) { + clientCode = str; + returnValue = ret; + } + + public String expand(String selector) { + return clientCode; + } + } + + enum ReleaseVersion implements Template { + FIVE("1.5"), + SIX("1.6"), + SEVEN("1.7"); + + final String versionStr; + + ReleaseVersion(String vstr) { + versionStr = vstr; + } + + public String expand(String selector) { + return toString(); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e combo-tests/tests/tools/javac/lambda/StaticMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/combo-tests/tests/tools/javac/lambda/StaticMethodTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,155 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 tools.javac.lambda; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +import org.testng.annotations.Factory; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import tools.javac.combo.*; + +/** + * StaticMethodTest: Test static methods in interfaces by running bytecode + * compiled at different times; where a static method is added/declared + * in one interface and only that interface is recompiled. + * + * Static methods in interface are not inherited and + * are not visible to any implementing (extending) classes (interfaces). + * @bug 8005968 + * @author sogoel + * + */ +public class StaticMethodTest extends ComboTestBase { + @Factory + public static Object[] testStaticMethod() throws Exception { + return factory(StaticMethodTest.class); + } + + @DimensionVar("SHAPE") CShapes shapeType; + + @DimensionVar("ADD") AddType addType; + + @SourceFile(value="B.java", group="A") + String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{ADD} }"; + + @SourceFile(value="B.java", group="B") + String interfaceB = "interface B #{SHAPE.B_DECL} {}"; + + @SourceFile(value="A.java", group="B") + String interfaceA = "interface A { static String m() { return \"A\"; } }"; + + @SourceFile(value="C.java", group="B") + String classC = "#{SHAPE.C}"; + + @SourceFile(value="Main.java", group="B") + String classMain = "public class Main {\n" + + " public String main() {\n" + + " return new C().m();\n" + + " }\n" + + "}"; + + @Override + protected boolean shouldRun() { return true; } + + @Override + protected void run(Class clazz) throws ReflectiveOperationException { + Method m = clazz.getMethod("main"); + Object obj = clazz.newInstance(); + String result = null, output = null; + try { + result = (String) m.invoke(obj); + } catch (InvocationTargetException ex) { + output = ex.getCause().toString(); + } + assertEquals(output, null); + assertEquals(result, "C"); + } + + /* + * In order for class Main to compile in group B, object of class C should have + * access to a method m(). Therefore, a method m() is needed in class C. + * static m() in interfaces A, B is not visible to C. + */ + static String methodSig = "public String m () { return \"C\"; }"; + enum CShapes implements Template { //shapes of class hierarchy + //class C implements interface A, B + C_AB("", + "class C implements A, B { " + methodSig + " }"), + //class C implements interface B, B extends interface A + C_B_A("extends A", + "class C implements B { " + methodSig + " }"), + //class C implements interface AB, AB extends interface A, B + C_I_AB("", + "interface AB extends A, B { }\n" + + "class C implements AB { " + methodSig + " }"), + //class C implements interface AB, AB extends interface A, B and defines its own static method + C_I_AB2("", + "interface AB extends A, B { static String m() { return \"AB\"; } }\n" + + "class C implements AB { " + methodSig + " }"), + //class C extends Class D implements Interface B + C_CI("", + "class D { public String m() { return \"D\"; } }\n" + + "class C extends D implements B { " + methodSig + " }"); + + private final String sB_DECL; + private final String sC; + + CShapes(String sB_DECL, String sC) { + this.sB_DECL = sB_DECL; + this.sC = sC; + } + + public String expand(String selector) { + switch(selector) { + case "B_DECL": return sB_DECL; + case "C": return sC; + default: return toString(); + } + } + } + + enum AddType implements Template { // add by adding static method or abstract interface method + ADD("static String m() { return \"B\"; }"), + REDECLARE("String m();"); + + final String newCode; + + AddType(String str) { + newCode = str; + } + + public String expand(String selector) { + return newCode; + } + } +} + diff -r f82b730c798b -r 99dd9e50f37e make/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/com/sun/crypto/provider/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/com/sun/net/httpserver/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/common/Defs.gmk diff -r f82b730c798b -r 99dd9e50f37e make/common/Release.gmk diff -r f82b730c798b -r 99dd9e50f37e make/common/internal/Defs-langtools.gmk --- a/make/common/internal/Defs-langtools.gmk Thu Oct 31 16:44:18 2013 -0700 +++ b/make/common/internal/Defs-langtools.gmk Mon Nov 11 23:17:30 2013 -0800 @@ -28,7 +28,8 @@ IMPORT_RT_PACKAGES += \ javax/annotation/processing \ javax/lang/model \ - javax/tools + javax/tools \ + com/sun/runtime IMPORT_TOOLS_PACKAGES += \ com/sun/javadoc \ diff -r f82b730c798b -r 99dd9e50f37e make/common/shared/Defs-control.gmk diff -r f82b730c798b -r 99dd9e50f37e make/common/shared/Defs-java.gmk diff -r f82b730c798b -r 99dd9e50f37e make/common/shared/Sanity-Settings.gmk diff -r f82b730c798b -r 99dd9e50f37e make/common/shared/Sanity.gmk diff -r f82b730c798b -r 99dd9e50f37e make/docs/CORE_PKGS.gmk diff -r f82b730c798b -r 99dd9e50f37e make/docs/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/docs/NON_CORE_PKGS.gmk --- a/make/docs/NON_CORE_PKGS.gmk Thu Oct 31 16:44:18 2013 -0700 +++ b/make/docs/NON_CORE_PKGS.gmk Mon Nov 11 23:17:30 2013 -0800 @@ -84,6 +84,8 @@ SCTPAPI_PKGS = com.sun.nio.sctp +LAMBDA_RTAPI = com.sun.runtime + ifeq ($(PLATFORM), macosx) APPLE_EXT_PKGS = com.apple.concurrent \ com.apple.eawt \ @@ -101,5 +103,6 @@ $(HTTPSERVER_PKGS) \ $(SMARTCARDIO_PKGS) \ $(SCTPAPI_PKGS) \ + $(LAMBDA_RTAPI) \ $(APPLE_EXT_PKGS) diff -r f82b730c798b -r 99dd9e50f37e make/java/invoke/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/java/java/FILES_java.gmk --- a/make/java/java/FILES_java.gmk Thu Oct 31 16:44:18 2013 -0700 +++ b/make/java/java/FILES_java.gmk Mon Nov 11 23:17:30 2013 -0800 @@ -300,12 +300,20 @@ java/util/EnumMap.java \ java/util/Arrays.java \ java/util/ArraysParallelSortHelpers.java \ + java/util/ArrayPrefixHelpers.java \ + java/util/ArraySortHelpers.java \ java/util/DualPivotQuicksort.java \ java/util/TimSort.java \ java/util/ComparableTimSort.java \ + java/util/Comparators.java \ java/util/ConcurrentModificationException.java \ + java/util/OptionalDouble.java \ + java/util/OptionalInt.java \ + java/util/Optional.java \ + java/util/OptionalLong.java \ java/util/ServiceLoader.java \ java/util/ServiceConfigurationError.java \ + java/util/StringJoiner.java \ java/util/Timer.java \ java/util/TimerTask.java \ java/util/Objects.java \ @@ -334,6 +342,8 @@ java/util/concurrent/CyclicBarrier.java \ java/util/concurrent/DelayQueue.java \ java/util/concurrent/Delayed.java \ + java/util/concurrent/DoubleAdder.java \ + java/util/concurrent/DoubleMaxUpdater.java \ java/util/concurrent/Exchanger.java \ java/util/concurrent/ExecutionException.java \ java/util/concurrent/Executor.java \ @@ -348,6 +358,10 @@ java/util/concurrent/LinkedBlockingDeque.java \ java/util/concurrent/LinkedBlockingQueue.java \ java/util/concurrent/LinkedTransferQueue.java \ + java/util/concurrent/LongAdder.java \ + java/util/concurrent/LongAdderTable.java \ + java/util/concurrent/LongMaxUpdater.java \ + java/util/concurrent/package-info.java \ java/util/concurrent/Phaser.java \ java/util/concurrent/PriorityBlockingQueue.java \ java/util/concurrent/RecursiveAction.java \ @@ -360,6 +374,8 @@ java/util/concurrent/ScheduledFuture.java \ java/util/concurrent/ScheduledThreadPoolExecutor.java \ java/util/concurrent/Semaphore.java \ + java/util/concurrent/SequenceLock.java \ + java/util/concurrent/Striped64.java \ java/util/concurrent/SynchronousQueue.java \ java/util/concurrent/ThreadFactory.java \ java/util/concurrent/ThreadLocalRandom.java \ @@ -379,18 +395,17 @@ java/util/concurrent/atomic/AtomicReferenceArray.java \ java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java \ java/util/concurrent/atomic/AtomicStampedReference.java \ - java/util/concurrent/atomic/DoubleAccumulator.java \ - java/util/concurrent/atomic/DoubleAdder.java \ - java/util/concurrent/atomic/LongAccumulator.java \ - java/util/concurrent/atomic/LongAdder.java \ - java/util/concurrent/atomic/Striped64.java \ + java/util/concurrent/atomic/package-info.java \ + java/util/concurrent/extra/AtomicDoubleArray.java \ + java/util/concurrent/extra/AtomicDouble.java \ + java/util/concurrent/extra/ReadMostlyVector.java \ java/util/concurrent/locks/AbstractOwnableSynchronizer.java \ java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java \ java/util/concurrent/locks/AbstractQueuedSynchronizer.java \ - java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java \ java/util/concurrent/locks/Condition.java \ java/util/concurrent/locks/Lock.java \ java/util/concurrent/locks/LockSupport.java \ + java/util/concurrent/locks/package-info.java \ java/util/concurrent/locks/ReadWriteLock.java \ java/util/concurrent/locks/ReentrantLock.java \ java/util/concurrent/locks/ReentrantReadWriteLock.java \ diff -r f82b730c798b -r 99dd9e50f37e make/java/java/Makefile --- a/make/java/java/Makefile Thu Oct 31 16:44:18 2013 -0700 +++ b/make/java/java/Makefile Mon Nov 11 23:17:30 2013 -0800 @@ -37,7 +37,7 @@ JAVAC_MAX_WARNINGS=true include $(BUILDDIR)/common/Defs.gmk -AUTO_FILES_JAVA_DIRS = java/util/function +AUTO_FILES_JAVA_DIRS = java/util/concurrent java/util/function java/util/stream # windows compiler flags ifeq ($(PLATFORM),windows) @@ -51,7 +51,7 @@ OTHER_CFLAGS += -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \ -DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"' \ -DJDK_MICRO_VERSION='"$(JDK_MICRO_VERSION)"' \ - -DJDK_BUILD_NUMBER='"$(JDK_BUILD_NUMBER)"' + -DJDK_BUILD_NUMBER='"$(JDK_BUILD_NUMBER)"' ifdef JDK_UPDATE_VERSION OTHER_CFLAGS += -DJDK_UPDATE_VERSION='"$(JDK_UPDATE_VERSION)"' @@ -281,7 +281,7 @@ $(GENSRCDIR)/java/lang/UNIXProcess.java: $(PLATFORM_UNIX_PROCESS) $(install-file) -clean:: +clean:: $(RM) $(GENSRCDIR)/java/lang/UNIXProcess.java endif @@ -295,10 +295,10 @@ # # Special rules. # -clean:: +clean:: $(RM) -r $(CLASSHDRDIR) -clobber:: +clobber:: $(RM) -r $(CLASSBINDIR)/java/io $(CLASSBINDIR)/java/lang \ $(CLASSBINDIR)/java/security $(CLASSBINDIR)/java/util \ $(CLASSBINDIR)/sun/misc @@ -315,12 +315,6 @@ CAL_PROPS = calendars.properties # -# Rule to copy Hijrah-umalqura calendar properties file. -# -HIJRAH_UMALQURA_PROPS = hijrah-config-umalqura.properties - - -# # Rule to copy tzmappings file on Windows # ifeq ($(PLATFORM), windows) @@ -332,7 +326,7 @@ $(call chmod-file, 444) endif -build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(LIBDIR)/$(HIJRAH_UMALQURA_PROPS) $(TZMAP) +build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(TZMAP) $(LIBDIR)/$(PROPS): $(PLATFORM_SRC)/lib/$(PROPS) $(install-file) @@ -340,10 +334,7 @@ $(LIBDIR)/$(CAL_PROPS): $(SHARE_SRC)/lib/$(CAL_PROPS) $(install-file) -$(LIBDIR)/$(HIJRAH_UMALQURA_PROPS): $(SHARE_SRC)/lib/$(HIJRAH_UMALQURA_PROPS) - $(install-file) - -clean:: +clean:: $(RM) -r $(LIBDIR)/$(PROPS) $(TZMAP) # @@ -364,12 +355,12 @@ $(MV) $@.temp $@ $(call chmod-file, 444) -clean:: +clean:: $(RM) $(CURDATA) # -# Rules to create $(GENSRCDIR)/sun/lang/CharacterData*.java +# Rules to create $(GENSRCDIR)/sun/lang/CharacterData*.java # CHARACTERDATA = $(BUILDDIR)/tools/GenerateCharacter UNICODEDATA = $(BUILDDIR)/tools/UnicodeData @@ -424,12 +415,12 @@ $(install-file) clean:: - $(RM) $(GENSRCDIR)/java/lang/CharacterDataLatin1.java + $(RM) $(GENSRCDIR)/java/lang/CharacterDataLatin1.java $(RM) $(GENSRCDIR)/java/lang/CharacterData00.java - $(RM) $(GENSRCDIR)/java/lang/CharacterData01.java + $(RM) $(GENSRCDIR)/java/lang/CharacterData01.java $(RM) $(GENSRCDIR)/java/lang/CharacterData02.java $(RM) $(GENSRCDIR)/java/lang/CharacterData0E.java - $(RM) $(GENSRCDIR)/java/lang/CharacterDataUndefined.java + $(RM) $(GENSRCDIR)/java/lang/CharacterDataUndefined.java $(RM) $(GENSRCDIR)/java/lang/CharacterDataPrivateUse.java # @@ -450,7 +441,7 @@ build.tools.generatecharacter.CharacterName \ $(UNICODEDATA)/UnicodeData.txt $(UNINAME) -clean:: +clean:: $(RM) $(UNINAME) # @@ -458,15 +449,15 @@ # # -# Rule to precompile CoreResourceBundleControl.java +# Rule to precompile CoreResourceBundleControl.java # LOCALES_GEN_SH = localelist.sh $(GENSRCDIR)/sun/util/CoreResourceBundleControl.java: \ $(SHARE_SRC)/classes/sun/util/CoreResourceBundleControl-XLocales.java.template $(LOCALES_GEN_SH) - @$(prep-target) + @$(prep-target) NAWK="$(NAWK)" SED="$(SED)" $(SH) $(LOCALES_GEN_SH) "$(JRE_NONEXIST_LOCALES)" \ - $< $@ + $< $@ clean:: $(RM) $(GENSRCDIR)/sun/util/CoreResourceBundleControl.java diff -r f82b730c798b -r 99dd9e50f37e make/java/nio/FILES_java.gmk diff -r f82b730c798b -r 99dd9e50f37e make/java/nio/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/java/sun_nio/FILES_java.gmk diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/README diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/awt2d/nbproject/project.xml diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/common/README-ent diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/common/architectures/arch-x86_64.properties diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/common/architectures/name-Macosx.properties diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/common/java-data-native.ent diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/common/java-data-no-native.ent diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/common/properties.ent diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/common/shared.xml --- a/make/netbeans/common/shared.xml Thu Oct 31 16:44:18 2013 -0700 +++ b/make/netbeans/common/shared.xml Mon Nov 11 23:17:30 2013 -0800 @@ -77,10 +77,10 @@ System configuration claims architecture is ${platform}-${arch} - + - + diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/j2se/build.xml diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/j2se/nbproject/project.xml diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/jarzip/nbproject/project.xml diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/jconsole/nbproject/project.xml diff -r f82b730c798b -r 99dd9e50f37e make/netbeans/jmx/nbproject/project.xml diff -r f82b730c798b -r 99dd9e50f37e make/org/Makefile --- a/make/org/Makefile Thu Oct 31 16:44:18 2013 -0700 +++ b/make/org/Makefile Mon Nov 11 23:17:30 2013 -0800 @@ -31,7 +31,7 @@ PRODUCT = org include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = ietf jcp +SUBDIRS = asm ietf jcp include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: diff -r f82b730c798b -r 99dd9e50f37e make/sun/nio/cs/FILES_java.gmk diff -r f82b730c798b -r 99dd9e50f37e make/sun/osxapp/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/sun/security/other/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/sun/util/Makefile diff -r f82b730c798b -r 99dd9e50f37e make/tools/CharsetMapping/DoubleByte-X.java.template diff -r f82b730c798b -r 99dd9e50f37e make/tools/CharsetMapping/JIS_X_0201.map diff -r f82b730c798b -r 99dd9e50f37e make/tools/CharsetMapping/dbcs diff -r f82b730c798b -r 99dd9e50f37e make/tools/CharsetMapping/extsbcs diff -r f82b730c798b -r 99dd9e50f37e make/tools/src/build/tools/charsetmapping/DBCS.java diff -r f82b730c798b -r 99dd9e50f37e make/tools/src/build/tools/charsetmapping/SBCS.java diff -r f82b730c798b -r 99dd9e50f37e makefiles/CompileNativeLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/CreateJars.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/CreateSecurityJars.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/Setup.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/Awt2dLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/CoreLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/NetworkingLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/NioLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/PlatformLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/SecurityLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/ServiceabilityLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e makefiles/lib/SoundLibraries.gmk diff -r f82b730c798b -r 99dd9e50f37e src/macosx/native/sun/osxapp/NSApplicationAWT.m diff -r f82b730c798b -r 99dd9e50f37e src/share/bin/java.c diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/com/sun/tools/jdi/EventSetImpl.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/awt/EventDispatchThread.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/beans/EventHandler.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/io/BufferedReader.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/io/Reader.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/io/UncheckedIOException.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/AbstractStringBuilder.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/AutoCloseable.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Boolean.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Byte.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/CharSequence.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Character.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Double.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Float.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Integer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Iterable.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Long.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/Short.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/String.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/StringBuffer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/StringBuilder.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/ThreadLocal.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/LambdaConversionException.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/LambdaForm.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/LambdaMetafactory.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/MemberName.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/MethodHandleImpl.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/MethodHandleInfo.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/MethodHandleNatives.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/MethodHandleProxies.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/SerializedLambda.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/nio/X-Buffer.java.template diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/nio/file/DirectoryStream.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/nio/file/FileTreeIterator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/nio/file/Files.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/ArrayDeque.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/ArrayList.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Arrays.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/ArraysParallelSortHelpers.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/BitSet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Collection.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Collections.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/ComparableTimSort.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Comparator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Comparators.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/DoubleSummaryStatistics.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/DualPivotQuicksort.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Enumeration.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/HashMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/HashSet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Hashtable.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/IdentityHashMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/IntSummaryStatistics.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Iterator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/LinkedHashMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/LinkedHashSet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/LinkedList.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/List.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/LongSummaryStatistics.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Map.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Objects.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Optional.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/OptionalDouble.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/OptionalInt.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/OptionalLong.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/PrimitiveIterator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/PriorityQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Queue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Random.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Set.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/SortedMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/SortedSet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Spliterator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Spliterators.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/SplittableRandom.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/StringJoiner.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/TimSort.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/TreeMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/TreeSet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Tripwire.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/Vector.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/WeakHashMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/AbstractExecutorService.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ArrayBlockingQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/BlockingDeque.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/BlockingQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/Callable.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/CompletableFuture.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/CompletionStage.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ConcurrentHashMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ConcurrentMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/CountedCompleter.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/CyclicBarrier.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/DelayQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/Exchanger.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ExecutorService.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/Executors.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ForkJoinPool.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ForkJoinTask.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/FutureTask.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/LinkedBlockingDeque.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/LinkedBlockingQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/LinkedTransferQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/Phaser.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/PriorityBlockingQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/RecursiveAction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/RecursiveTask.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/RunnableScheduledFuture.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ScheduledExecutorService.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/SynchronousQueue.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ThreadLocalRandom.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/ThreadPoolExecutor.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/TimeUnit.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicInteger.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicLong.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicReference.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/atomic/package-info.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/locks/Lock.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/locks/ReentrantLock.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/locks/StampedLock.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/concurrent/package-info.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/BiConsumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/BiFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/BiPredicate.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/BinaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/BooleanSupplier.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/Consumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoubleBinaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoubleConsumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoubleFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoublePredicate.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoubleSupplier.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoubleToIntFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoubleToLongFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/DoubleUnaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/Function.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntBinaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntConsumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntPredicate.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntSupplier.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntToDoubleFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntToLongFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/IntUnaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongBinaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongConsumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongPredicate.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongSupplier.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongToDoubleFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongToIntFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/LongUnaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ObjDoubleConsumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ObjIntConsumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ObjLongConsumer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/Predicate.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/Supplier.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ToDoubleBiFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ToDoubleFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ToIntBiFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ToIntFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ToLongBiFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/ToLongFunction.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/UnaryOperator.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/function/package-info.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/jar/JarFile.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/logging/Logger.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/regex/Pattern.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/AbstractPipeline.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/AbstractShortCircuitTask.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/AbstractSpinedBuffer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/AbstractTask.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/BaseStream.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Collector.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Collectors.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/DistinctOps.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/DoublePipeline.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/DoubleStream.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/FindOps.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/ForEachOps.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/IntPipeline.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/IntStream.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/LongPipeline.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/LongStream.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/MatchOps.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Node.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Nodes.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/PipelineHelper.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/ReduceOps.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/ReferencePipeline.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Sink.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/SliceOps.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/SortedOps.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/SpinedBuffer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Stream.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/StreamOpFlag.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/StreamShape.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/StreamSpliterators.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/StreamSupport.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Streams.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/TerminalOp.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/TerminalSink.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/Tripwire.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/stream/package-info.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/zip/ZipEntry.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/java/util/zip/ZipFile.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/awt/datatransfer/DataTransferer.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java --- a/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java Thu Oct 31 16:44:18 2013 -0700 +++ b/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java Mon Nov 11 23:17:30 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -26,6 +26,7 @@ package sun.reflect; import java.lang.reflect.*; +import sun.reflect.misc.ReflectUtil; /** Used only for the first few invocations of a Constructor; afterward, switches to bytecode-based implementation */ @@ -44,7 +45,11 @@ IllegalArgumentException, InvocationTargetException { - if (++numInvocations > ReflectionFactory.inflationThreshold()) { + // We can't inflate a constructor belonging to a vm-anonymous class + // because that kind of class can't be referred to by name, hence can't + // be found from the generated bytecode. + if (++numInvocations > ReflectionFactory.inflationThreshold() + && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) { ConstructorAccessorImpl acc = (ConstructorAccessorImpl) new MethodAccessorGenerator(). generateConstructor(c.getDeclaringClass(), diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/reflect/NativeMethodAccessorImpl.java --- a/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java Thu Oct 31 16:44:18 2013 -0700 +++ b/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java Mon Nov 11 23:17:30 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -26,6 +26,7 @@ package sun.reflect; import java.lang.reflect.*; +import sun.reflect.misc.ReflectUtil; /** Used only for the first few invocations of a Method; afterward, switches to bytecode-based implementation */ @@ -42,7 +43,11 @@ public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException { - if (++numInvocations > ReflectionFactory.inflationThreshold()) { + // We can't inflate methods belonging to vm-anonymous classes because + // that kind of class can't be referred to by name, hence can't be + // found from the generated bytecode. + if (++numInvocations > ReflectionFactory.inflationThreshold() + && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) { MethodAccessorImpl acc = (MethodAccessorImpl) new MethodAccessorGenerator(). generateMethod(method.getDeclaringClass(), diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/reflect/Reflection.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/reflect/misc/ReflectUtil.java --- a/src/share/classes/sun/reflect/misc/ReflectUtil.java Thu Oct 31 16:44:18 2013 -0700 +++ b/src/share/classes/sun/reflect/misc/ReflectUtil.java Mon Nov 11 23:17:30 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -298,4 +298,13 @@ } return false; } + + /** + * Checks if {@code Class cls} is a VM-anonymous class + * as defined by {@link sun.misc.Unsafe#defineAnonymousClass} + * (not to be confused with a Java Language anonymous inner class). + */ + public static boolean isVMAnonymousClass(Class cls) { + return cls.getSimpleName().contains("/"); + } } diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/security/provider/certpath/PKIX.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/tools/java/BinaryConstantPool.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/tools/java/RuntimeConstants.java diff -r f82b730c798b -r 99dd9e50f37e src/share/classes/sun/util/PreHashedMap.java diff -r f82b730c798b -r 99dd9e50f37e src/share/javavm/export/classfile_constants.h diff -r f82b730c798b -r 99dd9e50f37e src/share/javavm/export/jvm.h diff -r f82b730c798b -r 99dd9e50f37e src/share/lib/security/java.security-linux --- a/src/share/lib/security/java.security-linux Thu Oct 31 16:44:18 2013 -0700 +++ b/src/share/lib/security/java.security-linux Mon Nov 11 23:17:30 2013 -0800 @@ -199,14 +199,12 @@ com.sun.org.apache.xalan.internal.xsltc.trax.,\ com.sun.org.apache.xalan.internal.xsltc.util.,\ com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ com.sun.org.apache.xml.internal.serializer.utils.,\ com.sun.org.apache.xml.internal.utils.,\ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ oracle.jrockit.jfr.,\ - org.jcp.xml.dsig.internal.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools. @@ -245,14 +243,12 @@ com.sun.org.apache.xalan.internal.xsltc.trax.,\ com.sun.org.apache.xalan.internal.xsltc.util.,\ com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ com.sun.org.apache.xml.internal.serializer.utils.,\ com.sun.org.apache.xml.internal.utils.,\ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ oracle.jrockit.jfr.,\ - org.jcp.xml.dsig.internal.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools. diff -r f82b730c798b -r 99dd9e50f37e src/share/native/common/check_code.c --- a/src/share/native/common/check_code.c Thu Oct 31 16:44:18 2013 -0700 +++ b/src/share/native/common/check_code.c Mon Nov 11 23:17:30 2013 -0800 @@ -1307,7 +1307,10 @@ && clazz_info != context->currentclass_info && clazz_info != context->superclass_info) { int not_found = 1; - + jclass cb = object_fullinfo_to_classclass(context, clazz_info); + int is_interface = cb && JVM_IsInterface(env, cb); + + if (!is_interface) { jclass super = (*env)->GetSuperclass(env, context->class); while(super != 0) { jclass tmp_cb; @@ -1335,6 +1338,7 @@ } } } + } if (opcode == JVM_OPC_invokeinterface) { unsigned int args1; unsigned int args2; diff -r f82b730c798b -r 99dd9e50f37e src/share/native/java/lang/System.c diff -r f82b730c798b -r 99dd9e50f37e src/solaris/classes/sun/nio/fs/UnixPath.java diff -r f82b730c798b -r 99dd9e50f37e src/solaris/native/java/lang/java_props_md.c diff -r f82b730c798b -r 99dd9e50f37e src/windows/classes/sun/nio/fs/WindowsFileCopy.java diff -r f82b730c798b -r 99dd9e50f37e src/windows/classes/sun/nio/fs/WindowsLinkSupport.java diff -r f82b730c798b -r 99dd9e50f37e src/windows/classes/sun/nio/fs/WindowsPath.java diff -r f82b730c798b -r 99dd9e50f37e test-ng/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/README Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,20 @@ +Running the TestNG based unit tests requires downloading the TestNG +library and placing its jar file into the lib subdirectory: + + # download and install TestNG + wget http://testng.org/testng-x.y.z.zip + unzip testng-x.y.z.zip + mkdir lib + cp testng-x.y.z/testng.jar lib + + # run tests + ant test + +This will fail with a message like + + taskdef class org.testng.TestNGAntTask cannot be found + +if the TestNG jar file is not installed properly or if the wrong +version is present. (Check build.xml to find the version of TestNG +that is required.) Only the jar file is necessary. The unzipped +hierarchy can be removed. diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/Readme --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/Readme Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,118 @@ +To run this: + 1. unzip the bundle to a dir called agent (you should have already done + so, to be reading this) + 2. have the latest version of lambda repo built fully and in your PATH + 3. you can use the pre-built dist/SerializationInjector.jar if not you + can build it with "ant -f agent/make/build.xml dist" + 4. before running this modify the conf/agent.props if required, but not + necessary. + 5. At the time of this writing only test-ng's test-libs are supported. + + make the following changes in the lambda/jdk/test-ng/build.xml + for the test-libs target, you might want to bump the heap from 2g + to 4g if your choice of platform and the JVM allows. + + + + actual patch shown in appendix + + 6. to run simply run the test-ng test as "ant test-libs" + Note: make sure are running with the very latest lambda build + 7. what you expect to see is in the Appendix. + Note: you will see on failure which is a serialization negative test + +Details: +Directory structure: + src - containing the sources + build - intermediate classes + dist - jar used as an agent + make - build.xml and an nbproject, feel free to modify it + requires jdk8 with asm that recognizes v52.0 classfiles + conf - config files + +Description of sources: + Agent.java: installs an agent. + SerializationInjector: does the following + * parses properties and initializes the output + * initialize and install the VM shutdown hook, to print the test + statistics. + * using asm interrogates the target class, upon encountering an + indy, will save the params, invokes the indy, and restores the + original args to the indy + * invoke the indy + * invoke the SerializeAndDeserializeTest (SAND). + with the lambdaObject returned by the indy and the + non-primitive parameters and these will be passed to SAND. + Primitives are excluded + TestLambdaSerialization: + * the SAND will check the arguments if they are Serializable, if so, + then the LamdbaObject will be Serialized and Deserialized, and the + deserialized LambdaObject will be returned, otherwise the original + LambdaObject will be returned, the outcome and exception if any + will be recorded. + + The final report will be printed out when the JVM terminates. + +Running the agent: +java -jar path_to/jtreg.jar \ + -javaoption:"-javaagent:path_to/agent/dist/SerializationInjectorAgent.jar=/w/ksrini/Lambda/agent.props" \ + test/foo/Lambda2.java + +agent.props is a property file by which one can specify + * a regular expression to exclude classes + * specify an output file to log details + * specifiy debugging if required + +ex: +com.oracle.lambda.exclude.files=^java.*|^sun.misc.*|^javax.* +com.oracle.lambda.log.file=some_path/agent.log +com.oracle.lambda.debug=true + +A note about logfiles, the agent is installed into jtreg, however jtreg +may invoke a test in a different VM as specified by the test and/or command +line. + +Thus if a file exists the agent will create a unique file in the specified +directory. Therefore it is recommended that the desired output directory is +clean before starting a new test. + + +Appendix: + +1. Patch to install the agent into test-ng +diff --git a/test-ng/build.xml b/test-ng/build.xml +--- a/test-ng/build.xml ++++ b/test-ng/build.xml +@@ -55,6 +56,7 @@ + + + ++ + + + + +2. sample log +[testng] [TestNG] Running: + [testng] Ant suite + [testng] + [testng] + [testng] =============================================== + [testng] Ant suite + [testng] Total tests run: 7338, Failures: 1, Skips: 0 + [testng] =============================================== + [testng] + [testng] Lambda Serialization Test Status: + [testng] success: 2432727 + [testng] failed : 1099035 + [testng] Non Serializable Class(es): + [testng] NonSerializableObject: java.util.stream.op.Nodes$ArrayNode [92] + [testng] Throwable: + [testng] null + [testng] + [testng] NonSerializableObject: java.util.stream.op.Nodes$ConcNode [71] + [testng] Throwable: + [testng] null + [testng] + [testng] NonSerializableObject: org.openjdk.tests.java.util.stream.op.Group +........ diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/conf/agent.props --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/conf/agent.props Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,6 @@ +#com.oracle.lambda.exclude.files=java..*|sun.*|javax.*|org.testng.*|com.google.*|com.sun.tools.javac.*|.*javatest.*|com.sun.tools.classfile.*|com.beust.*|.*TTShape.*|.*TestHarness.* +#com.oracle.lambda.log.file=/tmp/agent_log/agent.log +#com.oracle.lambda.debug=true +#com.oracle.lambda.serialize.file=$CUSTOM/serialize.list +com.oracle.lambda.storeStackTraces=true +#com.oracle.lambda.deserialization.workaround=true diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/conf/serialize.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/conf/serialize.list Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,59 @@ +java/lang/invoke/MagicLambdaImpl +java/util/Optional +java/util/OptionalDouble +java/util/OptionalLong +java/util/OptionalInt +java/util/Spliterator +java/util/ArrayList\$SubList +java/util/SubList +java/util/RandomAccessSubList +java/util/HashMap\$.*Spliterator +java/util/TreeMap\$.*Spliterator +java/util/function/Function\$\$Lambda.* +java/util/function/Functions\$\$Lambda.* +java/util/stream/Collectors.* +java/util/stream/LambdaTestHelpers\$\$Lambda.* +java/util/stream/Nodes.*NodeBuilder +java/util/stream/Nodes\$.*Node +java/util/stream/AbstractSpinedBuffer +java/util/stream/SpinedBuffer +java/util/stream/.*Pipeline +java/util/stream/AbstractPipeline\$.* +java/util/stream/IntermediateOp +java/util/stream/.*StreamTestData\$.* +java/util/stream/.*NodeTest +java/util/stream/TestData\$AbstractTestData.* +org/openjdk/tests/java/util/stream/OpTestCase\$TestData +org/openjdk/tests/java/util/stream/OpTestCase\$ExerciseDataStreamBuilder +org/openjdk/tests/java/util/stream/OpTestCase\$ExerciseDataTerminalBuilder +org/openjdk/tests/java/util/stream/IntNodeTest +org/openjdk/tests/java/util/stream/UnorderedStreamTest +org/openjdk/tests/java/util/stream/GroupByOpTest +org/openjdk/tests/java/util/stream/TabulatorsTest +org/openjdk/tests/java/util/stream/TabulatorsTest\$.*Assertion +org/openjdk/tests/java/util/stream/StreamLinkTest +org.openjdk.tests.java.util.stream.SpliteratorLateBindingFailFastTest\$SpliteratorDataBuilder.* +org.openjdk.tests.java.util.stream.SpliteratorTraversingAndSplittingTest\$SpliteratorDataBuilder.* +org.openjdk.tests.java.util.stream.SliceOpTest.* +org.openjdk.tests.java.util.stream.MatchOpTest.* +org.openjdk.tests.java.util.stream.InfiniteStreamWithLimitOpTest.* +java.util.HashMap\$Values +java.util.LinkedHashMap\$KeyIterator +java.util.HashMap\$Entry +java.util.LinkedList\$Node +java.util.TreeMap\$Entry +java.util.HashMap\$EntrySet +java.util.HashMap\$KeySet +java.util.IdentityHashMap\$KeySet +java.util.LinkedHashMap\$ValueIterator +java.util.TreeMap\$KeySet +java.util.TreeMap\$EntrySet +java.util.TreeMap\$Values +java.util.WeakHashMap +java.util.WeakHashMap\$EntrySet +java.util.WeakHashMap\$KeySet +java.util.WeakHashMap\$Values +java.util.LinkedHashMap\$EntryIterator +java.util.IdentityHashMap\$EntrySet +java.util.IdentityHashMap\$Values + diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/make/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/make/build.xml Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/src/com/oracle/lambda/Agent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/src/com/oracle/lambda/Agent.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,71 @@ +/* + * 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. + */ +package com.oracle.lambda; + +import java.io.IOException; +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.ProtectionDomain; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.TreeSet; + +public class Agent { + public static void premain(String agentArgs, Instrumentation instrumentation) + throws IOException, NoSuchFieldException, IllegalAccessException { + // If run without a config file, all we do is set up the shutdown hook + if (agentArgs != null) { + final SerializationInjector si = new SerializationInjector(); + instrumentation.addTransformer(new ClassFileTransformer() { + @Override + public byte[] transform(final ClassLoader cl, String string, + Class type, ProtectionDomain pd, + byte[] bytes) throws IllegalClassFormatException { + return si.transformClass(cl, bytes, EnumSet.noneOf(SerializationInjector.Options.class)); + } + }); + } + else { + // Horrible horrible hack. + // TreeSet/HashSet are based off of HashSet/HashMap, and serializing their spliterators + // tries to serialize the underlying map, which uses a non-serializable sentinel object. + // This hack swaps that out for a serializable sentinel + Field f = HashSet.class.getDeclaredField("PRESENT"); + f.setAccessible(true); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); + f.set(null, Boolean.TRUE); + + f = TreeSet.class.getDeclaredField("PRESENT"); + f.setAccessible(true); + modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); + f.set(null, Boolean.TRUE); + + TestLambdaSerialization.initializeShutDownHook(); + } + } + } diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/src/com/oracle/lambda/Main.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/src/com/oracle/lambda/Main.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,196 @@ +/* + * 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. + */ +package com.oracle.lambda; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.regex.Pattern; + +import jdk.internal.org.objectweb.asm.ClassReader; +import static java.nio.file.StandardOpenOption.*; +import static java.nio.file.StandardCopyOption.*; + +/** + * + * @author kumasrin + */ +public class Main { + + static void usage() { + System.out.println("usage: -o output_dir path_to/SomeClass.class"); + System.out.println("usage: -o output_dir path_to_classes"); + System.out.println("usage: -o output_dir -s path_to_jar"); + System.exit(1); + } + + /* + * a standalone tester for this + */ + public static void main(String... inargs) throws Exception { + String[] args = inargs; + if (inargs != null && inargs.length == 1) { + args = inargs[0].split("\\s"); + } + if (args == null || args.length < 3) { + usage(); + } + File outDir = null; + File inFile = null; + boolean serializeOnly = false; + for (int i = 0 ; i < args.length ; i++) { + switch (args[i]) { + case "-o": + i++; + outDir = new File(args[i]); + break; + case "-s": + serializeOnly = true; + break; + default: + inFile = new File(args[i]); + } + } + if (inFile.isDirectory()) { + if (outDir.exists()) { + outDir.mkdirs(); + } + URL[] urls = {inFile.toURI().toURL()}; + ClassLoader cl = new URLClassLoader(urls, ClassLoader.getSystemClassLoader()); + try (DirectoryStream paths = + Files.newDirectoryStream(inFile.toPath(), "*")) { + for (Path p : paths) { + doFile(inFile, outDir, p.toFile(), cl); + } + } + } else if (inFile.getName().endsWith(".jar")) { + if (outDir.exists()) { + outDir.mkdirs(); + } + URL[] urls = {inFile.toURI().toURL()}; + ClassLoader cl = new URLClassLoader(urls, ClassLoader.getSystemClassLoader()); + Pattern pattern = Pattern.compile(".*"); + EnumSet options + = serializeOnly ? EnumSet.of(SerializationInjector.Options.SERIALIZE_ONLY) : EnumSet.noneOf(SerializationInjector.Options.class); + doJar(inFile, outDir, cl, pattern, options); + } else { + outDir.mkdirs(); + URL[] urls = {inFile.getParentFile().toURI().toURL()}; + ClassLoader cl = new URLClassLoader(urls, ClassLoader.getSystemClassLoader()); + doFile(null, outDir, inFile, cl); + } + } + static void copyStream(InputStream in, OutputStream out) throws IOException { + byte[] buf = new byte[8192]; + int n = in.read(buf); + while (n > 0) { + out.write(buf, 0, n); + n = in.read(buf); + } + } + + static byte[] readFully(InputStream is) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copyStream(is, baos); + return baos.toByteArray(); + } + + static void doJar(File inFile, File outDir, ClassLoader cl, Pattern pattern, + EnumSet options) throws IOException { + JarFile jf = new JarFile(inFile); + byte[] buffer; + SerializationInjector si = new SerializationInjector(); + FileSystem fs = null; + boolean jarOut = outDir.getName().endsWith(".jar"); + Set perms = PosixFilePermissions.fromString("rwxrwxrwx"); + FileAttribute> attr = + PosixFilePermissions.asFileAttribute(perms); + Map env = new HashMap<>(); + env.put("create", "true"); + if (jarOut) { + URI uri = URI.create("jar:file:" + outDir.getAbsolutePath()); + if (outDir.exists()) + outDir.delete(); + fs = FileSystems.newFileSystem(uri, env); + } else { + fs = FileSystems.getDefault(); + } + for (JarEntry je : Collections.list(jf.entries())) { + String fname = je.getName(); + if (fname.endsWith("/")) continue; + if (pattern.matcher(fname).matches()) { + buffer = readFully(jf.getInputStream(je)); + if (fname.endsWith(".class")) + buffer = si.transformClass(cl, buffer, options); + Path opath = jarOut ? fs.getPath(fname) : fs.getPath(outDir.getAbsolutePath(), fname); + Files.createDirectories(opath.getParent(), attr); + Files.write(opath, buffer, CREATE, TRUNCATE_EXISTING); + } + } + if (jarOut) + fs.close(); + } + + static String getRelativePath(File baseDir, File inFile) { + String bname = baseDir.getAbsolutePath(); + String fname = inFile.getAbsolutePath(); + return fname.substring(bname.length() + 1); + } + + static void doFile(File inDir, File outDir, File iFile, ClassLoader cl) throws Exception { + if (!iFile.getName().endsWith(".class")) { + Path p = new File(getRelativePath(inDir, iFile)).toPath(); + Files.copy(iFile.toPath(), p, COPY_ATTRIBUTES, REPLACE_EXISTING); + return; + } + byte[] classBuffer = Files.readAllBytes(iFile.toPath()); + ClassReader cr = new ClassReader(classBuffer); + File oFile = new File(outDir, cr.getClassName() + ".class"); + SerializationInjector si = new SerializationInjector(); + System.err.print("Transforming: " + iFile.getAbsolutePath()); + System.err.println(" to: " + oFile.getAbsolutePath()); + oFile.getParentFile().mkdirs(); + Files.write(oFile.toPath(), + si.transformClass(cl, classBuffer, EnumSet.noneOf(SerializationInjector.Options.class)), CREATE, TRUNCATE_EXISTING); + } +} diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/src/com/oracle/lambda/SerializationInjector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/src/com/oracle/lambda/SerializationInjector.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,399 @@ +/* + * 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. + */ +package com.oracle.lambda; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Handle; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import static jdk.internal.org.objectweb.asm.Opcodes.*; +import jdk.internal.org.objectweb.asm.Type; + +import static java.nio.file.StandardOpenOption.*; + + +public class SerializationInjector { + static final String PREFIX = "com.oracle.lambda"; + static final String INCLUDES = "java.util.*|org.openjdk.tests.java.*"; // also should include java.util... + static final String SERIALIZE = ""; + + // properties that can be set + static final String INCLUDE_FILES = PREFIX + ".include.files"; + static final String SERIALIZE_FILE = PREFIX + ".serialize.file"; + static final String STORE_FRAMES = PREFIX + ".store.frames"; + static final String LOGFILE = PREFIX + ".log.file"; + static final String DEBUG = PREFIX + ".debug"; + static final String NROUNDS = PREFIX + ".nrounds"; + + static boolean storeFrames = true; + static boolean deserializationWorkaround; + + final DebugPrint debug; + final Pattern includePattern; + final Pattern serializePattern; + final boolean serializeOnly; + + public enum Options { SERIALIZE_ONLY, FORCE_SERIALIZE } + + public SerializationInjector() throws IOException { + includePattern = propToPattern(INCLUDE_FILES, INCLUDES); + serializePattern = fileToPattern(SERIALIZE_FILE, SERIALIZE); + debug = new DebugPrint(); + TestLambdaSerialization.initializeShutDownHook(); + storeFrames = Boolean.getBoolean(STORE_FRAMES); + deserializationWorkaround = false; + serializeOnly = false; + } + final Pattern propToPattern(String propKey, String defValue) { + return Pattern.compile(System.getProperty(propKey, defValue)); + } + final Pattern fileToPattern(String propKey, String defValue) throws IOException { + String fname = System.getProperty(propKey, null); + if (fname != null) { + File pFile = new File(fname); + if (pFile.canRead()) { + return fileToPattern(pFile); + } + } + return Pattern.compile(defValue); + } + final Pattern fileToPattern(File inFile) throws IOException { + List serList = Files.readAllLines(inFile.toPath(), + Charset.defaultCharset()); + String regStr = ""; + boolean first = true; + for (String s : serList) { + String x = s.trim(); + if (x.startsWith("#")) { + continue; + } + regStr = regStr.concat((first ? "" : "|") + x); + first = false; + } + System.out.println("serialization: " + regStr); + return Pattern.compile(regStr); + } + + byte[] transformClass(ClassLoader cl, byte[] classBuffer, EnumSet options) { + byte[] xBuffer = classBuffer; + ClassReader classReader = new ClassReader(xBuffer); + String cname = classReader.getClassName(); + + if (options.contains(Options.FORCE_SERIALIZE) || serializePattern.matcher(cname).matches()) { + debug.println("Implementing Serialization: " + cname); + xBuffer = injectSerialization(xBuffer, cl); + } + if (serializeOnly || options.contains(Options.SERIALIZE_ONLY)) { + return xBuffer; + } + if (!includePattern.matcher(cname).matches()) { + debug.println("Excluding SAND: " + cname); + return xBuffer; + } + debug.println("Visiting: " + cname); + return injectSAND(xBuffer, cl); + } + + byte[] injectSAND(byte[] classBuffer, ClassLoader cl) { + Map locals = getLocals(classBuffer); + ClassReader classReader = new ClassReader(classBuffer); + ClassWriter classWriter = new ClassWriter(classReader, + ClassWriter.COMPUTE_MAXS /*| ClassWriter.COMPUTE_FRAMES*/); + classReader.accept(makeSANDVisitor(classWriter, locals), 0); + byte[] byteArray = classWriter.toByteArray(); +// CheckClassAdapter.verify(new ClassReader(byteArray), cl, false, +// new PrintWriter(System.err)); + return byteArray; + } + + Map getLocals(byte[] classBuffer) { + ClassReader cr = new ClassReader(classBuffer); + final Map locals = new HashMap<>(); + cr.accept(new ClassVisitor(ASM4, null) { + String cname; + @Override + public void visit(int version, int access, String name, + String signature, String superName, + String[] interfaces) { + cname = name; + super.visit(version, access, name, signature, superName, interfaces); + } + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + final String mid = cname + "+" + name + "+" + desc + "+" + signature; + return new MethodVisitor(ASM4, + super.visitMethod(access, name, desc, signature, exceptions)) { + @Override + public void visitMaxs(int maxStack, int maxLocals) { + super.visitEnd(); + super.visitMaxs(maxStack, maxLocals); + //debug.println("Pre-Visiting:" + mid + ", stack=" + maxLocals); + locals.put(mid, maxLocals); + } + }; + } + }, 0); + + return locals; + } + + ClassVisitor makeSANDVisitor(ClassWriter cw, final MapmethodLocals) { + return new ClassVisitor(ASM4, cw) { + String cname = null; + @Override + public void visit(int version, int access, String name, + String signature, String superName, + String[] interfaces) { + cname = name; + super.visit(version, access, name, signature, superName, interfaces); + } + @Override + public MethodVisitor visitMethod(int access, final String name, + final String desc, final String signature, + String[] exceptions) { + if (name.equals("$deserializeLambda$")) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + return new MethodVisitor(ASM4, + super.visitMethod(access, name, desc, signature, exceptions)) { + final String mid = cname + "+" + name + "+" + desc + "+" + signature; + int locals = methodLocals.containsKey(mid) ? methodLocals.get(mid) : 0; + + int saveArgs(Type[] types) { + final int n = locals + 1; + final int tlen = types.length; + int count = 0; + // store in LIFO order + for (int i = 0; i < tlen; i++) { + int pos = tlen - 1 - i; + super.visitVarInsn(types[pos].getOpcode(ISTORE), n + pos); + } + // restore back in FIFO order + for (int i = 0 ; i < tlen; i++) { + if (isNotPrimitive(types[i])) { + count++; + } + super.visitVarInsn(types[i].getOpcode(ILOAD), n + i); + } + return count; + } + boolean isNotPrimitive(Type t) { + int i = t.getSort(); + return i == Type.OBJECT || i == Type.ARRAY; + } + void restoreArgs(Type[] types, int count) { + final int n = locals + 1; + final int tlen = types.length; + // create the array + visitIntInsn(BIPUSH, count); + visitTypeInsn(ANEWARRAY, "java/lang/Object"); + int ncount = 0; + for (int i = 0 ; i < tlen ; i++ ) { + Type t = types[i]; + if (isNotPrimitive(t)) { + debug.println("injecting:" + t); + super.visitInsn(DUP); + super.visitIntInsn(BIPUSH, ncount); + super.visitVarInsn(t.getOpcode(ILOAD), n + i); + super.visitInsn(AASTORE); + ncount++; + } + } + } + @Override + public void visitInvokeDynamicInsn(String callsite, + String sig, Handle handle, Object... bsmArgs) { + // instrument only! lambda objects + final boolean needsTransform = handle.getName().equals("metafactory"); + final boolean injectSand = needsTransform || + handle.getName().equals("altMetafactory"); + if (!injectSand) { + super.visitInvokeDynamicInsn(callsite, sig, handle, bsmArgs); + return; + } + debug.println("indy:" + mid + ", locals = " + locals); + debug.println(" fixing: " + callsite + ":" + sig); + Handle nHandle = handle; + Object[] nbsmArgs = bsmArgs; + if (needsTransform) { + String ndesc = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"; + nHandle = new Handle(handle.getTag(), handle.getOwner(), + "altMetafactory", ndesc); + + ArrayList largs = new ArrayList<>(Arrays.asList(bsmArgs)); + largs.add(1); + largs.add(Type.getType(java.io.Serializable.class)); + nbsmArgs = new Object[largs.size()]; + largs.toArray(nbsmArgs); + debug.println("old: " + handle.toString()); + debug.println("new: " + nHandle.toString()); + } + Type[] types = Type.getArgumentTypes(sig); + int count = saveArgs(types); + super.visitInvokeDynamicInsn(callsite, sig, nHandle, nbsmArgs); + restoreArgs(types, count); + super.visitMethodInsn(INVOKESTATIC, + "com/oracle/lambda/TestLambdaSerialization", + (needsTransform && deserializationWorkaround) + ? "serializeOnly" + : "serializeAndDeserialize", + "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); + } + }; + } + }; + } + + void dumpClass(byte[] array, String prefix) { + try { + Path f = Files.createTempFile(new File("/tmp").toPath(), + prefix, ".class"); + System.out.println("dumping to:" + f.toString()); + Files.write(f, array, CREATE, TRUNCATE_EXISTING); + } catch (IOException ex) { + Logger.getLogger(SerializationInjector.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private byte[] injectSerialization(byte[] classBuffer, ClassLoader cl) { + ClassReader classReader = new ClassReader(classBuffer); + ClassWriter classWriter = new ClassWriter(classReader, + ClassWriter.COMPUTE_MAXS /*| ClassWriter.COMPUTE_FRAMES*/); + boolean hasNoArgCtor = hasNoArgCtor(classBuffer); + classReader.accept(makeSerializationVisitor(classWriter, !hasNoArgCtor), 0); + byte[] byteArray = classWriter.toByteArray(); + // Needed to comment this out because some classes are actually loaded during this verification + // and they fail the package name test (java.*) +// CheckClassAdapter.verify(new ClassReader(byteArray), cl, false, +// new PrintWriter(System.err)); + +// dumpClass(classBuffer, "pre-serialization"); +// dumpClass(byteArray, "post-serialization"); + return byteArray; + } + + private boolean hasNoArgCtor(byte[] buffer) { + final AtomicBoolean foundNoArg = new AtomicBoolean(); + new ClassReader(buffer).accept(new ClassVisitor(ASM4, null) { + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if (name.equals("") && desc.equals("()V")) + foundNoArg.set(true); + return super.visitMethod(access, name, desc, signature, exceptions); + } + }, 0); + return foundNoArg.get(); + } + + ClassVisitor makeSerializationVisitor(final ClassWriter cw, final boolean injectNoArg) { + return new ClassVisitor(ASM4, cw) { + @Override + public void visit(int version, int access, String name, + String signature, String superName, + String[] interfaces) { + String sername = java.io.Serializable.class.getName().replace('.', '/'); + boolean foundSer = false; + for (String x : interfaces) { + foundSer = foundSer || x.contains(sername); + } + if (!foundSer) { + debug.println("Injecting serialization: " + name); + int n = interfaces.length; + interfaces = Arrays.copyOf(interfaces, n + 1); + interfaces[n] = sername; + if (signature != null) + signature += "L" + sername + ";"; + } + super.visit(version, access, name, signature, superName, interfaces); + if (injectNoArg && (access & ACC_INTERFACE) == 0) { + debug.println("Injecting : " + name); + MethodVisitor ctor = visitMethod(ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(ALOAD, 0); + ctor.visitMethodInsn(INVOKESPECIAL, superName, "", "()V"); + ctor.visitInsn(RETURN); + ctor.visitMaxs(-1, -1); + ctor.visitEnd(); + } + } + }; + } +} +class DebugPrint { + final PrintStream out; + final boolean mustPrint; + final boolean shouldClose; + + DebugPrint() throws IOException { + mustPrint = Boolean.getBoolean(SerializationInjector.DEBUG); + String output = System.getProperty(SerializationInjector.LOGFILE, "out"); + switch (output) { + case "out": + out = System.out; + shouldClose = false; + break; + case "err": + out = System.err; + shouldClose = false; + break; + default: + File f = new File(output); + if (f.exists()) { + File dir = f.getParentFile(); + f = File.createTempFile("agent", ".log", dir); + } + FileOutputStream fos = new FileOutputStream(f); + out = new PrintStream(new BufferedOutputStream(fos)); + shouldClose = true; + } + } + + void println(String s) { + if (mustPrint) + out.println(s); + } + void print(String s) { + if (mustPrint) + out.print(s); + } +} diff -r f82b730c798b -r 99dd9e50f37e test-ng/agent/src/com/oracle/lambda/TestLambdaSerialization.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/agent/src/com/oracle/lambda/TestLambdaSerialization.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,253 @@ +/* + * 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. + */ +package com.oracle.lambda; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +public class TestLambdaSerialization { + + private static final Map nonSerializableClasses = + Collections.synchronizedMap(new HashMap()); + private static final Map serializableButFailedClasses = + Collections.synchronizedMap(new HashMap()); + private static final Map deserFailures = + Collections.synchronizedMap(new HashMap()); + private static final CounterSet serCounters = new CounterSet(); + private static final CounterSet deserCounters = new CounterSet(); + private static final int nRounds = + Integer.parseInt(System.getProperty(SerializationInjector.NROUNDS, "1")); + + public static void printStats() { + PrintStream rpt = System.out; + try { + rpt.println("Lambda Serialization Test Status:"); + rpt.println(" serializations attempted: " + serCounters.attempted); + rpt.println(" serializations succeeded: " + serCounters.succeeded); + rpt.println(" serializations failed: " + serCounters.failed); + rpt.println(" serializations not attempted: " + serCounters.notAttempted); + rpt.println(" deserializations attempted: " + deserCounters.attempted); + rpt.println(" deserializations succeeded: " + deserCounters.succeeded); + rpt.println(" deserializations failed: " + deserCounters.failed); + rpt.println(" deserializations not attempted: " + deserCounters.notAttempted); + if (nonSerializableClasses.size() > 0) { + rpt.println("Non Serializable Class(es):"); + for (Entry e : nonSerializableClasses.entrySet()) { + rpt.println(" " + e.getValue()); + } + } + if (serializableButFailedClasses.size() > 0) { + rpt.println("Serializable class(es) but failed serialization:"); + for (Entry e : serializableButFailedClasses.entrySet()) { + rpt.println(" " + e.getValue()); + } + } + if (deserFailures.size() > 0) { + rpt.println("Failed deserialization:"); + for (Entry e : deserFailures.entrySet()) { + rpt.println(" " + e.getValue()); + } + } + } finally { + rpt.flush(); + } + } + + public static Object serializeOnly(Object lambdaObj, Object... args) { + Object lObj = lambdaObj; + for (int i = 0 ; i < nRounds; i++) + lObj = serializeAndDeserialize0(true, lObj, args); + return lObj; + } + + public static Object serializeAndDeserialize(Object lambdaObj, Object... args) { + Object lObj = lambdaObj; + for (int i = 0; i < nRounds; i++) + lObj = serializeAndDeserialize0(false, lObj, args); + return lObj; + } + + private static Object serializeAndDeserialize0(boolean serializeonly, + Object lambdaObj, Object... args) { + boolean argsSerializable = true; + for (Object a : args) { + if (!(a instanceof java.io.Serializable)) { + argsSerializable = false; + String name = a.getClass().getName(); + SerializableStatus s = nonSerializableClasses.get(name); + if (s == null) { + s = new SerializableStatus("NonSerializableObject", name, + SerializationInjector.storeFrames + ? new Exception(name) : null); + nonSerializableClasses.put(name, s); + + } else { + s.incrementCount(); + } + } + } + + byte[] serBytes; + if (argsSerializable) { + try { + serCounters.attempted.incrementAndGet(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(lambdaObj); + oos.close(); + serBytes = bos.toByteArray(); + serCounters.succeeded.incrementAndGet(); + } catch (java.io.NotSerializableException e) { + serCounters.failed.incrementAndGet(); + String name = e.getMessage(); + SerializableStatus s = nonSerializableClasses.get(name); + if (s == null) { + s = new SerializableStatus("NonSerializableObject", name, + SerializationInjector.storeFrames ? e : null); + nonSerializableClasses.put(name, s); + } else { + s.incrementCount(); + } + return lambdaObj; + } catch (RuntimeException | IOException | Error e) { + serCounters.failed.incrementAndGet(); + String cname = lambdaObj.getClass().getName(); + SerializableStatus s = serializableButFailedClasses.get(cname); + if (s == null) { + serializableButFailedClasses.put(cname, new SerializableStatus("LambdaObject", + lambdaObj, SerializationInjector.storeFrames ? e : null)); + } else { + s.incrementCount(); + } + return lambdaObj; + } + } else { + serCounters.notAttempted.incrementAndGet(); + return lambdaObj; + } + + if (serializeonly) { + deserCounters.notAttempted.incrementAndGet(); + return lambdaObj; + } + + deserCounters.attempted.incrementAndGet(); + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(serBytes))) { + Object nlambdaObj = ois.readObject(); + deserCounters.succeeded.incrementAndGet(); + return nlambdaObj; + } catch (Exception e) { + deserCounters.failed.incrementAndGet(); + String cname = lambdaObj.getClass().getName(); + SerializableStatus s = deserFailures.get(cname); + if (s == null) { + deserFailures.put(cname, new SerializableStatus("NonDeserializableObject", + lambdaObj, SerializationInjector.storeFrames ? e : null)); + } else { + s.incrementCount(); + } + return lambdaObj; + } + } + + /* + * a unit tester for this class + */ + + public static void main(String... args) { + String s = "Lambda"; + Object o = new Object(); + Object[] array = { + "one", + "two", + "three" + }; + serializeAndDeserialize(s, "Hi", array); + serializeAndDeserialize(s, "Bye", array); + } + + static AtomicBoolean initialized = new AtomicBoolean(); + static { + initializeShutDownHook(); + } + + static void initializeShutDownHook() { + if (initialized.compareAndSet(false, true)) { + Runtime.getRuntime().addShutdownHook( + new Thread() { + @Override + public void run() { + printStats(); + } + } + ); + } + } +} + +class CounterSet { + AtomicInteger notAttempted = new AtomicInteger(0); + AtomicInteger attempted = new AtomicInteger(0); + AtomicInteger succeeded = new AtomicInteger(0); + AtomicInteger failed = new AtomicInteger(0); +} + +class SerializableStatus { + String type; + Object obj; + Throwable exception; + AtomicInteger count = new AtomicInteger(1); + + public SerializableStatus(String type, Object obj, Throwable exception) { + this.type = type; + this.obj = obj; + this.exception = exception; + } + + public void incrementCount() { + count.incrementAndGet(); + } + + public String toString() { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.printf("%s: %s [ %d ]%n", type, obj, count.get()); + if (exception != null) { + pw.printf(" Throwable: %s", exception); + exception.printStackTrace(pw); + } + return sw.toString(); + } +} diff -r f82b730c798b -r 99dd9e50f37e test-ng/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/build.xml Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Results at: file:${test.reports.dir}/index.html + + + + + + + + + + + + + + + + + Results at: file:${test.reports.dir}/index.html + + + + + + + + + + + + + + + + + Results at: file:${test.reports.dir}/index.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r f82b730c798b -r 99dd9e50f37e test-ng/tests/lambda/TestInterfaceBridges.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/lambda/TestInterfaceBridges.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,76 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 lambda; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * TestInterfaceBridges + * + * @author Brian Goetz + */ +@Test +public class TestInterfaceBridges { + public void testCovariantOverrideLambda() { + B b = () -> "Foo"; + assertEquals("Foo", b.make()); + assertEquals("Foo", ((A) b).make()); + } + + public void testCovariantOverrideIC() { + B b = new B() { + @Override + public String make() { + return "Foo"; + } + }; + assertEquals("Foo", b.make()); + assertEquals("Foo", ((A) b).make()); + } + + public static interface A { + Object make(); + } + + public static interface B extends A { + String make(); + } + + public void testCovariantMerge() { + D d = () -> "Foo"; + assertEquals("Foo", d.make()); + assertEquals("Foo", ((A) d).make()); + assertEquals("Foo", ((C) d).make()); + } + + public static interface C { + String make(); + } + + public static interface D extends A, C { + } +} diff -r f82b730c798b -r 99dd9e50f37e test/Makefile diff -r f82b730c798b -r 99dd9e50f37e test/ProblemList.txt --- a/test/ProblemList.txt Thu Oct 31 16:44:18 2013 -0700 +++ b/test/ProblemList.txt Mon Nov 11 23:17:30 2013 -0800 @@ -206,6 +206,10 @@ # 8014719 sun/net/www/http/HttpClient/ProxyTest.java generic-all +# 7150552 +sun/net/www/protocol/http/B6299712.java macosx-all +java/net/CookieHandler/CookieManagerTest.java macosx-all + ############################################################################ # jdk_nio diff -r f82b730c798b -r 99dd9e50f37e test/java/io/BufferedReader/Lines.java diff -r f82b730c798b -r 99dd9e50f37e test/java/io/Serializable/defaultSVID/Child.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/defaultSVID/Child.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,23 @@ +/* + * 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. + */ +class Child implements Parent, java.io.Serializable { } diff -r f82b730c798b -r 99dd9e50f37e test/java/io/Serializable/defaultSVID/DefaultSVID.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/defaultSVID/DefaultSVID.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,103 @@ +/* + * 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 + * @summary Test default serial version id creation + * + * @compile ParentA.java Child.java + * @run main DefaultSVID moveParentA + * @compile ParentB.java + * @run main DefaultSVID + */ + +import java.io.IOException; +import java.io.ObjectStreamClass; +import java.nio.file.*; +import static java.nio.file.StandardCopyOption.*; + +public class DefaultSVID { + + static String testClasses = System.getProperty("test.classes"); + + public static class MyClassLoader extends ClassLoader { + final String suffix; + + public MyClassLoader(String suffix) { + super(null); + this.suffix = suffix; + } + + public Class defineAndResolve(String name) { + try { + String file; + if ("Parent".equals(name)) { + file = name + suffix; + } else { + file = name; + } + byte[] classBytes = Files.readAllBytes(Paths.get(testClasses, file + ".class")); + Class ret = defineClass(name, classBytes, 0, classBytes.length); + resolveClass(ret); + return ret; + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + } + + public static void main(String args[]) throws Exception { + if (args.length > 0) { + Files.move(Paths.get(testClasses, "Parent.class"), + Paths.get(testClasses, "ParentA.class"), + REPLACE_EXISTING); + return; + } + + Files.move(Paths.get(testClasses, "Parent.class"), + Paths.get(testClasses, "ParentB.class"), + REPLACE_EXISTING); + + MyClassLoader cl_nodefault = new MyClassLoader("A"); + MyClassLoader cl_default = new MyClassLoader("B"); + + cl_nodefault.defineAndResolve("Parent"); + cl_default.defineAndResolve("Parent"); + + Class child_nodefault = cl_nodefault.defineAndResolve("Child"); + Class child_default = cl_default.defineAndResolve("Child"); + + ObjectStreamClass osc_child_nodefault = ObjectStreamClass.lookup(child_nodefault); + ObjectStreamClass osc_child_default = ObjectStreamClass.lookup(child_default); + + long svid_nodefault = osc_child_nodefault.getSerialVersionUID(); + long svid_default = osc_child_default.getSerialVersionUID(); + + System.out.printf("svid_nodefault : %016X \n svid_default : %016X\n", + svid_nodefault, svid_default); + + if (svid_nodefault != svid_default) { + throw new AssertionError("serial version IDs differ"); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/io/Serializable/defaultSVID/ParentA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/defaultSVID/ParentA.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,24 @@ +/* + * 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. + */ +interface Parent { +} diff -r f82b730c798b -r 99dd9e50f37e test/java/io/Serializable/defaultSVID/ParentB.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/defaultSVID/ParentB.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,25 @@ +/* + * 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. + */ +interface Parent { + default void parent() { } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/CharSequence/DefaultTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/Double/DoubleReducersTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/Double/DoubleReducersTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,70 @@ +/* + * 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 + * @summary + * @(#) DoubleReducersTest.java + * @author Tristan Yan + * @run testng DoubleReducersTest + */ + +import java.util.Random; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class DoubleReducersTest { + private final static int LOOP = 1 << 20; + + private final static Random rand = new Random(System.currentTimeMillis()); + + @Test + public void testMax() { + for(int index = 0; index < LOOP; index++){ + double d1 = rand.nextDouble(); + double d2 = rand.nextDouble(); + double expected = d1 > d2 ? d1 : d2; + assertEquals(Double.max(d1, d2), expected); + } + } + + @Test + public void testMin() { + for(int index = 0; index < LOOP; index++){ + double d1 = rand.nextDouble(); + double d2 = rand.nextDouble(); + double expected = d1 < d2 ? d1 : d2; + assertEquals(Double.min(d1, d2), expected); + } + } + + @Test + public void testSum() { + for(int index = 0; index < LOOP; index++){ + double d1 = rand.nextDouble(); + double d2 = rand.nextDouble(); + double expected = d1 + d2; + assertEquals(Double.sum(d1, d2), expected); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/Integer/IntegerReducersTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/Integer/IntegerReducersTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,92 @@ +/* + * 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 + * @summary + * @(#) IntegerReducersTest.java + * @author Tristan Yan + * @run testng IntegerReducersTest + */ + +import java.util.Random; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class IntegerReducersTest { + private final static int LOOP = 1 << 20; + + private final static Random rand = new Random(System.currentTimeMillis()); + + @Test + public void testMax() { + for(int index = 0; index < LOOP; index++){ + int i1 = rand.nextInt(); + int i2 = rand.nextInt(); + int expected = i1 > i2 ? i1 : i2; + assertEquals(Integer.max(i1, i2), expected); + } + } + + @Test + public void testMin() { + for(int index = 0; index < LOOP; index++){ + int i1 = rand.nextInt(); + int i2 = rand.nextInt(); + int expected = i1 < i2 ? i1 : i2; + assertEquals(Integer.min(i1, i2), expected); + } + } + + @Test + public void testSum() { + for(int index = 0; index < LOOP; index++){ + int i1 = rand.nextInt(); + int i2 = rand.nextInt(); + int expected = i1 + i2; + assertEquals(Integer.sum(i1, i2), expected); + } + } + + @Test + public void testUnsignedWithoutRadix(){ + for(int index = 0; index < LOOP; index++){ + int i = rand.nextInt(); + assertEquals(Integer.parseUnsignedInt(Integer.toUnsignedString(i)), i); + assertEquals(Integer.toUnsignedString(i, 10), Integer.toUnsignedString(i)); + if(i >= 0) + assertEquals(Integer.toUnsignedString(i), Integer.toString(i)); + } + } + + @Test + public void testUnsignedWithRadix(){ + for(int index = 0; index < LOOP; index++){ + int i = rand.nextInt(); + int radix = Character.MIN_RADIX + rand.nextInt(Character.MAX_RADIX - Character.MIN_RADIX + 1); + assertEquals(Integer.parseUnsignedInt(Integer.toUnsignedString(i, radix), radix), i); + if(i >= 0) + assertEquals(Integer.toUnsignedString(i, radix), Integer.toString(i, radix)); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/Long/LongReducersTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/Long/LongReducersTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,101 @@ +/* + * 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 + * @summary + * @author Tristan Yan + * @run testng LongReducersTest + */ + +import java.util.Random; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class LongReducersTest { + private final static int LOOP = 1 << 20; + + private final static Random rand = new Random(System.currentTimeMillis()); + + @Test + public void testMax() { + for(int index = 0; index < LOOP; index++){ + long l1 = rand.nextLong(); + long l2 = rand.nextLong(); + long expected = l1 > l2 ? l1 : l2; + assertEquals(Long.max(l1, l2), expected); + } + } + + @Test + public void testMin() { + for(int index = 0; index < LOOP; index++){ + long l1 = rand.nextLong(); + long l2 = rand.nextLong(); + long expected = l1 < l2 ? l1 : l2; + assertEquals(Long.min(l1, l2), expected); + } + } + + @Test + public void testSum() { + for(int index = 0; index < LOOP; index++){ + long l1 = rand.nextLong(); + long l2 = rand.nextLong(); + long expected = l1 + l2; + assertEquals(Long.sum(l1, l2), expected); + } + } + + @Test + public void testUnsignedWithoutRadix(){ + for(int index = 0; index < LOOP; index++){ + long l = rand.nextLong(); + assertEquals(Long.parseUnsignedLong(Long.toUnsignedString(l)), l); + assertEquals(Long.toUnsignedString(l, 10), Long.toUnsignedString(l)); + if(l >= 0) + assertEquals(Long.toUnsignedString(l), Long.toString(l)); + } + } + + @Test + public void testUnsignedWithRadix(){ + for(int index = 0; index < LOOP; index++){ + long l = rand.nextLong(); + int radix = Character.MIN_RADIX + rand.nextInt(Character.MAX_RADIX - Character.MIN_RADIX + 1); + assertEquals(Long.parseUnsignedLong(Long.toUnsignedString(l, radix), radix), l); + if(l >= 0) + assertEquals(Long.toUnsignedString(l, radix), Long.toString(l, radix)); + } + } + + @Test + public void testCompareUnsigned() { + for(int index = 0; index < LOOP; index++){ + long l1 = rand.nextLong(); + long l2 = rand.nextLong(); + assertEquals(Long.compareUnsigned(l1, l2), + Long.compare(Long.MAX_VALUE + l1, Long.MAX_VALUE + l2)); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/PrimitiveSumMinMaxTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/String/JoinTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/String/JoinTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,88 @@ +/* + * 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 + * @summary test for String.join(CharSequence , CharSequence...) and + * String.join(CharSequence , Iterable). + * @(#) JoinTest.java + * @author Tristan Yan + * @run testng JoinTest + */ + +import java.util.*; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class JoinTest { + private final String[] LANGUAGES = { "ABAP", "ALGOL", "ActionScript", + "AppleScript","AspectJ", "Assembly language", "AutoLISP", "AWK", "Bash", + "C", "C Shell", "CICS", "COBOL", "Cool", "CSH", "DCL", "Delphi", + "Eiffel", "F#", "Formula", "Fortran", "FoxBase", "FoxPro", "Groovy", + "Haskell", "J#", "JCL", "JavaScript", "Ksh", "LINC", "Lisp", "Logo", + "MASM", "MATLAB", "NASM", "XML", "Objective-C", "Pascal", "Perl", + "PL/I", "PostScript", "PowerBuilder", "PowerShell", "Prolog", "Pro*C", + "Python", "QBasic", "REBOL", "Ruby", "Scheme", "Sed", "Smalltalk", + "SQL", "VBScript" }; + + + private final String[] DELIMETERS = {"`", "~", "!", "@", "#", "$", "%", "^", + "&", "*", "(", ")", "-", "_", "+", "=", "\\", "|", ",", ".", "/", ":", + ";", "\"", "\"", "\n", "\t", " ", "\t"}; + + @Test + public void testJoin() { + //HashSet sort data with hashCode(), iterator order by hashCode() + List lanugageList = Arrays.asList(LANGUAGES); + Set lanugageSet = new HashSet<>(lanugageList); + Random rnd = new Random(); + String delimeter = DELIMETERS[rnd.nextInt(DELIMETERS.length)]; + StringBuilder sb = new StringBuilder(); + Iterator it = lanugageSet.iterator(); + int pos = 0; + while(it.hasNext()) { + sb.append(it.next()); + if(++pos < lanugageSet.size()) + sb.append(delimeter); + } + String result2 = String.join(delimeter, lanugageSet); + String result1 = sb.toString(); + assertEquals(result2, result1); + + Collections.shuffle(lanugageList, new Random(rnd.nextInt())); + String[] shuffledArray = new String[lanugageList.size()]; + lanugageList.toArray(shuffledArray); + result1 = String.join(delimeter, shuffledArray); + result2 = String.join(delimeter, lanugageList); + StringBuilder expectedSB = new StringBuilder(); + for(int index = 0; index < lanugageList.size() - 1; index++) + expectedSB.append(lanugageList.get(index)).append(delimeter); + expectedSB.append(lanugageList.get(lanugageList.size() - 1)); + assertEquals(expectedSB.toString(), result1); + assertEquals(result2, result1); + + String single = LANGUAGES[rnd.nextInt(LANGUAGES.length)]; + assertEquals(String.join(delimeter, new String[]{single}), single); + assertEquals(String.join(delimeter, new String[]{single}), single); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/StringBuffer/TestSynchronization.java diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/StringBuilder/AddAllTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/StringBuilder/AddAllTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,81 @@ +/* + * 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 + * @summary test for StringBuilde/StringBuffer.addAll() + * @library /sqeutil + * @author Tristan Yan + * @run testng AddAllTest + */ + +import java.util.*; +import java.util.stream.*; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class AddAllTest { + private final static int LINE_NUM = 1 << 8; + + private final static int LINE_MIN_CHARACTER_LEN = 2; + + private final static int LINE_MAX_CHARACTER_LEN = 80; + + @Test(dataProvider = "generateData") + public void builderAddAll(String[] buff){ + String str = Arrays.stream(buff).collect(Collectors.joining()); + int start = 0; + for(int index = 0; index < buff.length; index++){ + assert(start + buff[index].length() <= str.length()); + assertEquals(str.substring(start, start + buff[index].length()), buff[index]); + start += buff[index].length(); + } + } + + @Test(dataProvider = "generateData") + public void bufferAddAll(String[] buff){ + StringBuffer sb = Arrays.stream(buff).collect(StringBuffer::new, StringBuffer::append, (s, o) -> s.append(o)); + String str = sb.toString(); + int start = 0; + for(int index = 0; index < buff.length; index++){ + assert(start + buff[index].length() <= str.length()); + assertEquals(str.substring(start, start + buff[index].length()), buff[index]); + start += buff[index].length(); + } + } + + @DataProvider + public Object[][] generateData(){ + Object[][] data = new Object[LINE_NUM][]; + for(int line = 0; line < LINE_NUM; line++) { + List l = new ArrayList<>(); + String[] buffer = new String[line]; + for(int row = 0; row < line; row++) + buffer[row] = StringUtilities.randomString(LINE_MAX_CHARACTER_LEN, + 0); + data[line] = new Object[]{buffer}; + } + return data; + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/ThreadLocal/Basic.java --- a/test/java/lang/ThreadLocal/Basic.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/java/lang/ThreadLocal/Basic.java Mon Nov 11 23:17:30 2013 -0800 @@ -30,6 +30,7 @@ public class Basic { static ThreadLocal n = new ThreadLocal() { int i = 0; + @Override protected synchronized Object initialValue() { return new Integer(i++); } @@ -43,11 +44,12 @@ // Start the threads for(int i=0; i { String val; + @Override protected String initialValue() { - other = new ThreadLocal(); + other = new ThreadLocal<>(); // This should reuse the map that the containing get() created // or visa versa (i.e. instead of a second map being created). other.set("Other"); @@ -43,6 +44,7 @@ } } + @Override public void run() { MyLocal l = new MyLocal(); // This should pick up the initial value diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/ThreadLocal/TLRemoveTest.java --- a/test/java/lang/ThreadLocal/TLRemoveTest.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/java/lang/ThreadLocal/TLRemoveTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -32,6 +32,7 @@ private static final int REMOVE_SET_VALUE = 102; static ThreadLocal n = new ThreadLocal() { + @Override protected synchronized Integer initialValue() { return INITIAL_VALUE; } @@ -51,11 +52,12 @@ for(int i = 0; i void test(T arg) { + Function,Field[]> firstFunction = Class::getFields; + } + public static void main(String[] args) { + test("Hello World"); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,53 @@ +/* + * 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 8027681 + * @summary Lambda serialization fails once reflection proxy generation kicks in + * @author Robert Field + * @run main/othervm RepetitiveLambdaSerialization + */ + +import java.io.*; + +public class RepetitiveLambdaSerialization { + + static final int REPS = 20; + + public static void main(String[] args) throws Exception { + LSI ls = z -> "[" + z + "]"; + for (int i = 0; i < REPS; ++i) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(baos); + out.writeObject(ls); + out.flush(); + out.close(); + } + System.out.println("Passed."); + } +} + +interface LSI extends Serializable { + String convert(String x); +} diff -r f82b730c798b -r 99dd9e50f37e test/java/nio/Files/FilesLambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/nio/Files/FilesLambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,336 @@ +/* + * 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 + * @summary function test for Files.list()/find()/walk()/lines() + * @library /sqeutil + * @(#) FilesLambdaTest.java + * @author Tristan Yan + * @run testng/othervm FilesLambdaTest + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.NotDirectoryException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.*; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class FilesLambdaTest { + private static final Random rand = new Random(System.nanoTime()); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final String ROOT_NAME = "FilesLambdaTest" + System.nanoTime(); + + private static final String LINES_TEST_FILE = "lines" + System.nanoTime(); + + private static final int MAX_FILES_NUMBER = 1 << 6; + + private static final Charset UTF8 = Charset.forName("UTF-8"); + + private final static int MIN_LEN = 1 << 2; + + private final static int MAX_LEN = 1 << 8; + + private final static int LINES_NUM = 1 << 8; + + private static final String[][] folders = { + {"A01"}, + {"A01", "AA02"}, + {"A01", "AB02"}, + {"A01", "AC02"}, + {"B01"}, + {"B01", "BA02"}, + {"B01", "BA02", "BAA03"}, + {"B01", "BA02", "BAA03", "BAAA04", "BAAAA05", "BAAAAA06", "BAAAAAA07", + "BAAAAAAA08", "BAAAAAAAA09", "BAAAAAAAAA10", "BAAAAAAAAAA11"}, + {"C01"}, + {"C01", "CA02"}, + {"C01", "CD02"}, + {"D01", "DA02", "DAA03", "DAAA04", "DAAAA05", "DAAAAA06", "DAAAAAA07"}, + {"E01"}, + {"E01", "EA02"}, + {"E01", "EB02", "EBB03"}, + {"E01", "EC02", "ECC03", "ECCC04"}, + {"E01", "ED02", "EDD03", "EDDD04", "EDDDD05"}, + {"E01", "EE02", "EEE03", "EEEE04", "EEEEE05", "EEEEEE06"}, + {"E01", "EF02", "EFF03", "EFFF04", "EFFFF05", "EFFFFF06"}, + {"E01", "EG02", "EGG03", "EGGG04", "EGGGG05", "EGGGGG06", "EGGGGGG07"}, + {"E01", "EH02", "EHH03", "EHHH04", "EHHHH05", "EHHHHH06", "EHHHHHH07", + "EHHHHHHH08"}, + {"E01", "EI02", "EII03", "EIII04", "EIIII05", "EIIIII06", "EIIIIII07", + "EIIIIIII08", "EIIIIIIII09"}, + {"E01", "EJ02", "EJJ03", "EJJJ04", "EJJJJ05", "EJJJJJ06", "EJJJJJJ07", + "EJJJJJJJ08", "EJJJJJJJJ09", "EJJJJJJJJJ10"}, + {"E01", "EK02", "EKK03", "EKKK04", "EKKKK05", "EKKKKK06", "EKKKKKK07", + "EKKKKKKK08", "EKKKKKKKK09", "EKKKKKKKKK10", "EJJJJJJJJJJ11"} + }; + + private Path root; + + private Path testFile; + + private Path notExistPath; + + final Consumer writeReverseWithLink = path -> { + int filesCount = rand.nextInt(MAX_FILES_NUMBER); + for(int count = 0; count < filesCount; count++) { + String fileName = String.valueOf(rand.nextLong()); + Path file = path.resolve(fileName); + String linkName = String.valueOf(rand.nextLong()); + Path link = path.resolve(linkName); + try (BufferedWriter writer + = Files.newBufferedWriter(Files.createFile(file), UTF8)) { + writer.write(new StringBuilder(fileName).reverse().toString(), + 0, fileName.length()); + Files.createSymbolicLink(link, file); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + }; + + @BeforeClass + public void filesSetUp() throws IOException { + List paths = new ArrayList<>(); + root = Paths.get(TEST_SRC, ROOT_NAME); + paths.add(Files.createDirectory(root)); + for(int i = 0; i < folders.length; i++ ) { + String[] toBeCreated = folders[i]; + Path folder = Paths.get(ROOT_NAME, toBeCreated); + paths.add(Files.createDirectories(folder)); + } + paths.forEach(writeReverseWithLink); + + testFile = Paths.get(LINES_TEST_FILE); + try (BufferedWriter writer + = Files.newBufferedWriter(Files.createFile(testFile), UTF8)) { + for(int i = 0; i< LINES_NUM; i++) { + String line = StringUtilities.randomString(MAX_LEN, MIN_LEN); + writer.write(line, 0, line.length()); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + String NOT_EXIST = "NOT_EXIST"; + notExistPath = Paths.get(TEST_SRC, NOT_EXIST); + } + + @AfterClass + public void filesTearDown() throws IOException { + if(root != null) { + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException{ + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } + if(testFile != null) { + Files.delete(testFile); + } + } + + @Test + public void testFilesList() throws IOException { + checkFilesList(root); + } + + @Test + public void testWalk() throws IOException{ + String[] dir = folders[rand.nextInt(folders.length)]; + Path walkFolder = Paths.get(ROOT_NAME, dir); + final int maxDepth = rand.nextInt(11); + List expectedFullFileList = new ArrayList<>(); + List expectedMaxDepthFileList = new ArrayList<>(); + + List expectedFullSymList = new ArrayList<>(); + List expectedMaxDepthSymList = new ArrayList<>(); + + List expectedFullDirList = new ArrayList<>(); + List expectedMaxDepthDirList = new ArrayList<>(); + + Files.walkFileTree(walkFolder, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + if (walkFolder.relativize(file).getNameCount() <= maxDepth) { + expectedMaxDepthFileList.add(file); + if(Files.isSymbolicLink(file)) { + expectedMaxDepthSymList.add(file); + } + } + expectedFullFileList.add(file); + if(Files.isSymbolicLink(file)) { + expectedFullSymList.add(file); + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException{ + if (walkFolder.relativize(dir).getNameCount() <= maxDepth + || walkFolder.equals(dir)) { + expectedMaxDepthDirList.add(dir); + } + expectedFullDirList.add(dir); + return FileVisitResult.CONTINUE; + } + }); + Collections.sort(expectedFullFileList); + Collections.sort(expectedMaxDepthFileList); + Collections.sort(expectedFullSymList); + Collections.sort(expectedMaxDepthSymList); + Collections.sort(expectedFullDirList); + Collections.sort(expectedMaxDepthDirList); + + assertEquals(expectedMaxDepthFileList, + Files.walk(walkFolder, maxDepth).filter(p -> !Files.isDirectory(p)). + sorted().collect(Collectors.toList())); + assertEquals(expectedMaxDepthSymList, + Files.walk(walkFolder, maxDepth).filter(p -> Files.isSymbolicLink(p)). + sorted().collect(Collectors.toList())); + assertEquals(expectedMaxDepthDirList, + Files.walk(walkFolder, maxDepth).filter(p -> Files.isDirectory(p)). + sorted().collect(Collectors.toList())); + assertEquals(expectedFullFileList, + Files.walk(walkFolder).filter(p -> !Files.isDirectory(p)). + sorted().collect(Collectors.toList())); + assertEquals(expectedFullSymList, + Files.walk(walkFolder).filter(p -> Files.isSymbolicLink(p)). + sorted().collect(Collectors.toList())); + assertEquals(expectedFullDirList, + Files.walk(walkFolder).filter(p -> Files.isDirectory(p)). + sorted().collect(Collectors.toList())); + } + + @Test + public void testFind() throws IOException{ + String[] dir = folders[rand.nextInt(folders.length)]; + Path walkFolder = Paths.get(ROOT_NAME, dir); + String walkFoderName = dir[dir.length - 1]; + + int walkFolderDepth = Integer.parseInt(walkFoderName.substring(walkFoderName.length() - 2)); + int maxDepth = rand.nextInt(11); + Stream stream + = Files.find(walkFolder, maxDepth, (p,bfa) -> Files.isSymbolicLink(p)); + stream.forEach(p -> { + assertTrue(Files.isSymbolicLink(p)); + assertFalse(Files.isDirectory(p)); + assertFalse(Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)); + String parentName = p.getParent().toFile().getName(); + int depth = Integer.parseInt(parentName.substring(parentName.length() - 2)); + assertTrue(depth - walkFolderDepth < maxDepth); + }); + + assertEquals(Files.find(walkFolder, maxDepth, (p,bfa) -> Files.isSymbolicLink(p)).toArray(), + Files.find(walkFolder, maxDepth, (p,bfa) -> bfa.isSymbolicLink()).toArray()); + } + + @Test + public void testLines() throws IOException{ + Stream stream = Files.lines(testFile, UTF8); + List lines = Files.readAllLines(testFile, UTF8); + assertEquals(lines, stream.collect(Collectors.toList())); + } + + @Test(expectedExceptions = IOException.class) + public void testListNoReadAccess() throws IOException{ + Files.list(notExistPath); + } + + @Test(expectedExceptions = NotDirectoryException.class) + public void testListNotDirectory() throws IOException{ + Files.list(testFile); + } + + @Test(expectedExceptions = IOException.class) + public void testFindNoExist() throws IOException{ + Files.find(notExistPath, Integer.MAX_VALUE, (p, bfa) -> true); + } + + @Test(expectedExceptions = IOException.class) + public void testLinesNoExist() throws IOException{ + Files.lines(notExistPath, UTF8); + } + + @Test(expectedExceptions = IOException.class) + public void testWalkNoExist() throws IOException{ + Files.walk(notExistPath); + } + + @Test(expectedExceptions = IOException.class) + public void testWalkNoExistWithDepth() throws IOException{ + Files.walk(notExistPath, Integer.MAX_VALUE); + } + + public void checkFilesList(Path checkPath){ + try { + assert(Files.isDirectory(checkPath)); + Files.list(checkPath).filter(p -> Files.isDirectory(p)).forEach(p -> checkFilesList(p)); + assertEquals(Files.list(checkPath).filter(p -> Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)).count(), + Files.list(checkPath).filter(p -> Files.isSymbolicLink(p)).count()); + assertTrue(Files.list(checkPath).filter(p -> Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)).allMatch(file -> contentRevered(file))); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private boolean contentRevered(Path path) { + try (BufferedReader reader = Files.newBufferedReader(path, UTF8)){ + String fileName = path.getName(path.getNameCount() -1).toString(); + String reversed = new StringBuilder(reader.readLine()).reverse().toString(); + return (fileName.equals(reversed)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/nio/file/Files/FaultyFileSystem.java diff -r f82b730c798b -r 99dd9e50f37e test/java/nio/file/Files/PassThroughFileSystem.java diff -r f82b730c798b -r 99dd9e50f37e test/java/nio/file/Files/StreamTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Arrays/ArraysLambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/Arrays/ArraysLambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,221 @@ +/* + * 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 + * @summary Lambda unit test for Arrays. + * @library /sqeutil + * @(#) ArraysTest.java + * @author Tristan Yan + * @run testng ArraysLambdaTest + */ + +import java.util.Arrays; +import java.util.Random; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class ArraysLambdaTest { + private final static int ARRAY_SIZE = 1 << 8; + + private final static int MIN_LEN = 1 << 2; + + private final static int MAX_LEN = 1 << 6; + + private final static Random rand = new Random(System.currentTimeMillis()); + + private long[] generateLongData(int size) { + long[] array = new long[size]; + for(int i = 0; i < size; i++) { + array[i] = rand.nextLong(); + } + return array; + } + + private int[] generateIntData(int size) { + int[] array = new int[size]; + for(int i = 0; i < size; i++) { + array[i] = rand.nextInt(); + } + return array; + } + + private double[] generateDoubleData(int size) { + double[] array = new double[size]; + //Precision could be changed when do parallel calculation, we only use + //integer to test it to prevent precision lost issue + for(int i = 0; i < size; i++) { + array[i] = rand.nextInt(1024); + } + return array; + } + + private String[] generateStringData(int size) { + String[] array = new String[size]; + for(int i = 0; i < size; i++) { + array[i] = StringUtilities.randomString(MAX_LEN, MIN_LEN); + } + return array; + } + + private StringBuilder[] generateSBData(int size) { + StringBuilder[] array = new StringBuilder[size]; + for(int i = 0; i < size; i++) { + array[i] = new StringBuilder(StringUtilities.randomString(MAX_LEN, MIN_LEN)); + } + return array; + } + + @Test + public void testParallelPrefixForInt() { + int startIndex = rand.nextInt(ARRAY_SIZE); + int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex); + + int[] intArr1 = generateIntData(ARRAY_SIZE); + int[] intArr2 = Arrays.copyOf(intArr1, ARRAY_SIZE); + int[] intBackArr = Arrays.copyOf(intArr1, ARRAY_SIZE); + Arrays.parallelPrefix(intArr1, LambdaUtilities.addIntBinaryOperator()); + assertEquals(intArr1.length, intBackArr.length); + int totalInt = 0; + for(int i = 0; i < ARRAY_SIZE; i++) { + totalInt += intBackArr[i]; + assertEquals(totalInt, intArr1[i]); + } + Arrays.parallelPrefix(intArr2, startIndex, endIndex, LambdaUtilities.addIntBinaryOperator()); + totalInt = 0; + for(int i = startIndex; i < endIndex; i++) { + totalInt += intBackArr[i]; + assertEquals(totalInt, intArr2[i]); + } + } + + @Test + public void testParallelPrefixForLong() { + int startIndex = rand.nextInt(ARRAY_SIZE); + int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex); + long[] longArr1 = generateLongData(ARRAY_SIZE); + long[] longArr2 = Arrays.copyOf(longArr1, ARRAY_SIZE); + long[] longBackArr = Arrays.copyOf(longArr1, ARRAY_SIZE); + Arrays.parallelPrefix(longArr1, LambdaUtilities.addLongBinaryOperator()); + assertEquals(longArr1.length, longBackArr.length); + long totalLong = 0; + for(int i = 0; i < ARRAY_SIZE; i++) { + totalLong += longBackArr[i]; + assertEquals(totalLong, longArr1[i]); + } + Arrays.parallelPrefix(longArr2, startIndex, endIndex, LambdaUtilities.addLongBinaryOperator()); + totalLong = 0; + for(int i = startIndex; i < endIndex; i++) { + totalLong += longBackArr[i]; + assertEquals(totalLong, longArr2[i]); + } + } + + @Test + public void testParallelPrefixForDouble() { + int startIndex = rand.nextInt(ARRAY_SIZE); + int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex); + double[] doubleArr1 = generateDoubleData(ARRAY_SIZE); + double[] doubleArr2 = Arrays.copyOf(doubleArr1, ARRAY_SIZE); + double[] doubleBackArr = Arrays.copyOf(doubleArr1, ARRAY_SIZE); + Arrays.parallelPrefix(doubleArr1, LambdaUtilities.addDoubleBinaryOperator()); + assertEquals(doubleArr1.length, doubleBackArr.length); + double totalDouble = 0; + for(int i = 0; i < ARRAY_SIZE; i++) { + totalDouble += doubleBackArr[i]; + assertEquals(totalDouble, doubleArr1[i]); + } + Arrays.parallelPrefix(doubleArr2, startIndex, endIndex, LambdaUtilities.addDoubleBinaryOperator()); + totalDouble = 0; + for(int i = startIndex; i < endIndex; i++) { + totalDouble += doubleBackArr[i]; + assertEquals(totalDouble, doubleArr2[i]); + } + } + + @Test + public void testParallelPrefix() { + int startIndex = rand.nextInt(ARRAY_SIZE); + int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex); + StringBuilder[] sbArr1 = generateSBData(ARRAY_SIZE); + StringBuilder[] sbArr2 = Arrays.copyOf(sbArr1, ARRAY_SIZE); + StringBuilder[] sbBackArr = Arrays.copyOf(sbArr1, ARRAY_SIZE); + Arrays.parallelPrefix(sbArr1, LambdaUtilities.appendSBBinaryOperator()); + assertEquals(sbArr1.length, sbBackArr.length); + StringBuilder sbTotal = new StringBuilder(); + for(int i = 0; i < ARRAY_SIZE; i++) { + sbTotal.append(sbBackArr[i]); + assertEquals(sbTotal.toString(), sbArr1[i].toString()); + } + Arrays.parallelPrefix(sbArr2, startIndex, endIndex, LambdaUtilities.appendSBBinaryOperator()); + sbTotal = new StringBuilder(); + for(int i = startIndex; i < endIndex; i++) { + sbTotal.append(sbBackArr[i]); + assertEquals(sbTotal.toString(), sbArr2[i].toString()); + } + } + + @Test + public void testSetAll() { + boolean[] both = new boolean[]{true, false}; + for(boolean isParallel:both) { + //test Arrays.setAll(double[], IntFunction) + int[] iArray = new int[ARRAY_SIZE]; + if (isParallel) + Arrays.parallelSetAll(iArray, i -> 2 * i); + else + Arrays.setAll(iArray, i -> 2 * i); + for(int i = 0; i < iArray.length; i++) + assertEquals(iArray[i], 2 * i); + + //test Arrays.setAll(long[], IntFunction) + long[] lArray = new long[ARRAY_SIZE]; + if (isParallel) + Arrays.parallelSetAll(lArray, i -> (long)i << 32); + else + Arrays.setAll(lArray, i -> (long)i << 32); + for(int i = 0; i < lArray.length; i++) + assertEquals(lArray[i] >> 32, i); + + //test Arrays.setAll(double[], IntToDoubleFunction) + double[] dArray = new double[ARRAY_SIZE]; + if (isParallel) + Arrays.parallelSetAll(dArray, i -> Math.sin(i)); + else + Arrays.setAll(dArray, i -> Math.sin(i)); + for(int i = 0; i < dArray.length; i++) + assertEquals(dArray[i], Math.sin(i)); + + //test Arrays.setAll(T[], IntFunction) + //This is a other version of Arrays.copy() + String[] sArrExpected = generateStringData(ARRAY_SIZE); + String[] sArr = new String[ARRAY_SIZE]; + if (isParallel) + Arrays.parallelSetAll(sArr, i -> sArrExpected[i]); + else + Arrays.setAll(sArr, i -> sArrExpected[i]); + for(int i = 0; i < sArr.length; i++) + assertEquals(sArrExpected[i], sArrExpected[i]); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Arrays/ParallelPrefix.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Arrays/ParallelSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/Arrays/ParallelSet.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,157 @@ +/* + * 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 + * @summary unit test for Arrays.ParallelSet()/set(). + * @author Tristan Yan + * @run testng ParallelSet + */ + +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 static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class ParallelSet { + //Array size less than MIN_PARTITION + private final static int SMALL_ARRAY_SIZE = 1 << 3; + + //Array size equals MIN_PARTITION + private final static int THRESHOLD_ARRAY_SIZE = 1 << 4; + + //Array size greater than MIN_PARTITION + private final static int MEDIUM_ARRAY_SIZE = 1 << 8; + + //Array size much greater than MIN_PARTITION + private final static int LARGE_ARRAY_SIZE = 1 << 12; + + private final static int[] ARRAY_SIZE_COLLECTION = new int[]{ + SMALL_ARRAY_SIZE, THRESHOLD_ARRAY_SIZE,MEDIUM_ARRAY_SIZE, LARGE_ARRAY_SIZE}; + + @DataProvider + public static Object[][] intSet(){ + return genericData("Arrays.parrallelSetAll/setAll(new int[%d],IntUnaryOperator)", + int[]::new, new IntUnaryOperator[]{i -> i * 2, i -> i * 2 + 1}); + } + + @DataProvider + public static Object[][] longSet(){ + return genericData("Arrays.parrallelSetAll/setAll(new long[%d],IntToLongeFunction)", + long[]::new, new IntToLongFunction[]{ i -> i * 2, i -> i * 2 + 1}); + } + + @DataProvider + public static Object[][] doubleSet(){ + return genericData("Arrays.parallelSetAll/setAll(new double[%d],IntToDoubleFunction)", + double[]::new, new IntToDoubleFunction[]{i -> i * 2, i -> i * 2 + 1}); + } + + @DataProvider + public static Object[][] stringSet(){ + return genericData("Arrays.parallelSetAll/setAll(new String[%d],IntFunction)", + String[]::new, new IntFunction[]{Integer::toString}); + } + + private static Object[][] genericData(String description, IntFunction generateFunc, OPS[] funcs) { + //test arrays which size is equals n-1, n, n+1 + Object[][] data = new Object[ARRAY_SIZE_COLLECTION.length * 3 * funcs.length][4]; + for(int n = 0; n < ARRAY_SIZE_COLLECTION.length; n++ ) { + for(int testValue = -1 ; testValue <= 1; testValue++) { + int array_size = ARRAY_SIZE_COLLECTION[n] + testValue; + for(int funcN = 0; funcN < funcs.length; funcN++) { + int index = n * 3 * funcs.length + (testValue + 1) * funcs.length + funcN; + data[index][0] = String.format(description, array_size); + data[index][1] = array_size; + data[index][2] = generateFunc; + data[index][3] = funcs[funcN]; + } + } + } + return data; + } + + @Test(dataProvider="intSet") + public void testSetAllForInt(String description,int size, IntFunction dataFunc, IntUnaryOperator iuo) { + int[] expectedResult = dataFunc.apply(size); + for(int i = 0; i < size; i++) + expectedResult[i] = iuo.applyAsInt(i); + + int[] sequentialResult = dataFunc.apply(size); + Arrays.setAll(sequentialResult, iuo); + assertEquals(sequentialResult, expectedResult); + + int[] parallelResult = dataFunc.apply(size); + Arrays.setAll(parallelResult, iuo); + assertEquals(sequentialResult, expectedResult); + } + + @Test(dataProvider="longSet") + public void testSetAllForLong(String description, int size, IntFunction dataFunc, IntToLongFunction itlf) { + long[] expectedResult = dataFunc.apply(size); + for(int i = 0; i < size; i++) + expectedResult[i] = itlf.applyAsLong(i); + + long[] sequentialResult = dataFunc.apply(size); + Arrays.setAll(sequentialResult, itlf); + assertEquals(sequentialResult, expectedResult); + + long[] parallelResult = dataFunc.apply(size); + Arrays.setAll(parallelResult, itlf); + assertEquals(sequentialResult, expectedResult); + } + + @Test(dataProvider="doubleSet") + public void testSetAllForDouble(String description,int size, IntFunction dataFunc, IntToDoubleFunction itdf) { + double[] expectedResult = dataFunc.apply(size); + for(int i = 0; i < size; i++) + expectedResult[i] = itdf.applyAsDouble(i); + + double[] sequentialResult = dataFunc.apply(size); + Arrays.setAll(sequentialResult, itdf); + assertEquals(sequentialResult, expectedResult); + + double[] parallelResult = dataFunc.apply(size); + Arrays.setAll(parallelResult, itdf); + assertEquals(sequentialResult, expectedResult); + } + + @Test(dataProvider="stringSet") + public void testSetAllForString(String description,int size, IntFunction dataFunc, IntFunction itsf) { + String[] expectedResult = dataFunc.apply(size); + for(int i = 0; i < size; i++) + expectedResult[i] = itsf.apply(i); + + String[] sequentialResult = dataFunc.apply(size); + Arrays.setAll(sequentialResult, itsf); + assertEquals(sequentialResult, expectedResult); + + String[] parallelResult = dataFunc.apply(size); + Arrays.setAll(parallelResult, itsf); + assertEquals(sequentialResult, expectedResult); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/BitSet/BitSetStreamTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collection/CollectionDefaults.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collection/IntRemovePredicateAllTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/Collection/IntRemovePredicateAllTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,169 @@ +/* + * 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 + * @summary sanity tests for Collection.removeIf()/forEach() + * @library /sqeutil + * @(#) IntRemovePredicateAllTest.java + * @author Tristan Yan + * @run testng IntRemovePredicateAllTest + */ + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; +import static org.testng.Assert.*; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +public class IntRemovePredicateAllTest > { + private final static Random rand = new Random(System.currentTimeMillis()); + + //1K data is best we can optimize for now. + private final static int MAX_SIZE = 1 << 10; + + //At least we should have 4 elements in the list + private final static int MIN_SIZE = 1 << 2; + + T t; + + public IntRemovePredicateAllTest(T typeObject1){ + t = typeObject1; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private static Collection + generateData(Class> cls, + int... initValue) throws InstantiationException, + IllegalAccessException, NoSuchMethodException, + IllegalArgumentException, InvocationTargetException{ + Collection c; + int t1Size = 0; + if(initValue.length == 0) { + c = cls.newInstance(); + t1Size= rand.nextInt(MAX_SIZE); + if(t1Size < MIN_SIZE) t1Size = MIN_SIZE; + } else { + Constructor con = cls.getConstructor(int.class); + c = (Collection)con.newInstance(initValue[0]); + t1Size = initValue.length == 2 ? initValue[1] : initValue[0]; + } + for(int i = 0; i < t1Size; i++) + c.add(rand.nextInt()); + return c; + } + + @Factory + @SuppressWarnings({"rawtypes", "unchecked"}) + public static Object[] create() throws Exception{ + List result = new ArrayList<>(); + Class[] defaultConstructorClazz = { + (Class>)(Class)(ArrayDeque.class), + (Class>)(Class)(ArrayList.class), + (Class>)(Class)(ConcurrentLinkedDeque.class), + (Class>)(Class)(ConcurrentLinkedQueue.class), + (Class>)(Class)(ConcurrentSkipListSet.class), + (Class>)(Class)(HashSet.class), + (Class>)(Class)(LinkedBlockingDeque.class), + (Class>)(Class)(LinkedBlockingQueue.class), + (Class>)(Class)(LinkedHashSet.class), + (Class>)(Class)(LinkedList.class), + (Class>)(Class)(LinkedTransferQueue.class), + (Class>)(Class)(PriorityBlockingQueue.class), + (Class>)(Class)(PriorityQueue.class), + (Class>)(Class)(Stack.class), + (Class>)(Class)(TreeSet.class), + (Class>)(Class)(Vector.class) + }; + + Class[] capacityConstructorClazz = { + (Class>)(Class)(ArrayBlockingQueue.class), + (Class>)(Class)(ArrayDeque.class), + (Class>)(Class)(ArrayList.class), + (Class>)(Class)(HashSet.class), + (Class>)(Class)(LinkedBlockingDeque.class), + (Class>)(Class)(LinkedBlockingQueue.class), + (Class>)(Class)(LinkedHashSet.class), + (Class>)(Class)(PriorityBlockingQueue.class), + (Class>)(Class)(PriorityQueue.class), + (Class>)(Class)(Vector.class) + }; + + for(int i = 0; i < defaultConstructorClazz.length + + capacityConstructorClazz.length; i++) { + int initSize1 = rand.nextInt(MAX_SIZE); + if(initSize1 < MIN_SIZE) initSize1 = MIN_SIZE; + Collection c = i < defaultConstructorClazz.length ? + generateData(defaultConstructorClazz[i]) : + generateData(capacityConstructorClazz[i - defaultConstructorClazz.length], + initSize1); + result.add(new IntRemovePredicateAllTest(c)); + } + return result.toArray(); + } + + @Test + public void testRemoveIf() { + int limit = rand.nextInt(); + boolean isUP = rand.nextBoolean(); + Predicate p = LambdaUtilities.randomIntegerPredicate(isUP, limit); + t.removeIf(p); + assertTrue(verifyMatch(t, limit, !isUP, true)); + } + + @Test + public void testForEach() { + final AtomicInteger accumulator = new AtomicInteger(0); + t.forEach(t -> accumulator.addAndGet(t)); + + Optional opi = t.stream().reduce((i1, i2) -> i1 + i2); + assertTrue(opi.isPresent()); + assertEquals(accumulator.get(), opi.get().intValue()); + } + + private boolean verifyMatch(Collection c, int limit, boolean isUP, + boolean all) { + Iterator it = c.iterator(); + while(it.hasNext()) { + int current = it.next(); + if(isUP) { + if(all) { + if(current < limit) return false; + } else { + if(current >= limit) return true; + } + } else { + if(all) { + if(current >= limit) return false; + } else { + if(current < limit) return true; + } + } + } + return all; + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collection/MOAT.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collection/testlibrary/CollectionAsserts.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collection/testlibrary/CollectionSupplier.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collections/SingletonIterator.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collections/UnmodifiableMapEntrySet.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Collections/Wrappers.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Comparator/BasicTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Comparator/TypeTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Iterator/IteratorDefaults.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Iterator/PrimitiveIteratorDefaults.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/List/ExtensionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/List/ExtensionsTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,211 @@ +/* + * 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 + * @summary Basic tests for List's extension methods + * @library /sqeutil + * @(#) ListTest.java + * @author Tristan Yan + * @run testng ExtensionsTest + */ + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Stream; +import static org.testng.Assert.*; +import org.testng.annotations.*; + +public class ExtensionsTest> { + protected Class typeObject; + + protected boolean hasIni; + + protected int initSize; + + protected final static int START = -1 << 6; + + protected final static int END = 1 << 6; + + protected final static Random rand = new Random(System.currentTimeMillis()); + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected static Class[] defaultConstructorClazz = { + (Class>)(Class)(ArrayList.class), + (Class>)(Class)(CopyOnWriteArrayList.class), + (Class>)(Class)(LinkedList.class), + (Class>)(Class)(Stack.class), + (Class>)(Class)(Vector.class) + }; + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected static Class[] capacityConstructorClazz = { + (Class>)(Class)(ArrayList.class), + (Class>)(Class)(Vector.class) + }; + + public ExtensionsTest(Class clazz, int... initSizes){ + this.typeObject = clazz; + assert(initSizes.length <= 1); + if(initSizes.length == 1) { + hasIni = true; + this.initSize = initSizes[0]; + } + } + + protected List generateList(int start, int end, int size) + throws Exception{ + List list = hasIni ? + (List)LambdaUtilities.create(typeObject, initSize) : + (List)LambdaUtilities.create(typeObject); + for(int i = 0; i < size; i++) { + int element = start + rand.nextInt(end - start); + list.add(element); + } + return list; + } + + protected List generateList(int start, int end) throws Exception{ + return generateList(start, end, end - start); + } + + @Factory + @SuppressWarnings({"rawtypes", "unchecked"}) + public static Object[] create(){ + List result = new ArrayList<>(); + Stream stream1 = Arrays.stream(defaultConstructorClazz); + Stream stream2 = Arrays.stream(capacityConstructorClazz); + stream1.forEach(clazz -> result.add(new ExtensionsTest(clazz))); + stream2.forEach(clazz -> result.add(new ExtensionsTest(clazz, + END - START + rand.nextInt(END - START)))); + return result.toArray(); + } + + @Test + public void testReplaceAll() throws Exception { + List list = generateList(START, END); + List listCloned = hasIni ? + (List)LambdaUtilities.create(typeObject, initSize) : + (List)LambdaUtilities.create(typeObject); + listCloned.addAll(list); + EnumSet set = EnumSet.allOf(LambdaUtilities.IntOp.class); + LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()]; + set.toArray(ops); + LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)]; + int value = START + rand.nextInt(END - START); + if( op == LambdaUtilities.IntOp.DIVIDE || op == LambdaUtilities.IntOp.MOD) + while(value == 0) + value = START + rand.nextInt(END - START); + list.replaceAll(LambdaUtilities.opIntegerUnaryOperator(op, value)); + checkReplace(listCloned, list, op, value); + } + + @Test + @SuppressWarnings({"rawtypes", "unchecked"}) + public void testSort() throws Exception{ + Comparator[] cs = { Comparator.naturalOrder(), + Comparator.reverseOrder(), + Comparator.comparingInt(LambdaUtilities.highestPosValueIntFunction() ), + Comparator.comparingInt(LambdaUtilities.lowestPosValueIntFunction() ), + }; + + Iterator csit = Arrays.stream(cs).iterator(); + while(csit.hasNext()) + testComparator((Comparator)csit.next()); + } + + @Test + public void testRemoveAll() throws Exception { + List list = generateList(START, END); + int limit = rand.nextInt(2 * (END - START)) + 2 * START; + boolean isUP = rand.nextBoolean(); + list.removeIf(LambdaUtilities.randomIntegerPredicate(isUP, limit)); + assertTrue(verifyMatch(list, limit, !isUP, true)); + } + + @Test + public void testForEach() throws Exception { + List list = generateList(START, END); + List listCloned = hasIni ? + (List)LambdaUtilities.create(typeObject, initSize) : + (List)LambdaUtilities.create(typeObject); + list.forEach(LambdaUtilities.copyConsumer(listCloned)); + assertEquals(list, listCloned); + } + private void checkReplace(List orig, List replaced, + LambdaUtilities.IntOp op, int value) { + assertEquals(orig.size(), replaced.size()); + for(int index = 0; index < orig.size(); index++) + switch(op) { + case ADD: + assertTrue(orig.get(index) + value == replaced.get(index)); + break; + case SUBTRACT: + assertTrue(orig.get(index) - value == replaced.get(index)); + break; + case MULTIPLY: + assertTrue(orig.get(index) * value == replaced.get(index)); + break; + case DIVIDE: + assertTrue(orig.get(index) / value == replaced.get(index)); + break; + default: + assertTrue(orig.get(index) % value == replaced.get(index)); + break; + } + } + + private void testComparator(Comparator c) throws Exception { + List list = generateList(START, END); + List listCloned = hasIni ? + (List)LambdaUtilities.create(typeObject, initSize) : + (List)LambdaUtilities.create(typeObject); + listCloned.addAll(list); + list.sort(c); + for(int i = 0; i < list.size() - 1; i++) + assertTrue(c.compare(list.get(i), list.get(i+1)) <= 0); + //assertEquals(list, listCloned); + } + + private boolean verifyMatch(Collection c, int limit, boolean isUP, + boolean all) { + Iterator it = c.iterator(); + while(it.hasNext()) { + int current = it.next(); + if(isUP) { + if(all) { + if(current < limit) return false; + } else { + if(current >= limit) return true; + } + } else { + if(all) { + if(current >= limit) return false; + } else { + if(current < limit) return true; + } + } + } + return all; + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/List/ListDefaults.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/List/SortAndReplaceAllTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/List/SortAndReplaceAllTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,189 @@ +/* + * 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 + * @summary test for List default methods replaceAll() and sort(); + * @(#) SortAndReplaceAllTest.java + * @library /sqeutil + * @author Tristan Yan + * @run testng SortAndReplaceAllTest + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.Stack; +import java.util.Vector; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Function; +import java.util.stream.Stream; +import static org.testng.Assert.*; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +public class SortAndReplaceAllTest >{ + protected Class typeObject; + + protected boolean hasIni; + + protected int initSize; + + protected final static int START = -1 << 6; + + protected final static int END = 1 << 6; + + protected final static Random rand = new Random(System.currentTimeMillis()); + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected static Class[] defaultConstructorClazz = { + (Class>)(Class)(ArrayList.class), + (Class>)(Class)(CopyOnWriteArrayList.class), + (Class>)(Class)(LinkedList.class), + (Class>)(Class)(Stack.class), + (Class>)(Class)(Vector.class) + }; + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected static Class[] capacityConstructorClazz = { + (Class>)(Class)(ArrayList.class), + (Class>)(Class)(Vector.class) + }; + + public SortAndReplaceAllTest(Class clazz, int... initSizes){ + this.typeObject = clazz; + assert(initSizes.length <= 1); + if(initSizes.length == 1) { + hasIni = true; + this.initSize = initSizes[0]; + } + } + + private List generateList(int start, int end, int size) + throws Exception{ + List list = hasIni ? + (List)LambdaUtilities.create(typeObject, initSize) : + (List)LambdaUtilities.create(typeObject); + for(int i = 0; i < size; i++) { + int element = start + rand.nextInt(end - start); + list.add(element); + } + return list; + } + + protected List generateList(int start, int end) throws Exception{ + return generateList(start, end, end - start); + } + + @Factory + @SuppressWarnings({"rawtypes", "unchecked"}) + public static Object[] create(){ + List result = new ArrayList<>(); + Stream stream1 = Arrays.stream(defaultConstructorClazz); + Stream stream2 = Arrays.stream(capacityConstructorClazz); + stream1.forEach(clazz -> result.add(new SortAndReplaceAllTest(clazz))); + stream2.forEach(clazz -> result.add(new SortAndReplaceAllTest(clazz, + END - START + rand.nextInt(END - START)))); + return result.toArray(); + } + + @Test + public void testReplaceAll() throws Exception { + List list = generateList(START, END); + List listCloned = hasIni ? + (List)LambdaUtilities.create(typeObject, initSize) : + (List)LambdaUtilities.create(typeObject); + listCloned.addAll(list); + EnumSet set = EnumSet.allOf(LambdaUtilities.IntOp.class); + LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()]; + set.toArray(ops); + LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)]; + int value = START + rand.nextInt(END - START); + if( op == LambdaUtilities.IntOp.DIVIDE || op == LambdaUtilities.IntOp.MOD) { + while(value == 0) { + value = START + rand.nextInt(END - START); + } + } + list.replaceAll(LambdaUtilities.opIntegerUnaryOperator(op, value)); + checkReplace(listCloned, list, op, value); + } + + @Test + @SuppressWarnings({"rawtypes", "unchecked"}) + public void testSort() throws Exception{ + final Function i2s = i -> String.valueOf(i); + Comparator[] cs = { Comparator.naturalOrder(), + Comparator.reverseOrder(), + Comparator.comparingInt(LambdaUtilities.highestPosValueIntFunction()), + Comparator.comparingInt(LambdaUtilities.lowestPosValueIntFunction()), + Comparator.comparing(i2s, Comparator.naturalOrder()), + Comparator.comparing(i2s, Comparator.reverseOrder()), + }; + + Iterator csit = Arrays.stream(cs).iterator(); + while(csit.hasNext()) { + testComparator((Comparator)csit.next()); + } + } + + private void checkReplace(List orig, List replaced, + LambdaUtilities.IntOp op, int value) { + assertEquals(orig.size(), replaced.size()); + for(int index = 0; index < orig.size(); index++) { + switch(op) { + case ADD: + assertTrue(orig.get(index) + value == replaced.get(index)); + break; + case SUBTRACT: + assertTrue(orig.get(index) - value == replaced.get(index)); + break; + case MULTIPLY: + assertTrue(orig.get(index) * value == replaced.get(index)); + break; + case DIVIDE: + assertTrue(orig.get(index) / value == replaced.get(index)); + break; + default: + assertTrue(orig.get(index) % value == replaced.get(index)); + break; + } + } + } + + private void testComparator(Comparator c) throws Exception { + List list = generateList(START, END); + List listCloned = hasIni ? + (List)LambdaUtilities.create(typeObject, initSize) : + (List)LambdaUtilities.create(typeObject); + listCloned.addAll(list); + list.sort(c); + for(int i = 0; i < list.size() - 1; i++) { + assertTrue(c.compare(list.get(i), list.get(i+1)) <= 0); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Map/Defaults.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Map/LambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/Map/LambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,225 @@ +/* + * 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 + * @summary sanity test forEach on Map + * @library /sqeutil + * @(#)LambdaTest.java + * @author Yong Lu/Tristan Yan + * @run testng LambdaTest + */ + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.stream.Stream; +import static org.testng.Assert.*; +import org.testng.ITest; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public class LambdaTest> implements ITest { + private final static Random rand = new Random(System.currentTimeMillis()); + private Class typeObject; + private boolean hasIni; + private int initSize; + + private final static int START = -1 << 6; + private final static int END = 1 << 6; + + private static Class[] defaultConstructorClazz = { + (Class>) (Class) (ConcurrentHashMap.class), + (Class>) (Class) (ConcurrentSkipListMap.class), + (Class>) (Class) (HashMap.class), + (Class>) (Class) (Hashtable.class), + (Class>) (Class) (LinkedHashMap.class), + (Class>) (Class) (IdentityHashMap.class), + (Class>) (Class) (WeakHashMap.class) + }; + + public LambdaTest(Class clazz, int... initSizes) { + this.typeObject = clazz; + assert (initSizes.length <= 1); + if (initSizes.length == 1) { + hasIni = true; + this.initSize = initSizes[0]; + } + } + + protected Map generateData(int start, int end, int size) throws Exception { + Map m = LambdaUtilities.createMap(typeObject); + for (int i = 0; i < size; i++) { + int element = start + rand.nextInt(end - start); + if (element != Integer.SIZE) { + m.put(String.valueOf(element), new Integer(element)); + } + } + return m; + } + + protected Map generateData(int start, int end) throws Exception { + return generateData(start, end, end - start); + } + + @Factory + public static Object[] create(){ + List result = new ArrayList<>(); + Stream stream = Arrays.stream(defaultConstructorClazz); + stream.forEach(clazz -> result.add(new LambdaTest(clazz))); + return result.toArray(); + } + + @Test + public void testForEach() throws Exception{ + Map m1 = generateData(START, END); + m1.forEach((x,y) -> assertTrue(m1.get(x).equals(y))); + + Map m2 = LambdaUtilities.createMap(typeObject); + m1.forEach((x,y) -> m2.put(x, y)); + m2.forEach((x,y) -> assertTrue(m1.get(x).equals(y))); + + m1.forEach((x,y) -> { + m1.put(x, Integer.SIZE); + assertFalse(m1.containsValue(y)); + }); + } + + @Test + public void testReplaceAll() throws Exception{ + //ConcurrentSkipListMap doesn't replaceAll + if(typeObject.getName().endsWith("ConcurrentSkipListMap")) + return; + Map m = generateData(START, END); + Map mCloned = LambdaUtilities.createMap(typeObject); + mCloned.putAll(m); + EnumSet set = EnumSet.allOf(LambdaUtilities.IntOp.class); + LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()]; + set.toArray(ops); + LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)]; + int value = START + rand.nextInt(END - START); + while((value = START + rand.nextInt(END - START)) == 0); + m.replaceAll(LambdaUtilities.opBiFunction(op, value)); + checkReplace(mCloned, m, op, value); + } + + @Test + public void testCompute() throws Exception{ + Map m = generateData(START, END); + Map mCloned = LambdaUtilities.createMap(typeObject); + mCloned.putAll(m); + final int value = START + rand.nextInt(END - START); + EnumSet set = EnumSet.allOf(LambdaUtilities.IntOp.class); + LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()]; + set.toArray(ops); + LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)]; + mCloned.keySet().forEach(t -> m.compute(t, LambdaUtilities.opBiFunction(op, value))); + checkReplace(mCloned, m, op, value); + } + + @Test + public void testMerge() throws Exception{ + Map m = generateData(START, END); + Map mCloned = LambdaUtilities.createMap(typeObject); + mCloned.putAll(m); + final int value = START + rand.nextInt(END - START); + EnumSet set = EnumSet.allOf(LambdaUtilities.IntOp.class); + LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()]; + set.toArray(ops); + LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)]; + mCloned.keySet().forEach(t -> m.merge(t, value, LambdaUtilities.opBiFunction(op))); + checkReplace(mCloned, m, op, value); + } + + @Test + public void testReplace() throws Exception{ + Map m = generateData(START, END); + Map mCloned = LambdaUtilities.createMap(typeObject); + mCloned.putAll(m); + final int value = START + rand.nextInt(END - START); + EnumSet set = EnumSet.allOf(LambdaUtilities.IntOp.class); + LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()]; + set.toArray(ops); + LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)]; + mCloned.keySet().forEach(t -> m.replace(t, mCloned.get(t), LambdaUtilities.opBiFunction(op).apply(mCloned.get(t), value))); + checkReplace(mCloned, m, op, value); + } + + private void checkReplace(Map orig, Map replaced, + LambdaUtilities.IntOp op, int value) { + assertEquals(orig.size(), replaced.size()); + Iterator it = orig.keySet().iterator(); + while(it.hasNext()) { + String k = it.next(); + if(value == 0){ + assertEquals(orig.get(k), replaced.get(k)); + continue; + } + switch(op) { + case ADD: + assertTrue(orig.get(k) + value == replaced.get(k)); + break; + case SUBTRACT: + assertTrue(orig.get(k) - value == replaced.get(k)); + break; + case MULTIPLY: + assertTrue(orig.get(k) * value == replaced.get(k)); + break; + case DIVIDE: + assertTrue(orig.get(k) / value == replaced.get(k)); + break; + default: + assertTrue(orig.get(k) % value == replaced.get(k)); + break; + } + } + } + + @Test + public void testRemove() throws Exception { + Map m = generateData(START, END); + Map mCloned = LambdaUtilities.createMap(typeObject); + mCloned.putAll(m); + mCloned.keySet().forEach(t -> m.remove(t)); + assertTrue(m.isEmpty()); + } + + @Test + public void testComputeIfAbsent() throws Exception { + Map m = generateData(START, END); + Map mCloned = LambdaUtilities.createMap(typeObject); + final int value = START + rand.nextInt(END - START); + EnumSet set = EnumSet.allOf(LambdaUtilities.IntOp.class); + LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()]; + set.toArray(ops); + LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)]; + m.keySet().forEach(t -> mCloned.computeIfAbsent(t, LambdaUtilities.mappingFunction(m, op, value))); + checkReplace(m, mCloned, op, value); + } + + @Override + public String getTestName() { + return typeObject.getName() + ""; + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Map/MapBinToFromTreeTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Optional/Basic.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Optional/BasicDouble.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Optional/BasicInt.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Optional/BasicLong.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Random/RandomStreamTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Random/RandomTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Spliterator/SpliteratorCharacteristics.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java --- a/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -513,6 +513,12 @@ @Test(dataProvider = "Spliterator") @SuppressWarnings({"unchecked", "rawtypes"}) + public void testMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) public void testSplitAfterFullTraversal(String description, Collection exp, Supplier s) { testSplitAfterFullTraversal(s, (Consumer b) -> b); } @@ -669,6 +675,11 @@ } @Test(dataProvider = "Spliterator.OfInt") + public void testIntMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") public void testIntSplitAfterFullTraversal(String description, Collection exp, Supplier s) { testSplitAfterFullTraversal(s, intBoxingConsumer()); } @@ -829,6 +840,11 @@ } @Test(dataProvider = "Spliterator.OfLong") + public void testLongMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") public void testLongSplitAfterFullTraversal(String description, Collection exp, Supplier s) { testSplitAfterFullTraversal(s, longBoxingConsumer()); } @@ -989,6 +1005,11 @@ } @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") public void testDoubleSplitAfterFullTraversal(String description, Collection exp, Supplier s) { testSplitAfterFullTraversal(s, doubleBoxingConsumer()); } @@ -1097,6 +1118,53 @@ } } + private static > void testMixedTraverseAndSplit( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList dest = new ArrayList<>(); + spliterator = supplier.get(); + Consumer b = boxingAdapter.apply(dest::add); + + Spliterator spl1, spl2, spl3; + spliterator.tryAdvance(b); + spl2 = spliterator.trySplit(); + if (spl2 != null) { + spl2.tryAdvance(b); + spl1 = spl2.trySplit(); + if (spl1 != null) { + spl1.tryAdvance(b); + spl1.forEachRemaining(b); + } + spl2.tryAdvance(b); + spl2.forEachRemaining(b); + } + spliterator.tryAdvance(b); + spl3 = spliterator.trySplit(); + if (spl3 != null) { + spl3.tryAdvance(b); + spl3.forEachRemaining(b); + } + spliterator.tryAdvance(b); + spliterator.forEachRemaining(b); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, dest.size()); + } + assertEquals(dest.size(), exp.size()); + + if (isOrdered) { + assertEquals(dest, exp); + } + else { + assertContentsUnordered(dest, exp); + } + } + private static > void testSplitAfterFullTraversal( Supplier supplier, UnaryOperator> boxingAdapter) { diff -r f82b730c798b -r 99dd9e50f37e test/java/util/SplittableRandom/SplittableRandomTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/StringJoiner/BasicTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/StringJoiner/BasicTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,151 @@ +/* + * 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 + * @summary Sanity Test for StringJoiner + * @(#) BasicTest.java + * @library /sqeutil + * @author Tristan Yan + * @run testng BasicTest + */ + +import java.util.*; +import java.util.stream.Collectors; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class BasicTest { + protected final static int STRING_ARR_SIIE = 1 << 8; + + protected final static int STRING_LEN = 1 << 10; + + protected final static int TIMES = 1 << 4; + + protected final static Random rnd = new Random(System.currentTimeMillis()); + + protected String[] randomStringArray(){ + String[] arr = new String[STRING_ARR_SIIE]; + for(int index = 0; index < STRING_ARR_SIIE; index++) + arr[index] = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN)); + return arr; + } + + @DataProvider(name = "Connector-Provider") + public Object[][] notAlphanumeric(){ + Object[][] data = new Object[TIMES][3]; + for(int i = 0; i < TIMES; i++) { + List list = new ArrayList<>(); + for(char c=32; c < 127; c++) { + if(!Character.isAlphabetic(c) && !Character.isDigit(c)) + list.add(String.valueOf(c)); + } + Collections.shuffle(list); + int infixPos = rnd.nextInt(list.size()/2); + if(infixPos < 1) infixPos = 1; + int prefixPos = infixPos + rnd.nextInt(list.size() - infixPos); + if(prefixPos == infixPos) prefixPos = infixPos + 1; + data[i] = new String[]{ list.subList(0, infixPos).stream().collect(Collectors.joining("")).toString(), + list.subList(infixPos, prefixPos).stream().collect(Collectors.joining("")).toString(), + list.subList(prefixPos, list.size()).stream().collect(Collectors.joining("")).toString() + }; + } + return data; + } + + @Test(dataProvider = "Connector-Provider") + public void constructorTest(String INFIX, String PREFIX, String SUFFIX) { + //Test constructor with only infix + //String[] sj = notAlphanumeric(); + String[] rndStrings = randomStringArray(); + final StringJoiner nofixsj = new StringJoiner(INFIX); + Arrays.stream(rndStrings).forEach(t -> {nofixsj.add(t); }); + String longStr1 = nofixsj.toString(); + int index = 0; + int pos = 0; + while(index < rndStrings.length) { + if(index < rndStrings.length - 1) { + assertEquals(longStr1.substring(pos, pos + rndStrings[index].length()), rndStrings[index]); + pos += rndStrings[index++].length(); + assertEquals(longStr1.substring(pos, pos + INFIX.length()), INFIX); + pos += INFIX.length(); + } else + assertEquals(longStr1.substring(pos, pos + rndStrings[index].length()), rndStrings[index++]); + } + + //Test constructor with infix, prefix and suffix + final StringJoiner hasfixsj = new StringJoiner(INFIX, PREFIX, SUFFIX); + Arrays.stream(rndStrings).forEach(t -> {hasfixsj.add(t); }); + String longStr2 = hasfixsj.toString(); + index = 0; + pos = 0; + assertEquals(longStr2.substring(pos, pos + PREFIX.length()), PREFIX); + pos += PREFIX.length(); + while(index < rndStrings.length) { + if(index < rndStrings.length - 1) { + assertEquals(longStr2.substring(pos, pos + rndStrings[index].length()), rndStrings[index]); + pos += rndStrings[index++].length(); + assertEquals(longStr2.substring(pos, pos + INFIX.length()), INFIX); + pos += INFIX.length(); + } else { + assertEquals(longStr2.substring(pos, pos + rndStrings[index].length()), rndStrings[index]); + pos += rndStrings[index++].length(); + } + } + assertEquals(longStr2.substring(pos, pos + SUFFIX.length()), SUFFIX); + } + + @Test(dataProvider = "Connector-Provider") + public void addTest(String INFIX, String PREFIX, String SUFFIX) { + StringJoiner nofixsj = new StringJoiner(INFIX); + String randAddStr1 = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN)); + assertEquals(nofixsj.add(randAddStr1).toString(), randAddStr1); + String randAddStr2 = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN)); + assertEquals(nofixsj.add(randAddStr2).toString(), randAddStr1 + INFIX + randAddStr2); + + //Test constructor with infix, prefix and suffix + StringJoiner hasfixsj = new StringJoiner(INFIX, PREFIX, SUFFIX); + assertEquals(hasfixsj.add(randAddStr1).toString(), PREFIX + randAddStr1 + SUFFIX); + assertEquals(hasfixsj.add(randAddStr2).toString(), PREFIX + randAddStr1 + INFIX + randAddStr2 + SUFFIX); + } + + @Test(dataProvider = "Connector-Provider") + public void testsetEmptyValue(String INFIX, String PREFIX, String SUFFIX) { + StringJoiner nofixsj = new StringJoiner(INFIX); + String emptyExpectedStr = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN)); + assertEquals(nofixsj.toString().length(), 0); + nofixsj.setEmptyValue(emptyExpectedStr); + assertEquals(nofixsj.toString(), emptyExpectedStr); + String randAddStr = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN)); + assertEquals(nofixsj.add(randAddStr).toString(), randAddStr); + + //Test constructor with infix, prefix and suffix + StringJoiner hasfixsj = new StringJoiner(INFIX, PREFIX, SUFFIX); + assertEquals(hasfixsj.toString(), PREFIX + SUFFIX); + hasfixsj.setEmptyValue(emptyExpectedStr); + assertEquals(hasfixsj.toString(), emptyExpectedStr); + + assertEquals(hasfixsj.add(randAddStr).toString(), PREFIX + randAddStr + SUFFIX); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/StringJoiner/MergeTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/AtomicInteger/LambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/AtomicInteger/LambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,175 @@ +/* + * 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 + * @summary test for AtomicInteger.updateAndGet()/getAndUpdate() and + * AtomicInteger.accumulateAndGet()/getAndAccumulate(); + * @(#) LambdaTest.java + * @library /sqeutil + * @author Tristan Yan + * @bug 8001666 + * @run testng LambdaTest + */ + +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicInteger; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class LambdaTest { + private static enum Type{updateAndGet, getAndUpdate, accumulateAndGet, getAndAccumulate}; + + private static Random rand = new Random(System.currentTimeMillis()); + + private final static int MAX_VALUE = 1 << 24; + + private final static int MIN_VALUE = -1 << 24; + + private final static int OP_TIMES = 1 << 10; + + private final static int THREAD_NUM = 1 << 4; + + @DataProvider + public Object[][] booleanProvider(){ + Object[][] providersParam = new Object[Type.values().length][]; + Object[] a = Type.values(); + for(int i = 0; i < a.length; i++) + providersParam[i] = new Object[]{a[i]}; + return providersParam; + } + + @Test(dataProvider = "booleanProvider") + @SuppressWarnings({"rawtypes", "unchecked"}) + public void test(final Type type) throws InterruptedException, + ExecutionException { + int initValue = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE); + final AtomicInteger ai = new AtomicInteger(initValue); + final int randPlus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE); + final int randMinus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE); + switch(type) { + case updateAndGet: + assertEquals(ai.updateAndGet(LambdaUtilities.addIntUnaryOperator(randPlus)) + , initValue + randPlus); + assertEquals(ai.updateAndGet(LambdaUtilities.subIntUnaryOperator(randMinus)) + , initValue + randPlus - randMinus); + break; + case getAndUpdate: + assertEquals(ai.getAndUpdate(LambdaUtilities.addIntUnaryOperator(randPlus)) + , initValue); + assertEquals(ai.getAndUpdate(LambdaUtilities.subIntUnaryOperator(randMinus)) + , initValue + randPlus); + break; + case accumulateAndGet: + assertEquals(ai.accumulateAndGet(randPlus,LambdaUtilities.addIntBinaryOperator()) + , initValue + randPlus); + assertEquals(ai.accumulateAndGet(randMinus,LambdaUtilities.subIntBinaryOperator()) + , initValue + randPlus - randMinus); + break; + case getAndAccumulate: + assertEquals(ai.getAndAccumulate(randPlus,LambdaUtilities.addIntBinaryOperator()) + , initValue); + assertEquals(ai.getAndAccumulate(randMinus,LambdaUtilities.subIntBinaryOperator()) + , initValue + randPlus); + break; + } + assertEquals(ai.get(), initValue + randPlus - randMinus); + + ai.set(initValue); + Callable ac = new Callable(){ + @Override + public Integer call() throws Exception { + int plusTimes1 = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + if(plus) plusTimes1++; + switch(type) { + case updateAndGet: + ai.updateAndGet(plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case getAndUpdate: + ai.getAndUpdate(plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case accumulateAndGet: + ai.accumulateAndGet(plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + break; + case getAndAccumulate: + ai.getAndAccumulate(plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + } + } + return plusTimes1; + } + + }; + FutureTask[] futures = new FutureTask[THREAD_NUM -1]; + for(int i = 0; i < THREAD_NUM -1; i++) { + futures[i] = new FutureTask(ac); + new Thread(futures[i]).start(); + } + + int plusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + if(plus) plusTimes++; + switch(type) { + case updateAndGet: + ai.updateAndGet(plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case getAndUpdate: + ai.getAndUpdate(plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case accumulateAndGet: + ai.accumulateAndGet(plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + break; + case getAndAccumulate: + ai.getAndAccumulate(plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + } + } + for(int i = 0; i < THREAD_NUM -1; i++) { + plusTimes += ((FutureTask)futures[i]).get(); + } + int expected = initValue + plusTimes * randPlus - + (THREAD_NUM * OP_TIMES - plusTimes) * randMinus; + assertEquals(expected, ai.get()); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/AtomicIntegerFieldUpdater/LambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/AtomicIntegerFieldUpdater/LambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,182 @@ +/* + * 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 + * @summary test for AtomicIntegerUpdateField.updateAndGet()/getAndUpdate() and + * AtomicIntegerUpdateField.accumulateAndGet()/getAndAccumulate(); + * @(#) LambdaTest.java + * @library /sqeutil + * @author Tristan Yan + * @run testng LambdaTest + * @bug 8001666 + */ + +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class LambdaTest { + private static enum Type{updateAndGet, getAndUpdate, accumulateAndGet, getAndAccumulate}; + + private static Random rand = new Random(System.currentTimeMillis()); + + private final static int MAX_VALUE = 1 << 24; + + private final static int MIN_VALUE = -1 << 24; + + private final static int OP_TIMES = 1 << 10; + + private final static int THREAD_NUM = 1 << 4; + + @DataProvider + public Object[][] booleanProvider(){ + Object[][] providersParam = new Object[Type.values().length][]; + Object[] a = Type.values(); + for(int i = 0; i < a.length; i++) + providersParam[i] = new Object[]{a[i]}; + return providersParam; + } + + @Test(dataProvider = "booleanProvider") + @SuppressWarnings({"rawtypes", "unchecked"}) + public void test(final Type type) throws InterruptedException, + ExecutionException { + final Updater u = new Updater(); + final AtomicIntegerFieldUpdater accAIFU = AtomicIntegerFieldUpdater.newUpdater((Class)(Class)u.getClass(), "accumulation"); + final int randPlus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE); + final int randMinus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE); + switch(type) { + case updateAndGet: + assertEquals(accAIFU.updateAndGet(u, + LambdaUtilities.addIntUnaryOperator(randPlus)), randPlus); + assertEquals(accAIFU.updateAndGet(u, + LambdaUtilities.subIntUnaryOperator(randMinus)), randPlus - randMinus); + break; + case getAndUpdate: + assertEquals(accAIFU.getAndUpdate(u, + LambdaUtilities.addIntUnaryOperator(randPlus)), 0); + assertEquals(accAIFU.getAndUpdate(u, + LambdaUtilities.subIntUnaryOperator(randMinus)), randPlus); + break; + case accumulateAndGet: + assertEquals(accAIFU.accumulateAndGet(u, randPlus, + LambdaUtilities.addIntBinaryOperator()), randPlus); + assertEquals(accAIFU.accumulateAndGet(u, randMinus, + LambdaUtilities.subIntBinaryOperator()), randPlus - randMinus); + break; + case getAndAccumulate: + assertEquals(accAIFU.getAndAccumulate(u, randPlus, + LambdaUtilities.addIntBinaryOperator()), 0); + assertEquals(accAIFU.getAndAccumulate(u, randMinus, + LambdaUtilities.subIntBinaryOperator()), randPlus); + break; + } + assertEquals(u.accumulation, randPlus - randMinus); + + u.accumulation = 0; + + Callable ac = new Callable(){ + @Override + public Integer call() throws Exception { + int plusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + if(plus) plusTimes++; + switch(type) { + case updateAndGet: + accAIFU.updateAndGet(u, plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case getAndUpdate: + accAIFU.getAndUpdate(u, plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case accumulateAndGet: + accAIFU.accumulateAndGet(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + break; + case getAndAccumulate: + accAIFU.getAndAccumulate(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + break; + } + } + return plusTimes; + } + }; + + FutureTask[] futures = new FutureTask[THREAD_NUM -1]; + for(int i = 0; i < THREAD_NUM -1; i++) { + futures[i] = new FutureTask(ac); + new Thread(futures[i]).start(); + } + int plusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + if(plus) plusTimes++; + switch(type) { + case updateAndGet: + accAIFU.updateAndGet(u, plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case getAndUpdate: + accAIFU.getAndUpdate(u, plus ? + LambdaUtilities.addIntUnaryOperator(randPlus) : + LambdaUtilities.subIntUnaryOperator(randMinus)); + break; + case accumulateAndGet: + accAIFU.accumulateAndGet(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + break; + case getAndAccumulate: + accAIFU.getAndAccumulate(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + break; + } + } + for(int i = 0; i < THREAD_NUM -1; i++) { + plusTimes += ((FutureTask)futures[i]).get(); + } + int expected = plusTimes * randPlus - + (THREAD_NUM * OP_TIMES - plusTimes) * randMinus; + assertEquals(expected, u.accumulation); + } + + static class Updater{ + public volatile int accumulation; + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/AtomicLong/LambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/AtomicLong/LambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,245 @@ +/* + * 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 + * @summary test AtomicLong.updateAndGet()/getAndUpdate() and + * AtomicLong.accumulateAndGet()/getAndAccumulate(); + * @(#) LambdaTest.java + * @library /sqeutil + * @author Tristan Yan + * @run testng LambdaTest + * @bug 8001666 + */ + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicLong; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + + +public class LambdaTest { + private static enum Type{updateAndGet, getAndUpdate, accumulateAndGet, getAndAccumulate}; + + private static Random rand = new Random(System.currentTimeMillis()); + + private final static int MAX_VALUE = 1 << 24; + + private final static int MIN_VALUE = -1 << 24; + + private final static int OP_TIMES = 1 << 10; + + private final static int THREAD_NUM = 1 << 4; + + @DataProvider + public Object[][] booleanProvider(){ + Object[][] providersParam = new Object[Type.values().length][]; + Object[] a = Type.values(); + for(int i = 0; i < a.length; i++) + providersParam[i] = new Object[]{a[i]}; + return providersParam; + } + + @Test(dataProvider = "booleanProvider") + public void test(final Type type) throws InterruptedException, + ExecutionException { + long initValue = rand.nextLong(); + final AtomicLong al = new AtomicLong(initValue); + long tl1 = rand.nextLong(); + if(((byte)(tl1 >> 63) & (byte)(initValue >> 63)) == 0){ + if(initValue > 0) { + if(tl1 > Long.MAX_VALUE - initValue) + tl1 = - tl1; + } else { + if(tl1 < Long.MIN_VALUE - initValue) + tl1 = - tl1; + } + } + final long randPlus = tl1; + + long tl2 = rand.nextLong(); + if(((byte)(tl2 >> 63) & (byte)(initValue + randPlus >> 63)) == 1){ + if(initValue + randPlus > 0) { + if(-tl2 > Long.MAX_VALUE - (initValue + randPlus)) + tl2 = - tl2; + } else { + if(tl2 < Long.MIN_VALUE + (initValue + randPlus)) + tl2 = - tl2; + } + } + final long randMinus = tl2; + switch(type) { + case updateAndGet: + assertEquals(al.updateAndGet(LambdaUtilities.addLongUnaryOperator(randPlus)) + , initValue + randPlus); + assertEquals(al.updateAndGet(LambdaUtilities.subLongUnaryOperator(randMinus)) + , initValue + randPlus - randMinus); + break; + case getAndUpdate: + assertEquals(al.getAndUpdate(LambdaUtilities.addLongUnaryOperator(randPlus)) + , initValue); + assertEquals(al.getAndUpdate(LambdaUtilities.subLongUnaryOperator(randMinus)) + , initValue + randPlus); + break; + case accumulateAndGet: + assertEquals(al.accumulateAndGet(randPlus, LambdaUtilities.addLongBinaryOperator()) + , initValue + randPlus); + assertEquals(al.accumulateAndGet(randMinus, LambdaUtilities.subLongBinaryOperator()) + , initValue + randPlus - randMinus); + break; + case getAndAccumulate: + assertEquals(al.getAndAccumulate(randPlus, LambdaUtilities.addLongBinaryOperator()) + , initValue); + assertEquals(al.getAndAccumulate(randMinus, LambdaUtilities.subLongBinaryOperator()) + , initValue + randPlus); + break; + } + assertEquals(al.get() , initValue + randPlus - randMinus); + + final long randPlus1 = rand.nextBoolean() ? (long)rand.nextInt(MAX_VALUE) : -(long)rand.nextInt(MAX_VALUE); + final long randMinus1 = rand.nextBoolean() ? (long)rand.nextInt(MAX_VALUE) : -(long)rand.nextInt(MAX_VALUE); + al.set(initValue); + final int mainPLusTimes = 0; + int minusPLusTimes = 0; + + class UpdateThread extends Thread{ + OpTimes ops; + CountDownLatch latch; + UpdateThread(OpTimes ops, CountDownLatch latch){ + this.ops = ops; + this.latch = latch; + } + @Override + public void run() { + int plusTimes = 0; + int minusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + if(plus) { + if (randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1 + || randPlus1 < 0 && al.get() < Long.MIN_VALUE - randPlus1) + continue; + } + else { + if (randPlus1 > 0 && al.get() < Long.MIN_VALUE + randPlus1 + || randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1) + continue; + } + switch(type) { + case updateAndGet: + al.updateAndGet(plus ? + LambdaUtilities.addLongUnaryOperator(randPlus1) : + LambdaUtilities.subLongUnaryOperator(randMinus1)); + break; + case getAndUpdate: + al.getAndUpdate(plus ? + LambdaUtilities.addLongUnaryOperator(randPlus1) : + LambdaUtilities.subLongUnaryOperator(randMinus1)); + break; + case accumulateAndGet: + al.accumulateAndGet(plus ? randPlus1 : randMinus1, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + case getAndAccumulate: + al.getAndAccumulate(plus ? randPlus1 : randMinus1, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + } + if(plus) + plusTimes++; + else + minusTimes++; + } + ops.plus = plusTimes; + ops.minus = minusTimes; + latch.countDown(); + } + + }; + OpTimes[] opts = new OpTimes[THREAD_NUM -1]; + CountDownLatch latch = new CountDownLatch(THREAD_NUM -1); + for(int i = 0; i < THREAD_NUM -1; i++) { + opts[i] = new OpTimes(); + new UpdateThread(opts[i], latch).start(); + } + int plusTimes = 0; + int minusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + if(plus) { + if (randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1 + || randPlus1 < 0 && al.get() < Long.MIN_VALUE - randPlus1) + continue; + } + else { + if (randPlus1 > 0 && al.get() < Long.MIN_VALUE + randPlus1 + || randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1) + continue; + } + switch(type) { + case updateAndGet: + al.updateAndGet(plus ? + LambdaUtilities.addLongUnaryOperator(randPlus1) : + LambdaUtilities.subLongUnaryOperator(randMinus1)); + break; + case getAndUpdate: + al.getAndUpdate(plus ? + LambdaUtilities.addLongUnaryOperator(randPlus1) : + LambdaUtilities.subLongUnaryOperator(randMinus1)); + break; + case accumulateAndGet: + al.accumulateAndGet(plus ? randPlus1 : randMinus1, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + case getAndAccumulate: + al.getAndAccumulate(plus ? randPlus1 : randMinus1, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + } + if(plus) + plusTimes++; + else + minusTimes++; + } + latch.await(); + for(int i = 0; i < THREAD_NUM -1; i++) { + plusTimes += opts[i].plus; + minusTimes += opts[i].minus; + } + long expected = initValue + plusTimes * randPlus1 - + minusTimes * randMinus1; + assertEquals(expected, al.get()); + } +} +class OpTimes{ + public int plus; + + public int minus; +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/AtomicLongFieldUpdater/LambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/AtomicLongFieldUpdater/LambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,213 @@ +/* + * 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 + * @summary test AtomicLongFieldUpdater.updateAndGet()/getAndUpdate() and + * AtomicLongFieldUpdater.accumulateAndGet()/getAndAccumulate(); + * @(#) LambdaTest.java + * @library /sqeutil + * @author Tristan Yan + * @run testng LambdaTest + * @bug 8001666 + */ + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class LambdaTest { + private static enum Type{updateAndGet, getAndUpdate, accumulateAndGet, getAndAccumulate}; + + private static Random rand = new Random(System.currentTimeMillis()); + + private final static int OP_TIMES = 1 << 10; + + private final static int THREAD_NUM = 1 << 4; + + @DataProvider + public Object[][] booleanProvider(){ + Object[][] providersParam = new Object[Type.values().length][]; + Object[] a = Type.values(); + for(int i = 0; i < a.length; i++) + providersParam[i] = new Object[]{a[i]}; + return providersParam; + } + + @Test(dataProvider = "booleanProvider") + @SuppressWarnings({"rawtypes", "unchecked"}) + public void test(final Type type) throws InterruptedException, + ExecutionException { + long initValue = rand.nextLong(); + final Updater u = new Updater(); + u.accumulation = initValue; + final AtomicLongFieldUpdater accAIFU + = AtomicLongFieldUpdater.newUpdater((Class)(Class)u.getClass(), "accumulation"); + final long randPlus = rand.nextLong(); + final long randMinus = rand.nextLong(); + switch(type) { + case updateAndGet: + assertEquals(accAIFU.updateAndGet(u, + LambdaUtilities.addLongUnaryOperator(randPlus)), + initValue + randPlus); + assertEquals(accAIFU.updateAndGet(u, + LambdaUtilities.subLongUnaryOperator(randMinus)), + initValue + randPlus - randMinus); + break; + case getAndUpdate: + assertEquals(accAIFU.getAndUpdate(u, + LambdaUtilities.addLongUnaryOperator(randPlus)), + initValue); + assertEquals(accAIFU.getAndUpdate(u, + LambdaUtilities.subLongUnaryOperator(randMinus)), + initValue + randPlus); + break; + case accumulateAndGet: + assertEquals(accAIFU.accumulateAndGet(u, randPlus, + LambdaUtilities.addLongBinaryOperator()), + initValue + randPlus); + assertEquals(accAIFU.accumulateAndGet(u, randMinus, + LambdaUtilities.subLongBinaryOperator()), + initValue + randPlus - randMinus); + break; + case getAndAccumulate: + assertEquals(accAIFU.getAndAccumulate(u, randPlus, + LambdaUtilities.addLongBinaryOperator()), + initValue); + assertEquals(accAIFU.getAndAccumulate(u, randMinus, + LambdaUtilities.subLongBinaryOperator()), + initValue + randPlus); + break; + } + assertEquals(u.accumulation, initValue + randPlus - randMinus); + + class UpdateThread extends Thread{ + OpTimes ops; + + CountDownLatch latch; + UpdateThread(OpTimes ops, CountDownLatch latch){ + this.ops = ops; + this.latch = latch; + } + @Override + public void run() { + int plusTimes = 0; + int minusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + accAIFU.updateAndGet(u, plus ? + LambdaUtilities.addLongUnaryOperator(randPlus) : + LambdaUtilities.subLongUnaryOperator(randMinus)); + break; + case getAndUpdate: + accAIFU.getAndUpdate(u, plus ? + LambdaUtilities.addLongUnaryOperator(randPlus) : + LambdaUtilities.subLongUnaryOperator(randMinus)); + break; + case accumulateAndGet: + accAIFU.accumulateAndGet(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + case getAndAccumulate: + accAIFU.getAndAccumulate(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + } + if(plus) + plusTimes++; + else + minusTimes++; + } + ops.plus = plusTimes; + ops.minus = minusTimes; + latch.countDown(); + } + }; + u.accumulation = initValue; + + int plusTimes = 0; + int minusTimes = 0; + OpTimes[] opts = new OpTimes[THREAD_NUM -1]; + CountDownLatch latch = new CountDownLatch(THREAD_NUM -1); + for(int i = 0; i < THREAD_NUM -1; i++) { + opts[i] = new OpTimes(); + new UpdateThread(opts[i], latch).start(); + } + + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + accAIFU.updateAndGet(u, plus ? + LambdaUtilities.addLongUnaryOperator(randPlus) : + LambdaUtilities.subLongUnaryOperator(randMinus)); + break; + case getAndUpdate: + accAIFU.getAndUpdate(u, plus ? + LambdaUtilities.addLongUnaryOperator(randPlus) : + LambdaUtilities.subLongUnaryOperator(randMinus)); + break; + case accumulateAndGet: + accAIFU.accumulateAndGet(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + case getAndAccumulate: + accAIFU.getAndAccumulate(u, plus ? randPlus : randMinus, + plus ? LambdaUtilities.addLongBinaryOperator() : + LambdaUtilities.subLongBinaryOperator()); + break; + } + if(plus) + plusTimes++; + else + minusTimes++; + } + latch.await(); + for(int i = 0; i < THREAD_NUM -1; i++) { + plusTimes += opts[i].plus; + minusTimes += opts[i].minus; + } + long expected = initValue + plusTimes * randPlus - + minusTimes * randMinus; + assertEquals(expected, u.accumulation); + } + + static class Updater{ + public volatile long accumulation; + } + + static class OpTimes{ + public int plus; + + public int minus; + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/AtomicReference/LambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/AtomicReference/LambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,221 @@ +/* + * 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 + * @summary test for AtomicReference.updateAndGet()/getAndUpdate() and + * AtomicReference.accumulateAndGet()/getAndAccumulate(); + * @(#) LambdaTest.java + * @library ../../ + * @author Tristan Yan + * @run testng LambdaTest + * @bug 8001666 + */ + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BinaryOperator; +import java.util.function.UnaryOperator; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class LambdaTest { + private static enum Type{updateAndGet, getAndUpdate, accumulateAndGet, getAndAccumulate}; + + private static Random rand = new Random(System.currentTimeMillis()); + + private final static int OP_TIMES = 1 << 10; + + private final static int THREAD_NUM = 1 << 4; + + @DataProvider + public Object[][] booleanProvider(){ + Object[][] providersParam = new Object[Type.values().length][]; + Object[] a = Type.values(); + for(int i = 0; i < a.length; i++) + providersParam[i] = new Object[]{a[i]}; + return providersParam; + } + + @Test(dataProvider = "booleanProvider") + public void test(final Type type) throws InterruptedException{ + int initPlus = rand.nextInt(); + int initMinus = rand.nextInt(); + final AtomicReference ar + = new AtomicReference<>(new OpValues(initPlus, initMinus)); + final int oprnd = rand.nextInt(); + boolean startFromPlus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + assertEquals(ar.updateAndGet(opUnaryOperator(startFromPlus, oprnd)) + , startFromPlus ? new OpValues(initPlus + oprnd, initMinus) : + new OpValues(initPlus, initMinus - oprnd)); + assertEquals(ar.updateAndGet(opUnaryOperator(!startFromPlus, oprnd)) + , new OpValues(initPlus + oprnd, initMinus - oprnd)); + break; + case getAndUpdate: + assertEquals(ar.getAndUpdate(opUnaryOperator(startFromPlus, oprnd)) + , new OpValues(initPlus, initMinus)); + assertEquals(ar.getAndUpdate(opUnaryOperator(!startFromPlus, oprnd)) + , startFromPlus ? new OpValues(initPlus + oprnd, initMinus) : + new OpValues(initPlus, initMinus - oprnd)); + break; + case accumulateAndGet: + assertEquals(ar.accumulateAndGet( + new OpValues(oprnd, oprnd), + opBinaryOperator(startFromPlus)) + , startFromPlus ? new OpValues(initPlus + oprnd, initMinus) : + new OpValues(initPlus, initMinus - oprnd)); + assertEquals(ar.accumulateAndGet( + new OpValues(oprnd, oprnd), + opBinaryOperator(!startFromPlus)) + , new OpValues(initPlus + oprnd, initMinus - oprnd)); + break; + case getAndAccumulate: + assertEquals(ar.getAndAccumulate( + new OpValues(oprnd, oprnd), + opBinaryOperator(startFromPlus)) + , new OpValues(initPlus, initMinus)); + assertEquals(ar.getAndAccumulate( + new OpValues(oprnd, oprnd), + opBinaryOperator(!startFromPlus)) + , startFromPlus ? new OpValues(initPlus + oprnd, initMinus) : + new OpValues(initPlus, initMinus - oprnd)); + break; + } + class UpdateThread extends Thread{ + CountDownLatch latch; + private int plusTimes = 0; + private int minusTimes = 0; + + UpdateThread(CountDownLatch latch){ + this.latch = latch; + } + @Override + public void run() { + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + ar.updateAndGet(opUnaryOperator(plus, oprnd)); + break; + case getAndUpdate: + ar.getAndUpdate(opUnaryOperator(plus, oprnd)); + break; + case accumulateAndGet: + ar.accumulateAndGet(new OpValues(oprnd, oprnd), + opBinaryOperator(plus)); + break; + case getAndAccumulate: + ar.getAndAccumulate(new OpValues(oprnd, oprnd), + opBinaryOperator(plus)); + break; + } + if(plus) + plusTimes++; + else + minusTimes++; + } + latch.countDown(); + } + int plusTimes(){ return plusTimes; } + int minusTimes(){ return minusTimes; } + }; + UpdateThread[] threads = new UpdateThread[THREAD_NUM -1]; + CountDownLatch latch = new CountDownLatch(THREAD_NUM -1); + for(int i = 0; i < THREAD_NUM -1; i++) { + threads[i] = new UpdateThread(latch); + threads[i].start(); + } + int plusTimes = 0; + int minusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean isPlus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + ar.updateAndGet(opUnaryOperator(isPlus, oprnd)); + break; + case getAndUpdate: + ar.getAndUpdate(opUnaryOperator(isPlus, oprnd)); + break; + case accumulateAndGet: + ar.accumulateAndGet(new OpValues(oprnd, oprnd), + opBinaryOperator(isPlus)); + break; + case getAndAccumulate: + ar.getAndAccumulate(new OpValues(oprnd, oprnd), + opBinaryOperator(isPlus)); + break; + } + if(isPlus) + plusTimes++; + else + minusTimes++; + } + latch.await(); + for(int i = 0; i < THREAD_NUM -1; i++) { + plusTimes += threads[i].plusTimes(); + minusTimes += threads[i].minusTimes(); + } + assertEquals(ar.get().getPlusAccumulated(), initPlus + plusTimes * oprnd + oprnd); + assertEquals(ar.get().getMinusAccumulated(), initMinus - minusTimes * oprnd - oprnd); + } + + static final class OpValues{ + final int plusAccumulated; + + final int minusAccumulated; + + OpValues(int plusAccumulated, int minusAccumulated){ + this.plusAccumulated = plusAccumulated; + this.minusAccumulated = minusAccumulated; + } + + OpValues operate(boolean isPlus, int value) { + if(isPlus) + return new OpValues(plusAccumulated + value, minusAccumulated); + else + return new OpValues(plusAccumulated, minusAccumulated - value); + } + + int getPlusAccumulated(){ return plusAccumulated; } + int getMinusAccumulated(){ return minusAccumulated; } + + @Override + public boolean equals(Object o){ + OpValues opv = (OpValues)o; + return (opv.plusAccumulated == plusAccumulated) + && (opv.minusAccumulated == minusAccumulated); + } + } + + public static UnaryOperator opUnaryOperator(boolean isPlus, int value) { + return t -> t.operate(isPlus, value); + } + + public static BinaryOperator opBinaryOperator(boolean isPlus) { + return (t1, t2) -> t1.operate(isPlus, isPlus ? t2.getPlusAccumulated() : t2.getMinusAccumulated()); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/AtomicReferenceFieldUpdater/LambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/AtomicReferenceFieldUpdater/LambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,215 @@ +/* + * 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 + * @summary test for AtomicReferenceFieldUpdater.updateAndGet()/getAndUpdate() + * and AtomicReferenceFieldUpdater.accumulateAndGet()/getAndAccumulate(); + * @(#) LambdaTest.java + * @library ../../ + * @author Tristan Yan + * @run testng LambdaTest + * @bug 8001666 + */ + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +import java.util.function.BinaryOperator; +import java.util.function.UnaryOperator; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class LambdaTest { + private static enum Type{updateAndGet, getAndUpdate, accumulateAndGet, getAndAccumulate}; + + private static Random rand = new Random(System.currentTimeMillis()); + + private final static int OP_TIMES = 1 << 10; + + private final static int THREAD_NUM = 1 << 4; + + @DataProvider + public Object[][] booleanProvider(){ + Object[][] providersParam = new Object[Type.values().length][]; + Object[] a = Type.values(); + for(int i = 0; i < a.length; i++) + providersParam[i] = new Object[]{a[i]}; + return providersParam; + } + + @Test(dataProvider = "booleanProvider") + @SuppressWarnings({"rawtypes", "unchecked"}) + public void test(final Type type) throws InterruptedException{ + int initValue = rand.nextInt(); + final Updater u = new Updater(); + u.accumulation = new OpValues(initValue); + final AtomicReferenceFieldUpdater accARFU + = AtomicReferenceFieldUpdater.newUpdater((Class)(Class)u.getClass(), (Class)(Class)u.accumulation.getClass(), "accumulation"); + + final int oprnd = rand.nextInt(); + boolean startFromPlus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + assertEquals(accARFU.updateAndGet(u,opUnaryOperator(startFromPlus, oprnd)) + , new OpValues(startFromPlus ? initValue + oprnd : initValue - oprnd)); + assertEquals(accARFU.updateAndGet(u,opUnaryOperator(!startFromPlus, oprnd)) + , new OpValues(initValue)); + break; + case getAndUpdate: + assertEquals(accARFU.getAndUpdate(u,opUnaryOperator(startFromPlus, oprnd)) + , new OpValues(initValue)); + assertEquals(accARFU.getAndUpdate(u,opUnaryOperator(!startFromPlus, oprnd)) + , new OpValues(startFromPlus ? initValue + oprnd : initValue - oprnd)); + break; + case accumulateAndGet: + assertEquals(accARFU.accumulateAndGet(u, new OpValues(oprnd), + opBinaryOperator(startFromPlus)) + , new OpValues(startFromPlus ? initValue + oprnd : initValue - oprnd)); + assertEquals(accARFU.accumulateAndGet(u, new OpValues(oprnd), + opBinaryOperator(!startFromPlus)) + , new OpValues(initValue)); + break; + case getAndAccumulate: + assertEquals(accARFU.getAndAccumulate(u, new OpValues(oprnd), + opBinaryOperator(startFromPlus)) + , new OpValues(initValue)); + assertEquals(accARFU.getAndAccumulate(u, new OpValues(oprnd), + opBinaryOperator(!startFromPlus)) + , new OpValues(startFromPlus ? initValue + oprnd : initValue - oprnd)); + break; + } + class UpdateThread extends Thread{ + CountDownLatch latch; + private int plusTimes = 0; + private int minusTimes = 0; + + UpdateThread(CountDownLatch latch){ + this.latch = latch; + } + @Override + public void run() { + for(int index = 0; index < OP_TIMES; index++) { + boolean plus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + accARFU.updateAndGet(u,opUnaryOperator(plus, oprnd)); + break; + case getAndUpdate: + accARFU.getAndUpdate(u,opUnaryOperator(plus, oprnd)); + break; + case accumulateAndGet: + accARFU.accumulateAndGet(u, new OpValues(oprnd), + opBinaryOperator(plus)); + break; + case getAndAccumulate: + accARFU.getAndAccumulate(u, new OpValues(oprnd), + opBinaryOperator(plus)); + break; + } + if(plus) + plusTimes++; + else + minusTimes++; + } + latch.countDown(); + } + int plusTimes(){ return plusTimes; } + int minusTimes(){ return minusTimes; } + }; + UpdateThread[] threads = new UpdateThread[THREAD_NUM -1]; + CountDownLatch latch = new CountDownLatch(THREAD_NUM -1); + for(int i = 0; i < THREAD_NUM -1; i++) { + threads[i] = new UpdateThread(latch); + threads[i].start(); + } + int plusTimes = 0; + int minusTimes = 0; + for(int index = 0; index < OP_TIMES; index++) { + boolean isPlus = rand.nextBoolean(); + switch(type) { + case updateAndGet: + accARFU.updateAndGet(u,opUnaryOperator(isPlus, oprnd)); + break; + case getAndUpdate: + accARFU.getAndUpdate(u,opUnaryOperator(isPlus, oprnd)); + break; + case accumulateAndGet: + accARFU.accumulateAndGet(u, new OpValues(oprnd), + opBinaryOperator(isPlus)); + break; + case getAndAccumulate: + accARFU.getAndAccumulate(u, new OpValues(oprnd), + opBinaryOperator(isPlus)); + break; + } + if(isPlus) + plusTimes++; + else + minusTimes++; + } + latch.await(); + for(int i = 0; i < THREAD_NUM -1; i++) { + plusTimes += threads[i].plusTimes(); + minusTimes += threads[i].minusTimes(); + } + assertEquals(accARFU.get(u).getAccumulated(), initValue + plusTimes * oprnd - minusTimes * oprnd); + } + + static final class OpValues{ + int accumulated; + + OpValues(int accumulated){ + this.accumulated = accumulated; + } + + OpValues operate(boolean isPlus, int value) { + if(isPlus) + return new OpValues(accumulated + value); + else + return new OpValues(accumulated - value); + } + + int getAccumulated(){ return accumulated; } + + @Override + public boolean equals(Object o){ + OpValues opv = (OpValues)o; + return (opv.accumulated == accumulated); + } + } + + + static class Updater{ + public volatile OpValues accumulation; + } + + public static UnaryOperator opUnaryOperator(boolean isPlus, int value) { + return t -> t.operate(isPlus, value); + } + + public static BinaryOperator opBinaryOperator(boolean isPlus) { + return (t1, t2) -> t1.operate(isPlus, t2.getAccumulated()); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/CompletableFuture/Basic.java --- a/test/java/util/concurrent/CompletableFuture/Basic.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/java/util/concurrent/CompletableFuture/Basic.java Mon Nov 11 23:17:30 2013 -0800 @@ -66,6 +66,7 @@ try { equalAnyOf(cf.get(), values); } catch (Throwable x) { unexpected(x); } try { equalAnyOf(cf.get(0L, SECONDS), values); } catch (Throwable x) { unexpected(x); } check(cf.isDone(), "Expected isDone to be true, got:" + cf); + check(!cf.isCompletedExceptionally(), "Expected isCompletedExceptionally to return false"); check(!cf.isCancelled(), "Expected isCancelled to be false"); check(!cf.cancel(true), "Expected cancel to return false"); check(cf.toString().contains("[Completed normally]")); @@ -97,6 +98,7 @@ catch (CancellationException x) { if (cancelled) pass(); else fail(); } catch (ExecutionException x) { if (cancelled) check(x.getCause() instanceof CancellationException); else pass(); } check(cf.isDone(), "Expected isDone to be true, got:" + cf); + check(cf.isCompletedExceptionally(), "Expected isCompletedExceptionally"); check(cf.isCancelled() == cancelled, "Expected isCancelled: " + cancelled + ", got:" + cf.isCancelled()); check(cf.cancel(true) == cancelled, "Expected cancel: " + cancelled + ", got:" + cf.cancel(true)); check(cf.toString().contains("[Completed exceptionally]")); // ## TODO: 'E'xceptionally @@ -805,6 +807,49 @@ cf2 = cf1.handle((x,t) -> { check(t.getCause() == ex); return 2;}); checkCompletedExceptionally(cf1); checkCompletedNormally(cf2, 2); + + cf1 = supplyAsync(() -> 1); + cf2 = cf1.handleAsync((x,t) -> x+1); + checkCompletedNormally(cf1, 1); + checkCompletedNormally(cf2, 2); + + cf1 = supplyAsync(() -> { throw ex; }); + cf2 = cf1.handleAsync((x,t) -> { check(t.getCause() == ex); return 2;}); + checkCompletedExceptionally(cf1); + checkCompletedNormally(cf2, 2); + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // whenComplete tests + //---------------------------------------------------------------- + try { + AtomicInteger count = new AtomicInteger(); + CompletableFuture cf2; + CompletableFuture cf1 = supplyAsync(() -> 1); + cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement()); + checkCompletedNormally(cf1, 1); + checkCompletedNormally(cf2, 1); + check(count.get() == 1, "action count should be incremented"); + + final RuntimeException ex = new RuntimeException(); + cf1 = supplyAsync(() -> { throw ex; }); + cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement()); + checkCompletedExceptionally(cf1); + checkCompletedExceptionally(cf2); + check(count.get() == 2, "action count should be incremented"); + + cf1 = supplyAsync(() -> 1); + cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement()); + checkCompletedNormally(cf1, 1); + checkCompletedNormally(cf2, 1); + check(count.get() == 3, "action count should be incremented"); + + cf1 = supplyAsync(() -> { throw ex; }); + cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement()); + checkCompletedExceptionally(cf1); + checkCompletedExceptionally(cf2); + check(count.get() == 4, "action count should be incremented"); + } catch (Throwable t) { unexpected(t); } } diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/ConcurrentHashMap/ToArray.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/concurrent/forkjoin/ParallelSorting.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/forkjoin/ParallelSorting.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,2069 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* Adapted from test/java/util/Arrays/Sorting.java + * + * Where that test checks Arrays.sort against manual quicksort routines, + * this test checks parallelSort against either Arrays.sort or manual + * quicksort routines. + */ + +/* +/* + * @test + * @summary Exercise ForkJoinUtils.parallelSort (adapted from test Sorting) + * @build ParallelSorting + * @run main ParallelSorting -shortrun + * + * @author Vladimir Yaroslavskiy + * @author Jon Bentley + * @author Josh Bloch + * + */ + +import java.util.Arrays; +import java.util.Random; +import java.io.PrintStream; +import java.util.Comparator; + +public class ParallelSorting { + private static final PrintStream out = System.out; + private static final PrintStream err = System.err; + + // Array lengths used in a long run (default) + private static final int[] LONG_RUN_LENGTHS = { + 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000 }; + + // Array lengths used in a short run + private static final int[] SHORT_RUN_LENGTHS = { + 1, 2, 3, 21, 55, 1000, 10000 }; + + // Random initial values used in a long run (default) + private static final long[] LONG_RUN_RANDOMS = { 666, 0xC0FFEE, 999 }; + + // Random initial values used in a short run + private static final long[] SHORT_RUN_RANDOMS = { 666 }; + + public static void main(String[] args) { + boolean shortRun = args.length > 0 && args[0].equals("-shortrun"); + long start = System.currentTimeMillis(); + + if (shortRun) { + testAndCheck(SHORT_RUN_LENGTHS, SHORT_RUN_RANDOMS); + } else { + testAndCheck(LONG_RUN_LENGTHS, LONG_RUN_RANDOMS); + } + long end = System.currentTimeMillis(); + + out.format("PASSED in %d sec.\n", Math.round((end - start) / 1E3)); + } + + private static void testAndCheck(int[] lengths, long[] randoms) { + testEmptyAndNullIntArray(); + testEmptyAndNullLongArray(); + testEmptyAndNullShortArray(); + testEmptyAndNullCharArray(); + testEmptyAndNullByteArray(); + testEmptyAndNullFloatArray(); + testEmptyAndNullDoubleArray(); + + for (int length : lengths) { + testMergeSort(length); + testAndCheckRange(length); + testAndCheckSubArray(length); + } + for (long seed : randoms) { + for (int length : lengths) { + testAndCheckWithInsertionSort(length, new MyRandom(seed)); + testAndCheckWithCheckSum(length, new MyRandom(seed)); + testAndCheckWithScrambling(length, new MyRandom(seed)); + testAndCheckFloat(length, new MyRandom(seed)); + testAndCheckDouble(length, new MyRandom(seed)); + testStable(length, new MyRandom(seed)); + } + } + } + + private static void testEmptyAndNullIntArray() { + ourDescription = "Check empty and null array"; + Arrays.parallelSort(new int[]{}); + Arrays.parallelSort(new int[]{}, 0, 0); + + try { + Arrays.parallelSort((int[]) null); + } catch (NullPointerException expected) { + try { + Arrays.parallelSort((int[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("ForkJoinUtils.parallelSort(int[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("ForkJoinUtils.parallelSort(int[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullLongArray() { + ourDescription = "Check empty and null array"; + Arrays.parallelSort(new long[]{}); + Arrays.parallelSort(new long[]{}, 0, 0); + + try { + Arrays.parallelSort((long[]) null); + } catch (NullPointerException expected) { + try { + Arrays.parallelSort((long[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("ForkJoinUtils.parallelSort(long[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("ForkJoinUtils.parallelSort(long[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullShortArray() { + ourDescription = "Check empty and null array"; + Arrays.parallelSort(new short[]{}); + Arrays.parallelSort(new short[]{}, 0, 0); + + try { + Arrays.parallelSort((short[]) null); + } catch (NullPointerException expected) { + try { + Arrays.parallelSort((short[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("ForkJoinUtils.parallelSort(short[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("ForkJoinUtils.parallelSort(short[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullCharArray() { + ourDescription = "Check empty and null array"; + Arrays.parallelSort(new char[]{}); + Arrays.parallelSort(new char[]{}, 0, 0); + + try { + Arrays.parallelSort((char[]) null); + } catch (NullPointerException expected) { + try { + Arrays.parallelSort((char[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("ForkJoinUtils.parallelSort(char[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("ForkJoinUtils.parallelSort(char[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullByteArray() { + ourDescription = "Check empty and null array"; + Arrays.parallelSort(new byte[]{}); + Arrays.parallelSort(new byte[]{}, 0, 0); + + try { + Arrays.parallelSort((byte[]) null); + } catch (NullPointerException expected) { + try { + Arrays.parallelSort((byte[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("ForkJoinUtils.parallelSort(byte[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("ForkJoinUtils.parallelSort(byte[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullFloatArray() { + ourDescription = "Check empty and null array"; + Arrays.parallelSort(new float[]{}); + Arrays.parallelSort(new float[]{}, 0, 0); + + try { + Arrays.parallelSort((float[]) null); + } catch (NullPointerException expected) { + try { + Arrays.parallelSort((float[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("ForkJoinUtils.parallelSort(float[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("ForkJoinUtils.parallelSort(float[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullDoubleArray() { + ourDescription = "Check empty and null array"; + Arrays.parallelSort(new double[]{}); + Arrays.parallelSort(new double[]{}, 0, 0); + + try { + Arrays.parallelSort((double[]) null); + } catch (NullPointerException expected) { + try { + Arrays.parallelSort((double[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("ForkJoinUtils.parallelSort(double[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("ForkJoinUtils.parallelSort(double[]) shouldn't catch null array"); + } + + private static void testAndCheckSubArray(int length) { + ourDescription = "Check sorting of subarray"; + int[] golden = new int[length]; + boolean newLine = false; + + for (int m = 1; m < length / 2; m *= 2) { + newLine = true; + int fromIndex = m; + int toIndex = length - m; + + prepareSubArray(golden, fromIndex, toIndex, m); + int[] test = golden.clone(); + + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'subarray': " + converter + + " length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + Object convertedTest = converter.convert(test); + sortSubArray(convertedTest, fromIndex, toIndex); + checkSubArray(convertedTest, fromIndex, toIndex, m); + } + } + if (newLine) { + out.println(); + } + } + + private static void testAndCheckRange(int length) { + ourDescription = "Check range check"; + int[] golden = new int[length]; + + for (int m = 1; m < 2 * length; m *= 2) { + for (int i = 1; i <= length; i++) { + golden[i - 1] = i % m + m % i; + } + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'range': " + converter + + ", length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + checkRange(convertedGolden, m); + } + } + out.println(); + } + + private static void testStable(int length, MyRandom random) { + ourDescription = "Check if sorting is stable"; + Pair[] a = build(length, random); + + out.println("Test 'stable': " + "random = " + random.getSeed() + + ", length = " + length); + Arrays.parallelSort(a); + checkSorted(a); + checkStable(a); + out.println(); + + a = build(length, random); + + out.println("Test 'stable' comparator: " + "random = " + random.getSeed() + + ", length = " + length); + Arrays.parallelSort(a, pairCmp); + checkSorted(a); + checkStable(a); + out.println(); + + } + + private static void checkSorted(Pair[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i].getKey() > a[i + 1].getKey()) { + failedSort(i, "" + a[i].getKey(), "" + a[i + 1].getKey()); + } + } + } + + private static void checkStable(Pair[] a) { + for (int i = 0; i < a.length / 4; ) { + int key1 = a[i].getKey(); + int value1 = a[i++].getValue(); + int key2 = a[i].getKey(); + int value2 = a[i++].getValue(); + int key3 = a[i].getKey(); + int value3 = a[i++].getValue(); + int key4 = a[i].getKey(); + int value4 = a[i++].getValue(); + + if (!(key1 == key2 && key2 == key3 && key3 == key4)) { + failed("On position " + i + " keys are different " + + key1 + ", " + key2 + ", " + key3 + ", " + key4); + } + if (!(value1 < value2 && value2 < value3 && value3 < value4)) { + failed("Sorting is not stable at position " + i + + ". Second values have been changed: " + value1 + ", " + + value2 + ", " + value3 + ", " + value4); + } + } + } + + private static Pair[] build(int length, Random random) { + Pair[] a = new Pair[length * 4]; + + for (int i = 0; i < a.length; ) { + int key = random.nextInt(); + a[i++] = new Pair(key, 1); + a[i++] = new Pair(key, 2); + a[i++] = new Pair(key, 3); + a[i++] = new Pair(key, 4); + } + return a; + } + + private static Comparator pairCmp = new Comparator() { + public int compare(Pair p1, Pair p2) { + return p1.compareTo(p2); + } + }; + + private static final class Pair implements Comparable { + Pair(int key, int value) { + myKey = key; + myValue = value; + } + + int getKey() { + return myKey; + } + + int getValue() { + return myValue; + } + + public int compareTo(Pair pair) { + if (myKey < pair.myKey) { + return -1; + } + if (myKey > pair.myKey) { + return 1; + } + return 0; + } + + @Override + public String toString() { + return "(" + myKey + ", " + myValue + ")"; + } + + private int myKey; + private int myValue; + } + + + private static void testAndCheckWithInsertionSort(int length, MyRandom random) { + if (length > 1000) { + return; + } + ourDescription = "Check sorting with insertion sort"; + int[] golden = new int[length]; + + for (int m = 1; m < 2 * length; m *= 2) { + for (UnsortedBuilder builder : UnsortedBuilder.values()) { + builder.build(golden, m, random); + int[] test = golden.clone(); + + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'insertion sort': " + converter + + " " + builder + "random = " + random.getSeed() + + ", length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + Object convertedTest1 = converter.convert(test); + Object convertedTest2 = converter.convert(test); + sort(convertedTest1); + sortByInsertionSort(convertedTest2); + compare(convertedTest1, convertedTest2); + } + } + } + out.println(); + } + + private static void testMergeSort(int length) { + if (length < 1000) { + return; + } + ourDescription = "Check merge sorting"; + int[] golden = new int[length]; + int period = 67; // java.util.DualPivotQuicksort.MAX_RUN_COUNT + + for (int m = period - 2; m <= period + 2; m++) { + for (MergeBuilder builder : MergeBuilder.values()) { + builder.build(golden, m); + int[] test = golden.clone(); + + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'merge sort': " + converter + " " + + builder + "length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + sort(convertedGolden); + checkSorted(convertedGolden); + } + } + } + out.println(); + } + + private static void testAndCheckWithCheckSum(int length, MyRandom random) { + ourDescription = "Check sorting with check sum"; + int[] golden = new int[length]; + + for (int m = 1; m < 2 * length; m *= 2) { + for (UnsortedBuilder builder : UnsortedBuilder.values()) { + builder.build(golden, m, random); + int[] test = golden.clone(); + + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'check sum': " + converter + + " " + builder + "random = " + random.getSeed() + + ", length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + Object convertedTest = converter.convert(test); + sort(convertedTest); + checkWithCheckSum(convertedTest, convertedGolden); + } + } + } + out.println(); + } + + private static void testAndCheckWithScrambling(int length, MyRandom random) { + ourDescription = "Check sorting with scrambling"; + int[] golden = new int[length]; + + for (int m = 1; m <= 7; m++) { + if (m > length) { + break; + } + for (SortedBuilder builder : SortedBuilder.values()) { + builder.build(golden, m); + int[] test = golden.clone(); + scramble(test, random); + + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'scrambling': " + converter + + " " + builder + "random = " + random.getSeed() + + ", length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + Object convertedTest = converter.convert(test); + sort(convertedTest); + compare(convertedTest, convertedGolden); + } + } + } + out.println(); + } + + private static void testAndCheckFloat(int length, MyRandom random) { + ourDescription = "Check float sorting"; + float[] golden = new float[length]; + final int MAX = 10; + boolean newLine = false; + + for (int a = 0; a <= MAX; a++) { + for (int g = 0; g <= MAX; g++) { + for (int z = 0; z <= MAX; z++) { + for (int n = 0; n <= MAX; n++) { + for (int p = 0; p <= MAX; p++) { + if (a + g + z + n + p > length) { + continue; + } + if (a + g + z + n + p < length) { + continue; + } + for (FloatBuilder builder : FloatBuilder.values()) { + out.println("Test 'float': random = " + random.getSeed() + + ", length = " + length + ", a = " + a + ", g = " + + g + ", z = " + z + ", n = " + n + ", p = " + p); + builder.build(golden, a, g, z, n, p, random); + float[] test = golden.clone(); + scramble(test, random); + sort(test); + compare(test, golden, a, n, g); + } + newLine = true; + } + } + } + } + } + if (newLine) { + out.println(); + } + } + + private static void testAndCheckDouble(int length, MyRandom random) { + ourDescription = "Check double sorting"; + double[] golden = new double[length]; + final int MAX = 10; + boolean newLine = false; + + for (int a = 0; a <= MAX; a++) { + for (int g = 0; g <= MAX; g++) { + for (int z = 0; z <= MAX; z++) { + for (int n = 0; n <= MAX; n++) { + for (int p = 0; p <= MAX; p++) { + if (a + g + z + n + p > length) { + continue; + } + if (a + g + z + n + p < length) { + continue; + } + for (DoubleBuilder builder : DoubleBuilder.values()) { + out.println("Test 'double': random = " + random.getSeed() + + ", length = " + length + ", a = " + a + ", g = " + + g + ", z = " + z + ", n = " + n + ", p = " + p); + builder.build(golden, a, g, z, n, p, random); + double[] test = golden.clone(); + scramble(test, random); + sort(test); + compare(test, golden, a, n, g); + } + newLine = true; + } + } + } + } + } + if (newLine) { + out.println(); + } + } + + private static void prepareSubArray(int[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + a[i] = 0xDEDA; + } + int middle = (fromIndex + toIndex) >>> 1; + int k = 0; + + for (int i = fromIndex; i < middle; i++) { + a[i] = k++; + } + for (int i = middle; i < toIndex; i++) { + a[i] = k--; + } + for (int i = toIndex; i < a.length; i++) { + a[i] = 0xBABA; + } + } + + private static void scramble(int[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private static void scramble(float[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private static void scramble(double[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private static void swap(int[] a, int i, int j) { + int t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private static void swap(float[] a, int i, int j) { + float t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private static void swap(double[] a, int i, int j) { + double t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private static enum TypeConverter { + INT { + Object convert(int[] a) { + return a.clone(); + } + }, + LONG { + Object convert(int[] a) { + long[] b = new long[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = (long) a[i]; + } + return b; + } + }, + BYTE { + Object convert(int[] a) { + byte[] b = new byte[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = (byte) a[i]; + } + return b; + } + }, + SHORT { + Object convert(int[] a) { + short[] b = new short[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = (short) a[i]; + } + return b; + } + }, + CHAR { + Object convert(int[] a) { + char[] b = new char[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = (char) a[i]; + } + return b; + } + }, + FLOAT { + Object convert(int[] a) { + float[] b = new float[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = (float) a[i]; + } + return b; + } + }, + DOUBLE { + Object convert(int[] a) { + double[] b = new double[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = (double) a[i]; + } + return b; + } + }, + INTEGER { + Object convert(int[] a) { + Integer[] b = new Integer[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = new Integer(a[i]); + } + return b; + } + }; + + abstract Object convert(int[] a); + + @Override public String toString() { + String name = name(); + + for (int i = name.length(); i < 9; i++) { + name += " "; + } + return name; + } + } + + private static enum FloatBuilder { + SIMPLE { + void build(float[] x, int a, int g, int z, int n, int p, Random random) { + int fromIndex = 0; + float negativeValue = -random.nextFloat(); + float positiveValue = random.nextFloat(); + + writeValue(x, negativeValue, fromIndex, n); + fromIndex += n; + + writeValue(x, -0.0f, fromIndex, g); + fromIndex += g; + + writeValue(x, 0.0f, fromIndex, z); + fromIndex += z; + + writeValue(x, positiveValue, fromIndex, p); + fromIndex += p; + + writeValue(x, Float.NaN, fromIndex, a); + } + }; + + abstract void build(float[] x, int a, int g, int z, int n, int p, Random random); + } + + private static enum DoubleBuilder { + SIMPLE { + void build(double[] x, int a, int g, int z, int n, int p, Random random) { + int fromIndex = 0; + double negativeValue = -random.nextFloat(); + double positiveValue = random.nextFloat(); + + writeValue(x, negativeValue, fromIndex, n); + fromIndex += n; + + writeValue(x, -0.0d, fromIndex, g); + fromIndex += g; + + writeValue(x, 0.0d, fromIndex, z); + fromIndex += z; + + writeValue(x, positiveValue, fromIndex, p); + fromIndex += p; + + writeValue(x, Double.NaN, fromIndex, a); + } + }; + + abstract void build(double[] x, int a, int g, int z, int n, int p, Random random); + } + + private static void writeValue(float[] a, float value, int fromIndex, int count) { + for (int i = fromIndex; i < fromIndex + count; i++) { + a[i] = value; + } + } + + private static void compare(float[] a, float[] b, int numNaN, int numNeg, int numNegZero) { + for (int i = a.length - numNaN; i < a.length; i++) { + if (a[i] == a[i]) { + failed("On position " + i + " must be NaN instead of " + a[i]); + } + } + final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f); + + for (int i = numNeg; i < numNeg + numNegZero; i++) { + if (NEGATIVE_ZERO != Float.floatToIntBits(a[i])) { + failed("On position " + i + " must be -0.0 instead of " + a[i]); + } + } + for (int i = 0; i < a.length - numNaN; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void writeValue(double[] a, double value, int fromIndex, int count) { + for (int i = fromIndex; i < fromIndex + count; i++) { + a[i] = value; + } + } + + private static void compare(double[] a, double[] b, int numNaN, int numNeg, int numNegZero) { + for (int i = a.length - numNaN; i < a.length; i++) { + if (a[i] == a[i]) { + failed("On position " + i + " must be NaN instead of " + a[i]); + } + } + final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d); + + for (int i = numNeg; i < numNeg + numNegZero; i++) { + if (NEGATIVE_ZERO != Double.doubleToLongBits(a[i])) { + failed("On position " + i + " must be -0.0 instead of " + a[i]); + } + } + for (int i = 0; i < a.length - numNaN; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static enum SortedBuilder { + REPEATED { + void build(int[] a, int m) { + int period = a.length / m; + int i = 0; + int k = 0; + + while (true) { + for (int t = 1; t <= period; t++) { + if (i >= a.length) { + return; + } + a[i++] = k; + } + if (i >= a.length) { + return; + } + k++; + } + } + }, + ORGAN_PIPES { + void build(int[] a, int m) { + int i = 0; + int k = m; + + while (true) { + for (int t = 1; t <= m; t++) { + if (i >= a.length) { + return; + } + a[i++] = k; + } + } + } + }; + + abstract void build(int[] a, int m); + + @Override public String toString() { + String name = name(); + + for (int i = name.length(); i < 12; i++) { + name += " "; + } + return name; + } + } + + private static enum MergeBuilder { + ASCENDING { + void build(int[] a, int m) { + int period = a.length / m; + int v = 1, i = 0; + + for (int k = 0; k < m; k++) { + v = 1; + for (int p = 0; p < period; p++) { + a[i++] = v++; + } + } + for (int j = i; j < a.length - 1; j++) { + a[j] = v++; + } + a[a.length - 1] = 0; + } + }, + DESCENDING { + void build(int[] a, int m) { + int period = a.length / m; + int v = -1, i = 0; + + for (int k = 0; k < m; k++) { + v = -1; + for (int p = 0; p < period; p++) { + a[i++] = v--; + } + } + for (int j = i; j < a.length - 1; j++) { + a[j] = v--; + } + a[a.length - 1] = 0; + } + }; + + abstract void build(int[] a, int m); + + @Override public String toString() { + String name = name(); + + for (int i = name.length(); i < 12; i++) { + name += " "; + } + return name; + } + } + + private static enum UnsortedBuilder { + RANDOM { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = random.nextInt(); + } + } + }, + ASCENDING { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = m + i; + } + } + }, + DESCENDING { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = a.length - m - i; + } + } + }, + ALL_EQUAL { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = m; + } + } + }, + SAW { + void build(int[] a, int m, Random random) { + int incCount = 1; + int decCount = a.length; + int i = 0; + int period = m--; + + while (true) { + for (int k = 1; k <= period; k++) { + if (i >= a.length) { + return; + } + a[i++] = incCount++; + } + period += m; + + for (int k = 1; k <= period; k++) { + if (i >= a.length) { + return; + } + a[i++] = decCount--; + } + period += m; + } + } + }, + REPEATED { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = i % m; + } + } + }, + DUPLICATED { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = random.nextInt(m); + } + } + }, + ORGAN_PIPES { + void build(int[] a, int m, Random random) { + int middle = a.length / (m + 1); + + for (int i = 0; i < middle; i++) { + a[i] = i; + } + for (int i = middle; i < a.length; i++) { + a[i] = a.length - i - 1; + } + } + }, + STAGGER { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = (i * m + i) % a.length; + } + } + }, + PLATEAU { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = Math.min(i, m); + } + } + }, + SHUFFLE { + void build(int[] a, int m, Random random) { + int x = 0, y = 0; + for (int i = 0; i < a.length; i++) { + a[i] = random.nextBoolean() ? (x += 2) : (y += 2); + } + } + }; + + abstract void build(int[] a, int m, Random random); + + @Override public String toString() { + String name = name(); + + for (int i = name.length(); i < 12; i++) { + name += " "; + } + return name; + } + } + + private static void checkWithCheckSum(Object test, Object golden) { + checkSorted(test); + checkCheckSum(test, golden); + } + + private static void failed(String message) { + err.format("\n*** TEST FAILED - %s.\n\n%s.\n\n", ourDescription, message); + throw new RuntimeException("Test failed - see log file for details"); + } + + private static void failedSort(int index, String value1, String value2) { + failed("Array is not sorted at " + index + "-th position: " + + value1 + " and " + value2); + } + + private static void failedCompare(int index, String value1, String value2) { + failed("On position " + index + " must be " + value2 + " instead of " + value1); + } + + private static void compare(Object test, Object golden) { + if (test instanceof int[]) { + compare((int[]) test, (int[]) golden); + } else if (test instanceof long[]) { + compare((long[]) test, (long[]) golden); + } else if (test instanceof short[]) { + compare((short[]) test, (short[]) golden); + } else if (test instanceof byte[]) { + compare((byte[]) test, (byte[]) golden); + } else if (test instanceof char[]) { + compare((char[]) test, (char[]) golden); + } else if (test instanceof float[]) { + compare((float[]) test, (float[]) golden); + } else if (test instanceof double[]) { + compare((double[]) test, (double[]) golden); + } else if (test instanceof Integer[]) { + compare((Integer[]) test, (Integer[]) golden); + } else { + failed("Unknow type of array: " + test + " of class " + + test.getClass().getName()); + } + } + + private static void compare(int[] a, int[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void compare(long[] a, long[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void compare(short[] a, short[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void compare(byte[] a, byte[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void compare(char[] a, char[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void compare(float[] a, float[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void compare(double[] a, double[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void compare(Integer[] a, Integer[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i].compareTo(b[i]) != 0) { + failedCompare(i, "" + a[i], "" + b[i]); + } + } + } + + private static void checkSorted(Object object) { + if (object instanceof int[]) { + checkSorted((int[]) object); + } else if (object instanceof long[]) { + checkSorted((long[]) object); + } else if (object instanceof short[]) { + checkSorted((short[]) object); + } else if (object instanceof byte[]) { + checkSorted((byte[]) object); + } else if (object instanceof char[]) { + checkSorted((char[]) object); + } else if (object instanceof float[]) { + checkSorted((float[]) object); + } else if (object instanceof double[]) { + checkSorted((double[]) object); + } else if (object instanceof Integer[]) { + checkSorted((Integer[]) object); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + } + } + + private static void checkSorted(int[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkSorted(long[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkSorted(short[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkSorted(byte[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkSorted(char[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkSorted(float[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkSorted(double[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkSorted(Integer[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i].intValue() > a[i + 1].intValue()) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + } + + private static void checkCheckSum(Object test, Object golden) { + if (checkSumXor(test) != checkSumXor(golden)) { + failed("Original and sorted arrays are not identical [xor]"); + } + if (checkSumPlus(test) != checkSumPlus(golden)) { + failed("Original and sorted arrays are not identical [plus]"); + } + } + + private static int checkSumXor(Object object) { + if (object instanceof int[]) { + return checkSumXor((int[]) object); + } else if (object instanceof long[]) { + return checkSumXor((long[]) object); + } else if (object instanceof short[]) { + return checkSumXor((short[]) object); + } else if (object instanceof byte[]) { + return checkSumXor((byte[]) object); + } else if (object instanceof char[]) { + return checkSumXor((char[]) object); + } else if (object instanceof float[]) { + return checkSumXor((float[]) object); + } else if (object instanceof double[]) { + return checkSumXor((double[]) object); + } else if (object instanceof Integer[]) { + return checkSumXor((Integer[]) object); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + return -1; + } + } + + private static int checkSumXor(Integer[] a) { + int checkSum = 0; + + for (Integer e : a) { + checkSum ^= e.intValue(); + } + return checkSum; + } + + private static int checkSumXor(int[] a) { + int checkSum = 0; + + for (int e : a) { + checkSum ^= e; + } + return checkSum; + } + + private static int checkSumXor(long[] a) { + long checkSum = 0; + + for (long e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private static int checkSumXor(short[] a) { + short checkSum = 0; + + for (short e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private static int checkSumXor(byte[] a) { + byte checkSum = 0; + + for (byte e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private static int checkSumXor(char[] a) { + char checkSum = 0; + + for (char e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private static int checkSumXor(float[] a) { + int checkSum = 0; + + for (float e : a) { + checkSum ^= (int) e; + } + return checkSum; + } + + private static int checkSumXor(double[] a) { + int checkSum = 0; + + for (double e : a) { + checkSum ^= (int) e; + } + return checkSum; + } + + private static int checkSumPlus(Object object) { + if (object instanceof int[]) { + return checkSumPlus((int[]) object); + } else if (object instanceof long[]) { + return checkSumPlus((long[]) object); + } else if (object instanceof short[]) { + return checkSumPlus((short[]) object); + } else if (object instanceof byte[]) { + return checkSumPlus((byte[]) object); + } else if (object instanceof char[]) { + return checkSumPlus((char[]) object); + } else if (object instanceof float[]) { + return checkSumPlus((float[]) object); + } else if (object instanceof double[]) { + return checkSumPlus((double[]) object); + } else if (object instanceof Integer[]) { + return checkSumPlus((Integer[]) object); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + return -1; + } + } + + private static int checkSumPlus(int[] a) { + int checkSum = 0; + + for (int e : a) { + checkSum += e; + } + return checkSum; + } + + private static int checkSumPlus(long[] a) { + long checkSum = 0; + + for (long e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private static int checkSumPlus(short[] a) { + short checkSum = 0; + + for (short e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private static int checkSumPlus(byte[] a) { + byte checkSum = 0; + + for (byte e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private static int checkSumPlus(char[] a) { + char checkSum = 0; + + for (char e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private static int checkSumPlus(float[] a) { + int checkSum = 0; + + for (float e : a) { + checkSum += (int) e; + } + return checkSum; + } + + private static int checkSumPlus(double[] a) { + int checkSum = 0; + + for (double e : a) { + checkSum += (int) e; + } + return checkSum; + } + + private static int checkSumPlus(Integer[] a) { + int checkSum = 0; + + for (Integer e : a) { + checkSum += e.intValue(); + } + return checkSum; + } + + private static void sortByInsertionSort(Object object) { + if (object instanceof int[]) { + sortByInsertionSort((int[]) object); + } else if (object instanceof long[]) { + sortByInsertionSort((long[]) object); + } else if (object instanceof short[]) { + sortByInsertionSort((short[]) object); + } else if (object instanceof byte[]) { + sortByInsertionSort((byte[]) object); + } else if (object instanceof char[]) { + sortByInsertionSort((char[]) object); + } else if (object instanceof float[]) { + sortByInsertionSort((float[]) object); + } else if (object instanceof double[]) { + sortByInsertionSort((double[]) object); + } else if (object instanceof Integer[]) { + sortByInsertionSort((Integer[]) object); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + } + } + + private static void sortByInsertionSort(int[] a) { + for (int j, i = 1; i < a.length; i++) { + int ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sortByInsertionSort(long[] a) { + for (int j, i = 1; i < a.length; i++) { + long ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sortByInsertionSort(short[] a) { + for (int j, i = 1; i < a.length; i++) { + short ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sortByInsertionSort(byte[] a) { + for (int j, i = 1; i < a.length; i++) { + byte ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sortByInsertionSort(char[] a) { + for (int j, i = 1; i < a.length; i++) { + char ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sortByInsertionSort(float[] a) { + for (int j, i = 1; i < a.length; i++) { + float ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sortByInsertionSort(double[] a) { + for (int j, i = 1; i < a.length; i++) { + double ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sortByInsertionSort(Integer[] a) { + for (int j, i = 1; i < a.length; i++) { + Integer ai = a[i]; + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private static void sort(Object object) { + if (object instanceof int[]) { + Arrays.parallelSort((int[]) object); + } else if (object instanceof long[]) { + Arrays.parallelSort((long[]) object); + } else if (object instanceof short[]) { + Arrays.parallelSort((short[]) object); + } else if (object instanceof byte[]) { + Arrays.parallelSort((byte[]) object); + } else if (object instanceof char[]) { + Arrays.parallelSort((char[]) object); + } else if (object instanceof float[]) { + Arrays.parallelSort((float[]) object); + } else if (object instanceof double[]) { + Arrays.parallelSort((double[]) object); + } else if (object instanceof Integer[]) { + Arrays.parallelSort((Integer[]) object); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + } + } + + private static void sortSubArray(Object object, int fromIndex, int toIndex) { + if (object instanceof int[]) { + Arrays.parallelSort((int[]) object, fromIndex, toIndex); + } else if (object instanceof long[]) { + Arrays.parallelSort((long[]) object, fromIndex, toIndex); + } else if (object instanceof short[]) { + Arrays.parallelSort((short[]) object, fromIndex, toIndex); + } else if (object instanceof byte[]) { + Arrays.parallelSort((byte[]) object, fromIndex, toIndex); + } else if (object instanceof char[]) { + Arrays.parallelSort((char[]) object, fromIndex, toIndex); + } else if (object instanceof float[]) { + Arrays.parallelSort((float[]) object, fromIndex, toIndex); + } else if (object instanceof double[]) { + Arrays.parallelSort((double[]) object, fromIndex, toIndex); + } else if (object instanceof Integer[]) { + Arrays.parallelSort((Integer[]) object, fromIndex, toIndex); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + } + } + + private static void checkSubArray(Object object, int fromIndex, int toIndex, int m) { + if (object instanceof int[]) { + checkSubArray((int[]) object, fromIndex, toIndex, m); + } else if (object instanceof long[]) { + checkSubArray((long[]) object, fromIndex, toIndex, m); + } else if (object instanceof short[]) { + checkSubArray((short[]) object, fromIndex, toIndex, m); + } else if (object instanceof byte[]) { + checkSubArray((byte[]) object, fromIndex, toIndex, m); + } else if (object instanceof char[]) { + checkSubArray((char[]) object, fromIndex, toIndex, m); + } else if (object instanceof float[]) { + checkSubArray((float[]) object, fromIndex, toIndex, m); + } else if (object instanceof double[]) { + checkSubArray((double[]) object, fromIndex, toIndex, m); + } else if (object instanceof Integer[]) { + checkSubArray((Integer[]) object, fromIndex, toIndex, m); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + } + } + + private static void checkSubArray(Integer[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i].intValue() != 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i].intValue() > a[i + 1].intValue()) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i].intValue() != 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkSubArray(int[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkSubArray(byte[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (byte) 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (byte) 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkSubArray(long[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (long) 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (long) 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkSubArray(char[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (char) 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (char) 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkSubArray(short[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (short) 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (short) 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkSubArray(float[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (float) 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (float) 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkSubArray(double[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (double) 0xDEDA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + failedSort(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (double) 0xBABA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + } + + private static void checkRange(Object object, int m) { + if (object instanceof int[]) { + checkRange((int[]) object, m); + } else if (object instanceof long[]) { + checkRange((long[]) object, m); + } else if (object instanceof short[]) { + checkRange((short[]) object, m); + } else if (object instanceof byte[]) { + checkRange((byte[]) object, m); + } else if (object instanceof char[]) { + checkRange((char[]) object, m); + } else if (object instanceof float[]) { + checkRange((float[]) object, m); + } else if (object instanceof double[]) { + checkRange((double[]) object, m); + } else if (object instanceof Integer[]) { + checkRange((Integer[]) object, m); + } else { + failed("Unknow type of array: " + object + " of class " + + object.getClass().getName()); + } + } + + private static void checkRange(Integer[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(int[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(long[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(byte[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(short[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(char[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(float[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(double[] a, int m) { + try { + Arrays.parallelSort(a, m + 1, m); + + failed("ParallelSort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.parallelSort(a, -m, a.length); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.parallelSort(a, 0, a.length + m); + + failed("ParallelSort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void outArray(Object[] a) { + for (int i = 0; i < a.length; i++) { + out.print(a[i] + " "); + } + out.println(); + } + + private static void outArray(int[] a) { + for (int i = 0; i < a.length; i++) { + out.print(a[i] + " "); + } + out.println(); + } + + private static void outArray(float[] a) { + for (int i = 0; i < a.length; i++) { + out.print(a[i] + " "); + } + out.println(); + } + + private static void outArray(double[] a) { + for (int i = 0; i < a.length; i++) { + out.print(a[i] + " "); + } + out.println(); + } + + private static class MyRandom extends Random { + MyRandom(long seed) { + super(seed); + mySeed = seed; + } + + long getSeed() { + return mySeed; + } + + private long mySeed; + } + + private static String ourDescription; +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/function/BiFunction/BiFunctionTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/function/PredicateTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/function/PredicateTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,208 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8004561 + * @run testng PredicateTest + */ + +import org.testng.annotations.Test; + +import java.util.HashSet; +import java.util.function.Predicate; +import java.util.function.DoublePredicate; +import java.util.function.IntPredicate; +import java.util.function.LongPredicate; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; + +/** + * Unit tests for helper methods in Comparators + */ +@Test(groups = "unit") +public class PredicateTest { + + public void testIntPredicate() { + IntPredicate pOdd = (t) -> 0 != (t & 1); + IntPredicate pEven = (t) -> 0 == (t & 1); + + assertFalse(pOdd.test(0)); + assertFalse(pOdd.test(Integer.valueOf(0))); + assertFalse(pOdd.test(new Integer(0))); + assertFalse(pOdd.test(0)); + + assertTrue(pOdd.test(1)); + assertTrue(pOdd.test(Integer.valueOf(1))); + assertTrue(pOdd.test(new Integer(1))); + assertTrue(pOdd.test(1)); + + assertTrue(pEven.test(0)); + assertTrue(pEven.test(Integer.valueOf(0))); + assertTrue(pEven.test(new Integer(0))); + assertTrue(pEven.test(0)); + + assertFalse(pEven.test(1)); + assertFalse(pEven.test(Integer.valueOf(1))); + assertFalse(pEven.test(new Integer(1))); + assertFalse(pEven.test(1)); + + int magic[] = { 8675390 }; + IntPredicate pMagic = (t) -> t == magic[0]; + + assertFalse(pMagic.test(3927704 )); + assertFalse(pMagic.test(Integer.valueOf(3927704))); + assertFalse(pMagic.test(new Integer(3927704))); + assertFalse(pMagic.test(3927704)); + + assertTrue(pMagic.test(8675390)); + assertTrue(pMagic.test(Integer.valueOf(8675390))); + assertTrue(pMagic.test(new Integer(8675390))); + assertTrue(pMagic.test(8675390)); + + magic[0] = 3927704; + + assertTrue(pMagic.test(3927704)); + assertTrue(pMagic.test(Integer.valueOf(3927704))); + assertTrue(pMagic.test(new Integer(3927704))); + assertTrue(pMagic.test(3927704)); + + assertFalse(pMagic.test(8675390)); + assertFalse(pMagic.test(Integer.valueOf(8675390))); + assertFalse(pMagic.test(new Integer(8675390))); + assertFalse(pMagic.test(8675390)); + } + + public void testLongPredicate() { + LongPredicate pOdd = (t) -> 0 != (t & 1); + LongPredicate pEven = (t) -> 0 == (t & 1); + + assertFalse(pOdd.test(0L)); + assertFalse(pOdd.test(Long.valueOf(0L))); + assertFalse(pOdd.test(new Long(0L))); + assertFalse(pOdd.test(0L)); + + assertTrue(pOdd.test(1L)); + assertTrue(pOdd.test(Long.valueOf(1L))); + assertTrue(pOdd.test(new Long(1L))); + assertTrue(pOdd.test(1L)); + + assertTrue(pEven.test(0L)); + assertTrue(pEven.test(Long.valueOf(0L))); + assertTrue(pEven.test(new Long(0L))); + assertTrue(pEven.test(0L)); + + assertFalse(pEven.test(1L)); + assertFalse(pEven.test(Long.valueOf(1L))); + assertFalse(pEven.test(new Long(1L))); + assertFalse(pEven.test(1L)); + + long magic[] = { 8675390L }; + LongPredicate pMagic = (t) -> t == magic[0]; + + assertFalse(pMagic.test(3927704L)); + assertFalse(pMagic.test(Long.valueOf(3927704L))); + assertFalse(pMagic.test(new Long(3927704L))); + assertFalse(pMagic.test(3927704L)); + + assertTrue(pMagic.test(8675390L)); + assertTrue(pMagic.test(Long.valueOf(8675390L))); + assertTrue(pMagic.test(new Long(8675390L))); + assertTrue(pMagic.test(8675390L)); + + magic[0] = 3927704L; + + assertTrue(pMagic.test(3927704L)); + assertTrue(pMagic.test(Long.valueOf(3927704L))); + assertTrue(pMagic.test(new Long(3927704L))); + assertTrue(pMagic.test(3927704L)); + + assertFalse(pMagic.test(8675390L)); + assertFalse(pMagic.test(Long.valueOf(8675390L))); + assertFalse(pMagic.test(new Long(8675390L))); + assertFalse(pMagic.test(8675390L)); + } + + public void testDoublePredicate() { + DoublePredicate pInfinite = (t) -> Double.isInfinite(t); + DoublePredicate pFinite = (t) -> Double.isFinite(t); + + assertFalse(pInfinite.test(0.0)); + assertFalse(pInfinite.test(Double.valueOf(0.0))); + assertFalse(pInfinite.test(new Double(0.0))); + assertFalse(pInfinite.test(0.0)); + + assertTrue(pInfinite.test(Double.POSITIVE_INFINITY)); + assertTrue(pInfinite.test(Double.valueOf(Double.POSITIVE_INFINITY))); + assertTrue(pInfinite.test(new Double(Double.POSITIVE_INFINITY))); + assertTrue(pInfinite.test(Double.POSITIVE_INFINITY)); + + assertTrue(pFinite.test(0.0)); + assertTrue(pFinite.test(Double.valueOf(0.0))); + assertTrue(pFinite.test(new Double(0.0))); + assertTrue(pFinite.test(0.0)); + + assertFalse(pFinite.test(Double.POSITIVE_INFINITY)); + assertFalse(pFinite.test(Double.valueOf(Double.POSITIVE_INFINITY))); + assertFalse(pFinite.test(new Double(Double.POSITIVE_INFINITY))); + assertFalse(pFinite.test(Double.POSITIVE_INFINITY)); + + double magic[] = { 1.8675390 }; + DoublePredicate pMagic = (t) -> t == magic[0]; + + assertFalse(pMagic.test(1.3927704)); + assertFalse(pMagic.test(Double.valueOf(1.3927704))); + assertFalse(pMagic.test(new Double(1.3927704))); + assertFalse(pMagic.test(1.3927704)); + + assertTrue(pMagic.test(1.8675390)); + assertTrue(pMagic.test(Double.valueOf(1.8675390))); + assertTrue(pMagic.test(new Double(1.8675390))); + assertTrue(pMagic.test(1.8675390)); + + magic[0] = 1.3927704; + + assertTrue(pMagic.test(1.3927704)); + assertTrue(pMagic.test(Double.valueOf(1.3927704))); + assertTrue(pMagic.test(new Double(1.3927704))); + assertTrue(pMagic.test(1.3927704)); + + assertFalse(pMagic.test(1.8675390)); + assertFalse(pMagic.test(Double.valueOf(1.8675390))); + assertFalse(pMagic.test(new Double(1.8675390))); + assertFalse(pMagic.test(1.8675390)); + } + + @Test + public void testIsEqual() { + HashSet s1 = new HashSet<>(); + HashSet s2 = (HashSet) s1.clone(); + assertTrue(Predicate.isEqual(null).test(null)); + assertTrue(Predicate.isEqual(s2).test(s1)); + } + +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/regex/PatternStreamTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/regex/RegExTest.java --- a/test/java/util/regex/RegExTest.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/java/util/regex/RegExTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -40,6 +40,7 @@ import java.util.Random; import java.io.*; import java.util.*; +import java.util.function.Predicate; import java.nio.CharBuffer; import java.util.function.Predicate; diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/BaseStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/BaseStreamTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,76 @@ +/* + * 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.util.Random; + +public abstract class BaseStreamTest { + public ParallelType getParallelType() { + return parallelType; + } + protected enum ParallelType { Parallel, Sequential, Default } + + //Test data size + protected final static int VERY_SMALL_DATA_SIZE = 1; + + protected final static int SMALL_DATA_SIZE = 1 << 2; + + //MIN_PARTITION + protected final static int PARTITION_DATA_SIZE = 1 << 4; + + protected final static int MEDIUM_DATA_SIZE = 1 << 7; + + protected final static int[] ALL_DATA_SIZES = { + + MEDIUM_DATA_SIZE, + PARTITION_DATA_SIZE, + SMALL_DATA_SIZE, + VERY_SMALL_DATA_SIZE + }; + + protected final static int[] MEDIUM_DATA_SIZES = { + MEDIUM_DATA_SIZE, + PARTITION_DATA_SIZE, + SMALL_DATA_SIZE, + VERY_SMALL_DATA_SIZE + }; + + protected final static int[] SMALL_DATA_SIZES = { + SMALL_DATA_SIZE, + PARTITION_DATA_SIZE, + VERY_SMALL_DATA_SIZE + }; + + protected final static int SIXTY_FOUR = 64; + + protected final static Random rand = new Random(433494437); + + protected final ParallelType parallelType; + + BaseStreamTest(ParallelType parallelType) { + this.parallelType = parallelType; + } + + @FunctionalInterface + public interface TripleFunction { + public I apply(L l, M m, N n); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/CollectTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/CollectTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,74 @@ +/* + * 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.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; + +public class CollectTest> extends OperatorTest{ + public CollectTest(GenericStreamTest test) { + super(test); + } + + public void testCollectByGroupingBy(String desc, Collection col, Function mapFunc) { + Map> result = streamFor(col). collect(Collectors.groupingBy(mapFunc)); + result.keySet().stream().forEach((key) -> { + result.get(key).stream().forEach((u) -> { + assertEquals(key, mapFunc.apply(u)); + }); + }); + assertEqualContents(result.values().stream().flatMap(l -> l.stream()).collect(Collectors.toList()), col, + test.getNaturalOrderComparator()); + assertTrue(streamFor(createEmptyCollection()). + collect(Collectors.groupingBy(mapFunc)).isEmpty()); + } + + public void testCollectByPartition(String desc, Collection col, Predicate mapFunc) { + Map> partition = streamFor(col). collect(Collectors.partitioningBy(mapFunc)); + Map> emptyPartition + = streamFor(createEmptyCollection()).collect(Collectors.partitioningBy(mapFunc)); + Arrays.asList(true, false).forEach(key -> { + partition.get(key).stream().forEach((u) -> { + assertEquals(mapFunc.test(u), key.booleanValue()); + }); + assertTrue(emptyPartition.get(false).isEmpty()); + }); + } + + @Test(dataProvider="collectionKeyValueFunctionData", threadPoolSize = 3) + public void testCollectToMap(String desc, Collection col, Function keyFunc, + Function valueFunc) { + Map keyToValue = streamFor(col).collect(Collectors.toMap(keyFunc, valueFunc)); + assertEquals(keyToValue.size(), streamFor(col).map(keyFunc).distinct().count()); + col.stream().forEach((u) -> { + assertEquals(valueFunc.apply(u), keyToValue.get(keyFunc.apply(u))); + }); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/CollectorsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/CollectorsTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,458 @@ +/* + * 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 + * @summary function test for Collectors' static methods + * @(#) CollectorsTest.java + * @run testng CollectorsTest + * @author Tristan Yan + */ + +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class CollectorsTest { + private final static long COLLECTION_SIZE = 1 << 8; + + private final static Random RAND = new Random(System.nanoTime()); + + @Test(dataProvider="streams") + public void testCounting(Collection c) { + assertEquals(c.stream().collect(Collectors.counting()).longValue(), + COLLECTION_SIZE); + } + + @Test(dataProvider="streams") + public void testGroupingBy(Collection c) { + Map> map = c.parallelStream(). + collect(Collectors.groupingBy(Integer::lowestOneBit)); + map.forEach((i, l) -> { + for(Integer li : l) { + assertEquals(Integer.lowestOneBit(li), i.intValue()); + } + }); + + Map> mapConcurrent = c.parallelStream().collect( + Collectors.groupingByConcurrent(Integer::highestOneBit)); + mapConcurrent.forEach((i, l) -> { + for(Integer li : l) { + assertEquals(Integer.highestOneBit(li), i.intValue()); + } + }); + } + + @Test(dataProvider="streams") + public void testGroupingByWithCollector(Collection c) { + Map> map = c.parallelStream(). + collect(Collectors.groupingBy(Integer::lowestOneBit, + Collectors.mapping(Integer::lowestOneBit, + Collectors.toSet()))); + map.forEach((i, s) -> { + assertEquals(s.size(), 1); + assertEquals(s.toArray()[0], i); + }); + + Map> mapConcurrent = c.parallelStream(). + collect(Collectors.groupingBy(Integer::highestOneBit, + Collectors.mapping(Integer::highestOneBit, + Collectors.toSet()))); + mapConcurrent.forEach((i, s) -> { + assertEquals(s.size(), 1); + assertEquals(s.toArray()[0], i); + }); + } + + @Test(dataProvider="streams") + public void testGroupingByWithCollectorFactory(Collection c) { + Map> map = c.parallelStream(). + collect(Collectors.groupingBy(Integer::lowestOneBit, TreeMap::new, + Collectors.toCollection(TreeSet::new))); + final AtomicInteger lowerBit = new AtomicInteger(-1); + map.forEach((i, s) -> { + assertTrue(i > lowerBit.getAndSet(i)); + final AtomicInteger smallest = new AtomicInteger(Integer.MIN_VALUE); + s.forEach(v -> { + assertTrue(v >= smallest.getAndSet(v)); + }); + }); + + Map> mapConcurrent = c.parallelStream(). + collect(Collectors.groupingBy(Integer::lowestOneBit, TreeMap::new, + Collectors.toCollection(TreeSet::new))); + final AtomicInteger higherBit = new AtomicInteger(-1); + mapConcurrent.forEach((i, s) -> { + assertTrue(i > higherBit.getAndSet(i)); + final AtomicInteger smallest = new AtomicInteger(Integer.MIN_VALUE); + s.forEach(v -> { + assertTrue(v >= smallest.getAndSet(v)); + }); + }); + } + + @Test(dataProvider="streams") + public void testMapping(Collection c) { + Function itos = String::valueOf; + Function lenFunc = itos.andThen(Integer::parseInt); + List l = c.stream().collect(Collectors.mapping(lenFunc, + Collectors.toList())); + assertEquals(l.size(), c.size()); + Iterator iter1 = c.iterator(); + Iterator iter2 = l.iterator(); + while(iter1.hasNext() && iter2.hasNext()) { + assertEquals(iter1.next(), iter2.next()); + } + } + + @Test(dataProvider="streams") + public void testMaxBy(Collection c) { + Function f = Math::abs; + Comparator c1 = Comparator.comparing(f); + Integer max = c.stream().collect(Collectors.maxBy(c1)).get(); + int maxExpected + = c.stream().mapToInt(i -> Math.abs(i)).max().getAsInt(); + assertEquals(Math.abs(max.intValue()), maxExpected); + } + + @Test(dataProvider="streams") + public void testMinBy(Collection c) { + Comparator c1 = Comparator.comparing(i -> i * -1); + Integer max = c.stream().collect(Collectors.minBy(c1)).get(); + int maxExpected = c.stream().mapToInt(i -> i.intValue()).max().getAsInt(); + assertEquals(max.intValue(), maxExpected); + } + + @Test(dataProvider="streams") + public void testPartitionBy(Collection c) { + Map> partition = c.stream(). + collect(Collectors.partitioningBy(i -> i > 0)); + List greaterThanZero = partition.get(true); + List notGreaterThanZero = partition.get(false); + for(int i : greaterThanZero) + assertTrue(i > 0); + for(int i : notGreaterThanZero) + assertFalse(i > 0); + } + + @Test(dataProvider="streams") + public void testPartitionByWithCollector(Collection c) { + Map> partition = c.stream(). + collect(Collectors.partitioningBy(i -> (i & 0x01) == 0x01, + Collectors.toCollection(TreeSet::new))); + Set odds = partition.get(true); + Set evens = partition.get(false); + int smallest = Integer.MIN_VALUE; + for(int i : odds) { + assertTrue((i & 0x01) == 0x01); + assertTrue( i >= smallest); + smallest = i; + } + + smallest = Integer.MIN_VALUE; + for(int i : evens){ + assertTrue((i & 0x01) == 0x0); + assertTrue( i >= smallest); + smallest = i; + } + } + + @Test(dataProvider="streams") + public void testReducing(Collection c) { + Function absFunc = Math::abs; + Comparator comp = Comparator.comparing(absFunc); + BinaryOperator shortest = BinaryOperator.minBy(comp); + Integer smallestPositive = c.stream().collect(Collectors.reducing(shortest)).get(); + int expected = c.stream().mapToInt(Math::abs).min().getAsInt(); + assertEquals(Math.abs(smallestPositive.intValue()), expected); + } + + @Test(dataProvider="streams") + public void testReducingWithIdentity(Collection c) { + Map map = c.stream().collect(Collectors.groupingBy( + Integer::lowestOneBit, Collectors.reducing(0, (i1, i2) -> i1++))); + Map> mapCal = c.stream(). + map(Integer::lowestOneBit). + collect(Collectors.groupingBy(Function.identity())); + mapCal.forEach((i, l) -> { + assertEquals(l.size(), map.get(i).intValue()); + }); + } + + @Test(dataProvider="streams") + public void testReducingWithMapper(Collection c) { + Function itos = String::valueOf; + Function lenF = String::length; + int totalLen = c.stream().collect(Collectors.reducing( + 0, itos.andThen(lenF), Integer::sum)); + int expected + = c.stream().mapToInt(i -> String.valueOf(i).length()).sum(); + assertEquals(totalLen, expected); + } + + @Test(dataProvider="streams") + public void testSumBy(Collection c) { + Long posOverNeg = c.stream().collect(Collectors.summarizingLong( i -> new Long(Integer.signum(i)))).getSum(); + int expected = c.stream().mapToInt(Integer::signum).sum(); + assertEquals(posOverNeg.intValue(), expected); + } + + @Test(dataProvider="streams") + public void testToCollection(Collection c) { + ArrayDeque ad = c.stream().sequential(). + collect(Collectors.toCollection(ArrayDeque::new)); + assertEquals(ad, new ArrayDeque<>(c)); + ArrayList al = c.stream().sequential(). + collect(Collectors.toCollection(ArrayList::new)); + assertEquals(al, new ArrayList<>(c)); + ConcurrentLinkedDeque cld = c.stream().sequential().collect( + Collectors.toCollection(ConcurrentLinkedDeque::new)); + assertEquals(cld, new ConcurrentLinkedDeque<>(c)); + ConcurrentLinkedQueue clq = c.stream().sequential().collect( + Collectors.toCollection(ConcurrentLinkedQueue::new)); + assertEquals(clq, new ConcurrentLinkedQueue<>(c)); + ConcurrentSkipListSet ckls = c.stream().sequential().collect( + Collectors.toCollection(ConcurrentSkipListSet::new)); + assertEquals(ckls, new ConcurrentSkipListSet<>(c)); + CopyOnWriteArrayList cowal = c.stream().sequential().collect( + Collectors.toCollection(CopyOnWriteArrayList::new)); + assertEquals(cowal, new CopyOnWriteArrayList<>(c)); + HashSet hs = c.stream(). + collect(Collectors.toCollection(HashSet::new)); + assertEquals(hs, new HashSet<>(c)); + LinkedBlockingDeque lbd = c.stream().sequential().collect( + Collectors.toCollection(LinkedBlockingDeque::new)); + assertEquals(lbd, new LinkedBlockingDeque<>(c)); + LinkedBlockingQueue lbq = c.stream().sequential().collect( + Collectors.toCollection(LinkedBlockingQueue::new)); + assertEquals(lbq, new LinkedBlockingQueue<>(c)); + LinkedHashSet lhs = c.stream().sequential().collect( + Collectors.toCollection(LinkedHashSet::new)); + assertEquals(lhs, new LinkedHashSet<>(c)); + LinkedList ll = c.stream().sequential().collect( + Collectors.toCollection(LinkedList::new)); + assertEquals(ll, new LinkedList<>(c)); + LinkedTransferQueue ltq = c.stream().sequential().collect( + Collectors.toCollection(LinkedTransferQueue::new)); + assertEquals(ltq, new LinkedTransferQueue<>(c)); + + //PriorityQueue doesn't guarante to traverse the elements of in any + //particular order, we're using Arrays.sort(pq.toArray()) verify + //result + PriorityBlockingQueue pbq = c.stream().sequential().collect( + Collectors.toCollection(PriorityBlockingQueue::new)); + PriorityBlockingQueue pbqExpected + = new PriorityBlockingQueue<>(c); + Object[] pbqArr = pbq.toArray(); + Object[] pbqExpectedArr = pbqExpected.toArray(); + Arrays.sort(pbqArr); + Arrays.sort(pbqExpectedArr); + assertEquals(pbqArr, pbqExpectedArr); + + PriorityQueue pq = c.stream().sequential().collect( + Collectors.toCollection(PriorityQueue::new)); + PriorityQueue pqExpected = new PriorityQueue<>(c); + Object[] pqArr = pq.toArray(); + Object[] pqExpectedArr = pqExpected.toArray(); + Arrays.sort(pqArr); + Arrays.sort(pqExpectedArr); + assertEquals(pqArr, pqExpectedArr); + + Stack s = c.stream().sequential().collect(Collectors. + toCollection(Stack::new)); + Stack sExpected = new Stack<>(); + sExpected.addAll(c); + assertEquals(s, sExpected); + TreeSet ts = c.stream().sequential().collect(Collectors. + toCollection(TreeSet::new)); + assertEquals(ts, new TreeSet<>(c)); + Vector v = c.stream().sequential().collect(Collectors. + toCollection(Vector::new)); + assertEquals(v, new Vector<>(c)); + } + + @Test(dataProvider="streams") + public void testToMap(Collection c) { + Map map = c.stream().collect( + Collectors.toMap(Function.identity(), String::valueOf)); + map.forEach((k, v) -> { + assertEquals(k.intValue(), Integer.parseInt(v)); + }); + Map concurrentMap = c.stream().collect( + Collectors.toConcurrentMap(Function.identity(), String::valueOf)); + concurrentMap.forEach((k, v) -> { + assertEquals(k.intValue(), Integer.parseInt(v)); + }); + } + + @Test(dataProvider="streams") + public void testToMapWithOperator(Collection c) { + Map map = c.stream().collect( + Collectors.toMap(Integer::highestOneBit, i -> 1, Integer::sum)); + Map> hmap = c.stream(). + map(Integer::highestOneBit). + collect(Collectors.groupingBy(Function.identity())); + assertEquals(map.size(), hmap.size()); + map.forEach((k , v) -> { + assertEquals(v.intValue(), hmap.get(k).size()); + }); + + Map concurrentMap = c.stream().collect( + Collectors.toConcurrentMap(Integer::lowestOneBit, i -> 1, + Integer::sum)); + Map> lmap = c.stream(). + map(Integer::lowestOneBit). + collect(Collectors.groupingBy(Function.identity())); + assertEquals(concurrentMap.size(), lmap.size()); + concurrentMap.forEach((k , v) -> { + assertEquals(v.intValue(), lmap.get(k).size()); + }); + } + + @Test(dataProvider="streams") + public void testToMapWithOperatorAndSupplier(Collection c) { + Map map = c.stream().collect( + Collectors.toMap(Integer::highestOneBit, i -> 1, Integer::sum, + TreeMap::new)); + Map> hmap = c.stream(). + map(Integer::highestOneBit). + collect(Collectors.groupingBy(Function.identity())); + assertEquals(map.size(), hmap.size()); + + AtomicInteger lowerKey = new AtomicInteger(Integer.MIN_VALUE); + map.forEach((k , v) -> { + assertTrue(k >= lowerKey.getAndSet(k)); + assertEquals(v.intValue(), hmap.get(k).size()); + }); + + Map concurrentMap = c.stream().collect( + Collectors.toConcurrentMap(Integer::lowestOneBit, i -> 1, + Integer::sum, ConcurrentSkipListMap::new)); + Map> lmap = c.stream(). + map(Integer::lowestOneBit). + collect(Collectors.groupingBy(Function.identity())); + assertEquals(concurrentMap.size(), lmap.size()); + lowerKey.set(Integer.MIN_VALUE); + concurrentMap.forEach((k , v) -> { + assertTrue(k >= lowerKey.getAndSet(k)); + assertEquals(v.intValue(), lmap.get(k).size()); + }); + } + + @Test(dataProvider="streams") + public void testToDoubleSummaryStatistics(Collection c){ + DoubleSummaryStatistics dss = c.stream().collect(Collectors.summarizingDouble(Integer::doubleValue)); + IntSummaryStatistics iss = c.stream().mapToInt(Integer::intValue).summaryStatistics(); + assertEquals(dss.getAverage(), iss.getAverage()); + assertEquals(dss.getCount(), c.size()); + assertEquals(dss.getSum(), (double)iss.getSum()); + } + + @Test(dataProvider="streams") + public void testToIntSummaryStatistics(Collection c){ + IntSummaryStatistics iss = c.stream().collect(Collectors.summarizingInt(Math::abs)); + assertEquals(iss.getAverage(), + c.stream().mapToInt(Math::abs).average().getAsDouble()); + assertEquals(iss.getCount(), c.size()); + assertEquals(iss.getSum(), c.stream().mapToLong(i -> Math.abs(i)).sum()); + } + + @Test(dataProvider="streams") + public void testToLongSummaryStatistics(Collection c){ + LongSummaryStatistics lss = c.stream().collect(Collectors.summarizingLong(i -> (long)Math.pow(i, 2))); + assertEquals(lss.getAverage(), c.stream().mapToLong(i -> (long)Math.pow(i, 2)).average().getAsDouble()); + assertEquals(lss.getCount(), c.size()); + assertEquals(lss.getSum(), c.stream().mapToLong(i -> (long)Math.pow(i, 2)).sum()); + } + + @Test + public void testEmpty(){ + Stream stream = Stream.empty(); + assertEquals(0, Stream.empty().collect(Collectors.counting()).intValue()); + assertTrue(Stream.empty().collect(Collectors. + groupingBy(Function.identity())).isEmpty()); + assertTrue(Stream.empty().collect(Collectors.groupingBy( + Function.identity(), Collectors.toSet())).isEmpty()); + assertTrue(Stream.empty().collect(Collectors.groupingBy(Function.identity(), TreeMap::new, + Collectors.toCollection(TreeSet::new))).isEmpty()); + assertTrue(Stream.empty().collect(Collectors.mapping( + Function.identity(), Collectors.toList())).isEmpty()); + assertFalse(Stream.empty().collect(Collectors.maxBy(Comparator.naturalOrder())).isPresent()); + Map> partition1 = Stream.empty(). + collect(Collectors.partitioningBy(i -> i > 0)); + assertTrue(partition1.get(true).isEmpty()); + assertTrue(partition1.get(false).isEmpty()); + + Map> partition2 = Stream.empty(). + collect(Collectors.partitioningBy(i -> (i & 0x01) == 0x01, + Collectors.toCollection(TreeSet::new))); + assertTrue(partition2.get(true).isEmpty()); + assertTrue(partition2.get(false).isEmpty()); + + Comparator comp = Comparator.comparing(Function.identity()); + BinaryOperator largest = BinaryOperator.maxBy(comp); + assertFalse(Stream.empty().collect(Collectors.reducing(largest)).isPresent()); + } + + + @DataProvider + public static Object[][] streams() { + Supplier>[] suppliers = new Supplier[]{ + ArrayDeque::new, + ArrayList::new, + ConcurrentLinkedDeque::new, + ConcurrentLinkedQueue::new, + ConcurrentSkipListSet::new, + CopyOnWriteArrayList::new, + HashSet::new, + LinkedBlockingDeque::new, + LinkedBlockingQueue::new, + LinkedHashSet::new, + LinkedList::new, + LinkedTransferQueue::new, + PriorityBlockingQueue::new, + PriorityQueue::new, + Stack::new, + TreeSet::new, + Vector::new, + }; + Object[][] params = new Object[suppliers.length][1]; + int index = 0; + for(Supplier> s: suppliers) { + Collection c = s.get(); + for(int i = 0; i < COLLECTION_SIZE; i++) { + c.add(RAND.nextInt()); + } + params[index++][0] = c; + } + return params; + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/ConcatTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/ConcatTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,59 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.testng.annotations.Test; + +public class ConcatTest> extends OperatorTest{ + public ConcatTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="concatCollectionData") + public void testConcat(String desc, Collection tobeConcated, Collection concat) { + //We're using List to store expected result because Set could merge object, + Collection expected = new ArrayList<>(tobeConcated); + expected.addAll(concat); + + //test concat with parallel/non-parallel Stream + for(BaseStreamTest.ParallelType concatType : BaseStreamTest.ParallelType.values()) { + Stream concatStream = (concatType == BaseStreamTest.ParallelType.Parallel) ? + concat.parallelStream(): (concatType == BaseStreamTest.ParallelType.Sequential) + ? concat.parallelStream().sequential() : concat.stream(); + List calculated = Stream.concat(streamFor(tobeConcated), concatStream) + .collect(Collectors.toList()); + assertEqualContents(calculated, expected, test.getNaturalOrderComparator()); + } + + List result3 = Stream.concat(tobeConcated.stream(), streamFor(createEmptyCollection())) + .collect(Collectors.toList()); + List result4 = Stream.concat(tobeConcated.stream(), Stream.empty()) + .collect(Collectors.toList()); + assertEqualContents(tobeConcated, result3, test.getNaturalOrderComparator()); + assertEqualContents(tobeConcated, result4, test.getNaturalOrderComparator()); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/CountTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/CountTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,39 @@ +/* + * 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.util.Collection; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class CountTest> extends OperatorTest{ + public CountTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionData") + public void testCount(String desc, Collection col) { + assertEquals(streamFor(col).count(), col.size()); + assertEquals(streamFor(col).count(), streamFor(col).mapToLong(u -> 1).sum()); + assertEquals(streamFor(createEmptyCollection()).count(), 0); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/DistinctTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/DistinctTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,51 @@ +/* + * 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.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class DistinctTest> extends OperatorTest{ + public DistinctTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionDataWithSelection") + public void testDistinct(String desc, Collection col, Function> mapper) { + Set set = new HashSet<>(col); + + List expected = streamFor(col).flatMap(mapper).distinct().collect(Collectors.toList()); + if(expected.size() != 0) { + assertEqualContents(expected, set, test.getNaturalOrderComparator()); + } else { + assertEquals(mapper.apply(streamFor(col).findAny().get()).count(), 0); + } + assertEquals(streamFor(createEmptyCollection()).distinct().count(), 0); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/EmployeeStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/EmployeeStreamTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,319 @@ +/* + * 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 + * @summary Basic test for Stream + * @library /sqeutil + * @(#) EmployeeStreamTest.java + * @author Eric Wang/Tristan Yan + * @run testng/othervm -mx2g EmployeeStreamTest + */ + +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.ToIntFunction; +import java.util.stream.IntStream; +import org.testng.annotations.Factory; + +class Employee implements Comparable, Cloneable, java.io.Serializable { + private static final long serialVersionUID = 3241619007641335109L; + + static final int ID_LENGTH = 6; + static final int MIN_BIRTHDAY = 1900; + static final int MAX_BIRTHDAY = 2050; + static final int MIN_PAY = 1000; + static final int MAX_PAY = 100000; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public int getBirthday() { + return birthday; + } + + public boolean isMale() { + return male; + } + + public double getPay() { + return pay; + } + + public void setPay(double pay) { + this.pay = pay; + } + + public Title getTitle() { + return title; + } + + public void setTitle(Title title) { + this.title = title; + } + public Employee(String id, int birthday, boolean male, double pay, Title title) { + this.id = id; + this.birthday = birthday; + this.male = male; + this.pay = pay; + this.title = title; + } + + static enum Title { + SE, SSE, PSE, CSE, ARCHITECT, M1, M2, M3, M4 + } + + static enum Rule { + ID { + @Override + Function empFunc() { + return Employee::getId; + } + @Override + String funcName(){ + return "Employee::getId"; + } + }, + BIRTHDAY { + @Override + Function empFunc() { + return Employee::getBirthday; + } + @Override + String funcName(){ + return "Employee::getBirthday"; + } + }, + MALE { + @Override + Function empFunc() { + return Employee::isMale; + } + @Override + String funcName(){ + return "Employee::isMale"; + } + }, + PAY { + @Override + Function empFunc() { + return Employee::getPay; + } + @Override + String funcName(){ + return "Employee::getPay"; + } + }, + TITLE { + @Override + Function empFunc(){ + return Employee::getTitle; + } + + @Override + String funcName(){ + return "Employee::getTitle"; + } + }; + + Comparator getComparator() { + return Comparator.comparing(empFunc()); + } + + Object getValue(Employee e) { return empFunc().apply(e); } + + abstract String funcName(); + + abstract Function empFunc(); + } + + private String id; + private final int birthday; + private final boolean male; + private double pay; + private Title title; + + @Override + public boolean equals(Object other) { + if (other instanceof Employee) { + Employee compared = (Employee) other; + return id.equals(compared.getId()) && birthday == compared.getBirthday() + && male == compared.isMale() && pay == compared.getPay() + && title == compared.getTitle(); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.id); + } + + @Override + public int compareTo(Employee t) { + return id.compareTo(t.getId()); + } + + @Override + public Employee clone() { + try { + return (Employee)super.clone(); + } catch (CloneNotSupportedException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public String toString() { + return "id=" + getId() + ", birthday=" + getBirthday() + ". male=" + isMale() + + ", pay=" + getPay() + ", title=" + getTitle(); + } +} + +public class EmployeeStreamTest> extends + GenericStreamTest> { + private final static HashMap> cache = new HashMap<>(); + + static { + Function strToEmployee = EmployeeStreamTest::createEmployee; + Function lensToString = StringUtilities::randomNumeric; + Function lensToEmployee = lensToString.andThen(strToEmployee); + BiFunction randomLenToEmployee = (random, len) -> + lensToEmployee.apply(random ? rand.nextInt(len) + 1 : len); + Function> randomToEmployeesFunction = random -> + (size -> IntStream.rangeClosed(1, size).mapToObj(len -> + randomLenToEmployee.apply(random, len)).toArray(Employee[]::new)); + initCache(cache, randomToEmployeesFunction, "EmployeeStreamTest"); + } + public EmployeeStreamTest(Class clazz, + ParallelType parallelType, int initSize) { + super(clazz, parallelType, Comparator.naturalOrder(), initSize); + } + + public EmployeeStreamTest(Class clazz, + ParallelType parallelType) { + super(clazz, parallelType, Comparator.naturalOrder()); + } + + @Factory + public static Object[] create(){ + TripleFunction supplierWithInitSize = + EmployeeStreamTest>::new; + BiFunction supplier = + EmployeeStreamTest>::new; + return GenericStreamTest.create(supplierWithInitSize, supplier, true); + } + + @Override + public String getTestName() { + return typeObject.getName() + ""; + } + + @Override + protected Object[] predicateAndDesc(int size) { + Employee limit = createEmployee(); + boolean isUp = rand.nextBoolean(); + Employee.Rule rule = Arrays.stream(Employee.Rule.values()).findAny().get(); + return new Object[]{ LambdaUtilities.randomGenericPredicate(isUp, limit, rule.getComparator()), + String.format("emp -> Comparator.comparing(%s).compare(emp, %s) %s 0", rule.funcName(), isUp ? ">=" : "<", limit)}; + } + + //Function, descrption for Function + @Override + protected Object[][] functionAndDesc(){ + return Arrays.stream(Employee.Rule.values()).map(rule -> new Object[]{rule.empFunc(), rule.funcName()}) + .toArray(Object[][]::new); + } + + //BinaryOperator, descrption, stateless + @Override + protected Object[][] binaryOperatorAndDesc() { + BinaryOperator maxOp = (e1, e2) -> getNaturalOrderComparator().compare(e1, e2) < 0 ? e2 : e1; + BinaryOperator minOp = (e1, e2) -> getNaturalOrderComparator().compare(e1, e2) > 0? e2 : e1; + return new Object[][]{ + {maxOp, "(e1, e2) -> naturalOrderComparator.compare(e1, e2) < 0 ? e2 : e1", true}, + {minOp, "(e1, e2) -> naturalOrderComparator.compare(e1, e2) > 0? e2 : e1", true}, + }; + } + + @Override + protected Employee[] bases(int size){ + return new Employee[]{createEmployee()}; + } + + private static Employee createEmployee(String id) { + BiFunction RANDOM_INT_BETWEEN + = (start, end) -> start + rand.nextInt(end - start); + int birthday = RANDOM_INT_BETWEEN.apply(Employee.MIN_BIRTHDAY, Employee.MAX_BIRTHDAY); + Boolean gender = rand.nextBoolean(); + double pay = RANDOM_INT_BETWEEN.apply(Employee.MIN_PAY, Employee.MAX_PAY); + Employee.Title title = Employee.Title.values()[rand.nextInt(Employee.Title.values().length)]; + return new Employee(id, birthday, gender, pay, title); + } + + private Employee createEmployee() { + return this.createEmployee(StringUtilities.randomNumeric(Employee.ID_LENGTH)); + } + + @Override + protected Object[] validArrayGeneratorAndDesc() { + return new Object[]{ + new IntFunction[]{(IntFunction)Employee[]::new, (IntFunction)Object[]::new}, + "{Employee[]::new, Object[]::new}" + }; + } + + @Override + protected Object[][] invalidArrayGeneratorAndDesc() { + return new Object[][]{ + {(IntFunction)Employee.Rule[]::new, "Employee.Rule[]::new"}, + {(IntFunction)String[]::new, "String[]::new"}, + }; + } + + @Override + protected IntFunction createFunction() { + return i -> createEmployee(String.valueOf(i)); + } + + @Override + protected ToIntFunction intValueFunction() { + return e -> Integer.parseInt(e.getId()) ; + } + + @Override + protected Employee[] getArray(int size, boolean random) { return cache.get(random).get(size); } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/FilterTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/FilterTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,79 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; + +public class FilterTest> extends OperatorTest{ + public FilterTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionDualPredicateData") + public void testFilter(String desc, Collection col, Predicate p1, Predicate p2) { + //Filter the data, check if it works as expected. + Collection filteredColByP1 = streamFor(col).filter(p1) + .collect(Collectors.>toCollection(LinkedList::new)); + assertTrue(verifyMatch(filteredColByP1, p1, true)); + + //filter on parallel stream can cause IllegalStateException + Collection filteredColByAlwaysTrue = streamFor(col).filter(p1).filter(e -> true) + .collect(Collectors.>toCollection(LinkedList::new)); + assertTrue(verifyMatch(filteredColByAlwaysTrue, p1, true)); + + //filter with false will get nothing + Collection filteredColByAlwaysFalse = streamFor(col).filter(p1).filter(e -> false) + .collect(Collectors.>toCollection(LinkedList::new)); + assertTrue(filteredColByAlwaysFalse.isEmpty()); + + //The reason conver l to sorted is CopyOnWriteArrayList doesn't support + //sort, we use ArrayList sort data instead + Collection filteredColByP2AfterP1 = streamFor(col).filter(p1).filter(p2) + .collect(Collectors.>toCollection(ArrayList::new)); + + List filteredColByrP1AndP2 = streamFor(col).filter(p1.and(p2)) + .collect(Collectors.>toCollection(ArrayList::new)); + assertEqualContents(filteredColByP2AfterP1, filteredColByrP1AndP2, test.getNaturalOrderComparator()); + + List filteredColByrP1OrP2 = streamFor(col).filter(p1.or(p2)) + .collect(Collectors.>toCollection(ArrayList::new)); + + List filteredExpected = new ArrayList<>(filteredColByrP1AndP2); + filteredExpected.addAll(filteredColByrP1OrP2); + + //concat stream.filter(p1) with stream.filter(p2) should be same as stream.filter(p1 && p2) combine with + //stream.filter(p1 || p2) + List filteredColByP1CancatfilteredColByP2 = Stream.concat(streamFor(col).filter(p1), streamFor(col).filter(p2)) + .collect(Collectors.>toCollection(ArrayList::new)); + assertEqualContents(filteredColByP1CancatfilteredColByP2, filteredExpected, test.getNaturalOrderComparator()); + } +} + + diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/FindTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/FindTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,57 @@ +/* + * 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.util.Collection; +import java.util.Optional; +import java.util.stream.Stream; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; + +public class FindTest> extends OperatorTest{ + public FindTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionData") + public void testFind(String desc, Collection col) { + Stream stream = streamFor(col); + Optional opAny = stream.findAny(); + Optional opFirst = streamFor(col).findFirst(); + if(!stream.isParallel()) + assertEquals(opAny, opFirst); + assertTrue(opAny.isPresent()); + assertTrue(opFirst.isPresent()); + + assertFalse(streamFor(createEmptyCollection()).findAny().isPresent()); + assertFalse(streamFor(createEmptyCollection()).findFirst().isPresent()); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testFindNull() { + Collection nullCol = createEmptyCollection(); + nullCol.add(null); + streamFor(nullCol).findAny(); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/FlatMapTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/FlatMapTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,44 @@ +/* + * 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.util.Collection; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class FlatMapTest> extends OperatorTest{ + public FlatMapTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionDataWithSelection", threadPoolSize = 3) + public void testFlatMap(String desc, Collection col, Function> mapper) { + List result = streamFor(col).flatMap(mapper).collect(Collectors.toList()); + verifyFlatMap(col, result, mapper); + + assertEquals(streamFor(createEmptyCollection()).flatMap(mapper).count(), 0); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/ForEachTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/ForEachTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,54 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; + +public class ForEachTest> extends OperatorTest{ + public ForEachTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionData") + public void testForEach(String desc, Collection col) { + List expected= new ArrayList<>(col); + //Unordered streams could play parallel executions, which we need a + //thread-safe queue to check the data + ConcurrentLinkedQueue forEachQueue = new ConcurrentLinkedQueue<>(); + streamFor(col).forEach(forEachQueue::add); + assertEqualContents(forEachQueue, expected, test.getNaturalOrderComparator()); + + List forEachOrderedList = new ArrayList<>(); + streamFor(col).forEachOrdered(forEachOrderedList::add); + assertEquals(forEachOrderedList, expected); + + List expectedEmpty = new ArrayList<>(); + streamFor(createEmptyCollection()).forEach(expectedEmpty::add); + assertTrue(expectedEmpty.isEmpty()); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/GenericStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/GenericStreamTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,463 @@ +/* + * 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.IOException; +import java.io.ObjectOutputStream; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.Predicate; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.assertEquals; +import org.testng.ITest; + +public abstract class GenericStreamTest> + extends BaseStreamTest implements ITest { + protected final static int DEFAULT_INIT_SIZE = -1; + + protected final static Class[] defaultConstructorClazz = { + ArrayDeque.class, + ArrayList.class, + ConcurrentLinkedDeque.class, + ConcurrentLinkedQueue.class, + CopyOnWriteArrayList.class, + HashSet.class, + LinkedBlockingDeque.class, + LinkedBlockingQueue.class, + LinkedHashSet.class, + LinkedList.class, + LinkedTransferQueue.class, + Stack.class, + Vector.class + }; + + protected final static Class[] capacityConstructorClazz = { + ArrayBlockingQueue.class, + ArrayDeque.class, + ArrayList.class, + HashSet.class, + LinkedBlockingDeque.class, + LinkedBlockingQueue.class, + LinkedHashSet.class, + Vector.class + }; + + protected final static Class[] defaultComparableConstructorClazz = { + //Sorted collection only supports Comparable data type + PriorityBlockingQueue.class, + PriorityQueue.class, + ConcurrentSkipListSet.class, + TreeSet.class, + }; + + protected final static Class[] capacityComparableConstructorClazz = { + //Sorted collection only supports Comparable data type + PriorityBlockingQueue.class, + PriorityQueue.class, + }; + + private final HashMap>, String> flatMappers(){ + HashMap>, String> map = new HashMap<>(); + map.put(e -> Stream.empty(), "e -> Stream.empty()"); + map.put(e -> Collections.singletonList(e).stream(), + "e -> Collections.singletonList(e).stream()"); + map.put(e -> Stream.generate(() -> e).limit(SIXTY_FOUR), + "e -> Stream.generate(() -> e).limit(FIFTEEN)"); + return map; + } + + protected final Class typeObject; + + private final int initSize; + + protected final Comparator naturalOrderComparator; + + public Stream streamFor(Collection c1) { + return (getParallelType() == ParallelType.Parallel) ? + c1.parallelStream(): (getParallelType() == ParallelType.Sequential) + ? c1.parallelStream().sequential() : c1.stream(); + } + + public Collection createEmptyCollection() { + try { + Collection emptyCol = (initSize == DEFAULT_INIT_SIZE) ? + LambdaUtilities.create(typeObject) : + LambdaUtilities.create(typeObject, initSize); + return emptyCol; + } catch ( ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + + public static Object[] create(TripleFunction testCreatorWithInitSize, + BiFunction + testCreator, boolean comparable) { + List result = new ArrayList<>(); + List> functions = + Arrays.stream(OperatorTest.GenericOperatorType.values()). + map(OperatorTest.GenericOperatorType::getConstructor). + collect(Collectors.>toList()); + if(comparable) + functions.add(SortedTestForCompable::new); + else + functions.add(SortedTestForNonCompable::new); + Arrays.stream(ParallelType.values()).forEach(parallelType -> { + functions.stream().forEach(function -> { + Arrays.stream(defaultConstructorClazz).forEach( clazz -> { + result.add(function.apply(testCreator.apply( + clazz, parallelType))); + }); + Arrays.stream(capacityConstructorClazz).forEach( clazz -> { + result.add(function.apply(testCreatorWithInitSize.apply( + clazz, parallelType, MEDIUM_DATA_SIZE))); + }); + if(comparable) { + Arrays.stream(defaultComparableConstructorClazz).forEach( + clazz -> { + result.add(function.apply(testCreator.apply( + clazz, parallelType))); + }); + Arrays.stream(capacityComparableConstructorClazz).forEach( + clazz -> { + result.add(function.apply(testCreatorWithInitSize. + apply(clazz, parallelType, MEDIUM_DATA_SIZE))); + }); + } + }); + }); + return result.toArray(); + } + + protected GenericStreamTest(Class clazz, ParallelType parallelType, + Comparator naturalOrderComparator, int initSize) { + super(parallelType); + this.typeObject = clazz; + this.naturalOrderComparator = naturalOrderComparator; + this.initSize = initSize; + } + + protected GenericStreamTest(Class clazz, ParallelType parallelType, + Comparator naturalOrderComparator) { + this(clazz, parallelType, naturalOrderComparator, DEFAULT_INIT_SIZE); + } + + protected static void assertEqualContents(Collection result1, + Collection result2, Comparator comparator) { + assertEquals(result1.size(), result2.size()); + ArrayList a = new ArrayList<>(result1); + ArrayList b = new ArrayList<>(result2); + Collections.sort(a, comparator); + Collections.sort(b, comparator); + + for(int i = 0; i < result1.size(); i++) + assertEquals(comparator.compare(a.get(i), b.get(i)), 0); + } + + protected static void initCache(HashMap> + cache, Function> randomToObjecstFunc, + String testName){ + Arrays.asList(true, false).forEach(isRandom -> { + Function sizeToObjects = randomToObjecstFunc.apply(isRandom); + cache.put(isRandom, Arrays.stream(MEDIUM_DATA_SIZES).boxed().collect(Collectors. + toMap(Function.identity(), sizeToObjects))); + }); + + try(ObjectOutputStream cacheOOS = new ObjectOutputStream(Files. + newOutputStream(FileSystems.getDefault().getPath( + System.getProperty("test.classes", "."), testName + ".cache")))) { + cacheOOS.writeObject(cache); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + protected abstract U[] getArray(int size, boolean random); + + protected Collection generate(int size, boolean random) { + Collection col = createEmptyCollection(); + Arrays.stream(getArray(size, random)).forEach(col::add); + return col; + } + + //Predicate, descrption for Predicate + protected abstract Object[] predicateAndDesc(int size); + + //BinaryOperator, descrption for BinaryOperator, stateless + protected abstract Object[][] binaryOperatorAndDesc(); + + //Function, descrption for Function + protected abstract Object[][] functionAndDesc(); + + //IntFunction[], descrption for all IntFunction + protected abstract Object[] validArrayGeneratorAndDesc(); + + //IntFunction[], descrption for IntFunction + protected abstract Object[][] invalidArrayGeneratorAndDesc(); + + //IntFunction a generator from U to int + protected abstract IntFunction createFunction(); + + //ToIntFunction a generator from int to U + protected abstract ToIntFunction intValueFunction(); + + private final Function sizeRoBuilders = sizes -> + Arrays.stream(sizes).boxed().flatMap(size -> + Arrays.asList(true, false).stream().map(random -> generate(size, random)) + ).toArray(); + + //base object based on size, base object will be used when the operation like reduce + protected abstract U[] bases(int size); + + protected Object[] builders() { + return sizeRoBuilders.apply(MEDIUM_DATA_SIZES); + } + + protected Object[] smallSizeBuilders() { + return sizeRoBuilders.apply(SMALL_DATA_SIZES); + } + + //Test only needs Collection, test like find, count, forEach, subStream, + //sorted test need this + protected Iterator collectionData() { + Function, Object[]> objGenerator = data -> new Object[]{ + String.format("%s(%d)", typeObject.getName(), data.size()),data}; + return Arrays.stream(builders()). + map(data -> objGenerator.apply((Collection)data)).iterator(); + } + + //Test only needs Collection and invalid index, test like + // testSubstreamException needs this. + protected Iterator collectionStartEndData() { + List dataList= new ArrayList<>(); + long[][] exceptionStartEnd = new long[][]{ + {-1, 1}, //startInclusive is negative + {1, -1}, //endInclusive is negative + {1, 0} //startInclusive is greater than endExclusive + }; + TripleFunction, Long, Long, Object[]> objGenerator = + (data, start, end) -> new Object[]{String.format("%s(%d), %d, %d", + typeObject.getName(), data.size(), start, end), + data, start, end}; + Arrays.stream(builders()).forEach(data -> { + Arrays.stream(exceptionStartEnd).forEach(startEnd -> { + dataList.add(objGenerator.apply((Collection)data, startEnd[0], + startEnd[1])); + }); + }); + return dataList.iterator(); + } + + //Test needs Collection and one Predicate, tests like collect by + // partition, anyMatch, noneMatch, allMatch needs this + protected Iterator collectionPredicateData() { + List dataList= new ArrayList<>(); + Arrays.stream(builders()).forEach(data -> { + Collection col = (Collection)data; + Object[] predicateAndDesc = predicateAndDesc(col.size()); + Predicate p = (Predicate)predicateAndDesc[0]; + String desc = String.format("%s(%d), %s", typeObject.getName(), + col.size(), (String)predicateAndDesc[1]); + dataList.add(new Object[]{desc, data, p}); + }); + return dataList.iterator(); + } + + //Test needs Collection and two Predicates, test like filter needs this. + public Iterator collectionDualPredicateData() { + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(data -> { + Collection col = (Collection)data; + Object[] predicateAndDesc1 = predicateAndDesc(col.size()); + Object[] predicateAndDesc2 = predicateAndDesc(col.size()); + Predicate p1 = (Predicate)predicateAndDesc1[0]; + Predicate p2 = (Predicate)predicateAndDesc2[0]; + String desc = String.format("%s(%d), %s, %s", typeObject.getName(), + col.size(),(String)predicateAndDesc1[1], + (String)predicateAndDesc2[1]); + dataList.add(new Object[]{desc, col, p1, p2}); + }); + return dataList.iterator(); + } + + //Test needs Collection, U base and and BinaryOperator, stateless, + //test like reduce needs this. + protected Iterator collectionBinaryOpeatorData(){ + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(data -> { + Collection col = (Collection)data; + Arrays.stream(binaryOperatorAndDesc()).forEach((Object[] bpDesc) -> { + BinaryOperator bo = (BinaryOperator)bpDesc[0]; + String boDesc = (String)bpDesc[1]; + boolean stateless = (Boolean)bpDesc[2]; + Arrays.stream(bases(col.size())).forEach(base -> { + dataList.add(new Object[]{String.format("%s(%d), %s, %s, %s", + typeObject.getName(), col.size(), base, + boDesc, stateless), col, base, bo, stateless}); + }); + }); + }); + return dataList.iterator(); + } + + //Test needs Collection, Function, tests like + //collect by groupingBy, max, min, sorted, peek need this + protected Iterator collectionFunctionData(){ + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(data -> { + Collection col = (Collection)data; + Arrays.stream(functionAndDesc()).forEach((Object[] funcDesc) -> { + Function func = (Function)funcDesc[0]; + String desc = (String)funcDesc[1]; + dataList.add(new Object[]{String.format("%s(%d), %s", + typeObject.getName(), col.size(), desc), col, func}); + }); + }); + return dataList.iterator(); + } + + //Test needs Collection, Function keyFunc, Function valueFunc, + //tests like collect map needs this. + //toMap need keep key's identical, using Function.identity() + protected Iterator collectionKeyValueFunctionData(){ + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(data -> { + Collection col = (Collection)data; + Arrays.stream(functionAndDesc()).forEach((Object[] valueFuncDesc) -> { + Function valueFunc = (Function)valueFuncDesc[0]; + String valuedesc = (String)valueFuncDesc[1]; + dataList.add(new Object[]{String.format("%s(%d), %s, %s", + typeObject.getName(), col.size(), + "Function.identity()", valuedesc), col, Function.identity(), + valueFunc}); + }); + }); + return dataList.iterator(); + } + + //testToArray needs Collection, IntFunction[], test like toArray needs + //this. + protected Iterator collectionArrayGeneratorData(){ + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(data -> { + Collection col = (Collection)data; + Object[] validArrayGenerators = validArrayGeneratorAndDesc(); + IntFunction[] generators = (IntFunction[])validArrayGenerators[0]; + String desc = (String)validArrayGenerators[1]; + dataList.add(new Object[]{String.format("%s(%d), %s", + typeObject.getName(), col.size(), desc), col, generators}); + }); + return dataList.iterator(); + } + + //testToArrayException needs Collection, IntFunction, this is for + //testing toArray's ArrayStoreException + public Iterator collectionArrayInvalidGeneratorData(){ + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(data -> { + Collection col = (Collection)data; + Arrays.stream(invalidArrayGeneratorAndDesc()).forEach( + generatorAndDesc -> { + IntFunction generator = (IntFunction)generatorAndDesc[0]; + String desc = (String)generatorAndDesc[1]; + dataList.add(new Object[]{String.format("%s(%d), %s", + typeObject.getName(), col.size(), desc), col, generator}); + }); + }); + return dataList.iterator(); + } + + //Test needs two Collection, operation like concat needs this. + protected Iterator concatCollectionData(){ + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(data1 -> + Arrays.stream(builders()).forEach(data2 -> { + String desc = String.format("%s(%d), %s(%d)", + typeObject.getName(), ((Collection)data1).size(), + typeObject.getName(), ((Collection)data2).size()); + dataList.add(new Object[]{desc, data1, data2}); } + ) + ); + return dataList.iterator(); + } + + //Test like test limit's exception need this + protected Iterator exceptionTestData() { + Collection col = generate(SMALL_DATA_SIZE, false); + return Arrays.stream(new Object[][]{ + {String.format("%s(%d)", typeObject.getName(), col.size()), col}, + }).iterator(); + } + + //Test like distinct needs this. + protected Iterator smallSizeCollectionData() { + List dataList = new ArrayList<>(); + Arrays.stream(smallSizeBuilders()).forEach(data -> { + Collection col = (Collection)data; + dataList.add(new Object[]{String.format("%s(%d)", + typeObject.getName(), col.size()), col}); + }); + return dataList.iterator(); + } + + protected Iterator collectionDataWithLimit() { + List dataList = new ArrayList<>(); + Arrays.stream(builders()).forEach(dataCol -> { + Collection col = (Collection)dataCol; + int withBoundryLimit = rand.nextInt(col.size()); + int beyondBoundryLimit = col.size() + + rand.nextInt(Integer.MAX_VALUE - col.size()); + dataList.add(new Object[]{String.format("%s(%d), %s", + typeObject.getName(), col.size(), withBoundryLimit, + beyondBoundryLimit), col, withBoundryLimit, beyondBoundryLimit}); + }); + return dataList.iterator(); + } + + //Test like test flatMap need this + protected Iterator collectionDataWithSelection() { + List dataList = new ArrayList<>(); + TripleFunction, String, Function>, + Object[]> objectGenerator = (col, str , mapper) -> + new Object[]{String.format("<%s(%d), %s>", typeObject.getName(), + col.size(), str), col, mapper}; + Arrays.stream(smallSizeBuilders()).forEach(data -> { + Collection col = (Collection)data; + flatMappers().forEach((func, msg) -> { + dataList.add(objectGenerator.apply(col, msg, func)); + }); + }); + return dataList.iterator(); + } + + public Comparator getNaturalOrderComparator() { + return naturalOrderComparator; + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/IntStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/IntStreamTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,497 @@ +/* + * 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 + * @summary Basic test for IntStream + * @library /sqeutil + * @(#) IntStreamTest.java + * @author Tristan Yan + * @run testng IntStreamTest + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.OptionalInt; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.IntFunction; +import java.util.function.IntPredicate; +import java.util.function.IntUnaryOperator; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +public class IntStreamTest { + private final static int[] ARRAY_SIZES = {1, 1 << 2, 1 << 4, 1 << 7, 1 << 12}; + + protected enum Selection { EMPTY, SINGLE, TRIANGLE, COPY_64}; + + private final static int[] EMPTY_ARRAY = new int[0]; + + private IntStream streamFor(ParallelType p, int[] array) { + return (p == ParallelType.Parallel) ? Arrays.stream(array).parallel() + : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() : Arrays.stream(array); + } + + private IntStream streamFor(ParallelType p, int[] array, int startIndex, int endIndex) { + return (p == ParallelType.Parallel) ? Arrays.stream(array, startIndex, endIndex).parallel() + : (p == ParallelType.Sequential) ? Arrays.stream(array, startIndex, endIndex).sequential() : + Arrays.stream(array, startIndex, endIndex); + } + + static enum ParallelType { Parallel, Sequential, Default } + + private final static Random rand = new Random(1968721); + + private boolean verifyMatch(int[] array, IntPredicate predicate, boolean checkAll) { + for(int element : array) { + if(predicate.test(element) != checkAll) + return !checkAll; + } + return checkAll; + } + + private final ParallelType parallelType; + + private IntStreamTest(final ParallelType parallelType) { + this.parallelType = parallelType; + } + + @Factory + public static Object[] create(){ + return Arrays.stream(ParallelType.values()).map(p -> new IntStreamTest(p)).toArray(); + } + + final static Object[][] arrays = Arrays.stream(ARRAY_SIZES).mapToObj(size -> + new Object[]{IntStream.range(0, size).toArray()}).toArray(Object[][]::new); + + @DataProvider + public static Iterator intArrays(){ + ArrayList list = new ArrayList<>(); + String format = ""; + Arrays.stream(arrays).forEach(data -> { + int[] array = (int[])data[0]; + list.add(new Object[]{String.format(format, array.length), array}); + }); + return list.iterator(); + } + + @DataProvider + public static Iterator intArraysWithSkipLimit(){ + ArrayList list = new ArrayList<>(); + String format = ""; + Arrays.stream(arrays).forEach(data -> { + int[] array = (int[])data[0]; + list.add(new Object[]{String.format(format, array.length, 0, array.length), array, 0, array.length}); + list.add(new Object[]{String.format(format, array.length, array.length / 3, array.length /2), array, array.length / 3, array.length /2}); + list.add(new Object[]{String.format(format, array.length, array.length /2, array.length + 1), array, array.length /2, array.length + 1}); + }); + return list.iterator(); + } + + @DataProvider + public static Iterator intArraysWithLimit(){ + ArrayList list = new ArrayList<>(); + String format = ""; + Arrays.stream(arrays).forEach(data -> { + int[] array = (int[])data[0]; + list.add(new Object[]{String.format(format, array.length, 0), array, 0}); + list.add(new Object[]{String.format(format, array.length, array.length / 3), array, array.length / 3}); + list.add(new Object[]{String.format(format, array.length, array.length /2), array, array.length /2}); + list.add(new Object[]{String.format(format, array.length, array.length + 1), array, array.length + 1}); + }); + return list.iterator(); + } + + @DataProvider + public static Iterator intArraysWithPredicate(){ + ArrayList list = new ArrayList<>(); + String format = ""; + Arrays.stream(arrays).forEach(data -> { + int[] array = (int[])data[0]; + list.add(new Object[]{String.format(format, array.length, "i -> i < " + array.length / 2), array, (IntPredicate) i -> i < array.length / 2}); + list.add(new Object[]{String.format(format, array.length, "i -> i < 0"), array, (IntPredicate) i -> i < 0}); + list.add(new Object[]{String.format(format, array.length, "i -> i >= 0"), array, (IntPredicate) i -> i >= 0}); + list.add(new Object[]{String.format(format, array.length, "i -> i >= " + array.length), array, (IntPredicate) i -> i >= array.length}); + }); + return list.iterator(); + } + + @DataProvider + public static Iterator intArraysWithOperator(){ + ArrayList list = new ArrayList<>(); + String format = ""; + Arrays.stream(arrays).forEach(data -> { + int[] array = (int[])data[0]; + list.add(new Object[]{String.format(format, array.length, "i -> i + 1"), array, (IntUnaryOperator)i -> i + 1}); + list.add(new Object[]{String.format(format, array.length, " i -> i << 2"), array, (IntUnaryOperator) i -> i << 2}); + list.add(new Object[]{String.format(format, array.length, "Math::abs"), array, (IntUnaryOperator)Math::abs}); + }); + return list.iterator(); + } + + @DataProvider + public static Iterator intArraysWithSelection(){ + ArrayList list = new ArrayList<>(); + String format = ""; + Arrays.stream(arrays).forEach(data -> { + int[] array = (int[])data[0]; + Arrays.stream(Selection.values()).forEach(selection -> + list.add(new Object[]{String.format(format, array.length, selection), array, selection})); + }); + return list.iterator(); + } + + @Test(dataProvider="intArraysWithPredicate") + public void testXxxMatch(String desc, int[] array, IntPredicate predicate) { + assertEquals(streamFor(parallelType, array) .allMatch(predicate), verifyMatch(array, predicate, true)); + assertEquals(streamFor(parallelType, array) .anyMatch(predicate), verifyMatch(array, predicate, false)); + assertEquals(streamFor(parallelType, array) .noneMatch(predicate), verifyMatch(array, predicate.negate(), true)); + + assertEquals(streamFor(parallelType, array, 0, array.length).allMatch(predicate), + streamFor(parallelType, array).allMatch(predicate)); + assertEquals(streamFor(parallelType, array, 0, array.length).anyMatch(predicate), + streamFor(parallelType, array).anyMatch(predicate)); + assertEquals(streamFor(parallelType, array, 0, array.length).noneMatch(predicate), + streamFor(parallelType, array).noneMatch(predicate)); + + assertTrue(streamFor(parallelType, EMPTY_ARRAY).allMatch(predicate)); + assertFalse(streamFor(parallelType, EMPTY_ARRAY).anyMatch(predicate)); + assertTrue(streamFor(parallelType, EMPTY_ARRAY).noneMatch(predicate)); + } + + @Test(dataProvider="intArrays") + public void testAveargeAndSum(String desc, int[] array) throws Exception { + //for calculate average, we need bigger scale data type calculate total, this could prevent int overflow + double total = 0; + int intTotal = 0; + for(int index = 0; index < array.length; index++) { + total += array[index]; + intTotal += array[index]; + } + assertEquals(streamFor(parallelType, array).average(). getAsDouble(), total / array.length); + assertEquals(streamFor(parallelType, array).sum(), intTotal); + + assertEquals(streamFor(parallelType, array).average(), streamFor(parallelType, array, 0, array.length).average()); + assertEquals(streamFor(parallelType, array).sum(), streamFor(parallelType, array, 0, array.length).sum()); + + assertFalse(streamFor(parallelType, EMPTY_ARRAY).average().isPresent()); + assertEquals(streamFor(parallelType, EMPTY_ARRAY).sum(), 0); + } + + @Test(dataProvider="intArrays") + public void testBoxed(String desc, int[] array) throws Exception { + Object[] boxedArr1 = streamFor(parallelType, array).boxed().toArray(); + Object[] boxedArr2 = streamFor(parallelType, array).mapToObj(Integer::new).toArray(); + assertEquals(boxedArr1, boxedArr2); + + assertEquals(streamFor(parallelType, EMPTY_ARRAY).boxed().count(), 0); + } + + @Test(dataProvider="intArraysWithPredicate") + public void testFilter(String desc, int[] array/*, int startIndex, int endIndex*/, IntPredicate predicate) throws Exception{ + assertTrue(verifyMatch(streamFor(parallelType, array).filter(predicate).toArray(), predicate, true)); + assertEquals(streamFor(parallelType, array, 0, array.length).filter(predicate).toArray(), + streamFor(parallelType, array).filter(predicate).toArray()); + + assertEquals(streamFor(parallelType, EMPTY_ARRAY).filter(predicate).count(), 0); + } + + @Test(dataProvider="intArrays") + public void testFind(String desc, int[] array) throws Exception{ + IntStream streamFindAny = streamFor(parallelType, array); + OptionalInt opAny = streamFindAny.findAny(); + OptionalInt opFirst = streamFor(parallelType, array).findFirst(); + assertTrue(opAny.isPresent()); + assertTrue(opFirst.isPresent()); + if(!streamFindAny.isParallel()) + assertEquals(opAny, opFirst); + + assertFalse(streamFor(parallelType, EMPTY_ARRAY).findAny().isPresent()); + assertFalse(streamFor(parallelType, EMPTY_ARRAY).findFirst().isPresent()); + } + + @Test(dataProvider="intArrays") + public void testForEach(String desc, int[] array) throws Exception { + IntStream stream = streamFor(parallelType, array); + Arrays.parallelSort(array); + stream.forEach(t -> { assertTrue(Arrays.binarySearch(array, t) >= 0); }); + + ArrayList touch = new ArrayList<>(); + streamFor(parallelType, EMPTY_ARRAY).forEach(t -> { touch.add(t); }); + assertTrue(touch.isEmpty()); + } + + @Test(dataProvider="intArraysWithLimit") + public void testLimit(String desc, int[] array, int limit) { + if(limit > array.length) + assertEquals(streamFor(parallelType, array).limit(limit).count(), array.length); + else + assertEquals(streamFor(parallelType, array).limit(limit).count(), limit); + } + + @Test(dataProvider="intArraysWithSelection") + public void testFlatMap(String desc, int[] array, Selection selection) { + int[] flatArray = streamFor(parallelType, array).flatMap(genIntFlatMapper(selection)).sorted().toArray(); + verifyMultifunction(array, flatArray, selection); + + assertEquals(streamFor(parallelType, EMPTY_ARRAY).flatMap(genIntFlatMapper(selection)).toArray(),EMPTY_ARRAY); + } + + @Test(dataProvider="intArraysWithOperator") + public void testMap(String desc, int[] array, IntUnaryOperator mapper) { + int[] mapped = streamFor(parallelType, array).map(mapper).toArray(); + for(int index = 0; index < array.length; index++) { + assertEquals(mapped[index], mapper.applyAsInt(array[index])); + } + + IntFunction objMapper = i -> new Integer(mapper.applyAsInt(i)); + Object[] objArray1 = streamFor(parallelType, array).map(mapper).boxed().toArray(); + Object[] objArray2 = streamFor(parallelType, array).mapToObj(objMapper).toArray(); + assertEquals(objArray1, objArray2); + } + + @Test(dataProvider="intArrays") + public void testMaxAndMin(String desc, int[] array) { + boolean[] maxOrMin = {true, false}; + for(boolean testMax : maxOrMin) { + OptionalInt testOpt = testMax ? streamFor(parallelType, array).max() + : streamFor(parallelType, array).min(); + assertEquals(testOpt.getAsInt(), getMaxOrMin(array, testMax)); + assertEquals(testOpt.getAsInt(), getMaxOrMinWithReduceOp(array, testMax)); + assertEquals(testOpt.getAsInt(), getMaxOrMinWithReduceOpAndBase(array, testMax)); + + assertFalse(testMax ? streamFor(parallelType, EMPTY_ARRAY).max().isPresent() + : streamFor(parallelType, EMPTY_ARRAY).min().isPresent()); + } + } + + @Test(dataProvider="intArrays") + public void testSpliterator(String desc, int[] array) { + int[] calArrParallel = StreamSupport.intStream(streamFor(parallelType, array).spliterator(), true).toArray(); + int[] calArrSequential = StreamSupport.intStream(streamFor(parallelType, array).spliterator(), false).toArray(); + for(int index = 0; index < array.length; index++) { + assertEquals(array[index], calArrParallel[index]); + assertEquals(array[index], calArrSequential[index]); + } + } + + @Test(dataProvider="intArrays") + public void testReduceWithBase(String desc, int[] array) { + if(parallelType == ParallelType.Parallel) + return; + int base = rand.nextInt(); + int oiPlus = streamFor(parallelType, array).reduce(base, + LambdaUtilities.addIntBinaryOperator()); + int total = 0; + for(int index = 0; index < array.length; index++) + total += array[index]; + assertEquals(oiPlus, total + base); + + int oiSubtract = streamFor(parallelType, array).reduce(base, + LambdaUtilities.subIntBinaryOperator()); + int subTotal = base; + for(int index = 0; index < array.length; index++) + subTotal -= array[index]; + assertEquals(oiSubtract, subTotal); + + int emptyByBase = streamFor(parallelType, EMPTY_ARRAY).reduce(base, rand.nextBoolean() ? + LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + assertEquals(emptyByBase, base); + } + + @Test(dataProvider="intArrays") + public void testReduceWithoutBase(String desc, int[] array) { + OptionalInt oiPlus = streamFor(parallelType, array).reduce(Integer::sum); + assertTrue(oiPlus.isPresent()); + int total = 0; + for(int index = 0; index < array.length; index++) + total += array[index]; + assertTrue(oiPlus.getAsInt() == total); + + //Can't predict Parallel Substract reduce result, give up testing on + //parallel substract test + if(parallelType == ParallelType.Parallel) + return; + + OptionalInt oiSubtract = streamFor(parallelType, array). + reduce(LambdaUtilities.subIntBinaryOperator()); + assertTrue(oiSubtract.isPresent()); + int subTotal = array[0]; + for(int index = 1; index < array.length; index++) + subTotal -= array[index]; + assertEquals(oiSubtract.getAsInt(), subTotal); + + OptionalInt emptyOp = streamFor(parallelType, EMPTY_ARRAY). + reduce(rand.nextBoolean() ? LambdaUtilities.addIntBinaryOperator() : + LambdaUtilities.subIntBinaryOperator()); + assertFalse(emptyOp.isPresent()); + } + + @Test(dataProvider="intArraysWithSkipLimit") + public void testSubstream(String desc, int[] array, int skip, int limit) { + assert(limit >= skip); + int[] toArray = streamFor(parallelType, array).skip(skip).limit(limit).toArray(); + if(skip < array.length) { + if(limit < array.length) { + verifySlice(array, toArray, skip, limit); + } else { + verifySlice(array, toArray, skip, array.length); + } + } + else { + assertEquals(toArray.length, 0); + } + assertEquals(streamFor(parallelType, EMPTY_ARRAY).skip(skip).limit(limit).count(), 0); + + } + + @Test(dataProvider="intArrays") + public void testSorted(String desc, int[] array){ + checkSorted(streamFor(parallelType, array).sorted().toArray(), Comparator.naturalOrder()); + assertEquals(streamFor(parallelType, array).sorted().toArray(), + streamFor(parallelType, array, 0, array.length).sorted().toArray()); + assertEquals(streamFor(parallelType, EMPTY_ARRAY).sorted().toArray().length, 0); + } + + @Test(dataProvider="intArrays") + public void testPeek(String desc, int[] array){ + AtomicInteger ai1 = new AtomicInteger(0); + IntStream stream = streamFor(parallelType, array).peek(LambdaUtilities.addIntConsumer(ai1)); + //Lazy operation checking + assertEquals(ai1.get(), 0); + int sum = stream.sum(); + assertEquals(ai1.get(), sum); + + assertEquals(streamFor(parallelType,EMPTY_ARRAY).peek(LambdaUtilities.addIntConsumer(ai1)).count(), 0); + } + + @Test(dataProvider="intArrays") + public void testToArray(String desc, int[] array){ + assertEquals(streamFor(parallelType, array).toArray(), array); + assertEquals(streamFor(parallelType, array, 0, array.length).toArray(), array); + assertEquals(streamFor(parallelType, EMPTY_ARRAY).toArray().length, 0); + } + + @Test(dataProvider="intArrays") + public void testDistrinct(String desc, int[] array){ + int[] toArray = streamFor(parallelType, array).flatMap(genIntFlatMapper(Selection.COPY_64)).distinct().toArray(); + assertEquals(toArray, array); + + assertEquals(streamFor(parallelType, EMPTY_ARRAY).flatMap(genIntFlatMapper(Selection.COPY_64)). + distinct().toArray().length, 0); + } + + private void verifyMultifunction(int[] orig, int[] result, Selection selection) { + switch(selection) { + case EMPTY: + assertEquals(result.length, 0); + break; + case SINGLE: + assertEquals(orig, result); + break; + case TRIANGLE: + int expectedSize = orig.length * (orig.length + 1) / 2; + int[] expected = IntStream.range(0, expectedSize).toArray(); + assertEquals(result, expected); + break; + case COPY_64: + Stream sToBeConcated = Stream.empty(); + for(int current : orig) { + sToBeConcated = Stream.concat(sToBeConcated, + IntStream.generate(() -> current). + limit(1 << 6).boxed()); + } + assertEquals(sToBeConcated.toArray(), result); + break; + default: + throw new RuntimeException("Invalid selection " + selection); + } + } + + private int getMaxOrMin(int[] array, boolean isMax) { + assert(array.length > 0); + int pos = 0; + int choosen = array[pos++]; + while(pos < array.length) { + int current = array[pos++]; + if((choosen < current) == isMax) choosen = current; + } + return choosen; + } + + private int getMaxOrMinWithReduceOp(int[] array, boolean isMax) { + assert(array.length > 0); + OptionalInt choosen = Arrays.stream(array).reduce(isMax ? + LambdaUtilities.maxIntBinaryOperator() : + LambdaUtilities.minIntBinaryOperator()); + return choosen.getAsInt(); + } + + private int getMaxOrMinWithReduceOpAndBase(int[] array, boolean isMax) { + assert(array.length > 0); + int choosen = Arrays.stream(array).reduce(array[0], isMax ? + LambdaUtilities.maxIntBinaryOperator() : + LambdaUtilities.minIntBinaryOperator()); + return choosen; + } + + private void verifySlice(int[] array, int[] toArray, int skip, int limit){ + for(int index = skip; index < array.length && index < limit; index++) + assertTrue(array[index] <= toArray[index - skip]); + } + + private void checkSorted(int[] array, Comparator comp){ + assert(array.length > 0); + for(int index = 0; index < array.length - 1; index++) + assertTrue(comp.compare(array[index] , array[index + 1]) <= 0); + } + + private static IntFunction genIntFlatMapper(Selection selection) { + switch (selection) { + case EMPTY: + //Generate a empty collection + return e -> IntStream.empty(); + case SINGLE: + return e -> Arrays.stream(new int[]{ e }); + case TRIANGLE: + //Generate a triangle has different value + return e -> IntStream.range(0, e + 1).map(i -> e * (e + 1) / 2 + i); + case COPY_64: + //Generate 64 folded flat map + return e -> IntStream.range(0, 1 << 6).map(i -> e); + default: + throw new RuntimeException("Invalid selection " + selection); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/IntegerReduceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/IntegerReduceTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,84 @@ +/* + * 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.math.BigDecimal; +import java.util.Collection; +import java.util.IntSummaryStatistics; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class IntegerReduceTest> extends + OperatorTest { + public IntegerReduceTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionFunctionData") + public void testCollectSummarizingInt(String desc, Collection col, + Function mapFunc) { + //test summarizingInt + IntSummaryStatistics iss = streamFor(col).collect( + Collectors.summarizingInt(Integer::intValue)); + assertEquals(iss.getCount(), col.size()); + assertEquals(iss.getMax(), streamFor(col). + max(test.getNaturalOrderComparator()).get().intValue()); + assertEquals(iss.getMin(), streamFor(col). + min(test.getNaturalOrderComparator()).get().intValue()); + assertEquals(iss.getSum(), streamFor(col). + mapToLong(Integer::longValue).sum()); + } + + + @Test(dataProvider="collectionData") + public void testReduceIdentitiyWithoutBase(String desc, + Collection col) { + Optional total = streamFor(col).reduce( + LambdaUtilities.addIntegerBinaryOperator()); + double avg = (double) total.get().intValue() / col.size(); + BigDecimal deviationSquare = streamFor(col).reduce(new BigDecimal(0.0), + LambdaUtilities.deviationSequareFunction(avg), + LambdaUtilities.addBigDecimalBinaryOperator()); + double stdev = deviationSquare.doubleValue() / col.size(); + + int totalExpected = 0; + for (Integer aCol : col) + totalExpected += aCol; + assertEquals(totalExpected, total.get().intValue()); + double avgExpected = (double)totalExpected / col.size(); + assertEquals(avgExpected, avg); + + BigDecimal deviationSquareExpected = new BigDecimal(0.0); + for (Integer aCol : col) + deviationSquareExpected = deviationSquareExpected + .add(new BigDecimal(avg - aCol).pow(2)); + assertEquals(deviationSquare, deviationSquareExpected); + + double stddvExpected + = deviationSquareExpected.doubleValue() / col.size(); + assertEquals(stddvExpected, stdev); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/IntegerStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/IntegerStreamTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,173 @@ +/* + * 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 + * @summary Basic test for Stream + * @library /sqeutil + * @(#) IntegerStreamTest.java + * @author Tristan Yan + * @run testng IntegerStreamTest + */ + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.IntSummaryStatistics; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +public class IntegerStreamTest> extends + GenericStreamTest> { + private static HashMap> cache = new HashMap<>(); + + static { + Function> randomToArrays = random -> + random ? ( i -> rand.ints().limit(i).boxed().toArray(Integer[]::new)) : + (i -> IntStream.rangeClosed(1, i).boxed().toArray(Integer[]::new)); + initCache(cache, randomToArrays, "IntegerStreamTest"); + } + + @Factory + public static Object[] create(){ + TripleFunction + supplierWithInitSize = + IntegerStreamTest>::new; + BiFunction supplier = + IntegerStreamTest>::new; + List tests = new ArrayList(); + Arrays.stream(ParallelType.values()).forEach(parallelType -> { + Arrays.stream(defaultConstructorClazz).forEach( clazz -> + tests.add(new IntegerReduceTest(supplier.apply( + clazz, parallelType)))); + Arrays.stream(capacityConstructorClazz).forEach( clazz -> + tests.add(new IntegerReduceTest(supplierWithInitSize.apply( + clazz, parallelType,MEDIUM_DATA_SIZE)))); + Arrays.stream(defaultComparableConstructorClazz).forEach(clazz -> { + tests.add(new IntegerReduceTest(supplier.apply(clazz, + parallelType)));}); + Arrays.stream(capacityComparableConstructorClazz).forEach(clazz -> { + tests.add(new IntegerReduceTest(supplierWithInitSize.apply(clazz, + parallelType, MEDIUM_DATA_SIZE)));}); + }); + tests.addAll(Arrays.asList(GenericStreamTest.create( + supplierWithInitSize, supplier, true))); + return tests.toArray(); + } + + private IntegerStreamTest(Class clazz, + ParallelType parallelType, int initSize) { + super(clazz, parallelType, Comparator.naturalOrder(), initSize); + } + + private IntegerStreamTest(Class clazz, + ParallelType parallelType) { + super(clazz, parallelType, Comparator.naturalOrder()); + } + + @Override + public String getTestName() { + return typeObject.getName() + ""; + } + + @Override + protected Integer[] getArray(int size, boolean random){ + return cache.get(random).get(size); + } + + @Override + protected Object[] predicateAndDesc(int size){ + boolean isUp = rand.nextBoolean(); + int limit = rand.nextInt(size); + return new Object[]{ LambdaUtilities.randomIntegerPredicate(isUp, limit), + String.format("i -> i %s %d", isUp ? ">=" : "<", limit)}; + } + + //BinaryOperator, descrption, stateless + @Override + protected Object[][] binaryOperatorAndDesc() { + return new Object[][]{ + {(BinaryOperator)Integer::sum, "Integer::sum", false}, + {(BinaryOperator)Integer::max, "Integer::max", true}, + {(BinaryOperator)Integer::min, "Integer::min", true}, + }; + } + + //Function and descrption for Function + @Override + protected Object[][] functionAndDesc(){ + Function toStr = String::valueOf; + return new Object[][]{ + {(Function)i -> i++, "i -> i++"}, + {toStr, "String::valueOf"}, + }; + } + + @Override + protected Integer[] bases(int size){ + return new Integer[]{-1, 0, 1, size /2, size - 1, size, size + 1}; + } + + @Override + protected Object[] validArrayGeneratorAndDesc() { + return new Object[]{ + new IntFunction[]{ + (IntFunction)Integer[]::new, + (IntFunction)Number[]::new}, + "{Integer[]::new, Number[]::new}" + }; + } + + @Override + protected Object[][] invalidArrayGeneratorAndDesc() { + return new Object[][]{ + {(IntFunction)Double[]::new, "Double[]::new"}, + {(IntFunction)String[]::new, "String[]::new"}, + }; + } + + @Override + protected IntFunction createFunction() { + return Integer::valueOf; + } + + @Override + protected ToIntFunction intValueFunction() { + return Integer::intValue; + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/LimitTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/LimitTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,54 @@ +/* + * 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.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class LimitTest> extends OperatorTest{ + public LimitTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionDataWithLimit") + public void testLimit(String desc, Collection col, int withBoundryLimit, int beyondBoundryLimit) { + Collection resultWithBoundary = streamFor(col).limit(withBoundryLimit) + .collect(Collectors.>toCollection(LinkedList::new)); + assertEquals(resultWithBoundary.size(), withBoundryLimit); + + Collection resultBeyondBoundary = streamFor(col).limit(beyondBoundryLimit) + .collect(Collectors.>toCollection(LinkedList::new)); + assertEquals(col.size(), resultBeyondBoundary.size()); + + assertEquals(streamFor(createEmptyCollection()).limit(withBoundryLimit).count(), 0); + assertEquals(streamFor(createEmptyCollection()).limit(beyondBoundryLimit).count(), 0); + } + + @Test(dataProvider="exceptionTestData",expectedExceptions = IllegalArgumentException.class) + public void testLimitException(String desc, Collection col){ + streamFor(col).limit(-1).toArray(); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/MatchTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/MatchTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,49 @@ +/* + * 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.util.Collection; +import java.util.function.Predicate; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; + +public class MatchTest> extends OperatorTest{ + public MatchTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionPredicateData") + public void testXxxMatch(String desc, Collection col, Predicate predicate) { + assertEquals(streamFor(col).allMatch(predicate), + verifyMatch(col, predicate, true)); + assertEquals(streamFor(col).anyMatch(predicate), + verifyMatch(col, predicate, false)); + assertEquals(streamFor(col).noneMatch(predicate), + verifyMatch(col, predicate.negate(), true)); + + assertTrue(streamFor(createEmptyCollection()).allMatch(predicate)); + assertFalse(streamFor(createEmptyCollection()).anyMatch(predicate)); + assertTrue(streamFor(createEmptyCollection()).noneMatch(predicate)); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/MaxAndMinTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/MaxAndMinTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,102 @@ +/* + * 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.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class MaxAndMinTest> extends OperatorTest{ + public MaxAndMinTest(GenericStreamTest test) { + super(test); + } + + TripleFunction,Comparator,Boolean,U> maxMinFunctions[] = new TripleFunction[] { + (TripleFunction,Comparator,Boolean,U>) ( + (col, c, isMax) -> { + assert(!col.isEmpty()); + Iterator it = col.iterator(); + U choosen = it.next(); + while(it.hasNext()) { + U next = it.next(); + if (!(c.compare(choosen, next) < 0 ^ isMax)) choosen = next; + } + return choosen; + }), + (TripleFunction,Comparator,Boolean,U>) ( + (col, c, isMax) -> { + assert(!col.isEmpty()); + U choosen = isMax ? streamFor(col).collect(Collectors.maxBy(c)).get() : + streamFor(col).collect(Collectors.minBy(c)).get(); + return choosen; + }), + (TripleFunction,Comparator,Boolean,U>) ( + (col, c, isMax) -> { + assert (!col.isEmpty()); + Optional choosen = col.stream().reduce(isMax ? + LambdaUtilities.maxGenericBinaryOperator(c) : + LambdaUtilities.minGenericBinaryOperator(c) ); + assert(choosen.isPresent()); + return choosen.get(); + }), + (TripleFunction,Comparator,Boolean,U>) ( + (col, c, isMax) -> { + assert (!col.isEmpty()); + U any = col.iterator().next(); + U choosen = col.stream().reduce(any, + isMax ? LambdaUtilities.maxGenericFunction(c) : LambdaUtilities.minGenericFunction(c), + isMax ? LambdaUtilities.maxGenericBinaryOperator(c) : LambdaUtilities.minGenericBinaryOperator(c)); + return choosen; + }), + (TripleFunction,Comparator,Boolean,U>) ( + (col, c, isMax) -> { + assert (!col.isEmpty()); + U choosen = col.stream().collect(Collectors.reducing(isMax ? + LambdaUtilities.maxGenericBinaryOperator(c) : + LambdaUtilities.minGenericBinaryOperator(c))).get(); + return choosen; + }), + }; + + @Test(dataProvider="collectionFunctionData") + public void testMaxAndMin(String desc, Collection col, Function mapFunc) { + Comparator comp = Comparator.comparing(mapFunc); + Arrays.asList(true, false).stream().peek((testMax) -> { + Optional optional = testMax ? streamFor(col).max(comp) : streamFor(col).min(comp); + assertTrue(optional.isPresent()); + for(BaseStreamTest.TripleFunction,Comparator,Boolean,U> func : maxMinFunctions) { + assertEquals(comp.compare(optional.get(), func.apply(col, comp, testMax)), 0); + } + }).forEach((testMax) -> { + if(testMax) + assertFalse(streamFor(createEmptyCollection()).max(comp).isPresent()); + else + assertFalse(streamFor(createEmptyCollection()).min(comp).isPresent()); + }); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/OperatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/OperatorTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,252 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.DataProvider; + +public class OperatorTest> extends BaseStreamTest { + protected final GenericStreamTest test; + + public OperatorTest(GenericStreamTest test) { + super(test.parallelType); + this.test = test; + } + + protected Stream streamFor(Collection c1) { + return (test.getParallelType() == BaseStreamTest.ParallelType.Parallel) ? + c1.parallelStream(): (test.getParallelType() == BaseStreamTest.ParallelType.Sequential) + ? c1.parallelStream().sequential() : c1.stream(); + } + + @DataProvider + protected Iterator collectionArrayGeneratorData(){ + return test.collectionArrayGeneratorData(); + } + @DataProvider + protected Iterator collectionArrayInvalidGeneratorData(){ + return test.collectionArrayInvalidGeneratorData(); + } + @DataProvider + protected Iterator collectionBinaryOpeatorData(){ + return test.collectionBinaryOpeatorData(); + } + @DataProvider + protected Iterator collectionData() { + return test.collectionData(); + } + @DataProvider + protected Iterator collectionDataWithLimit() { + return test.collectionDataWithLimit(); + } + @DataProvider + protected Iterator collectionDataWithSelection() { + return test.collectionDataWithSelection(); + } + @DataProvider + public Iterator collectionDualPredicateData() { + return test.collectionDualPredicateData(); + } + @DataProvider + protected Iterator collectionFunctionData(){ + return test.collectionFunctionData(); + } + @DataProvider + protected Iterator collectionKeyValueFunctionData(){ + return test.collectionKeyValueFunctionData(); + } + @DataProvider + protected Iterator collectionPredicateData() { + return test.collectionPredicateData(); + } + @DataProvider + protected Iterator collectionStartEndData() { + return test.collectionStartEndData(); + } + @DataProvider + protected Iterator concatCollectionData(){ + return test.concatCollectionData(); + } + @DataProvider + protected Iterator exceptionTestData() { + return test.exceptionTestData(); + } + + protected static void assertEqualContents(Collection result1, + Collection result2, Comparator comparator) { + assertEquals(result1.size(), result2.size()); + ArrayList a = new ArrayList<>(result1); + ArrayList b = new ArrayList<>(result2); + Collections.sort(a, comparator); + Collections.sort(b, comparator); + + for(int i = 0; i < result1.size(); i++) + assertEquals(comparator.compare(a.get(i), b.get(i)), 0); + } + + public Collection createEmptyCollection(){ + return test.createEmptyCollection(); + } + + protected void verifySlice(Collection col, Collection subL, int skip, int limit, boolean ordered) { + int toIndex = skip + limit < col.size() ? skip + limit : col.size(); + if (ordered) { + assertEquals(new ArrayList(col).subList(skip, toIndex), subL); + } else { + // Unordered: verify that all items from the slice are + // present in the original collection + assertTrue(col.containsAll(subL)); + assertEquals(subL.size(), toIndex - skip); + } + } + + protected void verifyFlatMap(Collection orig, Collection result, Function> mapper) { + Collection expected = orig.stream().map(mapper::apply).reduce(Stream::concat). + get().collect(Collectors.toList()); + assertEqualContents(result, expected, test.getNaturalOrderComparator()); + } + + protected boolean verifyMatch(Collection col, Predicate predicate, boolean checkAll) { + for(U current : col) { + if (checkAll ^ predicate.test(current) ) + return !checkAll; + } + return checkAll; + } + + protected void verifyAfterMap(Collection origCol, Object[] result, Function mapFunc) { + int index = 0; + assertEquals(origCol.size(), result.length); + for(U element : origCol) + assertEquals(mapFunc.apply(element), result[index++]); + } + static enum GenericOperatorType{ + CONCATENATE{ + @Override + Function getConstructor() { + return ConcatTest::new; + } + }, + COLLECT{ + @Override + Function getConstructor() { + return CollectTest::new; + } + }, + COUNT{ + @Override + Function getConstructor() { + return CountTest::new; + } + }, + DISTINCT{ + @Override + Function getConstructor() { + return DistinctTest::new; + } + }, + FILTER { + @Override + Function getConstructor() { + return FilterTest::new; + } + }, + FIND{ + @Override + Function getConstructor() { + return FindTest::new; + } + }, + FOREACH{ + @Override + Function getConstructor() { + return ForEachTest::new; + } + }, + FLATMAP{ + @Override + Function getConstructor() { + return FlatMapTest::new; + } + }, + LIMIT{ + @Override + Function getConstructor() { + return LimitTest::new; + } + }, + MAX_MIN{ + @Override + Function getConstructor() { + return MaxAndMinTest::new; + } + }, + MATCH{ + @Override + Function getConstructor() { + return MatchTest::new; + } + }, + PEEK{ + @Override + Function getConstructor() { + return PeekTest::new; + } + }, + REDUCE{ + @Override + Function getConstructor() { + return ReduceTest::new; + } + }, + SORTED{ + @Override + Function getConstructor() { + return SortedTest::new; + } + }, + SUBSTREAM{ + @Override + Function getConstructor() { + return SubstreamTest::new; + } + }, + TOARRAY{ + @Override + Function getConstructor() { + return ToArrayTest::new; + } + }; + + abstract Function getConstructor(); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/PeekTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/PeekTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,52 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Stream; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; + +public class PeekTest> extends OperatorTest{ + public PeekTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionFunctionData") + public void testPeek(String desc, Collection col, Function mapFunc) { + //Note ArrayList is not a concurrent data type, if we don't set initial + //size, we could get AIOOBE + List peekList = new ArrayList<>(col.size()); + Stream peekedStream = streamFor(col).peek(peekList::add); + //Lasiness check for peek + assertTrue(peekList.isEmpty()); + Object[] result = peekedStream.map(mapFunc).toArray(); + verifyAfterMap(col, result, mapFunc); + + List emptyList = new ArrayList<>(); + assertEquals(streamFor(createEmptyCollection()).peek(emptyList::add).count(), 0); + assertTrue(emptyList.isEmpty()); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/ReduceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/ReduceTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,59 @@ +/* + * 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.math.BigDecimal; +import java.util.Collection; +import java.util.Iterator; +import java.util.Optional; +import java.util.function.BinaryOperator; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class ReduceTest> extends OperatorTest{ + public ReduceTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionBinaryOpeatorData") + public void testReduce(String desc, Collection col, U base, + BinaryOperator op, boolean stateless) { + Optional reduceResult = streamFor(col).reduce( op); + assertTrue(reduceResult.isPresent()); + Iterator iter = col.iterator(); + U expected = iter.next(); + while(iter.hasNext()) + expected = op.apply(expected, iter.next()); + assertEquals(reduceResult.get(), expected); + + assertEquals(streamFor(createEmptyCollection()).reduce(base,op), base); + assertFalse(streamFor(createEmptyCollection()).reduce(op).isPresent()); + + if(stateless || !streamFor(col).isParallel()) { + U reduceWithBaseResult = streamFor(col).reduce(base, op); + U expectedWithBase = base; + for(U aCol : col) + expectedWithBase = op.apply(expectedWithBase, aCol); + assertEquals(reduceWithBaseResult, expectedWithBase); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/SortedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/SortedTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,52 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class SortedTest> extends OperatorTest{ + public SortedTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionFunctionData") + public void testSorted(String desc, Collection col, + Function mapFunc) { + //SortedSet instance's stream can't be reordered, we use ArrayList to do + //reorder + Comparator comp = Comparator.comparing(mapFunc); + List sorted = new ArrayList<>(col); + List reversed = streamFor(col).sorted(comp).collect(Collectors.toList()); + Collections.sort(sorted, comp); + assertEquals(sorted, reversed); + + assertEquals(streamFor(createEmptyCollection()).sorted(comp).count(), 0); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/SortedTestForCompable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/SortedTestForCompable.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,49 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class SortedTestForCompable> + extends OperatorTest{ + public SortedTestForCompable(GenericStreamTest test) { + super(test); + } + + //Note non-Comparable U need override this method + @Test(dataProvider="collectionData") + public void testSortedSpecial(String desc, Collection col) { + // SortedSet instance's stream can't be reordered, we use ArrayList to do reorder + List sorted = new ArrayList<>(col); + List reversed = streamFor(col).sorted().collect(Collectors.toList()); + Collections.sort(sorted, test.getNaturalOrderComparator()); + assertEquals(sorted, reversed); + + assertEquals(streamFor(createEmptyCollection()).sorted().count(), 0); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/SortedTestForNonCompable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/SortedTestForNonCompable.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,40 @@ +/* + * 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.util.Collection; +import org.testng.annotations.Test; + +public class SortedTestForNonCompable> + extends OperatorTest{ + public SortedTestForNonCompable(GenericStreamTest test) { + super(test); + } + + //StringBuilder is not Comparable + //Not single element stream won't throw ClassCastException + @Test(dataProvider="exceptionTestData", expectedExceptions = ClassCastException.class) + public void testSortedSpecial(String desc, Collection col) { + streamFor(col).sorted().findFirst(); + System.out.println(col.size()); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/StringBuilderSpecialTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/StringBuilderSpecialTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,48 @@ +/* + * 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.util.Collection; +import java.util.function.Function; +import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class StringBuilderSpecialTest> + extends OperatorTest { + public StringBuilderSpecialTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionFunctionData") + public void testCollectJoining(String desc, Collection col, + Function mapFunc) { + //test joining + String joined = streamFor(col).collect(Collectors.joining()); + int pos = 0; + for(StringBuilder sb : col) { + String toString = sb.toString(); + assertEquals(joined.substring(pos, pos + toString.length()), toString); + pos += toString.length(); + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/StringBuilderStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/StringBuilderStreamTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,200 @@ +/* + * 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 + * @summary Basic test for Stream + * @library /sqeutil + * @(#) StringBuilderStreamTest.java + * @author Eric Wang/Tristan Yan + * @run testng/othervm -mx2g StringBuilderStreamTest + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.Predicate; +import java.util.function.ToIntFunction; +import java.util.stream.IntStream; +import org.testng.annotations.Factory; + +public class StringBuilderStreamTest> extends + GenericStreamTest> { + private final static HashMap> cache + = new HashMap<>(); + + private final static int MAX_STRING_LEN = 1 << 3; + + static { + Function strToBuilder = StringBuilder::new; + BiFunction lensToString + = StringUtilities::randomString; + BiFunction lensToBuilder + = lensToString.andThen(strToBuilder); + Function randomLenToBuilder = len -> + lensToBuilder.apply(MAX_STRING_LEN + 1, 1); + Function valueToString = String::valueOf; + Function valueToStringBuilder + = valueToString.andThen(strToBuilder); + BiFunction randomnessLenToStringBuilder + = (random, len) -> { + if(random) + return randomLenToBuilder.apply(len); + else + return valueToStringBuilder.apply(len); + }; + Function> + randomToBuildersFunction = random -> + (size -> IntStream.rangeClosed(1, size).mapToObj(len -> + randomnessLenToStringBuilder.apply(random, len)). + toArray(StringBuilder[]::new)); + initCache(cache, randomToBuildersFunction, "StringBuilderStreamTest"); + } + + public StringBuilderStreamTest(Class clazz, + ParallelType parallelType, int initSize) { + super(clazz, parallelType, Comparator.comparing((Function)StringBuilder::toString), initSize); + } + + public StringBuilderStreamTest(Class clazz, + ParallelType parallelType) { + super(clazz, parallelType, Comparator.comparing((Function)StringBuilder::toString)); + } + + @Factory + public static Object[] create(){ + TripleFunction + supplierWithInitSize = + StringBuilderStreamTest>::new; + BiFunction supplier = + StringBuilderStreamTest>::new; + List tests = new ArrayList(); + Arrays.stream(ParallelType.values()).forEach(parallelType -> { + Arrays.stream(defaultConstructorClazz).forEach( clazz -> + tests.add(new StringBuilderSpecialTest(supplier.apply( + clazz, parallelType)))); + Arrays.stream(capacityConstructorClazz).forEach( clazz -> + tests.add(new StringBuilderSpecialTest(supplierWithInitSize.apply( + clazz, parallelType,MEDIUM_DATA_SIZE)))); + }); + tests.addAll(Arrays.asList(GenericStreamTest.create( + supplierWithInitSize, supplier, false))); + return tests.toArray(); + } + + @Override + public String getTestName() { + return typeObject.getName() + ""; + } + + @Override + protected Object[] predicateAndDesc(int size){ + LambdaUtilities.CharType charType = Arrays.stream(LambdaUtilities.CharType.values()).findAny().get(); + Boolean isFirst = rand.nextBoolean(); + Predicate p = (Predicate) + LambdaUtilities.randomSBPredicate(charType, isFirst); + String funcName; + switch (charType) { + case DIGIT: funcName = "isDigit"; break; + case LOWERCASE: funcName = "isLowerCase"; break; + case UPPERCASE: funcName = "isUpperCase"; break; + default: funcName = "isLetterOrDigit"; break; + } + return new Object[]{ p , String.format("sb -> Character.%s(%s)", + funcName, isFirst ? "0" : "sb.toString().length() - 1")}; + } + + //BinaryOperator, descrption, stateless + @Override + protected Object[][] binaryOperatorAndDesc() { + return new Object[][]{ +// {(BinaryOperator)StringBuilder::append, "StringBuilder::append", false}, + {LambdaUtilities.maxGenericBinaryOperator(getNaturalOrderComparator()), + "(t1, t2) -> t1 < t2 ? t2 : t1", true}, + {LambdaUtilities.minGenericBinaryOperator(getNaturalOrderComparator()), + " (t1, t2) -> t1 < t2 ? t1 : t2", true}, + }; + } + + //Function, descrption for Function + @Override + protected Object[][] functionAndDesc(){ + return new Object[][]{ + {(Function)StringBuilder::toString, + "StringBuilder::toString"}, + }; + } + + @Override + protected StringBuilder[] getArray(int size, boolean random){ + return cache.get(random).get(size); + } + + @Override + protected StringBuilder[] bases(int size){ + return new StringBuilder[]{new StringBuilder(), + new StringBuilder(rand.nextInt(size)), new StringBuilder(size)}; + } + + //StringBuilder[] can be converted into StringBuilder[]::new, + //CharSequence[]::new, Object[]::new + @Override + protected Object[] validArrayGeneratorAndDesc() { + return new Object[]{ + new IntFunction[]{ + (IntFunction)StringBuilder[]::new, + (IntFunction)CharSequence[]::new, + (IntFunction)Object[]::new + }, + "{StringBuilder[]::new, CharSequence[]::new}, Object[]::new}" + }; + } + + //StringBuilder[] can't be converted into StringBuffer[]::new,Integer[]::new + @Override + protected Object[][] invalidArrayGeneratorAndDesc() { + return new Object[][]{ + {(IntFunction)StringBuffer[]::new, "StringBuffer[]::new"}, + {(IntFunction)Integer[]::new, "Integer[]::new"}, + }; + } + + @Override + protected IntFunction createFunction() { + return i -> new StringBuilder().append(i); + } + + @Override + protected ToIntFunction intValueFunction() { + return sb -> Integer.parseInt(sb.toString()) ; + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/SubstreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/SubstreamTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,69 @@ +/* + * 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.util.Collection; +import java.util.HashSet; +import java.util.Random; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class SubstreamTest> extends OperatorTest{ + public SubstreamTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionData") + public void testSubstream(String desc, Collection col) { + BiFunction bf = LambdaUtilities.randBetweenIntegerFunction(); + int skip = new Random().nextInt(col.size()); + int limit1 = bf.apply(0, col.size() - skip); + Collection sliceCol = streamFor(col).skip(skip).limit(limit1). + collect(Collectors.toList()); + verifySlice(col, sliceCol, skip, limit1, !col.getClass().equals(HashSet.class)); + + int limitExceeded = bf.apply(col.size() - skip, Integer.MAX_VALUE); + Collection sliceCol2 = streamFor(col).skip(skip).limit(limitExceeded). + collect(Collectors.toList()); + //We couldn't predicate unordered collection like HashSet behavior for substream, for unordered collection we + // only check the length and if data exists in original collection + verifySlice(col, sliceCol2, skip, limitExceeded, !col.getClass().equals(HashSet.class)); + + assertEquals(streamFor(col).skip(skip).limit(0).count(), 0); + + //skip exceed collection size cause empty stream + Stream stream3 = streamFor(col); + int skipExceeded = bf.apply(col.size(), Integer.MAX_VALUE); + assertEquals(stream3.skip(skipExceeded).limit(1).count(), 0); + + assertEquals(streamFor(createEmptyCollection()).skip(skip).limit(limit1).count(), 0); + } + + @Test(dataProvider="collectionStartEndData",expectedExceptions = IllegalArgumentException.class) + public void testSubstreamException(String desc, Collection col, long startInclusive, long endExclusive){ + streamFor(col).skip(startInclusive).count(); + streamFor(col).skip(startInclusive).limit(endExclusive-startInclusive).count(); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Stream/ToArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Stream/ToArrayTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,51 @@ +/* + * 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.util.Arrays; +import java.util.Collection; +import java.util.function.IntFunction; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +public class ToArrayTest> extends OperatorTest{ + public ToArrayTest(GenericStreamTest test) { + super(test); + } + + @Test(dataProvider="collectionArrayGeneratorData", threadPoolSize = 3) + public void testToArray(String desc, Collection col, IntFunction[] generators) { + Object[] expectedArr = col.toArray(); + assertEquals(streamFor(col).toArray(), expectedArr); + assertEquals(streamFor(createEmptyCollection()).toArray().length, 0); + + Arrays.stream(generators).forEach(generator -> { + assertEquals(streamFor(col).toArray(generator), expectedArr); + assertEquals(streamFor(createEmptyCollection()).toArray(generator).length, 0); + }); + } + + @Test(dataProvider="collectionArrayInvalidGeneratorData",expectedExceptions = ArrayStoreException.class) + public void testToArrayException(String desc, Collection col, IntFunction generator){ + streamFor(col).toArray(generator); + } +} \ No newline at end of file diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/Streams/BasicTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/Streams/BasicTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,129 @@ +/* + * 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 + * @summary Basic test for Streams's API + * @library /sqeutil + * @(#) BasicTest.java + * @author Tristan Yan + * @run testng BasicTest + */ + +import java.util.Arrays; +import java.util.Iterator; +import java.util.PrimitiveIterator; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.IntConsumer; +import java.util.function.IntUnaryOperator; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import java.util.Spliterators; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +public class BasicTest { + private final static int ARRAY_SIZE = 1 << 12; + + private final static Random rand = new Random(8675309); + + private final static String HELLO_WORLD = "Hello world"; + + @Test + public void testEmpty() { + final AtomicInteger accumulator = new AtomicInteger(0); + IntConsumer ic = i -> { + accumulator.getAndIncrement(); + }; + Spliterators.emptyIntSpliterator().forEachRemaining(ic); + assertEquals(accumulator.get(), 0); + + assertEquals(IntStream.empty().toArray().length, 0); + + assertEquals(Stream.empty().toArray().length, 0); + + assertEquals(Spliterators.emptyIntSpliterator().estimateSize(), 0); + + assertEquals(Spliterators.emptySpliterator().estimateSize(), 0); + } + + @Test + public void testGenerate() { + final int randomValue = rand.nextInt(); + final int randomSize= rand.nextInt(1 << 8); + IntStream is = IntStream.generate(() -> randomValue); + assertEquals(is.spliterator().getExactSizeIfKnown(), -1); + + IntStream is1 = IntStream.generate(() -> randomValue); + IntStream is2 = IntStream.generate(() -> randomValue); + assertEquals(is1.limit(randomSize).max(), is2.limit(randomSize).min()); + + Stream ss = Stream.generate(() -> HELLO_WORLD); + assertEquals(ss.spliterator().getExactSizeIfKnown(), -1); + Stream ss1 = Stream.generate(() -> HELLO_WORLD); + Stream ss2 = Stream.generate(() -> HELLO_WORLD); + assertEquals(ss1.limit(randomSize).findAny(), ss2.limit(randomSize).findAny()); + + LambdaUtilities.IntOp op = LambdaUtilities.IntOp.values()[rand.nextInt(LambdaUtilities.IntOp.values().length)]; + final int randomInit = rand.nextInt(); + final int randomOpnd = rand.nextInt(); + IntUnaryOperator iuo = LambdaUtilities.opIntUnaryOperator(op, randomOpnd); + IntStream isi = IntStream.iterate(randomInit, iuo); + int limitation = rand.nextInt( 1 << 10 ); + PrimitiveIterator.OfInt pi = isi.limit(limitation).iterator(); + + int next = randomInit; + + while(pi.hasNext()) { + assertEquals(pi.nextInt(), next); + next = iuo.applyAsInt(next); + } + + //below is time-consuming, need watch out if it's gonna affect our test + int start = rand.nextInt(1 << 12); + int end = rand.nextInt(1 << 12); + + if(start > end) { + start = start ^ end; + end = end ^ start; + start = end ^ start; + } + PrimitiveIterator.OfInt it1 = IntStream.range(start, end).iterator(); + while(it1.hasNext()) + assertEquals(it1.nextInt(), start++); + assertEquals(start, end); + } + + @Test + public void testIterator() { + int seed = rand.nextInt(); + int opRnd = rand.nextInt(); + int selected = rand.nextInt(LambdaUtilities.IntOp.values().length); + LambdaUtilities.IntOp op = LambdaUtilities.IntOp.values()[selected]; + int limitRnd = rand.nextInt(1 << 20); + IntUnaryOperator iuo = LambdaUtilities.opIntUnaryOperator(op, opRnd); + int[] arr = IntStream.iterate(seed, iuo).limit(limitRnd).toArray(); + assertEquals(arr.length, limitRnd); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/IntStreamTestDataProvider.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/LambdaTestMode.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/LoggingTestCase.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/OpTestCase.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/boottest/java/util/stream/DoubleNodeTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/boottest/java/util/stream/IntNodeTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/boottest/java/util/stream/LongNodeTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/boottest/java/util/stream/SliceSpliteratorTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/boottest/java/util/stream/SpinedBufferTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/GenBadMHTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/GenBadMHTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,120 @@ +/* + * 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. + */ +package org.openjdk.tests.java.lang.invoke; + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Handle; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandleInfo; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static jdk.internal.org.objectweb.asm.Opcodes.*; +import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD; +import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +/** + * Regression test to ensure that the VM does not report invokevirtual method handles as invokespecial + */ +@Test(groups = { "serialization-hostile" }) +public class GenBadMHTest { + public void testMHForStringToUpper() throws IOException, ReflectiveOperationException { + MethodHandle mh = mhFor(Opcodes.H_INVOKEVIRTUAL, "java/lang/String", "toUpperCase", "()Ljava/lang/String;"); + MethodHandleInfo mhi = MethodHandles.lookup().revealDirect(mh); + assertTrue(mhi.getReferenceKind() == MethodHandleInfo.REF_invokeVirtual); + } + + public void testMHForAtomicLong() throws IOException, ReflectiveOperationException { + MethodHandle mh = mhFor(Opcodes.H_INVOKEVIRTUAL, "java/util/concurrent/atomic/AtomicLong", "addAndGet", "(J)J"); + MethodHandleInfo mhi = MethodHandles.lookup().revealDirect(mh); + assertTrue(mhi.getReferenceKind() == MethodHandleInfo.REF_invokeVirtual); + } + + private MethodHandle mhFor(int kind, String host, String method, String sig) throws IOException, ReflectiveOperationException { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + cw.visit(51, ACC_SUPER + ACC_PUBLIC, "Foo", null, "java/lang/Object", new String[0]); + + // Constructor + MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(ALOAD, 0); + ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); + ctor.visitInsn(RETURN); + ctor.visitMaxs(-1, -1); + ctor.visitEnd(); + + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "foo", "()Ljava/lang/Object;", null, null); + mv.visitLdcInsn(new Handle(kind, host, method, sig)); + mv.visitInsn(ARETURN); + mv.visitMaxs(-1, -1); + mv.visitEnd(); + + cw.visitEnd(); + + byte[] bytes = cw.toByteArray(); + File f = new File("Foo.class"); + try (FileOutputStream fos = new FileOutputStream(f)) { + fos.write(bytes); + } + + List list = new ArrayList<>(); + list.add(new URL("file:" + f.getCanonicalFile().getParent().replace("\\", "/") + "/")); + Class clazz = Class.forName("Foo", true, new URLClassLoader(list.toArray(new URL[list.size()]))); + Method m = clazz.getMethod("foo"); + return (MethodHandle) m.invoke(clazz.newInstance()); + } + + public void testPrivateInnerCtorRef() { + Supplier ctor = new Enclosing().foo(); + Enclosing.Inner inner = (Enclosing.Inner) ctor.get(); + assertNotNull(inner); + } + + static class Enclosing { + + public Supplier foo() { + return Inner::new; + } + + private class Inner { + private Inner() {} + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java --- a/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -56,14 +56,18 @@ */ @Test public class SerializedLambdaTest { + public static final int REPS = 50; + @SuppressWarnings("unchecked") private void assertSerial(T p, Consumer asserter) throws IOException, ClassNotFoundException { asserter.accept(p); - byte[] bytes = serialize(p); - assertTrue(bytes.length > 0); + for (int i=0; i 0); - asserter.accept((T) deserialize(bytes)); + asserter.accept((T) deserialize(bytes)); + } } private void assertNotSerial(Predicate p, Consumer> asserter) diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/stream/test/org/openjdk/tests/java/util/stream/TabulatorsTest.java diff -r f82b730c798b -r 99dd9e50f37e test/java/util/zip/ZipFile/StreamZipEntriesTest.java diff -r f82b730c798b -r 99dd9e50f37e test/jdk/lambda/InvokespecialMethodKindTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/lambda/InvokespecialMethodKindTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,65 @@ +/* + * 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleInfo; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.function.Function; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * InvokespecialMethodKindTest + */ +@Test +public class InvokespecialMethodKindTest { + public void testStringToUpper() throws ReflectiveOperationException { + MethodHandle mh = MethodHandles.lookup().findVirtual(String.class, "toUpperCase", + MethodType.methodType(String.class)); + MethodHandleInfo mhi = MethodHandles.lookup().revealDirect(mh); + assertEquals(mhi.getReferenceKind(), MethodHandleInfo.REF_invokeVirtual); + } + + public void testSerializeStringToUpper() throws IOException, ClassNotFoundException { + Function f = (Function & Serializable) String::toUpperCase; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(f); + oos.flush(); + byte[] bs = bos.toByteArray(); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bs)); + @SuppressWarnings("unchecked") + Function ff = (Function) ois.readObject(); + assertEquals("FOO", ff.apply("fOo")); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/jdk/lambda/TestInterfaceBridges.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/lambda/TestInterfaceBridges.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,152 @@ +/* + * 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.util.List; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * TestInterfaceBridges + * + * @author Brian Goetz + */ +@Test +public class TestInterfaceBridges { + public void testCovariantOverrideLambda() { + B b = () -> "Foo"; + assertEquals("Foo", b.make()); + assertEquals("Foo", ((A) b).make()); + } + + public void testCovariantOverrideIC() { + B b = new B() { + @Override + public String make() { + return "Foo"; + } + }; + assertEquals("Foo", b.make()); + assertEquals("Foo", ((A) b).make()); + } + + public static interface A { + Object make(); + } + + public static interface B extends A { + String make(); + } + + public void testCovariantMerge() { + D d = () -> "Foo"; + assertEquals("Foo", d.make()); + assertEquals("Foo", ((A) d).make()); + assertEquals("Foo", ((C) d).make()); + } + + public static interface C { + String make(); + } + + public static interface D extends A, C { } + + public void testGenericSpecialization() { + F fss = x->x; + assertEquals("Foo", fss.m("Foo")); + } + + interface F { + B m(A a); + } + + public void testGenericFboundSpecialization() { + G gs = x->x; + assertEquals("Foo", gs.m("Foo")); + } + + interface G> { + X m(X x); + } + + public void testGenericSpecializationInSubclass() { + F_S_S fss = (s)->s; + assertEquals("Foo", fss.m("Foo")); + assertEquals("Foo", ((F)fss).m("Foo")); + } + + interface F_S_S extends F {} + + public void testCovariantMultiMerge() { + M1234 m1234 = ()->1; + assertEquals(1, (int)m1234.m()); + assertEquals(1, (int)((M1)m1234).m()); + assertEquals(1, (int)((M2)m1234).m()); + assertEquals(1, (int)((M3)m1234).m()); + assertEquals(1, (int)((M4)m1234).m()); + } + + interface M1 {Number m();} + interface M2 {Integer m();} + interface M3 {java.io.Serializable m();} + interface M4 {Object m();} + + interface M1234 extends M1, M2, M3, M4 {} + + public void testDefaultMerge() { + DD12 dds = s->1; + assertEquals(1, ((DD1)dds).m("")); + assertEquals(1, ((DD2)dds).m("")); + } + + interface DD1 { int m(T arg); } + interface DD2 { default int m(String arg) { return 42; } } + interface DD12 extends DD1, DD2 {} + + public void testDefaultNoMerge() { + DD12 dds = s->1; + assertEquals(1, ((DD1)dds).m(1)); + assertEquals(42, ((DD2)dds).m("")); + } + + public void testRawMerge() { + List ls = null; + R12 r12 = l->"Foo"; + assertEquals("Foo", r12.m(ls)); + assertEquals("Foo", ((R1)r12).m(ls)); + assertEquals("Foo", ((R2)r12).m(ls)); + } + + interface R1 { + Object m(List ls); + } + + @SuppressWarnings("rawtypes") + interface R2 { + String m(List l); + } + + interface R12 extends R1, R2 {} +} + diff -r f82b730c798b -r 99dd9e50f37e test/jdk/lambda/separate/Compiler.java --- a/test/jdk/lambda/separate/Compiler.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/jdk/lambda/separate/Compiler.java Mon Nov 11 23:17:30 2013 -0800 @@ -49,12 +49,12 @@ USECACHE // Keeps results around for reuse. Only use this is // you're sure that each compilation name maps to the // same source code - }; + } private static final AtomicInteger counter = new AtomicInteger(); private static final String targetDir = System.getProperty("lambda.separate.targetDirectory", - System.getProperty("java.io.tmpdir") + File.separator + "gen-separate"); + "tmp" + File.separator + "gen-separate"); private static final File root = new File(targetDir); private static ConcurrentHashMap cache = new ConcurrentHashMap<>(); @@ -90,7 +90,7 @@ } public void setFlags(Flags ... flags) { - this.flags = new HashSet(Arrays.asList(flags)); + this.flags = new HashSet<>(Arrays.asList(flags)); } public void addPostprocessor(ClassFilePreprocessor cfp) { @@ -136,17 +136,10 @@ outputDirs.put(type.getName(), outDir); Class superClass = type.getSuperclass(); - if (superClass != null) { - for( Map.Entry each : compileHierarchy(superClass).entrySet()) { - outputDirs.put(each.getKey(), each.getValue()); - } - } - for (Extends ext : type.getSupertypes()) { - Type iface = ext.getType(); - for( Map.Entry each : compileHierarchy(iface).entrySet()) { - outputDirs.put(each.getKey(), each.getValue()); - } - } + if (superClass != null) + outputDirs.putAll(compileHierarchy(superClass)); + for (Extends ext : type.getSupertypes()) + outputDirs.putAll(compileHierarchy(ext.getType())); return outputDirs; } @@ -161,8 +154,12 @@ List files = new ArrayList<>(); SourceProcessor accum = (name, src) -> files.add(new SourceFile(name, src)); - for (Type dep : type.typeDependencies()) { - dep.generateAsDependency(accum, type.methodDependencies()); + Collection deps = type.typeDependencies(type.isFullCompilation()); + for (Type dep : deps) { + if (type.isFullCompilation()) + dep.generate(accum); + else + dep.generateAsDependency(accum, type.methodDependencies()); } type.generate(accum); @@ -189,7 +186,7 @@ StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); } catch (IOException e) { throw new RuntimeException( - "IOException encountered during compilation"); + "IOException encountered during compilation", e); } Boolean result = ct.call(); if (result == Boolean.FALSE) { diff -r f82b730c798b -r 99dd9e50f37e test/jdk/lambda/separate/SourceModel.java --- a/test/jdk/lambda/separate/SourceModel.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/jdk/lambda/separate/SourceModel.java Mon Nov 11 23:17:30 2013 -0800 @@ -46,7 +46,7 @@ generate(pw); return sw.toString(); } - }; + } public static class AccessFlag extends Element { private String flag; @@ -123,6 +123,7 @@ // (and thus will be present in stubs) private Set methodDependencies; private List typeDependencies; + private boolean fullCompilation; protected Type(String name, List flags, List params, @@ -212,6 +213,14 @@ methodDependencies.add(m); } + public boolean isFullCompilation() { + return fullCompilation; + } + + public void setFullCompilation(boolean fullCompilation) { + this.fullCompilation = fullCompilation; + } + // Convenience method for creating an Extends object using this // class and specified type arguments. public Extends with(String ... args) { @@ -261,14 +270,23 @@ pw.println("}"); } - public Collection typeDependencies() { + public Collection typeDependencies(boolean recursive) { HashMap dependencies = new HashMap<>(); Type superclass = getSuperclass(); if (superclass != null) { dependencies.put(superclass.getName(), superclass); + if (recursive) { + for (Type t : superclass.typeDependencies(true)) + dependencies.put(t.getName(), t); + } } - for (Extends e : getSupertypes()) + for (Extends e : getSupertypes()) { dependencies.put(e.getType().getName(), e.getType()); + if (recursive) { + for (Type t : e.getType().typeDependencies(true)) + dependencies.put(t.getName(), t); + } + } // Do these last so that they override for (Type t : this.typeDependencies) dependencies.put(t.getName(), t); diff -r f82b730c798b -r 99dd9e50f37e test/jdk/lambda/separate/TestHarness.java --- a/test/jdk/lambda/separate/TestHarness.java Thu Oct 31 16:44:18 2013 -0700 +++ b/test/jdk/lambda/separate/TestHarness.java Mon Nov 11 23:17:30 2013 -0800 @@ -197,7 +197,7 @@ assertEquals(res, value); } } catch (InvocationTargetException | IllegalAccessException e) { - fail("Unexpected exception thrown: " + e.getCause()); + fail("Unexpected exception thrown: " + e.getCause(), e.getCause()); } } diff -r f82b730c798b -r 99dd9e50f37e test/jdk/lambda/vm/FDSeparateCompilationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/lambda/vm/FDSeparateCompilationTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,193 @@ +/* + * 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. + */ + +package vm; + +import java.util.ArrayList; +import java.util.Set; + +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import separate.TestHarness; +import separate.Compiler; +import shapegen.ClassCase; +import shapegen.Hierarchy; +import shapegen.HierarchyGenerator; + +import static org.testng.Assert.fail; +import static separate.SourceModel.AbstractMethod; +import static separate.SourceModel.AccessFlag; +import static separate.SourceModel.Class; +import static separate.SourceModel.ConcreteMethod; +import static separate.SourceModel.DefaultMethod; +import static separate.SourceModel.Interface; +import static separate.SourceModel.Method; +import static separate.SourceModel.Type; + +public class FDSeparateCompilationTest extends TestHarness { + + private static String EMPTY = "\"\""; + + public FDSeparateCompilationTest() { + super(false, true); + } + + @DataProvider(name = "allShapes", parallel = true) + public Object[][] hierarchyGenerator() { + ArrayList allCases = new ArrayList<>(); + + HierarchyGenerator hg = new HierarchyGenerator(); + hg.getOK().stream().map(x->new Object[]{x}).forEach(allCases::add); + hg.getErr().stream().map(x -> new Object[] { x }).forEach(allCases::add); + return allCases.toArray(new Object[0][]); + } + + // The expected value obtained when invoking the method from the specified + // class. If returns null, then an AbstractMethodError is expected. + private static String getExpectedResult(ClassCase cc) { + Set provs = cc.get_mprov(); + if (cc.get_mres() != null) { + return cc.get_mres().getName(); + } else if (provs != null && provs.size() == 1) { + ClassCase cand = provs.iterator().next(); + switch (cand.kind) { + case CCONCRETE: + case IDEFAULT: + return cand.getName(); + case CNONE: + case IVAC: + return getExpectedResult(cand); + } + } + return null; + } + + private static final ConcreteMethod canonicalMethod = new ConcreteMethod( + "String", "m", "returns " + EMPTY + ";", AccessFlag.PUBLIC); + + @Test(groups = "vm", dataProvider = "allShapes") + public void separateCompilationTest(Hierarchy hs) { + ClassCase cc = hs.root; + Type type = sourceTypeFrom(hs.root); + + Class specimen = null; + if (type instanceof Class) { + Class ctype = (Class)type; + if (ctype.isAbstract()) { + specimen = new Class("Test" + ctype.getName(), ctype); + } else { + specimen = ctype; + } + } else { + specimen = new Class("Test" + type.getName(), (Interface)type); + } + + String value = getExpectedResult(cc); + if (value != null) { + assertInvokeVirtualEquals(value, specimen, canonicalMethod, EMPTY); + } else { + assertThrows(AbstractMethodError.class, specimen, + canonicalMethod, EMPTY); + } + } + + @AfterMethod + public void printCaseError(ITestResult result) { + if (result.getStatus() == ITestResult.FAILURE) { + Hierarchy hs = (Hierarchy)result.getParameters()[0]; + System.out.println("Separate compilation case " + hs); + printCaseDetails(hs); + } + } + + @AfterSuite + public void cleanupCompilerCache() { + Compiler.purgeCache(); + } + + private void printCaseDetails(Hierarchy hs) { + String exp = getExpectedResult(hs.root); + hs.getDescription().forEach( + x -> System.out.println(" " + x)); + if (exp != null) { + System.out.println(" Expected \"" + exp + "\""); + } else { + System.out.println(" Expected AbstractMethodError"); + } + } + + private Type sourceTypeFrom(ClassCase cc) { + Type type = null; + + if (cc.isInterface()) { + Interface iface = new Interface(cc.getName()); + for (ClassCase scc : cc.getInterfaces()) { + Interface supertype = (Interface)sourceTypeFrom(scc); + iface.addSuperType(supertype); + } + type = iface; + } else { + Class cls = new Class(cc.getName()); + if (cc.hasSuperclass()) { + Class superc = (Class)sourceTypeFrom(cc.getSuperclass()); + cls.setSuperClass(superc); + } + for (ClassCase scc : cc.getInterfaces()) { + Interface supertype = (Interface)sourceTypeFrom(scc); + cls.addSuperType(supertype); + } + if (cc.isAbstract()) { + cls.getAccessFlags().add(AccessFlag.ABSTRACT); + } + type = cls; + } + Method method = methodFrom(cc); + if (method != null) { + type.addMethod(method); + } + return type; + } + + private Method methodFrom(ClassCase cc) { + switch (cc.kind) { + case IVAC: + case CNONE: return null; + case IPRESENT: + case CABSTRACT: + return new AbstractMethod("String", "m", AccessFlag.PUBLIC); + case IDEFAULT: + return new DefaultMethod( + "String", "m", "return \"" + cc.getName() + "\";"); + case CCONCRETE: + return new ConcreteMethod( + "String", "m", "return \"" + cc.getName() + "\";", + AccessFlag.PUBLIC); + default: + fail("Unknown method type in class"); + return null; + } + } +} diff -r f82b730c798b -r 99dd9e50f37e test/jdk/lambda/vm/JVMBridgingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/lambda/vm/JVMBridgingTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,147 @@ +/* + * 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. + */ + +package vm; + +import org.testng.annotations.Test; +import separate.Compiler; +import separate.TestHarness; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import static separate.SourceModel.AbstractMethod; +import static separate.SourceModel.AccessFlag; +import static separate.SourceModel.Class; +import static separate.SourceModel.ConcreteMethod; +import static separate.SourceModel.Interface; +import static separate.SourceModel.MethodParameter; +import static separate.SourceModel.Type; +import static separate.SourceModel.TypeParameter; + +public class JVMBridgingTest extends TestHarness { + public JVMBridgingTest() { + super(false, false); + } + + private static final String STATIC_CLASS = "S"; + private static final String STATIC_METHOD_NAME = "foo"; + private static final int SUCCESS_VALUE = 99; + + private boolean equalsSuccessValue(Type[] compUnits) { + Compiler compiler = new Compiler(); + ClassLoader cl = compiler.compile(compUnits); + + try { + java.lang.Class S_class = + java.lang.Class.forName(STATIC_CLASS, true, cl); + assertNotNull(S_class); + java.lang.reflect.Method m = S_class.getMethod(STATIC_METHOD_NAME); + assertNotNull(m); + Integer res = (Integer)m.invoke(null); + return res.intValue() == SUCCESS_VALUE; + } catch (ClassNotFoundException e) { + fail("Could not find class"); + } catch (NoSuchMethodException e) { + fail("Could not find method"); + } catch (IllegalAccessException e) { + fail("Unexpected IllegalAccessException"); + } catch (java.lang.reflect.InvocationTargetException e) { + return false; /* A valid situation: the method may not exist */ + } finally { + compiler.cleanup(); + } + fail("Unexpected result"); + return false; // unreachable + } + + @Test(groups = "vm") + public void testTraditionalBridge() { + Interface I = new Interface("I", new TypeParameter("T"), + new AbstractMethod("int", "m", new MethodParameter("T", "t"))); + Class C = new Class("C", I.with("String"), new ConcreteMethod( + "int", "m", "return " + SUCCESS_VALUE + ";", AccessFlag.PUBLIC, + new MethodParameter("String", "s"))); + ConcreteMethod mStub = new ConcreteMethod( + "int", "m", "return 0;", AccessFlag.PUBLIC, + new MethodParameter("Object", "o")); + Class Cstub = new Class("C", mStub); + Class S = new Class(STATIC_CLASS, new ConcreteMethod( + "int", STATIC_METHOD_NAME, "return (new C()).m(\"\");", + AccessFlag.PUBLIC, AccessFlag.STATIC)); + S.addCompilationDependency(Cstub); + S.addCompilationDependency(mStub); + + Type[] compUnits = new Type[] {S, C, I}; + assertFalse(equalsSuccessValue(compUnits)); + for (Type t : compUnits) + t.setFullCompilation(true); + assertTrue(equalsSuccessValue(compUnits)); + } + + @Test(groups = "vm") + public void testCovarReturn() { + ConcreteMethod numberRet = new ConcreteMethod( + "Number", "m", "return 0;", AccessFlag.PUBLIC); + Class C = new Class("C", numberRet); + Class D = new Class("D", C, new ConcreteMethod("Integer", "m", + "return " + SUCCESS_VALUE + ";", AccessFlag.PUBLIC)); + + Class Dstub = new Class("D", numberRet); + Class S = new Class(STATIC_CLASS, + new ConcreteMethod("Integer", STATIC_METHOD_NAME, + "return (Integer)(new D()).m();", + AccessFlag.PUBLIC, AccessFlag.STATIC)); + S.addCompilationDependency(Dstub); + S.addCompilationDependency(numberRet); + + Type[] compUnits = new Type[] {S, D, C}; + assertFalse(equalsSuccessValue(compUnits)); + for (Type t : compUnits) + t.setFullCompilation(true); + assertTrue(equalsSuccessValue(compUnits)); + } + + @Test(groups = "vm") + public void testNoBridgeNeeded() { + Interface I = new Interface("I", new TypeParameter("T"), + new AbstractMethod("int", "m", new MethodParameter("T", "t"))); + + ConcreteMethod implementing = new ConcreteMethod("int", "m", + "return 0;", AccessFlag.PUBLIC, new MethodParameter("String", "s")); + ConcreteMethod matching = new ConcreteMethod("int", "m", "return 99;", + AccessFlag.PUBLIC, new MethodParameter("Object", "o")); + + Class C = new Class("C", I.with("String"), implementing, matching); + + Class S = new Class(STATIC_CLASS, new ConcreteMethod( + "int", STATIC_METHOD_NAME, "return (new C()).m(new Object());", + AccessFlag.PUBLIC, AccessFlag.STATIC)); + S.addCompilationDependency(C); + S.addCompilationDependency(matching); + + Type[] compUnits = new Type[] { S, C, I }; + assertTrue(equalsSuccessValue(compUnits)); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/sqeutil/LambdaUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sqeutil/LambdaUtilities.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,674 @@ +/* + * 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. + */ + +/** + * @summary This class provide basic support for lambda syntax + * @(#) LambdaUtilities.java + * @author Tristan Yan + */ + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.math.BigDecimal; +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.*; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class LambdaUtilities { + + public static enum CharType { + DIGIT, LOWERCASE, UPPERCASE, SPECIAL + } + + public static enum StringPredicateType { + START_WTIH, NOT_START_WITH, MORE_THAN_LEN, LESS_THAN_LEN + } + + public static enum IntOp { + ADD, SUBTRACT, MULTIPLY, DIVIDE, MOD + } + + public static IntPredicate randomIntPredicate(boolean isUP, int limit) { + if (isUP) { + return i -> i >= limit; + } else { + return i -> i < limit; + } + } + + public static Predicate randomIntegerPredicate(boolean isUP, int limit) { + if (isUP) { + return i -> i >= limit; + } else { + return i -> i < limit; + } + } + + public static LongPredicate randomLongPredicate(boolean isUP, long limit) { + if (isUP) { + return i -> i >= limit; + } else { + return i -> i < limit; + } + } + + public static Predicate startPathPredicate(Path start) { + return p -> p.startsWith(start); + } + + public static Predicate randomGenericPredicate(boolean isUp, T value, Comparator c) { + if (isUp) { + return emp -> c.compare(emp, value) >= 0; + }else { + return emp -> c.compare(emp, value) < 0; + } + } + + public static Predicate randomSBPredicate(StringPredicateType type, String value) { + switch (type) { + case START_WTIH: + return sb -> Character.isDigit(sb.charAt(0)); + case NOT_START_WITH: + return sb -> Character.isLowerCase(sb.charAt(0)); + case MORE_THAN_LEN: + return sb -> Character.isUpperCase(sb.charAt(0)); + default: + return sb -> !Character.isLetterOrDigit(sb.charAt(0)); + } + } + + public static Predicate randomSBPredicate(CharType startType, + boolean first) { + switch (startType) { + case DIGIT: + return sb -> Character.isDigit(sb.charAt(first ? 0 : sb.toString().length() - 1)); + case LOWERCASE: + return sb -> Character.isLowerCase(sb.charAt(first ? 0 : sb.toString().length() - 1)); + case UPPERCASE: + return sb -> Character.isUpperCase(sb.charAt(first ? 0 : sb.toString().length() - 1)); + default: + return sb -> !Character.isLetterOrDigit(sb.charAt(first ? 0 : sb.toString().length() - 1)); + } + } + + public static Predicate isDigitCharacterPredicate() { + return c -> Character.isDigit(c); + } + + public static Function posIntegerFunction(boolean isHighest) { + if (isHighest) { + return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10; + } else { + return i -> i % 10 < 0 ? -i % 10 : i % 10; + } + } + + public static Function sbGenericFunction(boolean isFirst) { + if (isFirst) + return i -> Character.isAlphabetic(i.charAt(0)) ? (Character.isUpperCase(i.charAt(0)) ? CharType.UPPERCASE : CharType.LOWERCASE) : (Character.isDigit(i.charAt(0)) ? CharType.DIGIT : CharType.SPECIAL); + else + return i -> Character.isAlphabetic(i.charAt(i.length() - 1)) ? (Character.isUpperCase(i.charAt(i.length() - 1)) ? CharType.UPPERCASE : CharType.LOWERCASE) : (Character.isDigit(i.charAt(i.length() - 1)) ? CharType.DIGIT : CharType.SPECIAL); + } + + public static Function mappingFunction(Map m, IntOp op, int value) { + switch (op) { + case ADD: + return k -> (value != 0) ? m.get(k) + value : m.get(k); + case SUBTRACT: + return k -> (value != 0) ? m.get(k) - value : m.get(k); + case MULTIPLY: + return k -> (value != 0) ? m.get(k) * value : m.get(k); + case DIVIDE: + return k -> (value != 0) ? m.get(k) / value : m.get(k); + default: + return k -> (value != 0) ? m.get(k) % value : m.get(k); + } + } + + public static IntFunction posIntFunction(boolean isHighest) { + if (isHighest) { + return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10; + } else { + return i -> i % 10 < 0 ? -i % 10 : i % 10; + } + } + + public static BiFunction randBetweenIntegerFunction() { + return (t1, t2) -> randBetween(t1, t2); + } + + public static int randBetween(int low, int up) { + assert (low < up && low >= 0); + Random rand = new Random(); + int i = rand.nextInt(up); + while (i < low) { + i = rand.nextInt(); + } + return i; + } + + public static ToIntFunction highestPosValueIntFunction() { + return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10; + } + + public static ToIntFunction lowestPosValueIntFunction() { + return i -> i % 10 < 0 ? -i % 10 : i % 10; + } + + public static Consumer reverseConsumer(Set set) { + return t -> { + set.add(t); + }; + } + + public static Consumer addIntegerConsumer(AtomicInteger ai) { + return t -> { + ai.updateAndGet(t1 -> t1 + t); + }; + } + + public static Consumer appendSBConsumer(StringBuilder sb) { + return t -> { + sb.append(t); + }; + } + + public static IntConsumer addIntConsumer(AtomicInteger ai) { + return t -> { + ai.updateAndGet(t1 -> t1 + t); + }; + } + + public static IntConsumer addLongConsumer(AtomicLong ai) { + return t -> { + ai.updateAndGet(t1 -> t1 + t); + }; + } + + public static Consumer copyConsumer(List list) { + return t -> { + list.add(t); + }; + } + + public static Consumer existsConsumer(Collection in, Collection out) { + return t -> { + if (in.contains(t)) { + out.add(t); + } + }; + } + + public static Supplier sbSupplier(StringBuilder value) { + return () -> value; + } + + public static Supplier integerSupplier(int value) { + return () -> value; + } + + public static Supplier genericSuppiler(T value) { + return () -> value; + } + + public static IntSupplier intSupplier(int value) { + return () -> value; + } + + public static Supplier longSupplier(long value) { + return () -> value; + } + + public static Supplier atomicIntegerSupplier(int value) { + return () -> new AtomicInteger(value); + } + + public static Supplier> atomicGenericSupplier(T value) { + return () -> new AtomicReference<>(value); + } + + public static Supplier> atomicSBSupplier(StringBuilder value) { + return () -> new AtomicReference<>(value); + } + + public static UnaryOperator opIntegerUnaryOperator(IntOp op, int value) { + switch (op) { + case ADD: + return t -> t + value; + case SUBTRACT: + return t -> t - value; + case MULTIPLY: + return t -> t * value; + case DIVIDE: + return t -> t / value; + default: + return t -> t % value; + } + } + + public static IntUnaryOperator opIntUnaryOperator(IntOp op, int value) { + if(value == 0) + return t -> t; + switch (op) { + case ADD: + return t -> t + value; + case SUBTRACT: + return t -> t - value; + case MULTIPLY: + return t -> t * value; + case DIVIDE: + return t -> t / value; + default: + return t -> t % value; + } + } + + public static Function opIntegerFunction(IntOp op, int value) { + if(value == 0) + return t -> t; + switch (op) { + case ADD: + return t -> Integer.valueOf(t + value); + case SUBTRACT: + return t -> Integer.valueOf(t - value); + case MULTIPLY: + return t -> Integer.valueOf(t * value); + case DIVIDE: + return t -> Integer.valueOf(t / value); + default: + return t -> Integer.valueOf(t % value); + } + } + + public static ToIntFunction opToIntFunction(IntOp op, int value) { + if(value == 0) + return t -> t.intValue(); + switch (op) { + case ADD: + return t -> t.intValue() + value; + case SUBTRACT: + return t -> t.intValue() - value; + case MULTIPLY: + return t -> t.intValue() * value; + case DIVIDE: + return t -> t.intValue() / value; + default: + return t -> t.intValue() % value; + } + } + + public static IntFunction opIntFunction(IntOp op, int value) { + if(value == 0) + return t -> t; + switch (op) { + case ADD: + return t -> t + value; + case SUBTRACT: + return t -> t - value; + case MULTIPLY: + return t -> t * value; + case DIVIDE: + return t -> t / value; + default: + return t -> t % value; + } + } + + public static IntUnaryOperator addIntUnaryOperator(int value) { + return t -> t + value; + } + + public static IntUnaryOperator subIntUnaryOperator(int value) { + return t -> t - value; + } + + public static IntUnaryOperator mulIntUnaryOperator(int value) { + return t -> t * value; + } + + public static IntUnaryOperator divIntUnaryOperator(int value) { + return t -> t / value; + } + + public static IntBinaryOperator minIntBinaryOperator() { + return (t1, t2) -> t1< t2 ? t1 : t2; + } + + public static BinaryOperator minIntegerBinaryOperator(Comparator c) { + return (t1, t2) -> c.compare(t1, t2) < 0 ? t1 : t2; + } + + public static BinaryOperator minGenericBinaryOperator(Comparator c) { + return (t1, t2) -> c.compare(t1, t2) < 0 ? t1 : t2; + } + + public static BinaryOperator minSBBinaryOperator(Comparator c) { + return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t1 : t2; + } + + public static IntBinaryOperator maxIntBinaryOperator() { + return ( t1, t2 ) -> (t1< t2) ? t2: t1; + } + + public static BinaryOperator maxIntegerBinaryOperator(Comparator c) { + return (t1, t2) -> c.compare(t1, t2) < 0 ? t2 : t1; + } + + public static BinaryOperator maxGenericBinaryOperator(Comparator c) { + return (t1, t2) -> c.compare(t1, t2) < 0 ? t2 : t1; + } + + public static IntBinaryOperator maxIntBinaryOperator(Comparator c) { + return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t2 : t1; + } + + public static BinaryOperator maxSBBinaryOperator(Comparator c) { + return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t2 : t1; + } + + public static BinaryOperator addIntegerBinaryOperator() { + return ( t1 , t2 ) -> t1 + t2; + } + + public static IntBinaryOperator addIntBinaryOperator() { + return ( t1 , t2 ) -> t1 + t2; + } + + public static BinaryOperator addBigDecimalBinaryOperator() { + return ( t1 , t2 ) -> t1.add(t2); + } + + public static DoubleBinaryOperator addDoubleBinaryOperator() { + return ( t1 , t2 ) -> t1 + t2; + } + + public static BinaryOperator appendSBBinaryOperator() { + return (t1 , t2) -> new StringBuilder().append(t1).append(t2); + } + + public static BinaryOperator subIntegerBinaryOperator() { + return (t1, t2) -> t1 - t2; + } + + public static IntBinaryOperator subIntBinaryOperator() { + return (t1, t2) -> t1 - t2; + } + + public static BinaryOperator deleteSBBinaryOperator() { + return (t1, t2) -> {if (t1.length() >= t2.length()) { + int i1 = t1.indexOf(t2.toString()); + int i2 = i1 + t2.length(); + return new StringBuilder(t1).delete(i1, i2); + }else { + int i1 = t2.indexOf(t1.toString()); + int i2 = i1 + t1.length(); + return new StringBuilder(t2).delete(i1, i2); + } + }; + + } + + public static IntBinaryOperator mulIntBinaryOperator() { + return (t1, t2) -> t1 * t2; + } + + public static IntBinaryOperator divIntBinaryOperator() { + return (t1, t2) -> t1 / t2; + } + + public static LongUnaryOperator addLongUnaryOperator(long value) { + return t -> t + value; + } + + public static UnaryOperator appendSBUnaryOperator(StringBuilder value) { + return t -> t.append(value); + } + + public static LongUnaryOperator subLongUnaryOperator(long value) { + return t -> t - value; + } + + public static LongUnaryOperator mulLongUnaryOperator(long value) { + return t -> t * value; + } + + public static LongUnaryOperator divLongUnaryOperator(long value) { + return t -> t / value; + } + + public static LongBinaryOperator addLongBinaryOperator() { + return (t1, t2) -> t1 + t2; + } + + public static LongBinaryOperator subLongBinaryOperator() { + return (t1, t2) -> t1 - t2; + } + + public static LongBinaryOperator mulLongBinaryOperator() { + return (t1, t2) -> t1 * t2; + } + + public static LongBinaryOperator divLongBinaryOperator() { + return (t1, t2) -> t1 / t2; + } + + public static BiConsumer addIntegerBiConsumer() { + return (t1 , t2 ) -> { t1.addAndGet(t2); }; + } + + public static BiConsumer addAtomicIntegerBiConsumer() { + return (t1 , t2) -> { t1.addAndGet(t2.get()); }; + } + + public static BiConsumer, StringBuilder> appendSBBiConsumer() { + return (t1, t2) -> {t1.updateAndGet(appendSBUnaryOperator(t2));}; + } + + public static BiConsumer, AtomicReference> appendAtomicSBBiConsumer() { + return (t1, t2) -> {t1.updateAndGet(appendSBUnaryOperator(t2.get()));}; + } + + public static BiConsumer maxIntegerBiConsumer(Comparator c) { + return (t1 , t2 ) -> { t1.getAndUpdate(t -> max(t, t2, c)); }; + } + + public static BiConsumer, T> maxGenericBiConsumer(Comparator c) { + return (t1 , t2 ) -> { t1.getAndUpdate(t -> max(t, t2, c)); }; + } + + public static BiConsumer maxAtomicIntegerBiConsumer(Comparator c) { + return (t1 , t2) -> { t1.getAndUpdate(t -> max(t, t2.get(), c)); }; + } + + public static BiConsumer, AtomicReference> maxAtomicGenericBiConsumer(Comparator c) { + return (t1 , t2) -> { t1.getAndUpdate(t -> max(t, t2.get(), c)); }; + } + + public static BiConsumer minIntegerBiConsumer(Comparator c) { + return (t1 , t2) -> { t1.getAndUpdate(t -> min(t, t2, c)); }; + } + + public static BiConsumer, T> minGenericBiConsumer(Comparator c) { + return (t1 , t2) -> { t1.getAndUpdate(t -> min(t, t2, c)); }; + } + + public static BiConsumer minAtomicIntegerBiConsumer(Comparator c) { + return (t1, t2) -> { t1.getAndUpdate(t -> min(t, t2.get(), c)); }; + } + + public static BiConsumer, AtomicReference> minAtomicGenericBiConsumer(Comparator c) { + return (t1, t2) -> { t1.getAndUpdate(t -> min(t, t2.get(), c)); }; + } + + public static BiFunction maxIntegerFunction(Comparator c) { + return (t1, t2) -> max(t1, t2, c); + } + + public static BiFunction deviationSequareFunction(double avg) { + return (bd, t) -> bd.add(new BigDecimal(avg - t).pow(2)); + } + + public static BiFunction maxGenericFunction(Comparator c) { + return (t1, t2) -> max(t1, t2, c); + } + + public static BiFunction maxStringBuilderFunction(Comparator c) { + return (t1, t2) -> max(t1, t2, c); + } + + public static BiFunction minIntegerFunction(Comparator c) { + return (t1, t2) -> min(t1, t2, c); + } + + public static BiFunction minGenericFunction(Comparator c) { + return (t1, t2) -> min(t1, t2, c); + } + + public static BiFunction minStringBuilderFunction(Comparator c) { + return (t1, t2) -> min(t1, t2, c); + } + + public static BiFunction opBiFunction(IntOp op, int value) { + switch (op) { + case ADD: + return (k, v) -> (value != 0) ? v + value : v; + case SUBTRACT: + return (k, v) -> (value != 0) ? v - value : v; + case MULTIPLY: + return (k, v) -> (value != 0) ? v * value : v; + case DIVIDE: + return (k, v) -> (value != 0) ? v / value : v; + default: + return (k, v) -> (value != 0) ? v % value : v; + } + } + + + public static BiFunction opBiFunction(IntOp op) { + switch (op) { + case ADD: + return (oldv, v) -> (v != 0) ? oldv + v : oldv; + case SUBTRACT: + return (oldv, v) -> (v != 0) ? oldv - v : oldv; + case MULTIPLY: + return (oldv, v) -> (v != 0) ? oldv * v : oldv; + case DIVIDE: + return (oldv, v) -> (v != 0) ? oldv / v : oldv; + default: + return (oldv, v) -> (v != 0) ? oldv % v : oldv; + } + } + + private static Integer min(Integer i1, Integer i2, Comparator c) { + return c.compare(i1, i2) < 0 ? i1 : i2; + } + + private static T min(T i1, T i2, Comparator c) { + return c.compare(i1, i2) < 0 ? i1 : i2; + } + + private static StringBuilder min(StringBuilder sb1, StringBuilder sb2, Comparator c) { + return c.compare(sb1, sb2) < 0 ? sb1 : sb2; + } + + private static Integer max(Integer i1, Integer i2, Comparator c) { + return c.compare(i1, i2) < 0 ? i2 : i1; + } + + private static T max(T i1, T i2, Comparator c) { + return c.compare(i1, i2) < 0 ? i2 : i1; + } + + private static StringBuilder max(StringBuilder sb1, StringBuilder sb2, Comparator c) { + return c.compare(sb1, sb2) < 0 ? sb2 : sb1; + } + /* + * Construct a Collection C object based on a C object, using generic type + * instead of Class type can help preventing type error in compilation + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static > C create(C c, int... initSize) + throws InstantiationException, IllegalAccessException, + NoSuchMethodException, IllegalArgumentException, + InvocationTargetException { + return create((Class) c.getClass(), initSize); + } + + /* + * Construct a Collection C object based on a C's type, using generic type + * instead of Class type can help preventing type error in compilation + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static > T create( + Class> cls, int... initSize) + throws InstantiationException, IllegalAccessException, + NoSuchMethodException, IllegalArgumentException, + InvocationTargetException { + assert (initSize.length <= 1); + Collection c; + if (initSize.length == 0) { + c = cls.newInstance(); + } else { + Constructor con = cls.getConstructor(int.class); + c = (Collection) con.newInstance(initSize[0]); + } + return (T) c; + } + + /* + * Construct a T object based on T's type, using generic type instead of + * Class type can help preventing type error in compilation + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static > M createMap(M m, int... initSize) + throws InstantiationException, IllegalAccessException, + NoSuchMethodException, IllegalArgumentException, + InvocationTargetException { + return createMap((Class) m.getClass(), initSize); + } + + /* + * Construct a Map M object based on M's type, using generic type instead of + * Class type can help preventing type error in compilation + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static > M createMap(Class> cls, + int... initSize) throws InstantiationException, + IllegalAccessException, NoSuchMethodException, + IllegalArgumentException, InvocationTargetException { + assert (initSize.length <= 1); + Map map; + if (initSize.length == 0) { + map = cls.newInstance(); + } else { + Constructor con = cls.getConstructor(int.class); + map = (Map) con.newInstance(initSize[0]); + } + return (M) map; + } +} diff -r f82b730c798b -r 99dd9e50f37e test/sqeutil/StringUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sqeutil/StringUtilities.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,132 @@ +/* + * 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. + */ + +/** + * + * @summary utilities class supporting common operation for tests. + * @(#)StringUtilities.java + * @author Tristan Yan + * @version 1.0 + */ + +import java.util.Random; + +public class StringUtilities { + private final static Random RANDOM = new Random(System.currentTimeMillis()); + + public static String randomString(int max_length, int min_length){ + return randomAscii(min_length + RANDOM.nextInt(max_length - min_length)); + } + + public static String random(int count, int start, int end, boolean letters, + boolean numbers, char[] chars, Random rnd) { + if (count == 0) { + return ""; + } else if (count < 0) { + throw new IllegalArgumentException("Requested random string length " + count + " is less than 0."); + } + if ((start == 0) && (end == 0)) { + end = 'z' + 1; + start = ' '; + if (!letters && !numbers) { + start = 0; + end = Integer.MAX_VALUE; + } + } + + char[] buffer = new char[count]; + int gap = end - start; + + while (count-- != 0) { + char ch; + if (chars == null) { + ch = (char) (rnd.nextInt(gap) + start); + } else { + ch = chars[rnd.nextInt(gap) + start]; + } + if ((letters && Character.isLetter(ch)) + || (numbers && Character.isDigit(ch)) + || (!letters && !numbers)) + { + if(ch >= 56320 && ch <= 57343) { + if(count == 0) { + count++; + } else { + // low surrogate, insert high surrogate after putting it in + buffer[count] = ch; + count--; + buffer[count] = (char) (55296 + rnd.nextInt(128)); + } + } else if(ch >= 55296 && ch <= 56191) { + if(count == 0) { + count++; + } else { + // high surrogate, insert low surrogate before putting it in + buffer[count] = (char) (56320 + rnd.nextInt(128)); + count--; + buffer[count] = ch; + } + } else if(ch >= 56192 && ch <= 56319) { + // private high surrogate, no effing clue, so skip it + count++; + } else { + buffer[count] = ch; + } + } else { + count++; + } + } + return new String(buffer); + } + public static String random(int count) { + return random(count, false, false); + } + + public static String randomAscii(int count) { + return random(count, 32, 127, false, false); + } + + public static String randomAlphabetic(int count) { + return random(count, true, false); + } + + public static String randomAlphanumeric(int count) { + return random(count, true, true); + } + + public static String randomNumeric(int count) { + return random(count, false, true); + } + + public static String random(int count, boolean letters, boolean numbers) { + return random(count, 0, 0, letters, numbers); + } + + public static String random(int count, int start, int end, boolean letters, boolean numbers) { + return random(count, start, end, letters, numbers, null, RANDOM); + } + + public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars) { + return random(count, start, end, letters, numbers, chars, RANDOM); + } +} diff -r f82b730c798b -r 99dd9e50f37e test/sqeutil/TEST.properties diff -r f82b730c798b -r 99dd9e50f37e test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java Mon Nov 11 23:17:30 2013 -0800 @@ -0,0 +1,62 @@ +/* + * 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 7194897 + * @summary JSR 292: Cannot create more than 16 instances of an anonymous class + * @author Robert Field + * @library /lib/testlibrary + * @compile -XDignore.symbol.file ManyNewInstanceAnonTest.java + * @run main ClassFileInstaller ManyNewInstanceAnonTest + * @run main/othervm -Xbootclasspath/a:. -Xverify:all ManyNewInstanceAnonTest + */ +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import sun.misc.Unsafe; + +public class ManyNewInstanceAnonTest { + + static final int REPS = 20; + static final Class klass = ManyNewInstanceAnonTest.class; + + public static void main(String[] args) throws Exception { + Class c = Unsafe.getUnsafe().defineAnonymousClass(klass, readClassFile(), null); + for (int i = 0; i < REPS; ++i) { + System.out.printf("%d: %s\n", i, c.newInstance()); + } + System.out.println("Passed."); + } + + private static byte[] readClassFile() throws Exception { + try (InputStream in = klass.getResourceAsStream(klass.getSimpleName() + ".class"); + ByteArrayOutputStream out = new ByteArrayOutputStream()) + { + int b; + while ((b = in.read()) != -1) { + out.write(b); + } + return out.toByteArray(); + } + } +}