use super::CacheConfig;
use std::fs;
use std::path::PathBuf;
use std::time::Duration;
use tempfile::TempDir;
pub fn test_prolog() -> (TempDir, PathBuf, PathBuf) {
let _ = 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]
fn test_unrecognized_settings() {
let (_td, cd, cp) = test_prolog();
bad_config!(
cp,
"unrecognized-setting = 42\n\
[cache]\n\
directory = '{cache_dir}'",
cd
);
bad_config!(
cp,
"[cache]\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\
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,
"[cache]\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_eq!(
conf.directory(),
Some(&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\
directory = '{cache_dir}'\n\
baseline-compression-level = 1\n\
optimized-compression-level = 21",
cd
);
assert_eq!(conf.baseline_compression_level(), 1);
assert_eq!(conf.optimized_compression_level(), 21);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
baseline-compression-level = -1\n\
optimized-compression-level = 21",
cd
);
bad_config!(
cp,
"[cache]\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\
directory = '{cache_dir}'\n\
worker-event-queue-size = '42'\n\
optimized-compression-usage-counter-threshold = '4K'\n\
file-count-soft-limit = '3M'",
cd
);
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\
directory = '{cache_dir}'\n\
worker-event-queue-size = '2K'\n\
optimized-compression-usage-counter-threshold = '4444T'\n\
file-count-soft-limit = '1P'",
cd
);
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);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
worker-event-queue-size = '2g'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
file-count-soft-limit = 1",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
file-count-soft-limit = '-31337'",
cd
);
bad_config!(
cp,
"[cache]\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\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '76'",
cd
);
assert_eq!(conf.files_total_size_soft_limit(), 76);
let conf = load_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '42 Mi'",
cd
);
assert_eq!(conf.files_total_size_soft_limit(), 42 * (1u64 << 20));
let conf = load_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '2 Gi'",
cd
);
assert_eq!(conf.files_total_size_soft_limit(), 2 * (1u64 << 30));
let conf = load_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '31337 Ti'",
cd
);
assert_eq!(conf.files_total_size_soft_limit(), 31337 * (1u64 << 40));
let conf = load_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '7 Pi'",
cd
);
assert_eq!(conf.files_total_size_soft_limit(), 7 * (1u64 << 50));
let conf = load_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '7M'",
cd
);
assert_eq!(conf.files_total_size_soft_limit(), 7_000_000);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '7 mi'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = 1",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-soft-limit = '-31337'",
cd
);
bad_config!(
cp,
"[cache]\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\
directory = '{cache_dir}'\n\
cleanup-interval = '100s'\n\
optimizing-compression-task-timeout = '3m'\n\
allowed-clock-drift-for-files-from-future = '4h'",
cd
);
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\
directory = '{cache_dir}'\n\
cleanup-interval = '2d'\n\
optimizing-compression-task-timeout = '333 m'",
cd
);
assert_eq!(
conf.cleanup_interval(),
Duration::from_secs(2 * 24 * 60 * 60)
);
assert_eq!(
conf.optimizing_compression_task_timeout(),
Duration::from_secs(333 * 60)
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
optimizing-compression-task-timeout = '333'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
optimizing-compression-task-timeout = 333",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
optimizing-compression-task-timeout = '10 M'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
optimizing-compression-task-timeout = '10 min'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
optimizing-compression-task-timeout = '-10s'",
cd
);
bad_config!(
cp,
"[cache]\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\
directory = '{cache_dir}'\n\
file-count-limit-percent-if-deleting = '62%'\n\
files-total-size-limit-percent-if-deleting = '23 %'",
cd
);
assert_eq!(conf.file_count_limit_percent_if_deleting(), 62);
assert_eq!(conf.files_total_size_limit_percent_if_deleting(), 23);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-limit-percent-if-deleting = '23'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-limit-percent-if-deleting = '22.5%'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-limit-percent-if-deleting = '0.5'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-limit-percent-if-deleting = '-1%'",
cd
);
bad_config!(
cp,
"[cache]\n\
directory = '{cache_dir}'\n\
files-total-size-limit-percent-if-deleting = '101%'",
cd
);
}
#[test]
fn test_builder_default() {
let (_td, _cd, cp) = test_prolog();
let config_content = "[cache]\n";
fs::write(&cp, config_content).expect("Failed to write test config file");
let expected_config = CacheConfig::from_file(Some(&cp)).unwrap();
let mut config = CacheConfig::new();
config
.validate()
.expect("Failed to validate default config");
assert_eq!(config.directory, expected_config.directory);
assert_eq!(
config.worker_event_queue_size,
expected_config.worker_event_queue_size
);
assert_eq!(
config.baseline_compression_level,
expected_config.baseline_compression_level
);
assert_eq!(
config.optimized_compression_level,
expected_config.optimized_compression_level
);
assert_eq!(
config.optimized_compression_usage_counter_threshold,
expected_config.optimized_compression_usage_counter_threshold
);
assert_eq!(config.cleanup_interval, expected_config.cleanup_interval);
assert_eq!(
config.optimizing_compression_task_timeout,
expected_config.optimizing_compression_task_timeout
);
assert_eq!(
config.allowed_clock_drift_for_files_from_future,
expected_config.allowed_clock_drift_for_files_from_future
);
assert_eq!(
config.file_count_soft_limit,
expected_config.file_count_soft_limit
);
assert_eq!(
config.files_total_size_soft_limit,
expected_config.files_total_size_soft_limit
);
assert_eq!(
config.file_count_limit_percent_if_deleting,
expected_config.file_count_limit_percent_if_deleting
);
assert_eq!(
config.files_total_size_limit_percent_if_deleting,
expected_config.files_total_size_limit_percent_if_deleting
);
}
#[test]
fn test_builder_all_settings() {
let (_td, cd, _cp) = test_prolog();
let mut conf = CacheConfig::new();
conf.with_directory(&cd)
.with_worker_event_queue_size(0x10)
.with_baseline_compression_level(3)
.with_optimized_compression_level(20)
.with_optimized_compression_usage_counter_threshold(0x100)
.with_cleanup_interval(Duration::from_secs(60 * 60))
.with_optimizing_compression_task_timeout(Duration::from_secs(30 * 60))
.with_allowed_clock_drift_for_files_from_future(Duration::from_secs(60 * 60 * 24))
.with_file_count_soft_limit(0x10_000)
.with_files_total_size_soft_limit(512 * (1u64 << 20))
.with_file_count_limit_percent_if_deleting(70)
.with_files_total_size_limit_percent_if_deleting(70);
conf.validate().expect("validation failed");
check_conf(&conf, &cd);
fn check_conf(conf: &CacheConfig, cd: &PathBuf) {
assert_eq!(
conf.directory(),
Some(&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);
}
}