mirror of
https://gitlab.com/TECHNOFAB/nixtest.git
synced 2026-11-01 13:12:19 +01:00
297 lines
6.9 KiB
Nix
297 lines
6.9 KiB
Nix
|
|
{lib, ...}: let
|
||
|
|
inherit (lib) generators;
|
||
|
|
|
||
|
|
# Format any value to a readable string safely
|
||
|
|
formatVal = val:
|
||
|
|
if builtins.isString val
|
||
|
|
then val
|
||
|
|
else if builtins.isBool val || builtins.isInt val || builtins.isFloat val
|
||
|
|
then builtins.toString val
|
||
|
|
else generators.toPretty {} val;
|
||
|
|
|
||
|
|
mkFailure = {
|
||
|
|
message ? "Assertion failed",
|
||
|
|
expected ? null,
|
||
|
|
actual ? null,
|
||
|
|
}: {
|
||
|
|
ok = false;
|
||
|
|
inherit message;
|
||
|
|
expected =
|
||
|
|
if expected != null
|
||
|
|
then formatVal expected
|
||
|
|
else "";
|
||
|
|
actual =
|
||
|
|
if actual != null
|
||
|
|
then formatVal actual
|
||
|
|
else "";
|
||
|
|
};
|
||
|
|
in rec {
|
||
|
|
inherit formatVal;
|
||
|
|
|
||
|
|
equal = expected: actual:
|
||
|
|
if actual == expected
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected values to be equal";
|
||
|
|
inherit expected actual;
|
||
|
|
};
|
||
|
|
eq = equal;
|
||
|
|
|
||
|
|
notEqual = expected: actual:
|
||
|
|
if actual != expected
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected values to not be equal";
|
||
|
|
expected = "not ${formatVal expected}";
|
||
|
|
inherit actual;
|
||
|
|
};
|
||
|
|
ne = notEqual;
|
||
|
|
|
||
|
|
greaterThan = actual: min:
|
||
|
|
if actual > min
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to be greater than ${formatVal min}";
|
||
|
|
expected = "> ${formatVal min}";
|
||
|
|
inherit actual;
|
||
|
|
};
|
||
|
|
gt = greaterThan;
|
||
|
|
|
||
|
|
greaterThanOrEqual = actual: min:
|
||
|
|
if actual >= min
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to be greater than or equal to ${formatVal min}";
|
||
|
|
expected = ">= ${formatVal min}";
|
||
|
|
inherit actual;
|
||
|
|
};
|
||
|
|
gte = greaterThanOrEqual;
|
||
|
|
|
||
|
|
lessThan = actual: max:
|
||
|
|
if actual < max
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to be less than ${formatVal max}";
|
||
|
|
expected = "< ${formatVal max}";
|
||
|
|
inherit actual;
|
||
|
|
};
|
||
|
|
lt = lessThan;
|
||
|
|
|
||
|
|
lessThanOrEqual = actual: max:
|
||
|
|
if actual <= max
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to be less than or equal to ${formatVal max}";
|
||
|
|
expected = "<= ${formatVal max}";
|
||
|
|
inherit actual;
|
||
|
|
};
|
||
|
|
lte = lessThanOrEqual;
|
||
|
|
|
||
|
|
contains = container: item:
|
||
|
|
if builtins.isList container
|
||
|
|
then
|
||
|
|
if builtins.elem item container
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected list to contain item";
|
||
|
|
expected = "to contain: ${formatVal item}";
|
||
|
|
actual = container;
|
||
|
|
}
|
||
|
|
else if builtins.isString container
|
||
|
|
then
|
||
|
|
if lib.strings.hasInfix item container
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected string to contain substring";
|
||
|
|
expected = "to contain: ${formatVal item}";
|
||
|
|
actual = container;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected list or string for 'contains'";
|
||
|
|
actual = container;
|
||
|
|
};
|
||
|
|
|
||
|
|
notContains = container: item:
|
||
|
|
if builtins.isList container
|
||
|
|
then
|
||
|
|
if !(builtins.elem item container)
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected list to not contain item";
|
||
|
|
expected = "not to contain: ${formatVal item}";
|
||
|
|
actual = container;
|
||
|
|
}
|
||
|
|
else if builtins.isString container
|
||
|
|
then
|
||
|
|
if !(lib.strings.hasInfix item container)
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected string to not contain substring";
|
||
|
|
expected = "not to contain: ${formatVal item}";
|
||
|
|
actual = container;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected list or string for 'notContains'";
|
||
|
|
actual = container;
|
||
|
|
};
|
||
|
|
|
||
|
|
hasAttr = attr: set:
|
||
|
|
if !(builtins.isAttrs set)
|
||
|
|
then
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected attrset for 'hasAttr'";
|
||
|
|
actual = set;
|
||
|
|
}
|
||
|
|
else if builtins.hasAttr attr set
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected attrset to have attribute '${attr}'";
|
||
|
|
expected = "to have attribute: ${attr}";
|
||
|
|
actual = "available attributes: ${formatVal (builtins.attrNames set)}";
|
||
|
|
};
|
||
|
|
|
||
|
|
missingAttr = attr: set:
|
||
|
|
if !(builtins.isAttrs set)
|
||
|
|
then
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected attrset for 'missingAttr'";
|
||
|
|
actual = set;
|
||
|
|
}
|
||
|
|
else if !(builtins.hasAttr attr set)
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected attrset to not have attribute '${attr}'";
|
||
|
|
expected = "not to have attribute: ${attr}";
|
||
|
|
actual = "found attribute '${attr}' with value: ${formatVal set.${attr}}";
|
||
|
|
};
|
||
|
|
|
||
|
|
hasAttrs = attrs: set:
|
||
|
|
if !(builtins.isAttrs set)
|
||
|
|
then
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected attrset for 'hasAttrs'";
|
||
|
|
actual = set;
|
||
|
|
}
|
||
|
|
else let
|
||
|
|
missing = builtins.filter (a: !builtins.hasAttr a set) attrs;
|
||
|
|
in
|
||
|
|
if missing == []
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected attrset to have attributes ${formatVal attrs}";
|
||
|
|
expected = "missing attributes: ${formatVal missing}";
|
||
|
|
actual = "available attributes: ${formatVal (builtins.attrNames set)}";
|
||
|
|
};
|
||
|
|
|
||
|
|
matches = regex: str:
|
||
|
|
if !(builtins.isString str)
|
||
|
|
then
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected string for 'matches'";
|
||
|
|
actual = str;
|
||
|
|
}
|
||
|
|
else if builtins.match regex str != null
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected string to match regex '${regex}'";
|
||
|
|
expected = "match regex: ${regex}";
|
||
|
|
actual = str;
|
||
|
|
};
|
||
|
|
|
||
|
|
isNull = val:
|
||
|
|
if val == null
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to be null";
|
||
|
|
expected = "null";
|
||
|
|
actual = val;
|
||
|
|
};
|
||
|
|
|
||
|
|
isNotNull = val:
|
||
|
|
if val != null
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to not be null";
|
||
|
|
expected = "not null";
|
||
|
|
actual = "null";
|
||
|
|
};
|
||
|
|
|
||
|
|
isEmpty = val: let
|
||
|
|
empty =
|
||
|
|
if builtins.isList val
|
||
|
|
then val == []
|
||
|
|
else if builtins.isAttrs val
|
||
|
|
then val == {}
|
||
|
|
else if builtins.isString val
|
||
|
|
then val == ""
|
||
|
|
else false;
|
||
|
|
in
|
||
|
|
if empty
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to be empty";
|
||
|
|
expected = "empty";
|
||
|
|
actual = val;
|
||
|
|
};
|
||
|
|
|
||
|
|
isNotEmpty = val: let
|
||
|
|
notEmpty =
|
||
|
|
if builtins.isList val
|
||
|
|
then val != []
|
||
|
|
else if builtins.isAttrs val
|
||
|
|
then val != {}
|
||
|
|
else if builtins.isString val
|
||
|
|
then val != ""
|
||
|
|
else true;
|
||
|
|
in
|
||
|
|
if notEmpty
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected value to not be empty";
|
||
|
|
expected = "not empty";
|
||
|
|
actual = val;
|
||
|
|
};
|
||
|
|
|
||
|
|
throws = expr: let
|
||
|
|
res = builtins.tryEval expr;
|
||
|
|
in
|
||
|
|
if !res.success
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
message = "Expected expression to throw an error, but it succeeded";
|
||
|
|
expected = "to throw";
|
||
|
|
actual = "evaluated to: ${formatVal res.value}";
|
||
|
|
};
|
||
|
|
fails = throws;
|
||
|
|
|
||
|
|
custom = cond: message:
|
||
|
|
if cond
|
||
|
|
then true
|
||
|
|
else
|
||
|
|
mkFailure {
|
||
|
|
inherit message;
|
||
|
|
};
|
||
|
|
that = custom;
|
||
|
|
}
|