mod common;
use assert_cmd::Command;
use common::TestHomeGuard;
use predicates::prelude::*;
use serial_test::serial;
use std::fs;
use std::path::Path;
fn get_test_command(kopi_home: &Path) -> Command {
let mut cmd = Command::cargo_bin("kopi").unwrap();
cmd.env("KOPI_HOME", kopi_home.to_str().unwrap());
cmd.env("HOME", kopi_home.parent().unwrap());
cmd.current_dir(kopi_home.parent().unwrap());
cmd.env_remove("KOPI_JAVA_VERSION");
cmd.env_remove("SHELL");
cmd
}
fn setup_test_environment(test_home: &TestHomeGuard, version: &str) {
let kopi_version_file = test_home.path().join(".kopi-version");
fs::write(&kopi_version_file, version).unwrap();
}
#[test]
#[serial]
#[cfg(not(target_os = "windows"))]
fn test_env_basic_bash() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@21.0.1");
let jdk_path = kopi_home.join("jdks").join("temurin-21.0.1");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@21.0.1").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env").arg("--shell").arg("bash");
cmd.assert()
.success()
.stdout(predicate::str::contains("export JAVA_HOME="))
.stdout(predicate::str::contains("temurin-21.0.1"));
}
#[test]
#[serial]
fn test_env_platform_default() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@21.0.1");
let jdk_path = kopi_home.join("jdks").join("temurin-21.0.1");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@21.0.1").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env");
cmd.assert()
.success()
.stdout(predicate::str::contains("JAVA_HOME"))
.stdout(predicate::str::contains("temurin-21.0.1"));
}
#[test]
#[serial]
#[cfg(not(target_os = "windows"))]
fn test_env_fish_shell() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "corretto@17.0.5");
let jdk_path = kopi_home.join("jdks").join("corretto-17.0.5");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "corretto@17.0.5").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env").arg("--shell").arg("fish");
cmd.assert()
.success()
.stdout(predicate::str::contains("set -gx JAVA_HOME"))
.stdout(predicate::str::contains("corretto-17.0.5"));
}
#[test]
#[serial]
#[cfg(target_os = "windows")]
fn test_env_powershell() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "zulu@11.0.20");
let jdk_path = kopi_home.join("jdks").join("zulu-11.0.20");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "zulu@11.0.20").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env").arg("--shell").arg("powershell");
cmd.assert()
.success()
.stdout(predicate::str::contains("$env:JAVA_HOME ="))
.stdout(predicate::str::contains("zulu-11.0.20"));
}
#[test]
#[serial]
#[cfg(target_os = "windows")]
fn test_env_cmd() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "microsoft@21.0.1");
let jdk_path = kopi_home.join("jdks").join("microsoft-21.0.1");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "microsoft@21.0.1").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env").arg("--shell").arg("cmd");
cmd.assert()
.success()
.stdout(predicate::str::contains("set JAVA_HOME="))
.stdout(predicate::str::contains("microsoft-21.0.1"));
}
#[test]
#[serial]
#[cfg(not(target_os = "windows"))]
fn test_env_no_export() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@17.0.8");
let jdk_path = kopi_home.join("jdks").join("temurin-17.0.8");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@17.0.8").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env")
.arg("--shell")
.arg("bash")
.arg("--export")
.arg("false");
cmd.assert()
.success()
.stdout(predicate::str::contains("JAVA_HOME="))
.stdout(predicate::str::contains("temurin-17.0.8"))
.stdout(predicate::str::contains("export").not());
}
#[test]
#[serial]
fn test_env_explicit_version() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@17.0.8");
let jdk17_path = kopi_home.join("jdks").join("temurin-17.0.8");
let jdk21_path = kopi_home.join("jdks").join("temurin-21.0.1");
fs::create_dir_all(&jdk17_path).unwrap();
fs::create_dir_all(&jdk21_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@17.0.8").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
})
.arg("temurin@21.0.1");
#[cfg(target_os = "windows")]
let expected = "set JAVA_HOME=";
#[cfg(not(target_os = "windows"))]
let expected = "export JAVA_HOME=";
cmd.assert()
.success()
.stdout(predicate::str::contains(expected))
.stdout(predicate::str::contains("temurin-21.0.1"));
}
#[test]
#[serial]
fn test_env_kopi_version_file() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
let jdk_path = kopi_home.join("jdks").join("graalvm-22.0.1");
fs::create_dir_all(&jdk_path).unwrap();
let project_dir = test_home.path().join("project");
fs::create_dir_all(&project_dir).unwrap();
fs::write(project_dir.join(".kopi-version"), "graalvm@22.0.1").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.current_dir(&project_dir);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
#[cfg(target_os = "windows")]
let expected = "set JAVA_HOME=";
#[cfg(not(target_os = "windows"))]
let expected = "export JAVA_HOME=";
cmd.assert()
.success()
.stdout(predicate::str::contains(expected))
.stdout(predicate::str::contains("graalvm-22.0.1"));
}
#[test]
#[serial]
fn test_env_jdk_not_installed() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@21.0.1");
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@21.0.1").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
cmd.assert().failure().stderr(predicate::str::contains(
"JDK 'temurin@21.0.1' is not installed",
));
}
#[test]
#[serial]
fn test_env_no_version() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
let temp_dir = tempfile::TempDir::new().unwrap();
let isolated_dir = temp_dir.path().join("isolated");
fs::create_dir_all(&isolated_dir).unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.current_dir(&isolated_dir);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
cmd.assert().failure().stderr(predicate::str::contains(
"No JDK configured for current project",
));
}
#[test]
#[serial]
fn test_env_path_with_spaces() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin with spaces@21.0.1");
let jdk_path = kopi_home.join("jdks").join("temurin with spaces-21.0.1");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin with spaces@21.0.1").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
#[cfg(target_os = "windows")]
let expected = "set JAVA_HOME=";
#[cfg(not(target_os = "windows"))]
let expected = "export JAVA_HOME=";
cmd.assert()
.success()
.stdout(predicate::str::contains(expected))
.stdout(predicate::str::contains("temurin with spaces-21.0.1"));
}
#[test]
#[serial]
fn test_env_invalid_shell() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@21.0.1");
let jdk_path = kopi_home.join("jdks").join("temurin-21.0.1");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@21.0.1").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env").arg("--shell").arg("invalid-shell");
cmd.assert().failure().stderr(predicate::str::contains(
"Shell 'invalid-shell' is not supported",
));
}
#[test]
#[serial]
fn test_env_shell_detection() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@21.0.1");
let jdk_path = kopi_home.join("jdks").join("temurin-21.0.1");
fs::create_dir_all(&jdk_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@21.0.1").unwrap();
#[cfg(not(target_os = "windows"))]
let shells = vec![("bash", "export JAVA_HOME="), ("zsh", "export JAVA_HOME=")];
#[cfg(target_os = "windows")]
let shells = vec![("powershell", "$env:JAVA_HOME ="), ("cmd", "set JAVA_HOME")];
for (shell_name, expected_prefix) in shells {
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env").arg("--shell").arg(shell_name);
cmd.assert()
.success()
.stdout(predicate::str::contains(expected_prefix));
}
}
#[test]
#[serial]
fn test_env_malformed_version_file() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "invalid@@version");
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "invalid@@version").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
cmd.assert().failure().stderr(predicate::str::contains(
"Invalid configuration: Unknown package type: invalid",
));
}
#[test]
#[serial]
fn test_env_with_kopi_java_version() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@17.0.8");
let jdk17_path = kopi_home.join("jdks").join("temurin-17.0.8");
let jdk21_path = kopi_home.join("jdks").join("temurin-21.0.1");
fs::create_dir_all(&jdk17_path).unwrap();
fs::create_dir_all(&jdk21_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@17.0.8").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.env("KOPI_JAVA_VERSION", "temurin@21.0.1");
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
#[cfg(target_os = "windows")]
let expected = "set JAVA_HOME=";
#[cfg(not(target_os = "windows"))]
let expected = "export JAVA_HOME=";
cmd.assert()
.success()
.stdout(predicate::str::contains(expected))
.stdout(predicate::str::contains("temurin-21.0.1"));
}
#[test]
#[serial]
fn test_env_version_resolution_hierarchy() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
let jdk_path = kopi_home.join("jdks").join("zulu-11.0.20");
fs::create_dir_all(&jdk_path).unwrap();
let project_root = test_home.path().join("project");
let sub_dir = project_root.join("src").join("main").join("java");
fs::create_dir_all(&sub_dir).unwrap();
fs::write(project_root.join(".kopi-version"), "zulu@11.0.20").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.current_dir(&sub_dir);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
#[cfg(target_os = "windows")]
let expected = "set JAVA_HOME=";
#[cfg(not(target_os = "windows"))]
let expected = "export JAVA_HOME=";
cmd.assert()
.success()
.stdout(predicate::str::contains(expected))
.stdout(predicate::str::contains("zulu-11.0.20"));
}
#[test]
#[serial]
fn test_env_multiple_matching_jdks() {
let test_home = TestHomeGuard::new();
test_home.setup_kopi_structure();
let kopi_home = test_home.kopi_home();
setup_test_environment(&test_home, "temurin@21");
let jdk_old_path = kopi_home.join("jdks").join("temurin-21.0.1");
let jdk_new_path = kopi_home.join("jdks").join("temurin-21.0.2");
fs::create_dir_all(&jdk_old_path).unwrap();
fs::create_dir_all(&jdk_new_path).unwrap();
let global_version_file = kopi_home.join("version");
fs::write(&global_version_file, "temurin@21").unwrap();
let mut cmd = get_test_command(&kopi_home);
cmd.arg("env")
.arg("--shell")
.arg(if cfg!(target_os = "windows") {
"cmd"
} else {
"bash"
});
#[cfg(target_os = "windows")]
let expected = "set JAVA_HOME=";
#[cfg(not(target_os = "windows"))]
let expected = "export JAVA_HOME=";
cmd.assert()
.success()
.stdout(predicate::str::contains(expected))
.stdout(predicate::str::contains("temurin-21.0.2"));
}