use std::{fs, path::Path}; use shared_constants::bucket::FILE_BUCKET_BIND; use shared_functions::rola_test_sandbox; use space_system::Space; use crate::{ Bucket, NoProtocol, bind::{ BucketBind, check_bucket_bind_exists, read_bucket_bind, read_bucket_binds, remove_bucket_bind, write_bucket_bind, }, }; fn init_bucket(path: &Path) -> Space> { let bucket = Bucket::::new_local(); let mut space = Space::new(bucket); space.set_current_dir(&path).unwrap(); space.init(path).unwrap(); space } #[test] fn test_read_bucket_binds() { let sandbox = rola_test_sandbox("bucket_bind_read"); let b = init_bucket(&sandbox.path); let bind_1 = sandbox.join(FILE_BUCKET_BIND("1")); let bind_2 = sandbox.join(FILE_BUCKET_BIND("2")); let bind_3 = sandbox.join(FILE_BUCKET_BIND("3")); let bind_fail = sandbox.join(FILE_BUCKET_BIND("@")); let other = sandbox.join("ot"); fs::write(bind_1, "./bucket1").unwrap(); fs::write(bind_2, "\n./bucket2").unwrap(); fs::write(bind_3, "./bucket3\nbbb").unwrap(); fs::write(bind_fail, "omg").unwrap(); fs::write(other, "ok").unwrap(); let result = read_bucket_binds(&b).unwrap(); assert!(result.contains(&BucketBind::new(1, "./bucket1"))); assert!(result.contains(&BucketBind::new(2, "./bucket2"))); assert!(result.contains(&BucketBind::new(3, "./bucket3\nbbb"))); assert_eq!(result.len(), 3); } #[test] fn test_write_and_read_bucket_bind() { let sandbox = rola_test_sandbox("bucket_bind_write_read"); let space = init_bucket(&sandbox.path); // Write bucket bind records write_bucket_bind(&space, 1, "./bucket1").unwrap(); write_bucket_bind(&space, 2, "./bucket2").unwrap(); write_bucket_bind(&space, 3, "./bucket3\nbbb").unwrap(); // Verify reads return the correct values let bind1 = read_bucket_bind(&space, 1).unwrap().unwrap(); assert_eq!(bind1, BucketBind::new(1, "./bucket1")); let bind2 = read_bucket_bind(&space, 2).unwrap().unwrap(); assert_eq!(bind2, BucketBind::new(2, "./bucket2")); let bind3 = read_bucket_bind(&space, 3).unwrap().unwrap(); assert_eq!(bind3, BucketBind::new(3, "./bucket3\nbbb")); // Read a non-existent bind should return None let bind4 = read_bucket_bind(&space, 4).unwrap(); assert!(bind4.is_none()); } #[test] fn test_write_bucket_bind_trims_whitespace() { let sandbox = rola_test_sandbox("bucket_bind_trim"); let space = init_bucket(&sandbox.path); // Write URL with surrounding whitespace write_bucket_bind(&space, 1, " ./bucket1 ").unwrap(); // Verify it was trimmed on write let bind = read_bucket_bind(&space, 1).unwrap().unwrap(); assert_eq!(bind, BucketBind::new(1, "./bucket1")); } #[test] fn test_write_bucket_bind_overwrites_existing() { let sandbox = rola_test_sandbox("bucket_bind_overwrite"); let space = init_bucket(&sandbox.path); write_bucket_bind(&space, 1, "./bucket_v1").unwrap(); write_bucket_bind(&space, 1, "./bucket_v2").unwrap(); let bind = read_bucket_bind(&space, 1).unwrap().unwrap(); assert_eq!(bind, BucketBind::new(1, "./bucket_v2")); } #[test] fn test_check_bucket_bind_exists() { let sandbox = rola_test_sandbox("bucket_bind_check_exists"); let space = init_bucket(&sandbox.path); // Initially, no bucket bind should exist let exists = check_bucket_bind_exists(&space, 1).unwrap(); assert!(!exists); // Write a bucket bind and verify it exists write_bucket_bind(&space, 1, "./bucket1").unwrap(); let exists = check_bucket_bind_exists(&space, 1).unwrap(); assert!(exists); // A different index should still not exist let exists = check_bucket_bind_exists(&space, 2).unwrap(); assert!(!exists); // Write another bind and check write_bucket_bind(&space, 2, "./bucket2").unwrap(); let exists = check_bucket_bind_exists(&space, 2).unwrap(); assert!(exists); } #[test] fn test_check_bucket_bind_exists_after_delete() { let sandbox = rola_test_sandbox("bucket_bind_check_exists_after_delete"); let space = init_bucket(&sandbox.path); write_bucket_bind(&space, 1, "./bucket1").unwrap(); assert!(check_bucket_bind_exists(&space, 1).unwrap()); // Delete by removing the file directly let bind_path = sandbox.path.join(format!( "{}{:03}", shared_constants::bucket::PREFIX_BUCKET_BIND, 1 )); std::fs::remove_file(bind_path).unwrap(); let exists = check_bucket_bind_exists(&space, 1).unwrap(); assert!(!exists); } #[test] fn test_remove_bucket_bind() { let sandbox = rola_test_sandbox("bucket_bind_remove"); let space = init_bucket(&sandbox.path); // Write a bucket bind write_bucket_bind(&space, 1, "./bucket1").unwrap(); assert!(check_bucket_bind_exists(&space, 1).unwrap()); // Remove it remove_bucket_bind(&space, 1).unwrap(); assert!(!check_bucket_bind_exists(&space, 1).unwrap()); } #[test] fn test_remove_bucket_bind_nonexistent() { let sandbox = rola_test_sandbox("bucket_bind_remove_nonexistent"); let space = init_bucket(&sandbox.path); // Removing a non-existent bind should return an error let result = remove_bucket_bind(&space, 99); assert!(result.is_err()); } #[test] fn test_remove_bucket_bind_does_not_affect_others() { let sandbox = rola_test_sandbox("bucket_bind_remove_others"); let space = init_bucket(&sandbox.path); // Write multiple bucket binds write_bucket_bind(&space, 1, "./bucket1").unwrap(); write_bucket_bind(&space, 2, "./bucket2").unwrap(); write_bucket_bind(&space, 3, "./bucket3").unwrap(); // Remove bind 2 remove_bucket_bind(&space, 2).unwrap(); // Bind 1 and 3 should still exist assert!(check_bucket_bind_exists(&space, 1).unwrap()); assert!(!check_bucket_bind_exists(&space, 2).unwrap()); assert!(check_bucket_bind_exists(&space, 3).unwrap()); // Values should be preserved for remaining binds assert_eq!( read_bucket_bind(&space, 1).unwrap().unwrap(), BucketBind::new(1, "./bucket1") ); assert_eq!( read_bucket_bind(&space, 3).unwrap().unwrap(), BucketBind::new(3, "./bucket3") ); } #[test] fn test_remove_bucket_bind_then_read_returns_none() { let sandbox = rola_test_sandbox("bucket_bind_remove_then_read"); let space = init_bucket(&sandbox.path); write_bucket_bind(&space, 1, "./bucket1").unwrap(); remove_bucket_bind(&space, 1).unwrap(); let bind = read_bucket_bind(&space, 1).unwrap(); assert!(bind.is_none()); } #[test] fn test_remove_bucket_bind_then_write_again() { let sandbox = rola_test_sandbox("bucket_bind_remove_then_write"); let space = init_bucket(&sandbox.path); write_bucket_bind(&space, 1, "./bucket_v1").unwrap(); remove_bucket_bind(&space, 1).unwrap(); // Write the same index again write_bucket_bind(&space, 1, "./bucket_v2").unwrap(); let bind = read_bucket_bind(&space, 1).unwrap().unwrap(); assert_eq!(bind, BucketBind::new(1, "./bucket_v2")); }