This commit is contained in:
2026-02-20 20:07:52 +00:00
commit 35f0f3b0a5
13 changed files with 3017 additions and 0 deletions

315
tests/cidr-tests.nix Normal file
View File

@@ -0,0 +1,315 @@
{
lib,
cidr,
}:
let
inherit (lib) runTests;
in
runTests {
testParseBasic = {
expr = cidr.parse "192.168.1.0/24";
expected = {
address = 3232235776;
prefixLen = 24;
};
};
testParseSlash32 = {
expr = cidr.parse "10.0.0.1/32";
expected = {
address = 167772161;
prefixLen = 32;
};
};
testParseSlash0 = {
expr = cidr.parse "0.0.0.0/0";
expected = {
address = 0;
prefixLen = 0;
};
};
testMakeBasic = {
expr = cidr.make "192.168.1.0" 24;
expected = {
address = 3232235776;
prefixLen = 24;
};
};
testFormatBasic = {
expr = cidr.format {
address = 3232235776;
prefixLen = 24;
};
expected = "192.168.1.0/24";
};
testNetmask24 = {
expr = cidr.netmaskStr 24;
expected = "255.255.255.0";
};
testNetmask16 = {
expr = cidr.netmaskStr 16;
expected = "255.255.0.0";
};
testNetmask8 = {
expr = cidr.netmaskStr 8;
expected = "255.0.0.0";
};
testNetmask32 = {
expr = cidr.netmaskStr 32;
expected = "255.255.255.255";
};
testNetmask0 = {
expr = cidr.netmaskStr 0;
expected = "0.0.0.0";
};
testNetmask25 = {
expr = cidr.netmaskStr 25;
expected = "255.255.255.128";
};
testWildcard24 = {
expr = cidr.wildcardStr 24;
expected = "0.0.0.255";
};
testWildcard16 = {
expr = cidr.wildcardStr 16;
expected = "0.0.255.255";
};
testNetworkBasic = {
expr = cidr.networkStr "192.168.1.50/24";
expected = "192.168.1.0";
};
testNetworkAlreadyNetwork = {
expr = cidr.networkStr "192.168.1.0/24";
expected = "192.168.1.0";
};
testNetworkSlash16 = {
expr = cidr.networkStr "172.16.45.67/16";
expected = "172.16.0.0";
};
testBroadcastBasic = {
expr = cidr.broadcastStr "192.168.1.0/24";
expected = "192.168.1.255";
};
testBroadcastSlash16 = {
expr = cidr.broadcastStr "172.16.0.0/16";
expected = "172.16.255.255";
};
testBroadcastSlash30 = {
expr = cidr.broadcastStr "192.168.1.0/30";
expected = "192.168.1.3";
};
testFirstHostBasic = {
expr = cidr.firstHostStr "192.168.1.0/24";
expected = "192.168.1.1";
};
testLastHostBasic = {
expr = cidr.lastHostStr "192.168.1.0/24";
expected = "192.168.1.254";
};
testFirstHostSlash31 = {
expr = cidr.firstHostStr "192.168.1.0/31";
expected = "192.168.1.0";
};
testLastHostSlash31 = {
expr = cidr.lastHostStr "192.168.1.0/31";
expected = "192.168.1.1";
};
testFirstHostSlash32 = {
expr = cidr.firstHostStr "192.168.1.1/32";
expected = "192.168.1.1";
};
testSize24 = {
expr = cidr.size "192.168.1.0/24";
expected = 256;
};
testSize16 = {
expr = cidr.size "172.16.0.0/16";
expected = 65536;
};
testSize32 = {
expr = cidr.size "192.168.1.1/32";
expected = 1;
};
testSize30 = {
expr = cidr.size "192.168.1.0/30";
expected = 4;
};
testHostCount24 = {
expr = cidr.hostCount "192.168.1.0/24";
expected = 254;
};
testHostCount30 = {
expr = cidr.hostCount "192.168.1.0/30";
expected = 2;
};
testHostCount31 = {
expr = cidr.hostCount "192.168.1.0/31";
expected = 2;
};
testHostCount32 = {
expr = cidr.hostCount "192.168.1.1/32";
expected = 1;
};
testContainsTrue = {
expr = cidr.contains "10.0.0.0/8" "10.1.2.3";
expected = true;
};
testContainsFalse = {
expr = cidr.contains "10.0.0.0/8" "192.168.1.1";
expected = false;
};
testContainsNetwork = {
expr = cidr.contains "192.168.1.0/24" "192.168.1.0";
expected = true;
};
testContainsBroadcast = {
expr = cidr.contains "192.168.1.0/24" "192.168.1.255";
expected = true;
};
testContainsEdgeFalse = {
expr = cidr.contains "192.168.1.0/24" "192.168.2.0";
expected = false;
};
testIsSubnetOfTrue = {
expr = cidr.isSubnetOf "10.0.0.0/8" "10.1.0.0/16";
expected = true;
};
testIsSubnetOfFalse = {
expr = cidr.isSubnetOf "10.0.0.0/8" "192.168.0.0/16";
expected = false;
};
testIsSubnetOfSame = {
expr = cidr.isSubnetOf "10.0.0.0/8" "10.0.0.0/8";
expected = true;
};
testIsSubnetOfLarger = {
expr = cidr.isSubnetOf "10.1.0.0/16" "10.0.0.0/8";
expected = false;
};
testHostBasic = {
expr = cidr.hostStr "192.168.1.0/24" 5;
expected = "192.168.1.5";
};
testHostZero = {
expr = cidr.hostStr "192.168.1.0/24" 0;
expected = "192.168.1.0";
};
testHostLast = {
expr = cidr.hostStr "192.168.1.0/24" 255;
expected = "192.168.1.255";
};
testSubnetFirst = {
expr = cidr.format (cidr.subnet "192.168.0.0/24" 26 0);
expected = "192.168.0.0/26";
};
testSubnetSecond = {
expr = cidr.format (cidr.subnet "192.168.0.0/24" 26 1);
expected = "192.168.0.64/26";
};
testSubnetLast = {
expr = cidr.format (cidr.subnet "192.168.0.0/24" 26 3);
expected = "192.168.0.192/26";
};
testSubnetsCount = {
expr = builtins.length (cidr.subnets "192.168.0.0/24" 26);
expected = 4;
};
testSubnetsStr = {
expr = cidr.subnetsStr "192.168.0.0/24" 26;
expected = [
"192.168.0.0/26"
"192.168.0.64/26"
"192.168.0.128/26"
"192.168.0.192/26"
];
};
testOverlapsTrue = {
expr = cidr.overlaps "192.168.1.0/24" "192.168.0.0/16";
expected = true;
};
testOverlapsFalse = {
expr = cidr.overlaps "192.168.1.0/24" "10.0.0.0/8";
expected = false;
};
testOverlapsAdjacent = {
expr = cidr.overlaps "192.168.1.0/24" "192.168.2.0/24";
expected = false;
};
testPrefixForHosts100 = {
expr = cidr.prefixForHosts 100;
expected = 25;
};
testPrefixForHosts254 = {
expr = cidr.prefixForHosts 254;
expected = 24;
};
testPrefixForHosts1 = {
expr = cidr.prefixForHosts 1;
expected = 32;
};
testPrefixForSize256 = {
expr = cidr.prefixForSize 256;
expected = 24;
};
testPrefixForSize1 = {
expr = cidr.prefixForSize 1;
expected = 32;
};
}

