"""Tests for network_utils module - IP address classification.""" from local_deep_research.security.network_utils import is_private_ip class TestIsPrivateIPLocalhost: """Tests for localhost detection.""" def test_localhost_string(self): """Should detect 'localhost' as private.""" assert is_private_ip("localhost") is True def test_loopback_ipv4(self): """Should detect 127.0.0.1 as private.""" assert is_private_ip("127.0.0.1") is True def test_loopback_ipv6_bracketed(self): """Should detect [::1] as private.""" assert is_private_ip("[::1]") is True def test_all_zeros_ipv4(self): """Should detect 0.0.0.0 as private.""" assert is_private_ip("0.0.0.0") is True class TestIsPrivateIPIPv4Ranges: """Tests for IPv4 private address range detection.""" def test_10_0_0_0_range(self): """Should detect 10.x.x.x as private (RFC 1918).""" assert is_private_ip("10.0.0.1") is True assert is_private_ip("10.255.255.255") is True assert is_private_ip("10.100.50.25") is True def test_172_16_0_0_range(self): """Should detect 172.16-31.x.x as private (RFC 1918).""" assert is_private_ip("172.16.0.1") is True assert is_private_ip("172.31.255.255") is True assert is_private_ip("172.20.10.5") is True def test_192_168_0_0_range(self): """Should detect 192.168.x.x as private (RFC 1918).""" assert is_private_ip("192.168.0.1") is True assert is_private_ip("192.168.255.255") is True assert is_private_ip("192.168.1.100") is True def test_link_local_range(self): """Should detect 169.254.x.x as private (link-local).""" assert is_private_ip("169.254.1.1") is True assert is_private_ip("169.254.255.255") is True def test_loopback_range(self): """Should detect 127.x.x.x as private (loopback).""" assert is_private_ip("127.0.0.1") is True assert is_private_ip("127.255.255.255") is True assert is_private_ip("127.100.50.25") is True class TestIsPrivateIPIPv6: """Tests for IPv6 private address detection.""" def test_ipv6_loopback(self): """Should detect IPv6 loopback as private.""" assert is_private_ip("::1") is True def test_ipv6_unique_local(self): """Should detect fc00::/7 as private (unique local).""" assert is_private_ip("fc00::1") is True assert is_private_ip("fd00::1") is True def test_ipv6_link_local(self): """Should detect fe80::/10 as private (link-local).""" assert is_private_ip("fe80::1") is True def test_ipv6_bracketed(self): """Should handle bracketed IPv6 addresses.""" assert is_private_ip("[::1]") is True assert is_private_ip("[fc00::1]") is True assert is_private_ip("[fe80::1]") is True class TestIsPrivateIPPublicAddresses: """Tests for public address detection.""" def test_public_ipv4_google_dns(self): """Should not detect Google DNS (8.8.8.8) as private.""" assert is_private_ip("8.8.8.8") is False def test_public_ipv4_cloudflare_dns(self): """Should not detect Cloudflare DNS (1.1.1.1) as private.""" assert is_private_ip("1.1.1.1") is False def test_public_ipv4_example(self): """Should not detect example.com IP as private.""" assert is_private_ip("93.184.216.34") is False def test_public_ipv4_various(self): """Should not detect various public IPs as private.""" # Note: 203.0.113.x is TEST-NET-3 (RFC 5737), considered private/reserved assert is_private_ip("104.26.10.222") is False # Cloudflare assert is_private_ip("142.250.190.46") is False # Google assert is_private_ip("151.101.1.140") is False # Reddit def test_public_ipv6(self): """Should not detect public IPv6 addresses as private.""" assert is_private_ip("2001:4860:4860::8888") is False # Google DNS assert is_private_ip("2606:4700:4700::1111") is False # Cloudflare class TestIsPrivateIPHostnames: """Tests for hostname handling.""" def test_public_hostname(self): """Should not detect public hostnames as private.""" assert is_private_ip("example.com") is False assert is_private_ip("api.openai.com") is False assert is_private_ip("google.com") is False def test_local_domain(self): """Should detect .local domains as private (mDNS).""" assert is_private_ip("mydevice.local") is True assert is_private_ip("printer.local") is True assert is_private_ip("server.local") is True def test_local_domain_case_sensitive(self): """Should only match lowercase .local.""" # Note: actual behavior depends on implementation # The current implementation is case-sensitive for .local assert is_private_ip("mydevice.local") is True # These won't match the .local check, but aren't valid IPs either # so they'll return False def test_internal_subdomain(self): """Should not detect internal.corp as private (no DNS resolution).""" # The function doesn't resolve DNS for security reasons assert is_private_ip("internal.corp") is False assert is_private_ip("server.internal") is False class TestIsPrivateIPEdgeCases: """Tests for edge cases.""" def test_172_15_not_private(self): """172.15.x.x should NOT be private (only 172.16-31 are).""" # This is technically public IP space assert is_private_ip("172.15.0.1") is False def test_172_32_not_private(self): """172.32.x.x should NOT be private (only 172.16-31 are).""" assert is_private_ip("172.32.0.1") is False def test_empty_string(self): """Should handle empty string.""" # Empty string is not a valid IP and doesn't end with .local assert is_private_ip("") is False def test_invalid_ip_format(self): """Should handle invalid IP formats.""" assert is_private_ip("not.an.ip.address") is False assert is_private_ip("256.256.256.256") is False assert is_private_ip("192.168.1") is False