#[cfg(test)]
#[allow(clippy::module_inception)]
mod tests {
use super::super::*;
use tempfile::TempDir;
#[tokio::test]
async fn test_version_checker_cache() {
let temp_dir = TempDir::new().unwrap();
unsafe {
std::env::set_var("AGPM_CONFIG_PATH", temp_dir.path().join("config.toml"));
}
let cache = version_check::VersionCheckCache {
latest_version: "1.2.3".to_string(),
current_version: env!("CARGO_PKG_VERSION").to_string(),
checked_at: chrono::Utc::now(),
update_available: true,
notified: false,
notification_count: 0,
};
assert_eq!(cache.latest_version, "1.2.3");
assert_eq!(cache.current_version, env!("CARGO_PKG_VERSION"));
assert!(cache.update_available);
assert!(!cache.notified);
unsafe {
std::env::remove_var("AGPM_CONFIG_PATH");
}
}
#[tokio::test]
async fn test_backup_manager() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test_binary");
let test_content = b"test binary content";
tokio::fs::write(&test_file, test_content).await.unwrap();
let manager = backup::BackupManager::new(test_file.clone());
assert!(!manager.backup_exists());
manager.create_backup().await.unwrap();
assert!(manager.backup_exists());
tokio::fs::write(&test_file, b"modified content").await.unwrap();
manager.restore_backup().await.unwrap();
let restored_content = tokio::fs::read(&test_file).await.unwrap();
assert_eq!(restored_content, test_content);
manager.cleanup_backup().await.unwrap();
assert!(!manager.backup_exists());
}
#[test]
fn test_upgrade_config_defaults() {
let config = config::UpgradeConfig::default();
assert!(!config.check_on_startup);
assert_eq!(config.check_interval, 86400);
assert!(config.auto_backup);
assert!(config.verify_checksum);
}
#[test]
fn test_version_format_info() {
use version_check::VersionChecker;
let info = VersionChecker::format_version_info("1.0.0", None);
assert_eq!(info, "Current version: 1.0.0 (up to date)");
let info = VersionChecker::format_version_info("1.0.0", Some("1.0.0"));
assert_eq!(info, "Current version: 1.0.0 (up to date)");
let info = VersionChecker::format_version_info("1.0.0", Some("1.1.0"));
assert_eq!(info, "Current version: 1.0.0\nLatest version: 1.1.0 (update available)");
}
#[test]
fn test_self_updater_creation() {
let updater = SelfUpdater::new();
assert_eq!(updater.current_version(), env!("CARGO_PKG_VERSION"));
let updater_forced = updater.force(true);
assert_eq!(updater_forced.current_version(), env!("CARGO_PKG_VERSION"));
}
#[test]
fn test_self_updater_version_comparison() {
use semver::Version;
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
let older = Version::parse("0.1.0").unwrap();
let newer = Version::new(current.major, current.minor, current.patch + 1);
assert!(older < current); assert_eq!(current, current); assert!(newer > current); }
#[test]
fn test_self_updater_force_mode() {
let updater = SelfUpdater::new().force(true);
assert_eq!(updater.current_version(), env!("CARGO_PKG_VERSION"));
}
#[test]
fn test_self_updater_platform_detection() {
#[cfg(windows)]
let expected_name = "agpm.exe";
#[cfg(not(windows))]
let expected_name = "agpm";
assert!(expected_name.contains("agpm"));
}
#[test]
fn test_self_updater_archive_extension() {
#[cfg(windows)]
let expected_ext = ".zip";
#[cfg(not(windows))]
let expected_ext = ".tar.xz";
assert!(expected_ext.contains("."));
}
#[tokio::test]
async fn test_self_updater_download_url_construction() {
let version = "1.0.0";
let expected_components = vec!["github.com", "aig787/agpm", version, "agpm"];
#[cfg(target_os = "macos")]
{
#[cfg(target_arch = "x86_64")]
let target = "x86_64-apple-darwin";
#[cfg(target_arch = "aarch64")]
let target = "aarch64-apple-darwin";
assert!(target.contains("apple-darwin"));
}
#[cfg(target_os = "linux")]
{
#[cfg(target_arch = "x86_64")]
let target = "x86_64-unknown-linux-gnu";
#[cfg(target_arch = "aarch64")]
let target = "aarch64-unknown-linux-gnu";
assert!(target.contains("linux"));
}
#[cfg(target_os = "windows")]
{
#[cfg(target_arch = "x86_64")]
let target = "x86_64-pc-windows-msvc";
#[cfg(target_arch = "aarch64")]
let target = "aarch64-pc-windows-msvc";
assert!(target.contains("windows"));
}
for component in expected_components {
assert!(!component.is_empty());
}
}
#[tokio::test]
async fn test_self_updater_checksum_url() {
let download_url = "https://github.com/aig787/agpm/releases/download/v1.0.0/agpm-x86_64-unknown-linux-gnu.tar.xz";
let expected_checksum_url = format!("{}.sha256", download_url);
assert!(download_url.contains("github.com"));
assert!(expected_checksum_url.ends_with(".sha256"));
let non_github = "https://example.com/agpm.tar.gz";
assert!(!non_github.contains("github.com"));
}
#[tokio::test]
async fn test_backup_path_generation() {
let temp_dir = TempDir::new().unwrap();
let binary_path = temp_dir.path().join("agpm");
let manager = backup::BackupManager::new(binary_path.clone());
let backup_path = manager.backup_path();
assert_eq!(backup_path.file_name().unwrap(), "agpm.backup");
assert_eq!(backup_path.parent().unwrap(), binary_path.parent().unwrap());
}
#[tokio::test]
async fn test_backup_error_handling() {
let temp_dir = TempDir::new().unwrap();
let non_existent = temp_dir.path().join("non_existent");
let manager = backup::BackupManager::new(non_existent);
let result = manager.create_backup().await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("Original file does not exist"));
let result = manager.restore_backup().await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("No backup found"));
}
#[tokio::test]
async fn test_version_cache_ttl() {
use chrono::{Duration, Utc};
use serde_json;
let temp_dir = TempDir::new().unwrap();
let cache_path = temp_dir.path().join(".agpm").join(".version_cache");
tokio::fs::create_dir_all(cache_path.parent().unwrap()).await.unwrap();
let old_cache = version_check::VersionCheckCache {
latest_version: "1.0.0".to_string(),
current_version: env!("CARGO_PKG_VERSION").to_string(),
checked_at: Utc::now() - Duration::hours(25), update_available: false,
notified: false,
notification_count: 0,
};
let content = serde_json::to_string_pretty(&old_cache).unwrap();
tokio::fs::write(&cache_path, content).await.unwrap();
unsafe {
std::env::set_var(
"AGPM_CONFIG_PATH",
temp_dir.path().join(".agpm").join("config.toml"),
);
}
let age_in_hours = 25;
assert!(age_in_hours > 24);
unsafe {
std::env::remove_var("AGPM_CONFIG_PATH");
}
}
#[test]
fn test_version_check_cache_creation() {
use chrono::Utc;
use version_check::VersionCheckCache;
let cache = VersionCheckCache::new("1.0.0".to_string(), "1.1.0".to_string());
assert_eq!(cache.current_version, "1.0.0");
assert_eq!(cache.latest_version, "1.1.0");
assert!(cache.update_available);
assert!(!cache.notified);
assert_eq!(cache.notification_count, 0);
let now = Utc::now();
let diff = now.signed_duration_since(cache.checked_at);
assert!(diff.num_seconds() < 5); }
#[test]
fn test_version_checker_is_expired() {
use chrono::{Duration, Utc};
use version_check::VersionCheckCache;
let mut cache = VersionCheckCache::new("1.0.0".to_string(), "1.1.0".to_string());
cache.checked_at = Utc::now() - Duration::hours(12);
assert_eq!(cache.current_version, "1.0.0");
assert_eq!(cache.latest_version, "1.1.0");
}
#[test]
fn test_version_notification_tracking() {
use version_check::VersionCheckCache;
let mut cache = VersionCheckCache::new("1.0.0".to_string(), "1.1.0".to_string());
assert!(!cache.notified);
assert_eq!(cache.notification_count, 0);
cache.notified = true;
cache.notification_count = 1;
assert!(cache.notified);
assert_eq!(cache.notification_count, 1);
cache.notification_count += 1;
assert_eq!(cache.notification_count, 2);
}
#[tokio::test]
async fn test_version_checker_display_notification() {
version_check::VersionChecker::display_update_notification("1.1.0");
}
#[test]
fn test_should_check_for_updates_config() {
let config = config::UpgradeConfig {
check_on_startup: true,
check_interval: 86400,
auto_backup: true,
verify_checksum: true,
};
assert!(config.check_on_startup);
let config_disabled = config::UpgradeConfig {
check_on_startup: false,
check_interval: 0,
..config
};
assert_eq!(config_disabled.check_interval, 0);
}
#[tokio::test]
async fn test_upgrade_url_matches_github_releases() {
use reqwest;
let platform = match (std::env::consts::OS, std::env::consts::ARCH) {
("macos", "aarch64") => "aarch64-apple-darwin",
("macos", "x86_64") => "x86_64-apple-darwin",
("linux", "aarch64") => "aarch64-unknown-linux-gnu",
("linux", "x86_64") => "x86_64-unknown-linux-gnu",
("windows", "x86_64") => "x86_64-pc-windows-msvc",
("windows", "aarch64") => "aarch64-pc-windows-msvc",
(os, arch) => panic!("Unsupported platform: {os}-{arch}"),
};
let extension = if std::env::consts::OS == "windows" {
"zip"
} else {
"tar.xz"
};
let expected_filename_by_code = format!("agpm-cli-{platform}.{extension}");
let test_version = "0.4.9";
let constructed_url = format!(
"https://github.com/aig787/agpm/releases/download/v{}/{}",
test_version, expected_filename_by_code
);
let client = reqwest::Client::new();
let response = client.head(&constructed_url).send().await.unwrap();
assert_eq!(response.status(), 200, "Expected 200 for correct URL: {}", constructed_url);
let old_incorrect_filename = format!("agpm-{platform}.{extension}");
let old_incorrect_url = format!(
"https://github.com/aig787/agpm/releases/download/v{}/{}",
test_version, old_incorrect_filename
);
let old_response = client.head(&old_incorrect_url).send().await.unwrap();
assert_eq!(
old_response.status(),
404,
"Expected 404 for old incorrect URL: {}",
old_incorrect_url
);
}
#[test]
fn test_checksum_filename_matching_logic() {
let test_cases = vec![
("agpm", "agpm", true), ("agpm", "agpm-linux-x86_64", true), ("agpm", "path/to/agpm", true), ("agpm", "agpm-dev", true), ("agpm", "not-agpm", false), ("agpm", "some-agpm-file", false), ("agpm.exe", "agpm.exe", true), ("agpm.exe", "agpm.exe-windows-x86_64", true), ("agpm.exe", "agpm.exe-dev", true), ];
for (binary_name, filename, expected) in test_cases {
let result = filename == binary_name
|| filename.starts_with(&format!("{}-", binary_name))
|| filename.ends_with(&format!("/{}", binary_name));
assert_eq!(
result,
expected,
"Binary '{}' {} match filename '{}'",
binary_name,
if expected {
"should"
} else {
"should not"
},
filename
);
}
}
}