diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/default.nix | 25 | ||||
| -rw-r--r-- | tests/scenarios.nix | 38 |
2 files changed, 55 insertions, 8 deletions
diff --git a/tests/default.nix b/tests/default.nix index 3dabee9..686b130 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -1,7 +1,10 @@ # NixOS VM tests for populate: one test per source type, one for features # spanning sources, one for edge cases of flakes, one for staying inside the -# target directory, and one for writeDeploy's arguments to nixos-rebuild. Build all with nix-build tests, or one with, -# e.g., nix-build tests -A flake. jq runs populate's jq programs for flakes +# target directory, and one for writeDeploy's arguments to nixos-rebuild. +# Build all with nix-build tests, or one with, e.g., nix-build tests -A flake. +# The exhaustive tests add the combinations of options that no code path +# tells apart from the ones the others cover; build them with nix-build tests +# -A exhaustive, or one with, e.g., nix-build tests -A exhaustive.flake. jq runs populate's jq programs for flakes # without VMs. { pkgs ? import ../pkgs {} }: @@ -32,10 +35,22 @@ let }; scenarios = scenariosWith pkgs.rsync; flakeJq = import ../pkgs/populate/flake-jq.nix; + # VM tests of those of the groups of scenarios that are, or aren't, + # exhaustive, named after the groups with prefix in front. + testsOf = exhaustive: prefix: pkgs.lib.mapAttrs + (name: scenarios: import ./vm.nix { + inherit pkgs gitHead scenarios; + name = prefix + name; + }) + (pkgs.lib.filterAttrs (_: scenarios: scenarios != []) + (builtins.mapAttrs + (_: builtins.filter (scenario: scenario.exhaustive == exhaustive)) + scenarios)); in - builtins.mapAttrs - (name: scenarios: import ./vm.nix { inherit pkgs name scenarios gitHead; }) - scenarios + testsOf false "" + # An attribute set without recurseForDerivations, so nix-build tests + # doesn't build them. + // { exhaustive = testsOf true "exhaustive-"; } // pkgs.lib.mapAttrs' (version: rsync: { name = "rsync-${builtins.replaceStrings [ "." ] [ "-" ] version}"; diff --git a/tests/scenarios.nix b/tests/scenarios.nix index 2aecc53..4429409 100644 --- a/tests/scenarios.nix +++ b/tests/scenarios.nix @@ -82,9 +82,11 @@ let # Builds a scenario from a name, a target kind, and phases with sources. # Isolated scenarios start with no target directories and a collected store # on both machines, so no other scenario's store paths or roots stand in for - # missing ones. + # missing ones. An exhaustive scenario covers a combination that no code + # path tells apart from the ones the other scenarios cover, so it only runs + # in the exhaustive tests. scenario = { - name, targetKind, node ? null, isolate ? false, + name, targetKind, node ? null, isolate ? false, exhaustive ? false, prepare ? "", prepareDeployer ? null, phases, }: let path = "/var/krops/${name}"; @@ -146,7 +148,7 @@ let mutateDeployer = script mutateDeployer; }; in { - inherit name isolate; + inherit name isolate exhaustive; node = if node != null then node else if targetKind == "local" then "deployer" @@ -244,6 +246,10 @@ assert !(krops.isLocalTarget (targets.remote "/")); file = let f = flags: _: { + # Drawing inputs happens after rsync, so it doesn't depend on rsync's + # options. + exhaustive = flags.inputs != "none" && + (flags.checksum || flags.deleteExcluded || flags.filters); prepare = '' mkdir -p "$T"/x echo old > "$T"/x/skip-ex @@ -406,6 +412,10 @@ assert !(krops.isLocalTarget (targets.remote "/")); # The flake in a subdirectory has no inputs to draw from sources. if flags.kind == "subdir" && flags.inputs != "none" then null else { isolate = true; + # Materializing copies what got delivered, whichever way, so it depends + # on how inputs get drawn and on subdirectories, not on how the flake got + # there. + exhaustive = flags.materialize && !lib.elem flags.kind [ "git" "subdir" ]; phases = twice ({ sources = { x.flake = { @@ -438,6 +448,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); inputs = flags.inputs or "none"; in { isolate = true; + # Materializing copies what got delivered, whichever input it is. + exhaustive = flags.materialize && name != "dep"; phases = twice ({ sources = { x.flake-input = { @@ -497,6 +509,10 @@ assert !(krops.isLocalTarget (targets.remote "/")); } // drawInputs flags.inputs { dep.follows = "alt"; }; } // optionalAttrs (flags.inputs != "none") alt; in { + # Drawing inputs happens after Git, so it doesn't depend on Git's + # options. + exhaustive = flags.inputs != "none" && + (flags.shallow || flags.fetchAlways || flags.cleanExclude); phases = [ # The older commit first, so deploying HEAD changes the work tree, and # fetches if fetchAlways is set or the clone is shallow. @@ -664,6 +680,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); # The local target can't have another build target. if flags.buildTarget && ctx.targetKind == "local" then null else { node = if flags.buildTarget then "deployer" else null; + # /etc/nixos/flake.nix only matters if no flake gets deployed. + exhaustive = flags.etcFlake && flags.flake != "none"; # Each scenario creates or removes /etc/nixos/flake.nix. prepare = '' rm -f /tmp/nixos-rebuild.log @@ -1231,6 +1249,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); # An input that gets drawn from a source isn't needed on the target, with # all it pins. (modes "overridden-roots" ({ draw, mode, ... }: { + # What gets delivered doesn't depend on how inputs get drawn. + exhaustive = mode == "generated"; phases = twice { sources = alt // { x.flake-input = { @@ -1246,6 +1266,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); # The input's own lock file pins something unreachable, which gets drawn # from a source anyway. (modes "own-lock-unreachable" ({ draw, mode, ... }: { + # What gets delivered doesn't depend on how inputs get drawn. + exhaustive = mode == "generated"; prepareDeployer = '' rm -fR /root/.cache/nix ''; @@ -1427,6 +1449,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); # An input of an input drawn from a source that draws inputs itself # gets drawn from another source. (modes "override" ({ draw, flake, ... }: { + # Drawing inputs happens on the target alike for every kind of target. + exhaustive = targetKind != "local"; phases = twice { sources = { x.flake = { @@ -1444,6 +1468,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); # The same one level deeper: the input gets drawn from a source below # an input that the source in between draws from a source itself. (modes "override-deep" ({ draw, flake, ... }: { + # Drawing inputs happens on the target alike for every kind of target. + exhaustive = targetKind != "local"; phases = twice { sources = { x.flake = { @@ -1461,6 +1487,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); # A source with a rewritten lock file draws an input from a source with # a generated flake, and an input below it from another source. (s "override-mixed" { + # Drawing inputs happens on the target alike for every kind of target. + exhaustive = targetKind != "local"; phases = twice { sources = { x.flake = { @@ -1481,6 +1509,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); }; }) (modes "nonflake-input" ({ draw, flake, ... }: { + # Drawing inputs happens on the target alike for every kind of target. + exhaustive = targetKind != "local"; phases = twice { sources = { x.file = { path = "/fixtures/usedata"; } // draw { data.follows = "data"; }; @@ -1538,6 +1568,8 @@ assert !(krops.isLocalTarget (targets.remote "/")); (modes "source-name" ({ draw, flake, ... }: let x = from: { path = "/fixtures/filesrc"; } // draw { dep.follows = from; }; in { + # Drawing inputs happens on the target alike for every kind of target. + exhaustive = targetKind != "local"; phases = twice { sources = { "alt-1.0".file = "/fixtures/alt"; |
