use std::process::Command;
fn jbx_command() -> Command {
Command::new(env!("CARGO_BIN_EXE_jbx"))
}
fn jbx_output(args: &[&str]) -> String {
let output = jbx_command()
.args(args)
.output()
.expect("failed to run jbx");
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
if !output.status.success() {
panic!(
"jbx {} failed:\nstdout={stdout}\nstderr={stderr}",
args.join(" ")
);
}
stdout.to_string()
}
#[test]
fn jdk_list_shows_discovered_jdks() {
let output = jbx_output(&["jdk", "list"]);
assert!(
output
.lines()
.any(|line| line.starts_with(char::is_numeric)),
"jdk list should show at least one JDK, got: {output}"
);
}
#[test]
fn jdk_home_returns_path_for_baseline_jdk() {
let output = jbx_output(&["jdk", "home", "25"]);
assert!(
output.contains("jdks") || output.contains("jvm") || output.contains("Java"),
"jdk home 25 should return a JDK path, got: {output}"
);
}
#[test]
fn jdk_home_accepts_jbang_plus_version_selector() {
let plain = jbx_output(&["jdk", "home", "25"]);
let plus = jbx_output(&["jdk", "home", "25+"]);
assert_eq!(
plain.trim(),
plus.trim(),
"jdk home 25+ should resolve to the same path as jdk home 25"
);
}
#[test]
fn jdk_home_fails_for_missing_version_without_auto_install() {
let output = jbx_command()
.args(["jdk", "home", "999"])
.output()
.expect("failed to run jbx");
assert!(
!output.status.success(),
"jdk home 999 should fail without auto-install"
);
}
#[test]
fn jdk_home_defaults_to_25() {
let output = jbx_output(&["jdk", "home"]);
assert!(
output.contains("25"),
"jdk home (default) should reference JDK 25, got: {output}"
);
}
#[test]
fn jdk_symlink_cache_avoids_re_search() {
let output = jbx_output(&["jdk", "home", "25"]);
let _jdk_path = output.trim();
let cache_dir = dirs::cache_dir().unwrap().join("jbx").join("jdks");
let link = cache_dir.join("25");
assert!(link.exists(), "JDK cache should exist for JDK 25");
let resolved = if link.is_symlink() {
std::fs::read_link(&link).unwrap_or_else(|_| link.clone())
} else {
std::fs::canonicalize(&link).unwrap_or_else(|_| link.clone())
};
assert!(
resolved.join("bin").join("java").is_file(),
"symlink target should have bin/java, got: {}",
resolved.display()
);
assert!(
resolved.join("bin").join("javac").is_file(),
"symlink target should have bin/javac, got: {}",
resolved.display()
);
assert!(
resolved.join("release").is_file(),
"symlink target should have a release file, got: {}",
resolved.display()
);
}
#[cfg(unix)]
#[test]
fn jdk_home_removes_stale_cache_entry_that_is_not_jdk_root() {
let cache_dir = dirs::cache_dir().unwrap().join("jbx").join("jdks");
std::fs::create_dir_all(&cache_dir).unwrap();
let stale = cache_dir.join("999");
let _ = std::fs::remove_file(&stale);
std::os::unix::fs::symlink("/usr", &stale).unwrap();
let output = jbx_command()
.args(["jdk", "home", "999"])
.output()
.expect("failed to run jbx");
assert!(
!output.status.success(),
"stale /usr symlink must not be accepted as a JDK"
);
assert!(!stale.exists(), "stale cache entry should be removed");
}