tests: optimize building multiple tests at once

The result of `import tests.nix {}` is now an attrset of tests.
This makes it easier and more efficient to evaluate or build multiple
tests in one call to `nix build`.

Simplify tests.nix by removing the large module args scope in favor of
self-contained scenario module definitions.

Add CPU core and memory size defaults to the test configuration to
enable building tests without `run-tests.sh`.

Add the following top-level args to tests.nix:
- `extraScenarios` to provide a nix-level way to define extra scenarios.
- `pkgs` to allow building tests with custom pkgs or systems.
This commit is contained in:
Erik Arvstedt 2021-03-22 13:19:48 +01:00
parent 9ca52af523
commit 44439e2a81
No known key found for this signature in database
GPG Key ID: 33312B944DD97846
5 changed files with 59 additions and 32 deletions

View File

@ -84,6 +84,6 @@ if [[ ! ($containerBin && $(realpath $containerBin) == *extra-container-0.6*) ]]
fi fi
read -d '' src <<EOF || true read -d '' src <<EOF || true
(import "$scriptDir/tests.nix" { scenario = "$scenario"; }).container ((import "$scriptDir/tests.nix" {}).getTest "$scenario").container
EOF EOF
exec extra-container $containerCommand -E "$src" "$@" exec extra-container $containerCommand -E "$src" "$@"

View File

@ -1,7 +1,7 @@
pkgs: pkgs:
let let
pythonTesting = import "${toString pkgs.path}/nixos/lib/testing-python.nix" { pythonTesting = import "${toString pkgs.path}/nixos/lib/testing-python.nix" {
system = builtins.currentSystem; system = pkgs.stdenv.hostPlatform.system;
inherit pkgs; inherit pkgs;
}; };
in in

View File