43
tests/default.nix Normal file
View File

@@ -0,0 +1,43 @@
{
lib,
ipLib,
system,
}:
let
ipTests = import ./ip-tests.nix {
inherit lib;
ip = ipLib.ip;
};
cidrTests = import ./cidr-tests.nix {
inherit lib;
cidr = ipLib.cidr;
};
validateTests = import ./validate-tests.nix {
inherit lib;
validate = ipLib.validate;
};
iterateTests = import ./iterate-tests.nix {
inherit lib;
iterate = ipLib.iterate;
ip = ipLib.ip;
};
allTests = ipTests ++ cidrTests ++ validateTests ++ iterateTests;
in
if allTests == [ ] then
derivation {
name = "nix-ip-utils-tests";
inherit system;
builder = "/bin/sh";
args = [
"-c"
"echo 'passed!' > $out"
];
}
else
throw "Tests failed: ${builtins.toJSON allTests}"

205
tests/ip-tests.nix Normal file
View File

@@ -0,0 +1,205 @@
{ lib, ip }:
let
inherit (lib) runTests;
in
runTests {
testParseBasic = {
expr = ip.parse "192.168.1.1";
expected = 3232235777;
};
testParseZeros = {
expr = ip.parse "0.0.0.0";
expected = 0;
};
testParseMax = {
expr = ip.parse "255.255.255.255";
expected = 4294967295;
};
testParseLoopback = {
expr = ip.parse "127.0.0.1";
expected = 2130706433;
};
testParseTen = {
expr = ip.parse "10.0.0.1";
expected = 167772161;
};
testParsePassthroughInt = {
expr = ip.parse 3232235777;
expected = 3232235777;
};
testFormatBasic = {
expr = ip.format 3232235777;
expected = "192.168.1.1";
};
testFormatZeros = {
expr = ip.format 0;
expected = "0.0.0.0";
};
testFormatMax = {
expr = ip.format 4294967295;
expected = "255.255.255.255";
};
testFormatPassthroughString = {
expr = ip.format "192.168.1.1";
expected = "192.168.1.1";
};
testToOctetsBasic = {
expr = ip.toOctets "192.168.1.1";
expected = [
192
168
1
1
];
};
testToOctetsFromInt = {
expr = ip.toOctets 3232235777;
expected = [
192
168
1
1
];
};
testToOctetsZeros = {
expr = ip.toOctets "0.0.0.0";
expected = [
0
0
0
0
];
};
testFromOctetsBasic = {
expr = ip.fromOctets [
192
168
1
1
];
expected = 3232235777;
};
testFromOctetsZeros = {
expr = ip.fromOctets [
0
0
0
0
];
expected = 0;
};
testFromOctetsTen = {
expr = ip.fromOctets [
10
0
0
1
];
expected = 167772161;
};
testAddBasic = {
expr = ip.add "192.168.1.1" 10;
expected = 3232235787;
};
testAddStrBasic = {
expr = ip.addStr "192.168.1.1" 10;
expected = "192.168.1.11";
};
testAddCrossOctet = {
expr = ip.addStr "192.168.1.250" 10;
expected = "192.168.2.4";
};
testSubtractBasic = {
expr = ip.subtract "192.168.1.10" 5;
expected = 3232235781;
};
testSubtractStrBasic = {
expr = ip.subtractStr "192.168.1.10" 5;
expected = "192.168.1.5";
};
testDiffBasic = {
expr = ip.diff "192.168.1.10" "192.168.1.1";
expected = 9;
};
testDiffNegative = {
expr = ip.diff "192.168.1.1" "192.168.1.10";
expected = -9;
};
testCompareLess = {
expr = ip.compare "10.0.0.1" "10.0.0.2";
expected = -1;
};
testCompareGreater = {
expr = ip.compare "10.0.0.2" "10.0.0.1";
expected = 1;
};
testCompareEqual = {
expr = ip.compare "10.0.0.1" "10.0.0.1";
expected = 0;
};
testLtTrue = {
expr = ip.lt "10.0.0.1" "10.0.0.2";
expected = true;
};
testLtFalse = {
expr = ip.lt "10.0.0.2" "10.0.0.1";
expected = false;
};
testGtTrue = {
expr = ip.gt "10.0.0.2" "10.0.0.1";
expected = true;
};
testEqTrue = {
expr = ip.eq "10.0.0.1" "10.0.0.1";
expected = true;
};
testEqFalse = {
expr = ip.eq "10.0.0.1" "10.0.0.2";
expected = false;
};
testMinStr = {
expr = ip.minStr "10.0.0.5" "10.0.0.2";
expected = "10.0.0.2";
};
testMaxStr = {
expr = ip.maxStr "10.0.0.5" "10.0.0.2";
expected = "10.0.0.5";
};
testRoundtrip = {
expr = ip.format (ip.parse "172.16.32.64");
expected = "172.16.32.64";
};
}

