1use serde::{Deserialize, Serialize};
8use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub enum Platform {
17 Databricks,
18 Snowflake,
19 Aws,
20 HuggingFace,
21 Paiml,
22}
23
24impl Platform {
25 #[must_use]
27 pub const fn name(&self) -> &'static str {
28 match self {
29 Self::Databricks => "DATABRICKS",
30 Self::Snowflake => "SNOWFLAKE",
31 Self::Aws => "AWS",
32 Self::HuggingFace => "HUGGINGFACE",
33 Self::Paiml => "PAIML",
34 }
35 }
36
37 #[must_use]
39 pub fn all() -> Vec<Self> {
40 vec![Self::Databricks, Self::Snowflake, Self::Aws, Self::HuggingFace]
41 }
42}
43
44impl fmt::Display for Platform {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 write!(f, "{}", self.name())
47 }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct PlatformCategory {
53 pub name: String,
54 pub components: Vec<PlatformComponent>,
55}
56
57impl PlatformCategory {
58 pub fn new(name: impl Into<String>) -> Self {
59 Self { name: name.into(), components: Vec::new() }
60 }
61
62 pub fn with_component(mut self, component: PlatformComponent) -> Self {
63 self.components.push(component);
64 self
65 }
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct PlatformComponent {
71 pub name: String,
72 pub description: String,
73 pub sub_components: Vec<String>,
74}
75
76impl PlatformComponent {
77 pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
78 Self { name: name.into(), description: description.into(), sub_components: Vec::new() }
79 }
80
81 pub fn with_sub(mut self, sub: impl Into<String>) -> Self {
82 self.sub_components.push(sub.into());
83 self
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct DataPlatformTree {
90 pub platform: Platform,
91 pub categories: Vec<PlatformCategory>,
92}
93
94impl DataPlatformTree {
95 pub fn new(platform: Platform) -> Self {
96 Self { platform, categories: Vec::new() }
97 }
98
99 pub fn add_category(mut self, category: PlatformCategory) -> Self {
100 self.categories.push(category);
101 self
102 }
103
104 pub fn total_components(&self) -> usize {
105 self.categories.iter().map(|c| c.components.len()).sum()
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
115pub enum IntegrationType {
116 Compatible,
118 Alternative,
120 Orchestrates,
122 Uses,
124 Transpiles,
126}
127
128impl IntegrationType {
129 #[must_use]
131 pub const fn code(&self) -> &'static str {
132 match self {
133 Self::Compatible => "CMP",
134 Self::Alternative => "ALT",
135 Self::Orchestrates => "ORC",
136 Self::Uses => "USE",
137 Self::Transpiles => "TRN",
138 }
139 }
140
141 #[must_use]
143 pub const fn description(&self) -> &'static str {
144 match self {
145 Self::Compatible => "Compatible format/protocol",
146 Self::Alternative => "PAIML native alternative",
147 Self::Orchestrates => "PAIML orchestrates",
148 Self::Uses => "PAIML uses directly",
149 Self::Transpiles => "PAIML transpiles to Rust",
150 }
151 }
152}
153
154impl fmt::Display for IntegrationType {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "[{}]", self.code())
157 }
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct IntegrationMapping {
163 pub platform_component: String,
164 pub paiml_component: String,
165 pub integration_type: IntegrationType,
166 pub category: String,
167}
168
169impl IntegrationMapping {
170 pub fn new(
171 platform: impl Into<String>,
172 paiml: impl Into<String>,
173 integration_type: IntegrationType,
174 category: impl Into<String>,
175 ) -> Self {
176 Self {
177 platform_component: platform.into(),
178 paiml_component: paiml.into(),
179 integration_type,
180 category: category.into(),
181 }
182 }
183}
184
185#[must_use]
191pub fn build_databricks_tree() -> DataPlatformTree {
192 DataPlatformTree::new(Platform::Databricks)
193 .add_category(
194 PlatformCategory::new("Unity Catalog").with_component(
195 PlatformComponent::new("Unity Catalog", "Unified governance for data and AI")
196 .with_sub("Schemas")
197 .with_sub("Tables")
198 .with_sub("Views"),
199 ),
200 )
201 .add_category(
202 PlatformCategory::new("Delta Lake").with_component(
203 PlatformComponent::new("Delta Lake", "ACID transactions on data lakes")
204 .with_sub("Parquet storage")
205 .with_sub("Transaction log")
206 .with_sub("Time travel"),
207 ),
208 )
209 .add_category(
210 PlatformCategory::new("MLflow").with_component(
211 PlatformComponent::new("MLflow", "ML lifecycle management")
212 .with_sub("Experiment tracking")
213 .with_sub("Model registry")
214 .with_sub("Model serving"),
215 ),
216 )
217 .add_category(
218 PlatformCategory::new("Spark").with_component(
219 PlatformComponent::new("Spark", "Distributed compute engine")
220 .with_sub("DataFrames")
221 .with_sub("Structured Streaming")
222 .with_sub("MLlib"),
223 ),
224 )
225}
226
227#[must_use]
229pub fn build_snowflake_tree() -> DataPlatformTree {
230 DataPlatformTree::new(Platform::Snowflake)
231 .add_category(
232 PlatformCategory::new("Virtual Warehouse").with_component(
233 PlatformComponent::new("Virtual Warehouse", "Elastic compute clusters")
234 .with_sub("Compute clusters")
235 .with_sub("Result cache")
236 .with_sub("Auto-scaling"),
237 ),
238 )
239 .add_category(
240 PlatformCategory::new("Iceberg Tables").with_component(
241 PlatformComponent::new("Iceberg Tables", "Open table format support")
242 .with_sub("Open format")
243 .with_sub("Schema evolution")
244 .with_sub("Partition pruning"),
245 ),
246 )
247 .add_category(
248 PlatformCategory::new("Snowpark").with_component(
249 PlatformComponent::new("Snowpark", "Developer experience for data")
250 .with_sub("Python UDFs")
251 .with_sub("Java/Scala UDFs")
252 .with_sub("ML functions"),
253 ),
254 )
255 .add_category(
256 PlatformCategory::new("Data Sharing").with_component(
257 PlatformComponent::new("Data Sharing", "Secure data exchange")
258 .with_sub("Secure shares")
259 .with_sub("Reader accounts")
260 .with_sub("Marketplace"),
261 ),
262 )
263}
264
265#[must_use]
267pub fn build_aws_tree() -> DataPlatformTree {
268 DataPlatformTree::new(Platform::Aws)
269 .add_category(
270 PlatformCategory::new("Storage")
271 .with_component(
272 PlatformComponent::new("S3", "Object storage")
273 .with_sub("Objects")
274 .with_sub("Versioning")
275 .with_sub("Lifecycle"),
276 )
277 .with_component(
278 PlatformComponent::new("Glue Catalog", "Metadata catalog")
279 .with_sub("Databases")
280 .with_sub("Tables")
281 .with_sub("Crawlers"),
282 )
283 .with_component(PlatformComponent::new("Lake Formation", "Data lake management")),
284 )
285 .add_category(
286 PlatformCategory::new("Compute")
287 .with_component(PlatformComponent::new("EMR", "Managed Spark/Hadoop"))
288 .with_component(PlatformComponent::new("Lambda", "Serverless functions"))
289 .with_component(PlatformComponent::new("ECS/EKS", "Container orchestration")),
290 )
291 .add_category(
292 PlatformCategory::new("ML")
293 .with_component(
294 PlatformComponent::new("SageMaker", "ML platform")
295 .with_sub("Training")
296 .with_sub("Endpoints")
297 .with_sub("Pipelines"),
298 )
299 .with_component(
300 PlatformComponent::new("Bedrock", "Foundation models")
301 .with_sub("Foundation models")
302 .with_sub("Fine-tuning")
303 .with_sub("Agents"),
304 )
305 .with_component(PlatformComponent::new("Comprehend", "NLP service")),
306 )
307 .add_category(
308 PlatformCategory::new("Analytics")
309 .with_component(PlatformComponent::new("Athena", "Serverless SQL"))
310 .with_component(PlatformComponent::new("Redshift", "Data warehouse"))
311 .with_component(PlatformComponent::new("QuickSight", "BI dashboards")),
312 )
313}
314
315#[must_use]
317pub fn build_huggingface_tree() -> DataPlatformTree {
318 DataPlatformTree::new(Platform::HuggingFace)
319 .add_category(
320 PlatformCategory::new("Hub").with_component(
321 PlatformComponent::new("Hub", "Model and dataset repository")
322 .with_sub("Models (500K+)")
323 .with_sub("Datasets (100K+)")
324 .with_sub("Spaces (200K+)"),
325 ),
326 )
327 .add_category(
328 PlatformCategory::new("Libraries")
329 .with_component(PlatformComponent::new("Transformers", "Model library"))
330 .with_component(PlatformComponent::new("Datasets", "Dataset library"))
331 .with_component(PlatformComponent::new("Tokenizers", "Fast tokenization"))
332 .with_component(PlatformComponent::new("Accelerate", "Distributed training")),
333 )
334 .add_category(
335 PlatformCategory::new("Formats")
336 .with_component(PlatformComponent::new("SafeTensors", "Safe model format"))
337 .with_component(PlatformComponent::new("GGUF", "Quantized models"))
338 .with_component(PlatformComponent::new("ONNX", "Interop format")),
339 )
340}
341
342#[must_use]
348pub fn build_integration_mappings() -> Vec<IntegrationMapping> {
349 vec![
350 IntegrationMapping::new(
352 "Delta Lake",
353 "Alimentar (.ald)",
354 IntegrationType::Alternative,
355 "STORAGE & CATALOGS",
356 ),
357 IntegrationMapping::new(
358 "Iceberg Tables",
359 "Alimentar (.ald)",
360 IntegrationType::Compatible,
361 "STORAGE & CATALOGS",
362 ),
363 IntegrationMapping::new(
364 "S3",
365 "Alimentar (sync)",
366 IntegrationType::Compatible,
367 "STORAGE & CATALOGS",
368 ),
369 IntegrationMapping::new(
370 "Unity Catalog",
371 "Pacha Registry",
372 IntegrationType::Alternative,
373 "STORAGE & CATALOGS",
374 ),
375 IntegrationMapping::new(
376 "Glue Catalog",
377 "Pacha Registry",
378 IntegrationType::Alternative,
379 "STORAGE & CATALOGS",
380 ),
381 IntegrationMapping::new(
382 "HuggingFace Hub",
383 "Pacha Registry",
384 IntegrationType::Alternative,
385 "STORAGE & CATALOGS",
386 ),
387 IntegrationMapping::new(
389 "Spark DataFrames",
390 "Trueno",
391 IntegrationType::Alternative,
392 "COMPUTE & PROCESSING",
393 ),
394 IntegrationMapping::new(
395 "Snowpark",
396 "Trueno",
397 IntegrationType::Alternative,
398 "COMPUTE & PROCESSING",
399 ),
400 IntegrationMapping::new(
401 "EMR",
402 "Trueno",
403 IntegrationType::Alternative,
404 "COMPUTE & PROCESSING",
405 ),
406 IntegrationMapping::new(
407 "Snowpark Python",
408 "Depyler → Rust",
409 IntegrationType::Transpiles,
410 "COMPUTE & PROCESSING",
411 ),
412 IntegrationMapping::new(
413 "Lambda Python",
414 "Depyler → Rust",
415 IntegrationType::Transpiles,
416 "COMPUTE & PROCESSING",
417 ),
418 IntegrationMapping::new(
419 "Neptune/GraphQL",
420 "Trueno-Graph",
421 IntegrationType::Alternative,
422 "COMPUTE & PROCESSING",
423 ),
424 IntegrationMapping::new("MLlib", "Aprender", IntegrationType::Alternative, "ML TRAINING"),
426 IntegrationMapping::new(
427 "Snowpark ML",
428 "Aprender",
429 IntegrationType::Alternative,
430 "ML TRAINING",
431 ),
432 IntegrationMapping::new(
433 "SageMaker Training",
434 "Entrenar",
435 IntegrationType::Alternative,
436 "ML TRAINING",
437 ),
438 IntegrationMapping::new(
439 "MLflow Tracking",
440 "Entrenar",
441 IntegrationType::Alternative,
442 "ML TRAINING",
443 ),
444 IntegrationMapping::new(
445 "SageMaker Experiments",
446 "Entrenar",
447 IntegrationType::Alternative,
448 "ML TRAINING",
449 ),
450 IntegrationMapping::new("W&B", "Entrenar", IntegrationType::Uses, "ML TRAINING"),
451 IntegrationMapping::new(
453 "MLflow Serving",
454 "Realizar",
455 IntegrationType::Alternative,
456 "MODEL SERVING",
457 ),
458 IntegrationMapping::new(
459 "SageMaker Endpoints",
460 "Realizar",
461 IntegrationType::Alternative,
462 "MODEL SERVING",
463 ),
464 IntegrationMapping::new(
465 "Bedrock",
466 "Realizar + serve",
467 IntegrationType::Alternative,
468 "MODEL SERVING",
469 ),
470 IntegrationMapping::new("GGUF models", "Realizar", IntegrationType::Uses, "MODEL SERVING"),
471 IntegrationMapping::new(
472 "HF Transformers",
473 "Realizar (via GGUF)",
474 IntegrationType::Compatible,
475 "MODEL SERVING",
476 ),
477 IntegrationMapping::new(
479 "Databricks Workflows",
480 "Batuta",
481 IntegrationType::Orchestrates,
482 "ORCHESTRATION",
483 ),
484 IntegrationMapping::new(
485 "Snowflake Tasks",
486 "Batuta",
487 IntegrationType::Orchestrates,
488 "ORCHESTRATION",
489 ),
490 IntegrationMapping::new(
491 "Step Functions",
492 "Batuta",
493 IntegrationType::Orchestrates,
494 "ORCHESTRATION",
495 ),
496 IntegrationMapping::new(
497 "Airflow/Prefect",
498 "Batuta",
499 IntegrationType::Orchestrates,
500 "ORCHESTRATION",
501 ),
502 ]
503}
504
505pub fn format_platform_tree(tree: &DataPlatformTree) -> String {
511 let mut output = String::new();
512 output.push_str(&format!("{}\n", tree.platform.name()));
513
514 for (i, category) in tree.categories.iter().enumerate() {
515 let is_last_category = i == tree.categories.len() - 1;
516 let prefix = if is_last_category { "└── " } else { "├── " };
517 let child_prefix = if is_last_category { " " } else { "│ " };
518
519 output.push_str(&format!("{}{}\n", prefix, category.name));
520
521 for (j, component) in category.components.iter().enumerate() {
522 let is_last_component = j == category.components.len() - 1;
523 let comp_prefix = if is_last_component { "└── " } else { "├── " };
524 let sub_prefix = if is_last_component { " " } else { "│ " };
525
526 output.push_str(&format!("{}{}{}\n", child_prefix, comp_prefix, component.name));
527
528 for (k, sub) in component.sub_components.iter().enumerate() {
529 let is_last_sub = k == component.sub_components.len() - 1;
530 let sub_comp_prefix = if is_last_sub { "└── " } else { "├── " };
531 output
532 .push_str(&format!("{}{}{}{}", child_prefix, sub_prefix, sub_comp_prefix, sub));
533 output.push('\n');
534 }
535 }
536 }
537
538 output
539}
540
541pub fn format_all_platforms() -> String {
543 let mut output = String::new();
544 output.push_str("DATA PLATFORMS ECOSYSTEM\n");
545 output.push_str("========================\n\n");
546
547 let trees = vec![
548 build_databricks_tree(),
549 build_snowflake_tree(),
550 build_aws_tree(),
551 build_huggingface_tree(),
552 ];
553
554 let total_components: usize = trees.iter().map(|t| t.total_components()).sum();
555 let total_categories: usize = trees.iter().map(|t| t.categories.len()).sum();
556
557 for tree in &trees {
558 output.push_str(&format_platform_tree(tree));
559 output.push('\n');
560 }
561
562 output.push_str(&format!(
563 "Summary: {} platforms, {} categories, {} components\n",
564 trees.len(),
565 total_categories,
566 total_components
567 ));
568
569 output
570}
571
572pub fn format_integration_mappings() -> String {
574 let mut output = String::new();
575 output.push_str("PAIML ↔ DATA PLATFORMS INTEGRATION\n");
576 output.push_str("==================================\n\n");
577
578 let mappings = build_integration_mappings();
579
580 let mut current_category = String::new();
582 for mapping in &mappings {
583 if mapping.category != current_category {
584 if !current_category.is_empty() {
585 output.push('\n');
586 }
587 output.push_str(&format!("{}\n", mapping.category));
588 current_category = mapping.category.clone();
589 }
590
591 output.push_str(&format!(
592 "├── {} {} ←→ {}\n",
593 mapping.integration_type, mapping.paiml_component, mapping.platform_component
594 ));
595 }
596
597 let compatible =
599 mappings.iter().filter(|m| m.integration_type == IntegrationType::Compatible).count();
600 let alternative =
601 mappings.iter().filter(|m| m.integration_type == IntegrationType::Alternative).count();
602 let uses = mappings.iter().filter(|m| m.integration_type == IntegrationType::Uses).count();
603 let transpiles =
604 mappings.iter().filter(|m| m.integration_type == IntegrationType::Transpiles).count();
605 let orchestrates =
606 mappings.iter().filter(|m| m.integration_type == IntegrationType::Orchestrates).count();
607
608 output.push_str("\nLegend: [CMP]=Compatible [ALT]=Alternative [USE]=Uses [TRN]=Transpiles [ORC]=Orchestrates\n\n");
609 output.push_str(&format!(
610 "Summary: {} compatible, {} alternatives, {} uses, {} transpiles, {} orchestrates\n",
611 compatible, alternative, uses, transpiles, orchestrates
612 ));
613 output.push_str(&format!(" Total: {} integration points\n", mappings.len()));
614
615 output
616}
617
618#[cfg(test)]
623#[allow(non_snake_case)]
624mod tests {
625 use super::*;
626
627 #[test]
632 fn test_DATA_TREE_001_platform_names() {
633 assert_eq!(Platform::Databricks.name(), "DATABRICKS");
634 assert_eq!(Platform::Snowflake.name(), "SNOWFLAKE");
635 assert_eq!(Platform::Aws.name(), "AWS");
636 assert_eq!(Platform::HuggingFace.name(), "HUGGINGFACE");
637 }
638
639 #[test]
640 fn test_DATA_TREE_001_platform_all() {
641 let all = Platform::all();
642 assert_eq!(all.len(), 4);
643 }
644
645 #[test]
646 fn test_DATA_TREE_001_platform_display() {
647 assert_eq!(format!("{}", Platform::Databricks), "DATABRICKS");
648 }
649
650 #[test]
655 fn test_DATA_TREE_002_integration_codes() {
656 assert_eq!(IntegrationType::Compatible.code(), "CMP");
657 assert_eq!(IntegrationType::Alternative.code(), "ALT");
658 assert_eq!(IntegrationType::Orchestrates.code(), "ORC");
659 assert_eq!(IntegrationType::Uses.code(), "USE");
660 assert_eq!(IntegrationType::Transpiles.code(), "TRN");
661 }
662
663 #[test]
664 fn test_DATA_TREE_002_integration_display() {
665 assert_eq!(format!("{}", IntegrationType::Compatible), "[CMP]");
666 }
667
668 #[test]
673 fn test_DATA_TREE_003_databricks_tree() {
674 let tree = build_databricks_tree();
675 assert_eq!(tree.platform, Platform::Databricks);
676 assert!(!tree.categories.is_empty());
677 assert!(tree.total_components() > 0);
678 }
679
680 #[test]
681 fn test_DATA_TREE_003_snowflake_tree() {
682 let tree = build_snowflake_tree();
683 assert_eq!(tree.platform, Platform::Snowflake);
684 assert!(!tree.categories.is_empty());
685 }
686
687 #[test]
688 fn test_DATA_TREE_003_aws_tree() {
689 let tree = build_aws_tree();
690 assert_eq!(tree.platform, Platform::Aws);
691 assert!(tree.categories.len() >= 4); }
693
694 #[test]
695 fn test_DATA_TREE_003_huggingface_tree() {
696 let tree = build_huggingface_tree();
697 assert_eq!(tree.platform, Platform::HuggingFace);
698 assert!(!tree.categories.is_empty());
699 }
700
701 #[test]
706 fn test_DATA_TREE_004_mappings_exist() {
707 let mappings = build_integration_mappings();
708 assert!(!mappings.is_empty());
709 assert!(mappings.len() >= 25); }
711
712 #[test]
713 fn test_DATA_TREE_004_mapping_categories() {
714 let mappings = build_integration_mappings();
715 let categories: std::collections::HashSet<_> =
716 mappings.iter().map(|m| &m.category).collect();
717 assert!(categories.contains(&"STORAGE & CATALOGS".to_string()));
718 assert!(categories.contains(&"ML TRAINING".to_string()));
719 assert!(categories.contains(&"MODEL SERVING".to_string()));
720 }
721
722 #[test]
723 fn test_DATA_TREE_004_has_all_types() {
724 let mappings = build_integration_mappings();
725 let types: std::collections::HashSet<_> =
726 mappings.iter().map(|m| m.integration_type).collect();
727 assert!(types.contains(&IntegrationType::Compatible));
728 assert!(types.contains(&IntegrationType::Alternative));
729 assert!(types.contains(&IntegrationType::Uses));
730 assert!(types.contains(&IntegrationType::Transpiles));
731 assert!(types.contains(&IntegrationType::Orchestrates));
732 }
733
734 #[test]
739 fn test_DATA_TREE_005_format_platform_tree() {
740 let tree = build_databricks_tree();
741 let output = format_platform_tree(&tree);
742 assert!(output.contains("DATABRICKS"));
743 assert!(output.contains("Delta Lake"));
744 assert!(output.contains("MLflow"));
745 }
746
747 #[test]
748 fn test_DATA_TREE_005_format_all_platforms() {
749 let output = format_all_platforms();
750 assert!(output.contains("DATA PLATFORMS ECOSYSTEM"));
751 assert!(output.contains("DATABRICKS"));
752 assert!(output.contains("SNOWFLAKE"));
753 assert!(output.contains("AWS"));
754 assert!(output.contains("HUGGINGFACE"));
755 assert!(output.contains("Summary:"));
756 }
757
758 #[test]
759 fn test_DATA_TREE_005_format_integration_mappings() {
760 let output = format_integration_mappings();
761 assert!(output.contains("PAIML"));
762 assert!(output.contains("STORAGE & CATALOGS"));
763 assert!(output.contains("Alimentar"));
764 assert!(output.contains("Legend:"));
765 assert!(output.contains("Total:"));
766 }
767
768 #[test]
773 fn test_DATA_TREE_006_platform_category() {
774 let category = PlatformCategory::new("Test Category")
775 .with_component(PlatformComponent::new("Component1", "Description 1"));
776 assert_eq!(category.name, "Test Category");
777 assert_eq!(category.components.len(), 1);
778 }
779
780 #[test]
781 fn test_DATA_TREE_006_platform_component() {
782 let component =
783 PlatformComponent::new("Test", "Description").with_sub("Sub1").with_sub("Sub2");
784 assert_eq!(component.name, "Test");
785 assert_eq!(component.sub_components.len(), 2);
786 }
787
788 #[test]
789 fn test_DATA_TREE_006_integration_mapping() {
790 let mapping =
791 IntegrationMapping::new("Source", "Target", IntegrationType::Compatible, "Category");
792 assert_eq!(mapping.platform_component, "Source");
793 assert_eq!(mapping.paiml_component, "Target");
794 }
795
796 #[test]
801 fn test_integration_type_descriptions() {
802 assert!(!IntegrationType::Compatible.description().is_empty());
803 assert!(!IntegrationType::Alternative.description().is_empty());
804 assert!(!IntegrationType::Orchestrates.description().is_empty());
805 assert!(!IntegrationType::Uses.description().is_empty());
806 assert!(!IntegrationType::Transpiles.description().is_empty());
807 }
808
809 #[test]
810 fn test_platform_paiml() {
811 assert_eq!(Platform::Paiml.name(), "PAIML");
812 assert_eq!(format!("{}", Platform::Paiml), "PAIML");
813 }
814
815 #[test]
816 fn test_data_platform_tree_empty() {
817 let tree = DataPlatformTree::new(Platform::Paiml);
818 assert_eq!(tree.platform, Platform::Paiml);
819 assert!(tree.categories.is_empty());
820 assert_eq!(tree.total_components(), 0);
821 }
822
823 #[test]
824 fn test_data_platform_tree_multiple_categories() {
825 let tree = DataPlatformTree::new(Platform::Aws)
826 .add_category(
827 PlatformCategory::new("Cat1")
828 .with_component(PlatformComponent::new("C1", "D1"))
829 .with_component(PlatformComponent::new("C2", "D2")),
830 )
831 .add_category(
832 PlatformCategory::new("Cat2").with_component(PlatformComponent::new("C3", "D3")),
833 );
834 assert_eq!(tree.categories.len(), 2);
835 assert_eq!(tree.total_components(), 3);
836 }
837
838 #[test]
839 fn test_platform_equality() {
840 assert_eq!(Platform::Databricks, Platform::Databricks);
841 assert_ne!(Platform::Databricks, Platform::Snowflake);
842 }
843
844 #[test]
845 fn test_integration_type_equality() {
846 assert_eq!(IntegrationType::Compatible, IntegrationType::Compatible);
847 assert_ne!(IntegrationType::Compatible, IntegrationType::Alternative);
848 }
849
850 #[test]
851 fn test_platform_category_empty() {
852 let cat = PlatformCategory::new("Empty");
853 assert!(cat.components.is_empty());
854 }
855
856 #[test]
857 fn test_platform_component_no_subs() {
858 let comp = PlatformComponent::new("NoSubs", "Description");
859 assert!(comp.sub_components.is_empty());
860 }
861
862 #[test]
863 fn test_format_platform_tree_with_subs() {
864 let tree = DataPlatformTree::new(Platform::Paiml).add_category(
865 PlatformCategory::new("Category").with_component(
866 PlatformComponent::new("Component", "Desc").with_sub("Sub1").with_sub("Sub2"),
867 ),
868 );
869 let output = format_platform_tree(&tree);
870 assert!(output.contains("PAIML"));
871 assert!(output.contains("Sub1"));
872 assert!(output.contains("Sub2"));
873 }
874
875 #[test]
876 fn test_integration_mapping_fields() {
877 let mapping =
878 IntegrationMapping::new("Platform", "PAIML", IntegrationType::Orchestrates, "Category");
879 assert_eq!(mapping.integration_type, IntegrationType::Orchestrates);
880 assert_eq!(mapping.category, "Category");
881 }
882
883 #[test]
884 fn test_all_platforms_count() {
885 let platforms = Platform::all();
886 assert_eq!(platforms.len(), 4);
888 assert!(!platforms.contains(&Platform::Paiml));
889 }
890
891 #[test]
892 fn test_tree_with_multiple_components_per_category() {
893 let tree = DataPlatformTree::new(Platform::Aws).add_category(
894 PlatformCategory::new("MultiComp")
895 .with_component(PlatformComponent::new("A", "DA"))
896 .with_component(PlatformComponent::new("B", "DB"))
897 .with_component(PlatformComponent::new("C", "DC")),
898 );
899 assert_eq!(tree.total_components(), 3);
900 }
901}