8003280: Add lambda tests

Turn on lambda expression, method reference and default method support

Reviewed-by: jjg
This commit is contained in:
Maurizio Cimadamore 2012-11-17 19:01:03 +00:00
parent c39f1d99b4
commit a494f0ab86
451 changed files with 15433 additions and 488 deletions

View file

@ -0,0 +1,18 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Test that lambda conversion is only for SAM interface, not abstract class
* @compile/fail/ref=AbstractClass_neg.out -XDrawDiagnostics AbstractClass_neg.java
*/
public class AbstractClass_neg {
abstract class SAM {
abstract int m();
}
void test() {
SAM s = ()-> 6;
}
}

View file

@ -0,0 +1,2 @@
AbstractClass_neg.java:16:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf)
1 error

View file

@ -0,0 +1,26 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Test accessing non-static variable from lambda expressions in static context
* @compile/fail/ref=AccessNonStatic_neg.out -XDrawDiagnostics AccessNonStatic_neg.java
*/
public class AccessNonStatic_neg {
private int n = 0;
static {
((Runnable) ()-> {
System.out.println(this);
System.out.println(n);
}).run();
}
public static void test() {
((Runnable) ()-> {
Object o = this;
n++;
}).run();
}
}

View file

@ -0,0 +1,5 @@
AccessNonStatic_neg.java:15:32: compiler.err.non-static.cant.be.ref: kindname.variable, this
AccessNonStatic_neg.java:16:32: compiler.err.non-static.cant.be.ref: kindname.variable, n
AccessNonStatic_neg.java:22:24: compiler.err.non-static.cant.be.ref: kindname.variable, this
AccessNonStatic_neg.java:23:13: compiler.err.non-static.cant.be.ref: kindname.variable, n
4 errors

View file

@ -0,0 +1,25 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Negative test of capture of "effectively final" local variable in lambda expressions
* @compile/fail/ref=EffectivelyFinal_neg.out -XDrawDiagnostics EffectivelyFinal_neg.java
*/
public class EffectivelyFinal_neg {
void test() {
String s = "a";
String s2 = "a";
int n = 1;
((Runnable)
()-> {
s2 = "b"; //re-assign illegal here
System.out.println(n);
System.out.println(s);
s = "b"; // not effectively final
}
).run();
n = 2; // not effectively final
}
}

View file

@ -0,0 +1,5 @@
EffectivelyFinal_neg.java:17:17: compiler.err.cant.ref.non.effectively.final.var: s2, (compiler.misc.lambda)
EffectivelyFinal_neg.java:18:36: compiler.err.cant.ref.non.effectively.final.var: n, (compiler.misc.lambda)
EffectivelyFinal_neg.java:19:36: compiler.err.cant.ref.non.effectively.final.var: s, (compiler.misc.lambda)
EffectivelyFinal_neg.java:20:17: compiler.err.cant.ref.non.effectively.final.var: s, (compiler.misc.lambda)
4 errors

View file

@ -0,0 +1,17 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Test invalid lambda expressions
* @compile/fail/ref=InvalidExpression1.out -XDrawDiagnostics InvalidExpression1.java
*/
import java.util.Comparator;
public class InvalidExpression1 {
void test() {
Comparator<Number> c = (Number n1, Number n2)-> { 42; }; //not a statement
Comparator<Number> c = (Number n1, Number n2)-> { return 42 }; //";" expected
}
}

View file

@ -0,0 +1,3 @@
InvalidExpression1.java:14:59: compiler.err.not.stmt
InvalidExpression1.java:15:68: compiler.err.expected: ';'
2 errors

View file

@ -0,0 +1,16 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Test invalid lambda expressions
* @compile/fail/ref=InvalidExpression3.out -XDrawDiagnostics InvalidExpression3.java
*/
import java.util.Comparator;
public class InvalidExpression3 {
void test() {
Comparator<Integer> c2 = (Integer i1, Integer i2) -> { return "0"; }; //return type need to match
}
}