@ -1,7 +1,9 @@
pkgs:
let let
pkgs = import <nixpkgs> { config = {}; overlays = []; };
makeVM = import ./make-test-vm.nix pkgs; makeVM = import ./make-test-vm.nix pkgs;
inherit (pkgs) lib;
in in
name: testConfig: name: testConfig:
{ {
vm = makeVM { vm = makeVM {
@ -9,8 +11,15 @@ name: testConfig:
machine = { machine = {
imports = [ testConfig ]; imports = [ testConfig ];
virtualisation = {
# Needed because duplicity requires 270 MB of free temp space, regardless of backup size # Needed because duplicity requires 270 MB of free temp space, regardless of backup size
virtualisation.diskSize = 1024; diskSize = 1024;
# Min. 800 MiB needed to avoid 'out of memory' errors
memorySize = lib.mkDefault 2048;
cores = lib.mkDefault 2;
};
}; };
testScript = nodes: let testScript = nodes: let

View File

@ -110,7 +110,7 @@ trap 'eval "$runAtExit"' EXIT
if [[ $scenario = *' '* ]]; then if [[ $scenario = *' '* ]]; then
export scenarioOverridesFile=$(mktemp ${XDG_RUNTIME_DIR:-/tmp}/nb-scenario.XXX) export scenarioOverridesFile=$(mktemp ${XDG_RUNTIME_DIR:-/tmp}/nb-scenario.XXX)
runAtExit+='rm -f "$scenarioOverridesFile";' runAtExit+='rm -f "$scenarioOverridesFile";'
echo "{ testEnv, config, pkgs, lib }: with testEnv; with lib; { tmp = $scenario; }" > "$scenarioOverridesFile" echo "{ scenarios, pkgs, lib }: with lib; { tmp = $scenario; }" > "$scenarioOverridesFile"
scenario=tmp scenario=tmp
fi fi
@ -120,7 +120,7 @@ run() {
export TMPDIR=$(mktemp -d /tmp/nix-bitcoin-test.XXX) export TMPDIR=$(mktemp -d /tmp/nix-bitcoin-test.XXX)
runAtExit+="rm -rf $TMPDIR;" runAtExit+="rm -rf $TMPDIR;"
nix-build --out-link $TMPDIR/driver -E "(import \"$scriptDir/tests.nix\" { scenario = \"$scenario\"; }).vm" -A driver nix-build --out-link $TMPDIR/driver -E "((import \"$scriptDir/tests.nix\" {}).getTest \"$scenario\").vm" -A driver
# Variable 'tests' contains the Python code that is executed by the driver on startup # Variable 'tests' contains the Python code that is executed by the driver on startup
if [[ $1 == --interactive ]]; then if [[ $1 == --interactive ]]; then
@ -212,7 +212,7 @@ vmTestNixExpr() {
fi fi
cat <<EOF cat <<EOF
(import "$scriptDir/tests.nix" { scenario = "$scenario"; }).vm.overrideAttrs (old: rec { ((import "$scriptDir/tests.nix" {}).getTest "$scenario").vm.overrideAttrs (old: rec {
buildCommand = '' buildCommand = ''
export QEMU_OPTS="-smp $numCPUs -m $memoryMiB $extraQEMUOpts" export QEMU_OPTS="-smp $numCPUs -m $memoryMiB $extraQEMUOpts"
echo "VM stats: CPUs: $numCPUs, memory: $memoryMiB MiB" echo "VM stats: CPUs: $numCPUs, memory: $memoryMiB MiB"

View File

@ -1,14 +1,20 @@
# Integration tests, can be run without internet access. # Integration tests, can be run without internet access.
{ scenario ? "default" }: let
nixpkgs = (import ../pkgs/nixpkgs-pinned.nix).nixpkgs;
in
import ./lib/make-test.nix scenario ( { extraScenarios ? { ... }: {}
{ config, pkgs, lib, ... }: with lib; , pkgs ? import nixpkgs { config = {}; overlays = []; }
let testEnv = rec { }:
with pkgs.lib;
let
globalPkgs = pkgs;
baseConfig = { pkgs, config, ... }: let
cfg = config.services; cfg = config.services;
mkIfTest = test: mkIf (config.tests.${test} or false); mkIfTest = test: mkIf (config.tests.${test} or false);
in {
baseConfig = {
imports = [ imports = [
./lib/test-lib.nix ./lib/test-lib.nix
../modules/modules.nix ../modules/modules.nix
@ -26,6 +32,9 @@ let testEnv = rec {
}; };
config = mkMerge [{ config = mkMerge [{
# Share the same pkgs instance among tests
nixpkgs.pkgs = mkDefault globalPkgs;
tests.bitcoind = cfg.bitcoind.enable; tests.bitcoind = cfg.bitcoind.enable;
services.bitcoind = { services.bitcoind = {
enable = true; enable = true;
@ -183,14 +192,14 @@ let testEnv = rec {
]; ];
}; };
netnsBase = { netnsBase = { config, pkgs, ... }: {
nix-bitcoin.netns-isolation.enable = true; nix-bitcoin.netns-isolation.enable = true;
test.data.netns = config.nix-bitcoin.netns-isolation.netns; test.data.netns = config.nix-bitcoin.netns-isolation.netns;
tests.netns-isolation = true; tests.netns-isolation = true;
environment.systemPackages = [ pkgs.fping ]; environment.systemPackages = [ pkgs.fping ];
}; };
regtestBase = { regtestBase = { config, ... }: {
tests.regtest = true; tests.regtest = true;
services.bitcoind.regtest = true; services.bitcoind.regtest = true;
@ -241,20 +250,29 @@ let testEnv = rec {
# You can also set the env var `scenarioOverridesFile` (used below) to define custom scenarios. # You can also set the env var `scenarioOverridesFile` (used below) to define custom scenarios.
}; };
}; };
};
in
let
overrides = builtins.getEnv "scenarioOverridesFile"; overrides = builtins.getEnv "scenarioOverridesFile";
scenarios = testEnv.scenarios // (optionalAttrs (overrides != "") (import overrides { extraScenarios' = (if (overrides != "") then import overrides else extraScenarios) {
inherit testEnv config pkgs lib; inherit scenarios pkgs;
})); inherit (pkgs) lib;
autoScenario = {
services.${scenario}.enable = true;
}; };
in { allScenarios = scenarios // extraScenarios';
makeTest = name: config:
makeTest' name {
imports = [ imports = [
scenarios.base allScenarios.base
(scenarios.${scenario} or autoScenario) config
]; ];
};
makeTest' = import ./lib/make-test.nix pkgs;
tests = builtins.mapAttrs makeTest allScenarios;
getTest = name: tests.${name} or (makeTest name {
services.${name}.enable = true;
});
in
tests // {
inherit getTest;
} }
)