1use crate::chaos_utilities::ChaosConfig;
8use crate::intelligent_behavior::config::IntelligentBehaviorConfig;
9use crate::latency::{LatencyDistribution, LatencyProfile};
10use serde::{Deserialize, Serialize};
11use std::sync::Arc;
12use tokio::sync::RwLock;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
19#[serde(rename_all = "snake_case")]
20pub enum RealityLevel {
21 StaticStubs = 1,
23 LightSimulation = 2,
25 ModerateRealism = 3,
27 HighRealism = 4,
29 ProductionChaos = 5,
31}
32
33impl RealityLevel {
34 pub fn value(&self) -> u8 {
36 *self as u8
37 }
38
39 pub fn name(&self) -> &'static str {
41 match self {
42 RealityLevel::StaticStubs => "Static Stubs",
43 RealityLevel::LightSimulation => "Light Simulation",
44 RealityLevel::ModerateRealism => "Moderate Realism",
45 RealityLevel::HighRealism => "High Realism",
46 RealityLevel::ProductionChaos => "Production Chaos",
47 }
48 }
49
50 pub fn description(&self) -> &'static str {
52 match self {
53 RealityLevel::StaticStubs => "Simple, instant responses with no chaos",
54 RealityLevel::LightSimulation => "Minimal latency, basic intelligence",
55 RealityLevel::ModerateRealism => "Some chaos, moderate latency, full intelligence",
56 RealityLevel::HighRealism => "Increased chaos, realistic latency, session state",
57 RealityLevel::ProductionChaos => {
58 "Maximum chaos, production-like latency, full features"
59 }
60 }
61 }
62
63 pub fn from_value(value: u8) -> Option<Self> {
65 match value {
66 1 => Some(RealityLevel::StaticStubs),
67 2 => Some(RealityLevel::LightSimulation),
68 3 => Some(RealityLevel::ModerateRealism),
69 4 => Some(RealityLevel::HighRealism),
70 5 => Some(RealityLevel::ProductionChaos),
71 _ => None,
72 }
73 }
74
75 pub fn all() -> Vec<Self> {
77 vec![
78 RealityLevel::StaticStubs,
79 RealityLevel::LightSimulation,
80 RealityLevel::ModerateRealism,
81 RealityLevel::HighRealism,
82 RealityLevel::ProductionChaos,
83 ]
84 }
85}
86
87impl Default for RealityLevel {
88 fn default() -> Self {
89 RealityLevel::ModerateRealism
90 }
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct RealityConfig {
96 pub level: RealityLevel,
98 pub chaos: ChaosConfig,
100 pub latency: LatencyProfile,
102 pub mockai: IntelligentBehaviorConfig,
104}
105
106impl RealityConfig {
107 pub fn for_level(level: RealityLevel) -> Self {
109 match level {
110 RealityLevel::StaticStubs => Self::level_1_static_stubs(),
111 RealityLevel::LightSimulation => Self::level_2_light_simulation(),
112 RealityLevel::ModerateRealism => Self::level_3_moderate_realism(),
113 RealityLevel::HighRealism => Self::level_4_high_realism(),
114 RealityLevel::ProductionChaos => Self::level_5_production_chaos(),
115 }
116 }
117
118 fn level_1_static_stubs() -> Self {
124 Self {
125 level: RealityLevel::StaticStubs,
126 chaos: ChaosConfig {
127 enabled: false,
128 error_rate: 0.0,
129 delay_rate: 0.0,
130 min_delay_ms: 0,
131 max_delay_ms: 0,
132 status_codes: vec![],
133 inject_timeouts: false,
134 timeout_ms: 0,
135 },
136 latency: LatencyProfile {
137 base_ms: 0,
138 jitter_ms: 0,
139 distribution: LatencyDistribution::Fixed,
140 std_dev_ms: None,
141 pareto_shape: None,
142 min_ms: 0,
143 max_ms: Some(0),
144 tag_overrides: Default::default(),
145 },
146 mockai: IntelligentBehaviorConfig {
147 enabled: false,
148 ..Default::default()
149 },
150 }
151 }
152
153 fn level_2_light_simulation() -> Self {
159 Self {
160 level: RealityLevel::LightSimulation,
161 chaos: ChaosConfig {
162 enabled: false,
163 error_rate: 0.0,
164 delay_rate: 0.0,
165 min_delay_ms: 0,
166 max_delay_ms: 0,
167 status_codes: vec![],
168 inject_timeouts: false,
169 timeout_ms: 0,
170 },
171 latency: LatencyProfile {
172 base_ms: 30,
173 jitter_ms: 20,
174 distribution: LatencyDistribution::Fixed,
175 std_dev_ms: None,
176 pareto_shape: None,
177 min_ms: 10,
178 max_ms: Some(50),
179 tag_overrides: Default::default(),
180 },
181 mockai: IntelligentBehaviorConfig {
182 enabled: true,
183 ..Default::default()
184 },
185 }
186 }
187
188 fn level_3_moderate_realism() -> Self {
194 Self {
195 level: RealityLevel::ModerateRealism,
196 chaos: ChaosConfig {
197 enabled: true,
198 error_rate: 0.05,
199 delay_rate: 0.10,
200 min_delay_ms: 50,
201 max_delay_ms: 200,
202 status_codes: vec![500, 502, 503],
203 inject_timeouts: false,
204 timeout_ms: 0,
205 },
206 latency: LatencyProfile {
207 base_ms: 125,
208 jitter_ms: 75,
209 distribution: LatencyDistribution::Normal,
210 std_dev_ms: Some(30.0),
211 pareto_shape: None,
212 min_ms: 50,
213 max_ms: Some(200),
214 tag_overrides: Default::default(),
215 },
216 mockai: IntelligentBehaviorConfig {
217 enabled: true,
218 ..Default::default()
219 },
220 }
221 }
222
223 fn level_4_high_realism() -> Self {
229 Self {
230 level: RealityLevel::HighRealism,
231 chaos: ChaosConfig {
232 enabled: true,
233 error_rate: 0.10,
234 delay_rate: 0.20,
235 min_delay_ms: 100,
236 max_delay_ms: 500,
237 status_codes: vec![500, 502, 503, 504],
238 inject_timeouts: false,
239 timeout_ms: 0,
240 },
241 latency: LatencyProfile {
242 base_ms: 300,
243 jitter_ms: 200,
244 distribution: LatencyDistribution::Normal,
245 std_dev_ms: Some(80.0),
246 pareto_shape: None,
247 min_ms: 100,
248 max_ms: Some(500),
249 tag_overrides: Default::default(),
250 },
251 mockai: IntelligentBehaviorConfig {
252 enabled: true,
253 performance: crate::intelligent_behavior::config::PerformanceConfig {
254 max_history_length: 100,
255 session_timeout_seconds: 3600,
256 ..Default::default()
257 },
258 ..Default::default()
259 },
260 }
261 }
262
263 fn level_5_production_chaos() -> Self {
269 Self {
270 level: RealityLevel::ProductionChaos,
271 chaos: ChaosConfig {
272 enabled: true,
273 error_rate: 0.15,
274 delay_rate: 0.30,
275 min_delay_ms: 200,
276 max_delay_ms: 2000,
277 status_codes: vec![500, 502, 503, 504, 408],
278 inject_timeouts: true,
279 timeout_ms: 5000,
280 },
281 latency: LatencyProfile {
282 base_ms: 1100,
283 jitter_ms: 900,
284 distribution: LatencyDistribution::Pareto,
285 std_dev_ms: None,
286 pareto_shape: Some(2.0),
287 min_ms: 200,
288 max_ms: Some(2000),
289 tag_overrides: Default::default(),
290 },
291 mockai: IntelligentBehaviorConfig {
292 enabled: true,
293 performance: crate::intelligent_behavior::config::PerformanceConfig {
294 max_history_length: 200,
295 session_timeout_seconds: 7200,
296 ..Default::default()
297 },
298 ..Default::default()
299 },
300 }
301 }
302}
303
304impl Default for RealityConfig {
305 fn default() -> Self {
306 Self::for_level(RealityLevel::default())
307 }
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize)]
312pub struct RealityPreset {
313 pub name: String,
315 pub description: Option<String>,
317 pub config: RealityConfig,
319 pub metadata: Option<PresetMetadata>,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
325pub struct PresetMetadata {
326 pub created_at: Option<String>,
328 pub author: Option<String>,
330 pub tags: Vec<String>,
332 pub version: Option<String>,
334}
335
336impl Default for PresetMetadata {
337 fn default() -> Self {
338 Self {
339 created_at: None,
340 author: None,
341 tags: vec![],
342 version: Some("1.0".to_string()),
343 }
344 }
345}
346
347#[derive(Debug, Clone)]
353pub struct RealityEngine {
354 config: Arc<RwLock<RealityConfig>>,
356}
357
358impl RealityEngine {
359 pub fn new() -> Self {
361 Self {
362 config: Arc::new(RwLock::new(RealityConfig::default())),
363 }
364 }
365
366 pub fn with_level(level: RealityLevel) -> Self {
368 Self {
369 config: Arc::new(RwLock::new(RealityConfig::for_level(level))),
370 }
371 }
372
373 pub async fn get_level(&self) -> RealityLevel {
375 self.config.read().await.level
376 }
377
378 pub async fn set_level(&self, level: RealityLevel) {
380 let mut config = self.config.write().await;
381 *config = RealityConfig::for_level(level);
382 }
383
384 pub async fn get_config(&self) -> RealityConfig {
386 self.config.read().await.clone()
387 }
388
389 pub async fn get_chaos_config(&self) -> ChaosConfig {
391 self.config.read().await.chaos.clone()
392 }
393
394 pub async fn get_latency_profile(&self) -> LatencyProfile {
396 self.config.read().await.latency.clone()
397 }
398
399 pub async fn get_mockai_config(&self) -> IntelligentBehaviorConfig {
401 self.config.read().await.mockai.clone()
402 }
403
404 pub async fn create_preset(&self, name: String, description: Option<String>) -> RealityPreset {
406 let config = self.config.read().await.clone();
407 RealityPreset {
408 name,
409 description,
410 config,
411 metadata: Some(PresetMetadata {
412 created_at: Some(chrono::Utc::now().to_rfc3339()),
413 author: None,
414 tags: vec![],
415 version: Some("1.0".to_string()),
416 }),
417 }
418 }
419
420 pub async fn apply_preset(&self, preset: RealityPreset) {
422 let mut config = self.config.write().await;
423 *config = preset.config;
424 }
425
426 pub async fn apply_to_config(&self, config: &mut crate::config::ServerConfig) {
432 let reality_config = self.get_config().await;
433
434 if config.reality.enabled {
436 if let Some(ref mut chaos_eng) = config.observability.chaos {
438 chaos_eng.enabled = reality_config.chaos.enabled;
439 if let Some(ref mut fault) = chaos_eng.fault_injection {
440 fault.enabled = reality_config.chaos.enabled;
441 fault.http_error_probability = reality_config.chaos.error_rate;
442 fault.timeout_errors = reality_config.chaos.inject_timeouts;
443 fault.timeout_ms = reality_config.chaos.timeout_ms;
444 }
445 if let Some(ref mut latency) = chaos_eng.latency {
446 latency.enabled = reality_config.latency.base_ms > 0;
447 latency.fixed_delay_ms = Some(reality_config.latency.base_ms);
448 latency.jitter_percent = if reality_config.latency.jitter_ms > 0 {
449 (reality_config.latency.jitter_ms as f64
450 / reality_config.latency.base_ms as f64)
451 .min(1.0)
452 } else {
453 0.0
454 };
455 }
456 }
457 }
458
459 if config.reality.enabled {
461 config.core.default_latency = reality_config.latency.clone();
462 config.core.latency_enabled = reality_config.latency.base_ms > 0;
463 }
464
465 if config.reality.enabled {
467 config.mockai.enabled = reality_config.mockai.enabled;
468 config.mockai.intelligent_behavior = reality_config.mockai.clone();
469 }
470 }
471}
472
473impl Default for RealityEngine {
474 fn default() -> Self {
475 Self::new()
476 }
477}
478
479#[cfg(test)]
480mod tests {
481 use super::*;
482
483 #[test]
484 fn test_reality_level_values() {
485 assert_eq!(RealityLevel::StaticStubs.value(), 1);
486 assert_eq!(RealityLevel::LightSimulation.value(), 2);
487 assert_eq!(RealityLevel::ModerateRealism.value(), 3);
488 assert_eq!(RealityLevel::HighRealism.value(), 4);
489 assert_eq!(RealityLevel::ProductionChaos.value(), 5);
490 }
491
492 #[test]
493 fn test_reality_level_from_value() {
494 assert_eq!(RealityLevel::from_value(1), Some(RealityLevel::StaticStubs));
495 assert_eq!(RealityLevel::from_value(3), Some(RealityLevel::ModerateRealism));
496 assert_eq!(RealityLevel::from_value(5), Some(RealityLevel::ProductionChaos));
497 assert_eq!(RealityLevel::from_value(0), None);
498 assert_eq!(RealityLevel::from_value(6), None);
499 }
500
501 #[test]
502 fn test_level_1_config() {
503 let config = RealityConfig::for_level(RealityLevel::StaticStubs);
504 assert!(!config.chaos.enabled);
505 assert_eq!(config.latency.base_ms, 0);
506 assert!(!config.mockai.enabled);
507 }
508
509 #[test]
510 fn test_level_5_config() {
511 let config = RealityConfig::for_level(RealityLevel::ProductionChaos);
512 assert!(config.chaos.enabled);
513 assert!(config.chaos.inject_timeouts);
514 assert_eq!(config.chaos.error_rate, 0.15);
515 assert!(config.latency.base_ms >= 200);
516 assert!(config.mockai.enabled);
517 }
518
519 #[tokio::test]
520 async fn test_reality_engine() {
521 let engine = RealityEngine::with_level(RealityLevel::StaticStubs);
522 assert_eq!(engine.get_level().await, RealityLevel::StaticStubs);
523
524 engine.set_level(RealityLevel::ProductionChaos).await;
525 assert_eq!(engine.get_level().await, RealityLevel::ProductionChaos);
526
527 let chaos_config = engine.get_chaos_config().await;
528 assert!(chaos_config.enabled);
529 }
530
531 #[tokio::test]
532 async fn test_preset_creation() {
533 let engine = RealityEngine::with_level(RealityLevel::ModerateRealism);
534 let preset = engine
535 .create_preset("test-preset".to_string(), Some("Test description".to_string()))
536 .await;
537
538 assert_eq!(preset.name, "test-preset");
539 assert_eq!(preset.config.level, RealityLevel::ModerateRealism);
540 assert!(preset.metadata.is_some());
541 }
542}