View file

@ -0,0 +1,2 @@
InvalidExpression3.java:14:71: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.String, int))
1 error

View file

@ -0,0 +1,18 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Test invalid lambda expressions
* @compile/fail/ref=InvalidExpression4.out -XDrawDiagnostics InvalidExpression4.java
*/
public class InvalidExpression4 {
interface SAM {
void m(int i);
}
void test() {
SAM s = (Integer i) -> { }; //parameters not match, boxing not allowed here
}
}

View file

@ -0,0 +1,2 @@
InvalidExpression4.java:16:17: compiler.err.prob.found.req: (compiler.misc.incompatible.arg.types.in.lambda)
1 error

View file

@ -0,0 +1,14 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Test invalid lambda expressions
* @compile/fail/ref=InvalidExpression5.out -XDrawDiagnostics InvalidExpression5.java
*/
public class InvalidExpression5 {
void test() {
Object o = (int n) -> { }; // Invalid target type
}
}

View file

@ -0,0 +1,2 @@
InvalidExpression5.java:12:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf)
1 error

View file

@ -0,0 +1,19 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @summary Add lambda tests
* Test invalid lambda expressions
* @compile/fail/ref=InvalidExpression6.out -XDrawDiagnostics InvalidExpression6.java
*/
public class InvalidExpression6 {
interface SAM {
void m(int i);
}
void test() {
SAM s = (int n) -> { break; }; //break not allowed
s = (int n) -> { continue; }; //continue not allowed
}
}

View file

@ -0,0 +1,3 @@
InvalidExpression6.java:16:30: compiler.err.break.outside.switch.loop
InvalidExpression6.java:17:26: compiler.err.cont.outside.loop
2 errors

View file

@ -0,0 +1,119 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test lambda expressions for existing SAM interfaces like Runnable and Comparator<T>
* @compile LambdaTest1.java
* @run main LambdaTest1
*/
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
public class LambdaTest1 {
private static String assertionStr = "";
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
private static void test1(Runnable r) {
r.run();
}
void test2(Object o) {
if(o instanceof Runnable)
((Runnable)o).run();
}
Runnable test3() {
return ()-> { assertionStr += "Runnable6"; };
}
public static void main(String[] args) {
//lambda expressions for SAM interface Runnable:
//assign:
Runnable r = ()-> { assertionStr += "Runnable1 "; };
r.run();
//cast:
((Runnable)()-> { assertionStr += "Runnable2 "; }).run();
Object o = (Runnable)()-> {};
o = (Runnable)()-> {
switch (assertionStr) {
case "Runnable1 Runnable2 ":
assertionStr += "Runnable3 ";
break;
default:
throw new AssertionError();
}
return;
};
//method parameter:
test1(()-> { assertionStr += "Runnable4 "; return; });
LambdaTest1 test = new LambdaTest1();
test.test2((Runnable)()-> { assertionStr += "Runnable5 "; });
//return type:
r = test.test3();
r.run();
assertTrue(assertionStr.equals("Runnable1 Runnable2 Runnable4 Runnable5 Runnable6"));
//lambda expressions for SAM interface Comparator<T>:
List<Integer> list = new ArrayList<Integer>();
list.add(4);
list.add(10);
list.add(-5);
list.add(100);
list.add(9);
Collections.sort(list, (Integer i1, Integer i2)-> i2 - i1);
String result = "";
for(int i : list)
result += i + " ";
assertTrue(result.equals("100 10 9 4 -5 "));
Collections.sort(list,
(i1, i2) -> {
String s1 = i1.toString();
String s2 = i2.toString();
return s1.length() - s2.length();
});
result = "";
for(int i : list)
result += i + " ";
assertTrue(result.equals("9 4 10 -5 100 "));
}
}

View file

