/* * Copyright 2010-2015 JetBrains s.r.o. * * 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 org.jetbrains.kotlin.codegen; import junit.framework.*; import junit.textui.TestRunner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.common.messages.MessageRenderer; import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler; import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.ContentRootsKt; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager; import org.jetbrains.kotlin.psi.KtClass; import org.jetbrains.kotlin.psi.KtDeclaration; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContextUtils; import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.KotlinTestUtils; import org.jetbrains.kotlin.test.KotlinTestWithEnvironment; import org.jetbrains.kotlin.test.TestJdkKind; import org.jetbrains.kotlin.test.testFramework.TestRunnerUtil; import java.io.File; import java.lang.reflect.Modifier; public class StdlibTest extends KotlinTestWithEnvironment { private GeneratedClassLoader classLoader; @Override protected KotlinCoreEnvironment createEnvironment() { @SuppressWarnings("deprecation") File[] runtimeClasspath = ForTestCompileRuntime.runtimeClassesForTests(); CompilerConfiguration configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.JDK_NO_RUNTIME, TestJdkKind.FULL_JDK, runtimeClasspath); JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.kotlinTestJarForTests()); File junitJar = new File("libraries/lib/junit-4.11.jar"); assertTrue(junitJar.exists()); JvmContentRootsKt.addJvmClasspathRoot(configuration, junitJar); ContentRootsKt.addKotlinSourceRoot(configuration, KotlinTestUtils.getHomeDirectory() + "/libraries/stdlib/test"); configuration.put( CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, new PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, false) ); KotlinCoreEnvironment environment = KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); ModuleVisibilityManager moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.getProject()); for (File path: runtimeClasspath) { moduleVisibilityManager.addFriendPath(path.getPath()); } return environment; } public void testStdlib() throws ClassNotFoundException { GenerationState state = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate(getEnvironment()); if (state == null) { fail("There were compilation errors"); } classLoader = new GeneratedClassLoader(state.getFactory(), ForTestCompileRuntime.runtimeAndReflectJarClassLoader()) { @Override public Class<?> loadClass(@NotNull String name) throws ClassNotFoundException { if (name.startsWith("junit.") || name.startsWith("org.junit.")) { return StdlibTest.class.getClassLoader().loadClass(name); } return super.loadClass(name); } }; TestSuite tests = new TestSuite("Standard Library Tests"); for (KtFile file : getEnvironment().getSourceFiles()) { // Skip JS tests if (file.getVirtualFile().getPath().contains("/js/")) continue; for (KtDeclaration declaration : file.getDeclarations()) { if (!(declaration instanceof KtClass)) continue; ClassDescriptor descriptor = (ClassDescriptor) BindingContextUtils.getNotNull( state.getBindingContext(), BindingContext.DECLARATION_TO_DESCRIPTOR, declaration ); Test test = createTest(classLoader, state.getTypeMapper().mapClass(descriptor).getClassName()); if (test != null) { tests.addTest(test); } } } TestResult result = new TestRunner(System.err).doRun(tests); if (!result.wasSuccessful()) { fail("Some stdlib tests failed, see stderr for details"); } } @Override protected void tearDown() throws Exception { super.tearDown(); // This is important to prevent a memory leak (ClassFileFactory transitively retains all code generation results) classLoader.dispose(); } @Nullable private static Test createTest(@NotNull ClassLoader classLoader, @NotNull String className) { try { Class<?> aClass = classLoader.loadClass(className); if (Modifier.isAbstract(aClass.getModifiers()) || !Modifier.isPublic(aClass.getModifiers()) || !Modifier.isPublic(aClass.getConstructor().getModifiers())) { return null; } return TestCase.class.isAssignableFrom(aClass) ? new TestSuite(aClass) : TestRunnerUtil.isJUnit4TestClass(aClass) ? new JUnit4TestAdapter(aClass) : null; } catch (NoSuchMethodException | ClassNotFoundException e) { // Ignore test classes we can't instantiate return null; } } }