@@ -494,7 +494,230 @@ mod tests {
494
494
assert_eq ! ( bucket_result, improved_result) ;
495
495
496
496
// Bucket approach should be faster for small integer weights
497
- println ! ( "Bucket duration: {:?}" , bucket_duration) ;
498
- println ! ( "Improved duration: {:?}" , improved_duration) ;
497
+ println ! ( "Bucket duration: {bucket_duration:?}" ) ;
498
+ println ! ( "Improved duration: {improved_duration:?}" ) ;
499
+ }
500
+
501
+ #[ test]
502
+ fn test_zero_trait_implementations ( ) {
503
+ use super :: Zero ;
504
+ // Test all Zero trait implementations
505
+ assert_eq ! ( usize :: zero( ) , 0 ) ;
506
+ assert_eq ! ( isize :: zero( ) , 0 ) ;
507
+ assert_eq ! ( u32 :: zero( ) , 0 ) ;
508
+ assert_eq ! ( i32 :: zero( ) , 0 ) ;
509
+ assert_eq ! ( u64 :: zero( ) , 0 ) ;
510
+ assert_eq ! ( i64 :: zero( ) , 0 ) ;
511
+ assert_eq ! ( f32 :: zero( ) , 0.0 ) ;
512
+ assert_eq ! ( f64 :: zero( ) , 0.0 ) ;
513
+ }
514
+
515
+ #[ test]
516
+ fn test_vertex_distance_ordering ( ) {
517
+ use super :: VertexDistance ;
518
+
519
+ // Test ordering behavior for min-heap (reverse ordering)
520
+ let vd1 = VertexDistance {
521
+ vertex : 1 ,
522
+ distance : 5 ,
523
+ } ;
524
+ let vd2 = VertexDistance {
525
+ vertex : 2 ,
526
+ distance : 3 ,
527
+ } ;
528
+
529
+ // vd2 should be "greater" (comes first in min-heap) due to smaller distance
530
+ assert ! ( vd2 > vd1) ;
531
+
532
+ // Test equality
533
+ let vd3 = VertexDistance {
534
+ vertex : 1 ,
535
+ distance : 5 ,
536
+ } ;
537
+ assert_eq ! ( vd1. cmp( & vd3) , std:: cmp:: Ordering :: Equal ) ;
538
+
539
+ // Test same distance, different vertices
540
+ let vd4 = VertexDistance {
541
+ vertex : 3 ,
542
+ distance : 5 ,
543
+ } ;
544
+ assert_ne ! ( vd1. cmp( & vd4) , std:: cmp:: Ordering :: Equal ) ;
545
+ }
546
+
547
+ #[ test]
548
+ fn test_improved_shortest_path_edge_cases ( ) {
549
+ // Test empty graph
550
+ let empty_graph: Graph < i32 , i32 > = BTreeMap :: new ( ) ;
551
+ let result = improved_shortest_path ( & empty_graph, 0 ) ;
552
+ assert_eq ! ( result. len( ) , 1 ) ;
553
+ assert_eq ! ( result[ & 0 ] , None ) ;
554
+
555
+ // Test graph with only one vertex and no edges
556
+ let mut single_vertex: Graph < i32 , i32 > = BTreeMap :: new ( ) ;
557
+ single_vertex. insert ( 0 , BTreeMap :: new ( ) ) ;
558
+ let result = improved_shortest_path ( & single_vertex, 0 ) ;
559
+ assert_eq ! ( result. len( ) , 1 ) ;
560
+ assert_eq ! ( result[ & 0 ] , None ) ;
561
+
562
+ // Test disconnected vertices
563
+ let mut disconnected: Graph < i32 , i32 > = BTreeMap :: new ( ) ;
564
+ disconnected. insert ( 0 , BTreeMap :: new ( ) ) ;
565
+ disconnected. insert ( 1 , BTreeMap :: new ( ) ) ;
566
+ disconnected. insert ( 2 , BTreeMap :: new ( ) ) ;
567
+ let result = improved_shortest_path ( & disconnected, 0 ) ;
568
+ assert_eq ! ( result. len( ) , 1 ) ;
569
+ assert_eq ! ( result[ & 0 ] , None ) ;
570
+ }
571
+
572
+ #[ test]
573
+ fn test_bucket_shortest_path_edge_cases ( ) {
574
+ // Test with max_weight = 0
575
+ let mut graph = BTreeMap :: new ( ) ;
576
+ add_edge ( & mut graph, 0 , 1 , 0 ) ;
577
+
578
+ let result = bucket_shortest_path ( & graph, 0 , 0 ) ;
579
+ assert_eq ! ( result[ & 0 ] , None ) ;
580
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 0 ) ) ) ;
581
+
582
+ // Test with weights exceeding max_weight
583
+ let mut graph = BTreeMap :: new ( ) ;
584
+ add_edge ( & mut graph, 0 , 1 , 5 ) ;
585
+ add_edge ( & mut graph, 1 , 2 , 3 ) ;
586
+
587
+ let result = bucket_shortest_path ( & graph, 0 , 3 ) ;
588
+ // Should still work but may not find optimal path for vertex 2
589
+ assert_eq ! ( result[ & 0 ] , None ) ;
590
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 5 ) ) ) ;
591
+ }
592
+
593
+ #[ test]
594
+ fn test_adaptive_shortest_path_edge_cases ( ) {
595
+ // Test with empty graph
596
+ let empty_graph: Graph < i32 , usize > = BTreeMap :: new ( ) ;
597
+ let result = adaptive_shortest_path ( & empty_graph, 0 , 10 ) ;
598
+ assert_eq ! ( result. len( ) , 1 ) ;
599
+ assert_eq ! ( result[ & 0 ] , None ) ;
600
+
601
+ // Test threshold behavior - should choose bucket for small weights
602
+ let mut small_weights = BTreeMap :: new ( ) ;
603
+ add_edge ( & mut small_weights, 0 , 1 , 2 ) ;
604
+ add_edge ( & mut small_weights, 1 , 2 , 1 ) ;
605
+
606
+ let result = adaptive_shortest_path ( & small_weights, 0 , 5 ) ;
607
+ assert_eq ! ( result[ & 0 ] , None ) ;
608
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 2 ) ) ) ;
609
+ assert_eq ! ( result[ & 2 ] , Some ( ( 1 , 3 ) ) ) ;
610
+
611
+ // Test threshold behavior - should choose improved for large weights
612
+ let mut large_weights = BTreeMap :: new ( ) ;
613
+ add_edge ( & mut large_weights, 0 , 1 , 10 ) ;
614
+ add_edge ( & mut large_weights, 1 , 2 , 15 ) ;
615
+
616
+ let result = adaptive_shortest_path ( & large_weights, 0 , 5 ) ;
617
+ assert_eq ! ( result[ & 0 ] , None ) ;
618
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 10 ) ) ) ;
619
+ assert_eq ! ( result[ & 2 ] , Some ( ( 1 , 25 ) ) ) ;
620
+ }
621
+
622
+ #[ test]
623
+ fn test_priority_queue_behavior ( ) {
624
+ // Test that priority queue correctly handles duplicate vertices
625
+ let mut graph = BTreeMap :: new ( ) ;
626
+ add_edge ( & mut graph, 0 , 1 , 5 ) ;
627
+ add_edge ( & mut graph, 0 , 2 , 3 ) ;
628
+ add_edge ( & mut graph, 2 , 1 , 1 ) ; // This creates a shorter path to 1
629
+
630
+ let result = improved_shortest_path ( & graph, 0 ) ;
631
+
632
+ // Should find shortest path: 0 -> 2 -> 1 (distance 4)
633
+ assert_eq ! ( result[ & 0 ] , None ) ;
634
+ assert_eq ! ( result[ & 2 ] , Some ( ( 0 , 3 ) ) ) ;
635
+ assert_eq ! ( result[ & 1 ] . unwrap( ) . 1 , 4 ) ; // Distance should be 4, not 5
636
+ }
637
+
638
+ #[ test]
639
+ fn test_bucket_algorithm_empty_buckets ( ) {
640
+ // Test bucket algorithm with gaps in distances
641
+ let mut graph = BTreeMap :: new ( ) ;
642
+ add_edge ( & mut graph, 0 , 1 , 2 ) ;
643
+ add_edge ( & mut graph, 1 , 2 , 5 ) ; // Creates gap in bucket indices
644
+
645
+ let result = bucket_shortest_path ( & graph, 0 , 10 ) ;
646
+
647
+ assert_eq ! ( result[ & 0 ] , None ) ;
648
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 2 ) ) ) ;
649
+ assert_eq ! ( result[ & 2 ] , Some ( ( 1 , 7 ) ) ) ;
650
+ }
651
+
652
+ #[ test]
653
+ fn test_visited_vertex_skipping ( ) {
654
+ // Test that already visited vertices are properly skipped
655
+ let mut graph = BTreeMap :: new ( ) ;
656
+ add_edge ( & mut graph, 0 , 1 , 1 ) ;
657
+ add_edge ( & mut graph, 0 , 2 , 2 ) ;
658
+ add_edge ( & mut graph, 1 , 2 , 1 ) ; // Creates multiple paths to vertex 2
659
+
660
+ let result = improved_shortest_path ( & graph, 0 ) ;
661
+
662
+ // Should find optimal path: 0 -> 1 -> 2 (distance 2)
663
+ assert_eq ! ( result[ & 0 ] , None ) ;
664
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 1 ) ) ) ;
665
+ assert_eq ! ( result[ & 2 ] . unwrap( ) . 1 , 2 ) ;
666
+ }
667
+
668
+ #[ test]
669
+ fn test_different_numeric_types ( ) {
670
+ // Test with different numeric types to ensure trait implementations work
671
+ let mut graph_u32: Graph < u32 , u32 > = BTreeMap :: new ( ) ;
672
+ graph_u32. insert ( 0 , BTreeMap :: new ( ) ) ;
673
+ graph_u32. insert ( 1 , BTreeMap :: new ( ) ) ;
674
+ graph_u32. entry ( 0 ) . or_default ( ) . insert ( 1 , 5 ) ;
675
+
676
+ let result_u32 = improved_shortest_path ( & graph_u32, 0 ) ;
677
+ assert_eq ! ( result_u32[ & 1 ] , Some ( ( 0 , 5 ) ) ) ;
678
+
679
+ // Test with i64 (which implements Ord)
680
+ let mut graph_i64: Graph < i64 , i64 > = BTreeMap :: new ( ) ;
681
+ graph_i64. insert ( 0 , BTreeMap :: new ( ) ) ;
682
+ graph_i64. insert ( 1 , BTreeMap :: new ( ) ) ;
683
+ graph_i64. entry ( 0 ) . or_default ( ) . insert ( 1 , 314 ) ;
684
+
685
+ let result_i64 = improved_shortest_path ( & graph_i64, 0 ) ;
686
+ assert_eq ! ( result_i64[ & 1 ] , Some ( ( 0 , 314 ) ) ) ;
687
+ }
688
+
689
+ #[ test]
690
+ fn test_visited_vertex_continue_coverage ( ) {
691
+ // Test to specifically cover the continue statement when vertex is already visited
692
+ // This happens when a vertex appears multiple times in the priority queue
693
+ let mut graph = BTreeMap :: new ( ) ;
694
+ add_edge ( & mut graph, 0 , 1 , 1 ) ;
695
+ add_edge ( & mut graph, 0 , 2 , 2 ) ;
696
+ add_edge ( & mut graph, 1 , 2 , 1 ) ;
697
+ add_edge ( & mut graph, 2 , 3 , 1 ) ;
698
+
699
+ // This creates a scenario where vertex 2 might be processed multiple times
700
+ // due to different paths: 0->2 (weight 2) and 0->1->2 (weight 2)
701
+ let result = improved_shortest_path ( & graph, 0 ) ;
702
+
703
+ assert_eq ! ( result[ & 0 ] , None ) ;
704
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 1 ) ) ) ;
705
+ assert_eq ! ( result[ & 2 ] . unwrap( ) . 1 , 2 ) ; // Should find shortest path
706
+ assert_eq ! ( result[ & 3 ] . unwrap( ) . 1 , 3 ) ; // 0->1->2->3 or 0->2->3
707
+ }
708
+
709
+ #[ test]
710
+ fn test_bucket_visited_vertex_continue_coverage ( ) {
711
+ // Test to cover the continue statement in bucket algorithm
712
+ let mut graph = BTreeMap :: new ( ) ;
713
+ add_edge ( & mut graph, 0 , 1 , 1 ) ;
714
+ add_edge ( & mut graph, 0 , 2 , 2 ) ;
715
+ add_edge ( & mut graph, 1 , 2 , 1 ) ;
716
+
717
+ let result = bucket_shortest_path ( & graph, 0 , 5 ) ;
718
+
719
+ assert_eq ! ( result[ & 0 ] , None ) ;
720
+ assert_eq ! ( result[ & 1 ] , Some ( ( 0 , 1 ) ) ) ;
721
+ assert_eq ! ( result[ & 2 ] . unwrap( ) . 1 , 2 ) ;
499
722
}
500
723
}
0 commit comments