use std::env;
use std::path::PathBuf;
use std::process::Command;
fn get_kopi_binary() -> PathBuf {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let target_dir = PathBuf::from(manifest_dir).join("target");
let debug_binary = target_dir.join("debug").join("kopi");
if debug_binary.exists() {
return debug_binary;
}
let release_binary = target_dir.join("release").join("kopi");
if release_binary.exists() {
return release_binary;
}
panic!("kopi binary not found. Run 'cargo build' first.");
}
fn shell_available(shell: &str) -> bool {
Command::new("which")
.arg(shell)
.output()
.map(|output| output.status.success())
.unwrap_or(false)
}
#[test]
#[ignore] fn test_bash_shell_execution() {
if !shell_available("bash") {
eprintln!("Skipping bash test - shell not available");
return;
}
let kopi_path = get_kopi_binary();
let script = format!(
r#"
eval "$({} env --quiet)"
echo "$JAVA_HOME"
"#,
kopi_path.display()
);
let output = Command::new("bash")
.arg("-c")
.arg(&script)
.output()
.expect("Failed to execute bash");
if output.status.success() {
let java_home = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert!(!java_home.is_empty(), "JAVA_HOME should be set");
assert!(
java_home.contains("kopi"),
"JAVA_HOME should point to a kopi-managed JDK"
);
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("No local version") || stderr.contains("not installed"),
"Unexpected error: {stderr}"
);
}
}
#[test]
#[ignore] fn test_zsh_shell_execution() {
if !shell_available("zsh") {
eprintln!("Skipping zsh test - shell not available");
return;
}
let kopi_path = get_kopi_binary();
let script = format!(
r#"
eval "$({} env --quiet)"
echo "$JAVA_HOME"
"#,
kopi_path.display()
);
let output = Command::new("zsh")
.arg("-c")
.arg(&script)
.output()
.expect("Failed to execute zsh");
if output.status.success() {
let java_home = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert!(!java_home.is_empty(), "JAVA_HOME should be set");
assert!(
java_home.contains("kopi"),
"JAVA_HOME should point to a kopi-managed JDK"
);
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("No local version") || stderr.contains("not installed"),
"Unexpected error: {stderr}"
);
}
}
#[test]
#[ignore] fn test_fish_shell_execution() {
if !shell_available("fish") {
eprintln!("Skipping fish test - shell not available");
return;
}
let kopi_path = get_kopi_binary();
let script = format!(
r#"
{} env --quiet | source
echo $JAVA_HOME
"#,
kopi_path.display()
);
let output = Command::new("fish")
.arg("-c")
.arg(&script)
.output()
.expect("Failed to execute fish");
if output.status.success() {
let java_home = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert!(!java_home.is_empty(), "JAVA_HOME should be set");
assert!(
java_home.contains("kopi"),
"JAVA_HOME should point to a kopi-managed JDK"
);
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("No local version") || stderr.contains("not installed"),
"Unexpected error: {stderr}"
);
}
}
#[test]
#[ignore] fn test_powershell_shell_execution() {
if !cfg!(windows) && !shell_available("pwsh") {
eprintln!("Skipping PowerShell test - shell not available");
return;
}
let kopi_path = get_kopi_binary();
let shell = if cfg!(windows) { "powershell" } else { "pwsh" };
let script = format!(
r#"
& '{}' env --quiet | Invoke-Expression
$env:JAVA_HOME
"#,
kopi_path.display()
);
let output = Command::new(shell)
.arg("-Command")
.arg(&script)
.output()
.expect("Failed to execute PowerShell");
if output.status.success() {
let java_home = String::from_utf8_lossy(&output.stdout).trim().to_string();
if !java_home.is_empty() {
assert!(
java_home.contains("kopi"),
"JAVA_HOME should point to a kopi-managed JDK"
);
}
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!("PowerShell stderr: {stderr}");
}
}
#[test]
#[ignore] fn test_cmd_shell_execution() {
if !cfg!(windows) {
eprintln!("Skipping CMD test - only runs on Windows");
return;
}
let kopi_path = get_kopi_binary();
let temp_dir = env::temp_dir();
let batch_file = temp_dir.join("test_kopi_env.bat");
let batch_content = format!(
r#"@echo off
for /f "tokens=*" %%i in ('"{}" env --quiet --shell cmd') do %%i
echo %JAVA_HOME%
"#,
kopi_path.display()
);
std::fs::write(&batch_file, batch_content).expect("Failed to write batch file");
let output = Command::new("cmd")
.arg("/c")
.arg(&batch_file)
.output()
.expect("Failed to execute CMD");
let _ = std::fs::remove_file(&batch_file);
if output.status.success() {
let java_home = String::from_utf8_lossy(&output.stdout).trim().to_string();
if !java_home.is_empty() && !java_home.contains("JAVA_HOME") {
assert!(
java_home.contains("kopi"),
"JAVA_HOME should point to a kopi-managed JDK"
);
}
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!("CMD stderr: {stderr}");
}
}
#[test]
#[ignore] fn test_shell_execution_with_spaces_in_path() {
if !shell_available("bash") {
eprintln!("Skipping spaces test - bash not available");
return;
}
let kopi_path = get_kopi_binary();
let script = format!(
r#"
# First check if kopi env works
output=$({} env --quiet 2>&1)
if [ $? -eq 0 ]; then
# If it works, test that quotes are handled properly
eval "$output"
# Check that JAVA_HOME is set and accessible
if [ -n "$JAVA_HOME" ]; then
echo "JAVA_HOME is set to: $JAVA_HOME"
# Try to use the path (this will fail if escaping is wrong)
if [ -d "$JAVA_HOME" ]; then
echo "Directory exists"
else
echo "Directory does not exist"
fi
fi
else
echo "kopi env failed: $output"
fi
"#,
kopi_path.display()
);
let output = Command::new("bash")
.arg("-c")
.arg(&script)
.output()
.expect("Failed to execute bash");
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
println!("stdout: {stdout}");
println!("stderr: {stderr}");
assert!(
stdout.contains("Directory exists")
|| stderr.contains("No local version")
|| stderr.contains("not installed")
|| stdout.contains("kopi env failed"),
"Unexpected output"
);
}
#[test]
fn test_env_command_exists() {
let kopi_path = get_kopi_binary();
let output = Command::new(&kopi_path)
.arg("env")
.arg("--help")
.output()
.expect("Failed to execute kopi");
assert!(output.status.success(), "kopi env --help should succeed");
let help_text = String::from_utf8_lossy(&output.stdout);
assert!(help_text.contains("Output environment variables"));
assert!(help_text.contains("Examples:"));
assert!(help_text.contains("eval"));
}
#[test]
fn test_env_shell_override() {
let kopi_path = get_kopi_binary();
let bash_output = Command::new(&kopi_path)
.arg("env")
.arg("--shell")
.arg("bash")
.arg("--export=false")
.output()
.expect("Failed to execute kopi");
let fish_output = Command::new(&kopi_path)
.arg("env")
.arg("--shell")
.arg("fish")
.arg("--export=false")
.output()
.expect("Failed to execute kopi");
if bash_output.status.success() && fish_output.status.success() {
let bash_text = String::from_utf8_lossy(&bash_output.stdout);
let fish_text = String::from_utf8_lossy(&fish_output.stdout);
assert_eq!(bash_text, fish_text, "Path output should be the same");
}
let bash_export = Command::new(&kopi_path)
.arg("env")
.arg("--shell")
.arg("bash")
.output()
.expect("Failed to execute kopi");
let fish_export = Command::new(&kopi_path)
.arg("env")
.arg("--shell")
.arg("fish")
.output()
.expect("Failed to execute kopi");
if bash_export.status.success() && fish_export.status.success() {
let bash_text = String::from_utf8_lossy(&bash_export.stdout);
let fish_text = String::from_utf8_lossy(&fish_export.stdout);
assert!(bash_text.contains("export JAVA_HOME="));
assert!(fish_text.contains("set -gx JAVA_HOME"));
assert_ne!(bash_text, fish_text, "Shell-specific output should differ");
}
}