use std::fs;
use std::io::Write;
use tempfile::NamedTempFile;
use rumoca::compiler::pipeline::{check_balance_only, clear_dae_cache};
use rumoca::compiler::{Compiler, parse_source};
use rumoca::ir::transform::flatten::clear_caches;
#[test]
fn test_dae_cache_invalidation() {
clear_caches();
clear_dae_cache();
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let initial_model = r#"
model TestModel
Real x(start = 0);
equation
der(x) = 1;
end TestModel;
"#;
temp_file
.write_all(initial_model.as_bytes())
.expect("Failed to write initial model");
temp_file.flush().expect("Failed to flush");
let path = temp_file.path().to_str().unwrap();
let def1 = parse_source(initial_model, path).expect("Failed to parse initial model");
let result1 = check_balance_only(&def1, Some("TestModel")).expect("First balance check failed");
assert!(result1.is_balanced(), "Initial model should be balanced");
assert_eq!(result1.num_states, 1, "Should have 1 state");
assert_eq!(result1.num_equations, 1, "Should have 1 equation");
let result2 =
check_balance_only(&def1, Some("TestModel")).expect("Second balance check failed");
assert_eq!(
result1.num_states, result2.num_states,
"Cached result should match"
);
let modified_model = r#"
model TestModel
Real x(start = 0);
Real y(start = 0);
equation
der(x) = 1;
der(y) = x;
end TestModel;
"#;
fs::write(temp_file.path(), modified_model).expect("Failed to write modified model");
clear_caches();
let def2 = parse_source(modified_model, path).expect("Failed to parse modified model");
let result3 = check_balance_only(&def2, Some("TestModel")).expect("Third balance check failed");
assert!(result3.is_balanced(), "Modified model should be balanced");
assert_eq!(
result3.num_states, 2,
"Modified model should have 2 states, got {}",
result3.num_states
);
assert_eq!(
result3.num_equations, 2,
"Modified model should have 2 equations"
);
assert_ne!(
result1.num_states, result3.num_states,
"Cache should have been invalidated - states should differ"
);
}
#[test]
fn test_compiler_cache_invalidation() {
clear_caches();
clear_dae_cache();
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let initial_model = r#"
model CacheTest
parameter Real k = 1.0;
Real x(start = 0);
equation
der(x) = k;
end CacheTest;
"#;
temp_file
.write_all(initial_model.as_bytes())
.expect("Failed to write");
temp_file.flush().expect("Failed to flush");
let path = temp_file.path().to_str().unwrap();
let result1 = Compiler::new()
.model("CacheTest")
.compile_str(initial_model, path)
.expect("First compile failed");
assert!(result1.is_balanced());
assert_eq!(result1.balance.num_states, 1);
assert_eq!(result1.balance.num_parameters, 1);
let modified_model = r#"
model CacheTest
parameter Real k = 1.0;
parameter Real m = 2.0;
Real x(start = 0);
equation
der(x) = k * m;
end CacheTest;
"#;
fs::write(temp_file.path(), modified_model).expect("Failed to write modified");
clear_caches();
let result2 = Compiler::new()
.model("CacheTest")
.compile_str(modified_model, path)
.expect("Second compile failed");
assert!(result2.is_balanced());
assert_eq!(result2.balance.num_states, 1);
assert_eq!(
result2.balance.num_parameters, 2,
"Should have 2 parameters after modification"
);
}
#[test]
fn test_file_dependencies_validation() {
use rumoca::ir::transform::flatten::FileDependencies;
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
temp_file
.write_all(b"initial content")
.expect("Failed to write");
temp_file.flush().expect("Failed to flush");
let path = temp_file.path().to_str().unwrap();
clear_caches();
let mut deps = FileDependencies::new();
let content = fs::read(temp_file.path()).expect("Failed to read");
let hash = format!("{:x}", chksum_md5::hash(&content));
deps.record(path, &hash);
assert!(deps.is_valid(), "Dependencies should be valid initially");
fs::write(temp_file.path(), "modified content").expect("Failed to write modified");
clear_caches();
assert!(
!deps.is_valid(),
"Dependencies should be invalid after file modification"
);
}
#[test]
fn test_file_dependencies_missing_file() {
use rumoca::ir::transform::flatten::FileDependencies;
clear_caches();
let mut deps = FileDependencies::new();
deps.record("/nonexistent/path/to/file.mo", "somehash");
assert!(
!deps.is_valid(),
"Dependencies with missing file should be invalid"
);
}