1pub mod bindings;
18pub mod exports;
19pub mod memory;
20
21pub use bindings::{
25 BindingGenerator, BundleFormat, BundlingConfig, ModuleSystem, WebBindingConfig,
26 WebBindingLanguage,
27};
28
29pub use memory::{
31 CacheStorage, CacheStrategy, CachingConfig, LoadingStrategy, MemoryAlignment, MemoryBreakdown,
32 MemoryGrowthStrategy, MemoryManager, MemoryRequirements, ParallelConfig, PreloadingConfig,
33 ProgressiveLoadingConfig, VersioningStrategy, WasmMemoryConfig, WasmMemoryExport,
34 WasmMemoryImport,
35};
36
37pub use exports::{
39 BundleInfo, InlineLevel, MessagingStrategy, PerformanceHint, ProfilingConfig, ProfilingFormat,
40 TextureFormat, WasmCompilationConfig, WasmCompilationResult, WasmCompiler, WasmDebugConfig,
41 WasmExports, WasmFeatures, WasmFunctionExport, WasmFunctionImport, WasmGlobalExport,
42 WasmGlobalImport, WasmImports, WasmOptimization, WasmSignature, WasmTableExport,
43 WasmTableImport, WasmType, WasmVersion, WebAccelerationConfig, WebGLConfig, WebGPUConfig,
44 WebIntegrationConfig, WorkerConfig, WorkerPoolConfig, WorkerType,
45};
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use crate::layers::Dense;
51 use crate::models::sequential::Sequential;
52 use crate::serving::PackageMetadata;
53 use rand::SeedableRng;
54 use std::collections::HashMap;
55 use tempfile::TempDir;
56
57 #[test]
58 fn test_wasm_module_integration() {
59 let temp_dir = TempDir::new().unwrap();
61 let mut rng = rand::rngs::SmallRng::seed_from_u64(42);
62
63 let mut model: Sequential<f32> = Sequential::new();
65 let dense = Dense::new(10, 1, Some("relu"), &mut rng).unwrap();
66 model.add_layer(dense);
67
68 let wasm_config = WasmCompilationConfig::default();
70 let web_config = WebIntegrationConfig::default();
71 let metadata = PackageMetadata {
72 name: "test-model".to_string(),
73 version: "1.0.0".to_string(),
74 description: "Test WebAssembly model".to_string(),
75 author: "SciRS2".to_string(),
76 license: "MIT".to_string(),
77 platforms: vec!["wasm".to_string()],
78 dependencies: HashMap::new(),
79 input_specs: Vec::new(),
80 output_specs: Vec::new(),
81 runtime_requirements: crate::serving::RuntimeRequirements {
82 min_memory_mb: 256,
83 cpu_requirements: crate::serving::CpuRequirements {
84 min_cores: 1,
85 instruction_sets: Vec::new(),
86 min_frequency_mhz: None,
87 },
88 gpu_requirements: None,
89 system_dependencies: Vec::new(),
90 },
91 timestamp: chrono::Utc::now().to_rfc3339(),
92 checksum: "test".to_string(),
93 };
94
95 let compiler = WasmCompiler::new(
97 model,
98 wasm_config,
99 web_config,
100 metadata,
101 temp_dir.path().to_path_buf(),
102 );
103
104 let result = compiler.compile();
106 assert!(result.is_ok());
107
108 let compilation_result = result.unwrap();
109 assert!(compilation_result.wasm_module.exists());
110 assert!(!compilation_result.bindings.is_empty());
111 assert!(compilation_result.bundle_info.total_size > 0);
112 }
113
114 #[test]
115 fn test_memory_manager_integration() {
116 let performance_manager = MemoryManager::performance_optimized();
118 let constrained_manager = MemoryManager::resource_constrained();
119
120 let model_size = 10 * 1024 * 1024; let perf_requirements = performance_manager.calculate_memory_requirements(model_size);
123 let constrained_requirements =
124 constrained_manager.calculate_memory_requirements(model_size);
125
126 assert!(perf_requirements.total > constrained_requirements.total);
128
129 assert!(performance_manager.is_suitable_for_model(model_size));
131 assert!(constrained_manager.is_suitable_for_model(model_size));
132 }
133
134 #[test]
135 fn test_binding_generator_integration() {
136 let temp_dir = TempDir::new().unwrap();
137
138 let js_config = WebBindingConfig {
140 target_language: WebBindingLanguage::JavaScript,
141 module_system: ModuleSystem::ESModules,
142 type_definitions: false,
143 documentation: false,
144 bundling: BundlingConfig {
145 enable: false,
146 format: BundleFormat::Single,
147 minify: false,
148 tree_shaking: false,
149 code_splitting: false,
150 },
151 };
152
153 let ts_config = WebBindingConfig {
154 target_language: WebBindingLanguage::TypeScript,
155 module_system: ModuleSystem::ESModules,
156 type_definitions: true,
157 documentation: true,
158 bundling: BundlingConfig {
159 enable: true,
160 format: BundleFormat::Single,
161 minify: true,
162 tree_shaking: true,
163 code_splitting: false,
164 },
165 };
166
167 let both_config = WebBindingConfig {
168 target_language: WebBindingLanguage::Both,
169 module_system: ModuleSystem::ESModules,
170 type_definitions: true,
171 documentation: true,
172 bundling: BundlingConfig {
173 enable: true,
174 format: BundleFormat::Chunked,
175 minify: true,
176 tree_shaking: true,
177 code_splitting: true,
178 },
179 };
180
181 let js_generator = BindingGenerator::new(temp_dir.path().to_path_buf(), js_config);
183 let js_bindings = js_generator.generate_bindings().unwrap();
184 assert_eq!(js_bindings.len(), 1);
185 assert!(js_bindings[0].to_string_lossy().ends_with(".js"));
186
187 let ts_generator = BindingGenerator::new(temp_dir.path().to_path_buf(), ts_config);
189 let ts_bindings = ts_generator.generate_bindings().unwrap();
190 assert_eq!(ts_bindings.len(), 1);
191 assert!(ts_bindings[0].to_string_lossy().ends_with(".ts"));
192
193 let both_generator = BindingGenerator::new(temp_dir.path().to_path_buf(), both_config);
195 let both_bindings = both_generator.generate_bindings().unwrap();
196 assert_eq!(both_bindings.len(), 2);
197 }
198
199 #[test]
200 fn test_configuration_defaults() {
201 let wasm_config = WasmCompilationConfig::default();
203 assert_eq!(wasm_config.target_version, WasmVersion::SIMD);
204 assert!(wasm_config.features.simd);
205 assert!(wasm_config.features.bulk_memory);
206 assert!(wasm_config.optimization_level.lto);
207
208 let web_config = WebIntegrationConfig::default();
209 assert_eq!(
210 web_config.bindings.target_language,
211 WebBindingLanguage::Both
212 );
213 assert!(web_config.caching.enable);
214 assert!(web_config.progressive_loading.enable);
215 assert!(web_config.workers.enable);
216
217 let memory_config = WasmMemoryConfig::default();
218 assert_eq!(memory_config.initial_pages, 256);
219 assert_eq!(memory_config.maximum_pages, Some(1024));
220 assert_eq!(
221 memory_config.growth_strategy,
222 MemoryGrowthStrategy::OnDemand
223 );
224 }
225
226 #[test]
227 fn test_wasm_features_validation() {
228 let mvp_features = WasmFeatures {
230 simd: false,
231 threads: false,
232 bulk_memory: false,
233 reference_types: false,
234 exception_handling: false,
235 tail_calls: false,
236 multi_value: false,
237 wasi: false,
238 };
239
240 let modern_features = WasmFeatures {
241 simd: true,
242 threads: true,
243 bulk_memory: true,
244 reference_types: true,
245 exception_handling: false,
246 tail_calls: false,
247 multi_value: true,
248 wasi: false,
249 };
250
251 let mvp_config = WasmCompilationConfig {
253 target_version: WasmVersion::MVP,
254 features: mvp_features,
255 ..Default::default()
256 };
257
258 let simd_threads_config = WasmCompilationConfig {
259 target_version: WasmVersion::SIMDThreads,
260 features: modern_features,
261 ..Default::default()
262 };
263
264 assert_eq!(mvp_config.target_version, WasmVersion::MVP);
266 assert!(!mvp_config.features.simd);
267
268 assert_eq!(simd_threads_config.target_version, WasmVersion::SIMDThreads);
269 assert!(simd_threads_config.features.simd);
270 assert!(simd_threads_config.features.threads);
271 }
272
273 #[test]
274 fn test_memory_requirements_calculation() {
275 let manager = MemoryManager::performance_optimized();
276
277 let small_model = 1024 * 1024; let medium_model = 10 * 1024 * 1024; let large_model = 100 * 1024 * 1024; let small_req = manager.calculate_memory_requirements(small_model);
283 let medium_req = manager.calculate_memory_requirements(medium_model);
284 let large_req = manager.calculate_memory_requirements(large_model);
285
286 assert!(small_req.total < medium_req.total);
288 assert!(medium_req.total < large_req.total);
289
290 assert_eq!(small_req.model_memory, small_model);
292 assert_eq!(medium_req.model_memory, medium_model);
293 assert_eq!(large_req.model_memory, large_model);
294
295 let breakdown = medium_req.breakdown_percentages();
297 let total_percent = breakdown.base_percent
298 + breakdown.model_percent
299 + breakdown.cache_percent
300 + breakdown.preload_percent
301 + breakdown.worker_percent;
302 assert!((total_percent - 100.0).abs() < 0.1);
303 }
304
305 #[test]
306 fn test_chunk_size_recommendations() {
307 let manager = MemoryManager::performance_optimized();
308
309 let small_model = 512 * 1024; let medium_model = 10 * 1024 * 1024; let large_model = 200 * 1024 * 1024; let small_chunk = manager.recommended_chunk_size(small_model);
314 let medium_chunk = manager.recommended_chunk_size(medium_model);
315 let large_chunk = manager.recommended_chunk_size(large_model);
316
317 assert!(small_chunk < medium_chunk);
319 assert!(medium_chunk <= large_chunk);
320
321 assert_eq!(medium_chunk, manager.progressive_config().chunk_size);
323 }
324}