@@ -509,8 +509,8 @@ def test_from_nexthop_ip_third_octet_zero(self):
509509 assert str (spec .gateway ) == "100.127.0.17"
510510 assert str (spec .destination ) == "100.126.0.0/17"
511511
512- def test_from_nexthop_ip_third_octet_128 (self ):
513- """Test route destination calculation for third octet = 128."""
512+ def test_from_nexthop_ip_third_octet_128_range (self ):
513+ """Test route destination calculation for third octet in 128-255 range ."""
514514 spec = RouteSpec .from_nexthop_ip ("os-test-project" , "100.127.128.17" )
515515
516516 assert spec .svm_name == "os-test-project"
@@ -531,34 +531,55 @@ def test_from_nexthop_ip_various_valid_ips(self):
531531 assert spec .destination == expected_destination
532532 assert str (spec .gateway ) == nexthop_ip
533533
534- def test_calculate_destination_third_octet_zero (self ):
535- """Test _calculate_destination static method for third octet = 0."""
536- destination = RouteSpec ._calculate_destination ("100.127.0.17" )
537- assert destination == ipaddress .IPv4Network ("100.126.0.0/17" )
534+ def test_calculate_destination_third_octet_0_to_127_range (self ):
535+ """Test _calculate_destination static method for third octet in 0-127 range."""
536+ # Test boundary values and some values in between
537+ test_cases = [
538+ "100.127.0.17" , # Lower boundary
539+ "100.127.64.17" , # Middle value
540+ "100.127.127.17" , # Upper boundary
541+ ]
538542
539- def test_calculate_destination_third_octet_128 (self ):
540- """Test _calculate_destination static method for third octet = 128."""
541- destination = RouteSpec ._calculate_destination ("100.127.128.17" )
542- assert destination == ipaddress .IPv4Network ("100.126.128.0/17" )
543+ for ip in test_cases :
544+ destination = RouteSpec ._calculate_destination (ip )
545+ assert destination == ipaddress .IPv4Network ("100.126.0.0/17" )
546+
547+ def test_calculate_destination_third_octet_128_to_255_range (self ):
548+ """Test _calculate_destination static 128-255 range."""
549+ # Test boundary values and some values in between
550+ test_cases = [
551+ "100.127.128.17" , # Lower boundary
552+ "100.127.192.17" , # Middle value
553+ "100.127.255.17" , # Upper boundary
554+ ]
555+
556+ for ip in test_cases :
557+ destination = RouteSpec ._calculate_destination (ip )
558+ assert destination == ipaddress .IPv4Network ("100.126.128.0/17" )
543559
544560 def test_calculate_destination_invalid_pattern (self ):
545- """Test _calculate_destination with unsupported third octet values ."""
561+ """Test _calculate_destination with IPs outside 100.64.0.0/10 subnet ."""
546562 invalid_ips = [
547- "100.127.1.17" ,
548- "100.127.64.17" ,
549- "100.127.127.17" ,
550- "100.127.129.17" ,
551- "100.127.255.17" ,
563+ "192.168.1.17" , # Private network
564+ "10.0.0.17" , # Private network
565+ "172.16.0.17" , # Private network
566+ "8.8.8.8" , # Public network
567+ "100.63.255.17" , # Just below 100.64.0.0/10
568+ "100.128.0.17" , # Just above 100.64.0.0/10
552569 ]
553570
554571 for invalid_ip in invalid_ips :
555- with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
572+ with pytest .raises (
573+ ValueError , match = "not within required 100.64.0.0/10 subnet"
574+ ):
556575 RouteSpec ._calculate_destination (invalid_ip )
557576
558577 def test_from_nexthop_ip_invalid_pattern (self ):
559- """Test from_nexthop_ip with unsupported IP patterns."""
560- with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
561- RouteSpec .from_nexthop_ip ("os-test-project" , "100.127.64.17" )
578+ """Test from_nexthop_ip with IPs outside carrier-grade NAT range."""
579+ with pytest .raises (
580+ ValueError , match = "not within required 100.64.0.0/10 subnet"
581+ ):
582+ RouteSpec .from_nexthop_ip ("os-test-project" , "192.168.1.17" )
562583
563584 def test_calculate_destination_invalid_ip_format (self ):
564585 """Test _calculate_destination with invalid IP format."""
@@ -574,16 +595,16 @@ def test_calculate_destination_invalid_ip_format(self):
574595 with pytest .raises ((ValueError , ipaddress .AddressValueError )):
575596 RouteSpec ._calculate_destination (invalid_format )
576597
577- def test_calculate_destination_comprehensive_third_octet_zero (self ):
578- """Test comprehensive route destination calculation for third octet = 0 ."""
579- # Test various IP addresses with third octet = 0 within 100.64.0.0/10 subnet
598+ def test_calculate_destination_comprehensive_third_octet_0_to_127 (self ):
599+ """Test comprehensive route destination calculation for range 0-127 ."""
600+ # Test various IP addresses with third octets 0-127 within 100.64.0.0/10 subnet
580601 test_ips = [
581- "100.64.0.1" ,
582- "100.65.0 .1" ,
583- "100.66.0 .254" ,
584- "100.67.0 .100" ,
585- "100.68.0 .3" ,
586- "100.127.0 .255" ,
602+ "100.64.0.1" , # Third octet = 0
603+ "100.65.1 .1" , # Third octet = 1
604+ "100.66.63 .254" , # Third octet = 63
605+ "100.67.64 .100" , # Third octet = 64
606+ "100.68.126 .3" , # Third octet = 126
607+ "100.127.127 .255" , # Third octet = 127 (boundary)
587608 ]
588609
589610 for ip in test_ips :
@@ -592,16 +613,16 @@ def test_calculate_destination_comprehensive_third_octet_zero(self):
592613 "100.126.0.0/17"
593614 ), f"Failed for IP: { ip } "
594615
595- def test_calculate_destination_comprehensive_third_octet_128 (self ):
596- """Test comprehensive route destination calculation for third octet = 128."""
597- # Test various IP addresses with third octet = 128 within 100.64.0.0/10 subnet
616+ def test_calculate_destination_comprehensive_third_octet_128_to_255 (self ):
617+ """Test comprehensive route destination calculation for range 128-255 ."""
618+ # Test various IP addresses with third octets 128-255 within subnet
598619 test_ips = [
599- "100.64.128.1" ,
600- "100.65.128 .1" ,
601- "100.66.128 .254" ,
602- "100.67.128 .100" ,
603- "100.68.128 .3" ,
604- "100.127.128 .255" ,
620+ "100.64.128.1" , # Third octet = 128 (boundary)
621+ "100.65.129 .1" , # Third octet = 129
622+ "100.66.192 .254" , # Third octet = 192
623+ "100.67.200 .100" , # Third octet = 200
624+ "100.68.254 .3" , # Third octet = 254
625+ "100.127.255 .255" , # Third octet = 255 (boundary)
605626 ]
606627
607628 for ip in test_ips :
@@ -611,13 +632,21 @@ def test_calculate_destination_comprehensive_third_octet_128(self):
611632 ), f"Failed for IP: { ip } "
612633
613634 def test_calculate_destination_comprehensive_invalid_patterns (self ):
614- """Test comprehensive error handling for all invalid third octet values."""
615- # Test all invalid third octet values (not 0 or 128) within 100.64.0.0/10 subnet
616- invalid_third_octets = [1 , 2 , 63 , 64 , 127 , 129 , 192 , 254 , 255 ]
635+ """Test comprehensive error handling for IPs outside carrier-grade NAT range."""
636+ # Test IPs outside 100.64.0.0/10 subnet - these should all fail
637+ invalid_base_addresses = [
638+ "100.63" , # Just below the range
639+ "100.128" , # Just above the range
640+ "192.168" , # Private network
641+ "10.0" , # Private network
642+ "172.16" , # Private network
643+ ]
617644
618- for third_octet in invalid_third_octets :
619- invalid_ip = f"100.64.{ third_octet } .1"
620- with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
645+ for base_addr in invalid_base_addresses :
646+ invalid_ip = f"{ base_addr } .1.1"
647+ with pytest .raises (
648+ ValueError , match = "not within required 100.64.0.0/10 subnet"
649+ ):
621650 RouteSpec ._calculate_destination (invalid_ip )
622651
623652 def test_from_nexthop_ip_comprehensive_valid_patterns (self ):
@@ -653,15 +682,23 @@ def test_from_nexthop_ip_comprehensive_valid_patterns(self):
653682 assert spec .destination == expected_destination
654683
655684 def test_from_nexthop_ip_comprehensive_invalid_patterns (self ):
656- """Test RouteSpec.from_nexthop_ip with comprehensive invalid IP patterns ."""
685+ """Test RouteSpec.from_nexthop_ip with IPs outside carrier-grade NAT range ."""
657686 svm_name = "os-550e8400-e29b-41d4-a716-446655440000"
658687
659- # Test invalid third octet values within 100.64.0.0/10 subnet
660- invalid_third_octets = [1 , 2 , 63 , 64 , 127 , 129 , 192 , 254 , 255 ]
688+ # Test IPs outside 100.64.0.0/10 subnet - these should all fail
689+ invalid_ips = [
690+ "192.168.1.1" , # Private network
691+ "10.0.0.1" , # Private network
692+ "172.16.0.1" , # Private network
693+ "8.8.8.8" , # Public network
694+ "100.63.255.1" , # Just below 100.64.0.0/10
695+ "100.128.0.1" , # Just above 100.64.0.0/10
696+ ]
661697
662- for third_octet in invalid_third_octets :
663- invalid_ip = f"100.64.{ third_octet } .1"
664- with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
698+ for invalid_ip in invalid_ips :
699+ with pytest .raises (
700+ ValueError , match = "not within required 100.64.0.0/10 subnet"
701+ ):
665702 RouteSpec .from_nexthop_ip (svm_name , invalid_ip )
666703
667704 def test_from_nexthop_ip_edge_cases (self ):
@@ -693,24 +730,22 @@ def test_from_nexthop_ip_edge_cases(self):
693730 assert str (spec .gateway ) == ip
694731
695732 def test_calculate_destination_boundary_values (self ):
696- """Test _calculate_destination with boundary values for third octet."""
697- # Test exact boundary values within 100.64.0.0/10 subnet
698- assert RouteSpec ._calculate_destination ("100.64.0.1" ) == ipaddress .IPv4Network (
699- "100.126.0.0/17"
700- )
701- assert RouteSpec ._calculate_destination (
702- "100.64.128.1"
703- ) == ipaddress .IPv4Network ("100.126.128.0/17" )
704-
705- # Test values just outside boundaries should fail
706- with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
707- RouteSpec ._calculate_destination ("100.64.1.1" ) # Just above 0
708-
709- with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
710- RouteSpec ._calculate_destination ("100.64.127.1" ) # Just below 128
711-
712- with pytest .raises (ValueError , match = "Unsupported IP pattern" ):
713- RouteSpec ._calculate_destination ("100.64.129.1" ) # Just above 128
733+ """Test _calculate_destination with boundary values for third octet ranges."""
734+ # Test boundary values for 0-127 range (maps to 100.126.0.0/17)
735+ expected_0_127 = ipaddress .IPv4Network ("100.126.0.0/17" )
736+ expected_128_255 = ipaddress .IPv4Network ("100.126.128.0/17" )
737+
738+ # Test boundary values for 0-127 range
739+ assert RouteSpec ._calculate_destination ("100.64.0.1" ) == expected_0_127
740+ assert RouteSpec ._calculate_destination ("100.64.127.1" ) == expected_0_127
741+
742+ # Test boundary values for 128-255 range
743+ assert RouteSpec ._calculate_destination ("100.64.128.1" ) == expected_128_255
744+ assert RouteSpec ._calculate_destination ("100.64.255.1" ) == expected_128_255
745+
746+ # Test values throughout the ranges should work
747+ assert RouteSpec ._calculate_destination ("100.64.1.1" ) == expected_0_127
748+ assert RouteSpec ._calculate_destination ("100.64.129.1" ) == expected_128_255
714749
715750 def test_calculate_destination_subnet_validation (self ):
716751 """Test _calculate_destination validates IP is within 100.64.0.0/10 subnet."""
0 commit comments