1use super::*;
7use crate::performance_optimization::PerformanceMetrics;
8use std::collections::hash_map::DefaultHasher;
9use std::hash::Hasher;
10use std::sync::atomic::{AtomicUsize, Ordering};
11use std::thread;
12
13pub struct VerificationProbe {
22 pub invoke: Box<dyn Fn() -> (Duration, Option<usize>) + Send + Sync>,
28 pub iterations: usize,
32 pub concurrency: usize,
36}
37
38impl VerificationProbe {
39 pub fn from_timing(invoke: impl Fn() + Send + Sync + 'static) -> Self {
42 Self {
43 invoke: Box::new(move || {
44 let start = Instant::now();
45 invoke();
46 (start.elapsed(), None)
47 }),
48 iterations: 1,
49 concurrency: 1,
50 }
51 }
52}
53
54fn panic_payload_to_string(payload: &(dyn std::any::Any + Send)) -> String {
57 if let Some(s) = payload.downcast_ref::<&str>() {
58 (*s).to_string()
59 } else if let Some(s) = payload.downcast_ref::<String>() {
60 s.clone()
61 } else {
62 "<non-string panic payload>".to_string()
63 }
64}
65
66impl Default for FormalVerificationEngine {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72impl FormalVerificationEngine {
73 pub fn new() -> Self {
75 Self {
76 verification_tasks: Arc::new(Mutex::new(HashMap::new())),
77 results_cache: Arc::new(RwLock::new(HashMap::new())),
78 }
79 }
80
81 pub fn verify_contract(
91 &self,
92 contract: &ApiContract,
93 probe: Option<VerificationProbe>,
94 ) -> CoreResult<()> {
95 let taskid = format!("{}-{}", contract.module, contract.apiname);
96
97 let properties = self.extract_verification_properties(contract);
98
99 let task = VerificationTask {
100 apiname: contract.apiname.clone(),
101 module: contract.module.clone(),
102 properties: properties.clone(),
103 status: VerificationStatus::InProgress,
104 started_at: Instant::now(),
105 };
106
107 {
108 let mut tasks = self.verification_tasks.lock().expect("Operation failed");
109 tasks.insert(taskid.clone(), task);
110 }
111
112 let tasks_clone = Arc::clone(&self.verification_tasks);
115 let results_clone = Arc::clone(&self.results_cache);
116 let performance = contract.performance.clone();
117 let memory = contract.memory.clone();
118 let thread_safety = contract.concurrency.thread_safety;
119
120 thread::spawn(move || {
121 let result = Self::perform_verification(
122 &properties,
123 &performance,
124 &memory,
125 thread_safety,
126 probe,
127 );
128 let verified = result.verified;
129
130 {
132 let mut results = results_clone.write().expect("Operation failed");
133 results.insert(taskid.clone(), result);
134 }
135
136 {
140 let mut tasks = tasks_clone.lock().expect("Operation failed");
141 if let Some(task) = tasks.get_mut(&taskid) {
142 task.status = if verified {
143 VerificationStatus::Verified
144 } else {
145 VerificationStatus::Failed
146 };
147 }
148 }
149 });
150
151 Ok(())
152 }
153
154 fn extract_verification_properties(&self, contract: &ApiContract) -> Vec<VerificationProperty> {
156 let mut properties = Vec::new();
157
158 properties.push(VerificationProperty {
160 name: "performance_bound".to_string(),
161 specification: format!(
162 "execution_time <= {:?}",
163 contract
164 .performance
165 .maxexecution_time
166 .unwrap_or(Duration::from_secs(1))
167 ),
168 property_type: PropertyType::Safety,
169 });
170
171 if let Some(max_memory) = contract.memory.max_memory {
173 properties.push(VerificationProperty {
174 name: "memory_bound".to_string(),
175 specification: format!("memory_usage <= {max_memory}"),
176 property_type: PropertyType::Safety,
177 });
178 }
179
180 if contract.concurrency.thread_safety == ThreadSafety::ThreadSafe {
182 properties.push(VerificationProperty {
183 name: "thread_safety".to_string(),
184 specification: "no_race_conditions AND no_deadlocks".to_string(),
185 property_type: PropertyType::Safety,
186 });
187 }
188
189 properties
190 }
191
192 pub fn get_verification_status(&self, apiname: &str, module: &str) -> VerificationStatus {
194 let taskid = format!("{module}-{apiname}");
195
196 if let Ok(tasks) = self.verification_tasks.lock() {
197 if let Some(task) = tasks.get(&taskid) {
198 return task.status;
199 }
200 }
201
202 VerificationStatus::NotVerified
203 }
204
205 pub fn get_all_results(&self) -> HashMap<String, VerificationResult> {
207 if let Ok(results) = self.results_cache.read() {
208 results.clone()
209 } else {
210 HashMap::new()
211 }
212 }
213
214 pub fn is_verification_complete(&self, apiname: &str, module: &str) -> bool {
216 matches!(
217 self.get_verification_status(apiname, module),
218 VerificationStatus::Verified | VerificationStatus::Failed
219 )
220 }
221
222 pub fn get_verification_coverage(&self) -> f64 {
224 if let Ok(tasks) = self.verification_tasks.lock() {
225 if tasks.is_empty() {
226 return 0.0;
227 }
228
229 let verified_count = tasks
230 .values()
231 .filter(|task| task.status == VerificationStatus::Verified)
232 .count();
233
234 (verified_count as f64 / tasks.len() as f64) * 100.0
235 } else {
236 0.0
237 }
238 }
239
240 fn perform_verification(
252 properties: &[VerificationProperty],
253 performance: &PerformanceContract,
254 memory: &MemoryContract,
255 thread_safety: ThreadSafety,
256 probe: Option<VerificationProbe>,
257 ) -> VerificationResult {
258 let start_time = Instant::now();
259
260 let Some(probe) = probe else {
261 return VerificationResult {
262 verified: false,
263 verification_time: start_time.elapsed(),
264 checked_properties: vec![],
265 counterexample: Some(format!(
266 "no VerificationProbe was supplied: {} declared propert{} could not be \
267 executed against a real workload and so cannot be confirmed",
268 properties.len(),
269 if properties.len() == 1 { "y" } else { "ies" }
270 )),
271 method: VerificationMethod::StaticAnalysis,
272 };
273 };
274
275 let iterations = probe.iterations.max(1);
282 let mut max_elapsed = Duration::ZERO;
283 let mut max_memory_delta: Option<usize> = None;
284 let mut probe_panic_message: Option<String> = None;
285 for _ in 0..iterations {
286 match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| (probe.invoke)())) {
287 Ok((elapsed, memory_delta)) => {
288 max_elapsed = max_elapsed.max(elapsed);
289 if let Some(delta) = memory_delta {
290 max_memory_delta =
291 Some(max_memory_delta.map_or(delta, |current| current.max(delta)));
292 }
293 }
294 Err(payload) => {
295 probe_panic_message = Some(panic_payload_to_string(&payload));
296 break;
297 }
298 }
299 }
300
301 if let Some(message) = probe_panic_message {
302 return VerificationResult {
303 verified: false,
304 verification_time: start_time.elapsed(),
305 checked_properties: vec![],
306 counterexample: Some(format!(
307 "the supplied probe panicked during measurement: {message}"
308 )),
309 method: VerificationMethod::SymbolicExecution,
310 };
311 }
312
313 let mut checked_properties = Vec::new();
314 let mut counterexamples = Vec::new();
315
316 for property in properties {
317 match property.name.as_str() {
318 "performance_bound" => {
319 checked_properties.push(property.name.clone());
320 if let Some(bound) = performance.maxexecution_time {
321 if max_elapsed > bound {
322 counterexamples.push(format!(
323 "performance_bound violated: measured max execution time \
324 {max_elapsed:?} exceeds the contract bound {bound:?} (over \
325 {iterations} iteration(s))"
326 ));
327 }
328 }
329 }
330 "memory_bound" => {
331 checked_properties.push(property.name.clone());
332 match (memory.max_memory, max_memory_delta) {
333 (Some(bound), Some(delta)) if delta > bound => {
334 counterexamples.push(format!(
335 "memory_bound violated: measured memory delta {delta} bytes \
336 exceeds the contract bound {bound} bytes"
337 ));
338 }
339 (Some(_), None) => {
340 counterexamples.push(
341 "memory_bound could not be confirmed: the supplied probe never \
342 reported a memory measurement"
343 .to_string(),
344 );
345 }
346 _ => {}
347 }
348 }
349 "thread_safety" => {
350 checked_properties.push(property.name.clone());
351 if thread_safety == ThreadSafety::ThreadSafe && probe.concurrency > 1 {
352 if let Some(failure) = Self::concurrent_smoke_test(&probe) {
353 counterexamples.push(failure);
354 }
355 }
356 }
357 _ => {}
358 }
359 }
360
361 let verified = counterexamples.is_empty();
362 VerificationResult {
363 verified,
364 verification_time: start_time.elapsed(),
365 checked_properties,
366 counterexample: if counterexamples.is_empty() {
367 None
368 } else {
369 Some(counterexamples.join("; "))
370 },
371 method: VerificationMethod::SymbolicExecution,
377 }
378 }
379
380 fn concurrent_smoke_test(probe: &VerificationProbe) -> Option<String> {
386 const TIMEOUT: Duration = Duration::from_secs(10);
387
388 let concurrency = probe.concurrency.max(1);
389 let iterations_per_thread = probe.iterations.max(1);
390 let invoke = &probe.invoke;
391 let panic_count = AtomicUsize::new(0);
392 let (tx, rx) = mpsc::channel::<()>();
393
394 thread::scope(|scope| {
395 for _ in 0..concurrency {
396 let tx = tx.clone();
397 let panic_count = &panic_count;
398 scope.spawn(move || {
399 for _ in 0..iterations_per_thread {
400 let outcome =
401 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
402 (invoke)();
403 }));
404 if outcome.is_err() {
405 panic_count.fetch_add(1, Ordering::SeqCst);
406 }
407 }
408 let _ = tx.send(());
409 });
410 }
411 drop(tx);
412
413 let deadline = Instant::now() + TIMEOUT;
414 let mut completed = 0usize;
415 while completed < concurrency {
416 let remaining = deadline.saturating_duration_since(Instant::now());
417 if remaining.is_zero() {
418 break;
419 }
420 match rx.recv_timeout(remaining) {
421 Ok(()) => completed += 1,
422 Err(_) => break,
423 }
424 }
425
426 if completed < concurrency {
427 return Some(format!(
428 "thread_safety smoke test timed out: only {completed}/{concurrency} worker \
429 thread(s) completed within {TIMEOUT:?} (suspected deadlock/hang)"
430 ));
431 }
432
433 let panics = panic_count.load(Ordering::SeqCst);
434 if panics > 0 {
435 return Some(format!(
436 "thread_safety smoke test failed: {panics} panic(s) observed across \
437 {concurrency} concurrent thread(s) x {iterations_per_thread} iteration(s)"
438 ));
439 }
440
441 None
442 })
443 }
444}
445
446impl RuntimeContractValidator {
447 pub fn new() -> (Self, Receiver<MonitoringEvent>) {
449 let (sender, receiver) = mpsc::channel();
450
451 let validator = Self {
452 contracts: Arc::new(RwLock::new(HashMap::new())),
453 event_sender: sender,
454 stats: Arc::new(Mutex::new(ValidationStatistics {
455 total_validations: 0,
456 violations_detected: 0,
457 avg_validation_time: Duration::from_nanos(0),
458 success_rate: 1.0,
459 })),
460 chaos_controller: Arc::new(Mutex::new(ChaosEngineeringController {
461 enabled: false,
462 faultprobability: 0.01,
463 active_faults: Vec::new(),
464 fault_history: Vec::new(),
465 })),
466 };
467
468 (validator, receiver)
469 }
470
471 pub fn register_contract(&self, contract: ApiContract) {
473 let key = format!("{}-{}", contract.module, contract.apiname);
474
475 if let Ok(mut contracts) = self.contracts.write() {
476 contracts.insert(key, contract);
477 }
478 }
479
480 pub fn validate_api_call(
482 &self,
483 apiname: &str,
484 module: &str,
485 context: &ApiCallContext,
486 ) -> CoreResult<()> {
487 let start_time = Instant::now();
488 let key = format!("{module}-{apiname}");
489
490 {
492 if let Ok(mut stats) = self.stats.lock() {
493 stats.total_validations += 1;
494 }
495 }
496
497 self.maybe_inject_fault(apiname, module)?;
499
500 let contract = {
502 if let Ok(contracts) = self.contracts.read() {
503 contracts.get(&key).cloned()
504 } else {
505 return Err(CoreError::ValidationError(ErrorContext::new(
506 "Cannot access contracts for validation".to_string(),
507 )));
508 }
509 };
510
511 let contract = contract.ok_or_else(|| {
512 CoreError::ValidationError(ErrorContext::new(format!(
513 "No contract found for {module}::{apiname}"
514 )))
515 })?;
516
517 if let Some(max_time) = contract.performance.maxexecution_time {
519 if context.execution_time > max_time {
520 self.report_violation(
521 apiname,
522 module,
523 ContractViolation {
524 violation_type: ViolationType::Performance,
525 expected: format!("{max_time:?}"),
526 actual: format!("{:?}", context.execution_time),
527 severity: ViolationSeverity::High,
528 },
529 )?;
530 }
531 }
532
533 if let Some(max_memory) = contract.memory.max_memory {
535 if context.memory_usage > max_memory {
536 self.report_violation(
537 apiname,
538 module,
539 ContractViolation {
540 violation_type: ViolationType::Memory,
541 expected: format!("{max_memory}"),
542 actual: context.memory_usage.to_string(),
543 severity: ViolationSeverity::Medium,
544 },
545 )?;
546 }
547 }
548
549 let validation_time = start_time.elapsed();
551 {
552 if let Ok(mut stats) = self.stats.lock() {
553 let total = stats.total_validations as f64;
554 let prev_avg = stats.avg_validation_time.as_nanos() as f64;
555 let new_avg =
556 (prev_avg * (total - 1.0) + validation_time.as_nanos() as f64) / total;
557 stats.avg_validation_time = Duration::from_nanos(new_avg as u64);
558 stats.success_rate = (total - stats.violations_detected as f64) / total;
559 }
560 }
561
562 Ok(())
563 }
564
565 pub fn enable_chaos_engineering(&self, faultprobability: f64) {
567 if let Ok(mut controller) = self.chaos_controller.lock() {
568 controller.enabled = true;
569 controller.faultprobability = faultprobability.clamp(0.0, 1.0);
570 }
571 }
572
573 fn maybe_inject_fault(&self, apiname: &str, module: &str) -> CoreResult<()> {
575 if let Ok(mut controller) = self.chaos_controller.lock() {
576 if !controller.enabled {
577 return Ok(());
578 }
579
580 let mut hasher = DefaultHasher::new();
582 apiname.hash(&mut hasher);
583 module.hash(&mut hasher);
584 SystemTime::now()
585 .duration_since(SystemTime::UNIX_EPOCH)
586 .unwrap_or_default()
587 .as_nanos()
588 .hash(&mut hasher);
589
590 let rand_val = (hasher.finish() % 10000) as f64 / 10000.0;
591
592 if rand_val < controller.faultprobability {
593 let fault = match rand_val * 4.0 {
595 x if x < 1.0 => ChaosFault::LatencyInjection(Duration::from_millis(100)),
596 x if x < 2.0 => ChaosFault::MemoryPressure(1024 * 1024), x if x < 3.0 => ChaosFault::CpuThrottling(0.5),
598 _ => ChaosFault::RandomFailure(0.1),
599 };
600
601 controller.active_faults.push(fault.clone());
602 controller
603 .fault_history
604 .push((Instant::now(), fault.clone()));
605
606 let event = MonitoringEvent {
608 timestamp: Instant::now(),
609 apiname: apiname.to_string(),
610 module: module.to_string(),
611 event_type: MonitoringEventType::ChaosEngineeringFault(fault.clone()),
612 performance_metrics: RuntimePerformanceMetrics {
613 execution_time: Duration::from_nanos(0),
614 memory_usage: 0,
615 cpu_usage: 0.0,
616 cache_hit_rate: 0.0,
617 thread_count: 1,
618 },
619 thread_id: format!("{:?}", thread::current().id()),
620 };
621
622 let _ = self.event_sender.send(event);
623
624 match fault {
626 ChaosFault::LatencyInjection(delay) => {
627 thread::sleep(delay);
628 }
629 ChaosFault::RandomFailure(prob) if rand_val < prob => {
630 return Err(CoreError::ValidationError(ErrorContext::new(
631 "Chaos engineering: Random failure injected".to_string(),
632 )));
633 }
634 _ => {} }
636 }
637 }
638
639 Ok(())
640 }
641
642 fn report_violation(
644 &self,
645 apiname: &str,
646 module: &str,
647 violation: ContractViolation,
648 ) -> CoreResult<()> {
649 {
651 if let Ok(mut stats) = self.stats.lock() {
652 stats.violations_detected += 1;
653 let total = stats.total_validations as f64;
654 stats.success_rate = (total - stats.violations_detected as f64) / total;
655 }
656 }
657
658 let event = MonitoringEvent {
660 timestamp: Instant::now(),
661 apiname: apiname.to_string(),
662 module: module.to_string(),
663 event_type: MonitoringEventType::ContractViolation(violation.clone()),
664 performance_metrics: RuntimePerformanceMetrics {
665 execution_time: Duration::from_nanos(0),
666 memory_usage: 0,
667 cpu_usage: 0.0,
668 cache_hit_rate: 0.0,
669 thread_count: 1,
670 },
671 thread_id: format!("{:?}", thread::current().id()),
672 };
673
674 let _ = self.event_sender.send(event);
675
676 if violation.severity >= ViolationSeverity::High {
678 return Err(CoreError::ValidationError(ErrorContext::new(format!(
679 "Critical contract violation in {}::{}: {} (expected: {}, actual: {})",
680 module,
681 apiname,
682 match violation.violation_type {
683 ViolationType::Performance => "Performance",
684 ViolationType::Memory => "Memory",
685 ViolationType::Numerical => "Numerical",
686 ViolationType::Concurrency => "Concurrency",
687 ViolationType::Behavioral => "Behavioral",
688 },
689 violation.expected,
690 violation.actual
691 ))));
692 }
693
694 Ok(())
695 }
696
697 pub fn get_statistics(&self) -> Option<ValidationStatistics> {
699 self.stats.lock().ok().map(|stats| stats.clone())
700 }
701
702 pub fn get_chaos_status(&self) -> Option<(bool, f64, usize)> {
704 if let Ok(controller) = self.chaos_controller.lock() {
705 Some((
706 controller.enabled,
707 controller.faultprobability,
708 controller.fault_history.len(),
709 ))
710 } else {
711 None
712 }
713 }
714
715 pub fn disable_chaos_engineering(&self) {
717 if let Ok(mut controller) = self.chaos_controller.lock() {
718 controller.enabled = false;
719 controller.active_faults.clear();
720 }
721 }
722}
723
724#[derive(Debug, Clone)]
726pub struct ApiCallContext {
727 pub execution_time: Duration,
729 pub memory_usage: usize,
731 pub input_hash: String,
733 pub output_hash: String,
735 pub thread_id: String,
737}
738
739impl Default for AdvancedPerformanceModeler {
740 fn default() -> Self {
741 Self::new()
742 }
743}
744
745impl AdvancedPerformanceModeler {
746 pub fn new() -> Self {
748 Self {
749 performance_history: Arc::new(RwLock::new(Vec::new())),
750 prediction_models: Arc::new(RwLock::new(HashMap::new())),
751 training_status: Arc::new(Mutex::new(HashMap::new())),
752 }
753 }
754
755 pub fn record_measurement(
757 &self,
758 apiname: &str,
759 input_characteristics: InputCharacteristics,
760 performance: PerformanceMetrics,
761 system_state: SystemState,
762 ) {
763 let runtime_performance = RuntimePerformanceMetrics {
765 execution_time: Duration::from_secs_f64(
766 performance.operation_times.values().sum::<f64>()
767 / performance.operation_times.len().max(1) as f64,
768 ),
769 memory_usage: 0, cpu_usage: 0.0, cache_hit_rate: performance.cache_hit_rate,
772 thread_count: 1, };
774
775 let data_point = PerformanceDataPoint {
776 timestamp: Instant::now(),
777 apiname: apiname.to_string(),
778 input_characteristics,
779 performance: runtime_performance,
780 system_state,
781 };
782
783 if let Ok(mut history) = self.performance_history.write() {
784 history.push(data_point);
785
786 if history.len() > 10000 {
788 history.remove(0);
789 }
790 }
791
792 self.maybe_retrain_model(apiname);
794 }
795
796 pub fn predict_performance(
798 &self,
799 apiname: &str,
800 input_characteristics: InputCharacteristics,
801 system_state: &SystemState,
802 ) -> Option<RuntimePerformanceMetrics> {
803 if let Ok(models) = self.prediction_models.read() {
804 if let Some(model) = models.get(apiname) {
805 let base_time = Duration::from_nanos(1000);
807 let size_factor = match model.model_type {
808 ModelType::LinearRegression => {
809 if model.parameters.len() >= 2 {
811 model.parameters[0] * input_characteristics.size as f64
812 + model.parameters[1]
813 } else {
814 (input_characteristics.size as f64).sqrt()
815 }
816 }
817 ModelType::PolynomialRegression => (input_characteristics.size as f64).sqrt(),
818 _ => (input_characteristics.size as f64).sqrt(),
819 };
820
821 let scaled_time = Duration::from_nanos(
822 (base_time.as_nanos() as f64 * size_factor.max(1.0)) as u64,
823 );
824
825 return Some(RuntimePerformanceMetrics {
826 execution_time: scaled_time,
827 memory_usage: input_characteristics.size * 8, cpu_usage: system_state.cpu_utilization * 1.1, cache_hit_rate: 0.8, thread_count: 1,
831 });
832 }
833 }
834
835 None
836 }
837
838 fn maybe_retrain_model(&self, apiname: &str) {
840 let should_retrain = {
842 if let Ok(history) = self.performance_history.read() {
843 let api_data_points = history.iter().filter(|dp| dp.apiname == apiname).count();
844 api_data_points > 100 && (api_data_points % 50 == 0)
845 } else {
846 false
847 }
848 };
849
850 if should_retrain {
851 self.train_model(apiname);
852 }
853 }
854
855 fn train_model(&self, apiname: &str) {
857 {
859 if let Ok(mut status) = self.training_status.lock() {
860 status.insert(apiname.to_string(), TrainingStatus::InProgress);
861 }
862 }
863
864 let apiname = apiname.to_string();
865 let history_clone = Arc::clone(&self.performance_history);
866 let models_clone = Arc::clone(&self.prediction_models);
867 let status_clone = Arc::clone(&self.training_status);
868
869 thread::spawn(move || {
871 let training_data = {
872 if let Ok(history) = history_clone.read() {
873 history
874 .iter()
875 .filter(|dp| dp.apiname == apiname)
876 .cloned()
877 .collect::<Vec<_>>()
878 } else {
879 Vec::new()
880 }
881 };
882
883 if training_data.len() < 10 {
884 if let Ok(mut status) = status_clone.lock() {
886 status.insert(apiname.clone(), TrainingStatus::Failed);
887 }
888 return;
889 }
890
891 let mut sum_x = 0.0;
893 let mut sum_y = 0.0;
894 let mut sum_xy = 0.0;
895 let mut sum_x2 = 0.0;
896 let n = training_data.len() as f64;
897
898 for dp in &training_data {
899 let x = dp.input_characteristics.size as f64;
900 let y = dp.performance.execution_time.as_nanos() as f64;
901
902 sum_x += x;
903 sum_y += y;
904 sum_xy += x * y;
905 sum_x2 += x * x;
906 }
907
908 let slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x);
909 let intercept = (sum_y - slope * sum_x) / n;
910
911 let y_mean = sum_y / n;
913 let mut ss_tot = 0.0;
914 let mut ss_res = 0.0;
915
916 for dp in &training_data {
917 let x = dp.input_characteristics.size as f64;
918 let y = dp.performance.execution_time.as_nanos() as f64;
919 let y_pred = slope * x + intercept;
920
921 ss_tot += (y - y_mean).powi(2);
922 ss_res += (y - y_pred).powi(2);
923 }
924
925 let r_squared = if ss_tot > 0.0 {
926 1.0 - (ss_res / ss_tot)
927 } else {
928 0.0
929 };
930
931 let model = PerformancePredictionModel {
932 model_type: ModelType::LinearRegression,
933 parameters: vec![slope, intercept],
934 accuracy: r_squared.clamp(0.0, 1.0),
935 training_data_size: training_data.len(),
936 last_updated: Instant::now(),
937 };
938
939 {
941 if let Ok(mut models) = models_clone.write() {
942 models.insert(apiname.clone(), model);
943 }
944 }
945
946 {
948 if let Ok(mut status) = status_clone.lock() {
949 status.insert(apiname, TrainingStatus::Completed);
950 }
951 }
952 });
953 }
954
955 pub fn get_training_status(&self, apiname: &str) -> TrainingStatus {
957 if let Ok(status) = self.training_status.lock() {
958 status
959 .get(apiname)
960 .copied()
961 .unwrap_or(TrainingStatus::NotStarted)
962 } else {
963 TrainingStatus::NotStarted
964 }
965 }
966
967 pub fn get_model_accuracy(&self, apiname: &str) -> Option<f64> {
969 if let Ok(models) = self.prediction_models.read() {
970 models.get(apiname).map(|model| model.accuracy)
971 } else {
972 None
973 }
974 }
975
976 pub fn get_data_point_count(&self, apiname: &str) -> usize {
978 if let Ok(history) = self.performance_history.read() {
979 history.iter().filter(|dp| dp.apiname == apiname).count()
980 } else {
981 0
982 }
983 }
984}
985
986impl Default for ImmutableAuditTrail {
987 fn default() -> Self {
988 Self::new()
989 }
990}
991
992impl ImmutableAuditTrail {
993 pub fn new() -> Self {
995 Self {
996 audit_chain: Arc::new(RwLock::new(Vec::new())),
997 current_hash: Arc::new(RwLock::new(0.to_string())),
998 }
999 }
1000
1001 pub fn add_record(&self, data: AuditData) -> CoreResult<()> {
1003 let timestamp = SystemTime::now();
1004
1005 let previous_hash = {
1006 if let Ok(hash) = self.current_hash.read() {
1007 hash.clone()
1008 } else {
1009 return Err(CoreError::ValidationError(ErrorContext::new(
1010 "Cannot access current hash".to_string(),
1011 )));
1012 }
1013 };
1014
1015 let mut record = AuditRecord {
1017 timestamp,
1018 previous_hash: previous_hash.clone(),
1019 data,
1020 signature: String::new(), record_hash: String::new(),
1022 };
1023
1024 record.record_hash = self.calculate_record_hash(&record);
1026
1027 record.signature = record.record_hash.to_string();
1029
1030 {
1032 if let Ok(mut chain) = self.audit_chain.write() {
1033 chain.push(record.clone());
1034 } else {
1035 return Err(CoreError::ValidationError(ErrorContext::new(
1036 "Cannot access audit chain".to_string(),
1037 )));
1038 }
1039 }
1040
1041 {
1043 if let Ok(mut hash) = self.current_hash.write() {
1044 *hash = record.record_hash;
1045 }
1046 }
1047
1048 Ok(())
1049 }
1050
1051 fn calculate_record_hash(&self, record: &AuditRecord) -> String {
1053 let mut hasher = DefaultHasher::new();
1054
1055 record
1056 .timestamp
1057 .duration_since(SystemTime::UNIX_EPOCH)
1058 .unwrap_or_default()
1059 .as_nanos()
1060 .hash(&mut hasher);
1061 record.previous_hash.hash(&mut hasher);
1062
1063 match &record.data {
1065 AuditData::ContractRegistration(name) => name.hash(&mut hasher),
1066 AuditData::ContractValidation {
1067 apiname,
1068 module,
1069 result,
1070 } => {
1071 apiname.hash(&mut hasher);
1072 module.hash(&mut hasher);
1073 result.hash(&mut hasher);
1074 }
1075 AuditData::PerformanceMeasurement {
1076 apiname,
1077 module,
1078 metrics,
1079 } => {
1080 apiname.hash(&mut hasher);
1081 module.hash(&mut hasher);
1082 metrics.hash(&mut hasher);
1083 }
1084 AuditData::ViolationDetection {
1085 apiname,
1086 module,
1087 violation,
1088 } => {
1089 apiname.hash(&mut hasher);
1090 module.hash(&mut hasher);
1091 violation.hash(&mut hasher);
1092 }
1093 }
1094
1095 format!("{:x}", hasher.finish())
1096 }
1097
1098 pub fn verify_integrity(&self) -> bool {
1100 if let Ok(chain) = self.audit_chain.read() {
1101 if chain.is_empty() {
1102 return true;
1103 }
1104
1105 for (i, record) in chain.iter().enumerate() {
1106 let expected_hash = self.calculate_record_hash(record);
1108 if record.record_hash != expected_hash {
1109 return false;
1110 }
1111
1112 if i > 0 {
1114 let prev_record = &chain[i.saturating_sub(1)];
1115 if record.previous_hash != prev_record.record_hash {
1116 return false;
1117 }
1118 }
1119 }
1120
1121 true
1122 } else {
1123 false
1124 }
1125 }
1126
1127 pub fn len(&self) -> usize {
1129 if let Ok(chain) = self.audit_chain.read() {
1130 chain.len()
1131 } else {
1132 0
1133 }
1134 }
1135
1136 pub fn is_empty(&self) -> bool {
1138 self.len() == 0
1139 }
1140
1141 pub fn get_recent_records(&self, count: usize) -> Vec<AuditRecord> {
1143 if let Ok(chain) = self.audit_chain.read() {
1144 let start = chain.len().saturating_sub(count);
1145 chain[start..].to_vec()
1146 } else {
1147 Vec::new()
1148 }
1149 }
1150
1151 #[cfg(feature = "serialization")]
1153 pub fn export_trail(&self) -> CoreResult<String> {
1154 if let Ok(chain) = self.audit_chain.read() {
1155 serde_json::to_string_pretty(&*chain).map_err(|e| {
1156 CoreError::ValidationError(ErrorContext::new(format!(
1157 "Failed to serialize audit trail: {e}"
1158 )))
1159 })
1160 } else {
1161 Err(CoreError::ValidationError(ErrorContext::new(
1162 "Cannot access audit chain for export".to_string(),
1163 )))
1164 }
1165 }
1166
1167 #[cfg(not(feature = "serialization"))]
1169 pub fn export_trail(&self) -> CoreResult<String> {
1170 Err(CoreError::ValidationError(ErrorContext::new(
1171 "Audit trail export requires serialization feature".to_string(),
1172 )))
1173 }
1174}
1175
1176impl InputCharacteristics {
1178 pub fn new(size: usize, datatype: String) -> Self {
1180 Self {
1181 size,
1182 datatype,
1183 memory_layout: "contiguous".to_string(),
1184 access_pattern: "sequential".to_string(),
1185 }
1186 }
1187
1188 pub fn matrix(rows: usize, cols: usize) -> Self {
1190 Self {
1191 size: rows * cols,
1192 datatype: "f64".to_string(),
1193 memory_layout: "row_major".to_string(),
1194 access_pattern: "matrix".to_string(),
1195 }
1196 }
1197
1198 pub fn vector(length: usize) -> Self {
1200 Self {
1201 size: length,
1202 datatype: "f64".to_string(),
1203 memory_layout: "contiguous".to_string(),
1204 access_pattern: "sequential".to_string(),
1205 }
1206 }
1207}
1208
1209impl SystemState {
1210 pub fn new() -> Self {
1212 Self {
1213 cpu_utilization: 0.5, memory_utilization: 0.6, io_load: 0.1, network_load: 0.05, temperature: 65.0, }
1219 }
1220
1221 pub fn current() -> Self {
1223 Self::new()
1225 }
1226}
1227
1228impl Default for InputCharacteristics {
1229 fn default() -> Self {
1230 Self::new(1000, "f64".to_string())
1231 }
1232}
1233
1234impl Default for SystemState {
1235 fn default() -> Self {
1236 Self::new()
1237 }
1238}
1239
1240#[cfg(test)]
1241mod tests {
1242 use super::*;
1243
1244 fn make_contract(
1246 apiname: &str,
1247 module: &str,
1248 max_exec: Option<Duration>,
1249 max_memory: Option<usize>,
1250 thread_safe: bool,
1251 ) -> ApiContract {
1252 ApiContract {
1253 apiname: apiname.to_string(),
1254 module: module.to_string(),
1255 contract_hash: "test_hash".to_string(),
1256 created_at: SystemTime::now(),
1257 verification_status: VerificationStatus::NotVerified,
1258 stability: StabilityLevel::Stable,
1259 since_version: Version::new(1, 0, 0),
1260 performance: PerformanceContract {
1261 time_complexity: ComplexityBound::Linear,
1262 space_complexity: ComplexityBound::Constant,
1263 maxexecution_time: max_exec,
1264 min_throughput: None,
1265 memorybandwidth: None,
1266 },
1267 numerical: NumericalContract {
1268 precision: PrecisionGuarantee::MachinePrecision,
1269 stability: NumericalStability::Stable,
1270 input_domain: InputDomain {
1271 ranges: vec![],
1272 exclusions: vec![],
1273 special_values: SpecialValueHandling::Propagate,
1274 },
1275 output_range: OutputRange {
1276 bounds: None,
1277 monotonic: None,
1278 continuous: true,
1279 },
1280 },
1281 concurrency: ConcurrencyContract {
1282 thread_safety: if thread_safe {
1283 ThreadSafety::ThreadSafe
1284 } else {
1285 ThreadSafety::NotThreadSafe
1286 },
1287 atomicity: AtomicityGuarantee::OperationAtomic,
1288 lock_free: false,
1289 wait_free: false,
1290 memory_ordering: MemoryOrdering::AcquireRelease,
1291 },
1292 memory: MemoryContract {
1293 allocation_pattern: AllocationPattern::SingleAllocation,
1294 max_memory,
1295 alignment: None,
1296 locality: LocalityGuarantee::GoodSpatial,
1297 gc_behavior: GcBehavior::MinimalGc,
1298 },
1299 deprecation: None,
1300 }
1301 }
1302
1303 fn wait_for_verification(
1307 engine: &FormalVerificationEngine,
1308 apiname: &str,
1309 module: &str,
1310 ) -> VerificationStatus {
1311 let deadline = Instant::now() + Duration::from_secs(5);
1312 loop {
1313 let status = engine.get_verification_status(apiname, module);
1314 if status != VerificationStatus::InProgress {
1315 return status;
1316 }
1317 assert!(
1318 Instant::now() < deadline,
1319 "verification for {module}-{apiname} did not complete within the test timeout"
1320 );
1321 thread::sleep(Duration::from_millis(5));
1322 }
1323 }
1324
1325 #[test]
1326 fn test_formal_verification_engine() {
1327 let engine = FormalVerificationEngine::new();
1328 assert_eq!(engine.get_verification_coverage(), 0.0);
1329
1330 let contract = make_contract(
1331 "test_api",
1332 "test_module",
1333 Some(Duration::from_millis(100)),
1334 Some(1024),
1335 true,
1336 );
1337
1338 engine
1341 .verify_contract(&contract, None)
1342 .expect("Operation failed");
1343
1344 let status = wait_for_verification(&engine, "test_api", "test_module");
1345 assert_eq!(
1346 status,
1347 VerificationStatus::Failed,
1348 "verification with no executable probe must not fabricate Verified"
1349 );
1350
1351 let results = engine.get_all_results();
1352 let result = results
1353 .get("test_module-test_api")
1354 .expect("result recorded");
1355 assert!(!result.verified);
1356 assert!(result.counterexample.is_some());
1357 }
1358
1359 #[test]
1360 fn test_verify_contract_passes_with_probe_within_bounds() {
1361 let engine = FormalVerificationEngine::new();
1362 let contract = make_contract(
1363 "fast_api",
1364 "perf_module",
1365 Some(Duration::from_millis(50)),
1366 Some(1024),
1367 false,
1368 );
1369
1370 let probe = VerificationProbe {
1371 invoke: Box::new(|| (Duration::from_millis(1), Some(10))),
1372 iterations: 5,
1373 concurrency: 1,
1374 };
1375
1376 engine
1377 .verify_contract(&contract, Some(probe))
1378 .expect("start verification");
1379 let status = wait_for_verification(&engine, "fast_api", "perf_module");
1380 assert_eq!(status, VerificationStatus::Verified);
1381
1382 let results = engine.get_all_results();
1383 let result = results
1384 .get("perf_module-fast_api")
1385 .expect("result recorded");
1386 assert!(result.verified);
1387 assert!(result
1388 .checked_properties
1389 .contains(&"performance_bound".to_string()));
1390 assert!(result
1391 .checked_properties
1392 .contains(&"memory_bound".to_string()));
1393 }
1394
1395 #[test]
1396 fn test_verify_contract_detects_real_performance_violation() {
1397 let engine = FormalVerificationEngine::new();
1398 let contract = make_contract(
1399 "slow_api",
1400 "perf_module",
1401 Some(Duration::from_millis(10)),
1402 None,
1403 false,
1404 );
1405
1406 let probe = VerificationProbe {
1410 invoke: Box::new(|| (Duration::from_millis(200), None)),
1411 iterations: 1,
1412 concurrency: 1,
1413 };
1414
1415 engine
1416 .verify_contract(&contract, Some(probe))
1417 .expect("start verification");
1418 let status = wait_for_verification(&engine, "slow_api", "perf_module");
1419 assert_eq!(status, VerificationStatus::Failed);
1420
1421 let results = engine.get_all_results();
1422 let result = results
1423 .get("perf_module-slow_api")
1424 .expect("result recorded");
1425 assert!(!result.verified);
1426 let counterexample = result
1427 .counterexample
1428 .as_ref()
1429 .expect("counterexample present");
1430 assert!(
1431 counterexample.contains("performance_bound"),
1432 "got: {counterexample}"
1433 );
1434 }
1435
1436 #[test]
1437 fn test_verify_contract_detects_real_memory_violation() {
1438 let engine = FormalVerificationEngine::new();
1439 let contract = make_contract("greedy_api", "mem_module", None, Some(100), false);
1440
1441 let probe = VerificationProbe {
1442 invoke: Box::new(|| (Duration::from_micros(1), Some(500))),
1443 iterations: 1,
1444 concurrency: 1,
1445 };
1446
1447 engine
1448 .verify_contract(&contract, Some(probe))
1449 .expect("start verification");
1450 let status = wait_for_verification(&engine, "greedy_api", "mem_module");
1451 assert_eq!(status, VerificationStatus::Failed);
1452
1453 let results = engine.get_all_results();
1454 let result = results
1455 .get("mem_module-greedy_api")
1456 .expect("result recorded");
1457 let counterexample = result
1458 .counterexample
1459 .as_ref()
1460 .expect("counterexample present");
1461 assert!(
1462 counterexample.contains("memory_bound"),
1463 "got: {counterexample}"
1464 );
1465 }
1466
1467 #[test]
1468 fn test_verify_contract_concurrent_smoke_test_catches_real_panics() {
1469 let engine = FormalVerificationEngine::new();
1470 let contract = make_contract("racy_api", "concurrency_module", None, None, true);
1471
1472 let call_count = Arc::new(AtomicUsize::new(0));
1473 let call_count_probe = Arc::clone(&call_count);
1474 let probe = VerificationProbe {
1475 invoke: Box::new(move || {
1476 let n = call_count_probe.fetch_add(1, Ordering::SeqCst);
1477 assert!(n < 4 || n % 5 != 0, "simulated concurrency bug (call #{n})");
1486 (Duration::from_micros(1), None)
1487 }),
1488 iterations: 4,
1489 concurrency: 4,
1490 };
1491
1492 engine
1493 .verify_contract(&contract, Some(probe))
1494 .expect("start verification");
1495 let status = wait_for_verification(&engine, "racy_api", "concurrency_module");
1496 assert_eq!(status, VerificationStatus::Failed);
1497
1498 let results = engine.get_all_results();
1499 let result = results
1500 .get("concurrency_module-racy_api")
1501 .expect("result recorded");
1502 let counterexample = result
1503 .counterexample
1504 .as_ref()
1505 .expect("counterexample present");
1506 assert!(
1507 counterexample.contains("thread_safety"),
1508 "got: {counterexample}"
1509 );
1510 }
1511
1512 #[test]
1513 fn test_verify_contract_concurrent_smoke_test_passes_when_actually_safe() {
1514 let engine = FormalVerificationEngine::new();
1515 let contract = make_contract("safe_api", "concurrency_module2", None, None, true);
1516
1517 let probe = VerificationProbe {
1518 invoke: Box::new(|| (Duration::from_micros(1), None)),
1519 iterations: 4,
1520 concurrency: 4,
1521 };
1522
1523 engine
1524 .verify_contract(&contract, Some(probe))
1525 .expect("start verification");
1526 let status = wait_for_verification(&engine, "safe_api", "concurrency_module2");
1527 assert_eq!(status, VerificationStatus::Verified);
1528 }
1529
1530 #[test]
1538 fn test_verify_contract_probe_panic_during_sequential_pass_reports_failure_not_hang() {
1539 let engine = FormalVerificationEngine::new();
1540 let contract = make_contract(
1541 "panicky_api",
1542 "panic_module",
1543 Some(Duration::from_millis(50)),
1544 None,
1545 false,
1546 );
1547
1548 let probe = VerificationProbe {
1549 invoke: Box::new(|| panic!("probe always panics")),
1550 iterations: 1,
1551 concurrency: 1,
1552 };
1553
1554 engine
1555 .verify_contract(&contract, Some(probe))
1556 .expect("start verification");
1557 let status = wait_for_verification(&engine, "panicky_api", "panic_module");
1558 assert_eq!(
1559 status,
1560 VerificationStatus::Failed,
1561 "a probe that panics must resolve to Failed, not hang or fabricate Verified"
1562 );
1563
1564 let results = engine.get_all_results();
1565 let result = results
1566 .get("panic_module-panicky_api")
1567 .expect("result recorded");
1568 assert!(!result.verified);
1569 let counterexample = result
1570 .counterexample
1571 .as_ref()
1572 .expect("counterexample present");
1573 assert!(counterexample.contains("panicked"), "got: {counterexample}");
1574 }
1575
1576 #[test]
1577 fn test_runtime_contract_validator() {
1578 let (validator, receiver) = RuntimeContractValidator::new();
1579
1580 let stats = validator.get_statistics().expect("Operation failed");
1581 assert_eq!(stats.total_validations, 0);
1582 assert_eq!(stats.violations_detected, 0);
1583 assert_eq!(stats.success_rate, 1.0);
1584 }
1585
1586 #[test]
1587 fn test_performance_modeler() {
1588 let modeler = AdvancedPerformanceModeler::new();
1589
1590 let input_chars = InputCharacteristics::new(1000, "f64".to_string());
1591 let system_state = SystemState::new();
1592 let performance = PerformanceMetrics {
1593 operation_times: std::collections::HashMap::new(),
1594 strategy_success_rates: std::collections::HashMap::new(),
1595 memorybandwidth_utilization: 0.8,
1596 cache_hit_rate: 0.8,
1597 parallel_efficiency: 0.9,
1598 };
1599
1600 modeler.record_measurement(
1601 "test_api",
1602 input_chars.clone(),
1603 performance,
1604 system_state.clone(),
1605 );
1606
1607 assert_eq!(modeler.get_data_point_count("test_api"), 1);
1608 assert_eq!(
1609 modeler.get_training_status("test_api"),
1610 TrainingStatus::NotStarted
1611 );
1612 }
1613
1614 #[test]
1615 fn test_audit_trail() {
1616 let trail = ImmutableAuditTrail::new();
1617 assert!(trail.is_empty());
1618 assert!(trail.verify_integrity());
1619
1620 let data = AuditData::ContractRegistration("test::api".to_string());
1621 trail.add_record(data).expect("Operation failed");
1622
1623 assert_eq!(trail.len(), 1);
1624 assert!(trail.verify_integrity());
1625 }
1626
1627 #[test]
1628 fn test_input_characteristics() {
1629 let chars = InputCharacteristics::matrix(10, 10);
1630 assert_eq!(chars.size, 100);
1631 assert_eq!(chars.memory_layout, "row_major");
1632
1633 let vector_chars = InputCharacteristics::vector(50);
1634 assert_eq!(vector_chars.size, 50);
1635 assert_eq!(vector_chars.access_pattern, "sequential");
1636 }
1637
1638 #[test]
1639 fn test_system_state() {
1640 let state = SystemState::current();
1641 assert!(state.cpu_utilization >= 0.0 && state.cpu_utilization <= 1.0);
1642 assert!(state.memory_utilization >= 0.0 && state.memory_utilization <= 1.0);
1643 assert!(state.temperature > 0.0);
1644 }
1645}