summaryrefslogtreecommitdiffstats
path: root/nixos/lib/testing-python.nix
diff options
context:
space:
mode:
authorDavid Arnold <dar@xoe.solutions>2021-06-06 11:36:07 -0500
committerDavid Arnold <dar@xoe.solutions>2021-06-13 15:47:51 -0500
commit3884ff70badca0c93c717e6190946a9a2846e948 (patch)
tree8f9439bb6f3ef5f69d3c21dfdcd6bf537001c292 /nixos/lib/testing-python.nix
parentffb7cfcfad15e3bff9d05336767e59ee6ee24cb6 (diff)
nixos/tests/test-driver: cleanup nix expression
Less nesting, where that improves readability. More nesteing, where that improves readability, but most importantly: Expose individual functions separately so that they can be more easily built directly, eg.: `nix build --impure --expr '(import ./testing-python.nix {system = builtins.currentSystem;}).mkTestDriver'`
Diffstat (limited to 'nixos/lib/testing-python.nix')
-rw-r--r--nixos/lib/testing-python.nix257
1 files changed, 135 insertions, 122 deletions
diff --git a/nixos/lib/testing-python.nix b/nixos/lib/testing-python.nix
index 715482e87304..f5780123d6b0 100644
--- a/nixos/lib/testing-python.nix
+++ b/nixos/lib/testing-python.nix
@@ -16,13 +16,19 @@ rec {
inherit pkgs;
-
- mkTestDriver =
+ # Reifies and correctly wraps the python test driver for
+ # the respective qemu version and with or without ocr support
+ pythonTestDriver = {
+ qemu_pkg ? pkgs.qemu_test
+ , enableOCR ? false
+ }:
let
- testDriverScript = ./test-driver/test-driver.py;
- in
- qemu_pkg: stdenv.mkDerivation {
name = "nixos-test-driver";
+ testDriverScript = ./test-driver/test-driver.py;
+ ocrProg = tesseract4.override { enableLanguages = [ "eng" ]; };
+ imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
+ in stdenv.mkDerivation {
+ inherit name;
nativeBuildInputs = [ makeWrapper ];
buildInputs = [ (python3.withPackages (p: [ p.ptpython p.colorama ])) ];
@@ -35,7 +41,7 @@ rec {
buildPhase = ''
python <<EOF
from pydoc import importfile
- with open('driver-exports', 'w') as fp:
+ with open('driver-symbols', 'w') as fp:
fp.write(','.join(dir(importfile('${testDriverScript}'))))
EOF
'';
@@ -57,20 +63,17 @@ rec {
# TODO: copy user script part into this file (append)
wrapProgram $out/bin/nixos-test-driver \
+ --argv0 ${name} \
--prefix PATH : "${lib.makeBinPath [ qemu_pkg vde2 netpbm coreutils ]}" \
+ ${lib.optionalString enableOCR
+ "--prefix PATH : '${ocrProg}/bin:${imagemagick_tiff}/bin'"} \
- install -m 0644 -vD driver-exports $out/nix-support/driver-exports
+ install -m 0644 -vD driver-symbols $out/nix-support/driver-symbols
'';
};
# Run an automated test suite in the given virtual network.
- runTests = {
- # the script that runs the network
- driver,
- # a source position in the format of builtins.unsafeGetAttrPos
- # for meta.position
- pos,
- }:
+ runTests = { driver, pos }:
stdenv.mkDerivation {
name = "vm-test-run-${driver.testName}";
@@ -87,10 +90,99 @@ rec {
inherit driver;
};
- inherit pos;
+ inherit pos; # for better debugging
};
+ # Generate convenience wrappers for running the test driver
+ # has vlans, vms and test script defaulted through env variables
+ # also instantiates test script with nodes, if it's a function (contract)
+ setupDriverForTest = {
+ testScript
+ , testName
+ , nodes
+ , qemu_pkg ? pkgs.qemu_test
+ , enableOCR ? false
+ , skipLint ? false
+ , passthru ? {}
+ }:
+ let
+ # FIXME: get this pkg from the module system
+ testDriver = pythonTestDriver { inherit qemu_pkg enableOCR;};
+
+ testDriverName =
+ let
+ # A standard store path to the vm monitor is built like this:
+ # /tmp/nix-build-vm-test-run-$name.drv-0/vm-state-machine/monitor
+ # The max filename length of a unix domain socket is 108 bytes.
+ # This means $name can at most be 50 bytes long.
+ maxTestNameLen = 50;
+ testNameLen = builtins.stringLength testName;
+ in with builtins;
+ if testNameLen > maxTestNameLen then
+ abort
+ ("The name of the test '${testName}' must not be longer than ${toString maxTestNameLen} " +
+ "it's currently ${toString testNameLen} characters long.")
+ else
+ "nixos-test-driver-${testName}";
+
+ vlans = map (m: m.config.virtualisation.vlans) (lib.attrValues nodes);
+ vms = map (m: m.config.system.build.vm) (lib.attrValues nodes);
+
+ nodeHostNames = map (c: c.config.system.name) (lib.attrValues nodes);
+
+ invalidNodeNames = lib.filter
+ (node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null)
+ (builtins.attrNames nodes);
+
+ testScript' =
+ # Call the test script with the computed nodes.
+ if lib.isFunction testScript
+ then testScript { inherit nodes; }
+ else testScript;
+ in
+ if lib.length invalidNodeNames > 0 then
+ throw ''
+ Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
+ All machines are referenced as python variables in the testing framework which will break the
+ script when special characters are used.
+ Please stick to alphanumeric chars and underscores as separation.
+ ''
+ else lib.warnIf skipLint "Linting is disabled" (runCommand testDriverName
+ {
+ inherit testName;
+ nativeBuildInputs = [ makeWrapper ];
+ testScript = testScript';
+ preferLocalBuild = true;
+ passthru = passthru // {
+ inherit nodes;
+ };
+ }
+ ''
+ mkdir -p $out/bin
+
+ echo -n "$testScript" > $out/test-script
+ ${lib.optionalString (!skipLint) ''
+ PYFLAKES_BUILTINS="$(
+ echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
+ < ${lib.escapeShellArg "${testDriver}/nix-support/driver-symbols"}
+ )" ${python3Packages.pyflakes}/bin/pyflakes $out/test-script
+ ''}
+
+ ln -s ${testDriver}/bin/nixos-test-driver $out/bin/
+ vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
+ wrapProgram $out/bin/nixos-test-driver \
+ --add-flags "''${vms[*]}" \
+ --run "export testScript=\"\$(${coreutils}/bin/cat $out/test-script)\"" \
+ --set VLANS '${toString vlans}'
+ ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms
+ wrapProgram $out/bin/nixos-run-vms \
+ --add-flags "''${vms[*]}" \
+ --set tests 'start_all(); join_all();' \
+ --set VLANS '${toString vlans}'
+ '');
+
+ # Make a full-blown test
makeTest =
{ testScript
, enableOCR ? false
@@ -106,128 +198,47 @@ rec {
, ...
} @ t:
let
- # A standard store path to the vm monitor is built like this:
- # /tmp/nix-build-vm-test-run-$name.drv-0/vm-state-machine/monitor
- # The max filename length of a unix domain socket is 108 bytes.
- # This means $name can at most be 50 bytes long.
- maxTestNameLen = 50;
- testNameLen = builtins.stringLength name;
-
-
-
- ocrProg = tesseract4.override { enableLanguages = [ "eng" ]; };
-
- imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
-
- # Generate convenience wrappers for running the test driver
- # interactively with the specified network, and for starting the
- # VMs from the command line.
- mkDriver = qemu_pkg:
+ nodes = qemu_pkg:
let
build-vms = import ./build-vms.nix {
inherit system pkgs minimal specialArgs;
- extraConfigurations = extraConfigurations ++ (pkgs.lib.optional (qemu_pkg != null)
+ extraConfigurations = extraConfigurations ++ [(
{
virtualisation.qemu.package = qemu_pkg;
- }
- ) ++ [(
- {
# Ensure we do not use aliases. Ideally this is only set
# when the test framework is used by Nixpkgs NixOS tests.
nixpkgs.config.allowAliases = false;
}
)];
};
-
- # FIXME: get this pkg from the module system
- testDriver = mkTestDriver (if qemu_pkg == null then pkgs.qemu_test else qemu_pkg);
-
- nodes = build-vms.buildVirtualNetwork (
- t.nodes or (if t ? machine then { machine = t.machine; } else { })
- );
- vlans = map (m: m.config.virtualisation.vlans) (lib.attrValues nodes);
- vms = map (m: m.config.system.build.vm) (lib.attrValues nodes);
-
- testScript' =
- # Call the test script with the computed nodes.
- if lib.isFunction testScript
- then testScript { inherit nodes; }
- else testScript;
-
- testDriverName = with builtins;
- if testNameLen > maxTestNameLen then
- abort
- ("The name of the test '${name}' must not be longer than ${toString maxTestNameLen} " +
- "it's currently ${toString testNameLen} characters long.")
- else
- "nixos-test-driver-${name}";
in
- lib.warnIf skipLint "Linting is disabled" (runCommand testDriverName
- {
- nativeBuildInputs = [ makeWrapper ];
- testScript = testScript';
- preferLocalBuild = true;
- testName = name;
- passthru = passthru // {
- inherit nodes;
- };
- }
- ''
- mkdir -p $out/bin
-
- echo -n "$testScript" > $out/test-script
- ${lib.optionalString (!skipLint) ''
- PYFLAKES_BUILTINS="$(
- echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
- < ${lib.escapeShellArg "${testDriver}/nix-support/driver-exports"}
- )" ${python3Packages.pyflakes}/bin/pyflakes $out/test-script
- ''}
-
- ln -s ${testDriver}/bin/nixos-test-driver $out/bin/
- vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
- wrapProgram $out/bin/nixos-test-driver \
- --add-flags "''${vms[*]}" \
- ${lib.optionalString enableOCR
- "--prefix PATH : '${ocrProg}/bin:${imagemagick_tiff}/bin'"} \
- --run "export testScript=\"\$(${coreutils}/bin/cat $out/test-script)\"" \
- --set VLANS '${toString vlans}'
- ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms
- wrapProgram $out/bin/nixos-run-vms \
- --add-flags "''${vms[*]}" \
- ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \
- --set tests 'start_all(); join_all();' \
- --set VLANS '${toString vlans}'
- ''); # "
-
- passMeta = drv: drv // lib.optionalAttrs (t ? meta) {
- meta = (drv.meta or { }) // t.meta;
- };
-
- driver = mkDriver null;
- driverInteractive = mkDriver pkgs.qemu;
-
- test = passMeta (runTests { inherit driver pos; });
+ build-vms.buildVirtualNetwork (
+ t.nodes or (if t ? machine then { machine = t.machine; } else { })
+ );
- nodeNames = builtins.attrNames driver.nodes;
- invalidNodeNames = lib.filter
- (node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null)
- nodeNames;
+ driver = setupDriverForTest {
+ inherit testScript enableOCR skipLint;
+ testName = name;
+ qemu_pkg = pkgs.qemu_test;
+ nodes = nodes pkgs.qemu_test;
+ };
+ driverInteractive = setupDriverForTest {
+ inherit testScript enableOCR skipLint;
+ testName = name;
+ qemu_pkg = pkgs.qemu;
+ nodes = nodes pkgs.qemu;
+ };
- nodeHostNames = map (c: c.config.system.name) (lib.attrValues driver.nodes);
+ test =
+ let
+ passMeta = drv: drv // lib.optionalAttrs (t ? meta) {
+ meta = (drv.meta or { }) // t.meta;
+ };
+ in passMeta (runTests { inherit driver pos; });
in
- if lib.length invalidNodeNames > 0 then
- throw ''
- Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
- All machines are referenced as python variables in the testing framework which will break the
- script when special characters are used.
-
- Please stick to alphanumeric chars and underscores as separation.
- ''
- else
test // {
- inherit test driver driverInteractive;
- inherit (driver) nodes;
+ inherit test driver driverInteractive nodes;
};
runInMachine =
@@ -235,7 +246,7 @@ rec {
, machine
, preBuild ? ""
, postBuild ? ""
- , qemu ? pkgs.qemu_test
+ , qemu_pkg ? pkgs.qemu_test
, ... # ???
}:
let
@@ -272,6 +283,8 @@ rec {
client.succeed("sync") # flush all data before pulling the plug
'';
+ testDriver = pythonTestDriver { inherit qemu_pkg; };
+
vmRunCommand = writeText "vm-run" ''
xchg=vm-state-client/xchg
${coreutils}/bin/mkdir $out
@@ -290,7 +303,7 @@ rec {
unset xchg
export tests='${testScript}'
- ${mkTestDriver qemu}/bin/nixos-test-driver --keep-vm-state ${vm.config.system.build.vm}/bin/run-*-vm
+ ${testDriver}/bin/nixos-test-driver --keep-vm-state ${vm.config.system.build.vm}/bin/run-*-vm
''; # */
in