@ -0,0 +1,118 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test lambda expressions for different method signatures (parameter and return type)
* @compile LambdaTest2.java
* @run main LambdaTest2
*/
public class LambdaTest2 {
private static int count = 0;
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
public static void main(String[] args) {
LambdaTest2 test = new LambdaTest2();
test.method2((int n) -> { ; });
test.method2(n -> { }); // "int" is optional here
test.method2((int n) -> { }); // ";" is optional here
test.method2((int n) -> { return; }); // ";" is mandatory here
test.method2((int n) -> { count += n; });
assertTrue(count == 10);
VoidInt vi = (int i) -> {
switch (i) {
case 0:
System.out.println("normal");
break;
default:
System.out.println("invalid");
}
};
test.method3(()-> { count++; });
test.method3(() -> {});
assertTrue(count == 11);
VoidVoid vv = ()-> { while(true)
if(false)
break;
else
continue;
};
IntVoid iv1 = () -> 42;
IntVoid iv2 = () -> { return 43; };//";" is mandatory here
assertTrue(iv1.ivMethod() == 42);
assertTrue(iv2.ivMethod() == 43);
IntInt ii1 = (int n) -> n+1;
IntInt ii2 = n -> 42;
IntInt ii3 = n -> { return 43; };
IntInt ii4 =
(int n) -> {
if(n > 0)
return n+1;
else
return n-1;
};
assertTrue(ii1.iiMethod(1) == 2);
assertTrue(ii2.iiMethod(1) == 42);
assertTrue(ii3.iiMethod(1) == 43);
assertTrue(ii4.iiMethod(-1) == -2);
}
void method2(VoidInt a) {
a.viMethod(10);
}
void method3(VoidVoid a) {
a.vvMethod();
}
//SAM type interfaces
interface VoidInt {
void viMethod(int n);
}
interface VoidVoid {
void vvMethod();
}
interface IntVoid {
int ivMethod();
}
interface IntInt {
int iiMethod(int n);
}
}

View file

@ -0,0 +1,56 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test capture of "effectively final" local variable in lambda expressions
* @compile LambdaTest3.java
* @run main LambdaTest3
*/
public class LambdaTest3 {
private static int count = 0;
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
public static void main(String[] args) {
final int N = 100;
int n = 2; //effectively final variable
Runnable r = ((Runnable)
() -> {
count += N;
count += n;
}
);
assertTrue(count == 0);
r.run();
assertTrue(count == 102);
}
}

View file

@ -0,0 +1,72 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test accessing "this" in lambda expressions
* @compile LambdaTest4.java
* @run main LambdaTest4
*/
public class LambdaTest4 {
private String thisStr;
private static int count = 0;
{
((Runnable)
()-> {
this.init();
assertTrue(this.toString().equals(thisStr));
count++;
}
).run();
}
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
private void init() {
thisStr = this.toString();
}
private void m() {
String s1 = this.toString();
((Runnable)
()-> {
assertTrue(this.toString().equals(thisStr));
assertTrue(this.toString().equals(s1));
}
).run();
}
public static void main(String[] args) {
LambdaTest4 test = new LambdaTest4();
assertTrue(count == 1);
test.m();
}
}

View file

@ -0,0 +1,79 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test lambda expressions inside lambda expressions
* @compile LambdaTest5.java
* @run main LambdaTest5
*/
public class LambdaTest5 {
interface A {
int m();
}
interface B {
int make (int i);
}
private static int count = 0;
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
static A a;
static A a2;
static A a3;
static A a4;
public static void main(String[] args) {
B b = (int i) -> ((A)()-> 5).m();
assertTrue(b.make(0) == 5);
a = () -> ((A)()-> { return 6; }).m(); //self reference
assertTrue(a.m() == 6);
a2 = ()-> {
A an = ()-> { return 7; }; //self reference
return an.m();
};
assertTrue(a2.m() == 7);
a3 = () -> a3.m(); //self reference
try {
a3.m();
} catch(StackOverflowError e) {
count++;
}
assertTrue(count==1);
a4 = ()-> ((B)(int i)-> ((A)()-> 9).m() ).make(0);
assertTrue(a4.m() == 9);
}
}

