rustorch 0.6.29

Production-ready PyTorch-compatible deep learning library in Rust with special mathematical functions (gamma, Bessel, error functions), statistical distributions, Fourier transforms (FFT/RFFT), matrix decomposition (SVD/QR/LU/eigenvalue), automatic differentiation, neural networks, computer vision transforms, complete GPU acceleration (CUDA/Metal/OpenCL), SIMD optimizations, parallel processing, WebAssembly browser support, comprehensive distributed learning support, and performance validation
Documentation
//! Platform-specific CoreML Tests
//! プラットフォーム固有のCoreMLテスト
//!
//! This test suite validates platform-specific behavior and fallback chains
//! for the CoreML hybrid execution system.

#[cfg(test)]
mod platform_detection_tests {
    use rustorch::gpu::DeviceType;

    #[test]
    fn test_apple_silicon_detection() {
        // Test platform detection logic
        let is_apple_silicon = cfg!(target_arch = "aarch64") && cfg!(target_os = "macos");

        if is_apple_silicon {
            println!("Running on Apple Silicon");
            // On Apple Silicon, CoreML should be preferred
            #[cfg(feature = "coreml")]
            {
                let preferred_device = DeviceType::default();
                assert!(matches!(preferred_device, DeviceType::CoreML(_)));
            }
        } else {
            println!("Running on Intel/AMD");
            // On Intel/AMD, CUDA should be preferred if available
            #[cfg(feature = "cuda")]
            {
                let preferred_device = DeviceType::default();
                assert!(matches!(preferred_device, DeviceType::Cuda(_)));
            }
        }
    }

    #[test]
    fn test_device_availability_detection() {
        // Test that device availability detection works correctly
        assert!(DeviceType::Cpu.is_available()); // CPU should always be available

        #[cfg(feature = "cuda")]
        {
            let cuda_available = DeviceType::Cuda(0).is_available();
            println!("CUDA available: {}", cuda_available);
        }

        #[cfg(feature = "metal")]
        {
            let metal_available = DeviceType::Metal(0).is_available();
            println!("Metal available: {}", metal_available);

            // Metal should only be available on macOS
            if cfg!(target_os = "macos") {
                // May or may not be available depending on hardware
            } else {
                assert!(!metal_available);
            }
        }
    }

    #[test]
    #[cfg(any(feature = "coreml-hybrid", feature = "coreml-fallback"))]
    fn test_fallback_chain_platform_specific() {
        use rustorch::gpu::hybrid_executor::HybridExecutor;

        let mut executor = HybridExecutor::new();
        executor.build_fallback_chain();
        let chain = executor.get_fallback_chain();

        if cfg!(target_arch = "aarch64") && cfg!(target_os = "macos") {
            // Apple Silicon fallback chain: CoreML → Metal → CPU
            assert!(!chain.is_empty());

            #[cfg(feature = "coreml")]
            {
                // First preference should be CoreML
                assert!(matches!(chain[0], DeviceType::CoreML(_)));
            }

            #[cfg(feature = "metal")]
            {
                // Metal should be in the chain
                assert!(chain.iter().any(|d| matches!(d, DeviceType::Metal(_))));
            }

            // CPU should always be the final fallback
            assert!(matches!(chain[chain.len() - 1], DeviceType::Cpu));
        } else {
            // Intel/AMD fallback chain: CUDA → OpenCL → CPU
            assert!(!chain.is_empty());

            #[cfg(feature = "cuda")]
            {
                // CUDA should be preferred on Intel/AMD if available
                if chain.iter().any(|d| matches!(d, DeviceType::Cuda(_))) {
                    assert!(matches!(chain[0], DeviceType::Cuda(_)));
                }
            }

            // CPU should always be the final fallback
            assert!(matches!(chain[chain.len() - 1], DeviceType::Cpu));
        }
    }

