1 use super::CacheConfig; 2 use std::fs; 3 use std::path::PathBuf; 4 use std::time::Duration; 5 use tempfile::TempDir; 6 7 // note: config loading during validation creates cache directory to canonicalize its path, 8 // that's why these function and macro always use custom cache directory 9 // note: tempdir removes directory when being dropped, so we need to return it to the caller, 10 // so the paths are valid 11 pub fn test_prolog() -> (TempDir, PathBuf, PathBuf) { 12 let _ = pretty_env_logger::try_init(); 13 let temp_dir = tempfile::tempdir().expect("Can't create temporary directory"); 14 let cache_dir = temp_dir.path().join("cache-dir"); 15 let config_path = temp_dir.path().join("cache-config.toml"); 16 (temp_dir, cache_dir, config_path) 17 } 18 19 macro_rules! load_config { 20 ($config_path:ident, $content_fmt:expr, $cache_dir:ident) => {{ 21 let config_path = &$config_path; 22 let content = format!($content_fmt, cache_dir = $cache_dir.display()); 23 fs::write(config_path, content).expect("Failed to write test config file"); 24 CacheConfig::from_file(Some(config_path)).unwrap() 25 }}; 26 } 27 28 macro_rules! bad_config { 29 ($config_path:ident, $content_fmt:expr, $cache_dir:ident) => {{ 30 let config_path = &$config_path; 31 let content = format!($content_fmt, cache_dir = $cache_dir.display()); 32 fs::write(config_path, content).expect("Failed to write test config file"); 33 assert!(CacheConfig::from_file(Some(config_path)).is_err()); 34 }}; 35 } 36 37 // test without macros to test being disabled 38 #[test] 39 fn test_disabled() { 40 let dir = tempfile::tempdir().expect("Can't create temporary directory"); 41 let config_path = dir.path().join("cache-config.toml"); 42 let config_content = "[cache]\n\ 43 enabled = false\n"; 44 fs::write(&config_path, config_content).expect("Failed to write test config file"); 45 let conf = CacheConfig::from_file(Some(&config_path)).unwrap(); 46 assert!(!conf.enabled()); 47 } 48 49 #[test] 50 fn test_unrecognized_settings() { 51 let (_td, cd, cp) = test_prolog(); 52 bad_config!( 53 cp, 54 "unrecognized-setting = 42\n\ 55 [cache]\n\ 56 enabled = true\n\ 57 directory = '{cache_dir}'", 58 cd 59 ); 60 61 bad_config!( 62 cp, 63 "[cache]\n\ 64 enabled = true\n\ 65 directory = '{cache_dir}'\n\ 66 unrecognized-setting = 42", 67 cd 68 ); 69 } 70 71 #[test] 72 fn test_all_settings() { 73 let (_td, cd, cp) = test_prolog(); 74 let conf = load_config!( 75 cp, 76 "[cache]\n\ 77 enabled = true\n\ 78 directory = '{cache_dir}'\n\ 79 worker-event-queue-size = '16'\n\ 80 baseline-compression-level = 3\n\ 81 optimized-compression-level = 20\n\ 82 optimized-compression-usage-counter-threshold = '256'\n\ 83 cleanup-interval = '1h'\n\ 84 optimizing-compression-task-timeout = '30m'\n\ 85 allowed-clock-drift-for-files-from-future = '1d'\n\ 86 file-count-soft-limit = '65536'\n\ 87 files-total-size-soft-limit = '512Mi'\n\ 88 file-count-limit-percent-if-deleting = '70%'\n\ 89 files-total-size-limit-percent-if-deleting = '70%'", 90 cd 91 ); 92 check_conf(&conf, &cd); 93 94 let conf = load_config!( 95 cp, 96 // added some white spaces 97 "[cache]\n\ 98 enabled = true\n\ 99 directory = '{cache_dir}'\n\ 100 worker-event-queue-size = ' 16\t'\n\ 101 baseline-compression-level = 3\n\ 102 optimized-compression-level =\t 20\n\ 103 optimized-compression-usage-counter-threshold = '256'\n\ 104 cleanup-interval = ' 1h'\n\ 105 optimizing-compression-task-timeout = '30 m'\n\ 106 allowed-clock-drift-for-files-from-future = '1\td'\n\ 107 file-count-soft-limit = '\t \t65536\t'\n\ 108 files-total-size-soft-limit = '512\t\t Mi '\n\ 109 file-count-limit-percent-if-deleting = '70\t%'\n\ 110 files-total-size-limit-percent-if-deleting = ' 70 %'", 111 cd 112 ); 113 check_conf(&conf, &cd); 114 115 fn check_conf(conf: &CacheConfig, cd: &PathBuf) { 116 assert!(conf.enabled()); 117 assert_eq!( 118 conf.directory(), 119 &fs::canonicalize(cd).expect("canonicalize failed") 120 ); 121 assert_eq!(conf.worker_event_queue_size(), 0x10); 122 assert_eq!(conf.baseline_compression_level(), 3); 123 assert_eq!(conf.optimized_compression_level(), 20); 124 assert_eq!(conf.optimized_compression_usage_counter_threshold(), 0x100); 125 assert_eq!(conf.cleanup_interval(), Duration::from_secs(60 * 60)); 126 assert_eq!( 127 conf.optimizing_compression_task_timeout(), 128 Duration::from_secs(30 * 60) 129 ); 130 assert_eq!( 131 conf.allowed_clock_drift_for_files_from_future(), 132 Duration::from_secs(60 * 60 * 24) 133 ); 134 assert_eq!(conf.file_count_soft_limit(), 0x10_000); 135 assert_eq!(conf.files_total_size_soft_limit(), 512 * (1u64 << 20)); 136 assert_eq!(conf.file_count_limit_percent_if_deleting(), 70); 137 assert_eq!(conf.files_total_size_limit_percent_if_deleting(), 70); 138 } 139 } 140 141 #[test] 142 fn test_compression_level_settings() { 143 let (_td, cd, cp) = test_prolog(); 144 let conf = load_config!( 145 cp, 146 "[cache]\n\ 147 enabled = true\n\ 148 directory = '{cache_dir}'\n\ 149 baseline-compression-level = 1\n\ 150 optimized-compression-level = 21", 151 cd 152 ); 153 assert!(conf.enabled()); 154 assert_eq!(conf.baseline_compression_level(), 1); 155 assert_eq!(conf.optimized_compression_level(), 21); 156 157 bad_config!( 158 cp, 159 "[cache]\n\ 160 enabled = true\n\ 161 directory = '{cache_dir}'\n\ 162 baseline-compression-level = -1\n\ 163 optimized-compression-level = 21", 164 cd 165 ); 166 167 bad_config!( 168 cp, 169 "[cache]\n\ 170 enabled = true\n\ 171 directory = '{cache_dir}'\n\ 172 baseline-compression-level = 15\n\ 173 optimized-compression-level = 10", 174 cd 175 ); 176 } 177 178 #[test] 179 fn test_si_prefix_settings() { 180 let (_td, cd, cp) = test_prolog(); 181 let conf = load_config!( 182 cp, 183 "[cache]\n\ 184 enabled = true\n\ 185 directory = '{cache_dir}'\n\ 186 worker-event-queue-size = '42'\n\ 187 optimized-compression-usage-counter-threshold = '4K'\n\ 188 file-count-soft-limit = '3M'", 189 cd 190 ); 191 assert!(conf.enabled()); 192 assert_eq!(conf.worker_event_queue_size(), 42); 193 assert_eq!(conf.optimized_compression_usage_counter_threshold(), 4_000); 194 assert_eq!(conf.file_count_soft_limit(), 3_000_000); 195 196 let conf = load_config!( 197 cp, 198 "[cache]\n\ 199 enabled = true\n\ 200 directory = '{cache_dir}'\n\ 201 worker-event-queue-size = '2K'\n\ 202 optimized-compression-usage-counter-threshold = '4444T'\n\ 203 file-count-soft-limit = '1P'", 204 cd 205 ); 206 assert!(conf.enabled()); 207 assert_eq!(conf.worker_event_queue_size(), 2_000); 208 assert_eq!( 209 conf.optimized_compression_usage_counter_threshold(), 210 4_444_000_000_000_000 211 ); 212 assert_eq!(conf.file_count_soft_limit(), 1_000_000_000_000_000); 213 214 // different errors 215 bad_config!( 216 cp, 217 "[cache]\n\ 218 enabled = true\n\ 219 directory = '{cache_dir}'\n\ 220 worker-event-queue-size = '2g'", 221 cd 222 ); 223 224 bad_config!( 225 cp, 226 "[cache]\n\ 227 enabled = true\n\ 228 directory = '{cache_dir}'\n\ 229 file-count-soft-limit = 1", 230 cd 231 ); 232 233 bad_config!( 234 cp, 235 "[cache]\n\ 236 enabled = true\n\ 237 directory = '{cache_dir}'\n\ 238 file-count-soft-limit = '-31337'", 239 cd 240 ); 241 242 bad_config!( 243 cp, 244 "[cache]\n\ 245 enabled = true\n\ 246 directory = '{cache_dir}'\n\ 247 file-count-soft-limit = '3.14M'", 248 cd 249 ); 250 } 251 252 #[test] 253 fn test_disk_space_settings() { 254 let (_td, cd, cp) = test_prolog(); 255 let conf = load_config!( 256 cp, 257 "[cache]\n\ 258 enabled = true\n\ 259 directory = '{cache_dir}'\n\ 260 files-total-size-soft-limit = '76'", 261 cd 262 ); 263 assert!(conf.enabled()); 264 assert_eq!(conf.files_total_size_soft_limit(), 76); 265 266 let conf = load_config!( 267 cp, 268 "[cache]\n\ 269 enabled = true\n\ 270 directory = '{cache_dir}'\n\ 271 files-total-size-soft-limit = '42 Mi'", 272 cd 273 ); 274 assert!(conf.enabled()); 275 assert_eq!(conf.files_total_size_soft_limit(), 42 * (1u64 << 20)); 276 277 let conf = load_config!( 278 cp, 279 "[cache]\n\ 280 enabled = true\n\ 281 directory = '{cache_dir}'\n\ 282 files-total-size-soft-limit = '2 Gi'", 283 cd 284 ); 285 assert!(conf.enabled()); 286 assert_eq!(conf.files_total_size_soft_limit(), 2 * (1u64 << 30)); 287 288 let conf = load_config!( 289 cp, 290 "[cache]\n\ 291 enabled = true\n\ 292 directory = '{cache_dir}'\n\ 293 files-total-size-soft-limit = '31337 Ti'", 294 cd 295 ); 296 assert!(conf.enabled()); 297 assert_eq!(conf.files_total_size_soft_limit(), 31337 * (1u64 << 40)); 298 299 let conf = load_config!( 300 cp, 301 "[cache]\n\ 302 enabled = true\n\ 303 directory = '{cache_dir}'\n\ 304 files-total-size-soft-limit = '7 Pi'", 305 cd 306 ); 307 assert!(conf.enabled()); 308 assert_eq!(conf.files_total_size_soft_limit(), 7 * (1u64 << 50)); 309 310 let conf = load_config!( 311 cp, 312 "[cache]\n\ 313 enabled = true\n\ 314 directory = '{cache_dir}'\n\ 315 files-total-size-soft-limit = '7M'", 316 cd 317 ); 318 assert!(conf.enabled()); 319 assert_eq!(conf.files_total_size_soft_limit(), 7_000_000); 320 321 // different errors 322 bad_config!( 323 cp, 324 "[cache]\n\ 325 enabled = true\n\ 326 directory = '{cache_dir}'\n\ 327 files-total-size-soft-limit = '7 mi'", 328 cd 329 ); 330 331 bad_config!( 332 cp, 333 "[cache]\n\ 334 enabled = true\n\ 335 directory = '{cache_dir}'\n\ 336 files-total-size-soft-limit = 1", 337 cd 338 ); 339 340 bad_config!( 341 cp, 342 "[cache]\n\ 343 enabled = true\n\ 344 directory = '{cache_dir}'\n\ 345 files-total-size-soft-limit = '-31337'", 346 cd 347 ); 348 349 bad_config!( 350 cp, 351 "[cache]\n\ 352 enabled = true\n\ 353 directory = '{cache_dir}'\n\ 354 files-total-size-soft-limit = '3.14Ki'", 355 cd 356 ); 357 } 358 359 #[test] 360 fn test_duration_settings() { 361 let (_td, cd, cp) = test_prolog(); 362 let conf = load_config!( 363 cp, 364 "[cache]\n\ 365 enabled = true\n\ 366 directory = '{cache_dir}'\n\ 367 cleanup-interval = '100s'\n\ 368 optimizing-compression-task-timeout = '3m'\n\ 369 allowed-clock-drift-for-files-from-future = '4h'", 370 cd 371 ); 372 assert!(conf.enabled()); 373 assert_eq!(conf.cleanup_interval(), Duration::from_secs(100)); 374 assert_eq!( 375 conf.optimizing_compression_task_timeout(), 376 Duration::from_secs(3 * 60) 377 ); 378 assert_eq!( 379 conf.allowed_clock_drift_for_files_from_future(), 380 Duration::from_secs(4 * 60 * 60) 381 ); 382 383 let conf = load_config!( 384 cp, 385 "[cache]\n\ 386 enabled = true\n\ 387 directory = '{cache_dir}'\n\ 388 cleanup-interval = '2d'\n\ 389 optimizing-compression-task-timeout = '333 m'", 390 cd 391 ); 392 assert!(conf.enabled()); 393 assert_eq!( 394 conf.cleanup_interval(), 395 Duration::from_secs(2 * 24 * 60 * 60) 396 ); 397 assert_eq!( 398 conf.optimizing_compression_task_timeout(), 399 Duration::from_secs(333 * 60) 400 ); 401 402 // different errors 403 bad_config!( 404 cp, 405 "[cache]\n\ 406 enabled = true\n\ 407 directory = '{cache_dir}'\n\ 408 optimizing-compression-task-timeout = '333'", 409 cd 410 ); 411 412 bad_config!( 413 cp, 414 "[cache]\n\ 415 enabled = true\n\ 416 directory = '{cache_dir}'\n\ 417 optimizing-compression-task-timeout = 333", 418 cd 419 ); 420 421 bad_config!( 422 cp, 423 "[cache]\n\ 424 enabled = true\n\ 425 directory = '{cache_dir}'\n\ 426 optimizing-compression-task-timeout = '10 M'", 427 cd 428 ); 429 430 bad_config!( 431 cp, 432 "[cache]\n\ 433 enabled = true\n\ 434 directory = '{cache_dir}'\n\ 435 optimizing-compression-task-timeout = '10 min'", 436 cd 437 ); 438 439 bad_config!( 440 cp, 441 "[cache]\n\ 442 enabled = true\n\ 443 directory = '{cache_dir}'\n\ 444 optimizing-compression-task-timeout = '-10s'", 445 cd 446 ); 447 448 bad_config!( 449 cp, 450 "[cache]\n\ 451 enabled = true\n\ 452 directory = '{cache_dir}'\n\ 453 optimizing-compression-task-timeout = '1.5m'", 454 cd 455 ); 456 } 457 458 #[test] 459 fn test_percent_settings() { 460 let (_td, cd, cp) = test_prolog(); 461 let conf = load_config!( 462 cp, 463 "[cache]\n\ 464 enabled = true\n\ 465 directory = '{cache_dir}'\n\ 466 file-count-limit-percent-if-deleting = '62%'\n\ 467 files-total-size-limit-percent-if-deleting = '23 %'", 468 cd 469 ); 470 assert!(conf.enabled()); 471 assert_eq!(conf.file_count_limit_percent_if_deleting(), 62); 472 assert_eq!(conf.files_total_size_limit_percent_if_deleting(), 23); 473 474 // different errors 475 bad_config!( 476 cp, 477 "[cache]\n\ 478 enabled = true\n\ 479 directory = '{cache_dir}'\n\ 480 files-total-size-limit-percent-if-deleting = '23'", 481 cd 482 ); 483 484 bad_config!( 485 cp, 486 "[cache]\n\ 487 enabled = true\n\ 488 directory = '{cache_dir}'\n\ 489 files-total-size-limit-percent-if-deleting = '22.5%'", 490 cd 491 ); 492 493 bad_config!( 494 cp, 495 "[cache]\n\ 496 enabled = true\n\ 497 directory = '{cache_dir}'\n\ 498 files-total-size-limit-percent-if-deleting = '0.5'", 499 cd 500 ); 501 502 bad_config!( 503 cp, 504 "[cache]\n\ 505 enabled = true\n\ 506 directory = '{cache_dir}'\n\ 507 files-total-size-limit-percent-if-deleting = '-1%'", 508 cd 509 ); 510 511 bad_config!( 512 cp, 513 "[cache]\n\ 514 enabled = true\n\ 515 directory = '{cache_dir}'\n\ 516 files-total-size-limit-percent-if-deleting = '101%'", 517 cd 518 ); 519 } 520