mod utils; use nix_js::value::Value; use utils::eval_result; #[test] fn to_file_simple() { let result = eval_result(r#"builtins.toFile "hello.txt" "Hello, World!""#).expect("Failed to evaluate"); match result { Value::String(path) => { assert!(path.contains("-hello.txt")); assert!(std::path::Path::new(&path).exists()); let contents = std::fs::read_to_string(&path).expect("Failed to read file"); assert_eq!(contents, "Hello, World!"); } _ => panic!("Expected string, got {:?}", result), } } #[test] fn to_file_with_references() { let result = eval_result( r#" let dep = builtins.toFile "dep.txt" "dependency"; in builtins.toFile "main.txt" "Reference: ${dep}" "#, ) .expect("Failed to evaluate"); match result { Value::String(path) => { assert!(path.contains("-main.txt")); let contents = std::fs::read_to_string(&path).expect("Failed to read file"); assert!(contents.contains("Reference: ")); assert!(contents.contains("-dep.txt")); } _ => panic!("Expected string"), } } #[test] fn to_file_invalid_name_with_slash() { let result = eval_result(r#"builtins.toFile "foo/bar.txt" "content""#); assert!(result.is_err()); assert!( result .unwrap_err() .to_string() .contains("name cannot contain '/'") ); } #[test] fn to_file_invalid_name_dot() { let result = eval_result(r#"builtins.toFile "." "content""#); assert!(result.is_err()); assert!(result.unwrap_err().to_string().contains("invalid name")); } #[test] fn to_file_invalid_name_dotdot() { let result = eval_result(r#"builtins.toFile ".." "content""#); assert!(result.is_err()); assert!(result.unwrap_err().to_string().contains("invalid name")); } #[test] fn store_path_validation_not_in_store() { let result = eval_result(r#"builtins.storePath "/tmp/foo""#); assert!(result.is_err()); assert!( result .unwrap_err() .to_string() .contains("not in the Nix store") ); } #[test] fn store_path_validation_malformed_hash() { let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#) .expect("Failed to create dummy file"); let dummy_path = match dummy_file_result { Value::String(ref p) => p.clone(), _ => panic!("Expected string"), }; let store_dir = std::path::Path::new(&dummy_path) .parent() .expect("Failed to get parent dir") .to_str() .expect("Failed to convert to string"); let test_path = format!("{}/invalid-hash-hello", store_dir); let result = eval_result(&format!(r#"builtins.storePath "{}""#, test_path)); assert!(result.is_err()); let err_str = result.unwrap_err().to_string(); assert!( err_str.contains("invalid") || err_str.contains("hash"), "Expected hash validation error, got: {}", err_str ); } #[test] fn store_path_validation_missing_name() { let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#) .expect("Failed to create dummy file"); let dummy_path = match dummy_file_result { Value::String(ref p) => p.clone(), _ => panic!("Expected string"), }; let store_dir = std::path::Path::new(&dummy_path) .parent() .expect("Failed to get parent dir") .to_str() .expect("Failed to convert to string"); let test_path = format!("{}/abcd1234abcd1234abcd1234abcd1234", store_dir); let result = eval_result(&format!(r#"builtins.storePath "{}""#, test_path)); assert!(result.is_err()); let err_str = result.unwrap_err().to_string(); assert!( err_str.contains("missing name") || err_str.contains("format"), "Expected missing name error, got: {}", err_str ); } #[test] fn to_file_curried_application() { let result = eval_result( r#" let makeFile = builtins.toFile "test.txt"; in makeFile "test content" "#, ) .expect("Failed to evaluate"); match result { Value::String(path) => { assert!(path.contains("-test.txt")); let contents = std::fs::read_to_string(&path).expect("Failed to read file"); assert_eq!(contents, "test content"); } _ => panic!("Expected string"), } } #[test] fn to_file_number_conversion() { let result = eval_result(r#"builtins.toFile "number.txt" (builtins.toString 42)"#) .expect("Failed to evaluate"); match result { Value::String(path) => { let contents = std::fs::read_to_string(&path).expect("Failed to read file"); assert_eq!(contents, "42"); } _ => panic!("Expected string"), } } #[test] fn to_file_list_conversion() { let result = eval_result( r#"builtins.toFile "list.txt" (builtins.concatStringsSep "\n" ["line1" "line2" "line3"])"#, ) .expect("Failed to evaluate"); match result { Value::String(path) => { let contents = std::fs::read_to_string(&path).expect("Failed to read file"); assert_eq!(contents, "line1\nline2\nline3"); } _ => panic!("Expected string"), } }