From f9ef41b1a05a62961b390d32a5815f3c91fd4fd1 Mon Sep 17 00:00:00 2001 From: Ted Kaplan Date: Tue, 28 Mar 2023 15:47:42 -0700 Subject: [PATCH 1/4] Catch macro expansion exceptions in ScalacWorker Style fix --- src/java/io/bazel/rulesscala/scalac/ScalacWorker.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/java/io/bazel/rulesscala/scalac/ScalacWorker.java b/src/java/io/bazel/rulesscala/scalac/ScalacWorker.java index c40382eb4..e72dc1a04 100644 --- a/src/java/io/bazel/rulesscala/scalac/ScalacWorker.java +++ b/src/java/io/bazel/rulesscala/scalac/ScalacWorker.java @@ -248,6 +248,15 @@ private static String[] getPluginParamsFrom(CompileOptions ops) { return pluginParams.toArray(new String[pluginParams.size()]); } + private static boolean isMacroException(Throwable ex) { + for (StackTraceElement elem : ex.getStackTrace()) { + if (elem.getMethodName().equals("macroExpand")) { + return true; + } + } + return false; + } + private static void compileScalaSources(CompileOptions ops, String[] scalaSources, Path classes) throws IOException { @@ -269,6 +278,8 @@ private static void compileScalaSources(CompileOptions ops, String[] scalaSource } catch (Throwable ex) { if (ex.toString().contains("scala.reflect.internal.Types$TypeError")) { throw new RuntimeException("Build failure with type error", ex); + } else if (isMacroException(ex)) { + throw new RuntimeException("Build failure during macro expansion", ex); } else { throw ex; } From 1a6cc49300644a9e4b5be351d3f83fc1137b793d Mon Sep 17 00:00:00 2001 From: Ted Kaplan Date: Mon, 3 Apr 2023 00:26:44 -0700 Subject: [PATCH 2/4] E2E test for persistent worker --- test/shell/test_persistent_worker.sh | 17 +++++++++++++++++ test_expect_failure/scalac_exceptions/BUILD | 12 ++++++++++++ .../scalac_exceptions/BadMacro.scala | 9 +++++++++ .../scalac_exceptions/BadMacroInvocation.scala | 3 +++ 4 files changed, 41 insertions(+) create mode 100644 test/shell/test_persistent_worker.sh create mode 100644 test_expect_failure/scalac_exceptions/BUILD create mode 100644 test_expect_failure/scalac_exceptions/BadMacro.scala create mode 100644 test_expect_failure/scalac_exceptions/BadMacroInvocation.scala diff --git a/test/shell/test_persistent_worker.sh b/test/shell/test_persistent_worker.sh new file mode 100644 index 000000000..f1dcb2de8 --- /dev/null +++ b/test/shell/test_persistent_worker.sh @@ -0,0 +1,17 @@ +# shellcheck source=./test_runner.sh + +dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +. "${dir}"/test_runner.sh +. "${dir}"/test_helper.sh +runner=$(get_test_runner "${1:-local}") + +test_persistent_worker_handles_exception_in_macro_invocation() { + bazel build //test_expect_failure/scalac_exceptions:bad_macro_invocation --strategy=Scalac=worker --worker_sandboxing 2>&1 | grep -q -- "---8<---8<---" + RESPONSE_CODE=$? + if [ $RESPONSE_CODE -ne 1 ]; then + echo -e "${RED} Scalac persistent worker does not handle uncaught error in macro expansion. $NC" + exit 1 + fi +} + +$runner test_persistent_worker_handles_exception_in_macro_invocation \ No newline at end of file diff --git a/test_expect_failure/scalac_exceptions/BUILD b/test_expect_failure/scalac_exceptions/BUILD new file mode 100644 index 000000000..7f0fc8df0 --- /dev/null +++ b/test_expect_failure/scalac_exceptions/BUILD @@ -0,0 +1,12 @@ +load("//scala:scala.bzl", "scala_library", "scala_macro_library") + +scala_macro_library( + name = "bad_macro", + srcs = ["BadMacro.scala"], +) + +scala_library( + name = "bad_macro_invocation", + srcs = ["BadMacroInvocation.scala"], + deps = [":bad_macro"], +) diff --git a/test_expect_failure/scalac_exceptions/BadMacro.scala b/test_expect_failure/scalac_exceptions/BadMacro.scala new file mode 100644 index 000000000..81f725134 --- /dev/null +++ b/test_expect_failure/scalac_exceptions/BadMacro.scala @@ -0,0 +1,9 @@ +import scala.language.experimental.macros + +object BadMacro { + def badMacro(): Unit = macro badMacroImpl + + def badMacroImpl(c: scala.reflect.macros.blackbox.Context)(): c.Tree = { + throw new NoSuchMethodError() + } +} \ No newline at end of file diff --git a/test_expect_failure/scalac_exceptions/BadMacroInvocation.scala b/test_expect_failure/scalac_exceptions/BadMacroInvocation.scala new file mode 100644 index 000000000..6ce071010 --- /dev/null +++ b/test_expect_failure/scalac_exceptions/BadMacroInvocation.scala @@ -0,0 +1,3 @@ +object BadMacroInvocation { + BadMacro.badMacro() +} \ No newline at end of file From 95ef18b43bd9685ca95dd745a5a345f165079e4c Mon Sep 17 00:00:00 2001 From: Ted Kaplan Date: Mon, 3 Apr 2023 00:36:40 -0700 Subject: [PATCH 3/4] Add new test to test_rules_scala.sh --- test_rules_scala.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test_rules_scala.sh b/test_rules_scala.sh index 82db642c8..ac067dcd9 100755 --- a/test_rules_scala.sh +++ b/test_rules_scala.sh @@ -55,3 +55,4 @@ $runner bazel build //test_statsfile:SimpleNoStatsFile_statsfile --extra_toolcha . "${test_dir}"/test_compiler_dependency_tracking.sh . "${test_dir}"/test_twitter_scrooge.sh . "${test_dir}"/test_inherited_environment.sh +. "${test_dir}"/test_persistent_worker.sh From a3e4e6a8e951b2352949d7825ac8900dcc9c9424 Mon Sep 17 00:00:00 2001 From: Ted Kaplan Date: Mon, 3 Apr 2023 01:01:00 -0700 Subject: [PATCH 4/4] Update test cases --- test/shell/test_persistent_worker.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/shell/test_persistent_worker.sh b/test/shell/test_persistent_worker.sh index f1dcb2de8..5255ed281 100644 --- a/test/shell/test_persistent_worker.sh +++ b/test/shell/test_persistent_worker.sh @@ -5,13 +5,29 @@ dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) . "${dir}"/test_helper.sh runner=$(get_test_runner "${1:-local}") +PERSISTENT_WORKER_FLAGS="--strategy=Scalac=worker --worker_sandboxing" + +test_persistent_worker_success() { + # shellcheck disable=SC2086 + bazel build //test:ScalaBinary $PERSISTENT_WORKER_FLAGS +} + +test_persistent_worker_failure() { + action_should_fail "build //test_expect_failure/diagnostics_reporter:error_file $PERSISTENT_WORKER_FLAGS" +} + test_persistent_worker_handles_exception_in_macro_invocation() { - bazel build //test_expect_failure/scalac_exceptions:bad_macro_invocation --strategy=Scalac=worker --worker_sandboxing 2>&1 | grep -q -- "---8<---8<---" + command="bazel build //test_expect_failure/scalac_exceptions:bad_macro_invocation $PERSISTENT_WORKER_FLAGS" + output=$(${command} 2>&1) + ! (echo "$output" | grep -q -- "---8<---8<---") && (echo "$output" | grep -q "Build failure during macro expansion") + RESPONSE_CODE=$? - if [ $RESPONSE_CODE -ne 1 ]; then + if [ $RESPONSE_CODE -ne 0 ]; then echo -e "${RED} Scalac persistent worker does not handle uncaught error in macro expansion. $NC" exit 1 fi } +$runner test_persistent_worker_success +$runner test_persistent_worker_failure $runner test_persistent_worker_handles_exception_in_macro_invocation \ No newline at end of file