//! Tests for configuration parsing. use entropyk_cli::config::{ComponentConfig, ScenarioConfig, SolverConfig}; use entropyk_cli::error::CliError; use std::path::PathBuf; use tempfile::tempdir; #[test] fn test_parse_minimal_config() { let json = r#"{ "fluid": "R134a" }"#; let config = ScenarioConfig::from_json(json).unwrap(); assert_eq!(config.fluid, "R134a"); assert!(config.circuits.is_empty()); assert_eq!(config.solver.strategy, "fallback"); } #[test] fn test_parse_full_config() { let json = r#" { "fluid": "R410A", "circuits": [{ "id": 0, "components": [ { "type": "Condenser", "name": "cond1", "ua": 5000.0 }, { "type": "Evaporator", "name": "evap1", "ua": 4000.0 } ], "edges": [ { "from": "cond1:outlet", "to": "evap1:inlet" } ] }], "solver": { "strategy": "newton", "max_iterations": 50, "tolerance": 1e-8 } }"#; let config = ScenarioConfig::from_json(json).unwrap(); assert_eq!(config.fluid, "R410A"); assert_eq!(config.circuits.len(), 1); assert_eq!(config.circuits[0].components.len(), 2); assert_eq!(config.solver.strategy, "newton"); assert_eq!(config.solver.max_iterations, 50); } #[test] fn test_validate_missing_fluid() { let json = r#"{ "fluid": "" }"#; let result = ScenarioConfig::from_json(json); assert!(result.is_err()); if let Err(CliError::Config(msg)) = result { assert!(msg.contains("fluid")); } } #[test] fn test_validate_empty_circuit() { let json = r#" { "fluid": "R134a", "circuits": [{ "id": 0, "components": [] }] }"#; let result = ScenarioConfig::from_json(json); assert!(result.is_err()); } #[test] fn test_validate_invalid_edge_format() { let json = r#" { "fluid": "R134a", "circuits": [{ "id": 0, "components": [{ "type": "Condenser", "name": "cond1", "ua": 5000.0 }], "edges": [{ "from": "invalid", "to": "also_invalid" }] }] }"#; let result = ScenarioConfig::from_json(json); assert!(result.is_err()); if let Err(CliError::Config(msg)) = result { assert!(msg.contains("edge format")); } } #[test] fn test_load_config_from_file() { let dir = tempdir().unwrap(); let config_path = dir.path().join("test.json"); let json = r#"{ "fluid": "R744" }"#; std::fs::write(&config_path, json).unwrap(); let config = ScenarioConfig::from_file(&config_path).unwrap(); assert_eq!(config.fluid, "R744"); } #[test] fn test_load_config_file_not_found() { let result = ScenarioConfig::from_file(PathBuf::from("/nonexistent/path.json").as_path()); assert!(result.is_err()); if let Err(CliError::ConfigNotFound(path)) = result { assert!(path.to_str().unwrap().contains("nonexistent")); } } #[test] fn test_solver_config_defaults() { let config = SolverConfig::default(); assert_eq!(config.strategy, "fallback"); assert_eq!(config.max_iterations, 100); assert_eq!(config.tolerance, 1e-6); assert_eq!(config.timeout_ms, 0); assert!(!config.verbose); } #[test] fn test_component_config_params() { let json = r#" { "type": "Evaporator", "name": "evap1", "ua": 4000.0, "t_sat_k": 278.15, "superheat_k": 5.0 }"#; let component: ComponentConfig = serde_json::from_str(json).unwrap(); assert_eq!(component.component_type, "Evaporator"); assert_eq!(component.name, "evap1"); assert_eq!( component.params.get("ua").unwrap().as_f64().unwrap(), 4000.0 ); assert_eq!( component.params.get("t_sat_k").unwrap().as_f64().unwrap(), 278.15 ); assert_eq!( component .params .get("superheat_k") .unwrap() .as_f64() .unwrap(), 5.0 ); } #[test] fn test_validate_edge_unknown_component() { let json = r#" { "fluid": "R134a", "circuits": [{ "id": 0, "components": [{ "type": "Condenser", "name": "cond1", "ua": 5000.0 }], "edges": [{ "from": "cond1:outlet", "to": "nonexistent:inlet" }] }] }"#; let result = ScenarioConfig::from_json(json); assert!(result.is_err()); if let Err(CliError::Config(msg)) = result { assert!(msg.contains("unknown component")); assert!(msg.contains("nonexistent")); } }