195
tests/iterate-tests.nix Normal file
View File

@@ -0,0 +1,195 @@
{
lib,
iterate,
ip,
}:
let
inherit (lib) runTests;
in
runTests {
testRangeBasic = {
expr = iterate.rangeStr "10.0.0.1" "10.0.0.3";
expected = [
"10.0.0.1"
"10.0.0.2"
"10.0.0.3"
];
};
testRangeSingle = {
expr = iterate.rangeStr "10.0.0.1" "10.0.0.1";
expected = [ "10.0.0.1" ];
};
testRangeEmpty = {
expr = iterate.rangeStr "10.0.0.5" "10.0.0.1";
expected = [ ];
};
testRangeCrossOctet = {
expr = iterate.rangeStr "10.0.0.254" "10.0.1.2";
expected = [
"10.0.0.254"
"10.0.0.255"
"10.0.1.0"
"10.0.1.1"
"10.0.1.2"
];
};
testCidrAddresses30 = {
expr = iterate.cidrAddressesStr "10.0.0.0/30";
expected = [
"10.0.0.0"
"10.0.0.1"
"10.0.0.2"
"10.0.0.3"
];
};
testCidrAddresses32 = {
expr = iterate.cidrAddressesStr "10.0.0.1/32";
expected = [ "10.0.0.1" ];
};
testCidrAddressesCount = {
expr = builtins.length (iterate.cidrAddresses "10.0.0.0/28");
expected = 16;
};
testCidrHosts30 = {
expr = iterate.cidrHostsStr "10.0.0.0/30";
expected = [
"10.0.0.1"
"10.0.0.2"
];
};
testCidrHosts31 = {
expr = iterate.cidrHostsStr "10.0.0.0/31";
expected = [
"10.0.0.0"
"10.0.0.1"
];
};
testCidrHosts32 = {
expr = iterate.cidrHostsStr "10.0.0.1/32";
expected = [ "10.0.0.1" ];
};
testCidrHostsCount = {
expr = builtins.length (iterate.cidrHosts "10.0.0.0/28");
expected = 14;
};
testInRangeTrue = {
expr = iterate.inRange "10.0.0.1" "10.0.0.5" "10.0.0.3";
expected = true;
};
testInRangeStart = {
expr = iterate.inRange "10.0.0.1" "10.0.0.5" "10.0.0.1";
expected = true;
};
testInRangeEnd = {
expr = iterate.inRange "10.0.0.1" "10.0.0.5" "10.0.0.5";
expected = true;
};
testInRangeFalseLow = {
expr = iterate.inRange "10.0.0.2" "10.0.0.5" "10.0.0.1";
expected = false;
};
testInRangeFalseHigh = {
expr = iterate.inRange "10.0.0.1" "10.0.0.5" "10.0.0.6";
expected = false;
};
testCountRangeBasic = {
expr = iterate.countRange "10.0.0.1" "10.0.0.10";
expected = 10;
};
testCountRangeSingle = {
expr = iterate.countRange "10.0.0.1" "10.0.0.1";
expected = 1;
};
testCountRangeEmpty = {
expr = iterate.countRange "10.0.0.5" "10.0.0.1";
expected = 0;
};
testMapRangeFormat = {
expr = iterate.mapRange ip.format "10.0.0.1" "10.0.0.3";
expected = [
"10.0.0.1"
"10.0.0.2"
"10.0.0.3"
];
};
testMapRangeOctets = {
expr = iterate.mapRange ip.toOctets "10.0.0.1" "10.0.0.2";
expected = [
[
10
0
0
1
]
[
10
0
0
2
]
];
};
testFilterRangeEven = {
expr = builtins.map ip.format (iterate.filterRange (i: lib.mod i 2 == 0) "10.0.0.1" "10.0.0.5");
expected = [
"10.0.0.2"
"10.0.0.4"
];
};
testTakeRangeBasic = {
expr = iterate.takeRangeStr 3 "10.0.0.1" "10.0.0.10";
expected = [
"10.0.0.1"
"10.0.0.2"
"10.0.0.3"
];
};
testTakeRangeMoreThanAvailable = {
expr = iterate.takeRangeStr 10 "10.0.0.1" "10.0.0.3";
expected = [
"10.0.0.1"
"10.0.0.2"
"10.0.0.3"
];
};
testTakeRangeZero = {
expr = iterate.takeRangeStr 0 "10.0.0.1" "10.0.0.10";
expected = [ ];
};
testFindInRangeBasic = {
expr = iterate.findInRangeStr (i: lib.mod i 5 == 0) "10.0.0.1" "10.0.0.10";
expected = "10.0.0.5";
};
testFindInRangeNotFound = {
expr = iterate.findInRange (i: i > 1000000000) "10.0.0.1" "10.0.0.10";
expected = null;
};
}

