diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/integration/KotlinIntegrationTestBase.java b/compiler/tests-common/tests/org/jetbrains/kotlin/integration/KotlinIntegrationTestBase.java index 937f3296b05..4711def56eb 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/integration/KotlinIntegrationTestBase.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/integration/KotlinIntegrationTestBase.java @@ -104,7 +104,7 @@ public abstract class KotlinIntegrationTestBase extends TestCaseWithTmpdir { KotlinTestUtils.assertEqualsToFile(expectedFile, normalizedContent); } - private static int runProcess(GeneralCommandLine commandLine, StringBuilder executionLog) throws ExecutionException { + protected static int runProcess(GeneralCommandLine commandLine, StringBuilder executionLog) throws ExecutionException { OSProcessHandler handler = new OSProcessHandler(commandLine.createProcess(), commandLine.getCommandLineString(), commandLine.getCharset()); @@ -132,7 +132,7 @@ public abstract class KotlinIntegrationTestBase extends TestCaseWithTmpdir { } } - private static File getJavaRuntime() { + protected static File getJavaRuntime() { File javaHome = new File(System.getProperty("java.home")); String javaExe = SystemInfo.isWindows ? "java.exe" : "java"; diff --git a/compiler/tests/org/jetbrains/kotlin/integration/ParallelBuildTest.kt b/compiler/tests/org/jetbrains/kotlin/integration/ParallelBuildTest.kt new file mode 100644 index 00000000000..2294823db0f --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/integration/ParallelBuildTest.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.integration + +import com.intellij.execution.configurations.GeneralCommandLine +import org.jetbrains.kotlin.cli.AbstractCliTest +import org.jetbrains.kotlin.cli.common.ExitCode +import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler +import org.jetbrains.kotlin.test.util.KtTestUtil +import org.jetbrains.kotlin.utils.PathUtil.kotlinPathsForDistDirectory +import java.io.File + +class ParallelBuildTest : KotlinIntegrationTestBase() { + fun testParallelBuild() { + val testDataDir = KtTestUtil.getTestDataPathBase() + "/integration/smoke/helloApp" + val programText = """ + import org.jetbrains.kotlin.cli.common.messages.MessageRenderer + import org.jetbrains.kotlin.cli.common.ExitCode + import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler + import java.util.concurrent.Executors + import java.util.concurrent.TimeUnit + + // Increase `totalRuns` and change `threads` to `Runtime.getRuntime().availableProcessors()` to reproduce more reliably locally + val totalRuns = 100 + val threads = 2 + + fun main() { + var errors = 0 + + val pool = Executors.newFixedThreadPool(threads) + repeat(totalRuns) { + pool.submit { + try { + val code = K2JVMCompiler().exec( + System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, + "$testDataDir/hello.kt", + "-d", "$tmpdir/output" + ) + if (code != ExitCode.OK) errors++ + } catch (e: Throwable) { + errors++ + throw e + } + } + } + pool.shutdown() + pool.awaitTermination(120L, TimeUnit.SECONDS) + + println("" + errors + " errors") + if (errors > 0) { + System.exit(1) + } + } + """.trimIndent() + + val programSource = File(tmpdir, "program.kt") + programSource.writeText(programText) + + val program = File(tmpdir, "program").absolutePath + val (output, exitCode) = AbstractCliTest.executeCompilerGrabOutput( + K2JVMCompiler(), + listOf( + programSource.path, + "-d", program, + "-cp", kotlinPathsForDistDirectory.compilerPath.absolutePath, + ), + ) + assertEquals("Compilation failed:\n$output", ExitCode.OK, exitCode) + + val result = runJava( + testDataDir, + "-cp", + listOf( + program, + kotlinPathsForDistDirectory.compilerPath.absolutePath, + ).joinToString(File.pathSeparator), + "ProgramKt", + ) + assertEquals( + "Run failed:\n$result", + "OUT:\n0 errors\n\nReturn code: 0\n", result + ) + } + + private fun runJava(testDataDir: String, vararg arguments: String): String { + val commandLine = GeneralCommandLine().withWorkDirectory(testDataDir) + commandLine.exePath = getJavaRuntime().absolutePath + commandLine.addParameters(*arguments) + val executionLog = StringBuilder() + val exitCode = runProcess(commandLine, executionLog) + assertEquals("Non-zero exit code ($exitCode):\n$executionLog", 0, exitCode) + return executionLog.toString() + } +}