use sal_virt::rfs::{MountType, RfsBuilder, RfsError, StoreSpec}; /// Tests RFS builder creation and property validation /// /// This test verifies that: /// - Builders are created with correct initial state /// - Properties are accessible and correct /// - Initial state is properly set /// /// No external dependencies required - tests pure Rust logic #[test] fn test_rfs_builder_creation_and_properties() { let builder = RfsBuilder::new("/source/path", "/target/path", MountType::Local); // Validate builder properties are correctly set assert_eq!(builder.source(), "/source/path"); assert_eq!(builder.target(), "/target/path"); assert!(matches!(builder.mount_type(), MountType::Local)); assert!(builder.options().is_empty()); assert!(!builder.debug()); } /// Tests mount type behavior and string conversion /// /// This test verifies that: /// - Each mount type is properly stored and accessible /// - Mount types convert to correct string representations /// - Custom mount types preserve their values /// - Builders correctly store mount type information #[test] fn test_mount_type_behavior_and_serialization() { // Test each mount type's specific behavior let test_cases = vec![ (MountType::Local, "local", "/local/source", "/local/target"), ( MountType::SSH, "ssh", "user@host:/remote/path", "/ssh/target", ), (MountType::S3, "s3", "s3://bucket/key", "/s3/target"), ( MountType::WebDAV, "webdav", "https://webdav.example.com/path", "/webdav/target", ), ( MountType::Custom("fuse".to_string()), "fuse", "fuse://source", "/fuse/target", ), ]; for (mount_type, expected_str, source, target) in test_cases { // Test string representation assert_eq!(mount_type.to_string(), expected_str); // Test that mount type affects builder behavior correctly let builder = RfsBuilder::new(source, target, mount_type.clone()); assert_eq!(builder.source(), source); assert_eq!(builder.target(), target); // Verify mount type is stored correctly match (&mount_type, builder.mount_type()) { (MountType::Local, MountType::Local) => {} (MountType::SSH, MountType::SSH) => {} (MountType::S3, MountType::S3) => {} (MountType::WebDAV, MountType::WebDAV) => {} (MountType::Custom(expected), MountType::Custom(actual)) => { assert_eq!(expected, actual); } _ => assert!( false, "Mount type mismatch: expected {:?}, got {:?}", mount_type, builder.mount_type() ), } } } /// Tests RFS builder option handling and method chaining /// /// This test verifies that: /// - Options are properly stored and accessible /// - Method chaining works correctly /// - Multiple options can be added /// - Option values are preserved correctly #[test] fn test_rfs_builder_option_handling() { let builder = RfsBuilder::new("/source", "/target", MountType::Local) .with_option("read_only", "true") .with_option("uid", "1000") .with_option("gid", "1000"); // Verify options are stored correctly assert_eq!(builder.options().len(), 3); assert_eq!( builder.options().get("read_only"), Some(&"true".to_string()) ); assert_eq!(builder.options().get("uid"), Some(&"1000".to_string())); assert_eq!(builder.options().get("gid"), Some(&"1000".to_string())); // Verify other properties are preserved assert_eq!(builder.source(), "/source"); assert_eq!(builder.target(), "/target"); assert!(matches!(builder.mount_type(), MountType::Local)); } /// Tests StoreSpec creation and string serialization /// /// This test verifies that: /// - StoreSpec objects are created with correct type /// - Options are properly stored and accessible /// - String serialization works correctly /// - Method chaining preserves all data #[test] fn test_store_spec_creation_and_serialization() { // Test file store specification let file_spec = StoreSpec::new("file").with_option("path", "/path/to/store"); assert_eq!(file_spec.spec_type, "file"); assert_eq!(file_spec.options.len(), 1); assert_eq!( file_spec.options.get("path"), Some(&"/path/to/store".to_string()) ); assert_eq!(file_spec.to_string(), "file:path=/path/to/store"); // Test S3 store specification with multiple options let s3_spec = StoreSpec::new("s3") .with_option("bucket", "my-bucket") .with_option("region", "us-east-1"); assert_eq!(s3_spec.spec_type, "s3"); assert_eq!(s3_spec.options.len(), 2); assert_eq!( s3_spec.options.get("bucket"), Some(&"my-bucket".to_string()) ); assert_eq!( s3_spec.options.get("region"), Some(&"us-east-1".to_string()) ); // String representation should contain both options (order may vary) let s3_string = s3_spec.to_string(); assert!(s3_string.starts_with("s3:")); assert!(s3_string.contains("bucket=my-bucket")); assert!(s3_string.contains("region=us-east-1")); } #[test] fn test_rfs_error_types() { // Test that our error types work correctly let error = RfsError::CommandFailed("Test error".to_string()); assert!(matches!(error, RfsError::CommandFailed(_))); let error_msg = format!("{}", error); assert!(error_msg.contains("Test error")); } /// Tests MountType string conversion and round-trip behavior /// /// This test verifies that: /// - MountType to_string() produces correct values /// - MountType from_string() correctly parses values /// - Round-trip conversion preserves data /// - Debug formatting works without panicking #[test] fn test_mount_type_string_conversion() { // Test standard mount types let test_cases = vec![ (MountType::Local, "local"), (MountType::SSH, "ssh"), (MountType::S3, "s3"), (MountType::WebDAV, "webdav"), ]; for (mount_type, expected_string) in test_cases { // Test to_string conversion assert_eq!(mount_type.to_string(), expected_string); // Test round-trip conversion let parsed = MountType::from_string(expected_string); assert_eq!(format!("{:?}", mount_type), format!("{:?}", parsed)); // Test debug formatting doesn't panic let debug_str = format!("{:?}", mount_type); assert!(!debug_str.is_empty()); } // Test custom mount type let custom = MountType::Custom("myfs".to_string()); assert_eq!(custom.to_string(), "myfs"); let parsed_custom = MountType::from_string("myfs"); if let MountType::Custom(value) = parsed_custom { assert_eq!(value, "myfs"); } else { assert!(false, "Expected Custom mount type, got {:?}", parsed_custom); } } /// Tests PackBuilder creation and configuration /// /// This test verifies that: /// - PackBuilder is created with correct initial state /// - Store specifications are properly stored /// - Debug mode can be set and retrieved /// - Method chaining works correctly #[test] fn test_pack_builder_creation_and_configuration() { use sal_virt::rfs::PackBuilder; // Test creating a pack builder with store specs let specs = vec![ StoreSpec::new("file").with_option("path", "/tmp/store"), StoreSpec::new("s3").with_option("bucket", "test-bucket"), ]; let builder = PackBuilder::new("/source/dir", "/output/file") .with_store_specs(specs.clone()) .with_debug(true); // Verify builder properties assert_eq!(builder.directory(), "/source/dir"); assert_eq!(builder.output(), "/output/file"); assert_eq!(builder.store_specs().len(), 2); assert!(builder.debug()); // Verify store specs are correctly stored assert_eq!(builder.store_specs()[0].spec_type, "file"); assert_eq!(builder.store_specs()[1].spec_type, "s3"); assert_eq!( builder.store_specs()[0].options.get("path"), Some(&"/tmp/store".to_string()) ); assert_eq!( builder.store_specs()[1].options.get("bucket"), Some(&"test-bucket".to_string()) ); } #[test] fn test_rfs_functions_availability() { // Test that RFS functions are available (even if they fail due to missing RFS binary) use sal_virt::rfs::{list_mounts, unmount_all}; // These functions should exist and be callable // They will likely fail in test environment due to missing RFS binary, but that's expected let list_result = list_mounts(); let unmount_result = unmount_all(); // We expect these to fail in test environment, so we just check they're callable match list_result { Ok(_) => println!("RFS is available - list_mounts succeeded"), Err(RfsError::CommandFailed(_)) => { println!("RFS not available - expected in test environment") } Err(e) => println!("RFS error (expected): {:?}", e), } match unmount_result { Ok(_) => println!("RFS is available - unmount_all succeeded"), Err(RfsError::CommandFailed(_)) => { println!("RFS not available - expected in test environment") } Err(e) => println!("RFS error (expected): {:?}", e), } // Test passes if functions are callable and return proper Result types } #[test] fn test_pack_operations_availability() { // Test that pack operations are available use sal_virt::rfs::{list_contents, pack_directory, unpack, verify}; let specs = vec![StoreSpec::new("file").with_option("path", "/tmp/test")]; // These functions should exist and be callable let pack_result = pack_directory("/nonexistent", "/tmp/test.pack", &specs); let unpack_result = unpack("/tmp/test.pack", "/tmp/unpack"); let list_result = list_contents("/tmp/test.pack"); let verify_result = verify("/tmp/test.pack"); // We expect these to fail in test environment, so we just check they're callable match pack_result { Ok(_) => println!("RFS pack succeeded"), Err(_) => println!("RFS pack failed (expected in test environment)"), } match unpack_result { Ok(_) => println!("RFS unpack succeeded"), Err(_) => println!("RFS unpack failed (expected in test environment)"), } match list_result { Ok(_) => println!("RFS list_contents succeeded"), Err(_) => println!("RFS list_contents failed (expected in test environment)"), } match verify_result { Ok(_) => println!("RFS verify succeeded"), Err(_) => println!("RFS verify failed (expected in test environment)"), } // Test passes if all pack operations are callable and return proper Result types } /// Tests RFS builder debug mode and advanced chaining /// /// This test verifies that: /// - Debug mode can be set and retrieved /// - Builder chaining preserves all properties /// - Multiple options can be added in sequence /// - Builder state is immutable (each call returns new instance) #[test] fn test_rfs_builder_debug_and_chaining() { let base_builder = RfsBuilder::new("/src", "/dst", MountType::SSH); // Test debug mode let debug_builder = base_builder.clone().with_debug(true); assert!(debug_builder.debug()); assert!(!base_builder.debug()); // Original should be unchanged // Test complex chaining let complex_builder = base_builder .with_option("port", "2222") .with_option("user", "testuser") .with_debug(true) .with_option("timeout", "30"); // Verify all properties are preserved assert_eq!(complex_builder.source(), "/src"); assert_eq!(complex_builder.target(), "/dst"); assert!(matches!(complex_builder.mount_type(), MountType::SSH)); assert!(complex_builder.debug()); assert_eq!(complex_builder.options().len(), 3); assert_eq!( complex_builder.options().get("port"), Some(&"2222".to_string()) ); assert_eq!( complex_builder.options().get("user"), Some(&"testuser".to_string()) ); assert_eq!( complex_builder.options().get("timeout"), Some(&"30".to_string()) ); }