Add an IPv4 helper lib (parse, netmask, cidr, overlap) and derive router.lans.<name>.ipv4.subnet from address and prefixLength instead of requiring it twice. New assertions reject invalid addresses, DHCP pools that are reversed, outside the subnet or contain the router address, and overlapping LANs. Add `lib` unit tests and an `assertions` check that evaluates broken configs and compares the exact error messages. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
61 lines
2.4 KiB
Nix
61 lines
2.4 KiB
Nix
# Unit tests for modules/router/lib.nix, run at evaluation time.
|
|
{ pkgs }:
|
|
let
|
|
inherit (pkgs) lib;
|
|
r = import ../modules/router/lib.nix { inherit lib; };
|
|
inherit (r) ipv4;
|
|
ip = ipv4.parse;
|
|
|
|
failures = lib.runTests {
|
|
testParse = { expr = ip "192.168.10.1"; expected = 3232238081; };
|
|
testParseZero = { expr = ip "0.0.0.0"; expected = 0; };
|
|
testParseMax = { expr = ip "255.255.255.255"; expected = 4294967295; };
|
|
testParseBadOctet = { expr = ip "192.168.10.256"; expected = null; };
|
|
testParseShort = { expr = ip "192.168.10"; expected = null; };
|
|
testParseJunk = { expr = ip "192.168.10.x"; expected = null; };
|
|
testFormatRoundTrip = { expr = ipv4.format (ip "10.20.30.40"); expected = "10.20.30.40"; };
|
|
testFormatZero = { expr = ipv4.format 0; expected = "0.0.0.0"; };
|
|
testNetMask24 = { expr = ipv4.format (ipv4.netMask 24); expected = "255.255.255.0"; };
|
|
testNetMask20 = { expr = ipv4.format (ipv4.netMask 20); expected = "255.255.240.0"; };
|
|
testNetMask8 = { expr = ipv4.format (ipv4.netMask 8); expected = "255.0.0.0"; };
|
|
testCidr24 = { expr = ipv4.cidr "192.168.10.77" 24; expected = "192.168.10.0/24"; };
|
|
testCidr20 = { expr = ipv4.cidr "172.16.37.1" 20; expected = "172.16.32.0/20"; };
|
|
testCidr30 = { expr = ipv4.cidr "10.0.0.6" 30; expected = "10.0.0.4/30"; };
|
|
testInSubnetYes = {
|
|
expr = ipv4.inSubnet { address = ip "192.168.10.1"; prefixLength = 24; } (ip "192.168.10.200");
|
|
expected = true;
|
|
};
|
|
testInSubnetNo = {
|
|
expr = ipv4.inSubnet { address = ip "192.168.10.1"; prefixLength = 24; } (ip "192.168.11.1");
|
|
expected = false;
|
|
};
|
|
testOverlapNested = {
|
|
expr = ipv4.overlaps
|
|
{ address = ip "10.0.0.1"; prefixLength = 8; }
|
|
{ address = ip "10.1.2.3"; prefixLength = 24; };
|
|
expected = true;
|
|
};
|
|
testOverlapSame = {
|
|
expr = ipv4.overlaps
|
|
{ address = ip "192.168.10.1"; prefixLength = 24; }
|
|
{ address = ip "192.168.10.9"; prefixLength = 24; };
|
|
expected = true;
|
|
};
|
|
testOverlapDisjoint = {
|
|
expr = ipv4.overlaps
|
|
{ address = ip "192.168.10.1"; prefixLength = 24; }
|
|
{ address = ip "192.168.11.1"; prefixLength = 24; };
|
|
expected = false;
|
|
};
|
|
};
|
|
in
|
|
pkgs.runCommand "router-lib-tests" { } (
|
|
if failures == [ ] then
|
|
"touch $out"
|
|
else
|
|
''
|
|
echo ${lib.escapeShellArg (lib.generators.toPretty { } failures)} >&2
|
|
exit 1
|
|
''
|
|
)
|