    #[test]
    fn test_cuda_metal_mutual_exclusion() {
        // Test that CUDA and Metal are not both active on the same system
        #[cfg(all(feature = "cuda", feature = "metal"))]
        {
            let cuda_available = DeviceType::Cuda(0).is_available();
            let metal_available = DeviceType::Metal(0).is_available();

            if cfg!(target_os = "macos") {
                // On macOS, Metal may be available but CUDA typically isn't on Apple Silicon
                if cfg!(target_arch = "aarch64") {
                    // Apple Silicon: Metal may be available, CUDA should not be
                    assert!(!cuda_available || !metal_available);
                }
            } else {
                // On non-macOS, Metal should not be available
                assert!(!metal_available);
            }
        }
    }
}

#[cfg(test)]
mod coreml_feature_tests {
    use rustorch::tensor::Tensor;

    #[test]
    #[cfg(feature = "coreml")]
    fn test_coreml_basic_availability() {
        // Test basic CoreML functionality is available when feature is enabled
        use rustorch::gpu::DeviceCapability;

        let capability = DeviceCapability::coreml_capability();
        assert!(capability.supports_f32);
        assert!(capability.supports_f16);
        assert!(!capability.supports_f64); // CoreML limitation
        assert!(!capability.supports_complex); // CoreML limitation
    }

    #[test]
    #[cfg(not(feature = "coreml"))]
    fn test_fallback_without_coreml() {
        // Test that operations work without CoreML feature enabled
        let a = Tensor::ones(&[4, 4]);
        let b = Tensor::ones(&[4, 4]);

        // Should fall back to standard operations
        let result = a.dot(&b);
        assert!(result.is_ok());
    }

    #[test]
    #[cfg(feature = "coreml-hybrid")]
    fn test_hybrid_mode_availability() {
        // Test hybrid mode functionality
        use rustorch::gpu::GpuLinearAlgebra;

        let a = Tensor::ones(&[8, 8]).unwrap();
        let b = Tensor::ones(&[8, 8]).unwrap();

        let result = a.gpu_matmul(&b);
        assert!(result.is_ok());
    }

    #[test]
    #[cfg(feature = "coreml-fallback")]
    fn test_fallback_mode_availability() {
        // Test fallback mode functionality
        use rustorch::gpu::hybrid_executor::HybridExecutor;

        let executor = HybridExecutor::new();
        assert!(executor.is_fallback_enabled());
    }
}

#[cfg(test)]
mod memory_management_tests {
    // Unused imports removed

    #[test]
    #[cfg(any(feature = "coreml", feature = "coreml-hybrid"))]
    fn test_memory_pressure_handling() {
        // Test behavior under memory pressure
        let mut tensors = Vec::new();

        // Create progressively larger tensors until we hit memory limits
        for size in [64, 128, 256, 512].iter() {
            let tensor = Tensor::ones(&[*size, *size]).unwrap();
            tensors.push(tensor);
        }

        // Test operations still work
        if tensors.len() >= 2 {
            let result = tensors[0].gpu_matmul(&tensors[1]);
            assert!(result.is_ok() || result.is_err()); // Either outcome acceptable
        }
    }

    #[test]
    #[cfg(any(feature = "coreml", feature = "coreml-hybrid"))]
    fn test_large_tensor_fallback() {
        // Test that very large tensors properly fall back to appropriate backends
        if std::env::var("SKIP_LARGE_TENSOR_TESTS").is_ok() {
            return; // Skip on memory-constrained systems
        }

        let large_tensor = match Tensor::ones(&[1024, 1024]) {
            Ok(tensor) => tensor,
            Err(_) => {
                println!("Skipping large tensor test due to memory constraints");
                return;
            }
        };

        let result = large_tensor.gpu_matmul(&large_tensor);
        match result {
            Ok(output) => {
                assert_eq!(output.shape(), &[1024, 1024]);
                println!("Large tensor operation succeeded");
            }
            Err(e) => {
                println!("Large tensor operation failed as expected: {}", e);
                // Failure is acceptable for very large tensors
            }
        }
    }

    #[test]
    #[cfg(any(feature = "coreml", feature = "coreml-hybrid"))]
    fn test_memory_leak_prevention() {
        // Test that repeated operations don't cause memory leaks
        let a = Tensor::ones(&[32, 32]).unwrap();
        let b = Tensor::ones(&[32, 32]).unwrap();

        // Perform many operations
        for _ in 0..100 {
            let result = a.gpu_matmul(&b);
            assert!(result.is_ok());
            // Result should be dropped automatically
        }

        // No explicit assertion here, but this test helps detect memory leaks
        // through tools like Valgrind or AddressSanitizer
    }
}

