diff options
| author | tv <tv@krebsco.de> | 2026-11-14 00:33:20 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-14 01:48:35 +0100 |
| commit | dd166e5a4d4349241aa3408c8d7f7340cb0a90fb (patch) | |
| tree | 0955739060de93d99c6bc7828adc377815ad02a8 /tests/default.nix | |
| parent | a4540a584d762b000b21cb7e61987c414eb72a1d (diff) | |
tests: populate's tests of its own, krops' using them
populate's tests are in pkgs/populate/tests, independent of krops.
They run the program, with the sources as JSON from populate's Nix
library, and target strings for the remote targets, leaving the user
and whether the target is local to populate, so they cover its command
line too. Phases expecting populate to refuse its arguments, e.g. a
source name or a target path that can't be used, expect the program's
refusal, with refused, the message, since nothing checks them during
evaluation there.
builder.nix is what builds the scenarios, which krops' tests use as
well, with a function running the phases, and whether that checks the
arguments during evaluation. vm.nix takes a module for both machines,
for what else the scenarios run, and fixtures.nix and smoke.nix are
what both use of the fixtures and the smoke test.
krops' tests are deploy, writeDeploy's arguments to nixos-rebuild, with
the stand-in for nixos-rebuild in the module, and populate, populate's
scenarios that expect refusals, which pkgs.populate makes evaluation
fail with, and those of populate's smoke test, all through
pkgs.populate with target attribute sets as mkTarget returns them.
-A only selects from all of populate's scenarios and krops' own.
Diffstat (limited to 'tests/default.nix')
| -rw-r--r-- | tests/default.nix | 182 |
1 files changed, 98 insertions, 84 deletions
diff --git a/tests/default.nix b/tests/default.nix index 0e59e26..475ab5d 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -1,88 +1,118 @@ -# 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. -# 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. -# The smoke test runs a few scenarios covering each source type and each kind -# of target in a single VM test, for checking changes quickly; build it with -# nix-build tests -A smoke. nix-build tests -A only --argstr only REGEX runs -# the scenarios whose names match the regular expression REGEX in a single -# VM test, e.g. --argstr only 'lock-hooks-.*'. +# NixOS VM tests for krops, with the VM machinery and the scenarios of +# populate's tests, in ../pkgs/populate/tests: deploy, for writeDeploy's +# arguments to nixos-rebuild, and populate, for pkgs.populate, running +# populate's scenarios that expect populate to refuse its arguments, which +# pkgs.populate does during evaluation here, and the scenarios of +# populate's smoke test, with target attribute sets as mkTarget returns +# them. Build all with nix-build tests, or one with, e.g., nix-build tests +# -A deploy. 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. The smoke test runs a few scenarios of +# each in a single VM test; build it with nix-build tests -A smoke. +# nix-build tests -A only --argstr only REGEX runs the scenarios whose +# names match the regular expression REGEX, of all of populate's scenarios +# and krops' own, in a single VM test, e.g. --argstr only 'lock-hooks-.*'. +# populate's own tests run the program directly; see +# ../pkgs/populate/README.md. { pkgs ? import ../pkgs {}, only ? null }: let - # HEAD of /fixtures/gitsrc, which fixtures.sh creates deterministically, - # and its parent. fixtures.sh fails if HEAD differs, naming the actual one. - gitHead = "e42d44ef9cdb76ba5a84dff4c89c38222703bf0c"; - gitFirst = "8d47013fa0888948cf0ffcc4e3c69a7b5f180562"; + inherit (pkgs) lib; + krops = import ../lib; + populateTests = ../pkgs/populate/tests; - # rsync versions the scenarios depending on rsync's version run with. - # callPackage adds override and overrideDerivation, which aren't versions. - rsyncs = pkgs.lib.filterAttrs - (_: pkgs.lib.isDerivation) - (pkgs.callPackage ./rsync.nix {}); + inherit (import (populateTests + "/fixtures.nix")) gitHead gitFirst; - # The scenarios, with populate using rsync. - scenariosWith = rsync: let - populate = pkgs.populate.override { inherit rsync; }; - in import ./scenarios.nix { - inherit (pkgs) lib; - krops = import ../lib; - inherit populate; - inherit (pkgs.krops.override { inherit populate; }) writeDeploy; + remoteHost = "target"; + + # Targets of each kind for a path, as mkTarget returns them. + targets = { + local = path: krops.mkTarget "" // { host = "localhost"; inherit path; }; + remote = path: { + user = "root"; host = remoteHost; port = null; inherit path; + sudo = false; extraOptions = []; + }; + sudo = path: { + user = "deploy"; host = remoteHost; port = null; inherit path; + sudo = true; extraOptions = []; + }; + }; + + # A phase runs pkgs.populate, or writeDeploy with a stand-in for + # nixos-rebuild. + run = { + source, backup, force, prune, deploy, targetKind, targetPath, + }: let + args = { + inherit source backup force prune; + target = targets.${targetKind} targetPath; + }; + in + if deploy == null then pkgs.populate args + else pkgs.krops.writeDeploy "deploy" + (args // { useNixOutputMonitor = false; } // deploy); + + builderArgs = { + inherit lib run; + inherit (krops) evalSource; + checksDuringEvaluation = true; url = "http://deployer:8000"; gitUrl = "git://deployer/gitsrc.git"; - remoteHost = "target"; + inherit remoteHost; agePath = "${pkgs.age}/bin/age"; inherit gitHead gitFirst; - rsyncVersion = rsync.version; + rsyncVersion = pkgs.rsync.version; + }; + + populateScenarios = lib.concatLists (builtins.attrValues + (import (populateTests + "/scenarios.nix") builderArgs)); + kropsScenarios = import ./scenarios.nix (builderArgs // { inherit targets; }); + + # Names of the scenarios of the smoke test, besides populate's. + smokeNames = import (populateTests + "/smoke.nix") ++ [ + "deploy-local-buildTarget0-etcFlake0-flakefile" + "deploy-sudo-allocateTTY" + ]; + + scenarios = { + inherit (kropsScenarios) deploy; + populate = builtins.filter + (scenario: scenario.refusals || builtins.elem scenario.name smokeNames) + populateScenarios; + }; + allScenarios = populateScenarios ++ lib.concatLists (builtins.attrValues kropsScenarios); + + # The stand-in for nixos-rebuild replaces it on both machines. + module = { pkgs, ... }: { + environment.systemPackages = [ + (pkgs.writeScriptBin "nixos-rebuild" (builtins.readFile ./nixos-rebuild.sh)) + ]; + system.disableInstallerTools = true; }; - scenarios = scenariosWith pkgs.rsync; + + vm = name: scenarios: import (populateTests + "/vm.nix") { + inherit pkgs gitHead scenarios module; + name = "krops-${name}"; + }; + # 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 != []) + testsOf = exhaustive: prefix: lib.mapAttrs + (name: scenarios: vm (prefix + name) scenarios) + (lib.filterAttrs (_: scenarios: scenarios != []) (builtins.mapAttrs (_: builtins.filter (scenario: scenario.exhaustive == exhaustive)) scenarios)); - # Names of the scenarios of the smoke test. - smokeNames = [ - "file-local-checksum0-deleteExcluded0-filters0-inputsnone" - "file-sudo-checksum0-deleteExcluded0-filters1-inputsnone" - "git-remote-cleanExclude0-fetchAlways0-inputsnone-shallow0" - "git-local-shallow1-refs" - "symlink-local-absolute0-inputs0" - "pass-remote-storepass" - "passage-sudo-agedefault-dirstore" - "pipe-local" - "derivation-remote" - "flake-local-fetchOnTarget0-inputsrewrite-kindgit-materialize0" - "flake-sudo-fetchOnTarget1-inputsnone-kindgit-materialize0" - "flake-input-dep-remote-fetchOnTarget0-inputsgenerated-materialize0" - "flake-input-sub-local-fetchOnTarget0-materialize0" - "state-sentinel-local" - "prune-remote" - "names-local" - "paths-local" - "deploy-local-buildTarget0-etcFlake0-flakefile" - "deploy-sudo-allocateTTY" - ]; - allScenarios = pkgs.lib.concatLists (builtins.attrValues scenarios); smokeScenarios = let selected = builtins.filter (scenario: builtins.elem scenario.name smokeNames) allScenarios; - missing = pkgs.lib.subtractLists (map (scenario: scenario.name) selected) smokeNames; + missing = lib.subtractLists (map (scenario: scenario.name) selected) smokeNames; in if missing != [] then throw "tests: smoke test names missing scenarios: ${toString missing}" else selected; + # The scenarios whose names match the regular expression only. onlyScenarios = let selected = builtins.filter @@ -96,32 +126,16 @@ let else selected; in + +# The remote target must not count as local wherever this gets evaluated. +assert !(krops.isLocalTarget (targets.remote "/")); + testsOf false "" # Not built by nix-build tests either, which runs these scenarios anyway. // { - smoke.smoke = import ./vm.nix { - inherit pkgs gitHead; - name = "smoke"; - scenarios = smokeScenarios; - }; - only.only = import ./vm.nix { - inherit pkgs gitHead; - name = "only"; - scenarios = onlyScenarios; - }; + smoke.smoke = vm "smoke" smokeScenarios; + only.only = vm "only" onlyScenarios; } # 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}"; - value = import ./vm.nix { - inherit pkgs gitHead rsync; - name = "rsync-${version}"; - scenarios = builtins.filter - (scenario: pkgs.lib.hasInfix "insecureLinks" scenario.name) - (scenariosWith rsync).file; - }; - }) - rsyncs |
