@@ -436,10 +436,10 @@ def test_from_nexthop_ip_third_octet_128(self):
436
436
def test_from_nexthop_ip_various_valid_ips (self ):
437
437
"""Test route destination calculation with various valid IP patterns."""
438
438
test_cases = [
439
- ("192.168 .0.1" , "100.126.0.0/17" ),
440
- ("10.0 .0.254" , "100.126.0.0/17" ),
441
- ("172.16 .128.1" , "100.126.128.0/17" ),
442
- ("203.0 .128.100" , "100.126.128.0/17" ),
439
+ ("100.64 .0.1" , "100.126.0.0/17" ),
440
+ ("100.65 .0.254" , "100.126.0.0/17" ),
441
+ ("100.66 .128.1" , "100.126.128.0/17" ),
442
+ ("100.67 .128.100" , "100.126.128.0/17" ),
443
443
]
444
444
445
445
for nexthop_ip , expected_destination in test_cases :
@@ -490,6 +490,182 @@ def test_calculate_destination_invalid_ip_format(self):
490
490
with pytest .raises ((ValueError , ipaddress .AddressValueError )):
491
491
RouteSpec ._calculate_destination (invalid_format )
492
492
493
+ def test_calculate_destination_comprehensive_third_octet_zero (self ):
494
+ """Test comprehensive route destination calculation for third octet = 0."""
495
+ # Test various IP addresses with third octet = 0 within 100.64.0.0/10 subnet
496
+ test_ips = [
497
+ "100.64.0.1" ,
498
+ "100.65.0.1" ,
499
+ "100.66.0.254" ,
500
+ "100.67.0.100" ,
501
+ "100.68.0.3" ,
502
+ "100.127.0.255" ,
503
+ ]
504
+
505
+ for ip in test_ips :
506
+ destination = RouteSpec ._calculate_destination (ip )
507
+ assert destination == "100.126.0.0/17" , f"Failed for IP: { ip } "
508
+
509
+ def test_calculate_destination_comprehensive_third_octet_128 (self ):
510
+ """Test comprehensive route destination calculation for third octet = 128."""
511
+ # Test various IP addresses with third octet = 128 within 100.64.0.0/10 subnet
512
+ test_ips = [
513
+ "100.64.128.1" ,
514
+ "100.65.128.1" ,
515
+ "100.66.128.254" ,
516
+ "100.67.128.100" ,
517
+ "100.68.128.3" ,
518
+ "100.127.128.255" ,
519
+ ]
520
+
521
+ for ip in test_ips :
522
+ destination = RouteSpec ._calculate_destination (ip )
523
+ assert destination == "100.126.128.0/17" , f"Failed for IP: { ip } "
524
+
525
+ def test_calculate_destination_comprehensive_invalid_patterns (self ):
526
+ """Test comprehensive error handling for all invalid third octet values."""
527
+ # Test all invalid third octet values (not 0 or 128) within 100.64.0.0/10 subnet
528
+ invalid_third_octets = [1 , 2 , 63 , 64 , 127 , 129 , 192 , 254 , 255 ]
529
+
530
+ for third_octet in invalid_third_octets :
531
+ invalid_ip = f"100.64.{ third_octet } .1"
532
+ with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
533
+ RouteSpec ._calculate_destination (invalid_ip )
534
+
535
+ def test_from_nexthop_ip_comprehensive_valid_patterns (self ):
536
+ """Test RouteSpec.from_nexthop_ip with comprehensive valid IP patterns."""
537
+ # Test cases: (nexthop_ip, expected_destination) - all within 100.64.0.0/10
538
+ test_cases = [
539
+ # Third octet = 0 cases
540
+ ("100.64.0.1" , "100.126.0.0/17" ),
541
+ ("100.65.0.254" , "100.126.0.0/17" ),
542
+ ("100.66.0.100" , "100.126.0.0/17" ),
543
+ ("100.67.0.50" , "100.126.0.0/17" ),
544
+ ("100.127.0.17" , "100.126.0.0/17" ), # From design document example
545
+ # Third octet = 128 cases
546
+ ("100.64.128.1" , "100.126.128.0/17" ),
547
+ ("100.65.128.254" , "100.126.128.0/17" ),
548
+ ("100.66.128.100" , "100.126.128.0/17" ),
549
+ ("100.67.128.50" , "100.126.128.0/17" ),
550
+ ("100.127.128.17" , "100.126.128.0/17" ), # From design document example
551
+ ]
552
+
553
+ svm_name = "os-550e8400-e29b-41d4-a716-446655440000" # Valid UUID format
554
+
555
+ for nexthop_ip , expected_destination in test_cases :
556
+ spec = RouteSpec .from_nexthop_ip (svm_name , nexthop_ip )
557
+ assert spec .svm_name == svm_name
558
+ assert spec .gateway == nexthop_ip
559
+ assert spec .destination == expected_destination
560
+
561
+ def test_from_nexthop_ip_comprehensive_invalid_patterns (self ):
562
+ """Test RouteSpec.from_nexthop_ip with comprehensive invalid IP patterns."""
563
+ svm_name = "os-550e8400-e29b-41d4-a716-446655440000"
564
+
565
+ # Test invalid third octet values within 100.64.0.0/10 subnet
566
+ invalid_third_octets = [1 , 2 , 63 , 64 , 127 , 129 , 192 , 254 , 255 ]
567
+
568
+ for third_octet in invalid_third_octets :
569
+ invalid_ip = f"100.64.{ third_octet } .1"
570
+ with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
571
+ RouteSpec .from_nexthop_ip (svm_name , invalid_ip )
572
+
573
+ def test_from_nexthop_ip_edge_cases (self ):
574
+ """Test RouteSpec.from_nexthop_ip with edge case IP addresses."""
575
+ svm_name = "os-550e8400-e29b-41d4-a716-446655440000"
576
+
577
+ # Edge cases for third octet = 0 within 100.64.0.0/10 subnet
578
+ edge_cases_zero = [
579
+ "100.64.0.1" ,
580
+ "100.127.0.1" ,
581
+ "100.65.0.1" ,
582
+ ]
583
+
584
+ for ip in edge_cases_zero :
585
+ spec = RouteSpec .from_nexthop_ip (svm_name , ip )
586
+ assert spec .destination == "100.126.0.0/17"
587
+ assert spec .gateway == ip
588
+
589
+ # Edge cases for third octet = 128 within 100.64.0.0/10 subnet
590
+ edge_cases_128 = [
591
+ "100.64.128.1" ,
592
+ "100.127.128.255" ,
593
+ "100.65.128.1" ,
594
+ ]
595
+
596
+ for ip in edge_cases_128 :
597
+ spec = RouteSpec .from_nexthop_ip (svm_name , ip )
598
+ assert spec .destination == "100.126.128.0/17"
599
+ assert spec .gateway == ip
600
+
601
+ def test_calculate_destination_boundary_values (self ):
602
+ """Test _calculate_destination with boundary values for third octet."""
603
+ # Test exact boundary values within 100.64.0.0/10 subnet
604
+ assert RouteSpec ._calculate_destination ("100.64.0.1" ) == "100.126.0.0/17"
605
+ assert RouteSpec ._calculate_destination ("100.64.128.1" ) == "100.126.128.0/17"
606
+
607
+ # Test values just outside boundaries should fail
608
+ with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
609
+ RouteSpec ._calculate_destination ("100.64.1.1" ) # Just above 0
610
+
611
+ with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
612
+ RouteSpec ._calculate_destination ("100.64.127.1" ) # Just below 128
613
+
614
+ with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
615
+ RouteSpec ._calculate_destination ("100.64.129.1" ) # Just above 128
616
+
617
+ def test_calculate_destination_subnet_validation (self ):
618
+ """Test _calculate_destination validates IP is within 100.64.0.0/10 subnet."""
619
+ # Test IPs outside 100.64.0.0/10 subnet should fail
620
+ invalid_subnet_ips = [
621
+ "192.168.0.1" , # Private network
622
+ "10.0.0.1" , # Private network
623
+ "172.16.0.1" , # Private network
624
+ "8.8.8.8" , # Public network
625
+ "100.63.0.1" , # Just below 100.64.0.0/10
626
+ "100.128.0.1" , # Just above 100.64.0.0/10
627
+ "101.64.0.1" , # Outside range
628
+ "99.64.0.1" , # Outside range
629
+ ]
630
+
631
+ for invalid_ip in invalid_subnet_ips :
632
+ with pytest .raises (ValueError , match = "not within required 100.64.0.0/10" ):
633
+ RouteSpec ._calculate_destination (invalid_ip )
634
+
635
+ def test_from_nexthop_ip_subnet_validation (self ):
636
+ """Test RouteSpec.from_nexthop_ip validates IP is within 100.64.0.0/10."""
637
+ svm_name = "os-550e8400-e29b-41d4-a716-446655440000"
638
+
639
+ # Test IPs outside 100.64.0.0/10 subnet should fail
640
+ invalid_subnet_ips = [
641
+ "192.168.0.1" , # Private network
642
+ "10.0.0.1" , # Private network
643
+ "172.16.128.1" , # Private network
644
+ "8.8.8.8" , # Public network
645
+ "100.63.0.1" , # Just below 100.64.0.0/10
646
+ "100.128.0.1" , # Just above 100.64.0.0/10
647
+ ]
648
+
649
+ for invalid_ip in invalid_subnet_ips :
650
+ with pytest .raises (ValueError , match = "not within required 100.64.0.0/10" ):
651
+ RouteSpec .from_nexthop_ip (svm_name , invalid_ip )
652
+
653
+ def test_calculate_destination_valid_subnet_range (self ):
654
+ """Test _calculate_destination accepts valid IPs within 100.64.0.0/10 subnet."""
655
+ # Test boundary IPs within 100.64.0.0/10 subnet
656
+ valid_subnet_ips = [
657
+ ("100.64.0.1" , "100.126.0.0/17" ), # Start of range, third octet 0
658
+ ("100.64.128.1" , "100.126.128.0/17" ), # Start of range, third octet 128
659
+ ("100.127.0.1" , "100.126.0.0/17" ), # End of range, third octet 0
660
+ ("100.127.128.1" , "100.126.128.0/17" ), # End of range, third octet 128
661
+ ("100.65.0.100" , "100.126.0.0/17" ), # Middle of range, third octet 0
662
+ ("100.66.128.200" , "100.126.128.0/17" ), # Middle of range, third octet 128
663
+ ]
664
+
665
+ for valid_ip , expected_destination in valid_subnet_ips :
666
+ destination = RouteSpec ._calculate_destination (valid_ip )
667
+ assert destination == expected_destination
668
+
493
669
494
670
class TestRouteResult :
495
671
"""Test cases for RouteResult value object."""
0 commit comments