Functional Weave
Code in Python

net.cidr@1.0.0

vectors.json

9,910 bytes · view raw

[
  { "fn": "cidrInfo", "name": "a /24", "args": ["192.168.1.0/24"], "expect": { "cidr": "192.168.1.0/24", "network": "192.168.1.0", "prefix": 24, "netmask": "255.255.255.0", "wildcard": "0.0.0.255", "broadcast": "192.168.1.255", "firstHost": "192.168.1.1", "lastHost": "192.168.1.254", "hostCount": 254, "addressCount": 256 } },
  { "fn": "cidrInfo", "name": "an interface address: host bits are dropped", "args": ["192.168.1.77/24"], "expect": { "cidr": "192.168.1.0/24", "network": "192.168.1.0", "prefix": 24, "netmask": "255.255.255.0", "wildcard": "0.0.0.255", "broadcast": "192.168.1.255", "firstHost": "192.168.1.1", "lastHost": "192.168.1.254", "hostCount": 254, "addressCount": 256 } },
  { "fn": "cidrInfo", "name": "a /8", "args": ["10.0.0.0/8"], "expect": { "cidr": "10.0.0.0/8", "network": "10.0.0.0", "prefix": 8, "netmask": "255.0.0.0", "wildcard": "0.255.255.255", "broadcast": "10.255.255.255", "firstHost": "10.0.0.1", "lastHost": "10.255.255.254", "hostCount": 16777214, "addressCount": 16777216 } },
  { "fn": "cidrInfo", "name": "a /12 that does not fall on an octet: 172.16-172.31", "args": ["172.16.5.4/12"], "expect": { "cidr": "172.16.0.0/12", "network": "172.16.0.0", "prefix": 12, "netmask": "255.240.0.0", "wildcard": "0.15.255.255", "broadcast": "172.31.255.255", "firstHost": "172.16.0.1", "lastHost": "172.31.255.254", "hostCount": 1048574, "addressCount": 1048576 } },
  { "fn": "cidrInfo", "name": "a /26 in the middle of a /24", "args": ["203.0.113.64/26"], "expect": { "cidr": "203.0.113.64/26", "network": "203.0.113.64", "prefix": 26, "netmask": "255.255.255.192", "wildcard": "0.0.0.63", "broadcast": "203.0.113.127", "firstHost": "203.0.113.65", "lastHost": "203.0.113.126", "hostCount": 62, "addressCount": 64 } },
  { "fn": "cidrInfo", "name": "a /30 has two hosts", "args": ["192.168.1.0/30"], "expect": { "cidr": "192.168.1.0/30", "network": "192.168.1.0", "prefix": 30, "netmask": "255.255.255.252", "wildcard": "0.0.0.3", "broadcast": "192.168.1.3", "firstHost": "192.168.1.1", "lastHost": "192.168.1.2", "hostCount": 2, "addressCount": 4 } },
  { "fn": "cidrInfo", "name": "a /31 point-to-point link: both addresses usable, no broadcast (RFC 3021)", "args": ["198.51.100.7/31"], "expect": { "cidr": "198.51.100.6/31", "network": "198.51.100.6", "prefix": 31, "netmask": "255.255.255.254", "wildcard": "0.0.0.1", "broadcast": null, "firstHost": "198.51.100.6", "lastHost": "198.51.100.7", "hostCount": 2, "addressCount": 2 } },
  { "fn": "cidrInfo", "name": "a /32 is one host", "args": ["192.0.2.9/32"], "expect": { "cidr": "192.0.2.9/32", "network": "192.0.2.9", "prefix": 32, "netmask": "255.255.255.255", "wildcard": "0.0.0.0", "broadcast": null, "firstHost": "192.0.2.9", "lastHost": "192.0.2.9", "hostCount": 1, "addressCount": 1 } },
  { "fn": "cidrInfo", "name": "the whole IPv4 space", "args": ["0.0.0.0/0"], "expect": { "cidr": "0.0.0.0/0", "network": "0.0.0.0", "prefix": 0, "netmask": "0.0.0.0", "wildcard": "255.255.255.255", "broadcast": "255.255.255.255", "firstHost": "0.0.0.1", "lastHost": "255.255.255.254", "hostCount": 4294967294, "addressCount": 4294967296 } },
  { "fn": "cidrInfo", "name": "prefix above 32", "args": ["192.168.1.0/33"], "expectError": "is not a CIDR block" },
  { "fn": "cidrInfo", "name": "no prefix", "args": ["192.168.1.0"], "expectError": "is not a CIDR block" },
  { "fn": "cidrInfo", "name": "a leading zero in the prefix", "args": ["192.168.1.0/024"], "expectError": "is not a CIDR block" },
  { "fn": "cidrInfo", "name": "a trailing newline", "args": ["192.168.1.0/24\n"], "expectError": "is not a CIDR block" },
  { "fn": "cidrInfo", "name": "a non-ASCII digit in the prefix", "args": ["10.0.0.0/٨"], "expectError": "is not a CIDR block" },
  { "fn": "cidrInfo", "name": "IPv6 blocks are not described", "args": ["2001:db8::/32"], "expectError": "cidrInfo handles IPv4 blocks only" },

  { "fn": "cidrContains", "name": "inside a /24", "args": ["192.168.1.0/24", "192.168.1.200"], "expect": true },
  { "fn": "cidrContains", "name": "the next /24 is outside", "args": ["192.168.1.0/24", "192.168.2.1"], "expect": false },
  { "fn": "cidrContains", "name": "the last address of a /8", "args": ["10.0.0.0/8", "10.255.255.255"], "expect": true },
  { "fn": "cidrContains", "name": "172.31 is inside 172.16.0.0/12", "args": ["172.16.0.0/12", "172.31.0.1"], "expect": true },
  { "fn": "cidrContains", "name": "172.32 is not (a naive /16 reading gets 172.16-only)", "args": ["172.16.0.0/12", "172.32.0.1"], "expect": false },
  { "fn": "cidrContains", "name": "/0 contains everything of its family", "args": ["0.0.0.0/0", "203.0.113.5"], "expect": true },
  { "fn": "cidrContains", "name": "/32 contains only itself", "args": ["192.0.2.9/32", "192.0.2.10"], "expect": false },
  { "fn": "cidrContains", "name": "IPv6 inside a /32", "args": ["2001:db8::/32", "2001:db8:ffff::1"], "expect": true },
  { "fn": "cidrContains", "name": "IPv6 just outside a /32", "args": ["2001:db8::/32", "2001:db9::1"], "expect": false },
  { "fn": "cidrContains", "name": "link-local /10 reaches febf", "args": ["fe80::/10", "febf::1"], "expect": true },
  { "fn": "cidrContains", "name": "link-local /10 stops before fec0", "args": ["fe80::/10", "fec0::1"], "expect": false },
  { "fn": "cidrContains", "name": "a /33 splits a group: 7fff is in the lower half", "args": ["2001:db8::/33", "2001:db8:7fff::1"], "expect": true },
  { "fn": "cidrContains", "name": "a /33 splits a group: 8000 is in the upper half", "args": ["2001:db8::/33", "2001:db8:8000::1"], "expect": false },
  { "fn": "cidrContains", "name": "an IPv4-mapped IPv6 address is not in an IPv4 block", "args": ["10.0.0.0/8", "::ffff:10.0.0.1"], "expect": false },
  { "fn": "cidrContains", "name": "an IPv4 address is not in ::/0", "args": ["::/0", "10.0.0.1"], "expect": false },
  { "fn": "cidrContains", "name": "a malformed address", "args": ["10.0.0.0/8", "10.0.0.256"], "expectError": "is not an IP address" },
  { "fn": "cidrContains", "name": "a block without a prefix", "args": ["10.0.0.0", "10.0.0.1"], "expectError": "is not a CIDR block" },
  { "fn": "cidrContains", "name": "an IPv6 prefix above 128", "args": ["2001:db8::/129", "2001:db8::1"], "expectError": "is not a CIDR block" },

  { "fn": "isCidr", "name": "an IPv4 block", "args": ["10.0.0.0/8"], "expect": true },
  { "fn": "isCidr", "name": "an IPv6 block", "args": ["2001:db8::/32"], "expect": true },
  { "fn": "isCidr", "name": "/0", "args": ["0.0.0.0/0"], "expect": true },
  { "fn": "isCidr", "name": "IPv6 /128", "args": ["::/128"], "expect": true },
  { "fn": "isCidr", "name": "host bits set are still a block", "args": ["192.168.1.77/24"], "expect": true },
  { "fn": "isCidr", "name": "IPv4 prefix 33", "args": ["10.0.0.0/33"], "expect": false },
  { "fn": "isCidr", "name": "IPv6 prefix 129", "args": ["::/129"], "expect": false },
  { "fn": "isCidr", "name": "a bare address", "args": ["10.0.0.0"], "expect": false },
  { "fn": "isCidr", "name": "two slashes", "args": ["10.0.0.0/8/8"], "expect": false },
  { "fn": "isCidr", "name": "a leading zero in the prefix", "args": ["10.0.0.0/08"], "expect": false },
  { "fn": "isCidr", "name": "a trailing newline", "args": ["10.0.0.0/8\n"], "expect": false },
  { "fn": "isCidr", "name": "a zone id", "args": ["fe80::1%eth0/64"], "expect": false },
  { "fn": "isCidr", "name": "empty text", "args": [""], "expect": false },

  { "fn": "prefixToNetmask", "name": "/24", "args": [24], "expect": "255.255.255.0" },
  { "fn": "prefixToNetmask", "name": "/0", "args": [0], "expect": "0.0.0.0" },
  { "fn": "prefixToNetmask", "name": "/8", "args": [8], "expect": "255.0.0.0" },
  { "fn": "prefixToNetmask", "name": "/12", "args": [12], "expect": "255.240.0.0" },
  { "fn": "prefixToNetmask", "name": "/20", "args": [20], "expect": "255.255.240.0" },
  { "fn": "prefixToNetmask", "name": "/25", "args": [25], "expect": "255.255.255.128" },
  { "fn": "prefixToNetmask", "name": "/30", "args": [30], "expect": "255.255.255.252" },
  { "fn": "prefixToNetmask", "name": "/31", "args": [31], "expect": "255.255.255.254" },
  { "fn": "prefixToNetmask", "name": "/32", "args": [32], "expect": "255.255.255.255" },
  { "fn": "prefixToNetmask", "name": "33 is too long", "args": [33], "expectError": "prefix must be an integer from 0 to 32" },
  { "fn": "prefixToNetmask", "name": "negative", "args": [-1], "expectError": "prefix must be an integer from 0 to 32" },
  { "fn": "prefixToNetmask", "name": "a fraction", "args": [24.5], "expectError": "prefix must be an integer from 0 to 32" },

  { "fn": "netmaskToPrefix", "name": "255.255.255.0 is /24", "args": ["255.255.255.0"], "expect": 24 },
  { "fn": "netmaskToPrefix", "name": "all zeros is /0", "args": ["0.0.0.0"], "expect": 0 },
  { "fn": "netmaskToPrefix", "name": "all ones is /32", "args": ["255.255.255.255"], "expect": 32 },
  { "fn": "netmaskToPrefix", "name": "255.255.254.0 is /23", "args": ["255.255.254.0"], "expect": 23 },
  { "fn": "netmaskToPrefix", "name": "255.240.0.0 is /12", "args": ["255.240.0.0"], "expect": 12 },
  { "fn": "netmaskToPrefix", "name": "255.255.255.128 is /25", "args": ["255.255.255.128"], "expect": 25 },
  { "fn": "netmaskToPrefix", "name": "128.0.0.0 is /1", "args": ["128.0.0.0"], "expect": 1 },
  { "fn": "netmaskToPrefix", "name": "255.255.255.252 is /30", "args": ["255.255.255.252"], "expect": 30 },
  { "fn": "netmaskToPrefix", "name": "a gap in the one bits", "args": ["255.0.255.0"], "expectError": "is not a contiguous netmask" },
  { "fn": "netmaskToPrefix", "name": "a wildcard mask is not a netmask", "args": ["0.255.255.255"], "expectError": "is not a contiguous netmask" },
  { "fn": "netmaskToPrefix", "name": "a stray low bit", "args": ["255.255.255.1"], "expectError": "is not a contiguous netmask" },
  { "fn": "netmaskToPrefix", "name": "not a dotted quad", "args": ["255.255.256.0"], "expectError": "is not a dotted-quad IPv4 address" }
]