use std::path::PathBuf;
use tempfile::TempDir;
use tidepool_version_manager::{
go::GoManager, ListInstalledRequest, UninstallRequest, VersionManager,
};
#[cfg(windows)]
use tidepool_version_manager::SwitchRequest;
#[test]
fn test_new_go_manager() {
let _manager = GoManager::new();
}
#[test]
#[cfg(windows)]
fn test_switch_to_basic_functionality() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let base_dir = PathBuf::from(temp_dir.path());
let version = "1.21.3";
let go_root = base_dir.join(version);
let go_bin_dir = go_root.join("bin");
std::fs::create_dir_all(&go_bin_dir).unwrap();
std::fs::write(go_bin_dir.join("go.exe"), b"fake go binary").unwrap();
let request = SwitchRequest {
version: version.to_string(),
base_dir: base_dir.clone(),
global: false,
force: false,
};
let result = manager.switch_to(request);
match result {
Ok(()) => {
let current_dir = base_dir.join("current");
assert!(current_dir.exists(), "Current directory should be created as a symlink");
}
Err(e) => {
assert!(
e.contains("Failed to create symlink")
|| e.contains("Access is denied")
|| e.contains("permission")
|| e.contains("symlink"),
"Unexpected error: {e}"
);
println!("Test skipped due to permission issue: {e}");
}
}
}
#[test]
#[cfg(windows)]
fn test_switch_version() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let base_dir = PathBuf::from(temp_dir.path());
let version = "1.21.3";
let go_root = base_dir.join(version);
let go_bin_dir = go_root.join("bin");
std::fs::create_dir_all(&go_bin_dir).unwrap();
std::fs::write(go_bin_dir.join("go.exe"), b"fake go binary").unwrap();
let request = SwitchRequest {
version: version.to_string(),
base_dir: base_dir.clone(),
global: false,
force: false,
};
let result = manager.switch_to(request);
match result {
Ok(()) => {
println!("符号链接创建成功");
}
Err(e) => {
assert!(
e.contains("Failed to create symlink")
|| e.contains("Access is denied")
|| e.contains("permission")
|| e.contains("symlink"),
"Unexpected error: {e}"
);
println!("Test skipped due to permission issue: {e}");
}
}
let request = SwitchRequest {
version: "999.999.999".to_string(),
base_dir: base_dir.clone(),
global: false,
force: false,
};
let result = manager.switch_to(request);
assert!(result.is_err());
assert!(result.unwrap_err().contains("not installed"));
}
#[test]
fn test_list_installed_versions_success() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let base_dir = PathBuf::from(temp_dir.path());
let version1 = "1.21.3";
let version2 = "1.20.8";
for version in &[version1, version2] {
let version_dir = base_dir.join(version).join("bin");
std::fs::create_dir_all(&version_dir).unwrap();
let go_binary_name = if cfg!(target_os = "windows") { "go.exe" } else { "go" };
std::fs::write(version_dir.join(go_binary_name), b"fake go binary").unwrap();
}
let request = ListInstalledRequest { base_dir };
let result = manager.list_installed(request);
assert!(result.is_ok());
let version_list = result.unwrap();
assert_eq!(version_list.total_count, 2);
assert_eq!(version_list.versions.len(), 2);
assert!(version_list.versions.contains(&version1.to_string()));
assert!(version_list.versions.contains(&version2.to_string()));
}
#[test]
fn test_list_installed_versions_empty() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let base_dir = PathBuf::from(temp_dir.path());
let request = ListInstalledRequest { base_dir };
let result = manager.list_installed(request);
assert!(result.is_ok());
let version_list = result.unwrap();
assert_eq!(version_list.total_count, 0);
assert!(version_list.versions.is_empty());
}
#[test]
fn test_list_installed_versions_nonexistent_dir() {
let manager = GoManager::new();
let base_dir = PathBuf::from("nonexistent_directory");
let request = ListInstalledRequest { base_dir };
let result = manager.list_installed(request);
assert!(result.is_err());
let error_message = result.unwrap_err();
assert!(error_message.contains("does not exist") || error_message.contains("Failed to read"));
}
#[test]
fn test_uninstall_version_success() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let base_dir = PathBuf::from(temp_dir.path());
let version = "1.21.3";
let version_dir = base_dir.join(version);
std::fs::create_dir_all(&version_dir).unwrap();
assert!(version_dir.exists());
let request = UninstallRequest { version: version.to_string(), base_dir };
let result = manager.uninstall(request);
assert!(result.is_ok());
assert!(!version_dir.exists());
}
#[test]
fn test_uninstall_version_not_found() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let base_dir = PathBuf::from(temp_dir.path());
let request = UninstallRequest { version: "999.999.999".to_string(), base_dir };
let result = manager.uninstall(request);
assert!(result.is_err());
let error_message = result.unwrap_err();
assert!(error_message.contains("not installed") || error_message.contains("does not exist"));
}
#[test]
fn test_list_installed_excludes_current_directory() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let base_dir = PathBuf::from(temp_dir.path());
let version1 = "1.21.3";
let version2 = "1.20.5";
for version in [version1, version2] {
let go_root = base_dir.join(version);
let go_bin_dir = go_root.join("bin");
std::fs::create_dir_all(&go_bin_dir).unwrap();
let go_binary_name = if cfg!(target_os = "windows") { "go.exe" } else { "go" };
std::fs::write(go_bin_dir.join(go_binary_name), b"fake go binary").unwrap();
}
let current_dir = base_dir.join("current");
let current_bin_dir = current_dir.join("bin");
std::fs::create_dir_all(¤t_bin_dir).unwrap();
let go_binary_name = if cfg!(target_os = "windows") { "go.exe" } else { "go" };
std::fs::write(current_bin_dir.join(go_binary_name), b"fake go binary").unwrap();
let request = ListInstalledRequest { base_dir };
let result = manager.list_installed(request);
assert!(result.is_ok());
let version_list = result.unwrap();
assert_eq!(version_list.total_count, 2, "Should only count actual version directories");
assert_eq!(version_list.versions.len(), 2, "Should only list actual version directories");
assert!(version_list.versions.contains(&version1.to_string()));
assert!(version_list.versions.contains(&version2.to_string()));
assert!(
!version_list.versions.contains(&"current".to_string()),
"Should not include 'current' directory in version list"
);
let mut expected_versions = vec![version1.to_string(), version2.to_string()];
expected_versions.sort();
assert_eq!(version_list.versions, expected_versions);
}
#[test]
fn test_install_cache_functionality() {
let _manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let install_dir = PathBuf::from(temp_dir.path()).join("install");
let download_dir = PathBuf::from(temp_dir.path()).join("cache");
std::fs::create_dir_all(&install_dir).unwrap();
std::fs::create_dir_all(&download_dir).unwrap();
let version = "1.21.3";
let (os, arch) = if cfg!(target_os = "windows") {
("windows", if cfg!(target_arch = "x86_64") { "amd64" } else { "386" })
} else if cfg!(target_os = "macos") {
("darwin", if cfg!(target_arch = "x86_64") { "amd64" } else { "arm64" })
} else {
("linux", if cfg!(target_arch = "x86_64") { "amd64" } else { "386" })
};
let extension = if cfg!(target_os = "windows") { "zip" } else { "tar.gz" };
let archive_name = format!("go{version}.{os}-{arch}.{extension}");
let cache_file = download_dir.join(&archive_name);
std::fs::write(&cache_file, b"fake cached go archive content").unwrap();
assert!(cache_file.exists());
let metadata = std::fs::metadata(&cache_file).unwrap();
assert!(metadata.len() > 0);
println!("✅ Cache functionality test setup completed");
println!(" - Cache file: {}", cache_file.display());
println!(" - Cache file size: {} bytes", metadata.len());
}
#[test]
fn test_install_empty_cache_file() {
let temp_dir = TempDir::new().unwrap();
let download_dir = PathBuf::from(temp_dir.path()).join("cache");
std::fs::create_dir_all(&download_dir).unwrap();
let version = "1.21.3";
let (os, arch) = if cfg!(target_os = "windows") {
("windows", if cfg!(target_arch = "x86_64") { "amd64" } else { "386" })
} else if cfg!(target_os = "macos") {
("darwin", if cfg!(target_arch = "x86_64") { "amd64" } else { "arm64" })
} else {
("linux", if cfg!(target_arch = "x86_64") { "amd64" } else { "386" })
};
let extension = if cfg!(target_os = "windows") { "zip" } else { "tar.gz" };
let archive_name = format!("go{version}.{os}-{arch}.{extension}");
let cache_file = download_dir.join(&archive_name);
std::fs::write(&cache_file, b"").unwrap();
assert!(cache_file.exists());
let metadata = std::fs::metadata(&cache_file).unwrap();
assert_eq!(metadata.len(), 0);
println!("✅ Empty cache file handling test completed");
println!(" - Empty cache file: {}", cache_file.display());
}
#[test]
fn test_cache_file_validation() {
let manager = GoManager::new();
let temp_dir = TempDir::new().unwrap();
let cache_dir = PathBuf::from(temp_dir.path()).join("cache");
std::fs::create_dir_all(&cache_dir).unwrap();
let nonexistent_file = cache_dir.join("nonexistent.zip");
assert!(!manager.validate_cache_file(&nonexistent_file));
let empty_file = cache_dir.join("empty.zip");
std::fs::write(&empty_file, b"").unwrap();
assert!(!manager.validate_cache_file(&empty_file));
let small_file = cache_dir.join("small.zip");
std::fs::write(&small_file, b"small content").unwrap();
assert!(!manager.validate_cache_file(&small_file));
let valid_file = cache_dir.join("valid.zip");
let large_content = vec![b'x'; 2048]; std::fs::write(&valid_file, &large_content).unwrap();
assert!(manager.validate_cache_file(&valid_file));
println!("✅ Cache file validation tests completed");
}