add builder tests that validate errors are rendered relative to workspace.
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt
index b52a222..c7385bb 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt
@@ -15,11 +15,12 @@
*/
package io.bazel.kotlin.builder.tasks.jvm
-import io.bazel.kotlin.builder.toolchain.CompilationStatusException
import io.bazel.kotlin.builder.toolchain.KotlinToolchain
+import io.bazel.kotlin.builder.utils.CompilationTaskContext
import io.bazel.kotlin.builder.utils.addAll
import io.bazel.kotlin.builder.utils.joinedClasspath
import io.bazel.kotlin.model.JvmCompilationTask
+import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Singleton
@@ -27,14 +28,14 @@
internal class JavaCompiler @Inject constructor(
private val javacInvoker: KotlinToolchain.JavacInvoker
) {
- fun compile(command: JvmCompilationTask) {
+ fun compile(context: CompilationTaskContext, command: JvmCompilationTask) {
val i = command.inputs
val d = command.directories
if (i.javaSourcesList.isNotEmpty()) {
val args = mutableListOf(
"-cp", "${d.classes}/:${d.temp}/:${i.joinedClasspath}",
"-d", d.classes
- ).let {
+ ).also {
it.addAll(
// Kotlin takes care of annotation processing.
"-proc:none",
@@ -44,9 +45,10 @@
"-target", command.info.toolchainInfo.jvm.jvmTarget
)
it.addAll(i.javaSourcesList)
- it.toTypedArray()
}
- javacInvoker.compile(args).takeIf { it != 0 }?.also { throw CompilationStatusException("javac failed", it) }
+ context.executeCompilerTask(args, { a, pw ->
+ javacInvoker.compile(a, PrintWriter(pw))
+ })
}
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt
index 10bf26b..7debb8d 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt
@@ -36,16 +36,11 @@
private val jDepsGenerator: JDepsGenerator
) {
fun execute(context: CompilationTaskContext, task: JvmCompilationTask) {
- // TODO fix error handling
- try {
- val preprocessedTask = task.preProcessingSteps(context)
- context.execute("compile classes") { preprocessedTask.compileAll(context) }
- context.execute("create jar") { preprocessedTask.createOutputJar() }
- context.execute("produce src jar") { preprocessedTask.produceSourceJar() }
- context.execute("generate jdeps") { jDepsGenerator.generateJDeps(preprocessedTask) }
- } catch (ex: Throwable) {
- throw RuntimeException(ex)
- }
+ val preprocessedTask = task.preProcessingSteps(context)
+ context.execute("compile classes") { preprocessedTask.compileAll(context) }
+ context.execute("create jar") { preprocessedTask.createOutputJar() }
+ context.execute("produce src jar") { preprocessedTask.produceSourceJar() }
+ context.execute("generate jdeps") { jDepsGenerator.generateJDeps(preprocessedTask) }
}
private fun JvmCompilationTask.preProcessingSteps(context: CompilationTaskContext): JvmCompilationTask {
@@ -166,7 +161,7 @@
}
}
try {
- context.execute("javac") { javaCompiler.compile(this) }
+ context.execute("javac") { javaCompiler.compile(context, this) }
} finally {
checkNotNull(result).also(context::printCompilerOutput)
kotlinError?.also { throw it }
@@ -176,7 +171,7 @@
/**
* Compiles Kotlin sources to classes. Does not compile Java sources.
*/
- fun JvmCompilationTask.compileKotlin(context: CompilationTaskContext, printOnFail: Boolean = true) =
+ private fun JvmCompilationTask.compileKotlin(context: CompilationTaskContext, printOnFail: Boolean = true) =
getCommonArgs().let { args ->
args.addAll(inputs.javaSourcesList)
args.addAll(inputs.kotlinSourcesList)
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
index 9351233..9d02c20 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
@@ -27,7 +27,9 @@
class CompilationTaskContext(val info: CompilationTaskInfo, private val out: PrintStream) {
private val start = System.currentTimeMillis()
- private val executionRoot: String = Paths.get("").toAbsolutePath().toString() + File.separator
+ private val executionRoot: String = Paths.get(
+ System.getProperty("user.dir")
+ ).toAbsolutePath().toString() + File.separator
private var timings: MutableList<String>?
private var level = -1
@PublishedApi
@@ -100,7 +102,7 @@
* @throws CompilationStatusException if the compiler returns a status of anything but zero.
* @param args the compiler command line switches
* @param printOnFail if this is true the output will be printed if the task fails else the caller is responsible
- * for logging it by catching the [CompilationStatusException] excepotion.
+ * for logging it by catching the [CompilationStatusException] exception.
* @param compile the compilation method.
*/
inline fun executeCompilerTask(
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderJvmTestTask.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderJvmTestTask.java
index e3c1f97..d04604e 100644
--- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderJvmTestTask.java
+++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderJvmTestTask.java
@@ -94,7 +94,7 @@
public void runCompileTask(BiConsumer<CompilationTaskContext, JvmCompilationTask> operation) {
JvmCompilationTask task = taskBuilder.build();
super.runCompileTask(
- new CompilationTaskContext(task.getInfo(), System.err),
+ task.getInfo(),
task,
(ctx, t) -> {
operation.accept(ctx, t);
@@ -105,7 +105,6 @@
@SuppressWarnings("unused")
public <R> R runCompileTask(BiFunction<CompilationTaskContext, JvmCompilationTask, R> operation) {
JvmCompilationTask task = taskBuilder.build();
- return super.runCompileTask(
- new CompilationTaskContext(task.getInfo(), System.err), task, operation);
+ return super.runCompileTask(task.getInfo(), task, operation);
}
}
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderResource.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderResource.java
index 02db955..29c47ad 100644
--- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderResource.java
+++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderResource.java
@@ -1,16 +1,18 @@
package io.bazel.kotlin.builder;
+import io.bazel.kotlin.builder.toolchain.CompilationException;
+import io.bazel.kotlin.builder.toolchain.CompilationStatusException;
import io.bazel.kotlin.builder.utils.CompilationTaskContext;
import io.bazel.kotlin.model.CompilationTaskInfo;
import org.junit.rules.ExternalResource;
-import java.io.IOException;
-import java.io.UncheckedIOException;
+import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -109,8 +111,13 @@
return Objects.requireNonNull(instanceRoot);
}
+ public List<String> outLines() {
+ return outLines;
+ }
+
@Override
protected void before() throws Throwable {
+ outLines = null;
label = "a_test_" + counter.incrementAndGet();
setTimeout(DEFAULT_TIMEOUT);
try {
@@ -152,6 +159,7 @@
private int DEFAULT_TIMEOUT = 10;
private int timeoutSeconds = DEFAULT_TIMEOUT;
+ private List<String> outLines = null;
/**
* sets the timeout for the builder tasks.
@@ -165,20 +173,37 @@
}
<T, R> R runCompileTask(
- CompilationTaskContext context, T task, BiFunction<CompilationTaskContext, T, R> operation) {
+ CompilationTaskInfo info, T task, BiFunction<CompilationTaskContext, T, R> operation) {
String curDir = System.getProperty("user.dir");
- System.setProperty("user.dir", instanceRoot().toAbsolutePath().toString());
- try {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ try (PrintStream outputStream = new PrintStream(byteArrayOutputStream)) {
+ System.setProperty("user.dir", instanceRoot().toAbsolutePath().toString());
CompletableFuture<R> future =
- CompletableFuture.supplyAsync(() -> operation.apply(context, task));
+ CompletableFuture.supplyAsync(
+ () -> operation.apply(new CompilationTaskContext(info, outputStream), task));
return timeoutSeconds > 0 ? future.get(timeoutSeconds, TimeUnit.SECONDS) : future.get();
-
+ } catch (ExecutionException e) {
+ if (e.getCause() instanceof CompilationStatusException) {
+ throw (CompilationStatusException) e.getCause();
+ } else if (e.getCause() instanceof CompilationException) {
+ throw (CompilationException) e.getCause();
+ } else {
+ throw new RuntimeException(e.getCause());
+ }
} catch (TimeoutException e) {
throw new AssertionError("did not complete in: " + timeoutSeconds);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
System.setProperty("user.dir", curDir);
+ outLines =
+ Collections.unmodifiableList(
+ new BufferedReader(
+ new InputStreamReader(
+ new ByteArrayInputStream(byteArrayOutputStream.toByteArray())))
+ .lines()
+ .peek(System.err::println)
+ .collect(Collectors.toList()));
}
}
@@ -195,10 +220,10 @@
assertFileExistence(resolved(dir, filePath), false);
}
- private static void assertFileExistence(Stream<Path> pathStream, boolean shouldexist) {
+ private static void assertFileExistence(Stream<Path> pathStream, boolean shouldExist) {
pathStream.forEach(
path -> {
- if (shouldexist)
+ if (shouldExist)
assertWithMessage("file did not exist: " + path).that(path.toFile().exists()).isTrue();
else assertWithMessage("file existed: " + path).that(path.toFile().exists()).isFalse();
});
@@ -212,7 +237,7 @@
/**
* Normalize a path string.
*
- * @param path a path using '/' as the seperator.
+ * @param path a path using '/' as the separator.
* @return a path string suitable for the target platform.
*/
private static Path toPlatformPath(String path) {
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmTest.java
index 386bf8c..46eb6af 100644
--- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmTest.java
+++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmTest.java
@@ -5,6 +5,7 @@
import io.bazel.kotlin.builder.KotlinBuilderJvmTestTask;
import io.bazel.kotlin.builder.KotlinBuilderResource.Dep;
import io.bazel.kotlin.builder.KotlinBuilderResource.DirectoryType;
+import io.bazel.kotlin.builder.toolchain.CompilationStatusException;
import io.bazel.kotlin.builder.toolchain.KotlinToolchain;
import io.bazel.kotlin.builder.utils.CompilationTaskContext;
import io.bazel.kotlin.model.AnnotationProcessor;
@@ -13,6 +14,10 @@
import org.junit.Rule;
import org.junit.Test;
+import java.util.List;
+import java.util.function.Consumer;
+
+import static com.google.common.truth.Truth.assertThat;
import static io.bazel.kotlin.builder.KotlinBuilderResource.KOTLIN_ANNOTATIONS;
import static io.bazel.kotlin.builder.KotlinBuilderResource.KOTLIN_STDLIB;
@@ -154,24 +159,37 @@
}
@Test
+ public void testKotlinErrorRendering() {
+ ctx.addSource("AClass.kt", "package something;" + "class AClass{");
+ testExpectingCompileError(lines -> assertThat(lines.get(0)).startsWith("sources/AClass"));
+ }
+
+ @Test
+ public void testJavaErrorRendering() {
+ ctx.addSource("AClass.kt", "package something;" + "class AClass{}");
+ ctx.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{");
+ testExpectingCompileError(lines -> assertThat(lines.get(0)).startsWith("sources/AnotherClass"));
+ }
+
+ @Test
@Ignore("The Kotlin compiler expects a single kotlin file at least.")
public void testCompileSingleJavaFile() {
ctx.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}");
ctx.runCompileTask(this::jvmCompilationTask);
}
- @Test
- @Ignore(
- "This test needs to test the output of error handling by the compiler, when the kotlin compiler compiles java "
- + "this test needs to validate it.")
- public void testWithJavaError() {
- ctx.addSource("AClass.kt", "package something;" + "class AClass{}");
- ctx.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{");
- ctx.runCompileTask(this::jvmCompilationTask);
- }
-
private void jvmCompilationTask(CompilationTaskContext taskContext, JvmCompilationTask task) {
component.jvmTaskExecutor().execute(taskContext, task);
ctx.assertFilesExist(task.getOutputs().getJar(), task.getOutputs().getJdeps());
}
+
+ private void testExpectingCompileError(Consumer<List<String>> validator) {
+ try {
+ ctx.runCompileTask(this::jvmCompilationTask);
+ } catch (CompilationStatusException ex) {
+ validator.accept(ctx.outLines());
+ return;
+ }
+ throw new RuntimeException("expected an exception");
+ }
}