266
tests/validate-tests.nix Normal file
View File

@@ -0,0 +1,266 @@
{ lib, validate }:
let
inherit (lib) runTests;
in runTests {
testIsValidIpBasic = {
expr = validate.isValidIp "192.168.1.1";
expected = true;
};
testIsValidIpZeros = {
expr = validate.isValidIp "0.0.0.0";
expected = true;
};
testIsValidIpMax = {
expr = validate.isValidIp "255.255.255.255";
expected = true;
};
testIsValidIpInvalidOctet = {
expr = validate.isValidIp "256.1.1.1";
expected = false;
};
testIsValidIpTooFewOctets = {
expr = validate.isValidIp "192.168.1";
expected = false;
};
testIsValidIpTooManyOctets = {
expr = validate.isValidIp "192.168.1.1.1";
expected = false;
};
testIsValidIpEmpty = {
expr = validate.isValidIp "";
expected = false;
};
testIsValidIpLetters = {
expr = validate.isValidIp "abc.def.ghi.jkl";
expected = false;
};
testIsValidIpNegative = {
expr = validate.isValidIp "-1.0.0.0";
expected = false;
};
testIsValidIpNotString = {
expr = validate.isValidIp 12345;
expected = false;
};
testIsValidCidrBasic = {
expr = validate.isValidCidr "192.168.1.0/24";
expected = true;
};
testIsValidCidrSlash0 = {
expr = validate.isValidCidr "0.0.0.0/0";
expected = true;
};
testIsValidCidrSlash32 = {
expr = validate.isValidCidr "192.168.1.1/32";
expected = true;
};
testIsValidCidrInvalidPrefix = {
expr = validate.isValidCidr "192.168.1.0/33";
expected = false;
};
testIsValidCidrNoPrefix = {
expr = validate.isValidCidr "192.168.1.0";
expected = false;
};
testIsValidCidrInvalidIp = {
expr = validate.isValidCidr "256.168.1.0/24";
expected = false;
};
testIsValidCidrEmpty = {
expr = validate.isValidCidr "";
expected = false;
};
testIsValidCidrNotString = {
expr = validate.isValidCidr 12345;
expected = false;
};
testTryParseIpValid = {
expr = validate.tryParseIp "192.168.1.1";
expected = 3232235777;
};
testTryParseIpInvalid = {
expr = validate.tryParseIp "invalid";
expected = null;
};
testTryParseCidrValid = {
expr = validate.tryParseCidr "192.168.1.0/24";
expected = { address = 3232235776; prefixLen = 24; };
};
testTryParseCidrInvalid = {
expr = validate.tryParseCidr "invalid";
expected = null;
};
testIsPrivate10 = {
expr = validate.isPrivate "10.1.2.3";
expected = true;
};
testIsPrivate172 = {
expr = validate.isPrivate "172.16.5.10";
expected = true;
};
testIsPrivate172Edge = {
expr = validate.isPrivate "172.31.255.255";
expected = true;
};
testIsPrivate172Outside = {
expr = validate.isPrivate "172.32.0.0";
expected = false;
};
testIsPrivate192 = {
expr = validate.isPrivate "192.168.100.50";
expected = true;
};
testIsPrivatePublic = {
expr = validate.isPrivate "8.8.8.8";
expected = false;
};
testIsLoopback127 = {
expr = validate.isLoopback "127.0.0.1";
expected = true;
};
testIsLoopback127Any = {
expr = validate.isLoopback "127.255.255.254";
expected = true;
};
testIsLoopbackFalse = {
expr = validate.isLoopback "128.0.0.1";
expected = false;
};
testIsLinkLocalTrue = {
expr = validate.isLinkLocal "169.254.1.1";
expected = true;
};
testIsLinkLocalFalse = {
expr = validate.isLinkLocal "169.255.1.1";
expected = false;
};
testIsMulticastTrue = {
expr = validate.isMulticast "224.0.0.1";
expected = true;
};
testIsMulticastMax = {
expr = validate.isMulticast "239.255.255.255";
expected = true;
};
testIsMulticastFalse = {
expr = validate.isMulticast "223.255.255.255";
expected = false;
};
testIsBroadcastTrue = {
expr = validate.isBroadcast "255.255.255.255";
expected = true;
};
testIsBroadcastFalse = {
expr = validate.isBroadcast "255.255.255.254";
expected = false;
};
testIsUnspecifiedTrue = {
expr = validate.isUnspecified "0.0.0.0";
expected = true;
};
testIsUnspecifiedFalse = {
expr = validate.isUnspecified "0.0.0.1";
expected = false;
};
testIsDocumentation192 = {
expr = validate.isDocumentation "192.0.2.1";
expected = true;
};
testIsDocumentation198 = {
expr = validate.isDocumentation "198.51.100.50";
expected = true;
};
testIsDocumentation203 = {
expr = validate.isDocumentation "203.0.113.100";
expected = true;
};
testIsDocumentationFalse = {
expr = validate.isDocumentation "192.0.3.1";
expected = false;
};
testIsGlobalUnicastPublic = {
expr = validate.isGlobalUnicast "8.8.8.8";
expected = true;
};
testIsGlobalUnicastPrivate = {
expr = validate.isGlobalUnicast "192.168.1.1";
expected = false;
};
testIsGlobalUnicastLoopback = {
expr = validate.isGlobalUnicast "127.0.0.1";
expected = false;
};
testClassifyLoopback = {
expr = validate.classify "127.0.0.1";
expected = "loopback";
};
testClassifyPrivate = {
expr = validate.classify "192.168.1.1";
expected = "private";
};
testClassifyLinkLocal = {
expr = validate.classify "169.254.1.1";
expected = "link-local";
};
testClassifyMulticast = {
expr = validate.classify "224.0.0.1";
expected = "multicast";
};
testClassifyGlobal = {
expr = validate.classify "8.8.8.8";
expected = "global-unicast";
};
}