//! Tests for single simulation execution. use entropyk_cli::error::ExitCode; use entropyk_cli::run::{SimulationResult, SimulationStatus}; use tempfile::tempdir; #[test] fn test_simulation_result_serialization() { let result = SimulationResult { input: "test.json".to_string(), status: SimulationStatus::Converged, convergence: Some(entropyk_cli::run::ConvergenceInfo { final_residual: 1e-8, tolerance: 1e-6, }), iterations: Some(25), state: Some(vec![entropyk_cli::run::StateEntry { edge: 0, pressure_bar: 10.0, enthalpy_kj_kg: 400.0, }]), performance: None, error: None, elapsed_ms: 50, }; let json = serde_json::to_string_pretty(&result).unwrap(); assert!(json.contains("\"status\": \"converged\"")); assert!(json.contains("\"iterations\": 25")); assert!(json.contains("\"pressure_bar\": 10.0")); } #[test] fn test_simulation_status_values() { assert_eq!(SimulationStatus::Converged, SimulationStatus::Converged); assert_ne!(SimulationStatus::Converged, SimulationStatus::Error); let status = SimulationStatus::NonConverged; let json = serde_json::to_string(&status).unwrap(); assert_eq!(json, "\"non_converged\""); } #[test] fn test_exit_codes() { assert_eq!(ExitCode::Success as i32, 0); assert_eq!(ExitCode::SimulationError as i32, 1); assert_eq!(ExitCode::ConfigError as i32, 2); assert_eq!(ExitCode::IoError as i32, 3); } #[test] fn test_error_result_serialization() { let result = SimulationResult { input: "invalid.json".to_string(), status: SimulationStatus::Error, convergence: None, iterations: None, state: None, performance: None, error: Some("Configuration error".to_string()), elapsed_ms: 0, }; let json = serde_json::to_string(&result).unwrap(); assert!(json.contains("Configuration error")); } #[test] fn test_create_minimal_config_file() { let dir = tempdir().unwrap(); let config_path = dir.path().join("minimal.json"); let json = r#"{ "fluid": "R134a" }"#; std::fs::write(&config_path, json).unwrap(); assert!(config_path.exists()); let content = std::fs::read_to_string(&config_path).unwrap(); assert!(content.contains("R134a")); } #[test] fn test_screw_compressor_frequency_hz_config() { use entropyk_cli::config::ScenarioConfig; use tempfile::tempdir; let dir = tempdir().unwrap(); let config_path = dir.path().join("screw_vfd.json"); let json = r#" { "name": "Screw VFD Test", "fluid": "R134a", "circuits": [ { "id": 0, "components": [ { "type": "ScrewEconomizerCompressor", "name": "screw_test", "fluid": "R134a", "nominal_frequency_hz": 50.0, "frequency_hz": 40.0, "mechanical_efficiency": 0.92, "economizer_fraction": 0.12, "mf_a00": 1.2, "mf_a10": 0.003, "mf_a01": -0.002, "mf_a11": 0.00001, "pw_b00": 55000.0, "pw_b10": 200.0, "pw_b01": -300.0, "pw_b11": 0.5, "p_suction_bar": 3.2, "h_suction_kj_kg": 400.0, "p_discharge_bar": 12.8, "h_discharge_kj_kg": 440.0, "p_eco_bar": 6.4, "h_eco_kj_kg": 260.0 } ], "edges": [] } ], "solver": { "strategy": "fallback", "max_iterations": 10 } } "#; std::fs::write(&config_path, json).unwrap(); let config = ScenarioConfig::from_file(&config_path); assert!(config.is_ok(), "Config should parse successfully"); let config = config.unwrap(); assert_eq!(config.circuits.len(), 1); let screw_params = &config.circuits[0].components[0].params; assert_eq!( screw_params.get("frequency_hz").and_then(|v| v.as_f64()), Some(40.0) ); assert_eq!( screw_params .get("nominal_frequency_hz") .and_then(|v| v.as_f64()), Some(50.0) ); } #[test] fn test_run_simulation_with_coolprop() { use entropyk_cli::run::run_simulation; let dir = tempdir().unwrap(); let config_path = dir.path().join("coolprop.json"); let json = r#" { "fluid": "R134a", "fluid_backend": "CoolProp", "circuits": [ { "id": 0, "components": [ { "type": "HeatExchanger", "name": "hx1", "ua": 1000.0, "hot_fluid": "Water", "hot_t_inlet_c": 25.0, "cold_fluid": "R134a", "cold_t_inlet_c": 15.0 } ], "edges": [] } ], "solver": { "max_iterations": 1 } } "#; std::fs::write(&config_path, json).unwrap(); let result = run_simulation(&config_path, None, false).unwrap(); match result.status { SimulationStatus::Converged | SimulationStatus::NonConverged => {} SimulationStatus::Error => { let err_msg = result.error.unwrap(); assert!( err_msg.contains("CoolProp") || err_msg.contains("Fluid") || err_msg.contains("Component"), "Unexpected error: {}", err_msg ); } _ => panic!("Unexpected status: {:?}", result.status), } }