/*
* Copyright (C) 2014, United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
*
* The Java Pathfinder core (jpf-core) platform is licensed under the
* Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java8;
import org.junit.Ignore;
import org.junit.Test;
import gov.nasa.jpf.util.test.TestJPF;
/**
* @author Nastaran Shafiei <nastaran.shafiei@gmail.com>
*/
public class LambdaTest extends TestJPF{
static class EnforcedException extends RuntimeException {
// nothing in here
}
@Test
public void testFuncObjAssignment() {
if(verifyUnhandledException(EnforcedException.class.getName())) {
Runnable r = () -> {
throw new EnforcedException(); // make sure it gets here
};
assertTrue(r != null);
(new Thread(r)).start();
}
}
public interface FI1 {
void sam();
}
public interface FI2 extends FI1 {
@Override
public String toString();
}
@Test
public void testSyntheticFuncObjClass() {
if (verifyNoPropertyViolation()) {
FI2 fi = () -> {
return;
};
assertTrue(fi != null);
Class cls = fi.getClass();
assertEquals(cls.getInterfaces().length, 1);
assertEquals(cls.getDeclaredMethods().length, 1);
assertSame(cls.getInterfaces()[0], FI2.class);
assertSame(cls.getSuperclass(), Object.class);
}
}
public interface FI3 {
public String ret();
}
@Test
public void testSAMReturn() {
if (verifyNoPropertyViolation()) {
FI3 rt = () -> {
return "something";
};
assertEquals(rt.ret(),"something");
}
}
public class C {
int x = 1;
}
public interface IncX {
public int incX(C o);
}
@Test
public void testLambdaArgument() {
if (verifyNoPropertyViolation()) {
IncX fo = (arg) -> {
return ++arg.x;
};
C o = new C();
assertEquals(fo.incX(o),2);
assertEquals(fo.incX(o),3);
}
}
static Integer io = new Integer(20);
@Test
public void testClosure() {
if (verifyNoPropertyViolation()) {
int i = 10;
FI1 fi = () -> {
assertSame(i,10);
assertSame(io.intValue(), 20);
};
fi.sam();
}
}
static void method(FI1 fi) {
fi.sam();
}
@Test
public void testPassingToMethod() {
if (verifyUnhandledException(EnforcedException.class.getName())) {
int i = 10;
method(() -> {
assertSame(i,10);
assertSame(io.intValue(), 20);
throw new EnforcedException();
});
}
}
// When invokedynamic executes for the first time, it creates a new function object.
// Re-executing the same bytecode returns the existing function object.
@Test
public void testRepeatInvokedynamic() {
if (verifyNoPropertyViolation()) {
int i = 10;
FI1 f1, f2 = null;
for(int j=0; j<2; j++) {
f1 = () -> {
System.out.println("hello world!");
};
if(j==1) {
assertTrue(f1!=null);
assertSame(f1,f2);
}
f2 = f1;
}
}
}
public static class C2 {
public static void throwException() {
throw new EnforcedException();
}
}
@Test
public void testDoubleCloneOperator() {
if (verifyUnhandledException(EnforcedException.class.getName())) {
FI1 fi = C2::throwException;
fi.sam();
}
}
static class A {
static {
if(true) {
throw new EnforcedException();
}
}
}
@Test
public void testInitDoubleCloneOperator() {
if (verifyUnhandledException(EnforcedException.class.getName())) {
new Thread(A::new).start();
}
}
static class D {
public D() {
System.out.println('D');
}
static final B b = new B();
}
static class B {
static final D a = new D();
public B() {
System.out.println('B');
}
}
@Test@Ignore// TODO fix
public void testClinitDeadlock() {
if(verifyDeadlock()) {
new Thread(D::new).start();
new B();
}
}
@Test
public void testLambdaTypeName() {
if(verifyNoPropertyViolation()) {
Runnable r1 = (A::new);
Runnable r2 = (B::new);
assertFalse(r1.getClass().getName().equals(r2.getClass().getName()));
}
}
public interface FI {
default boolean returnTrue() {
return true;
}
@Override
public String toString();
public String toString(int i);
}
@Test
public void testLambdaWithOverridenDefaultMethods() {
if(verifyNoPropertyViolation()) {
FI fi = (int i) -> {return "output:"+ i;};
assertEquals(fi.toString(10),"output:10");
}
}
public interface FI4 {
}
public interface FI5 extends FI {
@Override
public boolean equals(Object obj);
}
@Test
public void testLambdaWithMultipleSuperInterfaces() {
if(verifyNoPropertyViolation()) {
FI5 fi = (int i) -> {return "output:"+ i;};
assertEquals(fi.toString(10),"output:10");
}
}
public static class Foo {
Integer i = 0;
static Integer j = 1;
public FI1 invokSam(FI1 fi) {
fi.sam();
return fi;
}
public FI1 withFreeVar() {
return invokSam(()->{Foo foo = this;});
}
public static FI1 withStatic(Foo foo) {
return foo.invokSam(()->{Foo.j = 10;});
}
}
@Test
public void testFreeVariables() {
if(verifyNoPropertyViolation()) {
Foo foo = new Foo();
FI1 fi1 = foo.withFreeVar();
FI1 fi2 = foo.withFreeVar();
assertFalse(fi1==fi2);
fi1 = Foo.withStatic(foo);
fi2 = Foo.withStatic(foo);
assertSame(fi1,fi2);
}
}
}