Extract jps-tests to separate module

Remove dependency to idea-full to build jps-plugin with Java 1.6

Original commit: 46b5305666
This commit is contained in:
Nikolay Krasko
2015-12-10 14:52:57 +03:00
parent 7e0a39e2d6
commit 72b18cd2e8
27 changed files with 27 additions and 11 deletions
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="jps-plugin" scope="TEST" />
<orderEntry type="module" module-name="descriptors" scope="TEST" />
<orderEntry type="module" module-name="frontend.java" scope="TEST" />
<orderEntry type="module" module-name="backend" scope="TEST" />
<orderEntry type="module" module-name="util" scope="TEST" />
<orderEntry type="module" module-name="daemon-common" scope="TEST" />
<orderEntry type="module" module-name="compiler-tests" scope="TEST" />
<orderEntry type="module" module-name="build-common" scope="TEST" />
<orderEntry type="library" scope="TEST" name="jps-test" level="project" />
<orderEntry type="library" scope="TEST" name="idea-full" level="project" />
</component>
</module>
@@ -0,0 +1,45 @@
/*
* 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.jps.build
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.incremental.testingUtils.Modification
import org.jetbrains.kotlin.incremental.testingUtils.ModifyContent
import org.jetbrains.kotlin.jps.incremental.CacheVersionProvider
abstract class AbstractIncrementalCacheVersionChangedTest : AbstractIncrementalJpsTest(allowNoFilesWithSuffixInTestData = true) {
override fun performAdditionalModifications(modifications: List<Modification>) {
val modifiedFiles = modifications.filterIsInstance<ModifyContent>().map { it.path }
val paths = projectDescriptor.dataManager.dataPaths
val targets = projectDescriptor.allModuleTargets
val hasKotlin = HasKotlinMarker(projectDescriptor.dataManager)
if (modifiedFiles.any { it.endsWith("clear-has-kotlin") }) {
targets.forEach { hasKotlin.clean(it) }
}
if (modifiedFiles.none { it.endsWith("do-not-change-cache-versions") }) {
val cacheVersionProvider = CacheVersionProvider(paths)
val versions = getVersions(cacheVersionProvider, targets)
val versionFiles = versions.map { it.formatVersionFile }.filter { it.exists() }
versionFiles.forEach { it.writeText("777") }
}
}
protected open fun getVersions(cacheVersionProvider: CacheVersionProvider, targets: Iterable<ModuleBuildTarget>) =
targets.map { cacheVersionProvider.normalVersion(it) }
}
@@ -0,0 +1,487 @@
/*
* Copyright 2010-2016 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.jps.build
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.testFramework.TestLoggerFactory
import com.intellij.testFramework.UsefulTestCase
import junit.framework.TestCase
import org.apache.log4j.ConsoleAppender
import org.apache.log4j.Level
import org.apache.log4j.Logger
import org.apache.log4j.PatternLayout
import org.jetbrains.jps.api.CanceledStatus
import org.jetbrains.jps.builders.BuildResult
import org.jetbrains.jps.builders.CompileScopeTestBuilder
import org.jetbrains.jps.builders.JpsBuildTestCase
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl
import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase
import org.jetbrains.jps.builders.java.dependencyView.Callbacks
import org.jetbrains.jps.builders.logging.BuildLoggingManager
import org.jetbrains.jps.cmdline.ProjectDescriptor
import org.jetbrains.jps.incremental.BuilderRegistry
import org.jetbrains.jps.incremental.IncProjectBuilder
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.jps.incremental.ModuleLevelBuilder
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.testingUtils.*
import org.jetbrains.kotlin.jps.incremental.JpsLookupStorageProvider
import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget
import org.jetbrains.kotlin.jps.incremental.getKotlinCache
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.keysToMap
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.util.*
import kotlin.properties.Delegates
abstract class AbstractIncrementalJpsTest(
private val allowNoFilesWithSuffixInTestData: Boolean = false,
private val checkDumpsCaseInsensitively: Boolean = false,
private val allowNoBuildLogFileInTestData: Boolean = false
) : JpsBuildTestCase() {
companion object {
val COMPILATION_FAILED = "COMPILATION FAILED"
// change to "/tmp" or anything when default is too long (for easier debugging)
val TEMP_DIRECTORY_TO_USE = File(FileUtilRt.getTempDirectory())
val DEBUG_LOGGING_ENABLED = System.getProperty("debug.logging.enabled") == "true"
}
protected open val enableExperimentalIncrementalCompilation = false
protected var testDataDir: File by Delegates.notNull()
protected var workDir: File by Delegates.notNull()
protected var projectDescriptor: ProjectDescriptor by Delegates.notNull()
protected var lookupsDuringTest: MutableSet<LookupSymbol> by Delegates.notNull()
protected var mapWorkingToOriginalFile: MutableMap<File, File> = hashMapOf()
protected open val buildLogFinder: BuildLogFinder
get() = BuildLogFinder(isExperimentalEnabled = enableExperimentalIncrementalCompilation)
private fun enableDebugLogging() {
com.intellij.openapi.diagnostic.Logger.setFactory(TestLoggerFactory::class.java)
TestLoggerFactory.dumpLogToStdout("")
TestLoggerFactory.enableDebugLogging(myTestRootDisposable, "#org")
val console = ConsoleAppender()
console.layout = PatternLayout("%d [%p|%c|%C{1}] %m%n");
console.threshold = Level.ALL
console.activateOptions()
Logger.getRootLogger().addAppender(console)
}
private val systemPropertiesBackup = run {
val props = System.getProperties()
val output = ByteArrayOutputStream()
props.store(output, "System properties backup")
output.toByteArray()
}
private fun restoreSystemProperties() {
val input = ByteArrayInputStream(systemPropertiesBackup)
val props = Properties()
props.load(input)
System.setProperties(props)
}
override fun setUp() {
super.setUp()
System.setProperty("kotlin.jps.tests", "true")
lookupsDuringTest = hashSetOf()
IncrementalCompilation.setIsExperimental(enableExperimentalIncrementalCompilation)
if (DEBUG_LOGGING_ENABLED) {
enableDebugLogging()
}
}
override fun tearDown() {
restoreSystemProperties()
super.tearDown()
}
protected open val mockConstantSearch: Callbacks.ConstantAffectionResolver?
get() = null
private fun createLookupTracker(): TestLookupTracker = TestLookupTracker()
protected open fun checkLookups(@Suppress("UNUSED_PARAMETER") lookupTracker: LookupTracker, compiledFiles: Set<File>) {
}
private fun build(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().all(), checkLookups: Boolean = true): MakeResult {
val workDirPath = FileUtil.toSystemIndependentName(workDir.absolutePath)
val logger = MyLogger(workDirPath)
projectDescriptor = createProjectDescriptor(BuildLoggingManager(logger))
val lookupTracker = createLookupTracker()
projectDescriptor.project.setTestingContext(TestingContext(lookupTracker, logger))
try {
val builder = IncProjectBuilder(projectDescriptor, BuilderRegistry.getInstance(), myBuildParams, CanceledStatus.NULL, mockConstantSearch, true)
val buildResult = BuildResult()
builder.addMessageHandler(buildResult)
builder.build(scope.build(), false)
if (checkLookups) {
checkLookups(lookupTracker, logger.compiledFiles)
}
val lookups = lookupTracker.lookups.map { LookupSymbol(it.name, it.scopeFqName) }
lookupsDuringTest.addAll(lookups)
if (!buildResult.isSuccessful) {
val errorMessages =
buildResult
.getMessages(BuildMessage.Kind.ERROR)
.map { it.messageText }
.map { it.replace("^.+:\\d+:\\s+".toRegex(), "").trim() }
.joinToString("\n")
return MakeResult(logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n", true, null)
}
else {
return MakeResult(logger.log, false, createMappingsDump(projectDescriptor))
}
}
finally {
projectDescriptor.dataManager.flush(false)
projectDescriptor.release()
}
}
private fun initialMake(): MakeResult {
val makeResult = build()
val initBuildLogFile = File(testDataDir, "init-build.log")
if (initBuildLogFile.exists()) {
UsefulTestCase.assertSameLinesWithFile(initBuildLogFile.absolutePath, makeResult.log)
}
else {
assertFalse("Initial make failed:\n$makeResult", makeResult.makeFailed)
}
return makeResult
}
private fun make(): MakeResult {
return build()
}
private fun rebuild(): MakeResult {
return build(CompileScopeTestBuilder.rebuild().allModules(), checkLookups = false)
}
private fun rebuildAndCheckOutput(makeOverallResult: MakeResult) {
val outDir = File(getAbsolutePath("out"))
val outAfterMake = File(getAbsolutePath("out-after-make"))
if (outDir.exists()) {
FileUtil.copyDir(outDir, outAfterMake)
}
val rebuildResult = rebuild()
assertEquals("Rebuild failed: ${rebuildResult.makeFailed}, last make failed: ${makeOverallResult.makeFailed}. Rebuild result: $rebuildResult",
rebuildResult.makeFailed, makeOverallResult.makeFailed)
if (!outAfterMake.exists()) {
assertFalse(outDir.exists())
}
else {
assertEqualDirectories(outDir, outAfterMake, makeOverallResult.makeFailed)
}
if (!makeOverallResult.makeFailed) {
if (checkDumpsCaseInsensitively && rebuildResult.mappingsDump?.toLowerCase() == makeOverallResult.mappingsDump?.toLowerCase()) {
// do nothing
}
else {
TestCase.assertEquals(rebuildResult.mappingsDump, makeOverallResult.mappingsDump)
}
}
FileUtil.delete(outAfterMake)
}
private fun clearCachesRebuildAndCheckOutput(makeOverallResult: MakeResult) {
FileUtil.delete(BuildDataPathsImpl(myDataStorageRoot).dataStorageRoot!!)
rebuildAndCheckOutput(makeOverallResult)
}
private fun readModuleDependencies(): Map<String, List<DependencyDescriptor>>? {
val dependenciesTxt = File(testDataDir, "dependencies.txt")
if (!dependenciesTxt.exists()) return null
val result = HashMap<String, List<DependencyDescriptor>>()
for (line in dependenciesTxt.readLines()) {
val split = line.split("->")
val module = split[0]
val dependencies = if (split.size > 1) split[1] else ""
val dependencyList = dependencies.split(",").filterNot { it.isEmpty() }
result[module] = dependencyList.map(::parseDependency)
}
return result
}
protected open fun createBuildLog(incrementalMakeResults: List<AbstractIncrementalJpsTest.MakeResult>): String =
buildString {
incrementalMakeResults.forEachIndexed { i, makeResult ->
if (i > 0) append("\n")
append("================ Step #${i + 1} =================\n\n")
append(makeResult.log)
}
}
protected open fun doTest(testDataPath: String) {
testDataDir = File(testDataPath)
workDir = FileUtilRt.createTempDirectory(TEMP_DIRECTORY_TO_USE, "jps-build", null)
val moduleNames = configureModules()
initialMake()
val otherMakeResults = performModificationsAndMake(moduleNames)
val buildLogFile = buildLogFinder.findBuildLog(testDataDir)
val logs = createBuildLog(otherMakeResults)
if (buildLogFile != null && buildLogFile.exists()) {
UsefulTestCase.assertSameLinesWithFile(buildLogFile.absolutePath, logs)
}
else if (!allowNoBuildLogFileInTestData) {
throw IllegalStateException("No build log file in $testDataDir")
}
if (!enableExperimentalIncrementalCompilation && File(testDataDir, "dont-check-caches-in-non-experimental-ic.txt").exists()) return
val lastMakeResult = otherMakeResults.last()
rebuildAndCheckOutput(lastMakeResult)
clearCachesRebuildAndCheckOutput(lastMakeResult)
}
private fun createMappingsDump(project: ProjectDescriptor) =
createKotlinIncrementalCacheDump(project) + "\n\n\n" +
createLookupCacheDump(project) + "\n\n\n" +
createCommonMappingsDump(project) + "\n\n\n" +
createJavaMappingsDump(project)
private fun createKotlinIncrementalCacheDump(project: ProjectDescriptor): String {
return buildString {
for (target in project.allModuleTargets.sortedBy { it.presentableName }) {
append("<target $target>\n")
append(project.dataManager.getKotlinCache(target).dump())
append("</target $target>\n\n\n")
}
}
}
private fun createLookupCacheDump(project: ProjectDescriptor): String {
val sb = StringBuilder()
val p = Printer(sb)
p.println("Begin of Lookup Maps")
p.println()
val lookupStorage = project.dataManager.getStorage(KotlinDataContainerTarget, JpsLookupStorageProvider)
lookupStorage.forceGC()
p.print(lookupStorage.dump(lookupsDuringTest))
p.println()
p.println("End of Lookup Maps")
return sb.toString()
}
private fun createCommonMappingsDump(project: ProjectDescriptor): String {
val resultBuf = StringBuilder()
val result = Printer(resultBuf)
result.println("Begin of SourceToOutputMap")
result.pushIndent()
for (target in project.allModuleTargets) {
result.println(target)
result.pushIndent()
val mapping = project.dataManager.getSourceToOutputMap(target)
mapping.sources.sorted().forEach {
val outputs = mapping.getOutputs(it)!!.sorted()
if (outputs.isNotEmpty()) {
result.println("source $it -> $outputs")
}
}
result.popIndent()
}
result.popIndent()
result.println("End of SourceToOutputMap")
return resultBuf.toString()
}
private fun createJavaMappingsDump(project: ProjectDescriptor): String {
val byteArrayOutputStream = ByteArrayOutputStream()
PrintStream(byteArrayOutputStream).use {
project.dataManager.mappings.toStream(it)
}
return byteArrayOutputStream.toString()
}
protected data class MakeResult(val log: String, val makeFailed: Boolean, val mappingsDump: String?)
private fun performModificationsAndMake(moduleNames: Set<String>?): List<MakeResult> {
val results = arrayListOf<MakeResult>()
val modifications = getModificationsToPerform(testDataDir, moduleNames, allowNoFilesWithSuffixInTestData, TouchPolicy.TIMESTAMP)
for (step in modifications) {
step.forEach { it.perform(workDir, mapWorkingToOriginalFile) }
performAdditionalModifications(step)
if (moduleNames == null) {
preProcessSources(File(workDir, "src"))
}
else {
moduleNames.forEach { preProcessSources(File(workDir, "$it/src")) }
}
results.add(make())
}
return results
}
protected open fun performAdditionalModifications(modifications: List<Modification>) {
}
// null means one module
private fun configureModules(): Set<String>? {
fun prepareModuleSources(moduleName: String?) {
val sourceDirName = moduleName?.let { "$it/src" } ?: "src"
val filePrefix = moduleName?.let { "${it}_" } ?: ""
val sourceDestinationDir = File(workDir, sourceDirName)
val sourcesMapping = copyTestSources(testDataDir, sourceDestinationDir, filePrefix)
mapWorkingToOriginalFile.putAll(sourcesMapping)
preProcessSources(sourceDestinationDir)
}
var moduleNames: Set<String>?
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl = JpsPathUtil.pathToUrl(getAbsolutePath("out"))
val jdk = addJdk("my jdk")
val moduleDependencies = readModuleDependencies()
mapWorkingToOriginalFile = hashMapOf()
if (moduleDependencies == null) {
addModule("module", arrayOf(getAbsolutePath("src")), null, null, jdk)
prepareModuleSources(moduleName = null)
moduleNames = null
}
else {
val nameToModule = moduleDependencies.keys
.keysToMap { addModule(it, arrayOf(getAbsolutePath("$it/src")), null, null, jdk)!! }
for ((moduleName, dependencies) in moduleDependencies) {
val module = nameToModule[moduleName]!!
for (dependency in dependencies) {
JpsModuleRootModificationUtil.addDependency(module, nameToModule[dependency.name],
JpsJavaDependencyScope.COMPILE, dependency.exported)
}
}
for (module in nameToModule.values) {
prepareModuleSources(module.name)
}
moduleNames = nameToModule.keys
}
AbstractKotlinJpsBuildTestCase.addKotlinRuntimeDependency(myProject)
AbstractKotlinJpsBuildTestCase.addKotlinTestRuntimeDependency(myProject)
return moduleNames
}
protected open fun preProcessSources(srcDir: File) {
}
override fun doGetProjectDir(): File? = workDir
private class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase(), BuildLogger {
private val dirtyFiles = ArrayList<File>()
override fun markedAsDirty(files: Iterable<File>) {
dirtyFiles.addAll(files)
}
override fun buildFinished(exitCode: ModuleLevelBuilder.ExitCode) {
if (dirtyFiles.isNotEmpty()) {
logLine("Marked as dirty by Kotlin:")
dirtyFiles
.map { FileUtil.toSystemIndependentName(it.path) }
.sorted()
.forEach { logLine(it) }
dirtyFiles.clear()
}
logLine("Exit code: $exitCode")
logLine("------------------------------------------")
}
private val logBuf = StringBuilder()
val log: String
get() = logBuf.toString()
val compiledFiles = hashSetOf<File>()
override fun isEnabled(): Boolean = true
override fun logCompiledFiles(files: MutableCollection<File>?, builderName: String?, description: String?) {
super.logCompiledFiles(files, builderName, description)
if (builderName == KotlinBuilder.KOTLIN_BUILDER_NAME) {
compiledFiles.addAll(files!!)
}
}
override fun logLine(message: String?) {
logBuf.append(KotlinTestUtils.replaceHashWithStar(message!!.replace("^$rootPath/".toRegex(), " "))).append('\n')
}
}
}
internal val ProjectDescriptor.allModuleTargets: Collection<ModuleBuildTarget>
get() = buildTargetIndex.allTargets.filterIsInstance<ModuleBuildTarget>()
private class DependencyDescriptor(val name: String, val exported: Boolean)
private fun parseDependency(dependency: String): DependencyDescriptor =
DependencyDescriptor(dependency.removeSuffix(EXPORTED_SUFFIX), dependency.endsWith(EXPORTED_SUFFIX))
private val EXPORTED_SUFFIX = "[exported]"
@@ -0,0 +1,124 @@
/*
* 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.jps.build
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.storage.BuildDataPaths
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.CacheVersion
import org.jetbrains.kotlin.incremental.KOTLIN_CACHE_DIRECTORY_NAME
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
import org.jetbrains.kotlin.incremental.testingUtils.Modification
import org.jetbrains.kotlin.incremental.testingUtils.ModifyContent
import org.jetbrains.kotlin.jps.incremental.CacheVersionProvider
import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget
import org.jetbrains.kotlin.utils.Printer
import java.io.File
abstract class AbstractIncrementalLazyCachesTest : AbstractIncrementalJpsTest() {
protected open val expectedCachesFileName: String
get() = "expected-kotlin-caches.txt"
override fun doTest(testDataPath: String) {
super.doTest(testDataPath)
val actual = dumpKotlinCachesFileNames()
val expectedFile = File(testDataPath, expectedCachesFileName)
UsefulTestCase.assertSameLinesWithFile(expectedFile.canonicalPath, actual)
}
override fun performAdditionalModifications(modifications: List<Modification>) {
super.performAdditionalModifications(modifications)
for (modification in modifications) {
if (modification !is ModifyContent) continue
val name = File(modification.path).name
when {
name.endsWith("incremental-compilation") -> {
IncrementalCompilation.setIsEnabled(modification.dataFile.readAsBool())
}
name.endsWith("experimental-compilation") -> {
IncrementalCompilation.setIsExperimental(modification.dataFile.readAsBool())
}
}
}
}
fun File.readAsBool(): Boolean {
val content = this.readText()
return when (content.trim()) {
"on" -> true
"off" -> false
else -> throw IllegalStateException("$this content is expected to be 'on' or 'off'")
}
}
private fun dumpKotlinCachesFileNames(): String {
val sb = StringBuilder()
val p = Printer(sb)
val targets = projectDescriptor.allModuleTargets
val paths = projectDescriptor.dataManager.dataPaths
val versions = CacheVersionProvider(paths)
dumpCachesForTarget(p, paths, KotlinDataContainerTarget, versions.dataContainerVersion())
for (target in targets.sortedBy { it.presentableName }) {
dumpCachesForTarget(p, paths, target, versions.normalVersion(target), versions.experimentalVersion(target),
subdirectory = KOTLIN_CACHE_DIRECTORY_NAME)
}
return sb.toString()
}
private fun dumpCachesForTarget(
p: Printer,
paths: BuildDataPaths,
target: BuildTarget<*>,
vararg cacheVersions: CacheVersion,
subdirectory: String? = null
) {
p.println(target)
p.pushIndent()
val dataRoot = paths.getTargetDataRoot(target).let { if (subdirectory != null) File(it, subdirectory) else it }
cacheVersions
.map { it.formatVersionFile }
.filter { it.exists() }
.sortedBy { it.name }
.forEach { p.println(it.name) }
kotlinCacheNames(dataRoot).sorted().forEach { p.println(it) }
p.popIndent()
}
private fun kotlinCacheNames(dir: File): List<String> {
val result = arrayListOf<String>()
for (file in dir.walk()) {
if (file.isFile && file.extension == BasicMapsOwner.CACHE_EXTENSION) {
result.add(file.name)
}
}
return result
}
}
@@ -0,0 +1,122 @@
/*
* 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.jps.build;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.JpsBuildTestCase;
import org.jetbrains.jps.model.JpsDummyElement;
import org.jetbrains.jps.model.JpsModuleRootModificationUtil;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
import org.jetbrains.jps.model.java.JpsJavaLibraryType;
import org.jetbrains.jps.model.java.JpsJavaSdkType;
import org.jetbrains.jps.model.library.JpsLibrary;
import org.jetbrains.jps.model.library.JpsOrderRootType;
import org.jetbrains.jps.model.library.JpsTypedLibrary;
import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.util.JpsPathUtil;
import org.jetbrains.kotlin.utils.PathUtil;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
public abstract class AbstractKotlinJpsBuildTestCase extends JpsBuildTestCase {
public static final String TEST_DATA_PATH = "jps-plugin/testData/";
protected File workDir;
@Override
public void setUp() throws Exception {
super.setUp();
System.setProperty("kotlin.jps.tests", "true");
}
@Override
public void tearDown() throws Exception {
System.clearProperty("kotlin.jps.tests");
super.tearDown();
}
protected static File copyTestDataToTmpDir(File testDataDir) throws IOException {
assert testDataDir.exists() : "Cannot find source folder " + testDataDir.getAbsolutePath();
File tmpDir = FileUtil.createTempDirectory("jps-build", null);
FileUtil.copyDir(testDataDir, tmpDir);
return tmpDir;
}
@Override
protected File doGetProjectDir() throws IOException {
return workDir;
}
@Override
protected JpsSdk<JpsDummyElement> addJdk(String name, String path) {
String homePath = System.getProperty("java.home");
String versionString = System.getProperty("java.version");
JpsTypedLibrary<JpsSdk<JpsDummyElement>> jdk = myModel.getGlobal().addSdk(name, homePath, versionString, JpsJavaSdkType.INSTANCE);
jdk.addRoot(JpsPathUtil.pathToUrl(path), JpsOrderRootType.COMPILED);
return jdk.getProperties();
}
protected JpsLibrary addKotlinRuntimeDependency() {
return addKotlinRuntimeDependency(myProject);
}
protected JpsLibrary addKotlinJavaScriptStdlibDependency() {
return addKotlinJavaScriptStdlibDependency(myProject);
}
protected JpsLibrary addKotlinJavaScriptDependency(String libraryName, File libraryFile) {
return addDependency(JpsJavaDependencyScope.COMPILE, myProject.getModules(), false, libraryName, libraryFile);
}
static JpsLibrary addKotlinRuntimeDependency(@NotNull JpsProject project) {
return addKotlinRuntimeDependency(JpsJavaDependencyScope.COMPILE, project.getModules(), false);
}
static JpsLibrary addKotlinTestRuntimeDependency(@NotNull JpsProject project) {
return addDependency(JpsJavaDependencyScope.COMPILE, project.getModules(), false, "kotlin-test", PathUtil.getKotlinPathsForDistDirectory().getKotlinTestPath());
}
static JpsLibrary addKotlinJavaScriptStdlibDependency(@NotNull JpsProject project) {
return addKotlinJavaScriptStdlibDependency(JpsJavaDependencyScope.COMPILE, project.getModules(), false);
}
protected static JpsLibrary addKotlinRuntimeDependency(JpsJavaDependencyScope type, Collection<JpsModule> modules, boolean exported) {
return addDependency(type, modules, exported, "kotlin-runtime", PathUtil.getKotlinPathsForDistDirectory().getRuntimePath());
}
protected static JpsLibrary addKotlinJavaScriptStdlibDependency(JpsJavaDependencyScope type, Collection<JpsModule> modules, boolean exported) {
return addDependency(type, modules, exported, "KotlinJavaScript", PathUtil.getKotlinPathsForDistDirectory().getJsStdLibJarPath());
}
protected static JpsLibrary addDependency(JpsJavaDependencyScope type, Collection<JpsModule> modules, boolean exported, String libraryName, File... file) {
JpsLibrary library = modules.iterator().next().getProject().addLibrary(libraryName, JpsJavaLibraryType.INSTANCE);
for (File fileRoot : file) {
library.addRoot(fileRoot, JpsOrderRootType.COMPILED);
}
for (JpsModule module : modules) {
JpsModuleRootModificationUtil.addDependency(module, library, type, exported);
}
return library;
}
}
@@ -0,0 +1,137 @@
/*
* 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.jps.build
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.containers.StringInterner
import org.jetbrains.kotlin.incremental.components.LookupInfo
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.Position
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
import java.util.*
private val DECLARATION_KEYWORDS = listOf("interface", "class", "enum class", "object", "fun", "operator fun", "val", "var")
private val DECLARATION_STARTS_WITH = DECLARATION_KEYWORDS.map { it + " " }
abstract class AbstractLookupTrackerTest : AbstractIncrementalJpsTest(
allowNoFilesWithSuffixInTestData = true,
allowNoBuildLogFileInTestData = true
) {
// ignore KDoc like comments which starts with `/**`, example: /** text */
val COMMENT_WITH_LOOKUP_INFO = "/\\*[^*]+\\*/".toRegex()
override fun checkLookups(lookupTracker: LookupTracker, compiledFiles: Set<File>) {
if (lookupTracker !is TestLookupTracker) throw AssertionError("Expected TestLookupTracker, but: ${lookupTracker.javaClass}")
val fileToLookups = lookupTracker.lookups.groupBy { it.filePath }
fun checkLookupsInFile(expectedFile: File, actualFile: File) {
val independentFilePath = FileUtil.toSystemIndependentName(actualFile.path)
val lookupsFromFile = fileToLookups[independentFilePath] ?: return
val text = actualFile.readText()
val matchResult = COMMENT_WITH_LOOKUP_INFO.find(text)
if (matchResult != null) {
fail("File $actualFile unexpectedly contains multiline comments. In range ${matchResult.range} found: ${matchResult.value} in $text")
}
val lines = text.lines().toMutableList()
for ((line, lookupsFromLine) in lookupsFromFile.groupBy { it.position.line }) {
val columnToLookups = lookupsFromLine.groupBy { it.position.column }.toList().sortedBy { it.first }
val lineContent = lines[line - 1]
val parts = ArrayList<CharSequence>(columnToLookups.size * 2)
var start = 0
for ((column, lookupsFromColumn) in columnToLookups) {
val end = column - 1
parts.add(lineContent.subSequence(start, end))
val lookups = lookupsFromColumn.distinct().joinToString(separator = " ", prefix = "/*", postfix = "*/") {
val rest = lineContent.substring(end)
val name =
when {
rest.startsWith(it.name) || // same name
rest.startsWith("$" + it.name) || // backing field
DECLARATION_STARTS_WITH.any { rest.startsWith(it) } // it's declaration
-> ""
else -> "(" + it.name + ")"
}
it.scopeKind.toString()[0].toLowerCase().toString() + ":" + it.scopeFqName.let { if (it.isNotEmpty()) it else "<root>" } + name
}
parts.add(lookups)
start = end
}
lines[line - 1] = parts.joinToString("") + lineContent.subSequence(start, lineContent.length)
}
val actual = lines.joinToString("\n")
KotlinTestUtils.assertEqualsToFile(expectedFile, actual)
}
for (actualFile in compiledFiles) {
val expectedFile = mapWorkingToOriginalFile[actualFile]!!
checkLookupsInFile(expectedFile, actualFile)
}
}
override fun preProcessSources(srcDir: File) = dropBlockComments(srcDir)
private fun dropBlockComments(workSrcDir: File) {
for (file in workSrcDir.walkTopDown()) {
if (!file.isFile) continue
val original = file.readText()
val modified = original.replace(COMMENT_WITH_LOOKUP_INFO, "")
if (original != modified) {
file.writeText(modified)
}
}
}
}
class TestLookupTracker : LookupTracker {
val lookups = arrayListOf<LookupInfo>()
private val interner = StringInterner()
override val requiresPosition: Boolean
get() = true
override fun record(filePath: String, position: Position, scopeFqName: String, scopeKind: ScopeKind, name: String) {
val internedFilePath = interner.intern(filePath)
val internedScopeFqName = interner.intern(scopeFqName)
val internedName = interner.intern(name)
lookups.add(LookupInfo(internedFilePath, position, internedScopeFqName, scopeKind, internedName))
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2016 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.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class DataContainerVersionChangedTestGenerated extends AbstractDataContainerVersionChangedTest {
public void testAllFilesPresentInCacheVersionChanged() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("clearedHasKotlin")
public void testClearedHasKotlin() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin/");
doTest(fileName);
}
@TestMetadata("exportedModule")
public void testExportedModule() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule/");
doTest(fileName);
}
@TestMetadata("javaOnlyModulesAreNotAffected")
public void testJavaOnlyModulesAreNotAffected() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected/");
doTest(fileName);
}
@TestMetadata("module1Modified")
public void testModule1Modified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified/");
doTest(fileName);
}
@TestMetadata("module2Modified")
public void testModule2Modified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified/");
doTest(fileName);
}
@TestMetadata("moduleWithConstantModified")
public void testModuleWithConstantModified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified/");
doTest(fileName);
}
@TestMetadata("moduleWithInlineModified")
public void testModuleWithInlineModified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified/");
doTest(fileName);
}
@TestMetadata("touchedFile")
public void testTouchedFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile/");
doTest(fileName);
}
@TestMetadata("touchedOnlyJavaFile")
public void testTouchedOnlyJavaFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile/");
doTest(fileName);
}
@TestMetadata("untouchedFiles")
public void testUntouchedFiles() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles/");
doTest(fileName);
}
@TestMetadata("withError")
public void testWithError() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/withError/");
doTest(fileName);
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2016 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.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/changeIncrementalOption")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class ExperimentalChangeIncrementalOptionTestGenerated extends AbstractExperimentalChangeIncrementalOptionTest {
public void testAllFilesPresentInChangeIncrementalOption() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/changeIncrementalOption"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("experimentalOn")
public void testExperimentalOn() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/changeIncrementalOption/experimentalOn/");
doTest(fileName);
}
@TestMetadata("experimentalOnJavaChanged")
public void testExperimentalOnJavaChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/changeIncrementalOption/experimentalOnJavaChanged/");
doTest(fileName);
}
@TestMetadata("experimentalOnJavaOnly")
public void testExperimentalOnJavaOnly() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/changeIncrementalOption/experimentalOnJavaOnly/");
doTest(fileName);
}
@TestMetadata("experimentalOnOff")
public void testExperimentalOnOff() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/changeIncrementalOption/experimentalOnOff/");
doTest(fileName);
}
@TestMetadata("incrementalOff")
public void testIncrementalOff() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOff/");
doTest(fileName);
}
@TestMetadata("incrementalOffOn")
public void testIncrementalOffOn() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOn/");
doTest(fileName);
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2016 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.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class ExperimentalIncrementalCacheVersionChangedTestGenerated extends AbstractExperimentalIncrementalCacheVersionChangedTest {
public void testAllFilesPresentInCacheVersionChanged() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("clearedHasKotlin")
public void testClearedHasKotlin() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin/");
doTest(fileName);
}
@TestMetadata("exportedModule")
public void testExportedModule() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule/");
doTest(fileName);
}
@TestMetadata("javaOnlyModulesAreNotAffected")
public void testJavaOnlyModulesAreNotAffected() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected/");
doTest(fileName);
}
@TestMetadata("module1Modified")
public void testModule1Modified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified/");
doTest(fileName);
}
@TestMetadata("module2Modified")
public void testModule2Modified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified/");
doTest(fileName);
}
@TestMetadata("moduleWithConstantModified")
public void testModuleWithConstantModified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified/");
doTest(fileName);
}
@TestMetadata("moduleWithInlineModified")
public void testModuleWithInlineModified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified/");
doTest(fileName);
}
@TestMetadata("touchedFile")
public void testTouchedFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile/");
doTest(fileName);
}
@TestMetadata("touchedOnlyJavaFile")
public void testTouchedOnlyJavaFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile/");
doTest(fileName);
}
@TestMetadata("untouchedFiles")
public void testUntouchedFiles() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles/");
doTest(fileName);
}
@TestMetadata("withError")
public void testWithError() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/withError/");
doTest(fileName);
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2016 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.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class ExperimentalIncrementalLazyCachesTestGenerated extends AbstractExperimentalIncrementalLazyCachesTest {
public void testAllFilesPresentInLazyKotlinCaches() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("class")
public void testClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/class/");
doTest(fileName);
}
@TestMetadata("classInheritance")
public void testClassInheritance() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/classInheritance/");
doTest(fileName);
}
@TestMetadata("constant")
public void testConstant() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/constant/");
doTest(fileName);
}
@TestMetadata("function")
public void testFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/function/");
doTest(fileName);
}
@TestMetadata("inlineFunctionWithUsage")
public void testInlineFunctionWithUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithUsage/");
doTest(fileName);
}
@TestMetadata("inlineFunctionWithoutUsage")
public void testInlineFunctionWithoutUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithoutUsage/");
doTest(fileName);
}
@TestMetadata("noKotlin")
public void testNoKotlin() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/noKotlin/");
doTest(fileName);
}
@TestMetadata("topLevelPropertyAccess")
public void testTopLevelPropertyAccess() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/topLevelPropertyAccess/");
doTest(fileName);
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2016 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.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalCacheVersionChangedTestGenerated extends AbstractIncrementalCacheVersionChangedTest {
public void testAllFilesPresentInCacheVersionChanged() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("clearedHasKotlin")
public void testClearedHasKotlin() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin/");
doTest(fileName);
}
@TestMetadata("exportedModule")
public void testExportedModule() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule/");
doTest(fileName);
}
@TestMetadata("javaOnlyModulesAreNotAffected")
public void testJavaOnlyModulesAreNotAffected() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected/");
doTest(fileName);
}
@TestMetadata("module1Modified")
public void testModule1Modified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified/");
doTest(fileName);
}
@TestMetadata("module2Modified")
public void testModule2Modified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified/");
doTest(fileName);
}
@TestMetadata("moduleWithConstantModified")
public void testModuleWithConstantModified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified/");
doTest(fileName);
}
@TestMetadata("moduleWithInlineModified")
public void testModuleWithInlineModified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified/");
doTest(fileName);
}
@TestMetadata("touchedFile")
public void testTouchedFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile/");
doTest(fileName);
}
@TestMetadata("touchedOnlyJavaFile")
public void testTouchedOnlyJavaFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile/");
doTest(fileName);
}
@TestMetadata("untouchedFiles")
public void testUntouchedFiles() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles/");
doTest(fileName);
}
@TestMetadata("withError")
public void testWithError() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/withError/");
doTest(fileName);
}
}
@@ -0,0 +1,68 @@
/*
* 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.jps.build
import org.jetbrains.jps.builders.java.dependencyView.Callbacks
import com.intellij.util.concurrency.FixedFuture
import java.io.File
import java.util.concurrent.Future
class IncrementalConstantSearchTest : AbstractIncrementalJpsTest() {
fun testJavaConstantChangedUsedInKotlin() {
doTest("jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/")
}
fun testJavaConstantUnchangedUsedInKotlin() {
doTest("jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/")
}
fun testKotlinConstantChangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/")
}
fun testKotlinJvmFieldChangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinJvmFieldChangedUsedInJava/")
}
fun testKotlinConstantUnchangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/")
}
fun testKotlinJvmFieldUnchangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinJvmFieldUnchangedUsedInJava/")
}
override val mockConstantSearch: Callbacks.ConstantAffectionResolver?
get() = object : Callbacks.ConstantAffectionResolver {
override fun request(
ownerClassName: String?,
fieldName: String?,
accessFlags: Int,
fieldRemoved: Boolean,
accessChanged: Boolean
): Future<Callbacks.ConstantAffection> {
// We emulate how constant affection service works in IDEA:
// it is able to find Kotlin usages of Java constant, but can't find Java usages of Kotlin constant
val affectedFiles = if (ownerClassName == "JavaClass" && fieldName == "CONST") {
listOf(File(workDir, "src/usage.kt"))
} else {
emptyList()
}
return FixedFuture(Callbacks.ConstantAffection(affectedFiles))
}
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2016 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.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalLazyCachesTestGenerated extends AbstractIncrementalLazyCachesTest {
public void testAllFilesPresentInLazyKotlinCaches() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("class")
public void testClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/class/");
doTest(fileName);
}
@TestMetadata("classInheritance")
public void testClassInheritance() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/classInheritance/");
doTest(fileName);
}
@TestMetadata("constant")
public void testConstant() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/constant/");
doTest(fileName);
}
@TestMetadata("function")
public void testFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/function/");
doTest(fileName);
}
@TestMetadata("inlineFunctionWithUsage")
public void testInlineFunctionWithUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithUsage/");
doTest(fileName);
}
@TestMetadata("inlineFunctionWithoutUsage")
public void testInlineFunctionWithoutUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithoutUsage/");
doTest(fileName);
}
@TestMetadata("noKotlin")
public void testNoKotlin() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/noKotlin/");
doTest(fileName);
}
@TestMetadata("topLevelPropertyAccess")
public void testTopLevelPropertyAccess() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/topLevelPropertyAccess/");
doTest(fileName);
}
}
@@ -0,0 +1,48 @@
/*
* 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.jps.build
import com.intellij.openapi.util.SystemInfoRt
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.kotlin.incremental.testingUtils.Modification
class IncrementalProjectPathCaseChangedTest : AbstractIncrementalJpsTest(checkDumpsCaseInsensitively = true) {
fun testProjectPathCaseChanged() {
doTest("jps-plugin/testData/incremental/custom/projectPathCaseChanged/")
}
fun testProjectPathCaseChangedMultiFile() {
doTest("jps-plugin/testData/incremental/custom/projectPathCaseChangedMultiFile/")
}
override fun doTest(testDataPath: String) {
if (SystemInfoRt.isFileSystemCaseSensitive) {
return
}
super.doTest(testDataPath)
}
override fun performAdditionalModifications(modifications: List<Modification>) {
val module = myProject.modules[0]
val sourceRoot = module.sourceRoots[0].url
assert(sourceRoot.endsWith("/src"))
val newSourceRoot = sourceRoot.replace("/src", "/SRC")
module.removeSourceRoot(sourceRoot, JavaSourceRootType.SOURCE)
module.addSourceRoot(newSourceRoot, JavaSourceRootType.SOURCE)
}
}
@@ -0,0 +1,869 @@
/*
* 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.jps.build
import com.google.common.collect.Lists
import com.intellij.openapi.util.Condition
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.testFramework.LightVirtualFile
import com.intellij.testFramework.UsefulTestCase
import com.intellij.util.ArrayUtil
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.io.ZipUtil
import org.jetbrains.jps.api.CanceledStatus
import org.jetbrains.jps.builders.BuildResult
import org.jetbrains.jps.builders.CompileScopeTestBuilder
import org.jetbrains.jps.builders.JpsBuildTestCase
import org.jetbrains.jps.builders.TestProjectBuilderLogger
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl
import org.jetbrains.jps.builders.logging.BuildLoggingManager
import org.jetbrains.jps.incremental.BuilderRegistry
import org.jetbrains.jps.incremental.IncProjectBuilder
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.CompilerMessage
import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassVisitor
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.junit.Assert
import java.io.*
import java.util.*
import java.util.regex.Pattern
import java.util.zip.ZipOutputStream
class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
companion object {
private val PROJECT_NAME = "kotlinProject"
private val ADDITIONAL_MODULE_NAME = "module2"
private val JDK_NAME = "IDEA_JDK"
private val EXCLUDE_FILES = arrayOf("Excluded.class", "YetAnotherExcluded.class")
private val NOTHING = arrayOf<String>()
private val KOTLIN_JS_LIBRARY = "jslib-example"
private val PATH_TO_KOTLIN_JS_LIBRARY = AbstractKotlinJpsBuildTestCase.TEST_DATA_PATH + "general/KotlinJavaScriptProjectWithDirectoryAsLibrary/" + KOTLIN_JS_LIBRARY
private val KOTLIN_JS_LIBRARY_JAR = "$KOTLIN_JS_LIBRARY.jar"
private val EXPECTED_JS_FILES_IN_OUTPUT_FOR_STDLIB_ONLY = hashSetOf(
"$PROJECT_NAME.js",
"$PROJECT_NAME.meta.js",
"lib/kotlin.js",
"lib/stdlib.meta.js"
)
private val EXPECTED_JS_FILES_IN_OUTPUT_FOR_MODULE_STDLIB_ONLY = hashSetOf(
"$ADDITIONAL_MODULE_NAME.js",
"$ADDITIONAL_MODULE_NAME.meta.js",
"lib/kotlin.js",
"lib/stdlib.meta.js"
)
private val EXPECTED_JS_FILES_IN_OUTPUT_NO_COPY = hashSetOf("$PROJECT_NAME.js", "$PROJECT_NAME.meta.js")
private val EXPECTED_JS_FILES_IN_OUTPUT_WITH_ADDITIONAL_LIB_AND_DEFAULT_DIR = hashSetOf(
"$PROJECT_NAME.js",
"$PROJECT_NAME.meta.js",
"lib/kotlin.js",
"lib/stdlib.meta.js",
"lib/jslib-example.js",
"lib/file0.js",
"lib/dir/file1.js",
"lib/META-INF-ex/file2.js",
"lib/res0.js",
"lib/resdir/res1.js"
)
private val EXPECTED_JS_FILES_IN_OUTPUT_WITH_ADDITIONAL_LIB_AND_CUSTOM_DIR = hashSetOf(
"$PROJECT_NAME.js",
"$PROJECT_NAME.meta.js",
"custom/kotlin.js",
"custom/stdlib.meta.js",
"custom/jslib-example.js",
"custom/file0.js",
"custom/dir/file1.js",
"custom/META-INF-ex/file2.js",
"custom/res0.js",
"custom/resdir/res1.js"
)
private fun k2jsOutput(vararg moduleNames: String): Array<String> {
val list = arrayListOf<String>()
for (moduleName in moduleNames) {
val outputDir = File("out/production/$moduleName")
list.add(toSystemIndependentName(JpsJsModuleUtils.getOutputFile(outputDir, moduleName).path))
list.add(toSystemIndependentName(JpsJsModuleUtils.getOutputMetaFile(outputDir, moduleName).path))
}
return list.toTypedArray()
}
private fun getMethodsOfClass(classFile: File): Set<String> {
val result = TreeSet<String>()
ClassReader(FileUtil.loadFileBytes(classFile)).accept(object : ClassVisitor(Opcodes.ASM5) {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
result.add(name)
return null
}
}, 0)
return result
}
private fun assertFilesExistInOutput(module: JpsModule, vararg relativePaths: String) {
for (path in relativePaths) {
val outputFile = findFileInOutputDir(module, path)
assertTrue("Output not written: " + outputFile.absolutePath + "\n Directory contents: \n" + dirContents(outputFile.parentFile), outputFile.exists())
}
}
private fun findFileInOutputDir(module: JpsModule, relativePath: String): File {
val outputUrl = JpsJavaExtensionService.getInstance().getOutputUrl(module, false)
assertNotNull(outputUrl)
val outputDir = File(JpsPathUtil.urlToPath(outputUrl))
return File(outputDir, relativePath)
}
private fun assertFilesNotExistInOutput(module: JpsModule, vararg relativePaths: String) {
val outputUrl = JpsJavaExtensionService.getInstance().getOutputUrl(module, false)
assertNotNull(outputUrl)
val outputDir = File(JpsPathUtil.urlToPath(outputUrl))
for (path in relativePaths) {
val outputFile = File(outputDir, path)
assertFalse("Output directory \"" + outputFile.absolutePath + "\" contains \"" + path + "\"", outputFile.exists())
}
}
private fun dirContents(dir: File): String {
val files = dir.listFiles() ?: return "<not found>"
val builder = StringBuilder()
for (file in files) {
builder.append(" * ").append(file.name).append("\n")
}
return builder.toString()
}
private fun klass(moduleName: String, classFqName: String): String {
val outputDirPrefix = "out/production/$moduleName/"
return outputDirPrefix + classFqName.replace('.', '/') + ".class"
}
private fun module(moduleName: String): String {
return "out/production/$moduleName/${JvmCodegenUtil.getMappingFileName(moduleName)}"
}
fun mergeArrays(vararg stringArrays: Array<String>): Array<String> {
val result = HashSet<String>()
for (array in stringArrays) {
result.addAll(Arrays.asList(*array))
}
return ArrayUtil.toStringArray(result)
}
}
override fun setUp() {
super.setUp()
val sourceFilesRoot = File(AbstractKotlinJpsBuildTestCase.TEST_DATA_PATH + "general/" + getTestName(false))
workDir = AbstractKotlinJpsBuildTestCase.copyTestDataToTmpDir(sourceFilesRoot)
orCreateProjectDir
}
override fun tearDown() {
FileUtil.delete(workDir)
super.tearDown()
}
override fun doGetProjectDir(): File = workDir
private fun initProject() {
addJdk(JDK_NAME)
loadProject(workDir.absolutePath + File.separator + PROJECT_NAME + ".ipr")
}
fun doTest() {
initProject()
makeAll().assertSuccessful()
}
fun doTestWithRuntime() {
initProject()
addKotlinRuntimeDependency()
makeAll().assertSuccessful()
}
fun doTestWithKotlinJavaScriptLibrary() {
initProject()
addKotlinJavaScriptStdlibDependency()
createKotlinJavaScriptLibraryArchive()
addKotlinJavaScriptDependency(KOTLIN_JS_LIBRARY, File(workDir, KOTLIN_JS_LIBRARY_JAR))
makeAll().assertSuccessful()
}
fun testKotlinProject() {
doTest()
checkWhen(touch("src/test1.kt"), null, packageClasses("kotlinProject", "src/test1.kt", "Test1Kt"))
}
fun testSourcePackagePrefix() {
doTest()
}
fun testSourcePackageLongPrefix() {
initProject()
val buildResult = makeAll()
buildResult.assertSuccessful()
val warnings = buildResult.getMessages(BuildMessage.Kind.WARNING)
assertEquals("Warning about invalid package prefix in module 2 is expected: $warnings", 2, warnings.size)
assertEquals("Invalid package prefix name is ignored: invalid-prefix.test", warnings.first().messageText)
}
fun testSourcePackagePrefixKnownIssueWithInnerClasses() {
initProject()
val buildResult = makeAll()
buildResult.assertFailed()
val errors = buildResult.getMessages(BuildMessage.Kind.ERROR).map { it.messageText }
assertTrue("Message wasn't found. $errors", errors.first().contains("class xxx.JavaWithInner.TextRenderer, unresolved supertypes: TableRow"))
}
fun testKotlinJavaScriptProject() {
initProject()
addKotlinJavaScriptStdlibDependency()
makeAll().assertSuccessful()
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_FOR_STDLIB_ONLY, contentOfOutputDir(PROJECT_NAME))
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
}
fun testKotlinJavaScriptProjectWithTwoModules() {
initProject()
addKotlinJavaScriptStdlibDependency()
makeAll().assertSuccessful()
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_FOR_STDLIB_ONLY, contentOfOutputDir(PROJECT_NAME))
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_FOR_MODULE_STDLIB_ONLY, contentOfOutputDir(ADDITIONAL_MODULE_NAME))
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
checkWhen(touch("module2/src/module2.kt"), null, k2jsOutput(ADDITIONAL_MODULE_NAME))
checkWhen(arrayOf(touch("src/test1.kt"), touch("module2/src/module2.kt")), null, k2jsOutput(PROJECT_NAME, ADDITIONAL_MODULE_NAME))
}
fun testKotlinJavaScriptProjectWithDirectoryAsStdlib() {
initProject()
val jslibJar = PathUtil.getKotlinPathsForDistDirectory().jsStdLibJarPath
val jslibDir = File(workDir, "KotlinJavaScript")
try {
ZipUtil.extract(jslibJar, jslibDir, null)
}
catch (ex: IOException) {
throw IllegalStateException(ex.message)
}
addKotlinJavaScriptDependency("KotlinJavaScript", jslibDir)
makeAll().assertSuccessful()
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_FOR_STDLIB_ONLY, contentOfOutputDir(PROJECT_NAME))
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
}
fun testKotlinJavaScriptProjectWithDirectoryAsLibrary() {
initProject()
addKotlinJavaScriptStdlibDependency()
addKotlinJavaScriptDependency(KOTLIN_JS_LIBRARY, File(workDir, KOTLIN_JS_LIBRARY))
makeAll().assertSuccessful()
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_WITH_ADDITIONAL_LIB_AND_DEFAULT_DIR, contentOfOutputDir(PROJECT_NAME))
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
}
fun testKotlinJavaScriptProjectWithLibrary() {
doTestWithKotlinJavaScriptLibrary()
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_WITH_ADDITIONAL_LIB_AND_DEFAULT_DIR, contentOfOutputDir(PROJECT_NAME))
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
}
fun testKotlinJavaScriptProjectWithLibraryCustomOutputDir() {
doTestWithKotlinJavaScriptLibrary()
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_WITH_ADDITIONAL_LIB_AND_CUSTOM_DIR, contentOfOutputDir(PROJECT_NAME))
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
}
fun testKotlinJavaScriptProjectWithLibraryNoCopy() {
doTestWithKotlinJavaScriptLibrary()
assertEquals(EXPECTED_JS_FILES_IN_OUTPUT_NO_COPY, contentOfOutputDir(PROJECT_NAME))
checkWhen(touch("src/test1.kt"), null, k2jsOutput(PROJECT_NAME))
}
fun testKotlinJavaScriptProjectWithLibraryAndErrors() {
initProject()
addKotlinJavaScriptStdlibDependency()
createKotlinJavaScriptLibraryArchive()
addKotlinJavaScriptDependency(KOTLIN_JS_LIBRARY, File(workDir, KOTLIN_JS_LIBRARY_JAR))
makeAll().assertFailed()
assertEquals(Collections.EMPTY_SET, contentOfOutputDir(PROJECT_NAME))
}
fun testExcludeFolderInSourceRoot() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "Foo.class")
assertFilesNotExistInOutput(module, *EXCLUDE_FILES)
checkWhen(touch("src/foo.kt"), null, arrayOf(klass("kotlinProject", "Foo")))
}
fun testExcludeModuleFolderInSourceRootOfAnotherModule() {
doTest()
for (module in myProject.modules) {
assertFilesExistInOutput(module, "Foo.class")
}
checkWhen(touch("src/foo.kt"), null, arrayOf(klass("kotlinProject", "Foo")))
checkWhen(touch("src/module2/src/foo.kt"), null, arrayOf(klass("module2", "Foo")))
}
fun testExcludeFileUsingCompilerSettings() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "Foo.class", "Bar.class")
assertFilesNotExistInOutput(module, *EXCLUDE_FILES)
checkWhen(touch("src/foo.kt"), null, arrayOf(klass("kotlinProject", "Foo")))
checkWhen(touch("src/Excluded.kt"), null, NOTHING)
checkWhen(touch("src/dir/YetAnotherExcluded.kt"), null, NOTHING)
}
fun testExcludeFolderNonRecursivelyUsingCompilerSettings() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "Foo.class", "Bar.class")
assertFilesNotExistInOutput(module, *EXCLUDE_FILES)
checkWhen(touch("src/foo.kt"), null, arrayOf(klass("kotlinProject", "Foo")))
checkWhen(touch("src/dir/subdir/bar.kt"), null, arrayOf(klass("kotlinProject", "Bar")))
checkWhen(touch("src/dir/Excluded.kt"), null, NOTHING)
checkWhen(touch("src/dir/subdir/YetAnotherExcluded.kt"), null, NOTHING)
}
fun testExcludeFolderRecursivelyUsingCompilerSettings() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "Foo.class", "Bar.class")
assertFilesNotExistInOutput(module, *EXCLUDE_FILES)
checkWhen(touch("src/foo.kt"), null, arrayOf(klass("kotlinProject", "Foo")))
checkWhen(touch("src/exclude/Excluded.kt"), null, NOTHING)
checkWhen(touch("src/exclude/YetAnotherExcluded.kt"), null, NOTHING)
checkWhen(touch("src/exclude/subdir/Excluded.kt"), null, NOTHING)
checkWhen(touch("src/exclude/subdir/YetAnotherExcluded.kt"), null, NOTHING)
}
fun testManyFiles() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "foo/MainKt.class", "boo/BooKt.class", "foo/Bar.class")
checkWhen(touch("src/main.kt"), null, packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"))
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"), arrayOf("src/Bar.kt"), arrayOf(klass("kotlinProject", "foo.Bar")))
checkWhen(del("src/main.kt"),
arrayOf("src/Bar.kt", "src/boo.kt"),
mergeArrays(packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"),
packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"),
arrayOf(klass("kotlinProject", "foo.Bar"))))
assertFilesExistInOutput(module, "boo/BooKt.class", "foo/Bar.class")
assertFilesNotExistInOutput(module, "foo/MainKt.class")
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"), null, arrayOf(klass("kotlinProject", "foo.Bar")))
}
fun testManyFilesForPackage() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "foo/MainKt.class", "boo/BooKt.class", "foo/Bar.class")
checkWhen(touch("src/main.kt"), null, packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"))
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"),
arrayOf("src/Bar.kt"),
arrayOf(klass("kotlinProject", "foo.Bar"),
packagePartClass("kotlinProject", "src/Bar.kt", "foo.MainKt"),
module("kotlinProject")))
checkWhen(del("src/main.kt"),
arrayOf("src/Bar.kt", "src/boo.kt"),
mergeArrays(packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"),
packageClasses("kotlinProject", "src/Bar.kt", "foo.MainKt"),
packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"),
arrayOf(klass("kotlinProject", "foo.Bar"))))
assertFilesExistInOutput(module, "boo/BooKt.class", "foo/Bar.class")
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"), null,
arrayOf(klass("kotlinProject", "foo.Bar"),
packagePartClass("kotlinProject", "src/Bar.kt", "foo.MainKt"),
module("kotlinProject")))
}
fun testKotlinProjectTwoFilesInOnePackage() {
doTest()
checkWhen(touch("src/test1.kt"), null, packageClasses("kotlinProject", "src/test1.kt", "_DefaultPackage"))
checkWhen(touch("src/test2.kt"), null, packageClasses("kotlinProject", "src/test2.kt", "_DefaultPackage"))
checkWhen(arrayOf(del("src/test1.kt"), del("src/test2.kt")), NOTHING,
arrayOf(packagePartClass("kotlinProject", "src/test1.kt", "_DefaultPackage"),
packagePartClass("kotlinProject", "src/test2.kt", "_DefaultPackage"),
module("kotlinProject")))
assertFilesNotExistInOutput(myProject.modules.get(0), "_DefaultPackage.class")
}
fun testKotlinJavaProject() {
doTestWithRuntime()
}
fun testJKJProject() {
doTestWithRuntime()
}
fun testKJKProject() {
doTestWithRuntime()
}
fun testKJCircularProject() {
doTestWithRuntime()
}
fun testJKJInheritanceProject() {
doTestWithRuntime()
}
fun testKJKInheritanceProject() {
doTestWithRuntime()
}
fun testCircularDependenciesNoKotlinFiles() {
doTest()
}
fun testCircularDependenciesDifferentPackages() {
initProject()
val result = makeAll()
// Check that outputs are located properly
assertFilesExistInOutput(findModule("module2"), "kt1/Kt1Kt.class")
assertFilesExistInOutput(findModule("kotlinProject"), "kt2/Kt2Kt.class")
result.assertSuccessful()
checkWhen(touch("src/kt2.kt"), null, packageClasses("kotlinProject", "src/kt2.kt", "kt2.Kt2Kt"))
checkWhen(touch("module2/src/kt1.kt"), null, packageClasses("module2", "module2/src/kt1.kt", "kt1.Kt1Kt"))
}
fun testCircularDependenciesSamePackage() {
initProject()
val result = makeAll()
result.assertSuccessful()
// Check that outputs are located properly
val facadeWithA = findFileInOutputDir(findModule("module1"), "test/AKt.class")
val facadeWithB = findFileInOutputDir(findModule("module2"), "test/BKt.class")
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithA), "<clinit>", "a", "getA")
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithB), "<clinit>", "b", "getB", "setB")
checkWhen(touch("module1/src/a.kt"), null, packageClasses("module1", "module1/src/a.kt", "test.TestPackage"))
checkWhen(touch("module2/src/b.kt"), null, packageClasses("module2", "module2/src/b.kt", "test.TestPackage"))
}
fun testCircularDependenciesSamePackageWithTests() {
initProject()
val result = makeAll()
result.assertSuccessful()
// Check that outputs are located properly
val facadeWithA = findFileInOutputDir(findModule("module1"), "test/AKt.class")
val facadeWithB = findFileInOutputDir(findModule("module2"), "test/BKt.class")
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithA), "<clinit>", "a", "funA", "getA")
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithB), "<clinit>", "b", "funB", "getB", "setB")
checkWhen(touch("module1/src/a.kt"), null, packageClasses("module1", "module1/src/a.kt", "test.TestPackage"))
checkWhen(touch("module2/src/b.kt"), null, packageClasses("module2", "module2/src/b.kt", "test.TestPackage"))
}
fun testInternalFromAnotherModule() {
initProject()
val result = makeAll()
result.assertFailed()
result.checkErrors()
}
fun testCircularDependenciesInternalFromAnotherModule() {
initProject()
val result = makeAll()
result.assertFailed()
result.checkErrors()
}
fun testCircularDependenciesWrongInternalFromTests() {
initProject()
val result = makeAll()
result.assertFailed()
result.checkErrors()
}
fun testCircularDependencyWithReferenceToOldVersionLib() {
initProject()
val libraryJar = MockLibraryUtil.compileLibraryToJar(workDir.absolutePath + File.separator + "oldModuleLib/src", "module-lib", false, false)
AbstractKotlinJpsBuildTestCase.addDependency(JpsJavaDependencyScope.COMPILE, Lists.newArrayList(findModule("module1"), findModule("module2")), false, "module-lib", libraryJar)
val result = makeAll()
result.assertSuccessful()
}
fun testDependencyToOldKotlinLib() {
initProject()
val libraryJar = MockLibraryUtil.compileLibraryToJar(workDir.absolutePath + File.separator + "oldModuleLib/src", "module-lib", false, false)
AbstractKotlinJpsBuildTestCase.addDependency(JpsJavaDependencyScope.COMPILE, Lists.newArrayList(findModule("module")), false, "module-lib", libraryJar)
addKotlinRuntimeDependency()
val result = makeAll()
result.assertSuccessful()
}
fun testAccessToInternalInProductionFromTests() {
initProject()
val result = makeAll()
result.assertSuccessful()
}
private fun createKotlinJavaScriptLibraryArchive() {
val jarFile = File(workDir, KOTLIN_JS_LIBRARY_JAR)
try {
val zip = ZipOutputStream(FileOutputStream(jarFile))
ZipUtil.addDirToZipRecursively(zip, jarFile, File(PATH_TO_KOTLIN_JS_LIBRARY), "", null, null)
zip.close()
}
catch (ex: FileNotFoundException) {
throw IllegalStateException(ex.message)
}
catch (ex: IOException) {
throw IllegalStateException(ex.message)
}
}
private fun contentOfOutputDir(moduleName: String): Set<String> {
val outputDir = "out/production/$moduleName"
val baseDir = File(workDir, outputDir)
val files = FileUtil.findFilesByMask(Pattern.compile(".*"), baseDir)
val result = HashSet<String>()
for (file in files) {
val relativePath = FileUtil.getRelativePath(baseDir, file)
assert(relativePath != null) { "relativePath should not be null" }
result.add(toSystemIndependentName(relativePath!!))
}
return result
}
fun testReexportedDependency() {
initProject()
AbstractKotlinJpsBuildTestCase.addKotlinRuntimeDependency(JpsJavaDependencyScope.COMPILE, ContainerUtil.filter(myProject.modules, object : Condition<JpsModule> {
override fun value(module: JpsModule): Boolean {
return module.name == "module2"
}
}), true)
makeAll().assertSuccessful()
}
fun testCancelLongKotlinCompilation() {
generateLongKotlinFile("Foo.kt", "foo", "Foo")
initProject()
val INITIAL_DELAY = 2000
val start = System.currentTimeMillis()
val canceledStatus = CanceledStatus() { System.currentTimeMillis() - start > INITIAL_DELAY }
val logger = TestProjectBuilderLogger()
val buildResult = BuildResult()
buildCustom(canceledStatus, logger, buildResult)
val interval = System.currentTimeMillis() - start - INITIAL_DELAY
assertCanceled(buildResult)
buildResult.assertSuccessful()
assert(interval < 8000) { "expected time for canceled compilation < 8000 ms, but $interval" }
val module = myProject.modules.get(0)
assertFilesNotExistInOutput(module, "foo/Foo.class")
val expectedLog = workDir.absolutePath + File.separator + "expected.log"
checkFullLog(logger, File(expectedLog))
}
fun testCancelKotlinCompilation() {
initProject()
makeAll().assertSuccessful()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "foo/Bar.class")
val buildResult = BuildResult()
val canceledStatus = object: CanceledStatus {
var checkFromIndex = 0;
override fun isCanceled(): Boolean {
val messages = buildResult.getMessages(BuildMessage.Kind.INFO)
for (i in checkFromIndex..messages.size - 1) {
if (messages.get(i).messageText.startsWith("Kotlin JPS plugin version")) return true;
}
checkFromIndex = messages.size;
return false;
}
}
touch("src/Bar.kt").apply()
buildCustom(canceledStatus, TestProjectBuilderLogger(), buildResult)
assertCanceled(buildResult)
assertFilesNotExistInOutput(module, "foo/Bar.class")
}
fun testFileDoesNotExistWarning() {
initProject()
AbstractKotlinJpsBuildTestCase.addDependency(
JpsJavaDependencyScope.COMPILE, Lists.newArrayList(findModule("module")), false, "LibraryWithBadRoots",
File("badroot.jar"),
File("test/other/file.xml"),
File("some/test.class"),
File("some/other/baddir"))
val result = makeAll()
result.assertSuccessful()
val warnings = result.getMessages(BuildMessage.Kind.WARNING)
Assert.assertArrayEquals(
arrayOf(
"""Classpath entry points to a non-existent location: TEST_PATH/badroot.jar""",
"""Classpath entry points to a non-existent location: TEST_PATH/some/test.class"""),
warnings.map {
it.messageText.replace(File("").absolutePath, "TEST_PATH").replace("\\", "/")
}.sorted().toTypedArray()
)
}
fun testCodeInKotlinPackage() {
initProject()
val result = makeAll()
result.assertFailed()
val errors = result.getMessages(BuildMessage.Kind.ERROR)
Assert.assertEquals("Only the Kotlin standard library is allowed to use the 'kotlin' package", errors.single().messageText)
}
fun testDoNotCreateUselessKotlinIncrementalCaches() {
initProject()
makeAll().assertSuccessful()
val storageRoot = BuildDataPathsImpl(myDataStorageRoot).dataStorageRoot
assertTrue(File(storageRoot, "targets/java-test/kotlinProject/kotlin").exists())
assertFalse(File(storageRoot, "targets/java-production/kotlinProject/kotlin").exists())
}
fun testDoNotCreateUselessKotlinIncrementalCachesForDependentTargets() {
initProject()
makeAll().assertSuccessful()
checkWhen(touch("src/utils.kt"), null, packageClasses("kotlinProject", "src/utils.kt", "_DefaultPackage"))
val storageRoot = BuildDataPathsImpl(myDataStorageRoot).dataStorageRoot
assertTrue(File(storageRoot, "targets/java-production/kotlinProject/kotlin").exists())
assertFalse(File(storageRoot, "targets/java-production/module2/kotlin").exists())
}
fun testKotlinProjectWithEmptyProductionOutputDir() {
initProject()
val result = makeAll()
result.assertFailed()
result.checkErrors()
}
fun testKotlinProjectWithEmptyTestOutputDir() {
doTest()
}
fun testKotlinProjectWithEmptyProductionOutputDirWithoutSrcDir() {
doTest()
}
fun testKotlinProjectWithEmptyOutputDirInSomeModules() {
doTest()
}
private fun BuildResult.checkErrors() {
val actualErrors = getMessages(BuildMessage.Kind.ERROR)
.map { it as CompilerMessage }
.map { "${it.messageText} at line ${it.line}, column ${it.column}" }.sorted().joinToString("\n")
val projectRoot = File(AbstractKotlinJpsBuildTestCase.TEST_DATA_PATH + "general/" + getTestName(false))
val expectedFile = File(projectRoot, "errors.txt")
KotlinTestUtils.assertEqualsToFile(expectedFile, actualErrors)
}
private fun buildCustom(canceledStatus: CanceledStatus, logger: TestProjectBuilderLogger,buildResult: BuildResult) {
val scopeBuilder = CompileScopeTestBuilder.make().all()
val descriptor = this.createProjectDescriptor(BuildLoggingManager(logger))
try {
val builder = IncProjectBuilder(descriptor, BuilderRegistry.getInstance(), this.myBuildParams, canceledStatus, null, true)
builder.addMessageHandler(buildResult)
builder.build(scopeBuilder.build(), false)
}
finally {
descriptor.dataManager.flush(false)
descriptor.release()
}
}
private fun checkFullLog(logger: TestProjectBuilderLogger, expectedLogFile: File) {
UsefulTestCase.assertSameLinesWithFile(expectedLogFile.absolutePath, logger.getFullLog(orCreateProjectDir, myDataStorageRoot))
}
private fun assertCanceled(buildResult: BuildResult) {
val list = buildResult.getMessages(BuildMessage.Kind.INFO)
assertTrue("The build has been canceled".equals(list.last().messageText))
}
private fun generateLongKotlinFile(filePath: String, packagename: String, className: String) {
val file = File(workDir.absolutePath + File.separator + "src" + File.separator + filePath)
FileUtilRt.createIfNotExists(file)
val writer = BufferedWriter(FileWriter(file))
try {
writer.write("package $packagename\n\n")
writer.write("public class $className {\n")
for (i in 0..10000) {
writer.write("fun f$i():Int = $i\n\n")
}
writer.write("}\n")
}
finally {
writer.close()
}
}
private fun findModule(name: String): JpsModule {
for (module in myProject.modules) {
if (module.name == name) {
return module
}
}
throw IllegalStateException("Couldn't find module $name")
}
private fun checkWhen(action: Action, pathsToCompile: Array<String>?, pathsToDelete: Array<String>?) {
checkWhen(arrayOf(action), pathsToCompile, pathsToDelete)
}
private fun checkWhen(actions: Array<Action>, pathsToCompile: Array<String>?, pathsToDelete: Array<String>?) {
for (action in actions) {
action.apply()
}
makeAll().assertSuccessful()
if (pathsToCompile != null) {
assertCompiled(KotlinBuilder.KOTLIN_BUILDER_NAME, *pathsToCompile)
}
if (pathsToDelete != null) {
assertDeleted(*pathsToDelete)
}
}
private fun packageClasses(moduleName: String, fileName: String, packageClassFqName: String): Array<String> {
return arrayOf(module(moduleName), packagePartClass(moduleName, fileName, packageClassFqName))
}
private fun packagePartClass(moduleName: String, fileName: String, packageClassFqName: String): String {
val path = FileUtilRt.toSystemIndependentName(File(workDir, fileName).absolutePath)
val fakeVirtualFile = object : LightVirtualFile(path.substringAfterLast('/')) {
override fun getPath(): String {
// strip extra "/" from the beginning
return path.substring(1)
}
}
val packagePartFqName = PackagePartClassUtils.getDefaultPartFqName(FqName(packageClassFqName), fakeVirtualFile)
return klass(moduleName, AsmUtil.internalNameByFqNameWithoutInnerClasses(packagePartFqName))
}
private enum class Operation {
CHANGE,
DELETE
}
private fun touch(path: String): Action = Action(Operation.CHANGE, path)
private fun del(path: String): Action = Action(Operation.DELETE, path)
// TODO inline after KT-3974 will be fixed
private fun touch(file: File): Unit = JpsBuildTestCase.change(file.absolutePath)
private inner class Action constructor(private val operation: Operation, private val path: String) {
fun apply() {
val file = File(workDir, path)
when (operation) {
Operation.CHANGE ->
touch(file)
Operation.DELETE ->
assertTrue("Can not delete file \"" + file.absolutePath + "\"", file.exists())
else ->
fail("Unknown operation")
}
}
}
}
@@ -0,0 +1,85 @@
/*
* Copyright 2010-2016 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.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/lookupTracker")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class LookupTrackerTestGenerated extends AbstractLookupTrackerTest {
public void testAllFilesPresentInLookupTracker() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/lookupTracker"), Pattern.compile("^([^\\.]+)$"), false);
}
@TestMetadata("classifierMembers")
public void testClassifierMembers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/classifierMembers/");
doTest(fileName);
}
@TestMetadata("conventions")
public void testConventions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/conventions/");
doTest(fileName);
}
@TestMetadata("expressionType")
public void testExpressionType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/expressionType/");
doTest(fileName);
}
@TestMetadata("java")
public void testJava() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/java/");
doTest(fileName);
}
@TestMetadata("localDeclarations")
public void testLocalDeclarations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/localDeclarations/");
doTest(fileName);
}
@TestMetadata("packageDeclarations")
public void testPackageDeclarations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/packageDeclarations/");
doTest(fileName);
}
@TestMetadata("simple")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/simple/");
doTest(fileName);
}
@TestMetadata("syntheticProperties")
public void testSyntheticProperties() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/lookupTracker/syntheticProperties/");
doTest(fileName);
}
}
@@ -0,0 +1,97 @@
/*
* 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.jps.build
import com.intellij.util.PathUtil
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
class SimpleKotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
override fun setUp() {
super.setUp()
workDir = KotlinTestUtils.tmpDirForTest(this)
}
fun testLoadingKotlinFromDifferentModules() {
val aFile = createFile("m1/K.kt",
"""
package m1;
interface K {
}
""")
createFile("m1/J.java",
"""
package m1;
public interface J {
K bar();
}
""")
val a = addModule("m1", PathUtil.getParentPath(aFile))
val bFile = createFile("m2/m2.kt",
"""
import m1.J;
import m1.K;
interface M2: J {
override fun bar(): K
}
""")
val b = addModule("b", PathUtil.getParentPath(bFile))
JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(
b.dependenciesList.addModuleDependency(a)
).isExported = false
addKotlinRuntimeDependency()
rebuildAll()
}
// TODO: add JS tests
fun testDaemon() {
System.setProperty(COMPILE_DAEMON_ENABLED_PROPERTY, "")
System.setProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY, "")
// spaces in the name to test proper file name handling
val flagFile = File.createTempFile("kotlin-jps - tests-", "-is-running");
val logFile = File.createTempFile("kotlin-daemon", ".log")
System.setProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY, flagFile.absolutePath)
System.setProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY, logFile.loggerCompatiblePath)
try {
testLoadingKotlinFromDifferentModules()
}
finally {
flagFile.delete()
System.clearProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)
System.clearProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY)
System.clearProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY)
System.clearProperty(COMPILE_DAEMON_ENABLED_PROPERTY)
}
}
}
// copied from CompilerDaemonTest.kt
// TODO: find shared place for this function
// java.util.Logger used in the daemon silently forgets to log into a file specified in the config on Windows,
// if file path is given in windows form (using backslash as a separator); the reason is unknown
// this function makes a path with forward slashed, that works on windows too
internal val File.loggerCompatiblePath: String
get() =
if (OSKind.current == OSKind.Windows) absolutePath.replace('\\', '/')
else absolutePath
@@ -0,0 +1,49 @@
/*
* 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.jps.build
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.incremental.testingUtils.BuildLogFinder
import org.jetbrains.kotlin.jps.incremental.CacheVersionProvider
abstract class AbstractExperimentalIncrementalJpsTest : AbstractIncrementalJpsTest() {
override val enableExperimentalIncrementalCompilation = true
}
abstract class AbstractExperimentalIncrementalLazyCachesTest : AbstractIncrementalLazyCachesTest() {
override val enableExperimentalIncrementalCompilation = true
override val expectedCachesFileName: String
get() = "experimental-expected-kotlin-caches.txt"
}
abstract class AbstractExperimentalChangeIncrementalOptionTest : AbstractIncrementalLazyCachesTest()
abstract class AbstractExperimentalIncrementalCacheVersionChangedTest : AbstractIncrementalCacheVersionChangedTest() {
override val enableExperimentalIncrementalCompilation = true
override fun getVersions(cacheVersionProvider: CacheVersionProvider, targets: Iterable<ModuleBuildTarget>) =
targets.map { cacheVersionProvider.experimentalVersion(it) }
}
abstract class AbstractDataContainerVersionChangedTest : AbstractExperimentalIncrementalCacheVersionChangedTest() {
override val buildLogFinder: BuildLogFinder
get() = BuildLogFinder(isExperimentalEnabled = true, isDataContainerBuildLogEnabled = true)
override fun getVersions(cacheVersionProvider: CacheVersionProvider, targets: Iterable<ModuleBuildTarget>) =
listOf(cacheVersionProvider.dataContainerVersion())
}
@@ -0,0 +1,33 @@
/*
* Copyright 2010-2016 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.jps.build
import org.jetbrains.kotlin.incremental.testingUtils.Modification
open class IncrementalRenameModuleTest : AbstractIncrementalJpsTest() {
fun testRenameModule() {
doTest("jps-plugin/testData/incremental/custom/renameModule/")
}
override fun performAdditionalModifications(modifications: List<Modification>) {
projectDescriptor.project.modules.forEach { it.name += "Renamed" }
}
}
class ExperimentalIncrementalRenameModuleTest : IncrementalRenameModuleTest() {
override val enableExperimentalIncrementalCompilation = true
}
@@ -0,0 +1,129 @@
/*
* 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.jps.incremental
import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.UsefulTestCase
import com.intellij.util.SmartList
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
import org.jetbrains.kotlin.incremental.difference
import org.jetbrains.kotlin.incremental.storage.ProtoMapValue
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.utils.Printer
import java.io.File
abstract class AbstractProtoComparisonTest : UsefulTestCase() {
fun doTest(testDataPath: String) {
val testDir = KotlinTestUtils.tmpDir("testDirectory")
val oldClassFiles = compileFileAndGetClasses(testDataPath, testDir, "old")
val newClassFiles = compileFileAndGetClasses(testDataPath, testDir, "new")
val oldClassMap = oldClassFiles.associateBy { it.name }
val newClassMap = newClassFiles.associateBy { it.name }
val sb = StringBuilder()
val p = Printer(sb)
val oldSetOfNames = oldClassFiles.map { it.name }.toSet()
val newSetOfNames = newClassFiles.map { it.name }.toSet()
val removedNames = (oldSetOfNames - newSetOfNames).sorted()
removedNames.forEach {
p.println("REMOVED: class $it")
}
val addedNames = (newSetOfNames - oldSetOfNames).sorted()
addedNames.forEach {
p.println("ADDED: class $it")
}
val commonNames = oldSetOfNames.intersect(newSetOfNames).sorted()
for(name in commonNames) {
p.printDifference(oldClassMap[name]!!, newClassMap[name]!!)
}
KotlinTestUtils.assertEqualsToFile(File(testDataPath + File.separator + "result.out"), sb.toString());
}
private fun compileFileAndGetClasses(testPath: String, testDir: File, prefix: String): List<File> {
val files = File(testPath).listFiles { it -> it.name.startsWith(prefix) }!!
val sourcesDirectory = testDir.createSubDirectory("sources")
val classesDirectory = testDir.createSubDirectory("$prefix.src")
files.forEach { file ->
FileUtil.copy(file, File(sourcesDirectory, file.name.replaceFirst(prefix, "main")))
}
MockLibraryUtil.compileKotlin(sourcesDirectory.path, classesDirectory)
return File(classesDirectory, "test").listFiles() { it -> it.name.endsWith(".class") }?.sortedBy { it.name }!!
}
private fun Printer.printDifference(oldClassFile: File, newClassFile: File) {
fun KotlinJvmBinaryClass.readProto(): ProtoMapValue? {
assert(classHeader.metadataVersion.isCompatible()) { "Incompatible class ($classHeader): $location" }
return when (classHeader.kind) {
KotlinClassHeader.Kind.CLASS, KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
ProtoMapValue(
classHeader.kind != KotlinClassHeader.Kind.CLASS,
BitEncoding.decodeBytes(classHeader.data!!),
classHeader.strings!!
)
}
else -> {
println("skip $classId")
return null
}
}
}
val oldClass = LocalFileKotlinClass.create(oldClassFile)!!
val newClass = LocalFileKotlinClass.create(newClassFile)!!
val diff = difference(
oldClass.readProto() ?: return,
newClass.readProto() ?: return
)
val changes = SmartList<String>()
if (diff.isClassAffected) {
changes.add("CLASS_SIGNATURE")
}
if (diff.changedMembersNames.isNotEmpty()) {
changes.add("MEMBERS\n ${diff.changedMembersNames.sorted()}")
}
if (changes.isEmpty()) {
changes.add("NONE")
}
println("changes in ${oldClass.classId}: ${changes.joinToString()}")
}
private fun File.createSubDirectory(relativePath: String): File {
val directory = File(this, relativePath)
FileUtil.createDirectory(directory)
return directory
}
}
@@ -0,0 +1,243 @@
/*
* Copyright 2010-2016 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.jps.incremental;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class ProtoComparisonTestGenerated extends AbstractProtoComparisonTest {
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassSignatureChange extends AbstractProtoComparisonTest {
public void testAllFilesPresentInClassSignatureChange() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("classAnnotationListChanged")
public void testClassAnnotationListChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classSignatureChange/classAnnotationListChanged/");
doTest(fileName);
}
@TestMetadata("classFlagsAndMembersChanged")
public void testClassFlagsAndMembersChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classSignatureChange/classFlagsAndMembersChanged/");
doTest(fileName);
}
@TestMetadata("classFlagsChanged")
public void testClassFlagsChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classSignatureChange/classFlagsChanged/");
doTest(fileName);
}
@TestMetadata("classToFileFacade")
public void testClassToFileFacade() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classSignatureChange/classToFileFacade/");
doTest(fileName);
}
@TestMetadata("classTypeParameterListChanged")
public void testClassTypeParameterListChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classSignatureChange/classTypeParameterListChanged/");
doTest(fileName);
}
@TestMetadata("classWithSuperTypeListChanged")
public void testClassWithSuperTypeListChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classSignatureChange/classWithSuperTypeListChanged/");
doTest(fileName);
}
@TestMetadata("packageFacadeToClass")
public void testPackageFacadeToClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classSignatureChange/packageFacadeToClass/");
doTest(fileName);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassPrivateOnlyChange extends AbstractProtoComparisonTest {
public void testAllFilesPresentInClassPrivateOnlyChange() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("classWithPrivateFunChanged")
public void testClassWithPrivateFunChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateFunChanged/");
doTest(fileName);
}
@TestMetadata("classWithPrivatePrimaryConstructorChanged")
public void testClassWithPrivatePrimaryConstructorChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivatePrimaryConstructorChanged/");
doTest(fileName);
}
@TestMetadata("classWithPrivateSecondaryConstructorChanged")
public void testClassWithPrivateSecondaryConstructorChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateSecondaryConstructorChanged/");
doTest(fileName);
}
@TestMetadata("classWithPrivateValChanged")
public void testClassWithPrivateValChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateValChanged/");
doTest(fileName);
}
@TestMetadata("classWithPrivateVarChanged")
public void testClassWithPrivateVarChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateVarChanged/");
doTest(fileName);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassMembersOnlyChanged extends AbstractProtoComparisonTest {
public void testAllFilesPresentInClassMembersOnlyChanged() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("classWithCompanionObjectChanged")
public void testClassWithCompanionObjectChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithCompanionObjectChanged/");
doTest(fileName);
}
@TestMetadata("classWithConstructorChanged")
public void testClassWithConstructorChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithConstructorChanged/");
doTest(fileName);
}
@TestMetadata("classWithFunAndValChanged")
public void testClassWithFunAndValChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithFunAndValChanged/");
doTest(fileName);
}
@TestMetadata("classWithNestedClassesChanged")
public void testClassWithNestedClassesChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithNestedClassesChanged/");
doTest(fileName);
}
@TestMetadata("classWitnEnumChanged")
public void testClassWitnEnumChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWitnEnumChanged/");
doTest(fileName);
}
@TestMetadata("defaultValues")
public void testDefaultValues() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/defaultValues/");
doTest(fileName);
}
@TestMetadata("membersFlagsChanged")
public void testMembersFlagsChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/membersFlagsChanged/");
doTest(fileName);
}
@TestMetadata("sealedClassImplAdded")
public void testSealedClassImplAdded() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded/");
doTest(fileName);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageMembers extends AbstractProtoComparisonTest {
public void testAllFilesPresentInPackageMembers() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("defaultValues")
public void testDefaultValues() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/packageMembers/defaultValues/");
doTest(fileName);
}
@TestMetadata("membersFlagsChanged")
public void testMembersFlagsChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/packageMembers/membersFlagsChanged/");
doTest(fileName);
}
@TestMetadata("packageFacadeMultifileClassChanged")
public void testPackageFacadeMultifileClassChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/packageMembers/packageFacadeMultifileClassChanged/");
doTest(fileName);
}
@TestMetadata("packageFacadePrivateOnlyChanges")
public void testPackageFacadePrivateOnlyChanges() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/packageMembers/packageFacadePrivateOnlyChanges/");
doTest(fileName);
}
@TestMetadata("packageFacadePublicChanges")
public void testPackageFacadePublicChanges() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/packageMembers/packageFacadePublicChanges/");
doTest(fileName);
}
}
@TestMetadata("jps-plugin/testData/comparison/unchanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Unchanged extends AbstractProtoComparisonTest {
public void testAllFilesPresentInUnchanged() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/comparison/unchanged"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("unchangedClass")
public void testUnchangedClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/unchanged/unchangedClass/");
doTest(fileName);
}
@TestMetadata("unchangedPackageFacade")
public void testUnchangedPackageFacade() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/unchanged/unchangedPackageFacade/");
doTest(fileName);
}
}
}
@@ -0,0 +1,60 @@
/*
* 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.jvm.compiler
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType
import org.jetbrains.kotlin.build.JvmSourceRoot
import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
/**
* This test checks that Java classes from sources have higher priority in Kotlin resolution process than classes from binaries.
* To test this, we compile a Kotlin+Java module (in two modes: CLI and module-based) where a runtime Java class was replaced
* with a "newer" version in sources, and check that this class resolves to the one from sources by calling a method absent in the runtime
*/
class ClasspathOrderTest : TestCaseWithTmpdir() {
companion object {
val sourceDir = File(KotlinTestUtils.getTestDataPathBase() + "/classpathOrder").absoluteFile
}
fun testClasspathOrderForCLI() {
MockLibraryUtil.compileKotlin(sourceDir.path, tmpdir)
}
fun testClasspathOrderForModuleScriptBuild() {
val xmlContent = KotlinModuleXmlBuilder().addModule(
"name",
File(tmpdir, "output").absolutePath,
listOf(sourceDir),
listOf(JvmSourceRoot(sourceDir)),
listOf(PathUtil.getKotlinPathsForDistDirectory().runtimePath),
JavaModuleBuildTargetType.PRODUCTION.typeId,
JavaModuleBuildTargetType.PRODUCTION.isTests,
setOf(),
emptyList()
).asText().toString()
val xml = File(tmpdir, "module.xml")
xml.writeText(xmlContent)
MockLibraryUtil.compileKotlinModule(xml.absolutePath)
}
}
@@ -0,0 +1,86 @@
/*
* 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.modules;
import junit.framework.TestCase;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.kotlin.build.JvmSourceRoot;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
public class KotlinModuleXmlGeneratorTest extends TestCase {
public void testBasic() throws Exception {
String actual = new KotlinModuleXmlBuilder().addModule(
"name",
"output",
Arrays.asList(new File("s1"), new File("s2")),
Collections.singletonList(new JvmSourceRoot(new File("java"), null)),
Arrays.asList(new File("cp1"), new File("cp2")),
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
Collections.<File>emptySet(),
Collections.<File>emptyList()
).asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/basic.xml"), actual);
}
public void testFiltered() throws Exception {
String actual = new KotlinModuleXmlBuilder().addModule(
"name",
"output",
Arrays.asList(new File("s1"), new File("s2")),
Collections.<JvmSourceRoot>emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
Collections.singleton(new File("cp1")),
Collections.<File>emptyList()
).asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/filtered.xml"), actual);
}
public void testMultiple() throws Exception {
KotlinModuleXmlBuilder builder = new KotlinModuleXmlBuilder();
builder.addModule(
"name",
"output",
Arrays.asList(new File("s1"), new File("s2")),
Collections.<JvmSourceRoot>emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
Collections.singleton(new File("cp1")),
Collections.<File>emptyList()
);
builder.addModule(
"name2",
"output2",
Arrays.asList(new File("s12"), new File("s22")),
Collections.<JvmSourceRoot>emptyList(),
Arrays.asList(new File("cp12"), new File("cp22")),
JavaModuleBuildTargetType.TEST.getTypeId(),
JavaModuleBuildTargetType.TEST.isTests(),
Collections.singleton(new File("cp12")),
Collections.<File>emptyList()
);
String actual = builder.asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/multiple.xml"), actual);
}
}