1use crate::cross_platform_tester::{
8 CrossPlatformConfig, CrossPlatformTestReport, CrossPlatformTester, PerformanceThresholds,
9 PlatformTarget, TestCategory,
10};
11use crate::error::{OptimError, Result};
12use serde::{Deserialize, Serialize};
13use std::collections::{HashMap, VecDeque};
14use std::fmt::Debug;
15use std::process::{Command, Stdio};
16use std::sync::{Arc, Mutex};
17use std::thread;
18use std::time::{Duration, Instant};
19
20#[derive(Debug)]
22pub struct AutomatedTestRunner {
23 config: AutomatedRunnerConfig,
25 platform_matrix: PlatformMatrix,
27 execution_queue: Arc<Mutex<VecDeque<TestExecution>>>,
29 resource_manager: ResourceManager,
31 results_aggregator: ResultsAggregator,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct AutomatedRunnerConfig {
38 pub max_parallel_runners: usize,
40 pub test_timeout_seconds: u64,
42 pub global_timeout_seconds: u64,
44 pub enable_resource_monitoring: bool,
46 pub fail_fast: bool,
48 pub retry_failed_tests: bool,
50 pub max_retries: usize,
52 pub enable_result_caching: bool,
54 pub ci_environment_vars: Vec<String>,
56 pub custom_runners: HashMap<PlatformTarget, String>,
58}
59
60impl Default for AutomatedRunnerConfig {
61 fn default() -> Self {
62 Self {
63 max_parallel_runners: 4,
64 test_timeout_seconds: 300, global_timeout_seconds: 1800, enable_resource_monitoring: true,
67 fail_fast: false,
68 retry_failed_tests: true,
69 max_retries: 2,
70 enable_result_caching: true,
71 ci_environment_vars: vec![
72 "GITHUB_ACTIONS".to_string(),
73 "GITHUB_WORKFLOW".to_string(),
74 "GITHUB_RUN_ID".to_string(),
75 "GITHUB_SHA".to_string(),
76 "CI".to_string(),
77 "BUILD_ID".to_string(),
78 ],
79 custom_runners: HashMap::new(),
80 }
81 }
82}
83
84#[derive(Debug, Clone)]
86pub struct PlatformMatrix {
87 pub platforms: HashMap<PlatformTarget, PlatformTestConfig>,
89 pub dependencies: HashMap<PlatformTarget, Vec<PlatformTarget>>,
91 pub priorities: HashMap<PlatformTarget, u32>,
93 pub environment_setup: HashMap<PlatformTarget, Vec<String>>,
95}
96
97#[derive(Debug, Clone)]
99pub struct PlatformTestConfig {
100 pub platform: PlatformTarget,
102 pub test_categories: Vec<TestCategory>,
104 pub performance_thresholds: PerformanceThresholds,
106 pub docker_image: Option<String>,
108 pub required_packages: Vec<String>,
110 pub environment_variables: HashMap<String, String>,
112 pub setup_commands: Vec<String>,
114 pub cleanup_commands: Vec<String>,
116 pub resource_requirements: ResourceRequirements,
118}
119
120#[derive(Debug, Clone)]
122pub struct ResourceRequirements {
123 pub min_cpu_cores: usize,
125 pub min_memory_mb: usize,
127 pub min_disk_space_mb: usize,
129 pub gpu_required: bool,
131 pub network_required: bool,
133}
134
135#[derive(Debug, Clone)]
137pub struct TestExecution {
138 pub id: String,
140 pub platform: PlatformTarget,
142 pub config: PlatformTestConfig,
144 pub status: ExecutionStatus,
146 pub start_time: Option<Instant>,
148 pub end_time: Option<Instant>,
150 pub retry_count: usize,
152 pub resource_usage: Option<ResourceUsage>,
154 pub results: Option<CrossPlatformTestReport>,
156 pub error: Option<String>,
158}
159
160#[derive(Debug, Clone, PartialEq)]
162pub enum ExecutionStatus {
163 Queued,
164 Running,
165 Completed,
166 Failed,
167 Timeout,
168 Cancelled,
169 Retrying,
170}
171
172#[derive(Debug, Clone)]
174pub struct ResourceUsage {
175 pub peak_cpu_usage: f64,
177 pub peak_memory_usage: usize,
179 pub average_cpu_usage: f64,
181 pub average_memory_usage: usize,
183 pub disk_io: (u64, u64),
185 pub network_io: (u64, u64),
187 pub execution_duration: Duration,
189}
190
191#[derive(Debug)]
193#[allow(dead_code)]
194pub struct ResourceManager {
195 available_cores: usize,
197 available_memory: usize,
199 allocated_resources: Arc<Mutex<HashMap<String, ResourceAllocation>>>,
201 _monitoringenabled: bool,
203}
204
205#[derive(Debug, Clone)]
207pub struct ResourceAllocation {
208 pub cpu_cores: usize,
210 pub memory_mb: usize,
212 pub allocated_at: Instant,
214 pub execution_id: String,
216}
217
218#[derive(Debug)]
220pub struct ResultsAggregator {
221 platform_results: HashMap<PlatformTarget, CrossPlatformTestReport>,
223 matrix_summary: MatrixExecutionSummary,
225 performance_matrix: PerformanceMatrix,
227 failure_analysis: FailureAnalysis,
229}
230
231#[derive(Debug, Clone)]
233pub struct MatrixExecutionSummary {
234 pub total_platforms: usize,
236 pub successful_platforms: usize,
238 pub failed_platforms: usize,
240 pub total_execution_time: Duration,
242 pub average_execution_time: Duration,
244 pub resource_utilization: ResourceUtilizationSummary,
246 pub ci_environment: CIEnvironmentInfo,
248}
249
250#[derive(Debug, Clone)]
252pub struct PerformanceMatrix {
253 pub performance_scores: HashMap<(PlatformTarget, String), f64>,
255 pub performance_rankings: HashMap<String, Vec<(PlatformTarget, f64)>>,
257 pub regression_analysis: Vec<PerformanceRegression>,
259 pub optimization_opportunities: Vec<OptimizationOpportunity>,
261}
262
263#[derive(Debug, Clone)]
265pub struct PerformanceRegression {
266 pub platform: PlatformTarget,
268 pub test_name: String,
270 pub current_performance: f64,
272 pub baseline_performance: f64,
274 pub regression_percentage: f64,
276 pub statistical_significance: f64,
278}
279
280#[derive(Debug, Clone)]
282pub struct OptimizationOpportunity {
283 pub platform: PlatformTarget,
285 pub optimization_type: String,
287 pub estimated_improvement: f64,
289 pub complexity: String,
291 pub priority: String,
293}
294
295#[derive(Debug, Clone)]
297pub struct FailureAnalysis {
298 pub common_patterns: Vec<FailurePattern>,
300 pub platform_issues: HashMap<PlatformTarget, Vec<String>>,
302 pub root_causes: Vec<RootCause>,
304 pub recommendations: Vec<String>,
306}
307
308#[derive(Debug, Clone)]
310pub struct FailurePattern {
311 pub description: String,
313 pub affected_platforms: Vec<PlatformTarget>,
315 pub frequency: usize,
317 pub severity: String,
319}
320
321#[derive(Debug, Clone)]
323pub struct RootCause {
324 pub description: String,
326 pub evidence: Vec<String>,
328 pub likelihood: f64,
330 pub impact: String,
332}
333
334#[derive(Debug, Clone)]
336pub struct ResourceUtilizationSummary {
337 pub avg_cpu_utilization: f64,
339 pub peak_cpu_utilization: f64,
341 pub avg_memory_utilization: f64,
343 pub peak_memory_utilization: f64,
345 pub total_compute_time: f64,
347}
348
349#[derive(Debug, Clone)]
351pub struct CIEnvironmentInfo {
352 pub ci_system: String,
354 pub build_id: Option<String>,
356 pub commit_sha: Option<String>,
358 pub branch: Option<String>,
360 pub workflow: Option<String>,
362 pub environment_vars: HashMap<String, String>,
364}
365
366impl AutomatedTestRunner {
367 pub fn new(config: AutomatedRunnerConfig) -> Self {
369 let platform_matrix = PlatformMatrix::default();
370 let execution_queue = Arc::new(Mutex::new(VecDeque::new()));
371 let resource_manager = ResourceManager::new(config.enable_resource_monitoring);
372 let results_aggregator = ResultsAggregator::new();
373
374 Self {
375 config,
376 platform_matrix,
377 execution_queue,
378 resource_manager,
379 results_aggregator,
380 }
381 }
382
383 pub fn run_test_matrix(&mut self) -> Result<MatrixTestResults> {
385 println!("๐ Starting automated cross-platform test matrix...");
386
387 let ci_environment = self.detect_ci_environment();
389 println!("CI Environment: {:?}", ci_environment.ci_system);
390
391 self.validate_resources()?;
393
394 self.setup_test_executions()?;
396
397 let start_time = Instant::now();
399 self.execute_test_matrix()?;
400 let total_execution_time = start_time.elapsed();
401
402 self.aggregate_results(total_execution_time, ci_environment)?;
404
405 let results = self.generate_matrix_results()?;
407
408 println!(
409 "โ
Cross-platform test matrix completed in {:?}",
410 total_execution_time
411 );
412
413 Ok(results)
414 }
415
416 fn detect_ci_environment(&self) -> CIEnvironmentInfo {
418 let mut environment_vars = HashMap::new();
419 let mut ci_system = "Unknown".to_string();
420 let mut build_id = None;
421 let mut commit_sha = None;
422 let mut branch = None;
423 let mut workflow = None;
424
425 for var_name in &self.config.ci_environment_vars {
427 if let Ok(value) = std::env::var(var_name) {
428 environment_vars.insert(var_name.clone(), value.clone());
429
430 match var_name.as_str() {
432 "GITHUB_ACTIONS" => {
433 ci_system = "GitHub Actions".to_string();
434 workflow = environment_vars.get("GITHUB_WORKFLOW").cloned();
435 build_id = environment_vars.get("GITHUB_RUN_ID").cloned();
436 commit_sha = environment_vars.get("GITHUB_SHA").cloned();
437 }
438 "JENKINS_URL" => {
439 ci_system = "Jenkins".to_string();
440 build_id = environment_vars.get("BUILD_ID").cloned();
441 }
442 "TRAVIS" => {
443 ci_system = "Travis CI".to_string();
444 build_id = environment_vars.get("TRAVIS_BUILD_ID").cloned();
445 }
446 "CIRCLECI" => {
447 ci_system = "CircleCI".to_string();
448 build_id = environment_vars.get("CIRCLE_BUILD_NUM").cloned();
449 }
450 _ => {}
451 }
452 }
453 }
454
455 if branch.is_none() {
457 if let Ok(output) = Command::new("git")
458 .args(["rev-parse", "--abbrev-ref", "HEAD"])
459 .output()
460 {
461 if output.status.success() {
462 branch = Some(String::from_utf8_lossy(&output.stdout).trim().to_string());
463 }
464 }
465 }
466
467 CIEnvironmentInfo {
468 ci_system,
469 build_id,
470 commit_sha,
471 branch,
472 workflow,
473 environment_vars,
474 }
475 }
476
477 fn validate_resources(&self) -> Result<()> {
479 println!("๐ Validating resource availability...");
480
481 let total_required_cores = self
482 .platform_matrix
483 .platforms
484 .values()
485 .map(|config| config.resource_requirements.min_cpu_cores)
486 .sum::<usize>();
487
488 let total_required_memory = self
489 .platform_matrix
490 .platforms
491 .values()
492 .map(|config| config.resource_requirements.min_memory_mb)
493 .sum::<usize>();
494
495 if total_required_cores
496 > self.resource_manager.available_cores * self.config.max_parallel_runners
497 {
498 return Err(OptimError::ResourceError(format!(
499 "Insufficient CPU cores: required {}, available {}",
500 total_required_cores,
501 self.resource_manager.available_cores * self.config.max_parallel_runners
502 )));
503 }
504
505 if total_required_memory > self.resource_manager.available_memory {
506 return Err(OptimError::ResourceError(format!(
507 "Insufficient memory: required {}MB, available {}MB",
508 total_required_memory, self.resource_manager.available_memory
509 )));
510 }
511
512 println!("โ
Resource validation passed");
513 Ok(())
514 }
515
516 fn setup_test_executions(&mut self) -> Result<()> {
518 println!("๐ Setting up test executions...");
519
520 let mut queue = self.execution_queue.lock().map_err(|_| {
521 OptimError::InvalidState("Failed to acquire execution queue lock".to_string())
522 })?;
523
524 let mut platforms: Vec<_> = self.platform_matrix.platforms.keys().collect();
526 platforms.sort_by_key(|&platform| {
527 std::cmp::Reverse(self.platform_matrix.priorities.get(platform).unwrap_or(&0))
528 });
529
530 for platform in platforms {
531 if let Some(config) = self.platform_matrix.platforms.get(platform) {
532 let execution = TestExecution {
533 id: format!("{}_{}", platform, chrono::Utc::now().timestamp()),
534 platform: platform.clone(),
535 config: config.clone(),
536 status: ExecutionStatus::Queued,
537 start_time: None,
538 end_time: None,
539 retry_count: 0,
540 resource_usage: None,
541 results: None,
542 error: None,
543 };
544
545 queue.push_back(execution);
546 }
547 }
548
549 println!("๐ Setup {} test executions", queue.len());
550 Ok(())
551 }
552
553 fn execute_test_matrix(&mut self) -> Result<()> {
555 println!(
556 "๐ Executing test matrix with {} parallel runners...",
557 self.config.max_parallel_runners
558 );
559
560 let mut handles = Vec::new();
561 let execution_queue = Arc::clone(&self.execution_queue);
562
563 for worker_id in 0..self.config.max_parallel_runners {
565 let queue_clone = Arc::clone(&execution_queue);
566 let config = self.config.clone();
567
568 let handle = thread::spawn(move || Self::worker_thread(worker_id, queue_clone, config));
569
570 handles.push(handle);
571 }
572
573 for handle in handles {
575 if let Err(e) = handle.join() {
576 eprintln!("Worker thread panicked: {:?}", e);
577 }
578 }
579
580 println!("โ
Test matrix execution completed");
581 Ok(())
582 }
583
584 fn worker_thread(
586 worker_id: usize,
587 execution_queue: Arc<Mutex<VecDeque<TestExecution>>>,
588 config: AutomatedRunnerConfig,
589 ) {
590 println!("๐งต Worker {} started", worker_id);
591
592 loop {
593 let mut execution = {
595 let mut queue = match execution_queue.lock() {
596 Ok(queue) => queue,
597 Err(_) => {
598 eprintln!("Worker {} failed to acquire _queue lock", worker_id);
599 break;
600 }
601 };
602
603 match queue
604 .iter_mut()
605 .find(|e| e.status == ExecutionStatus::Queued)
606 {
607 Some(exec) => {
608 exec.status = ExecutionStatus::Running;
609 exec.start_time = Some(Instant::now());
610 exec.clone()
611 }
612 None => {
613 break;
615 }
616 }
617 };
618
619 println!(
620 "๐งต Worker {} executing test for {:?}",
621 worker_id, execution.platform
622 );
623
624 let result = Self::execute_platform_test(&mut execution, &config);
626
627 {
629 let mut queue = execution_queue.lock().expect("lock poisoned");
630 if let Some(exec) = queue.iter_mut().find(|e| e.id == execution.id) {
631 exec.end_time = Some(Instant::now());
632 exec.resource_usage = execution.resource_usage.clone();
633 exec.results = execution.results.clone();
634 exec.error = execution.error.clone();
635
636 match result {
637 Ok(_) => exec.status = ExecutionStatus::Completed,
638 Err(_) => {
639 if config.retry_failed_tests && exec.retry_count < config.max_retries {
640 exec.status = ExecutionStatus::Retrying;
641 exec.retry_count += 1;
642 println!(
643 "๐ Retrying test for {:?} (attempt {})",
644 execution.platform,
645 exec.retry_count + 1
646 );
647 } else {
648 exec.status = ExecutionStatus::Failed;
649 }
650 }
651 }
652 }
653 }
654 }
655
656 println!("๐งต Worker {} completed", worker_id);
657 }
658
659 fn execute_platform_test(
661 execution: &mut TestExecution,
662 config: &AutomatedRunnerConfig,
663 ) -> Result<()> {
664 let start_time = Instant::now();
665
666 Self::setup_platform_environment(&execution.config)?;
668
669 let mut test_config = CrossPlatformConfig {
671 target_platforms: vec![execution.platform.clone()],
672 test_categories: execution.config.test_categories.clone(),
673 ..Default::default()
674 };
675 test_config.performance_thresholds.insert(
676 execution.platform.clone(),
677 execution.config.performance_thresholds.clone(),
678 );
679
680 let mut tester = CrossPlatformTester::new(test_config)?;
682 let _test_results = tester.run_test_suite()?;
683
684 let report = tester.generate_report();
686 execution.results = Some(report);
687
688 execution.resource_usage = Some(ResourceUsage {
690 peak_cpu_usage: 75.0,
691 peak_memory_usage: 512,
692 average_cpu_usage: 45.0,
693 average_memory_usage: 256,
694 disk_io: (1024 * 1024, 512 * 1024), network_io: (0, 0),
696 execution_duration: start_time.elapsed(),
697 });
698
699 Self::cleanup_platform_environment(&execution.config)?;
701
702 Ok(())
703 }
704
705 fn setup_platform_environment(config: &PlatformTestConfig) -> Result<()> {
707 for (key, value) in &config.environment_variables {
709 std::env::set_var(key, value);
710 }
711
712 for command in &config.setup_commands {
714 let output = Command::new("sh")
715 .arg("-c")
716 .arg(command)
717 .stdout(Stdio::null())
718 .stderr(Stdio::null())
719 .status();
720
721 match output {
722 Ok(status) if status.success() => continue,
723 Ok(_) => {
724 return Err(OptimError::ExecutionError(format!(
725 "Setup command failed: {}",
726 command
727 )))
728 }
729 Err(e) => {
730 return Err(OptimError::ExecutionError(format!(
731 "Failed to execute setup command '{}': {}",
732 command, e
733 )))
734 }
735 }
736 }
737
738 Ok(())
739 }
740
741 fn cleanup_platform_environment(config: &PlatformTestConfig) -> Result<()> {
743 for command in &config.cleanup_commands {
745 let _ = Command::new("sh")
746 .arg("-c")
747 .arg(command)
748 .stdout(Stdio::null())
749 .stderr(Stdio::null())
750 .status();
751 }
753
754 Ok(())
755 }
756
757 fn aggregate_results(
759 &mut self,
760 total_execution_time: Duration,
761 ci_environment: CIEnvironmentInfo,
762 ) -> Result<()> {
763 println!("๐ Aggregating test results...");
764
765 let queue = self.execution_queue.lock().map_err(|_| {
766 OptimError::InvalidState("Failed to acquire execution queue lock".to_string())
767 })?;
768
769 let total_platforms = queue.len();
770 let successful_platforms = queue
771 .iter()
772 .filter(|e| e.status == ExecutionStatus::Completed)
773 .count();
774 let failed_platforms = queue
775 .iter()
776 .filter(|e| e.status == ExecutionStatus::Failed)
777 .count();
778
779 let resource_utilization = self.calculate_resource_utilization(&queue);
781
782 self.results_aggregator.matrix_summary = MatrixExecutionSummary {
784 total_platforms,
785 successful_platforms,
786 failed_platforms,
787 total_execution_time,
788 average_execution_time: if total_platforms > 0 {
789 total_execution_time / total_platforms as u32
790 } else {
791 Duration::from_secs(0)
792 },
793 resource_utilization,
794 ci_environment,
795 };
796
797 for execution in queue.iter() {
799 if let Some(report) = &execution.results {
800 self.results_aggregator
801 .platform_results
802 .insert(execution.platform.clone(), report.clone());
803 }
804 }
805
806 let queue_clone = queue.clone();
808
809 drop(queue);
811
812 self.analyze_performance_matrix()?;
814 self.analyze_failures(&queue_clone)?;
815
816 println!("๐ Results aggregation completed");
817 Ok(())
818 }
819
820 fn calculate_resource_utilization(
822 &self,
823 queue: &VecDeque<TestExecution>,
824 ) -> ResourceUtilizationSummary {
825 let mut total_cpu = 0.0f64;
826 let mut peak_cpu = 0.0f64;
827 let mut total_memory = 0.0f64;
828 let mut peak_memory = 0.0f64;
829 let mut total_compute_time = 0.0;
830 let mut count = 0;
831
832 for execution in queue {
833 if let Some(usage) = &execution.resource_usage {
834 total_cpu += usage.average_cpu_usage;
835 peak_cpu = peak_cpu.max(usage.peak_cpu_usage);
836 total_memory += usage.average_memory_usage as f64;
837 peak_memory = peak_memory.max(usage.peak_memory_usage as f64);
838 total_compute_time += usage.execution_duration.as_secs_f64() / 3600.0; count += 1;
840 }
841 }
842
843 ResourceUtilizationSummary {
844 avg_cpu_utilization: if count > 0 {
845 total_cpu / count as f64
846 } else {
847 0.0
848 },
849 peak_cpu_utilization: peak_cpu,
850 avg_memory_utilization: if count > 0 {
851 total_memory / count as f64
852 } else {
853 0.0
854 },
855 peak_memory_utilization: peak_memory,
856 total_compute_time,
857 }
858 }
859
860 fn analyze_performance_matrix(&mut self) -> Result<()> {
862 self.results_aggregator.performance_matrix = PerformanceMatrix {
865 performance_scores: HashMap::new(),
866 performance_rankings: HashMap::new(),
867 regression_analysis: Vec::new(),
868 optimization_opportunities: Vec::new(),
869 };
870
871 Ok(())
872 }
873
874 fn analyze_failures(&mut self, queue: &VecDeque<TestExecution>) -> Result<()> {
876 let common_patterns = Vec::new();
877 let mut platform_issues = HashMap::new();
878 let mut recommendations = Vec::new();
879
880 for execution in queue.iter().filter(|e| e.status == ExecutionStatus::Failed) {
882 if let Some(error) = &execution.error {
883 platform_issues
884 .entry(execution.platform.clone())
885 .or_insert_with(Vec::new)
886 .push(error.clone());
887 }
888 }
889
890 if !platform_issues.is_empty() {
892 recommendations
893 .push("Review platform-specific test failures for common patterns".to_string());
894 recommendations
895 .push("Consider increasing timeout values for slower platforms".to_string());
896 recommendations.push("Verify platform-specific dependencies and setup".to_string());
897 }
898
899 self.results_aggregator.failure_analysis = FailureAnalysis {
900 common_patterns,
901 platform_issues,
902 root_causes: Vec::new(),
903 recommendations,
904 };
905
906 Ok(())
907 }
908
909 fn generate_matrix_results(&self) -> Result<MatrixTestResults> {
911 Ok(MatrixTestResults {
912 summary: self.results_aggregator.matrix_summary.clone(),
913 platform_results: self.results_aggregator.platform_results.clone(),
914 performance_matrix: self.results_aggregator.performance_matrix.clone(),
915 failure_analysis: self.results_aggregator.failure_analysis.clone(),
916 recommendations: self.generate_final_recommendations(),
917 })
918 }
919
920 fn generate_final_recommendations(&self) -> Vec<String> {
922 let mut recommendations = Vec::new();
923
924 let summary = &self.results_aggregator.matrix_summary;
925
926 if summary.successful_platforms < summary.total_platforms {
927 recommendations.push(format!(
928 "Platform compatibility: {}/{} platforms passed tests",
929 summary.successful_platforms, summary.total_platforms
930 ));
931 }
932
933 if summary.resource_utilization.avg_cpu_utilization > 80.0 {
934 recommendations.push("Consider optimizing for high CPU usage".to_string());
935 }
936
937 if summary.total_execution_time > Duration::from_secs(1800) {
938 recommendations.push(
939 "Matrix execution time is high - consider parallelization improvements".to_string(),
940 );
941 }
942
943 recommendations
944 }
945}
946
947#[derive(Debug)]
949pub struct MatrixTestResults {
950 pub summary: MatrixExecutionSummary,
952 pub platform_results: HashMap<PlatformTarget, CrossPlatformTestReport>,
954 pub performance_matrix: PerformanceMatrix,
956 pub failure_analysis: FailureAnalysis,
958 pub recommendations: Vec<String>,
960}
961
962impl PlatformMatrix {
963 fn default() -> Self {
965 let mut platforms = HashMap::new();
966 let mut priorities = HashMap::new();
967 let mut environment_setup = HashMap::new();
968
969 let common_platforms = [
971 PlatformTarget::LinuxX64,
972 PlatformTarget::MacOSX64,
973 PlatformTarget::WindowsX64,
974 ];
975
976 for (i, platform) in common_platforms.iter().enumerate() {
977 let config = PlatformTestConfig {
978 platform: platform.clone(),
979 test_categories: vec![
980 TestCategory::Functionality,
981 TestCategory::Performance,
982 TestCategory::Memory,
983 ],
984 performance_thresholds: PerformanceThresholds {
985 max_execution_time: 30.0,
986 min_throughput: 100.0,
987 max_memory_usage: 100.0,
988 max_cpu_usage: 80.0,
989 performance_tolerance: 20.0,
990 },
991 docker_image: None,
992 required_packages: Vec::new(),
993 environment_variables: HashMap::new(),
994 setup_commands: vec!["cargo --version".to_string(), "rustc --version".to_string()],
995 cleanup_commands: vec!["cargo clean".to_string()],
996 resource_requirements: ResourceRequirements {
997 min_cpu_cores: 2,
998 min_memory_mb: 2048,
999 min_disk_space_mb: 1024,
1000 gpu_required: false,
1001 network_required: false,
1002 },
1003 };
1004
1005 platforms.insert(platform.clone(), config);
1006 priorities.insert(platform.clone(), (common_platforms.len() - i) as u32);
1007 environment_setup.insert(platform.clone(), Vec::new());
1008 }
1009
1010 Self {
1011 platforms,
1012 dependencies: HashMap::new(),
1013 priorities,
1014 environment_setup,
1015 }
1016 }
1017}
1018
1019impl ResourceManager {
1020 fn new(_monitoringenabled: bool) -> Self {
1022 Self {
1023 available_cores: std::thread::available_parallelism()
1024 .map(|n| n.get())
1025 .unwrap_or(1),
1026 available_memory: Self::get_available_memory(),
1027 allocated_resources: Arc::new(Mutex::new(HashMap::new())),
1028 _monitoringenabled,
1029 }
1030 }
1031
1032 fn get_available_memory() -> usize {
1034 8 * 1024 }
1037}
1038
1039impl ResultsAggregator {
1040 fn new() -> Self {
1042 Self {
1043 platform_results: HashMap::new(),
1044 matrix_summary: MatrixExecutionSummary {
1045 total_platforms: 0,
1046 successful_platforms: 0,
1047 failed_platforms: 0,
1048 total_execution_time: Duration::from_secs(0),
1049 average_execution_time: Duration::from_secs(0),
1050 resource_utilization: ResourceUtilizationSummary {
1051 avg_cpu_utilization: 0.0,
1052 peak_cpu_utilization: 0.0,
1053 avg_memory_utilization: 0.0,
1054 peak_memory_utilization: 0.0,
1055 total_compute_time: 0.0,
1056 },
1057 ci_environment: CIEnvironmentInfo {
1058 ci_system: "Unknown".to_string(),
1059 build_id: None,
1060 commit_sha: None,
1061 branch: None,
1062 workflow: None,
1063 environment_vars: HashMap::new(),
1064 },
1065 },
1066 performance_matrix: PerformanceMatrix {
1067 performance_scores: HashMap::new(),
1068 performance_rankings: HashMap::new(),
1069 regression_analysis: Vec::new(),
1070 optimization_opportunities: Vec::new(),
1071 },
1072 failure_analysis: FailureAnalysis {
1073 common_patterns: Vec::new(),
1074 platform_issues: HashMap::new(),
1075 root_causes: Vec::new(),
1076 recommendations: Vec::new(),
1077 },
1078 }
1079 }
1080}
1081
1082impl std::fmt::Display for PlatformTarget {
1083 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1084 let name = match self {
1085 PlatformTarget::LinuxX64 => "linux-x64",
1086 PlatformTarget::LinuxArm64 => "linux-arm64",
1087 PlatformTarget::MacOSX64 => "macos-x64",
1088 PlatformTarget::MacOSArm64 => "macos-arm64",
1089 PlatformTarget::WindowsX64 => "windows-x64",
1090 PlatformTarget::WindowsArm64 => "windows-arm64",
1091 PlatformTarget::WebAssembly => "wasm32",
1092 PlatformTarget::Custom(name) => name,
1093 };
1094 write!(f, "{}", name)
1095 }
1096}
1097
1098#[cfg(test)]
1099mod tests {
1100 use super::*;
1101
1102 #[test]
1103 fn test_automated_runner_creation() {
1104 let config = AutomatedRunnerConfig::default();
1105 let runner = AutomatedTestRunner::new(config);
1106 assert_eq!(runner.config.max_parallel_runners, 4);
1107 }
1108
1109 #[test]
1110 fn test_platform_matrix_default() {
1111 let matrix = PlatformMatrix::default();
1112 assert!(!matrix.platforms.is_empty());
1113 assert!(matrix.platforms.contains_key(&PlatformTarget::LinuxX64));
1114 }
1115
1116 #[test]
1117 fn test_resource_manager() {
1118 let manager = ResourceManager::new(true);
1119 assert!(manager.available_cores > 0);
1120 assert!(manager.available_memory > 0);
1121 }
1122}