1use crate::prelude::*;
49use serde::{Deserialize, Serialize};
50use std::collections::HashMap;
51use std::time::{Duration, Instant};
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct AudioLibraryInfo {
56 pub name: String,
58 pub current_version: String,
60 pub latest_version: String,
62 pub update_available: bool,
64 pub has_breaking_changes: bool,
66 pub security_vulnerabilities: Vec<SecurityVulnerability>,
68 pub performance_impact: PerformanceImpact,
70 pub update_priority: UpdatePriority,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct SecurityVulnerability {
77 pub id: String,
79 pub severity: SecuritySeverity,
81 pub description: String,
83 pub fixed_in_version: Option<String>,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
89pub enum SecuritySeverity {
90 Low,
92 Medium,
94 High,
96 Critical,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct PerformanceImpact {
103 pub performance_change_percent: f64,
105 pub memory_change_percent: f64,
107 pub compatibility_risk: CompatibilityRisk,
109 pub migration_effort: MigrationEffort,
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
115pub enum CompatibilityRisk {
116 Low,
118 Medium,
120 High,
122 Critical,
124}
125
126#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
128pub enum MigrationEffort {
129 Minimal,
131 Low,
133 Medium,
135 High,
137 Extensive,
139}
140
141#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
143pub enum UpdatePriority {
144 Optional,
146 Recommended,
148 Important,
150 Critical,
152 Security,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct LibraryVersionAnalysis {
159 pub total_libraries: usize,
161 pub outdated_libraries: Vec<AudioLibraryInfo>,
163 pub up_to_date_libraries: Vec<AudioLibraryInfo>,
165 pub libraries_with_security_issues: Vec<AudioLibraryInfo>,
167 pub overall_security_risk: u32,
169 pub performance_improvement_potential: f64,
171 pub recommended_update_order: Vec<String>,
173}
174
175#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct CompatibilityTestResult {
178 pub all_compatible: bool,
180 pub library_compatibility: HashMap<String, LibraryCompatibility>,
182 pub failed_tests: Vec<CompatibilityTest>,
184 pub performance_tests: Vec<PerformanceTest>,
186 pub api_compatibility: ApiCompatibilityAnalysis,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct LibraryCompatibility {
193 pub library_name: String,
195 pub current_compatible: bool,
197 pub target_compatible: bool,
199 pub breaking_changes: Vec<BreakingChange>,
201 pub migration_steps: Vec<MigrationStep>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct BreakingChange {
208 pub change_type: BreakingChangeType,
210 pub description: String,
212 pub affected_apis: Vec<String>,
214 pub migration_suggestion: String,
216}
217
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
220pub enum BreakingChangeType {
221 ApiRemoval,
223 ApiModification,
225 SignatureChange,
227 BehaviorChange,
229 DependencyUpdate,
231 MinimumVersionChange,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct MigrationStep {
238 pub description: String,
240 pub code_change: Option<CodeChange>,
242 pub automated: bool,
244 pub effort_minutes: u32,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct CodeChange {
251 pub file_pattern: String,
253 pub search_pattern: String,
255 pub replacement_pattern: String,
257 pub is_regex: bool,
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
263pub struct CompatibilityTest {
264 pub name: String,
266 pub passed: bool,
268 pub error_message: Option<String>,
270 pub duration_ms: u64,
272}
273
274#[derive(Debug, Clone, Serialize, Deserialize)]
276pub struct PerformanceTest {
277 pub name: String,
279 pub current_performance_ms: f64,
281 pub target_performance_ms: f64,
283 pub performance_change_percent: f64,
285 pub is_regression: bool,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
291pub struct ApiCompatibilityAnalysis {
292 pub removed_apis: Vec<String>,
294 pub modified_apis: Vec<String>,
296 pub new_apis: Vec<String>,
298 pub deprecated_apis: Vec<String>,
300 pub compatibility_score: u32,
302}
303
304pub struct AudioLibrariesUpdater {
306 current_versions: HashMap<String, String>,
308 latest_versions: HashMap<String, String>,
310 test_suite: CompatibilityTestSuite,
312 benchmarks: PerformanceBenchmarks,
314 migration_tools: MigrationTools,
316}
317
318impl AudioLibrariesUpdater {
319 pub async fn new() -> Result<Self> {
321 let current_versions = Self::detect_current_versions().await?;
322 let test_suite = CompatibilityTestSuite::new();
323 let benchmarks = PerformanceBenchmarks::new();
324 let migration_tools = MigrationTools::new();
325
326 Ok(Self {
327 current_versions,
328 latest_versions: HashMap::new(),
329 test_suite,
330 benchmarks,
331 migration_tools,
332 })
333 }
334
335 pub async fn analyze_current_versions(&mut self) -> Result<LibraryVersionAnalysis> {
337 let latest_versions = self.fetch_latest_versions().await?;
338 self.latest_versions = latest_versions;
339
340 let mut outdated_libraries = Vec::new();
341 let mut up_to_date_libraries = Vec::new();
342 let mut libraries_with_security_issues = Vec::new();
343
344 for (library_name, current_version) in &self.current_versions {
345 let latest_version = self
346 .latest_versions
347 .get(library_name)
348 .cloned()
349 .unwrap_or_else(|| current_version.clone());
350
351 let update_available = Self::version_needs_update(current_version, &latest_version);
352 let security_vulnerabilities = self
353 .check_security_vulnerabilities(library_name, current_version)
354 .await?;
355 let has_security_issues = !security_vulnerabilities.is_empty();
356
357 let performance_impact = self
358 .analyze_performance_impact(library_name, current_version, &latest_version)
359 .await?;
360 let update_priority = Self::determine_update_priority(
361 update_available,
362 has_security_issues,
363 &security_vulnerabilities,
364 &performance_impact,
365 );
366
367 let library_info = AudioLibraryInfo {
368 name: library_name.clone(),
369 current_version: current_version.clone(),
370 latest_version: latest_version.clone(),
371 update_available,
372 has_breaking_changes: self
373 .check_breaking_changes(library_name, current_version, &latest_version)
374 .await?,
375 security_vulnerabilities: security_vulnerabilities.clone(),
376 performance_impact,
377 update_priority,
378 };
379
380 if update_available {
381 outdated_libraries.push(library_info.clone());
382 } else {
383 up_to_date_libraries.push(library_info.clone());
384 }
385
386 if has_security_issues {
387 libraries_with_security_issues.push(library_info);
388 }
389 }
390
391 let overall_security_risk =
392 self.calculate_overall_security_risk(&libraries_with_security_issues);
393 let performance_improvement_potential =
394 self.calculate_performance_improvement_potential(&outdated_libraries);
395 let recommended_update_order = self.calculate_recommended_update_order(&outdated_libraries);
396
397 Ok(LibraryVersionAnalysis {
398 total_libraries: self.current_versions.len(),
399 outdated_libraries,
400 up_to_date_libraries,
401 libraries_with_security_issues,
402 overall_security_risk,
403 performance_improvement_potential,
404 recommended_update_order,
405 })
406 }
407
408 pub async fn test_compatibility(&self) -> Result<CompatibilityTestResult> {
410 let mut library_compatibility = HashMap::new();
411 let mut failed_tests = Vec::new();
412 let mut performance_tests = Vec::new();
413
414 for (library_name, current_version) in &self.current_versions {
415 let target_version = self
416 .latest_versions
417 .get(library_name)
418 .cloned()
419 .unwrap_or_else(|| current_version.clone());
420
421 if current_version != &target_version {
422 let compatibility = self
423 .test_library_compatibility(library_name, current_version, &target_version)
424 .await?;
425
426 if !compatibility.target_compatible {
427 failed_tests.extend(compatibility.breaking_changes.iter().map(|bc| {
428 CompatibilityTest {
429 name: format!(
430 "{library_name}: {description}",
431 description = bc.description
432 ),
433 passed: false,
434 error_message: Some(bc.migration_suggestion.clone()),
435 duration_ms: 0,
436 }
437 }));
438 }
439
440 let perf_test = self
442 .benchmarks
443 .run_performance_comparison(library_name, current_version, &target_version)
444 .await?;
445
446 performance_tests.push(perf_test);
447 library_compatibility.insert(library_name.clone(), compatibility);
448 }
449 }
450
451 let api_compatibility = self.analyze_api_compatibility().await?;
452 let all_compatible = failed_tests.is_empty();
453
454 Ok(CompatibilityTestResult {
455 all_compatible,
456 library_compatibility,
457 failed_tests,
458 performance_tests,
459 api_compatibility,
460 })
461 }
462
463 pub async fn apply_updates(&self) -> Result<UpdateResult> {
465 let mut update_results = Vec::new();
466
467 for (library_name, current_version) in &self.current_versions {
468 let target_version = self
469 .latest_versions
470 .get(library_name)
471 .cloned()
472 .unwrap_or_else(|| current_version.clone());
473
474 if current_version != &target_version {
475 let update_result = self
476 .update_single_library(library_name, &target_version)
477 .await?;
478 update_results.push(update_result);
479 }
480 }
481
482 let failed_updates: Vec<SingleUpdateResult> = update_results
483 .iter()
484 .filter(|r| !r.success)
485 .cloned()
486 .collect();
487 let successful_count = update_results.iter().filter(|r| r.success).count();
488
489 Ok(UpdateResult {
490 total_updates: update_results.len(),
491 successful_updates: successful_count,
492 failed_updates,
493 update_details: update_results,
494 })
495 }
496
497 pub async fn generate_migration_guide(&self) -> Result<MigrationGuide> {
499 let compatibility_result = self.test_compatibility().await?;
500 let mut migration_steps = Vec::new();
501
502 for (library_name, compatibility) in &compatibility_result.library_compatibility {
503 if !compatibility.target_compatible {
504 for step in &compatibility.migration_steps {
505 migration_steps.push(MigrationGuideStep {
506 library_name: library_name.clone(),
507 step_description: step.description.clone(),
508 code_changes: step
509 .code_change
510 .as_ref()
511 .map(|cc| vec![cc.clone()])
512 .unwrap_or_default(),
513 automated_migration: step.automated,
514 estimated_effort_minutes: step.effort_minutes,
515 priority: MigrationPriority::High,
516 });
517 }
518 }
519 }
520
521 Ok(MigrationGuide {
522 total_steps: migration_steps.len(),
523 automated_steps: migration_steps
524 .iter()
525 .filter(|s| s.automated_migration)
526 .count(),
527 manual_steps: migration_steps
528 .iter()
529 .filter(|s| !s.automated_migration)
530 .count(),
531 total_estimated_effort_hours: migration_steps
532 .iter()
533 .map(|s| s.estimated_effort_minutes)
534 .sum::<u32>() as f64
535 / 60.0,
536 migration_steps,
537 })
538 }
539
540 async fn detect_current_versions() -> Result<HashMap<String, String>> {
543 let mut versions = HashMap::new();
545
546 versions.insert("cpal".to_string(), "0.15.0".to_string());
548 versions.insert("dasp".to_string(), "0.11.0".to_string());
549 versions.insert("realfft".to_string(), "3.3.0".to_string());
550 versions.insert("rustfft".to_string(), "6.2.0".to_string());
551 versions.insert("hound".to_string(), "3.5.0".to_string());
552 versions.insert("symphonia".to_string(), "0.5.0".to_string());
553 versions.insert("claxon".to_string(), "0.4.0".to_string());
554 versions.insert("opus".to_string(), "0.3.0".to_string());
555 versions.insert("lewton".to_string(), "0.10.0".to_string());
556 versions.insert("minimp3".to_string(), "0.5.0".to_string());
557
558 Ok(versions)
559 }
560
561 async fn fetch_latest_versions(&self) -> Result<HashMap<String, String>> {
562 let mut latest_versions = HashMap::new();
564
565 latest_versions.insert("cpal".to_string(), "0.15.3".to_string());
567 latest_versions.insert("dasp".to_string(), "0.11.2".to_string());
568 latest_versions.insert("realfft".to_string(), "3.3.0".to_string()); latest_versions.insert("rustfft".to_string(), "6.2.0".to_string()); latest_versions.insert("hound".to_string(), "3.5.1".to_string());
571 latest_versions.insert("symphonia".to_string(), "0.5.4".to_string());
572 latest_versions.insert("claxon".to_string(), "0.4.3".to_string());
573 latest_versions.insert("opus".to_string(), "0.3.0".to_string()); latest_versions.insert("lewton".to_string(), "0.10.2".to_string());
575 latest_versions.insert("minimp3".to_string(), "0.5.1".to_string());
576
577 Ok(latest_versions)
578 }
579
580 fn version_needs_update(current: &str, latest: &str) -> bool {
581 current != latest
583 }
584
585 async fn check_security_vulnerabilities(
586 &self,
587 library_name: &str,
588 version: &str,
589 ) -> Result<Vec<SecurityVulnerability>> {
590 let mut vulnerabilities = Vec::new();
592
593 if library_name == "symphonia" && version == "0.5.0" {
595 vulnerabilities.push(SecurityVulnerability {
596 id: "RUSTSEC-2023-0001".to_string(),
597 severity: SecuritySeverity::Medium,
598 description: "Buffer overflow in audio decoder".to_string(),
599 fixed_in_version: Some("0.5.2".to_string()),
600 });
601 }
602
603 Ok(vulnerabilities)
604 }
605
606 async fn analyze_performance_impact(
607 &self,
608 library_name: &str,
609 current_version: &str,
610 target_version: &str,
611 ) -> Result<PerformanceImpact> {
612 let performance_change = match library_name {
614 "cpal" => 5.0, "dasp" => 10.0, "symphonia" => -2.0, _ => 0.0,
618 };
619
620 let compatibility_risk = if current_version == target_version {
621 CompatibilityRisk::Low
622 } else {
623 CompatibilityRisk::Medium
624 };
625
626 Ok(PerformanceImpact {
627 performance_change_percent: performance_change,
628 memory_change_percent: performance_change * 0.5, compatibility_risk,
630 migration_effort: MigrationEffort::Low,
631 })
632 }
633
634 async fn check_breaking_changes(
635 &self,
636 library_name: &str,
637 current_version: &str,
638 target_version: &str,
639 ) -> Result<bool> {
640 match library_name {
642 "symphonia" => {
643 Ok(current_version != target_version && target_version.starts_with("0.5"))
644 }
645 _ => Ok(false),
646 }
647 }
648
649 fn determine_update_priority(
650 update_available: bool,
651 has_security_issues: bool,
652 vulnerabilities: &[SecurityVulnerability],
653 performance_impact: &PerformanceImpact,
654 ) -> UpdatePriority {
655 if has_security_issues {
656 let max_severity = vulnerabilities
657 .iter()
658 .map(|v| v.severity)
659 .max()
660 .unwrap_or(SecuritySeverity::Low);
661
662 match max_severity {
663 SecuritySeverity::Critical => UpdatePriority::Security,
664 SecuritySeverity::High => UpdatePriority::Critical,
665 SecuritySeverity::Medium => UpdatePriority::Important,
666 SecuritySeverity::Low => UpdatePriority::Recommended,
667 }
668 } else if update_available {
669 if performance_impact.performance_change_percent > 10.0 {
670 UpdatePriority::Important
671 } else if performance_impact.performance_change_percent > 0.0 {
672 UpdatePriority::Recommended
673 } else {
674 UpdatePriority::Optional
675 }
676 } else {
677 UpdatePriority::Optional
678 }
679 }
680
681 fn calculate_overall_security_risk(&self, libraries_with_issues: &[AudioLibraryInfo]) -> u32 {
682 if libraries_with_issues.is_empty() {
683 return 0;
684 }
685
686 let total_risk: u32 = libraries_with_issues
687 .iter()
688 .flat_map(|lib| &lib.security_vulnerabilities)
689 .map(|vuln| match vuln.severity {
690 SecuritySeverity::Critical => 25,
691 SecuritySeverity::High => 15,
692 SecuritySeverity::Medium => 10,
693 SecuritySeverity::Low => 5,
694 })
695 .sum();
696
697 total_risk.min(100)
698 }
699
700 fn calculate_performance_improvement_potential(
701 &self,
702 outdated_libraries: &[AudioLibraryInfo],
703 ) -> f64 {
704 if outdated_libraries.is_empty() {
705 return 0.0;
706 }
707
708 let total_improvement: f64 = outdated_libraries
709 .iter()
710 .map(|lib| lib.performance_impact.performance_change_percent.max(0.0))
711 .sum();
712
713 total_improvement / outdated_libraries.len() as f64
714 }
715
716 fn calculate_recommended_update_order(
717 &self,
718 outdated_libraries: &[AudioLibraryInfo],
719 ) -> Vec<String> {
720 let mut libraries = outdated_libraries.to_vec();
721 libraries.sort_by_key(|lib| std::cmp::Reverse(lib.update_priority));
722 libraries.into_iter().map(|lib| lib.name).collect()
723 }
724
725 async fn test_library_compatibility(
726 &self,
727 library_name: &str,
728 current_version: &str,
729 target_version: &str,
730 ) -> Result<LibraryCompatibility> {
731 let breaking_changes = self
732 .detect_breaking_changes(library_name, current_version, target_version)
733 .await?;
734 let migration_steps = self
735 .generate_migration_steps(library_name, &breaking_changes)
736 .await?;
737
738 Ok(LibraryCompatibility {
739 library_name: library_name.to_string(),
740 current_compatible: true,
741 target_compatible: breaking_changes.is_empty(),
742 breaking_changes,
743 migration_steps,
744 })
745 }
746
747 async fn detect_breaking_changes(
748 &self,
749 library_name: &str,
750 _current_version: &str,
751 _target_version: &str,
752 ) -> Result<Vec<BreakingChange>> {
753 let mut changes = Vec::new();
754
755 if library_name == "symphonia" {
757 changes.push(BreakingChange {
758 change_type: BreakingChangeType::ApiModification,
759 description: "CodecParameters struct field changes".to_string(),
760 affected_apis: vec!["CodecParameters::new".to_string()],
761 migration_suggestion: "Update CodecParameters initialization".to_string(),
762 });
763 }
764
765 Ok(changes)
766 }
767
768 async fn generate_migration_steps(
769 &self,
770 _library_name: &str,
771 breaking_changes: &[BreakingChange],
772 ) -> Result<Vec<MigrationStep>> {
773 let mut steps = Vec::new();
774
775 for change in breaking_changes {
776 steps.push(MigrationStep {
777 description: format!("Migrate {description}", description = change.description),
778 code_change: Some(CodeChange {
779 file_pattern: "**/*.rs".to_string(),
780 search_pattern: "CodecParameters::new".to_string(),
781 replacement_pattern: "CodecParameters::new_with_defaults".to_string(),
782 is_regex: false,
783 }),
784 automated: true,
785 effort_minutes: 15,
786 });
787 }
788
789 Ok(steps)
790 }
791
792 async fn analyze_api_compatibility(&self) -> Result<ApiCompatibilityAnalysis> {
793 Ok(ApiCompatibilityAnalysis {
795 removed_apis: vec!["deprecated_function".to_string()],
796 modified_apis: vec!["CodecParameters::new".to_string()],
797 new_apis: vec!["improved_decoder".to_string()],
798 deprecated_apis: vec!["old_format_reader".to_string()],
799 compatibility_score: 85,
800 })
801 }
802
803 async fn update_single_library(
804 &self,
805 library_name: &str,
806 target_version: &str,
807 ) -> Result<SingleUpdateResult> {
808 tokio::time::sleep(Duration::from_millis(100)).await; Ok(SingleUpdateResult {
812 library_name: library_name.to_string(),
813 target_version: target_version.to_string(),
814 success: true,
815 error_message: None,
816 duration_ms: 100,
817 })
818 }
819}
820
821pub struct CompatibilityTestSuite {
823 }
825
826impl CompatibilityTestSuite {
827 fn new() -> Self {
829 Self {}
830 }
831}
832
833pub struct PerformanceBenchmarks {
835 }
837
838impl PerformanceBenchmarks {
839 fn new() -> Self {
841 Self {}
842 }
843
844 async fn run_performance_comparison(
846 &self,
847 library_name: &str,
848 current_version: &str,
849 target_version: &str,
850 ) -> Result<PerformanceTest> {
851 let current_perf = 100.0; let target_perf = match library_name {
854 "cpal" => 95.0, "dasp" => 90.0, _ => 100.0,
857 };
858
859 let change_percent = ((target_perf - current_perf) / current_perf) * 100.0;
860
861 Ok(PerformanceTest {
862 name: format!("{library_name} {current_version} -> {target_version}"),
863 current_performance_ms: current_perf,
864 target_performance_ms: target_perf,
865 performance_change_percent: change_percent,
866 is_regression: change_percent > 5.0,
867 })
868 }
869}
870
871pub struct MigrationTools {
873 }
875
876impl MigrationTools {
877 fn new() -> Self {
879 Self {}
880 }
881}
882
883#[derive(Debug, Clone, Serialize, Deserialize)]
885pub struct UpdateResult {
886 pub total_updates: usize,
888 pub successful_updates: usize,
890 pub failed_updates: Vec<SingleUpdateResult>,
892 pub update_details: Vec<SingleUpdateResult>,
894}
895
896#[derive(Debug, Clone, Serialize, Deserialize)]
898pub struct SingleUpdateResult {
899 pub library_name: String,
901 pub target_version: String,
903 pub success: bool,
905 pub error_message: Option<String>,
907 pub duration_ms: u64,
909}
910
911#[derive(Debug, Clone, Serialize, Deserialize)]
913pub struct MigrationGuide {
914 pub total_steps: usize,
916 pub automated_steps: usize,
918 pub manual_steps: usize,
920 pub total_estimated_effort_hours: f64,
922 pub migration_steps: Vec<MigrationGuideStep>,
924}
925
926#[derive(Debug, Clone, Serialize, Deserialize)]
928pub struct MigrationGuideStep {
929 pub library_name: String,
931 pub step_description: String,
933 pub code_changes: Vec<CodeChange>,
935 pub automated_migration: bool,
937 pub estimated_effort_minutes: u32,
939 pub priority: MigrationPriority,
941}
942
943#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
945pub enum MigrationPriority {
946 Low,
948 Medium,
950 High,
952 Critical,
954}
955
956#[cfg(test)]
957mod tests {
958 use super::*;
959
960 #[tokio::test]
961 async fn test_audio_libraries_updater_creation() {
962 let updater = AudioLibrariesUpdater::new().await;
963 assert!(updater.is_ok());
964 }
965
966 #[tokio::test]
967 async fn test_version_analysis() {
968 let mut updater = AudioLibrariesUpdater::new().await.unwrap();
969 let analysis = updater.analyze_current_versions().await.unwrap();
970
971 assert!(analysis.total_libraries > 0);
972 assert!(analysis.overall_security_risk <= 100);
973 }
974
975 #[tokio::test]
976 async fn test_compatibility_testing() {
977 let updater = AudioLibrariesUpdater::new().await.unwrap();
978 let compatibility = updater.test_compatibility().await.unwrap();
979
980 assert!(compatibility.api_compatibility.compatibility_score <= 100);
981 }
982
983 #[test]
984 fn test_version_needs_update() {
985 assert!(AudioLibrariesUpdater::version_needs_update(
986 "0.15.0", "0.15.3"
987 ));
988 assert!(!AudioLibrariesUpdater::version_needs_update(
989 "0.15.3", "0.15.3"
990 ));
991 }
992
993 #[test]
994 fn test_security_severity_ordering() {
995 assert!(SecuritySeverity::Critical > SecuritySeverity::High);
996 assert!(SecuritySeverity::High > SecuritySeverity::Medium);
997 assert!(SecuritySeverity::Medium > SecuritySeverity::Low);
998 }
999
1000 #[test]
1001 fn test_update_priority_ordering() {
1002 assert!(UpdatePriority::Security > UpdatePriority::Critical);
1003 assert!(UpdatePriority::Critical > UpdatePriority::Important);
1004 assert!(UpdatePriority::Important > UpdatePriority::Recommended);
1005 assert!(UpdatePriority::Recommended > UpdatePriority::Optional);
1006 }
1007
1008 #[test]
1009 fn test_compatibility_risk_levels() {
1010 let risks = vec![
1011 CompatibilityRisk::Low,
1012 CompatibilityRisk::Medium,
1013 CompatibilityRisk::High,
1014 CompatibilityRisk::Critical,
1015 ];
1016
1017 for i in 0..risks.len() - 1 {
1018 assert!(risks[i] < risks[i + 1]);
1019 }
1020 }
1021
1022 #[test]
1023 fn test_migration_effort_levels() {
1024 let efforts = vec![
1025 MigrationEffort::Minimal,
1026 MigrationEffort::Low,
1027 MigrationEffort::Medium,
1028 MigrationEffort::High,
1029 MigrationEffort::Extensive,
1030 ];
1031
1032 for i in 0..efforts.len() - 1 {
1033 assert!(efforts[i] < efforts[i + 1]);
1034 }
1035 }
1036
1037 #[tokio::test]
1038 async fn test_migration_guide_generation() {
1039 let updater = AudioLibrariesUpdater::new().await.unwrap();
1040 let guide = updater.generate_migration_guide().await.unwrap();
1041
1042 assert!(guide.total_estimated_effort_hours >= 0.0);
1043 assert_eq!(
1044 guide.total_steps,
1045 guide.automated_steps + guide.manual_steps
1046 );
1047 }
1048
1049 #[test]
1050 fn test_breaking_change_types() {
1051 let change_types = vec![
1052 BreakingChangeType::ApiRemoval,
1053 BreakingChangeType::ApiModification,
1054 BreakingChangeType::SignatureChange,
1055 BreakingChangeType::BehaviorChange,
1056 BreakingChangeType::DependencyUpdate,
1057 BreakingChangeType::MinimumVersionChange,
1058 ];
1059
1060 assert_eq!(change_types.len(), 6);
1061 }
1062
1063 #[test]
1064 fn test_audio_library_info_creation() {
1065 let library_info = AudioLibraryInfo {
1066 name: "test-lib".to_string(),
1067 current_version: "1.0.0".to_string(),
1068 latest_version: "1.0.1".to_string(),
1069 update_available: true,
1070 has_breaking_changes: false,
1071 security_vulnerabilities: vec![],
1072 performance_impact: PerformanceImpact {
1073 performance_change_percent: 5.0,
1074 memory_change_percent: 2.0,
1075 compatibility_risk: CompatibilityRisk::Low,
1076 migration_effort: MigrationEffort::Minimal,
1077 },
1078 update_priority: UpdatePriority::Recommended,
1079 };
1080
1081 assert_eq!(library_info.name, "test-lib");
1082 assert!(library_info.update_available);
1083 assert!(!library_info.has_breaking_changes);
1084 }
1085}