refactor(nix/runTestsuite): implement in terms of generic assertBool

Refactor assertEq and assertThrows to be implemented in terms of a more
generic assertBool to reduce code duplication and ease adding new assert
types.

To preserve meaningful error messages AssertResult is changed slightly:
nope-eq and nope-throw have been replaced by a single nope branch which
contains an AssertErrorContext which contains error information. To
implement an assert assertBoolContext (which is not exposed) can be
used: It takes an AssertErrorContext which is returned in case of an
error and a boolean determining whether the assert was successful.

The currently possible AssertErrorContext are:

* should-throw: error result of assertThrows, formerly nope-throw
* not-equal: error result of assertEq, formerly nope-eq

Change-Id: Ifd6b3aa4187c90c3add2df63fa7c906c8f03fd2d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2473
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
This commit is contained in:
sterni 2021-01-31 13:41:32 +01:00
parent 03f1fefc72
commit 00f79da358

View file

@ -34,10 +34,15 @@ let
defun defun
list list
drv drv
bool
; ;
bins = depot.nix.getBins pkgs.coreutils [ "printf" "touch" ]; bins = depot.nix.getBins pkgs.coreutils [ "printf" "touch" ];
# Returns true if the given expression throws when `deepSeq`-ed
throws = expr:
!(builtins.tryEval (builtins.deepSeq expr {})).success;
# rewrite the builtins.partition result # rewrite the builtins.partition result
# to use `ok` and `err` instead of `right` and `wrong`. # to use `ok` and `err` instead of `right` and `wrong`.
partitionTests = pred: xs: partitionTests = pred: xs:
@ -47,23 +52,30 @@ let
err = res.wrong; err = res.wrong;
}; };
AssertErrorContext =
sum "AssertErrorContext" {
not-equal = struct "not-equal" {
left = any;
right = any;
};
should-throw = struct "should-throw" {
expr = any;
};
};
# The result of an assert, # The result of an assert,
# either its true (yep) or false (nope). # either its true (yep) or false (nope).
# If its nope, we return the left and right # If it's nope we return an additional context
# side of the assert, together with the description. # attribute which gives details on the failure
# depending on the type of assert performed.
AssertResult = AssertResult =
sum "AssertResult" { sum "AssertResult" {
yep = struct "yep" { yep = struct "yep" {
test = string; test = string;
}; };
nope-eq = struct "nope-eq" { nope = struct "nope" {
test = string; test = string;
left = any; context = AssertErrorContext;
right = any;
};
nope-throw = struct "nope-throw" {
test = string;
expr = any;
}; };
}; };
@ -75,27 +87,37 @@ let
asserts = list AssertResult; asserts = list AssertResult;
}; };
# If the given boolean is true return a positive AssertResult.
# If the given boolean is false return a negative AssertResult
# with the provided AssertErrorContext describing the failure.
#
# This function is intended as a generic assert to implement
# more assert types and is not exposed to the user.
assertBoolContext = defun [ AssertErrorContext string bool AssertResult ]
(context: desc: res:
if res
then { yep = { test = desc; }; }
else { nope = {
test = desc;
inherit context;
};
});
# assert that left and right values are equal # assert that left and right values are equal
assertEq = defun [ string any any AssertResult ] assertEq = defun [ string any any AssertResult ]
(desc: left: right: (desc: left: right:
if left == right let
then { yep = { test = desc; }; } context = { not-equal = { inherit left right; }; };
else { nope-eq = { in
test = desc; assertBoolContext context desc (left == right));
inherit left right;
};
});
# assert that the expression throws when `deepSeq`-ed # assert that the expression throws when `deepSeq`-ed
assertThrows = defun [ string any AssertResult ] assertThrows = defun [ string any AssertResult ]
(desc: expr: (desc: expr:
if ! (builtins.tryEval (builtins.deepSeq expr {})).success let
then { yep = { test = desc; }; } context = { should-throw = { inherit expr; }; };
else { nope-throw = { in
test = desc; assertBoolContext context desc (throws expr));
inherit expr;
};
});
# Annotate a bunch of asserts with a descriptive name # Annotate a bunch of asserts with a descriptive name
it = desc: asserts: { it = desc: asserts: {
@ -114,8 +136,7 @@ let
goodAss = ass: { goodAss = ass: {
good = AssertResult.match ass { good = AssertResult.match ass {
yep = _: true; yep = _: true;
nope-eq = _: false; nope = _: false;
nope-throw = _: false;
}; };
x = ass; x = ass;
}; };
@ -124,8 +145,7 @@ let
asserts = partitionTests (ass: asserts = partitionTests (ass:
AssertResult.match ass { AssertResult.match ass {
yep = _: true; yep = _: true;
nope-eq = _: false; nope = _: false;
nope-throw = _: false;
}) it.asserts; }) it.asserts;
}; };
goodIts = partitionTests (it: (goodIt it).asserts.err == []); goodIts = partitionTests (it: (goodIt it).asserts.err == []);