1use super::core_traits::Plugin;
8use super::security::{DigitalSignature, Permission, PublisherInfo, SecurityPolicy};
9use super::types_config::{
10 PluginCapability, PluginCategory, PluginConfig, PluginMetadata, PluginParameter,
11};
12use super::validation::{PluginManifest, PluginValidator, ValidationReport};
13use crate::error::Result;
14use std::any::{Any, TypeId};
15use std::collections::HashMap;
16use std::time::{Duration, Instant, SystemTime};
17
18#[derive(Debug, Clone)]
52pub struct MockPlugin {
53 pub id: String,
55 pub metadata: PluginMetadata,
57 pub config: Option<PluginConfig>,
59 pub initialized: bool,
61 pub initialization_error: Option<String>,
63 pub validation_error: Option<String>,
65 pub cleanup_error: Option<String>,
67 pub call_counts: HashMap<String, usize>,
69 pub artificial_delays: HashMap<String, Duration>,
71}
72
73impl MockPlugin {
74 pub fn new(id: &str) -> Self {
89 Self {
90 id: id.to_string(),
91 metadata: PluginMetadata {
92 name: format!("Mock Plugin {}", id),
93 version: "1.0.0".to_string(),
94 description: "A mock plugin for testing".to_string(),
95 author: "Test Framework".to_string(),
96 category: PluginCategory::Algorithm,
97 supported_types: vec![TypeId::of::<f64>(), TypeId::of::<f32>()],
98 dependencies: Vec::new(),
99 capabilities: vec![PluginCapability::Parallel],
100 min_sdk_version: "0.1.0".to_string(),
101 },
102 config: None,
103 initialized: false,
104 initialization_error: None,
105 validation_error: None,
106 cleanup_error: None,
107 call_counts: HashMap::new(),
108 artificial_delays: HashMap::new(),
109 }
110 }
111
112 pub fn for_category(id: &str, category: PluginCategory) -> Self {
128 let mut mock = Self::new(id);
129 mock.metadata.category = category.clone();
130 mock.metadata.name = format!("Mock {} Plugin", Self::category_name(&category));
131 mock
132 }
133
134 pub fn add_supported_type(&mut self, type_id: TypeId) {
140 if !self.metadata.supported_types.contains(&type_id) {
141 self.metadata.supported_types.push(type_id);
142 }
143 }
144
145 pub fn remove_supported_type(&mut self, type_id: TypeId) {
151 self.metadata.supported_types.retain(|&t| t != type_id);
152 }
153
154 pub fn set_initialization_error(&mut self, error: Option<&str>) {
160 self.initialization_error = error.map(|s| s.to_string());
161 }
162
163 pub fn set_validation_error(&mut self, error: Option<&str>) {
169 self.validation_error = error.map(|s| s.to_string());
170 }
171
172 pub fn set_cleanup_error(&mut self, error: Option<&str>) {
178 self.cleanup_error = error.map(|s| s.to_string());
179 }
180
181 pub fn add_artificial_delay(&mut self, method: &str, delay: Duration) {
188 self.artificial_delays.insert(method.to_string(), delay);
189 }
190
191 pub fn get_call_count(&self, method: &str) -> usize {
201 self.call_counts.get(method).copied().unwrap_or(0)
202 }
203
204 pub fn reset_call_counts(&mut self) {
206 self.call_counts.clear();
207 }
208
209 fn record_call(&mut self, method: &str) {
211 *self.call_counts.entry(method.to_string()).or_insert(0) += 1;
212
213 if let Some(delay) = self.artificial_delays.get(method) {
214 std::thread::sleep(*delay);
215 }
216 }
217
218 fn category_name(category: &PluginCategory) -> &str {
220 match category {
221 PluginCategory::Algorithm => "Algorithm",
222 PluginCategory::Transformer => "Transformer",
223 PluginCategory::DataProcessor => "DataProcessor",
224 PluginCategory::Evaluator => "Evaluator",
225 PluginCategory::Visualizer => "Visualizer",
226 PluginCategory::Custom(name) => name,
227 }
228 }
229}
230
231impl Plugin for MockPlugin {
232 fn id(&self) -> &str {
233 &self.id
234 }
235
236 fn metadata(&self) -> PluginMetadata {
237 self.metadata.clone()
238 }
239
240 fn initialize(&mut self, config: &PluginConfig) -> Result<()> {
241 self.record_call("initialize");
242
243 if let Some(ref error) = self.initialization_error {
244 return Err(crate::error::SklearsError::InvalidOperation(error.clone()));
245 }
246
247 self.config = Some(config.clone());
248 self.initialized = true;
249 Ok(())
250 }
251
252 fn is_compatible(&self, input_type: TypeId) -> bool {
253 self.metadata.supported_types.contains(&input_type)
254 }
255
256 fn as_any(&self) -> &dyn Any {
257 self
258 }
259
260 fn as_any_mut(&mut self) -> &mut dyn Any {
261 self
262 }
263
264 fn validate_config(&self, _config: &PluginConfig) -> Result<()> {
265 if let Some(ref error) = self.validation_error {
266 return Err(crate::error::SklearsError::InvalidOperation(error.clone()));
267 }
268 Ok(())
269 }
270
271 fn cleanup(&mut self) -> Result<()> {
272 self.record_call("cleanup");
273
274 if let Some(ref error) = self.cleanup_error {
275 return Err(crate::error::SklearsError::InvalidOperation(error.clone()));
276 }
277
278 self.initialized = false;
279 self.config = None;
280 Ok(())
281 }
282}
283
284#[derive(Debug)]
302pub struct PluginTestFixture {
303 pub security_policy: SecurityPolicy,
305 pub plugins: Vec<Box<dyn Plugin>>,
307 pub manifests: Vec<PluginManifest>,
309}
310
311impl PluginTestFixture {
312 pub fn new() -> Self {
314 Self {
315 security_policy: SecurityPolicy::permissive(),
316 plugins: Vec::new(),
317 manifests: Vec::new(),
318 }
319 }
320
321 pub fn with_strict_security() -> Self {
323 Self {
324 security_policy: SecurityPolicy::strict(),
325 plugins: Vec::new(),
326 manifests: Vec::new(),
327 }
328 }
329
330 pub fn create_test_plugins(&self) -> Vec<Box<dyn Plugin>> {
336 vec![
337 Box::new(MockPlugin::for_category(
338 "linear_regression",
339 PluginCategory::Algorithm,
340 )),
341 Box::new(MockPlugin::for_category(
342 "standard_scaler",
343 PluginCategory::Transformer,
344 )),
345 Box::new(MockPlugin::for_category(
346 "csv_loader",
347 PluginCategory::DataProcessor,
348 )),
349 Box::new(MockPlugin::for_category(
350 "accuracy_metric",
351 PluginCategory::Evaluator,
352 )),
353 Box::new(MockPlugin::for_category(
354 "plot_generator",
355 PluginCategory::Visualizer,
356 )),
357 ]
358 }
359
360 pub fn create_test_manifests(&self) -> Vec<PluginManifest> {
366 vec![
367 self.create_safe_manifest(),
368 self.create_risky_manifest(),
369 self.create_invalid_manifest(),
370 self.create_signed_manifest(),
371 ]
372 }
373
374 fn create_safe_manifest(&self) -> PluginManifest {
376 PluginManifest {
377 metadata: PluginMetadata {
378 name: "SafePlugin".to_string(),
379 version: "1.0.0".to_string(),
380 description: "A safe test plugin".to_string(),
381 author: "Test Suite".to_string(),
382 category: PluginCategory::Algorithm,
383 supported_types: vec![TypeId::of::<f64>()],
384 dependencies: Vec::new(),
385 capabilities: vec![PluginCapability::Parallel],
386 min_sdk_version: "0.1.0".to_string(),
387 },
388 permissions: vec![Permission::FileSystemRead, Permission::GpuAccess],
389 api_usage: None,
390 contains_unsafe_code: false,
391 dependencies: Vec::new(),
392 code_analysis: None,
393 signature: None,
394 content_hash: "safe_hash_123".to_string(),
395 publisher: PublisherInfo {
396 name: "Trusted Publisher".to_string(),
397 email: "trusted@example.com".to_string(),
398 website: Some("https://trusted.example.com".to_string()),
399 verified: true,
400 trust_score: 9,
401 },
402 marketplace: super::validation::MarketplaceInfo {
403 url: "https://marketplace.example.com/safe-plugin".to_string(),
404 downloads: 1000,
405 rating: 4.5,
406 reviews: 50,
407 last_updated: "2024-01-15".to_string(),
408 },
409 }
410 }
411
412 fn create_risky_manifest(&self) -> PluginManifest {
414 PluginManifest {
415 metadata: PluginMetadata {
416 name: "RiskyPlugin".to_string(),
417 version: "1.0.0".to_string(),
418 description: "A risky test plugin".to_string(),
419 author: "Unknown".to_string(),
420 category: PluginCategory::Algorithm,
421 supported_types: vec![TypeId::of::<f64>()],
422 dependencies: Vec::new(),
423 capabilities: Vec::new(),
424 min_sdk_version: "0.1.0".to_string(),
425 },
426 permissions: vec![
427 Permission::FileSystemWrite,
428 Permission::NetworkAccess,
429 Permission::SystemCommands,
430 ],
431 api_usage: Some(super::validation::ApiUsageInfo {
432 calls: vec!["std::process::Command".to_string()],
433 network_access: vec!["http://api.example.com".to_string()],
434 filesystem_access: vec!["/tmp/".to_string()],
435 }),
436 contains_unsafe_code: true,
437 dependencies: Vec::new(),
438 code_analysis: Some(super::validation::CodeAnalysisInfo {
439 cyclomatic_complexity: 25,
440 suspicious_patterns: vec!["eval".to_string()],
441 potential_memory_issues: 2,
442 lines_of_code: 1500,
443 test_coverage: 45.0,
444 }),
445 signature: None,
446 content_hash: "risky_hash_456".to_string(),
447 publisher: PublisherInfo {
448 name: "Unknown Publisher".to_string(),
449 email: "unknown@example.com".to_string(),
450 website: None,
451 verified: false,
452 trust_score: 2,
453 },
454 marketplace: super::validation::MarketplaceInfo {
455 url: "https://marketplace.example.com/risky-plugin".to_string(),
456 downloads: 10,
457 rating: 2.0,
458 reviews: 5,
459 last_updated: "2023-06-01".to_string(),
460 },
461 }
462 }
463
464 fn create_invalid_manifest(&self) -> PluginManifest {
466 PluginManifest {
467 metadata: PluginMetadata {
468 name: "".to_string(), version: "invalid".to_string(), description: "Invalid plugin".to_string(),
471 author: "".to_string(), category: PluginCategory::Algorithm,
473 supported_types: Vec::new(),
474 dependencies: Vec::new(),
475 capabilities: Vec::new(),
476 min_sdk_version: "999.0.0".to_string(), },
478 permissions: vec![Permission::Custom("invalid_permission".to_string())],
479 api_usage: None,
480 contains_unsafe_code: true,
481 dependencies: Vec::new(),
482 code_analysis: None,
483 signature: None,
484 content_hash: "".to_string(), publisher: PublisherInfo {
486 name: "".to_string(),
487 email: "invalid-email".to_string(), website: None,
489 verified: false,
490 trust_score: 15, },
492 marketplace: super::validation::MarketplaceInfo {
493 url: "".to_string(),
494 downloads: 0,
495 rating: 0.0,
496 reviews: 0,
497 last_updated: "".to_string(),
498 },
499 }
500 }
501
502 fn create_signed_manifest(&self) -> PluginManifest {
504 let mut manifest = self.create_safe_manifest();
505 manifest.signature = Some(DigitalSignature {
506 algorithm: "RSA-SHA256".to_string(),
507 signature: vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0],
508 public_key_fingerprint: "SHA256:test_fingerprint_123".to_string(),
509 timestamp: SystemTime::now(),
510 signer_certificate: Some(
511 "-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----".to_string(),
512 ),
513 });
514 manifest
515 }
516
517 pub fn create_test_configs(&self) -> Vec<PluginConfig> {
523 vec![
524 self.create_minimal_config(),
525 self.create_full_config(),
526 self.create_invalid_config(),
527 ]
528 }
529
530 fn create_minimal_config(&self) -> PluginConfig {
532 PluginConfig::default()
533 }
534
535 fn create_full_config(&self) -> PluginConfig {
537 let mut config = PluginConfig::default();
538
539 config
541 .parameters
542 .insert("learning_rate".to_string(), PluginParameter::Float(0.01));
543 config
544 .parameters
545 .insert("max_iterations".to_string(), PluginParameter::Int(1000));
546 config
547 .parameters
548 .insert("use_bias".to_string(), PluginParameter::Bool(true));
549 config.parameters.insert(
550 "algorithm".to_string(),
551 PluginParameter::String("adam".to_string()),
552 );
553 config.parameters.insert(
554 "layer_sizes".to_string(),
555 PluginParameter::IntArray(vec![100, 50, 10]),
556 );
557 config.parameters.insert(
558 "dropout_rates".to_string(),
559 PluginParameter::FloatArray(vec![0.2, 0.3, 0.5]),
560 );
561
562 config.runtime_settings.num_threads = Some(4);
564 config.runtime_settings.memory_limit = Some(1024 * 1024 * 1024); config.runtime_settings.timeout_ms = Some(30000); config.runtime_settings.use_gpu = true;
567
568 config
570 .plugin_settings
571 .insert("backend".to_string(), "cuda".to_string());
572 config
573 .plugin_settings
574 .insert("precision".to_string(), "float32".to_string());
575
576 config
577 }
578
579 fn create_invalid_config(&self) -> PluginConfig {
581 let mut config = PluginConfig::default();
582
583 config.runtime_settings.num_threads = Some(0); config.runtime_settings.timeout_ms = Some(0); config.runtime_settings.memory_limit = Some(0); config
589 }
590}
591
592impl Default for PluginTestFixture {
593 fn default() -> Self {
594 Self::new()
595 }
596}
597
598#[derive(Debug)]
615pub struct PluginPerformanceTester {
616 pub test_configs: Vec<PluginConfig>,
618 pub max_duration: Duration,
620 pub memory_baseline: usize,
622}
623
624impl PluginPerformanceTester {
625 pub fn new() -> Self {
627 Self {
628 test_configs: Vec::new(),
629 max_duration: Duration::from_secs(10),
630 memory_baseline: 0,
631 }
632 }
633
634 pub fn with_timeout(max_duration: Duration) -> Self {
640 Self {
641 test_configs: Vec::new(),
642 max_duration,
643 memory_baseline: 0,
644 }
645 }
646
647 pub fn benchmark_initialization(&mut self, plugin: &mut dyn Plugin) -> PerformanceResult {
657 let config = PluginConfig::default();
658 let start = Instant::now();
659 let memory_start = self.get_memory_usage();
660
661 let result = plugin.initialize(&config);
662
663 let duration = start.elapsed();
664 let memory_end = self.get_memory_usage();
665 let memory_used = memory_end.saturating_sub(memory_start);
666
667 PerformanceResult {
668 operation: "initialization".to_string(),
669 duration,
670 memory_used,
671 success: result.is_ok(),
672 error: result.err().map(|e| e.to_string()),
673 within_limits: duration <= self.max_duration,
674 }
675 }
676
677 pub fn benchmark_validation(
688 &self,
689 plugin: &dyn Plugin,
690 config: &PluginConfig,
691 ) -> PerformanceResult {
692 let start = Instant::now();
693 let memory_start = self.get_memory_usage();
694
695 let result = plugin.validate_config(config);
696
697 let duration = start.elapsed();
698 let memory_end = self.get_memory_usage();
699 let memory_used = memory_end.saturating_sub(memory_start);
700
701 PerformanceResult {
702 operation: "validation".to_string(),
703 duration,
704 memory_used,
705 success: result.is_ok(),
706 error: result.err().map(|e| e.to_string()),
707 within_limits: duration <= self.max_duration,
708 }
709 }
710
711 pub fn run_performance_suite(&mut self, plugin: &mut dyn Plugin) -> Vec<PerformanceResult> {
721 let mut results = Vec::new();
722
723 results.push(self.benchmark_initialization(plugin));
725
726 let fixture = PluginTestFixture::new();
728 for config in fixture.create_test_configs() {
729 results.push(self.benchmark_validation(plugin, &config));
730 }
731
732 results.push(self.benchmark_cleanup(plugin));
734
735 results
736 }
737
738 fn benchmark_cleanup(&self, plugin: &mut dyn Plugin) -> PerformanceResult {
740 let start = Instant::now();
741 let memory_start = self.get_memory_usage();
742
743 let result = plugin.cleanup();
744
745 let duration = start.elapsed();
746 let memory_end = self.get_memory_usage();
747 let memory_used = memory_end.saturating_sub(memory_start);
748
749 PerformanceResult {
750 operation: "cleanup".to_string(),
751 duration,
752 memory_used,
753 success: result.is_ok(),
754 error: result.err().map(|e| e.to_string()),
755 within_limits: duration <= self.max_duration,
756 }
757 }
758
759 fn get_memory_usage(&self) -> usize {
761 1024 * 1024 }
765}
766
767impl Default for PluginPerformanceTester {
768 fn default() -> Self {
769 Self::new()
770 }
771}
772
773#[derive(Debug, Clone)]
775pub struct PerformanceResult {
776 pub operation: String,
778 pub duration: Duration,
780 pub memory_used: usize,
782 pub success: bool,
784 pub error: Option<String>,
786 pub within_limits: bool,
788}
789
790impl PerformanceResult {
791 pub fn is_good_performance(&self) -> bool {
793 self.success && self.within_limits
794 }
795
796 pub fn performance_score(&self) -> u8 {
798 if !self.success {
799 return 0;
800 }
801
802 let time_score = if self.within_limits { 50 } else { 0 };
803 let memory_score = if self.memory_used < 10 * 1024 * 1024 {
804 50
805 } else {
806 25
807 }; (time_score + memory_score).min(100)
810 }
811}
812
813#[derive(Debug)]
831pub struct ValidationTestRunner {
832 validator: PluginValidator,
834 performance_tester: PluginPerformanceTester,
836 fixture: PluginTestFixture,
838}
839
840impl ValidationTestRunner {
841 pub fn new() -> Self {
843 Self {
844 validator: PluginValidator::new(),
845 performance_tester: PluginPerformanceTester::new(),
846 fixture: PluginTestFixture::new(),
847 }
848 }
849
850 pub fn with_strict_security() -> Self {
852 Self {
853 validator: PluginValidator::new(),
854 performance_tester: PluginPerformanceTester::new(),
855 fixture: PluginTestFixture::with_strict_security(),
856 }
857 }
858
859 pub fn run_validation_tests(
870 &self,
871 plugin: &dyn Plugin,
872 manifest: &PluginManifest,
873 ) -> ValidationReport {
874 self.validator
875 .validate_comprehensive(plugin, manifest)
876 .unwrap_or_else(|_| {
877 let mut report = ValidationReport::new();
878 report.add_error(super::validation::ValidationError::InvalidMetadata(
879 "Failed to run validation tests".to_string(),
880 ));
881 report
882 })
883 }
884
885 pub fn run_performance_tests(&mut self, plugin: &mut dyn Plugin) -> Vec<PerformanceResult> {
895 self.performance_tester.run_performance_suite(plugin)
896 }
897
898 pub fn run_compatibility_tests(&self, plugin: &dyn Plugin) -> CompatibilityTestResult {
908 let mut supported_types = Vec::new();
909 let mut unsupported_types = Vec::new();
910
911 let test_types = vec![
913 TypeId::of::<f32>(),
914 TypeId::of::<f64>(),
915 TypeId::of::<i32>(),
916 TypeId::of::<i64>(),
917 TypeId::of::<String>(),
918 ];
919
920 for type_id in test_types {
921 if plugin.is_compatible(type_id) {
922 supported_types.push(type_id);
923 } else {
924 unsupported_types.push(type_id);
925 }
926 }
927
928 let compatibility_score = (supported_types.len() as f32 / 5.0 * 100.0) as u8;
929
930 CompatibilityTestResult {
931 supported_types,
932 unsupported_types,
933 total_types_tested: 5,
934 compatibility_score,
935 }
936 }
937
938 pub fn create_test_fixture(&self) -> &PluginTestFixture {
940 &self.fixture
941 }
942
943 pub fn run_complete_test_suite(
954 &mut self,
955 plugin: &mut dyn Plugin,
956 manifest: &PluginManifest,
957 ) -> CompleteTestResult {
958 let validation_report = self.run_validation_tests(plugin, manifest);
959 let performance_results = self.run_performance_tests(plugin);
960 let compatibility_result = self.run_compatibility_tests(plugin);
961
962 let overall_score = self.calculate_overall_score(
963 &validation_report,
964 &performance_results,
965 &compatibility_result,
966 );
967
968 CompleteTestResult {
969 validation_report,
970 performance_results,
971 compatibility_result,
972 overall_score,
973 test_passed: overall_score >= 70, }
975 }
976
977 fn calculate_overall_score(
979 &self,
980 validation: &ValidationReport,
981 performance: &[PerformanceResult],
982 compatibility: &CompatibilityTestResult,
983 ) -> u8 {
984 let validation_score = if validation.has_errors() { 0 } else { 40 };
985
986 let avg_performance = if performance.is_empty() {
987 0
988 } else {
989 performance
990 .iter()
991 .map(|r| r.performance_score() as u32)
992 .sum::<u32>()
993 / performance.len() as u32
994 };
995 let performance_score = (avg_performance as f32 * 0.3) as u8;
996
997 let compatibility_score = (compatibility.compatibility_score as f32 * 0.3) as u8;
998
999 (validation_score + performance_score + compatibility_score).min(100)
1000 }
1001}
1002
1003impl Default for ValidationTestRunner {
1004 fn default() -> Self {
1005 Self::new()
1006 }
1007}
1008
1009#[derive(Debug, Clone)]
1011pub struct CompatibilityTestResult {
1012 pub supported_types: Vec<TypeId>,
1014 pub unsupported_types: Vec<TypeId>,
1016 pub total_types_tested: usize,
1018 pub compatibility_score: u8,
1020}
1021
1022#[derive(Debug)]
1024pub struct CompleteTestResult {
1025 pub validation_report: ValidationReport,
1027 pub performance_results: Vec<PerformanceResult>,
1029 pub compatibility_result: CompatibilityTestResult,
1031 pub overall_score: u8,
1033 pub test_passed: bool,
1035}
1036
1037impl CompleteTestResult {
1038 pub fn summary(&self) -> String {
1040 format!(
1041 "Plugin Test Summary:\n\
1042 - Validation: {} errors, {} warnings\n\
1043 - Performance: {}/{} operations within limits\n\
1044 - Compatibility: {:.1}% type support\n\
1045 - Overall Score: {}/100\n\
1046 - Result: {}",
1047 self.validation_report.errors.len(),
1048 self.validation_report.warnings.len(),
1049 self.performance_results
1050 .iter()
1051 .filter(|r| r.within_limits)
1052 .count(),
1053 self.performance_results.len(),
1054 self.compatibility_result.compatibility_score,
1055 self.overall_score,
1056 if self.test_passed { "PASSED" } else { "FAILED" }
1057 )
1058 }
1059}
1060
1061#[allow(non_snake_case)]
1062#[cfg(test)]
1063mod tests {
1064 use super::*;
1065
1066 #[test]
1067 fn test_mock_plugin_creation() {
1068 let mock = MockPlugin::new("test_plugin");
1069 assert_eq!(mock.id(), "test_plugin");
1070 assert_eq!(mock.metadata.name, "Mock Plugin test_plugin");
1071 assert!(!mock.initialized);
1072 }
1073
1074 #[test]
1075 fn test_mock_plugin_categories() {
1076 let algo = MockPlugin::for_category("test", PluginCategory::Algorithm);
1077 assert_eq!(algo.metadata.category, PluginCategory::Algorithm);
1078
1079 let transformer = MockPlugin::for_category("test", PluginCategory::Transformer);
1080 assert_eq!(transformer.metadata.category, PluginCategory::Transformer);
1081 }
1082
1083 #[test]
1084 fn test_mock_plugin_type_support() {
1085 let mut mock = MockPlugin::new("test");
1086
1087 assert!(mock.is_compatible(TypeId::of::<f64>()));
1089
1090 mock.add_supported_type(TypeId::of::<i32>());
1092 assert!(mock.is_compatible(TypeId::of::<i32>()));
1093
1094 mock.remove_supported_type(TypeId::of::<f64>());
1096 assert!(!mock.is_compatible(TypeId::of::<f64>()));
1097 }
1098
1099 #[test]
1100 fn test_mock_plugin_error_simulation() {
1101 let mut mock = MockPlugin::new("test");
1102
1103 mock.set_initialization_error(Some("Test error"));
1105 let result = mock.initialize(&PluginConfig::default());
1106 assert!(result.is_err());
1107
1108 mock.set_initialization_error(None);
1110 let result = mock.initialize(&PluginConfig::default());
1111 assert!(result.is_ok());
1112 }
1113
1114 #[test]
1115 fn test_plugin_test_fixture() {
1116 let fixture = PluginTestFixture::new();
1117
1118 let plugins = fixture.create_test_plugins();
1119 assert_eq!(plugins.len(), 5);
1120
1121 let manifests = fixture.create_test_manifests();
1122 assert_eq!(manifests.len(), 4);
1123
1124 let configs = fixture.create_test_configs();
1125 assert_eq!(configs.len(), 3);
1126 }
1127
1128 #[test]
1129 fn test_performance_tester() {
1130 let mut tester = PluginPerformanceTester::new();
1131 let mut mock = MockPlugin::new("test");
1132
1133 let result = tester.benchmark_initialization(&mut mock);
1134 assert_eq!(result.operation, "initialization");
1135 assert!(result.success);
1136 }
1137
1138 #[test]
1139 fn test_validation_test_runner() {
1140 let runner = ValidationTestRunner::new();
1141 let mock = MockPlugin::new("test");
1142 let fixture = runner.create_test_fixture();
1143 let manifest = &fixture.create_test_manifests()[3]; let report = runner.run_validation_tests(&mock, manifest);
1146 assert!(!report.has_errors()); }
1148
1149 #[test]
1150 fn test_compatibility_tests() {
1151 let runner = ValidationTestRunner::new();
1152 let mock = MockPlugin::new("test"); let result = runner.run_compatibility_tests(&mock);
1155 assert!(!result.supported_types.is_empty());
1156 assert_eq!(result.total_types_tested, 5);
1157 assert!(result.compatibility_score > 0);
1158 }
1159
1160 #[test]
1161 fn test_performance_result_scoring() {
1162 let good_result = PerformanceResult {
1163 operation: "test".to_string(),
1164 duration: Duration::from_millis(10),
1165 memory_used: 1024, success: true,
1167 error: None,
1168 within_limits: true,
1169 };
1170 assert!(good_result.is_good_performance());
1171 assert_eq!(good_result.performance_score(), 100);
1172
1173 let bad_result = PerformanceResult {
1174 operation: "test".to_string(),
1175 duration: Duration::from_secs(20),
1176 memory_used: 50 * 1024 * 1024, success: false,
1178 error: Some("Error".to_string()),
1179 within_limits: false,
1180 };
1181 assert!(!bad_result.is_good_performance());
1182 assert_eq!(bad_result.performance_score(), 0);
1183 }
1184}