#![allow(
clippy::unwrap_used,
clippy::panic,
clippy::too_many_lines,
clippy::doc_markdown
)]
mod helpers;
use cobre_core::EntityId;
use cobre_io::{deserialize_system, load_case, serialize_system};
use tempfile::TempDir;
#[test]
fn test_minimal_valid_case() {
let dir = TempDir::new().unwrap();
helpers::make_minimal_case(&dir);
let result = load_case(dir.path());
let system = match result {
Ok(s) => s,
Err(e) => panic!("expected Ok(System) for minimal case, got Err: {e}"),
};
assert_eq!(
system.n_buses(),
1,
"minimal case should have exactly 1 bus"
);
assert_eq!(system.n_hydros(), 0, "minimal case should have 0 hydros");
assert_eq!(
system.n_thermals(),
0,
"minimal case should have 0 thermals"
);
assert_eq!(system.n_lines(), 0, "minimal case should have 0 lines");
assert_eq!(
system.n_stages(),
1,
"minimal case should have exactly 1 stage"
);
assert!(
system.bus(EntityId(1)).is_some(),
"bus with id=1 should be found by O(1) lookup"
);
}
#[test]
fn test_multi_entity_case() {
let dir = TempDir::new().unwrap();
helpers::make_multi_entity_case(&dir);
let result = load_case(dir.path());
let system = match result {
Ok(s) => s,
Err(e) => panic!("expected Ok(System) for multi-entity case, got Err: {e}"),
};
assert_eq!(
system.n_buses(),
2,
"multi-entity case should have exactly 2 buses"
);
assert_eq!(
system.n_hydros(),
1,
"multi-entity case should have exactly 1 hydro"
);
assert_eq!(
system.n_thermals(),
1,
"multi-entity case should have exactly 1 thermal"
);
assert_eq!(
system.n_lines(),
1,
"multi-entity case should have exactly 1 line"
);
assert_eq!(
system.n_stages(),
2,
"multi-entity case should have exactly 2 stages"
);
assert!(
system.bus(EntityId(1)).is_some(),
"bus with id=1 should be accessible via O(1) lookup"
);
assert!(
system.bus(EntityId(2)).is_some(),
"bus with id=2 should be accessible via O(1) lookup"
);
}
#[test]
fn test_missing_required_file() {
let dir = TempDir::new().unwrap();
helpers::make_minimal_case(&dir);
std::fs::remove_file(dir.path().join("system/buses.json")).unwrap();
let result = load_case(dir.path());
match result {
Err(err) => {
let display = err.to_string();
assert!(
display.contains("buses"),
"error display should mention 'buses', got: {display}"
);
}
Ok(_) => panic!("expected Err when buses.json is missing, got Ok"),
}
}
#[test]
fn test_malformed_json() {
let dir = TempDir::new().unwrap();
helpers::make_minimal_case(&dir);
helpers::write_file(
dir.path(),
"system/hydros.json",
"{ this is not valid json }",
);
let result = load_case(dir.path());
match result {
Err(err) => {
let display = err.to_string();
assert!(
!display.is_empty(),
"error display should be non-empty for malformed JSON"
);
}
Ok(_) => panic!("expected Err for malformed hydros.json, got Ok"),
}
}
#[test]
fn test_referential_integrity_violation() {
let dir = TempDir::new().unwrap();
helpers::make_referential_violation_case(&dir);
let result = load_case(dir.path());
match result {
Err(err) => {
let display = err.to_string();
assert!(
display.contains("999") || display.contains("bus") || display.contains("Bus"),
"error display should mention the invalid bus reference (999), got: {display}"
);
}
Ok(_) => panic!("expected Err when hydro references non-existent bus_id=999, got Ok"),
}
}
#[test]
fn test_postcard_round_trip() {
let dir = TempDir::new().unwrap();
helpers::make_minimal_case(&dir);
let original = load_case(dir.path())
.unwrap_or_else(|e| panic!("load_case should succeed for minimal case, got: {e}"));
let bytes = serialize_system(&original)
.unwrap_or_else(|e| panic!("serialize_system should succeed, got: {e}"));
assert!(!bytes.is_empty(), "serialized bytes should be non-empty");
let deserialized = deserialize_system(&bytes)
.unwrap_or_else(|e| panic!("deserialize_system should succeed, got: {e}"));
assert_eq!(
deserialized.n_buses(),
original.n_buses(),
"bus count must match after postcard round-trip"
);
assert!(
deserialized.bus(EntityId(1)).is_some(),
"O(1) bus lookup must work after index rebuild on deserialized System"
);
assert_eq!(
deserialized.n_hydros(),
original.n_hydros(),
"hydro count must match after round-trip"
);
assert_eq!(
deserialized.n_thermals(),
original.n_thermals(),
"thermal count must match after round-trip"
);
assert_eq!(
deserialized.n_lines(),
original.n_lines(),
"line count must match after round-trip"
);
assert_eq!(
deserialized.n_stages(),
original.n_stages(),
"stage count must match after round-trip"
);
}