//! PPO model integration test //! //! Verifies: create model -> forward pass -> valid output with padding //! Uses lightweight config for fast execution (<10s) use ml::ensemble::adapters::PpoInferenceAdapter; use ml::ensemble::inference_adapter::{FeatureVector, ModelInferenceAdapter}; use ml::ppo::ppo::PPOConfig; fn small_ppo_config() -> PPOConfig { PPOConfig { state_dim: 64, num_actions: 45, policy_hidden_dims: vec![32, 32], value_hidden_dims: vec![32, 32], ..Default::default() } } #[test] fn test_ppo_adapter_produces_valid_prediction() { let adapter = PpoInferenceAdapter::new(small_ppo_config()).expect("PpoInferenceAdapter::new should succeed"); assert_eq!(adapter.model_name(), "PPO"); assert!(adapter.is_ready()); // 51-dim input gets zero-padded to state_dim=64 let fv = FeatureVector { values: vec![0.1; 51], timestamp: 1_700_000_000_000_000, }; let pred = adapter.predict(&fv).expect("PPO predict should succeed"); assert!( pred.direction >= -1.0 && pred.direction <= 1.0, "direction {} out of [-1,1]", pred.direction ); assert!( pred.confidence >= 0.0 && pred.confidence <= 1.0, "confidence {} out of [0,1]", pred.confidence ); assert!(pred.direction.is_finite(), "direction must not be NaN/Inf"); assert!( pred.confidence.is_finite(), "confidence must not be NaN/Inf" ); } #[test] fn test_ppo_deterministic_inference() { let adapter = PpoInferenceAdapter::new(small_ppo_config()).expect("PpoInferenceAdapter::new should succeed"); let fv = FeatureVector { values: vec![0.3; 51], timestamp: 1_700_000_000_000_000, }; let pred1 = adapter.predict(&fv).expect("predict 1"); let pred2 = adapter.predict(&fv).expect("predict 2"); assert_eq!( pred1.direction, pred2.direction, "PPO inference should be deterministic" ); } #[test] fn test_ppo_handles_short_input() { let adapter = PpoInferenceAdapter::new(small_ppo_config()).expect("PpoInferenceAdapter::new should succeed"); // 10-dim input (much shorter than state_dim=64) should still work via padding let fv = FeatureVector { values: vec![0.5; 10], timestamp: 1_700_000_000_000_000, }; let pred = adapter .predict(&fv) .expect("PPO should handle short input via padding"); assert!(pred.direction.is_finite()); assert!(pred.confidence.is_finite()); }