Test framework fix: Load kotlin test classes in separate class loader
This commit is contained in:
@@ -229,8 +229,10 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
Class[] interfaces = aClass.getInterfaces();
|
||||
assertEquals(2, interfaces.length);
|
||||
assertEquals(0, aClass.getDeclaredMethods().length);
|
||||
assertTrue(Annotation.class == interfaces[0] || Annotation.class == interfaces[1]);
|
||||
assertTrue(JetObject.class == interfaces[0] || JetObject.class == interfaces[1]);
|
||||
Class annotationClass = getCorrespondingClass(Annotation.class);
|
||||
Class jetObjectClass = getCorrespondingClass(JetObject.class);
|
||||
assertTrue(annotationClass == interfaces[0] || annotationClass == interfaces[1]);
|
||||
assertTrue(jetObjectClass == interfaces[0] || jetObjectClass == interfaces[1]);
|
||||
assertTrue(aClass.isAnnotation());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
public class ClassLoaderIsolationUtil {
|
||||
|
||||
public static void assertEquals(Class<?> expected, Class<?> actual) {
|
||||
if (actual == null) {
|
||||
assertNull(expected);
|
||||
}
|
||||
else Assert.assertEquals(getClassFromClassLoader(expected, actual.getClassLoader()), actual);
|
||||
}
|
||||
|
||||
public static Class<? extends Annotation> getAnnotationClass(Class<? extends Annotation> annotationClass, ClassLoader classLoader) {
|
||||
return (Class<? extends Annotation>) getClassFromClassLoader(annotationClass, classLoader);
|
||||
}
|
||||
|
||||
public static Object getAnnotationAttribute(Object annotation, String name) {
|
||||
try {
|
||||
return annotation.getClass().getMethod(name).invoke(annotation);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Class<?> getClassFromClassLoader(Class<?> classForName, ClassLoader classLoader) {
|
||||
try {
|
||||
return classLoader.loadClass(classForName.getName());
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class ClassPathInParentClassLoaderTest extends CodegenTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected GeneratedClassLoader createClassLoader(@NotNull ClassFileFactory factory) {
|
||||
ClassLoader parentClassLoader = new URLClassLoader(getClassPathURLs(), CodegenTestCase.class.getClassLoader());
|
||||
ClassLoader parentClassLoader = new URLClassLoader(getClassPathURLs(), null);
|
||||
initializedClassLoader = new GeneratedClassLoader(factory, parentClassLoader);
|
||||
return initializedClassLoader;
|
||||
}
|
||||
|
||||
@@ -25,12 +25,14 @@ import org.jetbrains.jet.JetTestCaseBuilder;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.codegen.forTestCompile.ForTestCompileRuntime;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.utils.ExceptionUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
@@ -109,7 +111,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
|
||||
fail("Double initialization of class loader in same test");
|
||||
}
|
||||
|
||||
initializedClassLoader = new GeneratedClassLoader(factory, CodegenTestCase.class.getClassLoader(), getClassPathURLs());
|
||||
initializedClassLoader = new GeneratedClassLoader(factory, null, getClassPathURLs());
|
||||
return initializedClassLoader;
|
||||
}
|
||||
|
||||
@@ -123,6 +125,13 @@ public abstract class CodegenTestCase extends UsefulTestCase {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
//add runtime library
|
||||
urls.add(ForTestCompileRuntime.runtimeJarForTests().toURI().toURL());
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
}
|
||||
@@ -201,4 +210,12 @@ public abstract class CodegenTestCase extends UsefulTestCase {
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
public Class<? extends Annotation> getCorrespondingAnnotationClass(Class<? extends Annotation> classForName) {
|
||||
return ClassLoaderIsolationUtil.getAnnotationClass(classForName, initializedClassLoader);
|
||||
}
|
||||
|
||||
public Class<?> getCorrespondingClass(Class<?> classForName) {
|
||||
return ClassLoaderIsolationUtil.getClassFromClassLoader(classForName, initializedClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class JUnitUsageGenTest extends CodegenTestCase {
|
||||
@@ -49,8 +50,9 @@ public class JUnitUsageGenTest extends CodegenTestCase {
|
||||
Class<?> namespaceClass = generateNamespaceClass();
|
||||
Method method = namespaceClass.getMethod("foo", Method.class);
|
||||
method.setAccessible(true);
|
||||
Test annotation = method.getAnnotation(Test.class);
|
||||
assertEquals(annotation.timeout(), 0l);
|
||||
assertEquals(annotation.expected(), Test.None.class);
|
||||
Annotation annotation = method.getAnnotation(getCorrespondingAnnotationClass(Test.class));
|
||||
assertEquals(ClassLoaderIsolationUtil.getAnnotationAttribute(annotation, "timeout"), 0l);
|
||||
ClassLoaderIsolationUtil.assertEquals(Test.None.class, (Class<?>) ClassLoaderIsolationUtil.getAnnotationAttribute(annotation,
|
||||
"expected"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,9 @@ public class JetValueParameterAnnotationTest extends CodegenTestCase {
|
||||
for (int i = 0, length = annotations.length; i < length; i++) {
|
||||
assertSize(1, annotations[i]);
|
||||
Annotation annotation = annotations[i][0];
|
||||
assertEquals(JetValueParameter.class, annotation.annotationType());
|
||||
assertEquals(expected[i].name(), ((JetValueParameter) annotation).name());
|
||||
assertEquals(expected[i].type(), ((JetValueParameter) annotation).type());
|
||||
ClassLoaderIsolationUtil.assertEquals(JetValueParameter.class, annotation.annotationType());
|
||||
assertEquals(expected[i].name(), ClassLoaderIsolationUtil.getAnnotationAttribute(annotation, "name"));
|
||||
assertEquals(expected[i].type(), ClassLoaderIsolationUtil.getAnnotationAttribute(annotation, "type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -47,10 +48,11 @@ public class KotlinClassAnnotationTest extends CodegenTestCase {
|
||||
"}\n");
|
||||
Class aClass = generateClass(NAMESPACE_NAME + "." + CLASS_NAME);
|
||||
|
||||
assertTrue(aClass.isAnnotationPresent(KotlinClass.class));
|
||||
KotlinClass kotlinClass = (KotlinClass) aClass.getAnnotation(KotlinClass.class);
|
||||
Class<? extends Annotation> annotationClass = getCorrespondingAnnotationClass(KotlinClass.class);
|
||||
assertTrue(aClass.isAnnotationPresent(annotationClass));
|
||||
Annotation kotlinClass = aClass.getAnnotation(annotationClass);
|
||||
|
||||
ClassData data = JavaProtoBufUtil.readClassDataFrom(kotlinClass.data());
|
||||
ClassData data = JavaProtoBufUtil.readClassDataFrom((String[]) ClassLoaderIsolationUtil.getAnnotationAttribute(kotlinClass, "data"));
|
||||
|
||||
Set<String> callableNames = collectCallableNames(data.getClassProto().getMemberList(), data.getNameResolver());
|
||||
assertSameElements(Arrays.asList("foo", "bar"), callableNames);
|
||||
|
||||
@@ -19,13 +19,11 @@ package org.jetbrains.jet.codegen;
|
||||
import jet.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.ConfigurationKind;
|
||||
import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
|
||||
import org.jetbrains.jet.descriptors.serialization.NameResolver;
|
||||
import org.jetbrains.jet.descriptors.serialization.PackageData;
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
|
||||
import org.jetbrains.jet.descriptors.serialization.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -51,10 +49,14 @@ public class KotlinPackageAnnotationTest extends CodegenTestCase {
|
||||
"object C\n");
|
||||
Class aClass = generateClass(PackageClassUtils.getPackageClassFqName(NAMESPACE_NAME).asString());
|
||||
|
||||
assertTrue(aClass.isAnnotationPresent(KotlinPackage.class));
|
||||
KotlinPackage kotlinPackage = (KotlinPackage) aClass.getAnnotation(KotlinPackage.class);
|
||||
Class<? extends Annotation> annotationClass = getCorrespondingAnnotationClass(KotlinPackage.class);
|
||||
assertTrue(aClass.isAnnotationPresent(annotationClass));
|
||||
assertTrue(aClass.isAnnotationPresent(annotationClass));
|
||||
|
||||
PackageData data = JavaProtoBufUtil.readPackageDataFrom(kotlinPackage.data());
|
||||
Annotation kotlinPackage = aClass.getAnnotation(annotationClass);
|
||||
|
||||
PackageData data = JavaProtoBufUtil.readPackageDataFrom((String[]) ClassLoaderIsolationUtil.getAnnotationAttribute(kotlinPackage,
|
||||
"data"));
|
||||
|
||||
Set<String> callableNames = collectCallableNames(data.getPackageProto().getMemberList(), data.getNameResolver());
|
||||
assertSameElements(Arrays.asList("foo", "bar", "C"), callableNames);
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
public class KotlinPackageFragmentAnnotationTest extends CodegenTestCase {
|
||||
public static final FqName NAMESPACE_NAME = new FqName("test");
|
||||
|
||||
@@ -42,12 +44,17 @@ public class KotlinPackageFragmentAnnotationTest extends CodegenTestCase {
|
||||
// The file which is not a facade is a package fragment
|
||||
String fqName = fileName.substring(0, fileName.length() - ".class".length()).replace('/', '.');
|
||||
Class aClass = generateClass(fqName);
|
||||
assertTrue("No KotlinPackageFragment annotation on a package fragment",
|
||||
aClass.isAnnotationPresent(KotlinPackageFragment.class));
|
||||
|
||||
KotlinPackageFragment annotation = (KotlinPackageFragment) aClass.getAnnotation(KotlinPackageFragment.class);
|
||||
Class<? extends Annotation> annotationClass = getCorrespondingAnnotationClass(KotlinPackageFragment.class);
|
||||
|
||||
assertTrue("No KotlinPackageFragment annotation on a package fragment",
|
||||
aClass.isAnnotationPresent(annotationClass));
|
||||
|
||||
Annotation kotlinPackageFragment = aClass.getAnnotation(annotationClass);
|
||||
|
||||
assertTrue("KotlinPackageFragment annotation is written with an unsupported format",
|
||||
AbiVersionUtil.isAbiVersionCompatible(annotation.abiVersion()));
|
||||
AbiVersionUtil.isAbiVersionCompatible(
|
||||
(Integer) ClassLoaderIsolationUtil.getAnnotationAttribute(kotlinPackageFragment, "abiVersion")));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -414,10 +414,11 @@ public class NamespaceGenTest extends CodegenTestCase {
|
||||
public void testIntRange() throws Exception {
|
||||
loadText("fun foo() = 1..10");
|
||||
Method main = generateFunction();
|
||||
IntRange result = (IntRange) main.invoke(null);
|
||||
assertTrue(result.contains(1));
|
||||
assertTrue(result.contains(10));
|
||||
assertFalse(result.contains(11));
|
||||
Object result = main.invoke(null);
|
||||
Method contains = result.getClass().getMethod("contains", Integer.TYPE);
|
||||
assertTrue((Boolean) contains.invoke(result, 1));
|
||||
assertTrue((Boolean) contains.invoke(result, 10));
|
||||
assertFalse((Boolean) contains.invoke(result, 11));
|
||||
}
|
||||
|
||||
public void testSubstituteJavaMethodTypeParameters() throws Exception {
|
||||
|
||||
@@ -108,8 +108,17 @@ public class TestlibTest extends UsefulTestCase {
|
||||
ClassFileFactory classFileFactory = generationState.getFactory();
|
||||
|
||||
classLoader = new GeneratedClassLoader(classFileFactory,
|
||||
new URLClassLoader(new URL[] {ForTestCompileRuntime.runtimeJarForTests().toURI().toURL(), junitJar.toURI().toURL()},
|
||||
TestCase.class.getClassLoader()));
|
||||
new URLClassLoader(new URL[] {ForTestCompileRuntime.runtimeJarForTests().toURI().toURL()},
|
||||
null)) {
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
if (name.startsWith("junit.") || name.startsWith("org.junit.")) {
|
||||
//In other way we don't find any test cause will have two different TestCase classes!
|
||||
return TestlibTest.class.getClassLoader().loadClass(name);
|
||||
}
|
||||
return super.loadClass(name);
|
||||
}
|
||||
};
|
||||
|
||||
typeMapper = generationState.getTypeMapper();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user