use std::fs;
use std::io::Write;
use std::path::PathBuf;
use tempfile::TempDir;
fn fixture_path(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join(name)
}
fn create_temp_json_file(content: &str) -> (TempDir, PathBuf) {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("test.json");
let mut file = fs::File::create(&file_path).unwrap();
file.write_all(content.as_bytes()).unwrap();
(temp_dir, file_path)
}
#[test]
fn test_complete_loading_flow() {
let json_content = r#"{"name": "Alice", "age": 30, "city": "Seattle"}"#;
let (_temp_dir, file_path) = create_temp_json_file(json_content);
assert!(file_path.exists(), "Test file should exist");
let content = fs::read_to_string(&file_path).unwrap();
assert_eq!(content, json_content, "File content should match");
}
#[test]
fn test_missing_file_error() {
use jiq::input::loader::FileLoader;
use std::thread;
use std::time::Duration;
let nonexistent_path = PathBuf::from("/nonexistent/path/to/file.json");
let mut loader = FileLoader::spawn_load(nonexistent_path);
let mut result = None;
for _ in 0..100 {
if let Some(r) = loader.poll() {
result = Some(r);
break;
}
thread::sleep(Duration::from_millis(10));
}
assert!(result.is_some(), "Loader should complete");
let result = result.unwrap();
assert!(result.is_err(), "Should return error for missing file");
let err = result.unwrap_err();
match err {
jiq::error::JiqError::Io(io_err_msg) => {
assert!(
io_err_msg.to_lowercase().contains("no such file")
|| io_err_msg.to_lowercase().contains("not found"),
"Error message should indicate file not found, got: {}",
io_err_msg
);
}
other => panic!("Expected JiqError::Io, got {:?}", other),
}
}
#[test]
fn test_invalid_json_error() {
use jiq::input::loader::FileLoader;
use std::thread;
use std::time::Duration;
let invalid_json = r#"{"name": "test", invalid syntax here}"#;
let (_temp_dir, file_path) = create_temp_json_file(invalid_json);
let mut loader = FileLoader::spawn_load(file_path);
let mut result = None;
for _ in 0..100 {
if let Some(r) = loader.poll() {
result = Some(r);
break;
}
thread::sleep(Duration::from_millis(10));
}
assert!(result.is_some(), "Loader should complete");
let result = result.unwrap();
assert!(result.is_err(), "Should return error for invalid JSON");
let err = result.unwrap_err();
match err {
jiq::error::JiqError::InvalidJson(msg) => {
assert!(
!msg.is_empty(),
"Error message should contain parsing details"
);
assert!(
msg.contains("expected")
|| msg.contains("invalid")
|| msg.contains("error")
|| msg.contains("key must be")
|| msg.contains("line")
|| msg.contains("column"),
"Error message should describe the parsing error: {}",
msg
);
}
other => panic!("Expected JiqError::InvalidJson, got {:?}", other),
}
}
#[test]
#[cfg(unix)] fn test_permission_error() {
use jiq::input::loader::FileLoader;
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::thread;
use std::time::Duration;
let json_content = r#"{"name": "test"}"#;
let (_temp_dir, file_path) = create_temp_json_file(json_content);
let mut perms = fs::metadata(&file_path).unwrap().permissions();
perms.set_mode(0o000); fs::set_permissions(&file_path, perms).unwrap();
if fs::read_to_string(&file_path).is_ok() {
let mut perms = fs::metadata(&file_path).unwrap().permissions();
perms.set_mode(0o644);
let _ = fs::set_permissions(&file_path, perms);
eprintln!("Skipping test_permission_error: running with elevated privileges (root)");
return;
}
let mut loader = FileLoader::spawn_load(file_path.clone());
let mut result = None;
for _ in 0..100 {
if let Some(r) = loader.poll() {
result = Some(r);
break;
}
thread::sleep(Duration::from_millis(10));
}
let mut perms = fs::metadata(&file_path).unwrap().permissions();
perms.set_mode(0o644);
let _ = fs::set_permissions(&file_path, perms);
assert!(result.is_some(), "Loader should complete");
let result = result.unwrap();
assert!(result.is_err(), "Should return error for permission denied");
let err = result.unwrap_err();
match err {
jiq::error::JiqError::Io(io_err_msg) => {
assert!(
io_err_msg.to_lowercase().contains("permission denied")
|| io_err_msg.to_lowercase().contains("access denied"),
"Error message should indicate permission denied, got: {}",
io_err_msg
);
}
other => panic!(
"Expected JiqError::Io with PermissionDenied, got {:?}",
other
),
}
}
#[test]
fn test_deferred_loading_with_fixtures() {
use jiq::input::loader::FileLoader;
use std::thread;
use std::time::Duration;
let simple_path = fixture_path("simple.json");
assert!(simple_path.exists(), "simple.json fixture should exist");
let mut loader = FileLoader::spawn_load(simple_path);
let mut result = None;
for _ in 0..100 {
if let Some(r) = loader.poll() {
result = Some(r);
break;
}
thread::sleep(Duration::from_millis(10));
}
assert!(result.is_some(), "Loader should complete");
let result = result.unwrap();
assert!(result.is_ok(), "Loading simple.json should succeed");
let json_content = result.unwrap();
assert!(
json_content.contains("Alice"),
"Loaded content should contain expected data"
);
}