f45e3f1237
Compile and validate original exporter bundles during release builds, cache development compilation, and reuse initialized JVMs and collision data during preparation. Keep legacy preparers compatible while current releases need only a Java runtime. Co-Authored-By: Codex <noreply@openai.com>
146 lines
5.4 KiB
Rust
146 lines
5.4 KiB
Rust
//! Each scenario runs in its own process so Java discovery sees a controlled environment.
|
|
use horizon_prepare::java;
|
|
use std::{env, fs, path::Path, process::Command};
|
|
|
|
const TEST: &str = "selects_a_compatible_compiler_and_runtime";
|
|
const CHILD: &str = "HORIZON_JAVA_SELECTION_CHILD";
|
|
const ROOT: &str = "HORIZON_JAVA_SELECTION_ROOT";
|
|
|
|
fn tool(bin: &Path, name: &str) -> std::path::PathBuf {
|
|
bin.join(format!("{name}{}", env::consts::EXE_SUFFIX))
|
|
}
|
|
|
|
#[test]
|
|
fn selects_a_compatible_compiler_and_runtime() {
|
|
if let Ok(scenario) = env::var(CHILD) {
|
|
let root = std::path::PathBuf::from(env::var_os(ROOT).unwrap());
|
|
if scenario.ends_with("error") {
|
|
// Use a future compiler version to keep real installed JDKs out of the result.
|
|
let error = java::find(255, &[]).err().expect("accepted an old runtime");
|
|
let runtime = if scenario == "legacy-runtime-error" {
|
|
8
|
|
} else {
|
|
21
|
|
};
|
|
assert!(error.contains(&format!("java {runtime} (")), "{error}");
|
|
return;
|
|
}
|
|
let jdk = if scenario == "runtime-only" {
|
|
java::find_runtime(25, &[])
|
|
} else {
|
|
java::find(25, &[])
|
|
}
|
|
.unwrap();
|
|
let expected = root.join(if scenario == "runtime-only" {
|
|
"jre25"
|
|
} else if scenario == "target-release" {
|
|
"newer"
|
|
} else {
|
|
"jdk25"
|
|
});
|
|
for (actual, name) in [(&jdk.javac, "javac"), (&jdk.java, "java")] {
|
|
if scenario == "runtime-only" && name == "javac" {
|
|
continue;
|
|
}
|
|
assert_eq!(
|
|
fs::canonicalize(actual).unwrap(),
|
|
fs::canonicalize(tool(&expected.join("bin"), name)).unwrap()
|
|
);
|
|
}
|
|
assert_eq!(
|
|
fs::canonicalize(jdk.home()).unwrap(),
|
|
fs::canonicalize(expected).unwrap()
|
|
);
|
|
let log_path = root.join(format!("{scenario}.log"));
|
|
let log = fs::File::create(&log_path).unwrap();
|
|
jdk.java(&[], None, &log).unwrap();
|
|
assert_eq!(fs::read_to_string(log_path).unwrap().trim(), "java 25.0.1");
|
|
return;
|
|
}
|
|
|
|
let root = env::temp_dir().join(format!("horizon-java-selection-{}", std::process::id()));
|
|
fs::create_dir_all(&root).unwrap();
|
|
let probe = tool(&root, "probe");
|
|
let output = Command::new("rustc")
|
|
.arg(Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/support/java_probe.rs"))
|
|
.arg("-o")
|
|
.arg(&probe)
|
|
.output()
|
|
.unwrap();
|
|
assert!(
|
|
output.status.success(),
|
|
"{}",
|
|
String::from_utf8_lossy(&output.stderr)
|
|
);
|
|
for (home, compiler, runtime) in [
|
|
("jre21", None, "21.0.1"),
|
|
("jre25", None, "25.0.1"),
|
|
("jdk21", Some("21.0.1"), "21.0.1"),
|
|
("jdk25", Some("25.0.1"), "25.0.1"),
|
|
("mixed", Some("25.0.1"), "21.0.1"),
|
|
("failing", Some("25.0.1"), "25.0.1"),
|
|
("newer", Some("26-ea+1"), "25.0.1"),
|
|
("future", Some("255.0.1"), "21.0.1"),
|
|
("legacy", Some("255.0.1"), "1.8.0_442"),
|
|
] {
|
|
let bin = root.join(home).join("bin");
|
|
fs::create_dir_all(&bin).unwrap();
|
|
for (name, version) in [("javac", compiler), ("java", Some(runtime))] {
|
|
if let Some(version) = version {
|
|
fs::copy(&probe, tool(&bin, name)).unwrap();
|
|
fs::write(bin.join(format!("{name}.version")), version).unwrap();
|
|
}
|
|
}
|
|
}
|
|
fs::write(root.join("failing/bin/java.exit"), "7").unwrap();
|
|
let scenarios = vec![
|
|
("runtime-only", Some("jre25"), vec!["jre21", "jre25"]),
|
|
("older-runtime", None, vec!["jre21", "jdk25"]),
|
|
("older-jdk", None, vec!["jdk21", "jdk25"]),
|
|
("incompatible-home", Some("mixed"), vec!["jdk25"]),
|
|
("failed-runtime", Some("failing"), vec!["jdk25"]),
|
|
("target-release", Some("newer"), vec![]),
|
|
("runtime-error", Some("future"), vec![]),
|
|
("legacy-runtime-error", Some("legacy"), vec![]),
|
|
];
|
|
#[cfg(unix)]
|
|
let scenarios = {
|
|
let mut scenarios = scenarios;
|
|
let bin = root.join("shims/bin");
|
|
fs::create_dir_all(&bin).unwrap();
|
|
std::os::unix::fs::symlink(tool(&root.join("jdk25/bin"), "javac"), tool(&bin, "javac"))
|
|
.unwrap();
|
|
std::os::unix::fs::symlink(tool(&root.join("jre21/bin"), "java"), tool(&bin, "java"))
|
|
.unwrap();
|
|
scenarios.push(("symlinked-path", None, vec!["shims"]));
|
|
scenarios
|
|
};
|
|
for (scenario, home, path) in scenarios {
|
|
let mut child = Command::new(env::current_exe().unwrap());
|
|
child
|
|
.args(["--exact", TEST, "--nocapture"])
|
|
.env(CHILD, scenario)
|
|
.env(ROOT, &root)
|
|
.env(
|
|
"PATH",
|
|
env::join_paths(path.iter().map(|home| root.join(home).join("bin"))).unwrap(),
|
|
)
|
|
.env("HOME", &root)
|
|
.env("USERPROFILE", &root)
|
|
.env("ProgramFiles", &root)
|
|
.env("ProgramW6432", &root)
|
|
.env_remove("JAVA_HOME");
|
|
if let Some(home) = home {
|
|
child.env("JAVA_HOME", root.join(home));
|
|
}
|
|
let output = child.output().unwrap();
|
|
assert!(
|
|
output.status.success(),
|
|
"{scenario}:\n{}\n{}",
|
|
String::from_utf8_lossy(&output.stdout),
|
|
String::from_utf8_lossy(&output.stderr)
|
|
);
|
|
}
|
|
fs::remove_dir_all(root).unwrap();
|
|
}
|