View file

@ -0,0 +1,118 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test bridge methods for certain SAM conversions
* @compile LambdaTest6.java
* @run main LambdaTest6
*/
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
public class LambdaTest6<T> {
interface H {Object m();}
interface K<U> {void m(U element);}
interface L extends K<String> {} //generic substitution
interface M {void m(String s);}
interface KM extends K<String>, M{} //generic substitution
interface N extends H {String m();} //covariant return
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
private Set<String> setOfStringObject() {
Set<String> s = new HashSet<>();
s.add("java.lang.String");
s.add("java.lang.Object");
return s;
}
private void test1()
{
L la = s -> { };
la.m("hi");
Class<? extends L> c1 = la.getClass();
Method[] methods = c1.getDeclaredMethods();
Set<String> types = setOfStringObject();
for(Method m : methods) {
assertTrue(m.getName().equals("m"));
Class[] parameterTypes = m.getParameterTypes();
assertTrue(parameterTypes.length == 1);
assertTrue(types.remove(parameterTypes[0].getName()));
}
assertTrue(types.isEmpty() || (types.size() == 1 && types.contains("java.lang.String")));
}
private void test2()
{
KM km = s -> { };
//km.m("hi");
Class<? extends KM> c2 = km.getClass();
Method[] methods = c2.getDeclaredMethods();
Set<String> types = setOfStringObject();
for(Method m : methods) {
assertTrue(m.getName().equals("m"));
Class[] parameterTypes = m.getParameterTypes();
assertTrue(parameterTypes.length == 1);
assertTrue(types.remove(parameterTypes[0].getName()));
}
assertTrue(types.isEmpty());
}
private void test3()
{
N na = ()-> "hi";
assertTrue( na.m().equals("hi") );
assertTrue( ((H)na).m().equals("hi") );
Class<? extends N> c3 = na.getClass();
Method[] methods = c3.getDeclaredMethods();
Set<String> types = setOfStringObject();
for(Method m : methods) {
assertTrue(m.getName().equals("m"));
Class returnType = m.getReturnType();
assertTrue(types.remove(returnType.getName()));
}
assertTrue(types.isEmpty());
}
public static void main(String[] args) {
LambdaTest6 test = new LambdaTest6();
test.test1();
test.test2();
test.test3();
}
}

View file

@ -0,0 +1,151 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test SAM conversion of lambda expressions in context of assignment, method call, return statement and cast.
* @compile SamConversion.java
* @run main SamConversion
*/
public class SamConversion {
static interface Foo {
Integer m(int i);
}
static interface Bar {
int m(Integer i) throws Exception;
}
private static String assertionStr = "";
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
private static void test1(Foo foo) {
assertTrue(foo.m(1) == 2);
}
private static void test2(Bar bar) {
try {
assertTrue(bar.m(1) == 2);
} catch (Exception e){
assertTrue(false);
}
}
private static Bar test3(int i) {
switch (i) {
case 0:
return n -> n + 1;
case 1:
return (Integer n) -> 2 * n;
case 2:
return (Integer n) -> {return new Integer(n-1);};
case 3:
return n -> {throw new Exception();};
default:
return null;
}
}
public static void main(String[] args) {
//assign:
Foo foo = (int n) -> n + 1; //explicit type and boxing
assertTrue(foo.m(1) == 2);
foo = n -> n + 1; //type inferrred and boxing
assertTrue(foo.m(1) == 2);
Bar bar = (Integer n) -> n + 1; //explicit type and unboxing
try {
assertTrue(bar.m(1) == 2);
} catch (Exception e) {
assertTrue(false);
}
bar = (Integer n) -> new Integer(n+1); //explicit type and unboxing twice
try {
assertTrue(bar.m(1) == 2);
} catch (Exception e) {
assertTrue(false);
}
bar = n -> n.intValue() + 1; //type inferred
try {
assertTrue(bar.m(1) == 2);
} catch (Exception e) {
assertTrue(false);
}
bar = n -> n + 1; // type inferred and unboxing
try {
assertTrue(bar.m(1) == 2);
} catch (Exception e) {
assertTrue(false);
}
//cast:
assertTrue(((Foo)n -> {return n+1;}).m(1) == 2); //statement (instead of expression) in lambda body
try {
assertTrue(((Bar)n -> {return n+1;}).m(1) == 2); //statement in lambda body
} catch (Exception e) {
assertTrue(false);
}
//method parameter:
test1((int n) -> new Integer(n+1)); //explicit type
test2((Integer n) -> n.intValue() + 1); //explicit type
//return statement:
bar = test3(0);
try {
assertTrue(bar.m(1) == 2);
} catch (Exception e) {
assertTrue(false);
}
bar = test3(1);
try {
assertTrue(bar.m(3) == 6);
} catch (Exception e) {
assertTrue(false);
}
bar = test3(2);
try {
assertTrue(bar.m(10) == 9);
} catch (Exception e) {
assertTrue(false);
}
bar = test3(3);
try {
bar.m(10);
assertTrue(false);
} catch (Exception e) {}
}
}

