From 7c413298fbb9ca38ae1da7e86c7ad5ad47b7ff34 Mon Sep 17 00:00:00 2001 From: Hubert Plociniczak Date: Mon, 23 Sep 2024 10:59:56 +0200 Subject: [PATCH] More info when critical failure occurs (#11092) * More info when critical failure occurs Log problematic module to help with debugging critical failure. * One more exception * s/System.err/Logger.error/ * maybe append slf4j deps * fix what looks like a long standing typo `GeneratedFormatTests.java` not `GeneratedFormatTests..java` * one more typo * Fix directory where to look for classpath `./run java-gen test --skip-version-check` now works. At least locally. * Local is fine, CI is not. More temporary debugging... * Ensure project's managedClasspath is exported Running java tests requires us knowing all additional dependencies as they have to be added to the classpath manually. That can only be ensured by invoking the right sbt target. * Move sbt call after graalvm setup * removing CI debugging * Apply suggestions from code review Co-authored-by: Kaz Wesley --------- Co-authored-by: Kaz Wesley --- build.sbt | 8 ++++++ build/build/src/engine/context.rs | 10 ++++++++ build/build/src/rust/parser.rs | 25 ++++++++++++++++--- build/cli/src/lib.rs | 6 ++++- .../generate-java/java/module-info.java | 2 ++ .../java/org/enso/syntax2/Parser.java | 10 +++++++- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/build.sbt b/build.sbt index 7bc80a41789..f6e8d7143ff 100644 --- a/build.sbt +++ b/build.sbt @@ -769,6 +769,14 @@ lazy val `syntax-rust-definition` = project publish / skip := false, autoScalaLibrary := false, crossPaths := false, + libraryDependencies ++= Seq( + "org.slf4j" % "slf4j-api" % slf4jVersion + ), + moduleDependencies := { + Seq( + "org.slf4j" % "slf4j-api" % slf4jVersion + ) + }, javaModuleName := "org.enso.syntax", Compile / sourceGenerators += generateParserJavaSources, Compile / resourceGenerators += generateRustParserLib, diff --git a/build/build/src/engine/context.rs b/build/build/src/engine/context.rs index bc6702bfa78..c4c2a61e263 100644 --- a/build/build/src/engine/context.rs +++ b/build/build/src/engine/context.rs @@ -190,6 +190,16 @@ impl RunContext { graalpy.install_if_missing(&self.cache).await?; ide_ci::programs::graalpy::GraalPy.require_present().await?; + if self.config.test_java_generated_from_rust { + // Ensure all runtime dependencies are resolved and exported so that they can be + // appended to classpath + let sbt = engine::sbt::Context { + repo_root: self.paths.repo_root.path.clone(), + system_properties: default(), + }; + sbt.call_arg("syntax-rust-definition/Runtime/managedClasspath").await?; + } + prepare_simple_library_server.await??; Ok(()) } diff --git a/build/build/src/rust/parser.rs b/build/build/src/rust/parser.rs index 76b3041baeb..580f30f469c 100644 --- a/build/build/src/rust/parser.rs +++ b/build/build/src/rust/parser.rs @@ -9,14 +9,15 @@ use ide_ci::programs::Cargo; use ide_ci::programs::Java; use ide_ci::programs::Javac; - +use std::fs; +use std::path::Path; const GENERATOR_CRATE_NAME: &str = "enso-parser-generate-java"; const GENERATOR_BIN_NAME: &str = GENERATOR_CRATE_NAME; const TEST_GENERATOR_BIN_NAME: &str = "java-tests"; const GENERATED_CODE_NAMESPACE: [&str; 3] = ["org", "enso", "syntax2"]; const GENERATED_TEST_CLASS: &str = "GeneratedFormatTests"; -const JAVA_EXTENSION: &str = ".java"; +const JAVA_EXTENSION: &str = "java"; pub fn cargo_run_generator_cmd(repo_root: &Path, binary_name: &str) -> Result { let mut ret = Cargo.cmd()?; @@ -50,6 +51,20 @@ pub async fn generate_java(repo_root: &RepoRoot) -> Result { pub async fn run_self_tests(repo_root: &RepoRoot) -> Result { let base = &repo_root.target.generated_java; let lib = &repo_root.lib.rust.parser.generate_java.java; + let external_dependencies_file = lib + .ancestors() + .nth(2) + .unwrap() + .join("target") + .join("streams") + .join("runtime") + .join("managedClasspath") + .join("_global") + .join("streams") + .join("export"); + + let dependencies_from_string = fs::read_to_string(&external_dependencies_file)?; + let dependencies_from_string = dependencies_from_string.trim_ascii_end(); let package = repo_root.target.generated_java.join_iter(GENERATED_CODE_NAMESPACE); let test = package.join(GENERATED_TEST_CLASS).with_extension(JAVA_EXTENSION); let test_class = @@ -63,7 +78,11 @@ pub async fn run_self_tests(repo_root: &RepoRoot) -> Result { Javac .cmd()? - .apply(&javac::Classpath::new([lib.as_path(), base.as_path()])) + .apply(&javac::Classpath::new([ + lib.as_path(), + base.as_path(), + Path::new(dependencies_from_string), + ])) .apply(&javac::Options::Directory(base.into())) .arg(&test) .run_ok() diff --git a/build/cli/src/lib.rs b/build/cli/src/lib.rs index ac7f5b2dc41..9d9a1b1e149 100644 --- a/build/cli/src/lib.rs +++ b/build/cli/src/lib.rs @@ -806,7 +806,11 @@ pub async fn main_internal(config: Option) -> Result { java_gen::Command::Build => generate_job.await, java_gen::Command::Test => { generate_job.await?; - let backend_context = ctx.prepare_backend_context(default()).await?; + let config = enso_build::engine::BuildConfigurationFlags { + test_java_generated_from_rust: true, + ..Default::default() + }; + let backend_context = ctx.prepare_backend_context(config).await?; backend_context.prepare_build_env().await?; enso_build::rust::parser::run_self_tests(&repo_root).await } diff --git a/lib/rust/parser/generate-java/java/module-info.java b/lib/rust/parser/generate-java/java/module-info.java index 3e1085f954e..0d64592703e 100644 --- a/lib/rust/parser/generate-java/java/module-info.java +++ b/lib/rust/parser/generate-java/java/module-info.java @@ -1,3 +1,5 @@ module org.enso.syntax { + requires org.slf4j; + exports org.enso.syntax2; } diff --git a/lib/rust/parser/generate-java/java/org/enso/syntax2/Parser.java b/lib/rust/parser/generate-java/java/org/enso/syntax2/Parser.java index 91731cdde52..04dd5f5b944 100644 --- a/lib/rust/parser/generate-java/java/org/enso/syntax2/Parser.java +++ b/lib/rust/parser/generate-java/java/org/enso/syntax2/Parser.java @@ -2,9 +2,11 @@ package org.enso.syntax2; import java.io.File; import java.net.URISyntaxException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; +import org.slf4j.LoggerFactory; public final class Parser implements AutoCloseable { private static void initializeLibraries() { @@ -141,7 +143,13 @@ public final class Parser implements AutoCloseable { var metadata = getMetadata(state); serializedTree.order(ByteOrder.LITTLE_ENDIAN); var message = new Message(serializedTree, input, base, metadata); - return Tree.deserialize(message); + try { + return Tree.deserialize(message); + } catch (BufferUnderflowException | IllegalArgumentException e) { + LoggerFactory.getLogger(this.getClass()) + .error("Unrecoverable parser failure for: {}", input, e); + throw e; + } } public static String getWarningMessage(Warning warning) {