Skip to main content

torsh_core/
runtime_config.rs

1//! Runtime Configuration System for ToRSh Core
2//!
3//! Provides centralized runtime configuration for debugging, validation,
4//! and performance monitoring features. This module allows dynamic control
5//! of framework behavior without recompilation.
6//!
7//! # Features
8//!
9//! - **Debug Modes**: Control assertion levels and validation strictness
10//! - **Performance Monitoring**: Enable/disable metrics collection per operation type
11//! - **Memory Tracking**: Configure memory debugging and leak detection
12//! - **Validation Levels**: Adjust shape/dtype validation strictness
13//! - **Logging Control**: Fine-grained logging configuration
14//!
15//! # Examples
16//!
17//! ```rust
18//! use torsh_core::runtime_config::{RuntimeConfig, DebugLevel, ValidationLevel};
19//!
20//! // Enable maximum debugging for development
21//! RuntimeConfig::global().set_debug_level(DebugLevel::Verbose);
22//! RuntimeConfig::global().set_validation_level(ValidationLevel::Strict);
23//!
24//! // Production mode with minimal overhead
25//! RuntimeConfig::global().set_debug_level(DebugLevel::None);
26//! RuntimeConfig::global().set_validation_level(ValidationLevel::Essential);
27//! ```
28
29use std::collections::HashMap;
30use std::sync::{Arc, Mutex, OnceLock};
31
32use crate::telemetry::LogLevel;
33
34/// Global runtime configuration instance
35static RUNTIME_CONFIG: OnceLock<Arc<Mutex<RuntimeConfigInternal>>> = OnceLock::new();
36
37/// Debug level for assertions and validation
38#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub enum DebugLevel {
40    /// No debug checks (production mode)
41    None = 0,
42    /// Only critical assertions that prevent undefined behavior
43    Essential = 1,
44    /// Standard debug assertions
45    Standard = 2,
46    /// Verbose debugging with extensive checks
47    Verbose = 3,
48    /// Paranoid mode with maximum validation (slowest)
49    Paranoid = 4,
50}
51
52impl Default for DebugLevel {
53    fn default() -> Self {
54        #[cfg(debug_assertions)]
55        {
56            Self::Standard
57        }
58        #[cfg(not(debug_assertions))]
59        {
60            Self::Essential
61        }
62    }
63}
64
65/// Validation level for shape and dtype operations
66#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
67pub enum ValidationLevel {
68    /// Only validate critical constraints that prevent crashes
69    Essential = 0,
70    /// Standard validation for common errors
71    Standard = 1,
72    /// Strict validation with comprehensive checks
73    Strict = 2,
74    /// Maximum validation including performance-impacting checks
75    Maximum = 3,
76}
77
78impl Default for ValidationLevel {
79    fn default() -> Self {
80        #[cfg(debug_assertions)]
81        {
82            Self::Strict
83        }
84        #[cfg(not(debug_assertions))]
85        {
86            Self::Standard
87        }
88    }
89}
90
91/// Performance monitoring scope
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
93pub enum MonitoringScope {
94    /// No performance monitoring
95    None,
96    /// Monitor only critical operations (< 1% overhead)
97    Minimal,
98    /// Monitor common operations (< 5% overhead)
99    Standard,
100    /// Monitor all operations (may add significant overhead)
101    Comprehensive,
102}
103
104impl Default for MonitoringScope {
105    fn default() -> Self {
106        Self::Standard
107    }
108}
109
110/// Memory tracking configuration
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112pub struct MemoryTrackingConfig {
113    /// Enable allocation tracking
114    pub track_allocations: bool,
115    /// Enable deallocation tracking
116    pub track_deallocations: bool,
117    /// Enable leak detection
118    pub detect_leaks: bool,
119    /// Enable memory pattern analysis
120    pub analyze_patterns: bool,
121    /// Maximum tracked allocations before sampling
122    pub max_tracked_allocations: usize,
123}
124
125impl Default for MemoryTrackingConfig {
126    fn default() -> Self {
127        Self {
128            track_allocations: cfg!(debug_assertions),
129            track_deallocations: cfg!(debug_assertions),
130            detect_leaks: cfg!(debug_assertions),
131            analyze_patterns: false, // Expensive, opt-in
132            max_tracked_allocations: 10_000,
133        }
134    }
135}
136
137/// Operation-specific configuration
138#[derive(Debug, Clone)]
139pub struct OperationConfig {
140    /// Enable performance metrics for this operation
141    pub enable_metrics: bool,
142    /// Enable validation for this operation
143    pub enable_validation: bool,
144    /// Custom timeout for this operation (None = no timeout)
145    pub timeout_ms: Option<u64>,
146    /// Custom memory limit for this operation (None = no limit)
147    pub memory_limit_bytes: Option<usize>,
148}
149
150impl Default for OperationConfig {
151    fn default() -> Self {
152        Self {
153            enable_metrics: true,
154            enable_validation: true,
155            timeout_ms: None,
156            memory_limit_bytes: None,
157        }
158    }
159}
160
161/// Internal runtime configuration state
162#[derive(Debug, Clone)]
163struct RuntimeConfigInternal {
164    /// Current debug level
165    debug_level: DebugLevel,
166    /// Current validation level
167    validation_level: ValidationLevel,
168    /// Current monitoring scope
169    monitoring_scope: MonitoringScope,
170    /// Memory tracking configuration
171    memory_tracking: MemoryTrackingConfig,
172    /// Log level for telemetry
173    log_level: LogLevel,
174    /// Per-operation custom configuration
175    operation_configs: HashMap<String, OperationConfig>,
176    /// Environment detection
177    is_testing: bool,
178    /// Whether to panic on warnings in debug mode
179    panic_on_warnings: bool,
180}
181
182impl Default for RuntimeConfigInternal {
183    fn default() -> Self {
184        Self {
185            debug_level: DebugLevel::default(),
186            validation_level: ValidationLevel::default(),
187            monitoring_scope: MonitoringScope::default(),
188            memory_tracking: MemoryTrackingConfig::default(),
189            log_level: LogLevel::Info,
190            operation_configs: HashMap::new(),
191            is_testing: std::env::var("RUST_TEST").is_ok(),
192            panic_on_warnings: false,
193        }
194    }
195}
196
197/// Runtime configuration manager
198///
199/// Provides thread-safe access to global runtime configuration.
200/// Configuration changes are immediately visible to all threads.
201#[derive(Clone)]
202pub struct RuntimeConfig {
203    inner: Arc<Mutex<RuntimeConfigInternal>>,
204}
205
206impl RuntimeConfig {
207    /// Get the global runtime configuration instance
208    ///
209    /// # Examples
210    ///
211    /// ```rust
212    /// use torsh_core::runtime_config::RuntimeConfig;
213    ///
214    /// let config = RuntimeConfig::global();
215    /// println!("Debug level: {:?}", config.debug_level());
216    /// ```
217    pub fn global() -> Self {
218        let inner = RUNTIME_CONFIG
219            .get_or_init(|| Arc::new(Mutex::new(RuntimeConfigInternal::default())))
220            .clone();
221        Self { inner }
222    }
223
224    /// Create a new isolated runtime configuration (for testing)
225    ///
226    /// # Examples
227    ///
228    /// ```rust
229    /// use torsh_core::runtime_config::RuntimeConfig;
230    ///
231    /// let config = RuntimeConfig::new();
232    /// // This config is independent of the global config
233    /// ```
234    pub fn new() -> Self {
235        Self {
236            inner: Arc::new(Mutex::new(RuntimeConfigInternal::default())),
237        }
238    }
239
240    /// Get the current debug level
241    pub fn debug_level(&self) -> DebugLevel {
242        self.inner
243            .lock()
244            .expect("lock should not be poisoned")
245            .debug_level
246    }
247
248    /// Set the debug level
249    ///
250    /// # Examples
251    ///
252    /// ```rust
253    /// use torsh_core::runtime_config::{RuntimeConfig, DebugLevel};
254    ///
255    /// RuntimeConfig::global().set_debug_level(DebugLevel::Verbose);
256    /// ```
257    pub fn set_debug_level(&self, level: DebugLevel) {
258        self.inner
259            .lock()
260            .expect("lock should not be poisoned")
261            .debug_level = level;
262    }
263
264    /// Get the current validation level
265    pub fn validation_level(&self) -> ValidationLevel {
266        self.inner
267            .lock()
268            .expect("lock should not be poisoned")
269            .validation_level
270    }
271
272    /// Set the validation level
273    ///
274    /// # Examples
275    ///
276    /// ```rust
277    /// use torsh_core::runtime_config::{RuntimeConfig, ValidationLevel};
278    ///
279    /// RuntimeConfig::global().set_validation_level(ValidationLevel::Maximum);
280    /// ```
281    pub fn set_validation_level(&self, level: ValidationLevel) {
282        self.inner
283            .lock()
284            .expect("lock should not be poisoned")
285            .validation_level = level;
286    }
287
288    /// Get the current monitoring scope
289    pub fn monitoring_scope(&self) -> MonitoringScope {
290        self.inner
291            .lock()
292            .expect("lock should not be poisoned")
293            .monitoring_scope
294    }
295
296    /// Set the monitoring scope
297    ///
298    /// # Examples
299    ///
300    /// ```rust
301    /// use torsh_core::runtime_config::{RuntimeConfig, MonitoringScope};
302    ///
303    /// RuntimeConfig::global().set_monitoring_scope(MonitoringScope::Comprehensive);
304    /// ```
305    pub fn set_monitoring_scope(&self, scope: MonitoringScope) {
306        self.inner
307            .lock()
308            .expect("lock should not be poisoned")
309            .monitoring_scope = scope;
310    }
311
312    /// Get memory tracking configuration
313    pub fn memory_tracking(&self) -> MemoryTrackingConfig {
314        self.inner
315            .lock()
316            .expect("lock should not be poisoned")
317            .memory_tracking
318    }
319
320    /// Set memory tracking configuration
321    pub fn set_memory_tracking(&self, config: MemoryTrackingConfig) {
322        self.inner
323            .lock()
324            .expect("lock should not be poisoned")
325            .memory_tracking = config;
326    }
327
328    /// Get the current log level
329    pub fn log_level(&self) -> LogLevel {
330        self.inner
331            .lock()
332            .expect("lock should not be poisoned")
333            .log_level
334    }
335
336    /// Set the log level
337    ///
338    /// # Examples
339    ///
340    /// ```rust
341    /// use torsh_core::runtime_config::RuntimeConfig;
342    /// use torsh_core::telemetry::LogLevel;
343    ///
344    /// RuntimeConfig::global().set_log_level(LogLevel::Debug);
345    /// ```
346    pub fn set_log_level(&self, level: LogLevel) {
347        self.inner
348            .lock()
349            .expect("lock should not be poisoned")
350            .log_level = level;
351    }
352
353    /// Check if currently running in test mode
354    pub fn is_testing(&self) -> bool {
355        self.inner
356            .lock()
357            .expect("lock should not be poisoned")
358            .is_testing
359    }
360
361    /// Set testing mode
362    pub fn set_testing(&self, testing: bool) {
363        self.inner
364            .lock()
365            .expect("lock should not be poisoned")
366            .is_testing = testing;
367    }
368
369    /// Check if warnings should panic in debug mode
370    pub fn panic_on_warnings(&self) -> bool {
371        self.inner
372            .lock()
373            .expect("lock should not be poisoned")
374            .panic_on_warnings
375    }
376
377    /// Set whether to panic on warnings in debug mode
378    pub fn set_panic_on_warnings(&self, panic: bool) {
379        self.inner
380            .lock()
381            .expect("lock should not be poisoned")
382            .panic_on_warnings = panic;
383    }
384
385    /// Get configuration for a specific operation
386    ///
387    /// # Examples
388    ///
389    /// ```rust
390    /// use torsh_core::runtime_config::RuntimeConfig;
391    ///
392    /// let config = RuntimeConfig::global();
393    /// if let Some(op_config) = config.get_operation_config("matmul") {
394    ///     println!("Matmul metrics enabled: {}", op_config.enable_metrics);
395    /// }
396    /// ```
397    pub fn get_operation_config(&self, operation: &str) -> Option<OperationConfig> {
398        self.inner
399            .lock()
400            .expect("runtime config lock should not be poisoned")
401            .operation_configs
402            .get(operation)
403            .cloned()
404    }
405
406    /// Set configuration for a specific operation
407    ///
408    /// # Examples
409    ///
410    /// ```rust
411    /// use torsh_core::runtime_config::{RuntimeConfig, OperationConfig};
412    ///
413    /// let mut config = OperationConfig::default();
414    /// config.timeout_ms = Some(1000); // 1 second timeout
415    ///
416    /// RuntimeConfig::global().set_operation_config("slow_operation", config);
417    /// ```
418    pub fn set_operation_config(&self, operation: impl Into<String>, config: OperationConfig) {
419        self.inner
420            .lock()
421            .expect("runtime config lock should not be poisoned")
422            .operation_configs
423            .insert(operation.into(), config);
424    }
425
426    /// Remove configuration for a specific operation
427    pub fn remove_operation_config(&self, operation: &str) -> Option<OperationConfig> {
428        self.inner
429            .lock()
430            .expect("runtime config lock should not be poisoned")
431            .operation_configs
432            .remove(operation)
433    }
434
435    /// Clear all operation-specific configurations
436    pub fn clear_operation_configs(&self) {
437        self.inner
438            .lock()
439            .expect("lock should not be poisoned")
440            .operation_configs
441            .clear();
442    }
443
444    /// Check if an operation should collect metrics
445    pub fn should_collect_metrics(&self, operation: &str) -> bool {
446        let guard = self.inner.lock().expect("lock should not be poisoned");
447
448        // Check operation-specific config first
449        if let Some(op_config) = guard.operation_configs.get(operation) {
450            return op_config.enable_metrics;
451        }
452
453        // Fall back to monitoring scope
454        match guard.monitoring_scope {
455            MonitoringScope::None => false,
456            MonitoringScope::Minimal => {
457                // Only critical operations
458                matches!(operation, "matmul" | "conv2d" | "backward")
459            }
460            MonitoringScope::Standard => {
461                // Common operations
462                !matches!(operation, "add" | "mul" | "sub" | "div")
463            }
464            MonitoringScope::Comprehensive => true,
465        }
466    }
467
468    /// Check if an operation should perform validation
469    pub fn should_validate(&self, operation: &str) -> bool {
470        let guard = self.inner.lock().expect("lock should not be poisoned");
471
472        // Check operation-specific config first
473        if let Some(op_config) = guard.operation_configs.get(operation) {
474            return op_config.enable_validation;
475        }
476
477        // Fall back to validation level
478        guard.validation_level >= ValidationLevel::Standard
479    }
480
481    /// Check if essential validation should be performed
482    pub fn should_validate_essential(&self) -> bool {
483        let guard = self.inner.lock().expect("lock should not be poisoned");
484        guard.validation_level >= ValidationLevel::Essential
485    }
486
487    /// Check if standard validation should be performed
488    pub fn should_validate_standard(&self) -> bool {
489        let guard = self.inner.lock().expect("lock should not be poisoned");
490        guard.validation_level >= ValidationLevel::Standard
491    }
492
493    /// Check if strict validation should be performed
494    pub fn should_validate_strict(&self) -> bool {
495        let guard = self.inner.lock().expect("lock should not be poisoned");
496        guard.validation_level >= ValidationLevel::Strict
497    }
498
499    /// Check if maximum validation should be performed
500    pub fn should_validate_maximum(&self) -> bool {
501        let guard = self.inner.lock().expect("lock should not be poisoned");
502        guard.validation_level >= ValidationLevel::Maximum
503    }
504
505    /// Apply a preset configuration for specific environments
506    ///
507    /// # Examples
508    ///
509    /// ```rust
510    /// use torsh_core::runtime_config::{RuntimeConfig, ConfigPreset};
511    ///
512    /// // Development mode
513    /// RuntimeConfig::global().apply_preset(ConfigPreset::Development);
514    ///
515    /// // Production mode
516    /// RuntimeConfig::global().apply_preset(ConfigPreset::Production);
517    /// ```
518    pub fn apply_preset(&self, preset: ConfigPreset) {
519        let mut guard = self.inner.lock().expect("lock should not be poisoned");
520        match preset {
521            ConfigPreset::Development => {
522                guard.debug_level = DebugLevel::Verbose;
523                guard.validation_level = ValidationLevel::Maximum;
524                guard.monitoring_scope = MonitoringScope::Comprehensive;
525                guard.memory_tracking = MemoryTrackingConfig {
526                    track_allocations: true,
527                    track_deallocations: true,
528                    detect_leaks: true,
529                    analyze_patterns: true,
530                    max_tracked_allocations: 50_000,
531                };
532                guard.log_level = LogLevel::Debug;
533                guard.panic_on_warnings = false;
534            }
535            ConfigPreset::Testing => {
536                guard.debug_level = DebugLevel::Standard;
537                guard.validation_level = ValidationLevel::Strict;
538                guard.monitoring_scope = MonitoringScope::Standard;
539                guard.memory_tracking = MemoryTrackingConfig {
540                    track_allocations: true,
541                    track_deallocations: true,
542                    detect_leaks: true,
543                    analyze_patterns: false,
544                    max_tracked_allocations: 10_000,
545                };
546                guard.log_level = LogLevel::Info;
547                guard.panic_on_warnings = true;
548                guard.is_testing = true;
549            }
550            ConfigPreset::Production => {
551                guard.debug_level = DebugLevel::None;
552                guard.validation_level = ValidationLevel::Essential;
553                guard.monitoring_scope = MonitoringScope::Minimal;
554                guard.memory_tracking = MemoryTrackingConfig {
555                    track_allocations: false,
556                    track_deallocations: false,
557                    detect_leaks: false,
558                    analyze_patterns: false,
559                    max_tracked_allocations: 0,
560                };
561                guard.log_level = LogLevel::Warn;
562                guard.panic_on_warnings = false;
563            }
564            ConfigPreset::Profiling => {
565                guard.debug_level = DebugLevel::Essential;
566                guard.validation_level = ValidationLevel::Standard;
567                guard.monitoring_scope = MonitoringScope::Comprehensive;
568                guard.memory_tracking = MemoryTrackingConfig {
569                    track_allocations: true,
570                    track_deallocations: true,
571                    detect_leaks: false,
572                    analyze_patterns: true,
573                    max_tracked_allocations: 100_000,
574                };
575                guard.log_level = LogLevel::Info;
576                guard.panic_on_warnings = false;
577            }
578        }
579    }
580
581    /// Reset to default configuration
582    pub fn reset(&self) {
583        *self.inner.lock().expect("lock should not be poisoned") = RuntimeConfigInternal::default();
584    }
585
586    /// Get a snapshot of the current configuration (for debugging)
587    pub fn snapshot(&self) -> RuntimeConfigSnapshot {
588        let guard = self.inner.lock().expect("lock should not be poisoned");
589        RuntimeConfigSnapshot {
590            debug_level: guard.debug_level,
591            validation_level: guard.validation_level,
592            monitoring_scope: guard.monitoring_scope,
593            memory_tracking: guard.memory_tracking,
594            log_level: guard.log_level,
595            is_testing: guard.is_testing,
596            panic_on_warnings: guard.panic_on_warnings,
597            operation_count: guard.operation_configs.len(),
598        }
599    }
600}
601
602impl Default for RuntimeConfig {
603    fn default() -> Self {
604        Self::global()
605    }
606}
607
608/// Configuration preset for common environments
609#[derive(Debug, Clone, Copy, PartialEq, Eq)]
610pub enum ConfigPreset {
611    /// Development mode: maximum debugging, comprehensive validation
612    Development,
613    /// Testing mode: standard debugging, strict validation, panics on warnings
614    Testing,
615    /// Production mode: minimal overhead, essential checks only
616    Production,
617    /// Profiling mode: comprehensive metrics, minimal validation overhead
618    Profiling,
619}
620
621/// Snapshot of runtime configuration (for debugging/reporting)
622#[derive(Debug, Clone)]
623pub struct RuntimeConfigSnapshot {
624    pub debug_level: DebugLevel,
625    pub validation_level: ValidationLevel,
626    pub monitoring_scope: MonitoringScope,
627    pub memory_tracking: MemoryTrackingConfig,
628    pub log_level: LogLevel,
629    pub is_testing: bool,
630    pub panic_on_warnings: bool,
631    pub operation_count: usize,
632}
633
634/// Convenience macros for debug assertions with configurable levels
635#[macro_export]
636macro_rules! torsh_debug_assert {
637    ($cond:expr) => {
638        if $crate::runtime_config::RuntimeConfig::global().debug_level() >= $crate::runtime_config::DebugLevel::Standard {
639            assert!($cond);
640        }
641    };
642    ($cond:expr, $($arg:tt)+) => {
643        if $crate::runtime_config::RuntimeConfig::global().debug_level() >= $crate::runtime_config::DebugLevel::Standard {
644            assert!($cond, $($arg)+);
645        }
646    };
647}
648
649/// Verbose debug assertion (only in Verbose or Paranoid mode)
650#[macro_export]
651macro_rules! torsh_debug_assert_verbose {
652    ($cond:expr) => {
653        if $crate::runtime_config::RuntimeConfig::global().debug_level() >= $crate::runtime_config::DebugLevel::Verbose {
654            assert!($cond);
655        }
656    };
657    ($cond:expr, $($arg:tt)+) => {
658        if $crate::runtime_config::RuntimeConfig::global().debug_level() >= $crate::runtime_config::DebugLevel::Verbose {
659            assert!($cond, $($arg)+);
660        }
661    };
662}
663
664/// Essential assertion (always runs unless debug level is None)
665#[macro_export]
666macro_rules! torsh_assert_essential {
667    ($cond:expr) => {
668        if $crate::runtime_config::RuntimeConfig::global().debug_level() >= $crate::runtime_config::DebugLevel::Essential {
669            assert!($cond);
670        }
671    };
672    ($cond:expr, $($arg:tt)+) => {
673        if $crate::runtime_config::RuntimeConfig::global().debug_level() >= $crate::runtime_config::DebugLevel::Essential {
674            assert!($cond, $($arg)+);
675        }
676    };
677}
678
679#[cfg(test)]
680mod tests {
681    use super::*;
682
683    #[test]
684    fn test_runtime_config_creation() {
685        let config = RuntimeConfig::new();
686        assert_eq!(config.debug_level(), DebugLevel::default());
687        assert_eq!(config.validation_level(), ValidationLevel::default());
688    }
689
690    #[test]
691    fn test_debug_level_setting() {
692        let config = RuntimeConfig::new();
693        config.set_debug_level(DebugLevel::Paranoid);
694        assert_eq!(config.debug_level(), DebugLevel::Paranoid);
695    }
696
697    #[test]
698    fn test_validation_level_setting() {
699        let config = RuntimeConfig::new();
700        config.set_validation_level(ValidationLevel::Maximum);
701        assert_eq!(config.validation_level(), ValidationLevel::Maximum);
702    }
703
704    #[test]
705    fn test_monitoring_scope_setting() {
706        let config = RuntimeConfig::new();
707        config.set_monitoring_scope(MonitoringScope::Comprehensive);
708        assert_eq!(config.monitoring_scope(), MonitoringScope::Comprehensive);
709    }
710
711    #[test]
712    fn test_operation_config() {
713        let config = RuntimeConfig::new();
714
715        let op_config = OperationConfig {
716            enable_metrics: false,
717            enable_validation: true,
718            timeout_ms: Some(5000),
719            memory_limit_bytes: Some(1024 * 1024), // 1MB
720        };
721
722        config.set_operation_config("test_op", op_config.clone());
723
724        let retrieved = config
725            .get_operation_config("test_op")
726            .expect("get_operation_config should succeed");
727        assert!(!retrieved.enable_metrics);
728        assert!(retrieved.enable_validation);
729        assert_eq!(retrieved.timeout_ms, Some(5000));
730        assert_eq!(retrieved.memory_limit_bytes, Some(1024 * 1024));
731    }
732
733    #[test]
734    fn test_should_collect_metrics() {
735        let config = RuntimeConfig::new();
736
737        // Test monitoring scope
738        config.set_monitoring_scope(MonitoringScope::None);
739        assert!(!config.should_collect_metrics("matmul"));
740
741        config.set_monitoring_scope(MonitoringScope::Minimal);
742        assert!(config.should_collect_metrics("matmul"));
743        assert!(!config.should_collect_metrics("add"));
744
745        config.set_monitoring_scope(MonitoringScope::Comprehensive);
746        assert!(config.should_collect_metrics("add"));
747    }
748
749    #[test]
750    fn test_should_validate() {
751        let config = RuntimeConfig::new();
752
753        config.set_validation_level(ValidationLevel::Essential);
754        assert!(!config.should_validate("any_operation"));
755
756        config.set_validation_level(ValidationLevel::Standard);
757        assert!(config.should_validate("any_operation"));
758    }
759
760    #[test]
761    fn test_development_preset() {
762        let config = RuntimeConfig::new();
763        config.apply_preset(ConfigPreset::Development);
764
765        assert_eq!(config.debug_level(), DebugLevel::Verbose);
766        assert_eq!(config.validation_level(), ValidationLevel::Maximum);
767        assert_eq!(config.monitoring_scope(), MonitoringScope::Comprehensive);
768        assert!(config.memory_tracking().track_allocations);
769    }
770
771    #[test]
772    fn test_production_preset() {
773        let config = RuntimeConfig::new();
774        config.apply_preset(ConfigPreset::Production);
775
776        assert_eq!(config.debug_level(), DebugLevel::None);
777        assert_eq!(config.validation_level(), ValidationLevel::Essential);
778        assert_eq!(config.monitoring_scope(), MonitoringScope::Minimal);
779        assert!(!config.memory_tracking().track_allocations);
780    }
781
782    #[test]
783    fn test_testing_preset() {
784        let config = RuntimeConfig::new();
785        config.apply_preset(ConfigPreset::Testing);
786
787        assert_eq!(config.debug_level(), DebugLevel::Standard);
788        assert_eq!(config.validation_level(), ValidationLevel::Strict);
789        assert!(config.panic_on_warnings());
790        assert!(config.is_testing());
791    }
792
793    #[test]
794    fn test_snapshot() {
795        let config = RuntimeConfig::new();
796        config.set_debug_level(DebugLevel::Verbose);
797
798        let snapshot = config.snapshot();
799        assert_eq!(snapshot.debug_level, DebugLevel::Verbose);
800    }
801
802    #[test]
803    fn test_reset() {
804        let config = RuntimeConfig::new();
805        config.set_debug_level(DebugLevel::Paranoid);
806        config.reset();
807        assert_eq!(config.debug_level(), DebugLevel::default());
808    }
809
810    #[test]
811    fn test_clear_operation_configs() {
812        let config = RuntimeConfig::new();
813        config.set_operation_config("op1", OperationConfig::default());
814        config.set_operation_config("op2", OperationConfig::default());
815
816        config.clear_operation_configs();
817        assert!(config.get_operation_config("op1").is_none());
818        assert!(config.get_operation_config("op2").is_none());
819    }
820}