View file

@ -0,0 +1,277 @@
/*
* 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.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* Test SAM conversion of lambda expressions in combinations of different contexts,
* lambda body types(statement/expression), explict/implicit target type etc, to verify
* SAM conversion being conducted successfully as expected.
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
public class SamConversionComboTest {
enum FInterface {
A("A", "interface A { Integer m(int i); }"),
B("B", "interface B { int m(Integer i); }"),
C("C", "interface C { int m(Integer i) throws Exception; }");
String interfaceType;
String interfaceDef;
FInterface(String interfaceType, String interfaceDef) {
this.interfaceType = interfaceType;
this.interfaceDef = interfaceDef;
}
String getParameterType() {
switch(this) {
case A:
return "int";
case B:
case C:
return "Integer";
default:
return null;
}
}
}
enum Context {
ASSIGNMENT("#FType f = #LBody;"),
METHOD_CALL("void method1(#FType f) { }\n" +
" void method2() {\n" +
" method1(#LBody);\n" +
" }"),
CONSTRUCTOR("X x = new X(#LBody);"),
RETURN_OF_METHOD("#FType method1() {\n" +
" return #LBody;\n" +
"}"),
ARRAY_INITIALIZER("Object[] oarray = {\"a\", 1, (#FType)#LBody};"),
LAMBDA_BODY("#FType f = n -> ((#FType)#LBody).m(n);"),
CAST("void test() throws Exception { int n = ((#FType)#LBody).m(1); }"),
CONDITIONAL_EXPRESSION("#FType f = 2 > 1 ? #LBody : null;");
String context;
Context(String context) {
this.context = context;
}
String getContext(FInterface f, LambdaKind lk, LambdaBody lb, ReturnValue rv) {
return context.replace("#FType", f.interfaceType).replace("#LBody", lb.getLambdaBody(f, lk, rv));
}
}
enum LambdaKind {
EXPRESSION("#VAL"),
STATEMENT("{return #VAL;}"),
EXCEPTION_STMT("{throw new Exception();}");
String stmt;
LambdaKind(String stmt) {
this.stmt = stmt;
}
}
enum ReturnValue {
INT("i + 1"),
INTEGER("new Integer(i+1)"),
INT2("i.intValue() + 1"),
STRING("i + \"\""),
DOUBLE("i * 1.0");
String rValue;
ReturnValue(String rValue) {
this.rValue = rValue;
}
}
enum LambdaBody {
IMPLICIT("i -> #RET"),//type inferred
EXPLICIT("(#Type i) -> #RET");//explicit type
String bodyStr;
LambdaBody(String bodyStr) {
this.bodyStr = bodyStr;
}
String getLambdaBody(FInterface fi, LambdaKind lk, ReturnValue rv) {
return bodyStr.replace("#Type", fi.getParameterType()).replace("#RET", lk.stmt.replace("#VAL", rv.rValue));
}
}
boolean checkSamConversion() {
if(lambdaKind != LambdaKind.EXCEPTION_STMT && (returnValue == ReturnValue.DOUBLE || returnValue == ReturnValue.STRING)) //return type mismatch
return false;
if(context != Context.CONSTRUCTOR) {//context other than construcotr argument
if(fInterface != FInterface.C && lambdaKind == LambdaKind.EXCEPTION_STMT)
return false;
if(fInterface == FInterface.A && returnValue == ReturnValue.INT2)
return false;
}
else { //constructor argument context
//match X(A a) or X(B b) or X(C c)
if (lambdaKind == LambdaKind.EXCEPTION_STMT) {
return false; //ambiguous target type
}
else if(lambdaBody == LambdaBody.IMPLICIT) {
if(returnValue != ReturnValue.INTEGER) //ambiguous target type
return false;
}
else { //explicit parameter type
if(fInterface.getParameterType().equals("Integer")) //ambiguous target type
//e.g. X x = new X((Integer i) -> i + 1);
return false;
if(returnValue == ReturnValue.INT2)
//e.g. X x = new X(int i -> i.intValue() + 1);
return false;
}
}
return true;
}
SourceFile samSourceFile = new SourceFile("FInterface.java", "#C") {
public String toString() {
String interfaces = "";
for(FInterface fi : FInterface.values())
interfaces += fi.interfaceDef + "\n";
return template.replace("#C", interfaces);
}
};
String clientTemplate = "class Client {\n" +
" #Context\n" +
"}\n\n" +
"class X {\n" +
" int value = 0;\n\n" +
" X(A a) {\n" +
" value = a.m(6);\n" +
" }\n\n" +
" X(B b) {\n" +
" value = b.m(7);\n" +
" }\n\n" +
" X(C c) {\n" +
" try {\n" +
" value = c.m(8);\n" +
" } catch (Exception e){}\n" +
" }\n" +
"}";
SourceFile clientSourceFile = new SourceFile("Client.java", clientTemplate) {
public String toString() {
return template.replace("#Context", context.getContext(fInterface, lambdaKind, lambdaBody, returnValue));
}
};
void test() throws Exception {
System.out.println("\n====================================");
System.out.println(fInterface + ", " + context + ", " + lambdaKind + ", " + lambdaBody + ", " + returnValue);
System.out.println(samSourceFile + "\n");
String clientFileStr = clientSourceFile.toString();
System.out.println(clientFileStr.substring(0, clientFileStr.indexOf("\n\n")));
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
DiagnosticChecker dc = new DiagnosticChecker();
JavacTask ct = (JavacTask)tool.getTask(null, null, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
ct.analyze();
if (dc.errorFound == checkSamConversion()) {
throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile);
}
count++;
}
abstract class SourceFile extends SimpleJavaFileObject {
protected String template;
public SourceFile(String filename, String template) {
super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
this.template = template;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return toString();
}
public abstract String toString();
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound = false;
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
errorFound = true;
}
}
}
FInterface fInterface;
Context context;
LambdaBody lambdaBody;
LambdaKind lambdaKind;
ReturnValue returnValue;
static int count = 0;
SamConversionComboTest(FInterface f, Context c, LambdaBody lb, LambdaKind lk, ReturnValue rv) {
fInterface = f;
context = c;
lambdaKind = lk;
lambdaBody = lb;
returnValue = rv;
}
public static void main(String[] args) throws Exception {
for(Context ct : Context.values()) {
for (FInterface fi : FInterface.values()) {
for (LambdaKind lk: LambdaKind.values()) {
for (LambdaBody lb : LambdaBody.values()) {
for(ReturnValue rv : ReturnValue.values()) {
new SamConversionComboTest(fi, ct, lb, lk, rv).test();
}
}
}
}
}
System.out.println("total tests: " + count);
}
}