/**
* Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite
* contributors
*
* This file is part of EvoSuite.
*
* EvoSuite is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* EvoSuite is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
*/
package org.evosuite.testcase;
import com.examples.with.different.packagename.AbstractEnumInInnerClass;
import com.examples.with.different.packagename.AbstractEnumUser;
import com.examples.with.different.packagename.EnumInInnerClass;
import com.examples.with.different.packagename.EnumUser;
import org.evosuite.ga.ConstructionFailedException;
import org.evosuite.testcase.statements.*;
import org.evosuite.testcase.variable.ArrayIndex;
import org.evosuite.testcase.variable.VariableReference;
import org.evosuite.utils.generic.GenericConstructor;
import org.evosuite.utils.generic.GenericMethod;
import org.evosuite.utils.generic.WildcardTypeImpl;
import org.junit.Assert;
import org.junit.Test;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServlet;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.Set;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Created by Andrea Arcuri on 02/07/15.
*/
public class TestCodeVisitorTest {
public static <T extends Servlet> T foo(T servlet) {
return servlet;
}
public static <T> T bar(T obj) {
return obj;
}
public static class ClassWithGeneric<T extends Servlet> {
public T hello(T servlet) {
return servlet;
}
}
public static class FakeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public FakeServlet() {
}
}
@Test
public void testGenerics_methodWithExtends() throws NoSuchMethodException, ConstructionFailedException {
//first construct a test case for the Generic method
TestCase tc = new DefaultTestCase();
TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(FakeServlet.class.getDeclaredConstructor(), FakeServlet.class), 0, 0);
VariableReference genericClass = TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(ClassWithGeneric.class.getDeclaredConstructor(), ClassWithGeneric.class), 1, 0);
Method m = ClassWithGeneric.class.getDeclaredMethod("hello", Servlet.class);
GenericMethod gm = new GenericMethod(m, ClassWithGeneric.class);
TestFactory.getInstance().addMethodFor(tc, genericClass, gm, 2);
//Check if generic types were correctly analyzed/inferred
Type[] types = gm.getParameterTypes();
Assert.assertEquals(1, types.length); //only 1 input
Type type = types[0];
Assert.assertNotNull(type);
TypeVariable<?> tv = (TypeVariable<?>) type;
Assert.assertEquals(1, tv.getBounds().length);
Class<?> upper = (Class<?>) tv.getBounds()[0];
Assert.assertEquals(Servlet.class, upper);
//Finally, visit the test
TestCodeVisitor visitor = new TestCodeVisitor();
tc.accept(visitor); //should not throw exception
}
@Test
public void testGenerics_staticMethod() throws NoSuchMethodException, ConstructionFailedException {
//first construct a test case for the Generic method
TestCase tc = new DefaultTestCase();
TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(Object.class.getDeclaredConstructor(), Object.class), 0, 0);
Method m = TestCodeVisitorTest.class.getDeclaredMethod("bar", Object.class);
GenericMethod gm = new GenericMethod(m, TestCodeVisitorTest.class);
TestFactory.getInstance().addMethod(tc, gm, 1, 0);
//Check if generic types were correctly analyzed/inferred
Type[] types = gm.getParameterTypes();
Assert.assertEquals(1, types.length); //only 1 input
Type type = types[0];
Assert.assertNotNull(type);
WildcardTypeImpl wt = (WildcardTypeImpl) type;
Assert.assertEquals(0, wt.getLowerBounds().length);
Assert.assertEquals(1, wt.getUpperBounds().length);
Class<?> upper = (Class<?>) wt.getUpperBounds()[0];
Assert.assertEquals(Object.class, upper);
//Finally, visit the test
TestCodeVisitor visitor = new TestCodeVisitor();
tc.accept(visitor); //should not throw exception
System.out.println(visitor.getCode());
}
@Test
public void testGenerics_staticMethodWithExtends() throws NoSuchMethodException, ConstructionFailedException {
//first construct a test case for the Generic method
TestCase tc = new DefaultTestCase();
TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(FakeServlet.class.getDeclaredConstructor(), FakeServlet.class), 0, 0);
Method m = TestCodeVisitorTest.class.getDeclaredMethod("foo", Servlet.class);
GenericMethod gm = new GenericMethod(m, TestCodeVisitorTest.class);
TestFactory.getInstance().addMethod(tc, gm, 1, 0);
//Check if generic types were correctly analyzed/inferred
Type[] types = gm.getParameterTypes();
Assert.assertEquals(1, types.length); //only 1 input
Type type = types[0];
Assert.assertNotNull(type);
WildcardTypeImpl wt = (WildcardTypeImpl) type;
Assert.assertEquals(0, wt.getLowerBounds().length);
Assert.assertEquals(1, wt.getUpperBounds().length);
Class<?> upper = (Class<?>) wt.getUpperBounds()[0];
Assert.assertEquals(Object.class, upper);
//Finally, visit the test
TestCodeVisitor visitor = new TestCodeVisitor();
tc.accept(visitor); //should not throw exception
}
@Test
public void testClashingImportNames() throws NoSuchMethodException, ConstructionFailedException {
TestCase tc = new DefaultTestCase();
TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.class.getDeclaredConstructor(), com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.class), 0, 0);
TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.class.getDeclaredConstructor(), com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.class), 1, 0);
TestCodeVisitor visitor = new TestCodeVisitor();
tc.accept(visitor);
System.out.println(visitor.getCode());
Set<Class<?>> imports = visitor.getImports();
// Imported
assertTrue(imports.contains(com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.class));
// Not imported as the fully qualified name is used
assertFalse(imports.contains(com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.class));
Assert.assertEquals("ExampleWithInnerClass", visitor.getClassName(com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.class));
Assert.assertEquals("com.examples.with.different.packagename.subpackage.ExampleWithInnerClass", visitor.getClassName(com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.class));
}
@Test
public void testClashingImportNamesSubClasses() throws NoSuchMethodException, ConstructionFailedException {
TestCase tc = new DefaultTestCase();
TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.Foo.class.getDeclaredConstructor(), com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.Foo.class), 0, 0);
TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.Bar.class.getDeclaredConstructor(), com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.Bar.class), 1, 0);
TestCodeVisitor visitor = new TestCodeVisitor();
tc.accept(visitor);
System.out.println(visitor.getCode());
Set<Class<?>> imports = visitor.getImports();
// Imported
assertTrue(imports.contains(com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.class));
// Not imported as the fully qualified name is used
assertFalse(imports.contains(com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.class));
Assert.assertEquals("ExampleWithInnerClass", visitor.getClassName(com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.class));
Assert.assertEquals("com.examples.with.different.packagename.subpackage.ExampleWithInnerClass", visitor.getClassName(com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.class));
Assert.assertEquals("ExampleWithInnerClass.Foo", visitor.getClassName(com.examples.with.different.packagename.otherpackage.ExampleWithInnerClass.Foo.class));
Assert.assertEquals("com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.Bar", visitor.getClassName(com.examples.with.different.packagename.subpackage.ExampleWithInnerClass.Bar.class));
}
@Test
public void testCastAndBoxingInArray() {
// short[] shortArray0 = new short[5];
// Long[] longArray0 = new Long[5];
// longArray0[0] = (Long) shortArray0[1]; <-- this gives a compile error
TestCase tc = new DefaultTestCase();
ArrayStatement shortArrayStatement = new ArrayStatement(tc, short[].class, 5);
tc.addStatement(shortArrayStatement);
ArrayStatement longArrayStatement = new ArrayStatement(tc, Long[].class, 5);
tc.addStatement(longArrayStatement);
ArrayIndex longIndex = new ArrayIndex(tc, longArrayStatement.getArrayReference(), 0);
ArrayIndex shortIndex = new ArrayIndex(tc, shortArrayStatement.getArrayReference(), 1);
AssignmentStatement assignmentStatement = new AssignmentStatement(tc, longIndex, shortIndex);
tc.addStatement(assignmentStatement);
String code = tc.toCode();
System.out.println(tc);
assertFalse(code.contains("longArray0[0] = (Long) shortArray0[1]"));
}
@Test
public void testWrapperCastInArray() {
// Short[] shortArray0 = new Short[5];
// Integer[] integerArray0 = new Integer[9];
// integerArray0[0] = (Integer) shortArray0[3];
TestCase tc = new DefaultTestCase();
ArrayStatement shortArrayStatement = new ArrayStatement(tc, Short[].class, 5);
tc.addStatement(shortArrayStatement);
ArrayStatement intArrayStatement = new ArrayStatement(tc, Integer[].class, 9);
tc.addStatement(intArrayStatement);
ArrayIndex intIndex = new ArrayIndex(tc, intArrayStatement.getArrayReference(), 0);
ArrayIndex shortIndex = new ArrayIndex(tc, shortArrayStatement.getArrayReference(), 3);
AssignmentStatement assignmentStatement = new AssignmentStatement(tc, intIndex, shortIndex);
tc.addStatement(assignmentStatement);
String code = tc.toCode();
System.out.println(tc);
assertFalse(code.contains("integerArray0[0] = (Integer) shortArray0[3]"));
}
@Test
public void testInnerClassEnum() throws Throwable {
//first construct a test case for the Generic method
TestCase tc = new DefaultTestCase();
VariableReference userObject = TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(EnumUser.class.getDeclaredConstructor(), EnumUser.class), 0, 0);
EnumPrimitiveStatement primitiveStatement = new EnumPrimitiveStatement(tc, EnumInInnerClass.AnEnum.class);
primitiveStatement.setValue(EnumInInnerClass.AnEnum.FOO);
VariableReference enumObject = tc.addStatement(primitiveStatement);
Method m = EnumUser.class.getDeclaredMethod("foo", EnumInInnerClass.AnEnum.class);
GenericMethod gm = new GenericMethod(m, EnumUser.class);
MethodStatement ms = new MethodStatement(tc, gm, userObject, Arrays.asList(enumObject));
tc.addStatement(ms);
//Finally, visit the test
TestCodeVisitor visitor = new TestCodeVisitor();
tc.accept(visitor); //should not throw exception
String code = visitor.getCode();
assertTrue(code.contains("= EnumInInnerClass.AnEnum.FOO"));
}
/*
* There are some weird enum constructs in Closure, so we need to check that enum names
* don't contain the name of the anonymous class they might represent
*/
@Test
public void testInnerClassAbstractEnum() throws NoSuchMethodException, ConstructionFailedException {
//first construct a test case for the Generic method
TestCase tc = new DefaultTestCase();
VariableReference userObject = TestFactory.getInstance().addConstructor(tc,
new GenericConstructor(AbstractEnumUser.class.getDeclaredConstructor(), AbstractEnumUser.class), 0, 0);
EnumPrimitiveStatement primitiveStatement = new EnumPrimitiveStatement(tc, AbstractEnumInInnerClass.AnEnum.class);
primitiveStatement.setValue(AbstractEnumInInnerClass.AnEnum.FOO);
VariableReference enumObject = tc.addStatement(primitiveStatement);
Method m = AbstractEnumUser.class.getDeclaredMethod("foo", AbstractEnumInInnerClass.AnEnum.class);
GenericMethod gm = new GenericMethod(m, AbstractEnumUser.class);
MethodStatement ms = new MethodStatement(tc, gm, userObject, Arrays.asList(enumObject));
tc.addStatement(ms);
//Finally, visit the test
TestCodeVisitor visitor = new TestCodeVisitor();
tc.accept(visitor); //should not throw exception
String code = visitor.getCode();
System.out.println(code);
assertFalse(code.contains("= AbstractEnumInInnerClass.AnEnum.1.FOO"));
assertTrue(code.contains("= AbstractEnumInInnerClass.AnEnum.FOO"));
}
}