#[cfg(test)]
mod error_handling_tests {
    // Unused imports removed

    #[test]
    #[cfg(any(feature = "coreml", feature = "coreml-hybrid"))]
    fn test_invalid_tensor_shapes() {
        // Test error handling for incompatible tensor shapes
        let a = Tensor::ones(&[3, 4]).unwrap();
        let b = Tensor::ones(&[5, 6]).unwrap(); // Incompatible shapes

        let result = a.gpu_matmul(&b);
        assert!(result.is_err()); // Should fail due to incompatible shapes
    }

    #[test]
    #[cfg(any(feature = "coreml", feature = "coreml-hybrid"))]
    fn test_empty_tensor_handling() {
        // Test handling of empty tensors
        let empty = Tensor::zeros(&[0, 0]).unwrap();
        let normal = Tensor::ones(&[4, 4]).unwrap();

        let result = empty.gpu_matmul(&normal);
        assert!(result.is_err()); // Should fail gracefully
    }

    #[test]
    #[cfg(any(feature = "coreml", feature = "coreml-hybrid"))]
    fn test_device_unavailable_fallback() {
        // Test fallback when preferred device is unavailable
        let input = Tensor::ones(&[16, 16]).unwrap();

        // Even if CoreML is not available, operations should fall back
        let result = input.gpu_relu();
        assert!(result.is_ok()); // Should succeed via fallback
    }

    #[test]
    #[cfg(any(feature = "coreml", feature = "coreml-hybrid"))]
    fn test_concurrent_operations() {
        use std::sync::Arc;
        use std::thread;

        let tensor = Arc::new(Tensor::ones(&[16, 16]).unwrap());
        let mut handles = Vec::new();

        // Spawn multiple threads performing operations
        for _ in 0..4 {
            let tensor_clone = Arc::clone(&tensor);
            let handle = thread::spawn(move || {
                let result = tensor_clone.gpu_relu();
                assert!(result.is_ok());
            });
            handles.push(handle);
        }

        // Wait for all threads to complete
        for handle in handles {
            handle.join().unwrap();
        }
    }
}

#[cfg(test)]
mod compatibility_tests {
    use rustorch::tensor::Tensor;

    #[test]
    fn test_cross_platform_tensor_format() {
        // Test that tensors work consistently across platforms
        let data = vec![1.0, 2.0, 3.0, 4.0];
        let tensor = Tensor::from_vec(data.clone(), vec![2, 2]);

        // Data should be preserved regardless of platform
        let retrieved_data = &tensor.data;
        for (original, retrieved) in data.iter().zip(retrieved_data.iter()) {
            assert!((original - retrieved).abs() < 1e-6);
        }
    }

    #[test]
    #[cfg(all(feature = "coreml", feature = "cuda"))]
    fn test_coreml_cuda_compatibility() {
        // Test that CoreML and CUDA features can coexist in the binary
        // (even if they don't run simultaneously on the same hardware)

        let tensor = Tensor::ones(&[8, 8]).unwrap();

        // Both backends should be available in the binary
        use rustorch::gpu::DeviceType;

        let _coreml_device = DeviceType::CoreML(0);
        let _cuda_device = DeviceType::Cuda(0);

        // Actual availability depends on hardware
        println!("CoreML device type available in binary");
        println!("CUDA device type available in binary");
    }

    #[test]
    #[cfg(all(feature = "coreml", feature = "metal"))]
    fn test_coreml_metal_integration() {
        // Test CoreML and Metal working together on Apple platforms
        if !cfg!(target_os = "macos") {
            return; // Skip on non-macOS platforms
        }

        let tensor = Tensor::ones(&[16, 16]).unwrap();

        // Operations should work with either CoreML or Metal backends
        use rustorch::gpu::GpuLinearAlgebra;
        let result = tensor.gpu_matmul(&tensor);
        assert!(result.is_ok());
    }
}