1use super::types::{CheckItem, Evidence, EvidenceType, Severity};
12use std::path::Path;
13use std::time::Instant;
14
15pub fn evaluate_all(project_path: &Path) -> Vec<CheckItem> {
17 vec![
18 check_pcie_rule(project_path),
19 check_simd_speedup(project_path),
20 check_wasm_performance(project_path),
21 check_inference_latency(project_path),
22 check_batch_efficiency(project_path),
23 check_parallel_scaling(project_path),
24 check_model_loading(project_path),
25 check_startup_time(project_path),
26 check_test_suite_time(project_path),
27 check_overprocessing(project_path),
28 check_zero_copy(project_path),
29 check_cache_efficiency(project_path),
30 check_cost_model(project_path),
31 check_transport_minimization(project_path),
32 check_inventory_minimization(project_path),
33 ]
34}
35
36pub fn check_pcie_rule(project_path: &Path) -> CheckItem {
38 let start = Instant::now();
39 let mut item = CheckItem::new(
40 "PW-01",
41 "5× PCIe Rule Validation",
42 "GPU dispatch beneficial when compute > 5× transfer",
43 )
44 .with_severity(Severity::Major)
45 .with_tps("Cost-based backend selection");
46
47 let has_gpu = check_for_pattern(project_path, &["wgpu", "cuda", "gpu", "GPU"]);
48 let has_cost_model =
49 check_for_pattern(project_path, &["cost_model", "crossover", "dispatch_threshold"]);
50
51 item = item.with_evidence(Evidence {
52 evidence_type: EvidenceType::StaticAnalysis,
53 description: format!("PCIe rule: gpu={}, cost_model={}", has_gpu, has_cost_model),
54 data: None,
55 files: Vec::new(),
56 });
57
58 if !has_gpu || has_cost_model {
59 item = item.pass();
60 } else {
61 item = item.partial("GPU usage without cost model");
62 }
63
64 item.finish_timed(start)
65}
66
67pub fn check_simd_speedup(project_path: &Path) -> CheckItem {
69 let start = Instant::now();
70 let mut item = CheckItem::new(
71 "PW-02",
72 "SIMD Speedup Verification",
73 "AVX2 provides >2× speedup over scalar",
74 )
75 .with_severity(Severity::Major)
76 .with_tps("Muda (Waiting) reduction");
77
78 let has_simd =
79 check_for_pattern(project_path, &["simd", "avx2", "avx512", "neon", "target_feature"]);
80 let has_benchmarks = project_path.join("benches").exists();
81
82 item = item.with_evidence(Evidence {
83 evidence_type: EvidenceType::StaticAnalysis,
84 description: format!("SIMD: impl={}, benchmarks={}", has_simd, has_benchmarks),
85 data: None,
86 files: Vec::new(),
87 });
88
89 if has_simd && has_benchmarks {
90 item = item.pass();
91 } else if has_simd {
92 item = item.partial("SIMD without speedup benchmarks");
93 } else {
94 item = item.partial("No SIMD optimization");
95 }
96
97 item.finish_timed(start)
98}
99
100pub fn check_wasm_performance(project_path: &Path) -> CheckItem {
102 let start = Instant::now();
103 let mut item = CheckItem::new(
104 "PW-03",
105 "WASM Performance Ratio",
106 "WASM achieves 50-90% native performance",
107 )
108 .with_severity(Severity::Major)
109 .with_tps("Edge deployment efficiency");
110
111 let has_wasm = check_for_pattern(project_path, &["wasm", "wasm32", "wasm-bindgen"]);
112 let has_perf_tests = check_for_pattern(project_path, &["wasm_bench", "native_comparison"]);
113
114 item = item.with_evidence(Evidence {
115 evidence_type: EvidenceType::StaticAnalysis,
116 description: format!("WASM perf: wasm={}, benchmarks={}", has_wasm, has_perf_tests),
117 data: None,
118 files: Vec::new(),
119 });
120
121 if !has_wasm || has_perf_tests {
122 item = item.pass();
123 } else {
124 item = item.partial("WASM without performance comparison");
125 }
126
127 item.finish_timed(start)
128}
129
130pub fn check_inference_latency(project_path: &Path) -> CheckItem {
132 let start = Instant::now();
133 let mut item = CheckItem::new("PW-04", "Inference Latency SLA", "Inference <50ms/token on CPU")
134 .with_severity(Severity::Major)
135 .with_tps("Muda (Waiting) elimination");
136
137 let has_inference = check_for_pattern(project_path, &["inference", "infer", "predict"]);
138 let has_latency_tests = check_for_pattern(project_path, &["latency", "p99", "benchmark"]);
139
140 item = item.with_evidence(Evidence {
141 evidence_type: EvidenceType::StaticAnalysis,
142 description: format!("Latency: inference={}, tests={}", has_inference, has_latency_tests),
143 data: None,
144 files: Vec::new(),
145 });
146
147 if !has_inference || has_latency_tests {
148 item = item.pass();
149 } else {
150 item = item.partial("Inference without latency benchmarks");
151 }
152
153 item.finish_timed(start)
154}
155
156pub fn check_batch_efficiency(project_path: &Path) -> CheckItem {
158 let start = Instant::now();
159 let mut item = CheckItem::new(
160 "PW-05",
161 "Batch Processing Efficiency",
162 "Batching provides near-linear throughput scaling",
163 )
164 .with_severity(Severity::Major)
165 .with_tps("Resource utilization");
166
167 let has_batching = check_for_pattern(project_path, &["batch", "Batch", "batch_size"]);
168 let has_scaling_tests =
169 check_for_pattern(project_path, &["batch_scaling", "throughput", "batch_bench"]);
170
171 item = item.with_evidence(Evidence {
172 evidence_type: EvidenceType::StaticAnalysis,
173 description: format!("Batch: impl={}, tests={}", has_batching, has_scaling_tests),
174 data: None,
175 files: Vec::new(),
176 });
177
178 if !has_batching || has_scaling_tests {
179 item = item.pass();
180 } else {
181 item = item.partial("Batching without scaling verification");
182 }
183
184 item.finish_timed(start)
185}
186
187pub fn check_parallel_scaling(project_path: &Path) -> CheckItem {
189 let start = Instant::now();
190 let mut item = CheckItem::new(
191 "PW-06",
192 "Parallel Scaling Efficiency",
193 "Multi-threaded operations scale with cores",
194 )
195 .with_severity(Severity::Major)
196 .with_tps("Resource utilization");
197
198 let has_parallel = check_for_pattern(project_path, &["rayon", "parallel", "thread", "spawn"]);
199 let has_scaling_tests =
200 check_for_pattern(project_path, &["parallel_bench", "scaling", "amdahl"]);
201
202 item = item.with_evidence(Evidence {
203 evidence_type: EvidenceType::StaticAnalysis,
204 description: format!("Parallel: impl={}, tests={}", has_parallel, has_scaling_tests),
205 data: None,
206 files: Vec::new(),
207 });
208
209 if has_parallel && has_scaling_tests {
210 item = item.pass();
211 } else if has_parallel {
212 item = item.partial("Parallelization without scaling benchmarks");
213 } else {
214 item = item.partial("No parallel optimization");
215 }
216
217 item.finish_timed(start)
218}
219
220pub fn check_model_loading(project_path: &Path) -> CheckItem {
222 let start = Instant::now();
223 let mut item = CheckItem::new("PW-07", "Model Loading Time", "Model loading <2s per GB")
224 .with_severity(Severity::Minor)
225 .with_tps("Muda (Waiting)");
226
227 let has_model_loading = check_for_pattern(project_path, &["load_model", "ModelLoader", "mmap"]);
228 let has_loading_tests = check_for_pattern(project_path, &["load_bench", "loading_time"]);
229
230 item = item.with_evidence(Evidence {
231 evidence_type: EvidenceType::StaticAnalysis,
232 description: format!("Loading: impl={}, tests={}", has_model_loading, has_loading_tests),
233 data: None,
234 files: Vec::new(),
235 });
236
237 if !has_model_loading || has_loading_tests {
238 item = item.pass();
239 } else {
240 item = item.partial("Model loading without benchmarks");
241 }
242
243 item.finish_timed(start)
244}
245
246pub fn check_startup_time(project_path: &Path) -> CheckItem {
248 let start = Instant::now();
249 let mut item = CheckItem::new("PW-08", "Startup Time", "CLI startup <100ms")
250 .with_severity(Severity::Minor)
251 .with_tps("Developer experience");
252
253 let makefile = project_path.join("Makefile");
255 let has_startup_bench = makefile
256 .exists()
257 .then(|| std::fs::read_to_string(&makefile).ok())
258 .flatten()
259 .map(|c| c.contains("hyperfine") || c.contains("startup"))
260 .unwrap_or(false);
261
262 item = item.with_evidence(Evidence {
263 evidence_type: EvidenceType::StaticAnalysis,
264 description: format!("Startup: benchmark={}", has_startup_bench),
265 data: None,
266 files: Vec::new(),
267 });
268
269 if has_startup_bench {
270 item = item.pass();
271 } else {
272 item = item.partial("No startup time benchmarking");
273 }
274
275 item.finish_timed(start)
276}
277
278pub fn check_test_suite_time(project_path: &Path) -> CheckItem {
280 let start = Instant::now();
281 let mut item = CheckItem::new("PW-09", "Test Suite Performance", "Full test suite <5 minutes")
282 .with_severity(Severity::Major)
283 .with_tps("Muda (Waiting) in CI");
284
285 let has_nextest = project_path.join(".config/nextest.toml").exists();
287 let has_parallel_tests = check_for_pattern(project_path, &["nextest", "test-threads"]);
288
289 item = item.with_evidence(Evidence {
290 evidence_type: EvidenceType::StaticAnalysis,
291 description: format!("Test perf: nextest={}, parallel={}", has_nextest, has_parallel_tests),
292 data: None,
293 files: Vec::new(),
294 });
295
296 if has_nextest || has_parallel_tests {
297 item = item.pass();
298 } else {
299 item = item.partial("Tests without optimization (consider nextest)");
300 }
301
302 item.finish_timed(start)
303}
304
305pub fn check_overprocessing(project_path: &Path) -> CheckItem {
307 let start = Instant::now();
308 let mut item = CheckItem::new(
309 "PW-10",
310 "Overprocessing Detection",
311 "Model complexity justified by improvement",
312 )
313 .with_severity(Severity::Major)
314 .with_tps("Muda (Overprocessing)");
315
316 let has_baseline = check_for_pattern(project_path, &["baseline", "simple_model", "comparison"]);
317 let has_complexity_analysis =
318 check_for_pattern(project_path, &["complexity", "flops", "parameters"]);
319
320 item = item.with_evidence(Evidence {
321 evidence_type: EvidenceType::StaticAnalysis,
322 description: format!(
323 "Overprocessing: baseline={}, analysis={}",
324 has_baseline, has_complexity_analysis
325 ),
326 data: None,
327 files: Vec::new(),
328 });
329
330 if has_baseline {
331 item = item.pass();
332 } else {
333 let is_complex = check_for_pattern(project_path, &["transformer", "neural", "deep"]);
334 if !is_complex {
335 item = item.pass();
336 } else {
337 item = item.partial("Complex models without baseline comparison");
338 }
339 }
340
341 item.finish_timed(start)
342}
343
344pub fn check_zero_copy(project_path: &Path) -> CheckItem {
346 let start = Instant::now();
347 let mut item = CheckItem::new(
348 "PW-11",
349 "Zero-Copy Operation Verification",
350 "Hot paths operate without allocation",
351 )
352 .with_severity(Severity::Minor)
353 .with_tps("Muda (Motion) — memory efficiency");
354
355 let has_zero_copy =
356 check_for_pattern(project_path, &["zero_copy", "no_alloc", "in_place", "&mut"]);
357 let has_alloc_tests =
358 check_for_pattern(project_path, &["allocation_free", "heaptrack", "alloc_count"]);
359
360 item = item.with_evidence(Evidence {
361 evidence_type: EvidenceType::StaticAnalysis,
362 description: format!("Zero-copy: impl={}, tests={}", has_zero_copy, has_alloc_tests),
363 data: None,
364 files: Vec::new(),
365 });
366
367 if has_alloc_tests {
368 item = item.pass();
369 } else if has_zero_copy {
370 item = item.partial("Zero-copy patterns (verify with tests)");
371 } else {
372 item = item.partial("No explicit zero-copy optimization");
373 }
374
375 item.finish_timed(start)
376}
377
378pub fn check_cache_efficiency(project_path: &Path) -> CheckItem {
380 let start = Instant::now();
381 let mut item = CheckItem::new("PW-12", "Cache Efficiency", "Cache >90% hit ratio")
382 .with_severity(Severity::Minor)
383 .with_tps("Muda (Waiting) reduction");
384
385 let has_cache = check_for_pattern(project_path, &["cache", "Cache", "lru", "memoize"]);
386 let has_cache_metrics =
387 check_for_pattern(project_path, &["hit_ratio", "cache_stats", "cache_hit"]);
388
389 item = item.with_evidence(Evidence {
390 evidence_type: EvidenceType::StaticAnalysis,
391 description: format!("Cache: impl={}, metrics={}", has_cache, has_cache_metrics),
392 data: None,
393 files: Vec::new(),
394 });
395
396 if !has_cache || has_cache_metrics {
397 item = item.pass();
398 } else {
399 item = item.partial("Cache without efficiency metrics");
400 }
401
402 item.finish_timed(start)
403}
404
405pub fn check_cost_model(project_path: &Path) -> CheckItem {
407 let start = Instant::now();
408 let mut item = CheckItem::new(
409 "PW-13",
410 "Cost Model Accuracy",
411 "Backend selection predicts optimal choice >90%",
412 )
413 .with_severity(Severity::Major)
414 .with_tps("Intelligent automation (Jidoka)");
415
416 let has_cost_model =
417 check_for_pattern(project_path, &["cost_model", "CostModel", "backend_selection"]);
418 let has_accuracy_tests = check_for_pattern(project_path, &["prediction_accuracy", "cost_test"]);
419
420 item = item.with_evidence(Evidence {
421 evidence_type: EvidenceType::StaticAnalysis,
422 description: format!("Cost model: impl={}, tests={}", has_cost_model, has_accuracy_tests),
423 data: None,
424 files: Vec::new(),
425 });
426
427 if !has_cost_model || has_accuracy_tests {
428 item = item.pass();
429 } else {
430 item = item.partial("Cost model without accuracy verification");
431 }
432
433 item.finish_timed(start)
434}
435
436pub fn check_transport_minimization(project_path: &Path) -> CheckItem {
438 let start = Instant::now();
439 let mut item = CheckItem::new(
440 "PW-14",
441 "Data Transport Minimization",
442 "Data movement minimized through co-location",
443 )
444 .with_severity(Severity::Minor)
445 .with_tps("Muda (Transport)");
446
447 let has_colocation =
448 check_for_pattern(project_path, &["colocation", "locality", "data_parallel"]);
449
450 item = item.with_evidence(Evidence {
451 evidence_type: EvidenceType::StaticAnalysis,
452 description: format!("Transport: colocation={}", has_colocation),
453 data: None,
454 files: Vec::new(),
455 });
456
457 let has_distributed = check_for_pattern(project_path, &["distributed", "network", "remote"]);
458 if !has_distributed || has_colocation {
459 item = item.pass();
460 } else {
461 item = item.partial("Distributed compute without locality optimization");
462 }
463
464 item.finish_timed(start)
465}
466
467pub fn check_inventory_minimization(project_path: &Path) -> CheckItem {
469 let start = Instant::now();
470 let mut item = CheckItem::new("PW-15", "Inventory Minimization", "No hoarded unused data")
471 .with_severity(Severity::Minor)
472 .with_tps("Muda (Inventory)");
473
474 let has_lifecycle =
475 check_for_pattern(project_path, &["lifecycle", "retention", "ttl", "expiration"]);
476 let has_cleanup = check_for_pattern(project_path, &["cleanup", "prune", "garbage_collect"]);
477
478 item = item.with_evidence(Evidence {
479 evidence_type: EvidenceType::StaticAnalysis,
480 description: format!("Inventory: lifecycle={}, cleanup={}", has_lifecycle, has_cleanup),
481 data: None,
482 files: Vec::new(),
483 });
484
485 let stores_data = check_for_pattern(project_path, &["store", "persist", "save"]);
486 if !stores_data || has_lifecycle || has_cleanup {
487 item = item.pass();
488 } else {
489 item = item.partial("Data storage without lifecycle management");
490 }
491
492 item.finish_timed(start)
493}
494
495fn check_for_pattern(project_path: &Path, patterns: &[&str]) -> bool {
496 super::helpers::source_contains_pattern(project_path, patterns)
497}
498
499#[cfg(test)]
500mod tests {
501 use super::*;
502 use std::path::PathBuf;
503
504 #[test]
505 fn test_evaluate_all_returns_15_items() {
506 let path = PathBuf::from(".");
507 let items = evaluate_all(&path);
508 assert_eq!(items.len(), 15);
509 }
510
511 #[test]
512 fn test_all_items_have_tps_principle() {
513 let path = PathBuf::from(".");
514 for item in evaluate_all(&path) {
515 assert!(!item.tps_principle.is_empty(), "Item {} missing TPS", item.id);
516 }
517 }
518
519 #[test]
520 fn test_all_items_have_evidence() {
521 let path = PathBuf::from(".");
522 for item in evaluate_all(&path) {
523 assert!(!item.evidence.is_empty(), "Item {} missing evidence", item.id);
524 }
525 }
526
527 #[test]
528 fn test_check_pcie_rule() {
529 let path = PathBuf::from(".");
530 let item = check_pcie_rule(&path);
531 assert_eq!(item.id, "PW-01");
532 assert!(item.name.contains("PCIe"));
533 assert_eq!(item.severity, Severity::Major);
534 assert!(item.tps_principle.contains("Cost-based"));
535 }
536
537 #[test]
538 fn test_check_simd_speedup() {
539 let path = PathBuf::from(".");
540 let item = check_simd_speedup(&path);
541 assert_eq!(item.id, "PW-02");
542 assert!(item.name.contains("SIMD"));
543 assert_eq!(item.severity, Severity::Major);
544 assert!(item.tps_principle.contains("Muda"));
545 }
546
547 #[test]
548 fn test_check_wasm_performance() {
549 let path = PathBuf::from(".");
550 let item = check_wasm_performance(&path);
551 assert_eq!(item.id, "PW-03");
552 assert!(item.name.contains("WASM"));
553 assert_eq!(item.severity, Severity::Major);
554 }
555
556 #[test]
557 fn test_check_inference_latency() {
558 let path = PathBuf::from(".");
559 let item = check_inference_latency(&path);
560 assert_eq!(item.id, "PW-04");
561 assert!(item.name.contains("Inference"));
562 assert_eq!(item.severity, Severity::Major);
563 }
564
565 #[test]
566 fn test_check_batch_efficiency() {
567 let path = PathBuf::from(".");
568 let item = check_batch_efficiency(&path);
569 assert_eq!(item.id, "PW-05");
570 assert!(item.name.contains("Batch"));
571 assert_eq!(item.severity, Severity::Major);
572 }
573
574 #[test]
575 fn test_check_parallel_scaling() {
576 let path = PathBuf::from(".");
577 let item = check_parallel_scaling(&path);
578 assert_eq!(item.id, "PW-06");
579 assert!(item.name.contains("Parallel"));
580 assert_eq!(item.severity, Severity::Major);
581 }
582
583 #[test]
584 fn test_check_model_loading() {
585 let path = PathBuf::from(".");
586 let item = check_model_loading(&path);
587 assert_eq!(item.id, "PW-07");
588 assert!(item.name.contains("Model Loading"));
589 assert_eq!(item.severity, Severity::Minor);
590 }
591
592 #[test]
593 fn test_check_startup_time() {
594 let path = PathBuf::from(".");
595 let item = check_startup_time(&path);
596 assert_eq!(item.id, "PW-08");
597 assert!(item.name.contains("Startup"));
598 assert_eq!(item.severity, Severity::Minor);
599 }
600
601 #[test]
602 fn test_check_test_suite_time() {
603 let path = PathBuf::from(".");
604 let item = check_test_suite_time(&path);
605 assert_eq!(item.id, "PW-09");
606 assert!(item.name.contains("Test Suite"));
607 assert_eq!(item.severity, Severity::Major);
608 }
609
610 #[test]
611 fn test_check_overprocessing() {
612 let path = PathBuf::from(".");
613 let item = check_overprocessing(&path);
614 assert_eq!(item.id, "PW-10");
615 assert!(item.name.contains("Overprocessing"));
616 assert_eq!(item.severity, Severity::Major);
617 }
618
619 #[test]
620 fn test_check_zero_copy() {
621 let path = PathBuf::from(".");
622 let item = check_zero_copy(&path);
623 assert_eq!(item.id, "PW-11");
624 assert!(item.name.contains("Zero-Copy"));
625 assert_eq!(item.severity, Severity::Minor);
626 }
627
628 #[test]
629 fn test_check_cache_efficiency() {
630 let path = PathBuf::from(".");
631 let item = check_cache_efficiency(&path);
632 assert_eq!(item.id, "PW-12");
633 assert!(item.name.contains("Cache"));
634 assert_eq!(item.severity, Severity::Minor);
635 }
636
637 #[test]
638 fn test_check_cost_model() {
639 let path = PathBuf::from(".");
640 let item = check_cost_model(&path);
641 assert_eq!(item.id, "PW-13");
642 assert!(item.name.contains("Cost Model"));
643 assert_eq!(item.severity, Severity::Major);
644 }
645
646 #[test]
647 fn test_check_transport_minimization() {
648 let path = PathBuf::from(".");
649 let item = check_transport_minimization(&path);
650 assert_eq!(item.id, "PW-14");
651 assert!(item.name.contains("Transport"));
652 assert_eq!(item.severity, Severity::Minor);
653 }
654
655 #[test]
656 fn test_check_inventory_minimization() {
657 let path = PathBuf::from(".");
658 let item = check_inventory_minimization(&path);
659 assert_eq!(item.id, "PW-15");
660 assert!(item.name.contains("Inventory"));
661 assert_eq!(item.severity, Severity::Minor);
662 }
663
664 #[test]
665 fn test_item_ids_are_unique() {
666 let path = PathBuf::from(".");
667 let items = evaluate_all(&path);
668 let mut ids: Vec<&str> = items.iter().map(|i| i.id.as_str()).collect();
669 ids.sort();
670 ids.dedup();
671 assert_eq!(ids.len(), 15, "All item IDs should be unique");
672 }
673
674 #[test]
675 fn test_item_names_are_descriptive() {
676 let path = PathBuf::from(".");
677 for item in evaluate_all(&path) {
678 assert!(item.name.len() >= 10, "Item {} name too short: {}", item.id, item.name);
679 }
680 }
681
682 #[test]
687 fn test_check_overprocessing_complex_without_baseline() {
688 let temp_dir = std::env::temp_dir().join("test_pw10_complex");
690 let _ = std::fs::remove_dir_all(&temp_dir);
691 std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
692
693 std::fs::write(
695 temp_dir.join("src/model.rs"),
696 "pub struct TransformerBlock { layers: Vec<NeuralLayer> }\npub fn deep_forward() {}",
697 )
698 .expect("unexpected failure");
699
700 let result = check_overprocessing(&temp_dir);
701 assert_eq!(result.id, "PW-10");
702 assert_eq!(result.status, super::super::types::CheckStatus::Partial);
704 assert!(result.rejection_reason.as_deref().unwrap_or("").contains("baseline"));
705
706 let _ = std::fs::remove_dir_all(&temp_dir);
707 }
708
709 #[test]
710 fn test_check_overprocessing_not_complex_no_baseline() {
711 let temp_dir = std::env::temp_dir().join("test_pw10_simple");
713 let _ = std::fs::remove_dir_all(&temp_dir);
714 std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
715
716 std::fs::write(temp_dir.join("src/lib.rs"), "pub fn add(a: i32, b: i32) -> i32 { a + b }")
717 .expect("unexpected failure");
718
719 let result = check_overprocessing(&temp_dir);
720 assert_eq!(result.id, "PW-10");
721 assert_eq!(result.status, super::super::types::CheckStatus::Pass);
722
723 let _ = std::fs::remove_dir_all(&temp_dir);
724 }
725
726 #[test]
727 fn test_check_overprocessing_with_baseline() {
728 let temp_dir = std::env::temp_dir().join("test_pw10_baseline");
730 let _ = std::fs::remove_dir_all(&temp_dir);
731 std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
732
733 std::fs::write(
734 temp_dir.join("src/lib.rs"),
735 "pub fn baseline_comparison() -> f64 { 0.0 }\npub fn transformer_forward() {}",
736 )
737 .expect("unexpected failure");
738
739 let result = check_overprocessing(&temp_dir);
740 assert_eq!(result.id, "PW-10");
741 assert_eq!(result.status, super::super::types::CheckStatus::Pass);
742
743 let _ = std::fs::remove_dir_all(&temp_dir);
744 }
745
746 fn empty_dir() -> tempfile::TempDir {
751 tempfile::TempDir::new().expect("Failed to create temp dir")
752 }
753
754 #[test]
755 fn test_pcie_rule_gpu_no_cost_model() {
756 let dir = empty_dir();
757 let src_dir = dir.path().join("src");
758 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
759 std::fs::write(src_dir.join("gpu.rs"), "fn gpu_compute() { use wgpu::Device; }")
760 .expect("unexpected failure");
761 let item = check_pcie_rule(dir.path());
762 assert_eq!(item.id, "PW-01");
763 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
764 assert!(item
765 .rejection_reason
766 .as_ref()
767 .expect("unexpected failure")
768 .contains("GPU usage without cost model"));
769 }
770
771 #[test]
772 fn test_simd_no_benchmarks() {
773 let dir = empty_dir();
774 let src_dir = dir.path().join("src");
775 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
776 std::fs::write(
777 src_dir.join("simd.rs"),
778 "#[target_feature(enable = \"avx2\")] fn simd_dot() {}",
779 )
780 .expect("unexpected failure");
781 let item = check_simd_speedup(dir.path());
782 assert_eq!(item.id, "PW-02");
783 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
784 assert!(item
785 .rejection_reason
786 .as_ref()
787 .expect("unexpected failure")
788 .contains("SIMD without speedup benchmarks"));
789 }
790
791 #[test]
792 fn test_simd_no_simd_at_all() {
793 let dir = empty_dir();
794 let item = check_simd_speedup(dir.path());
795 assert_eq!(item.id, "PW-02");
796 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
797 assert!(item
798 .rejection_reason
799 .as_ref()
800 .expect("unexpected failure")
801 .contains("No SIMD optimization"));
802 }
803
804 #[test]
805 fn test_simd_with_benchmarks() {
806 let dir = empty_dir();
807 let src_dir = dir.path().join("src");
808 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
809 std::fs::write(
810 src_dir.join("simd.rs"),
811 "#[target_feature(enable = \"avx2\")] fn simd_dot() {}",
812 )
813 .expect("unexpected failure");
814 std::fs::create_dir_all(dir.path().join("benches")).expect("mkdir failed");
815 let item = check_simd_speedup(dir.path());
816 assert_eq!(item.id, "PW-02");
817 assert_eq!(item.status, super::super::types::CheckStatus::Pass);
818 }
819
820 #[test]
821 fn test_parallel_no_scaling_tests() {
822 let dir = empty_dir();
823 let src_dir = dir.path().join("src");
824 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
825 std::fs::write(src_dir.join("par.rs"), "use rayon::prelude::*; fn parallel_map() {}")
826 .expect("unexpected failure");
827 let item = check_parallel_scaling(dir.path());
828 assert_eq!(item.id, "PW-06");
829 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
830 assert!(item
831 .rejection_reason
832 .as_ref()
833 .expect("unexpected failure")
834 .contains("Parallelization without scaling"));
835 }
836
837 #[test]
838 fn test_parallel_no_parallel() {
839 let dir = empty_dir();
840 let item = check_parallel_scaling(dir.path());
841 assert_eq!(item.id, "PW-06");
842 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
843 assert!(item
844 .rejection_reason
845 .as_ref()
846 .expect("unexpected failure")
847 .contains("No parallel optimization"));
848 }
849
850 #[test]
851 fn test_parallel_with_scaling_tests() {
852 let dir = empty_dir();
853 let src_dir = dir.path().join("src");
854 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
855 std::fs::write(
856 src_dir.join("par.rs"),
857 "use rayon::prelude::*; fn scaling() {} fn amdahl() {}",
858 )
859 .expect("unexpected failure");
860 let item = check_parallel_scaling(dir.path());
861 assert_eq!(item.id, "PW-06");
862 assert_eq!(item.status, super::super::types::CheckStatus::Pass);
863 }
864
865 #[test]
866 fn test_zero_copy_patterns_no_tests() {
867 let dir = empty_dir();
868 let src_dir = dir.path().join("src");
869 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
870 std::fs::write(
871 src_dir.join("zc.rs"),
872 "fn process_in_place(data: &mut [f32]) { /* zero_copy */ }",
873 )
874 .expect("unexpected failure");
875 let item = check_zero_copy(dir.path());
876 assert_eq!(item.id, "PW-11");
877 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
878 assert!(item
879 .rejection_reason
880 .as_ref()
881 .expect("unexpected failure")
882 .contains("Zero-copy patterns"));
883 }
884
885 #[test]
886 fn test_zero_copy_no_patterns() {
887 let dir = empty_dir();
888 let item = check_zero_copy(dir.path());
889 assert_eq!(item.id, "PW-11");
890 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
891 assert!(item
892 .rejection_reason
893 .as_ref()
894 .expect("unexpected failure")
895 .contains("No explicit zero-copy"));
896 }
897
898 #[test]
899 fn test_zero_copy_with_alloc_tests() {
900 let dir = empty_dir();
901 let src_dir = dir.path().join("src");
902 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
903 std::fs::write(
904 src_dir.join("test.rs"),
905 "fn allocation_free_test() { let c = alloc_count(); }",
906 )
907 .expect("unexpected failure");
908 let item = check_zero_copy(dir.path());
909 assert_eq!(item.id, "PW-11");
910 assert_eq!(item.status, super::super::types::CheckStatus::Pass);
911 }
912
913 #[test]
914 fn test_startup_time_with_hyperfine() {
915 let dir = empty_dir();
916 std::fs::write(dir.path().join("Makefile"), "bench:\n\thyperfine ./target/release/app")
917 .expect("unexpected failure");
918 let item = check_startup_time(dir.path());
919 assert_eq!(item.id, "PW-08");
920 assert_eq!(item.status, super::super::types::CheckStatus::Pass);
921 }
922
923 #[test]
924 fn test_startup_time_no_makefile() {
925 let dir = empty_dir();
926 let item = check_startup_time(dir.path());
927 assert_eq!(item.id, "PW-08");
928 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
929 }
930
931 #[test]
932 fn test_startup_time_makefile_no_hyperfine() {
933 let dir = empty_dir();
934 std::fs::write(dir.path().join("Makefile"), "build:\n\tcargo build --release")
935 .expect("unexpected failure");
936 let item = check_startup_time(dir.path());
937 assert_eq!(item.id, "PW-08");
938 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
939 }
940
941 #[test]
942 fn test_startup_time_makefile_with_startup_keyword() {
943 let dir = empty_dir();
944 std::fs::write(dir.path().join("Makefile"), "bench-startup:\n\ttime ./app")
945 .expect("fs write failed");
946 let item = check_startup_time(dir.path());
947 assert_eq!(item.id, "PW-08");
948 assert_eq!(item.status, super::super::types::CheckStatus::Pass);
949 }
950
951 #[test]
952 fn test_test_suite_with_nextest_config() {
953 let dir = empty_dir();
954 let config_dir = dir.path().join(".config");
955 std::fs::create_dir_all(&config_dir).expect("mkdir failed");
956 std::fs::write(config_dir.join("nextest.toml"), "[profile.default]\n")
957 .expect("fs write failed");
958 let item = check_test_suite_time(dir.path());
959 assert_eq!(item.id, "PW-09");
960 assert_eq!(item.status, super::super::types::CheckStatus::Pass);
961 }
962
963 #[test]
964 fn test_test_suite_no_nextest() {
965 let dir = empty_dir();
966 let item = check_test_suite_time(dir.path());
967 assert_eq!(item.id, "PW-09");
968 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
969 }
970
971 #[test]
972 fn test_wasm_no_perf_tests() {
973 let dir = empty_dir();
974 let src_dir = dir.path().join("src");
975 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
976 std::fs::write(src_dir.join("wasm.rs"), "use wasm_bindgen::prelude::*;")
977 .expect("fs write failed");
978 let item = check_wasm_performance(dir.path());
979 assert_eq!(item.id, "PW-03");
980 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
981 assert!(item
982 .rejection_reason
983 .as_ref()
984 .expect("unexpected failure")
985 .contains("WASM without performance comparison"));
986 }
987
988 #[test]
989 fn test_inference_no_latency() {
990 let dir = empty_dir();
991 let src_dir = dir.path().join("src");
992 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
993 std::fs::write(
994 src_dir.join("serve.rs"),
995 "fn inference(model: &Model) -> Vec<f32> { vec![] }",
996 )
997 .expect("unexpected failure");
998 let item = check_inference_latency(dir.path());
999 assert_eq!(item.id, "PW-04");
1000 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1001 }
1002
1003 #[test]
1004 fn test_batch_no_scaling() {
1005 let dir = empty_dir();
1006 let src_dir = dir.path().join("src");
1007 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1008 std::fs::write(src_dir.join("batch.rs"), "fn batch_process(batch_size: usize) {}")
1009 .expect("unexpected failure");
1010 let item = check_batch_efficiency(dir.path());
1011 assert_eq!(item.id, "PW-05");
1012 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1013 }
1014
1015 #[test]
1016 fn test_model_loading_no_benchmarks() {
1017 let dir = empty_dir();
1018 let src_dir = dir.path().join("src");
1019 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1020 std::fs::write(src_dir.join("loader.rs"), "fn load_model(path: &str) { mmap(path); }")
1021 .expect("unexpected failure");
1022 let item = check_model_loading(dir.path());
1023 assert_eq!(item.id, "PW-07");
1024 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1025 }
1026
1027 #[test]
1028 fn test_cache_no_metrics() {
1029 let dir = empty_dir();
1030 let src_dir = dir.path().join("src");
1031 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1032 std::fs::write(src_dir.join("cache.rs"), "struct LruCache {} fn memoize() {}")
1033 .expect("unexpected failure");
1034 let item = check_cache_efficiency(dir.path());
1035 assert_eq!(item.id, "PW-12");
1036 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1037 }
1038
1039 #[test]
1040 fn test_cost_model_no_tests() {
1041 let dir = empty_dir();
1042 let src_dir = dir.path().join("src");
1043 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1044 std::fs::write(src_dir.join("cost.rs"), "struct CostModel {} fn backend_selection() {}")
1045 .expect("unexpected failure");
1046 let item = check_cost_model(dir.path());
1047 assert_eq!(item.id, "PW-13");
1048 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1049 }
1050
1051 #[test]
1052 fn test_transport_distributed_no_colocation() {
1053 let dir = empty_dir();
1054 let src_dir = dir.path().join("src");
1055 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1056 std::fs::write(src_dir.join("dist.rs"), "fn distributed(remote: &str) { network_send(); }")
1057 .expect("unexpected failure");
1058 let item = check_transport_minimization(dir.path());
1059 assert_eq!(item.id, "PW-14");
1060 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1061 }
1062
1063 #[test]
1064 fn test_inventory_no_lifecycle() {
1065 let dir = empty_dir();
1066 let src_dir = dir.path().join("src");
1067 std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1068 std::fs::write(src_dir.join("storage.rs"), "fn store(key: &str) { persist(); save(); }")
1069 .expect("unexpected failure");
1070 let item = check_inventory_minimization(dir.path());
1071 assert_eq!(item.id, "PW-15");
1072 assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1073 }
1074
1075 #[test]
1076 fn test_evaluate_all_empty_project() {
1077 let dir = empty_dir();
1078 let items = evaluate_all(dir.path());
1079 assert_eq!(items.len(), 15);
1080 for item in &items {
1081 assert!(!item.evidence.is_empty(), "Item {} missing evidence", item.id);
1082 }
1083 }
1084}