use super::CacheConfig; use std::fs; use std::path::PathBuf; use std::time::Duration; use tempfile::TempDir; // note: config loading during validation creates cache directory to canonicalize its path, // that's why these function and macro always use custom cache directory // note: tempdir removes directory when being dropped, so we need to return it to the caller, // so the paths are valid pub fn test_prolog() -> (TempDir, PathBuf, PathBuf) { let _ = pretty_env_logger::try_init(); let temp_dir = tempfile::tempdir().expect("Can't create temporary directory"); let cache_dir = temp_dir.path().join("cache-dir"); let config_path = temp_dir.path().join("cache-config.toml"); (temp_dir, cache_dir, config_path) } macro_rules! load_config { ($config_path:ident, $content_fmt:expr, $cache_dir:ident) => {{ let config_path = &$config_path; let content = format!($content_fmt, cache_dir = $cache_dir.display()); fs::write(config_path, content).expect("Failed to write test config file"); CacheConfig::from_file(Some(config_path)).unwrap() }}; } macro_rules! bad_config { ($config_path:ident, $content_fmt:expr, $cache_dir:ident) => {{ let config_path = &$config_path; let content = format!($content_fmt, cache_dir = $cache_dir.display()); fs::write(config_path, content).expect("Failed to write test config file"); assert!(CacheConfig::from_file(Some(config_path)).is_err()); }}; } // test without macros to test being disabled #[test] fn test_disabled() { let dir = tempfile::tempdir().expect("Can't create temporary directory"); let config_path = dir.path().join("cache-config.toml"); let config_content = "[cache]\n\ enabled = false\n"; fs::write(&config_path, config_content).expect("Failed to write test config file"); let conf = CacheConfig::from_file(Some(&config_path)).unwrap(); assert!(!conf.enabled()); } #[test] fn test_unrecognized_settings() { let (_td, cd, cp) = test_prolog(); bad_config!( cp, "unrecognized-setting = 42\n\ [cache]\n\ enabled = true\n\ directory = '{cache_dir}'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ unrecognized-setting = 42", cd ); } #[test] fn test_all_settings() { let (_td, cd, cp) = test_prolog(); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ worker-event-queue-size = '16'\n\ baseline-compression-level = 3\n\ optimized-compression-level = 20\n\ optimized-compression-usage-counter-threshold = '256'\n\ cleanup-interval = '1h'\n\ optimizing-compression-task-timeout = '30m'\n\ allowed-clock-drift-for-files-from-future = '1d'\n\ file-count-soft-limit = '65536'\n\ files-total-size-soft-limit = '512Mi'\n\ file-count-limit-percent-if-deleting = '70%'\n\ files-total-size-limit-percent-if-deleting = '70%'", cd ); check_conf(&conf, &cd); let conf = load_config!( cp, // added some white spaces "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ worker-event-queue-size = ' 16\t'\n\ baseline-compression-level = 3\n\ optimized-compression-level =\t 20\n\ optimized-compression-usage-counter-threshold = '256'\n\ cleanup-interval = ' 1h'\n\ optimizing-compression-task-timeout = '30 m'\n\ allowed-clock-drift-for-files-from-future = '1\td'\n\ file-count-soft-limit = '\t \t65536\t'\n\ files-total-size-soft-limit = '512\t\t Mi '\n\ file-count-limit-percent-if-deleting = '70\t%'\n\ files-total-size-limit-percent-if-deleting = ' 70 %'", cd ); check_conf(&conf, &cd); fn check_conf(conf: &CacheConfig, cd: &PathBuf) { assert!(conf.enabled()); assert_eq!( conf.directory(), &fs::canonicalize(cd).expect("canonicalize failed") ); assert_eq!(conf.worker_event_queue_size(), 0x10); assert_eq!(conf.baseline_compression_level(), 3); assert_eq!(conf.optimized_compression_level(), 20); assert_eq!(conf.optimized_compression_usage_counter_threshold(), 0x100); assert_eq!(conf.cleanup_interval(), Duration::from_secs(60 * 60)); assert_eq!( conf.optimizing_compression_task_timeout(), Duration::from_secs(30 * 60) ); assert_eq!( conf.allowed_clock_drift_for_files_from_future(), Duration::from_secs(60 * 60 * 24) ); assert_eq!(conf.file_count_soft_limit(), 0x10_000); assert_eq!(conf.files_total_size_soft_limit(), 512 * (1u64 << 20)); assert_eq!(conf.file_count_limit_percent_if_deleting(), 70); assert_eq!(conf.files_total_size_limit_percent_if_deleting(), 70); } } #[test] fn test_compression_level_settings() { let (_td, cd, cp) = test_prolog(); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ baseline-compression-level = 1\n\ optimized-compression-level = 21", cd ); assert!(conf.enabled()); assert_eq!(conf.baseline_compression_level(), 1); assert_eq!(conf.optimized_compression_level(), 21); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ baseline-compression-level = -1\n\ optimized-compression-level = 21", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ baseline-compression-level = 15\n\ optimized-compression-level = 10", cd ); } #[test] fn test_si_prefix_settings() { let (_td, cd, cp) = test_prolog(); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ worker-event-queue-size = '42'\n\ optimized-compression-usage-counter-threshold = '4K'\n\ file-count-soft-limit = '3M'", cd ); assert!(conf.enabled()); assert_eq!(conf.worker_event_queue_size(), 42); assert_eq!(conf.optimized_compression_usage_counter_threshold(), 4_000); assert_eq!(conf.file_count_soft_limit(), 3_000_000); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ worker-event-queue-size = '2K'\n\ optimized-compression-usage-counter-threshold = '4444T'\n\ file-count-soft-limit = '1P'", cd ); assert!(conf.enabled()); assert_eq!(conf.worker_event_queue_size(), 2_000); assert_eq!( conf.optimized_compression_usage_counter_threshold(), 4_444_000_000_000_000 ); assert_eq!(conf.file_count_soft_limit(), 1_000_000_000_000_000); // different errors bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ worker-event-queue-size = '2g'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ file-count-soft-limit = 1", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ file-count-soft-limit = '-31337'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ file-count-soft-limit = '3.14M'", cd ); } #[test] fn test_disk_space_settings() { let (_td, cd, cp) = test_prolog(); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '76'", cd ); assert!(conf.enabled()); assert_eq!(conf.files_total_size_soft_limit(), 76); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '42 Mi'", cd ); assert!(conf.enabled()); assert_eq!(conf.files_total_size_soft_limit(), 42 * (1u64 << 20)); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '2 Gi'", cd ); assert!(conf.enabled()); assert_eq!(conf.files_total_size_soft_limit(), 2 * (1u64 << 30)); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '31337 Ti'", cd ); assert!(conf.enabled()); assert_eq!(conf.files_total_size_soft_limit(), 31337 * (1u64 << 40)); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '7 Pi'", cd ); assert!(conf.enabled()); assert_eq!(conf.files_total_size_soft_limit(), 7 * (1u64 << 50)); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '7M'", cd ); assert!(conf.enabled()); assert_eq!(conf.files_total_size_soft_limit(), 7_000_000); // different errors bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '7 mi'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = 1", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '-31337'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-soft-limit = '3.14Ki'", cd ); } #[test] fn test_duration_settings() { let (_td, cd, cp) = test_prolog(); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ cleanup-interval = '100s'\n\ optimizing-compression-task-timeout = '3m'\n\ allowed-clock-drift-for-files-from-future = '4h'", cd ); assert!(conf.enabled()); assert_eq!(conf.cleanup_interval(), Duration::from_secs(100)); assert_eq!( conf.optimizing_compression_task_timeout(), Duration::from_secs(3 * 60) ); assert_eq!( conf.allowed_clock_drift_for_files_from_future(), Duration::from_secs(4 * 60 * 60) ); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ cleanup-interval = '2d'\n\ optimizing-compression-task-timeout = '333 m'", cd ); assert!(conf.enabled()); assert_eq!( conf.cleanup_interval(), Duration::from_secs(2 * 24 * 60 * 60) ); assert_eq!( conf.optimizing_compression_task_timeout(), Duration::from_secs(333 * 60) ); // different errors bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ optimizing-compression-task-timeout = '333'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ optimizing-compression-task-timeout = 333", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ optimizing-compression-task-timeout = '10 M'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ optimizing-compression-task-timeout = '10 min'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ optimizing-compression-task-timeout = '-10s'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ optimizing-compression-task-timeout = '1.5m'", cd ); } #[test] fn test_percent_settings() { let (_td, cd, cp) = test_prolog(); let conf = load_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ file-count-limit-percent-if-deleting = '62%'\n\ files-total-size-limit-percent-if-deleting = '23 %'", cd ); assert!(conf.enabled()); assert_eq!(conf.file_count_limit_percent_if_deleting(), 62); assert_eq!(conf.files_total_size_limit_percent_if_deleting(), 23); // different errors bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-limit-percent-if-deleting = '23'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-limit-percent-if-deleting = '22.5%'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-limit-percent-if-deleting = '0.5'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-limit-percent-if-deleting = '-1%'", cd ); bad_config!( cp, "[cache]\n\ enabled = true\n\ directory = '{cache_dir}'\n\ files-total-size-limit-percent-if-deleting = '101%'", cd ); }