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");
+  }
 }