2019-09-06 09:25:22 +02:00
|
|
|
{ system
|
|
|
|
, pkgs ? import ../.. { inherit system config; }
|
|
|
|
# Use a minimal kernel?
|
|
|
|
, minimal ? false
|
|
|
|
# Ignored
|
2020-10-23 23:13:38 +02:00
|
|
|
, config ? { }
|
2020-06-02 16:27:07 +02:00
|
|
|
# !!! See comment about args in lib/modules.nix
|
2020-10-23 23:13:38 +02:00
|
|
|
, specialArgs ? { }
|
2019-09-06 09:25:22 +02:00
|
|
|
# Modules to add to each VM
|
2020-10-23 23:13:38 +02:00
|
|
|
, extraConfigurations ? [ ]
|
|
|
|
}:
|
2019-09-06 09:25:22 +02:00
|
|
|
|
|
|
|
with pkgs;
|
|
|
|
|
2020-05-14 14:34:50 +02:00
|
|
|
rec {
|
2019-09-06 09:25:22 +02:00
|
|
|
|
|
|
|
inherit pkgs;
|
|
|
|
|
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
mkTestDriver =
|
|
|
|
let
|
|
|
|
testDriverScript = ./test-driver/test-driver.py;
|
|
|
|
in
|
|
|
|
qemu_pkg: stdenv.mkDerivation {
|
|
|
|
name = "nixos-test-driver";
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
nativeBuildInputs = [ makeWrapper ];
|
2021-05-15 01:57:11 +02:00
|
|
|
buildInputs = [ (python3.withPackages (p: [ p.ptpython p.colorama ])) ];
|
2020-10-23 23:13:38 +02:00
|
|
|
checkInputs = with python3Packages; [ pylint black mypy ];
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
dontUnpack = true;
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
preferLocalBuild = true;
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2021-05-08 17:52:22 +02:00
|
|
|
buildPhase = ''
|
|
|
|
python <<EOF
|
|
|
|
from pydoc import importfile
|
|
|
|
with open('driver-exports', 'w') as fp:
|
|
|
|
fp.write(','.join(dir(importfile('${testDriverScript}'))))
|
|
|
|
EOF
|
|
|
|
'';
|
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
doCheck = true;
|
|
|
|
checkPhase = ''
|
|
|
|
mypy --disallow-untyped-defs \
|
|
|
|
--no-implicit-optional \
|
|
|
|
--ignore-missing-imports ${testDriverScript}
|
|
|
|
pylint --errors-only ${testDriverScript}
|
|
|
|
black --check --diff ${testDriverScript}
|
|
|
|
'';
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
installPhase =
|
|
|
|
''
|
|
|
|
mkdir -p $out/bin
|
|
|
|
cp ${testDriverScript} $out/bin/nixos-test-driver
|
|
|
|
chmod u+x $out/bin/nixos-test-driver
|
|
|
|
# TODO: copy user script part into this file (append)
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
wrapProgram $out/bin/nixos-test-driver \
|
|
|
|
--prefix PATH : "${lib.makeBinPath [ qemu_pkg vde2 netpbm coreutils ]}" \
|
2021-05-08 17:52:22 +02:00
|
|
|
|
|
|
|
install -m 0644 -vD driver-exports $out/nix-support/driver-exports
|
2020-10-23 23:13:38 +02:00
|
|
|
'';
|
|
|
|
};
|
2019-09-06 09:25:22 +02:00
|
|
|
|
|
|
|
# Run an automated test suite in the given virtual network.
|
2021-05-03 13:33:41 +02:00
|
|
|
runTests = {
|
|
|
|
# the script that runs the network
|
|
|
|
driver,
|
|
|
|
# a source position in the format of builtins.unsafeGetAttrPos
|
|
|
|
# for meta.position
|
|
|
|
pos,
|
|
|
|
}:
|
2019-09-06 09:25:22 +02:00
|
|
|
stdenv.mkDerivation {
|
|
|
|
name = "vm-test-run-${driver.testName}";
|
|
|
|
|
|
|
|
requiredSystemFeatures = [ "kvm" "nixos-test" ];
|
|
|
|
|
|
|
|
buildCommand =
|
|
|
|
''
|
2020-05-07 15:56:30 +02:00
|
|
|
mkdir -p $out
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-08-31 00:42:06 +02:00
|
|
|
LOGFILE=/dev/null tests='exec(os.environ["testScript"])' ${driver}/bin/nixos-test-driver
|
2019-09-06 09:25:22 +02:00
|
|
|
'';
|
2020-12-09 12:59:39 +01:00
|
|
|
|
2021-05-08 17:24:47 +02:00
|
|
|
passthru = driver.passthru // {
|
|
|
|
inherit driver;
|
|
|
|
};
|
2021-02-09 12:02:35 +01:00
|
|
|
|
|
|
|
inherit pos;
|
2019-09-06 09:25:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
makeTest =
|
|
|
|
{ testScript
|
|
|
|
, enableOCR ? false
|
|
|
|
, name ? "unnamed"
|
2020-10-23 23:13:38 +02:00
|
|
|
# Skip linting (mainly intended for faster dev cycles)
|
2019-12-22 14:50:08 +01:00
|
|
|
, skipLint ? false
|
2020-12-09 12:59:39 +01:00
|
|
|
, passthru ? {}
|
2021-02-09 12:02:35 +01:00
|
|
|
, # For meta.position
|
|
|
|
pos ? # position used in error messages and for meta.position
|
|
|
|
(if t.meta.description or null != null
|
|
|
|
then builtins.unsafeGetAttrPos "description" t.meta
|
|
|
|
else builtins.unsafeGetAttrPos "testScript" t)
|
2019-09-06 09:25:22 +02:00
|
|
|
, ...
|
|
|
|
} @ 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; };
|
|
|
|
|
2020-07-01 05:31:32 +02:00
|
|
|
# Generate convenience wrappers for running the test driver
|
2019-09-06 09:25:22 +02:00
|
|
|
# interactively with the specified network, and for starting the
|
|
|
|
# VMs from the command line.
|
2020-10-23 23:09:18 +02:00
|
|
|
mkDriver = qemu_pkg:
|
2020-10-23 23:13:38 +02:00
|
|
|
let
|
2020-10-23 23:09:18 +02:00
|
|
|
build-vms = import ./build-vms.nix {
|
|
|
|
inherit system pkgs minimal specialArgs;
|
|
|
|
extraConfigurations = extraConfigurations ++ (pkgs.lib.optional (qemu_pkg != null)
|
|
|
|
{
|
|
|
|
virtualisation.qemu.package = qemu_pkg;
|
|
|
|
}
|
2020-11-07 13:04:50 +01:00
|
|
|
) ++ [(
|
|
|
|
{
|
|
|
|
# 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;
|
|
|
|
}
|
|
|
|
)];
|
2020-10-23 23:09:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
# 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 (
|
2020-10-23 23:13:38 +02:00
|
|
|
t.nodes or (if t ? machine then { machine = t.machine; } else { })
|
|
|
|
);
|
2020-10-23 23:09:18 +02:00
|
|
|
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
|
2020-10-23 23:13:38 +02:00
|
|
|
abort
|
|
|
|
("The name of the test '${name}' must not be longer than ${toString maxTestNameLen} " +
|
|
|
|
"it's currently ${toString testNameLen} characters long.")
|
2020-10-23 23:09:18 +02:00
|
|
|
else
|
|
|
|
"nixos-test-driver-${name}";
|
2020-10-05 15:52:27 +02:00
|
|
|
in
|
2021-04-27 15:52:15 +02:00
|
|
|
lib.warnIf skipLint "Linting is disabled" (runCommand testDriverName
|
2020-10-23 23:13:38 +02:00
|
|
|
{
|
2021-05-08 17:25:34 +02:00
|
|
|
nativeBuildInputs = [ makeWrapper ];
|
2020-10-23 23:13:38 +02:00
|
|
|
testScript = testScript';
|
|
|
|
preferLocalBuild = true;
|
|
|
|
testName = name;
|
2020-12-09 12:59:39 +01:00
|
|
|
passthru = passthru // {
|
2020-10-23 23:13:38 +02:00
|
|
|
inherit nodes;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
''
|
|
|
|
mkdir -p $out/bin
|
|
|
|
|
|
|
|
echo -n "$testScript" > $out/test-script
|
|
|
|
${lib.optionalString (!skipLint) ''
|
2021-05-08 17:52:22 +02:00
|
|
|
PYFLAKES_BUILTINS="$(
|
|
|
|
echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
|
|
|
|
< ${lib.escapeShellArg "${testDriver}/nix-support/driver-exports"}
|
|
|
|
)" ${python3Packages.pyflakes}/bin/pyflakes $out/test-script
|
2020-10-23 23:13:38 +02:00
|
|
|
''}
|
|
|
|
|
|
|
|
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();' \
|
2021-06-06 19:07:02 +02:00
|
|
|
--set VLANS '${toString vlans}'
|
2020-10-23 23:13:38 +02:00
|
|
|
''); # "
|
2019-09-06 09:25:22 +02:00
|
|
|
|
|
|
|
passMeta = drv: drv // lib.optionalAttrs (t ? meta) {
|
2020-10-23 23:13:38 +02:00
|
|
|
meta = (drv.meta or { }) // t.meta;
|
2019-09-06 09:25:22 +02:00
|
|
|
};
|
|
|
|
|
2020-10-23 23:09:18 +02:00
|
|
|
driver = mkDriver null;
|
|
|
|
driverInteractive = mkDriver pkgs.qemu;
|
|
|
|
|
2021-02-09 12:02:35 +01:00
|
|
|
test = passMeta (runTests { inherit driver pos; });
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-10-23 23:09:18 +02:00
|
|
|
nodeNames = builtins.attrNames driver.nodes;
|
2019-09-06 09:25:22 +02:00
|
|
|
invalidNodeNames = lib.filter
|
2020-10-23 23:13:38 +02:00
|
|
|
(node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null)
|
|
|
|
nodeNames;
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2021-05-08 17:52:22 +02:00
|
|
|
nodeHostNames = map (c: c.config.system.name) (lib.attrValues driver.nodes);
|
|
|
|
|
2019-09-06 09:25:22 +02:00
|
|
|
in
|
2020-10-23 23:13:38 +02:00
|
|
|
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.
|
2019-09-06 09:25:22 +02:00
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
Please stick to alphanumeric chars and underscores as separation.
|
|
|
|
''
|
|
|
|
else
|
2020-10-23 23:09:18 +02:00
|
|
|
test // {
|
2020-10-23 23:13:38 +02:00
|
|
|
inherit test driver driverInteractive;
|
nixos/tests: fix wrong inherit that passes on the nodes attrs
The hydra tarball step would fail due to the nodes attribute not being
properly inherited. Since we can't execute all the tests and release
steps locally anymore (thanks to the JSONification and faster hydra
eval) these errors will probably keep in appearing.
This is hopefully the last of those introduced by me test runner
refactoring.
Error was seen on hydra (https://hydra.nixos.org/build/129282411):
> unpacking sources
> unpacking source archive /nix/store/bp95x52h6nv3j8apxrryyj2rviw682k1-source
> source root is source
> patching sources
> autoconfPhase
> No bootstrap, bootstrap.sh, configure.in or configure.ac. Assuming this is not an GNU Autotools package.
> configuring
> release name is nixpkgs-21.03pre249116.1088f059401
> git-revision is 1088f059401c43450ed85e4a4ec3f57dc8aa992f
> building
> no Makefile, doing nothing
> running tests
> warning: you did not specify '--add-root'; the result might be removed by the garbage collector
> warning: you did not specify '--add-root'; the result might be removed by the garbage collector
> checking Nixpkgs on i686-linux
> checking Nixpkgs on x86_64-linux
> checking Nixpkgs on x86_64-darwin
> checking eval-release.nix
> trace: `mkStrict' is obsolete; use `mkOverride 0' instead.
> trace: `lib.nixpkgsVersion` is deprecated, use `lib.version` instead!
> trace: warning: lib.readPathsFromFile is deprecated, use a list instead
> trace: Warning: `showVal` is deprecated and will be removed in the next release, please use `traceSeqN`
> trace: lib.zip is deprecated, use lib.zipAttrsWith instead
> checking find-tarballs.nix
> trace: `mkStrict' is obsolete; use `mkOverride 0' instead.
> trace: `lib.nixpkgsVersion` is deprecated, use `lib.version` instead!
> trace: warning: lib.readPathsFromFile is deprecated, use a list instead
> trace: Warning: `showVal` is deprecated and will be removed in the next release, please use `traceSeqN`
> trace: lib.zip is deprecated, use lib.zipAttrsWith instead
> error: while evaluating anonymous function at /build/source/maintainers/scripts/find-tarballs.nix:6:1, called from undefined position:
> while evaluating 'operator' at /build/source/maintainers/scripts/find-tarballs.nix:27:16, called from undefined position:
> while evaluating 'immediateDependenciesOf' at /build/source/maintainers/scripts/find-tarballs.nix:39:29, called from /build/source/maintainers/scripts/find-tarballs.nix:27:44:
> while evaluating anonymous function at /build/source/lib/attrsets.nix:234:10, called from undefined position:
> while evaluating anonymous function at /build/source/maintainers/scripts/find-tarballs.nix:40:37, called from /build/source/lib/attrsets.nix:234:16:
> while evaluating 'derivationsIn' at /build/source/maintainers/scripts/find-tarballs.nix:42:19, called from /build/source/maintainers/scripts/find-tarballs.nix:40:40:
> while evaluating 'canEval' at /build/source/maintainers/scripts/find-tarballs.nix:48:13, called from /build/source/maintainers/scripts/find-tarballs.nix:43:9:
> while evaluating the attribute 'nodes' at /build/source/nixos/lib/testing-python.nix:195:23:
> attribute 'nodes' missing, at /build/source/nixos/lib/testing-python.nix:193:16
> build time elapsed: 0m0.122s 0m0.043s 17m51.526s 0m56.668s
> builder for '/nix/store/96rk3c74vrk6m3snm7n6jhis3j640pn4-nixpkgs-tarball-21.03pre249116.1088f059401.drv' failed with exit code 1
2020-10-27 00:10:31 +01:00
|
|
|
inherit (driver) nodes;
|
2020-10-23 23:13:38 +02:00
|
|
|
};
|
2019-09-06 09:25:22 +02:00
|
|
|
|
|
|
|
runInMachine =
|
|
|
|
{ drv
|
|
|
|
, machine
|
|
|
|
, preBuild ? ""
|
|
|
|
, postBuild ? ""
|
2020-10-24 21:28:38 +02:00
|
|
|
, qemu ? pkgs.qemu_test
|
2019-09-06 09:25:22 +02:00
|
|
|
, ... # ???
|
|
|
|
}:
|
|
|
|
let
|
2020-10-23 23:09:18 +02:00
|
|
|
build-vms = import ./build-vms.nix {
|
|
|
|
inherit system pkgs minimal specialArgs extraConfigurations;
|
|
|
|
};
|
|
|
|
|
|
|
|
vm = build-vms.buildVM { }
|
2020-10-23 23:13:38 +02:00
|
|
|
[
|
|
|
|
machine
|
|
|
|
{
|
|
|
|
key = "run-in-machine";
|
2019-09-06 09:25:22 +02:00
|
|
|
networking.hostName = "client";
|
|
|
|
nix.readOnlyStore = false;
|
|
|
|
virtualisation.writableStore = false;
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
buildrunner = writeText "vm-build" ''
|
|
|
|
source $1
|
|
|
|
|
|
|
|
${coreutils}/bin/mkdir -p $TMPDIR
|
|
|
|
cd $TMPDIR
|
|
|
|
|
|
|
|
exec $origBuilder $origArgs
|
|
|
|
'';
|
|
|
|
|
|
|
|
testScript = ''
|
2020-02-09 22:21:52 +01:00
|
|
|
start_all()
|
|
|
|
client.wait_for_unit("multi-user.target")
|
2019-09-06 09:25:22 +02:00
|
|
|
${preBuild}
|
2020-02-09 22:21:52 +01:00
|
|
|
client.succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2")
|
2019-09-06 09:25:22 +02:00
|
|
|
${postBuild}
|
2020-02-09 22:21:52 +01:00
|
|
|
client.succeed("sync") # flush all data before pulling the plug
|
2019-09-06 09:25:22 +02:00
|
|
|
'';
|
|
|
|
|
|
|
|
vmRunCommand = writeText "vm-run" ''
|
|
|
|
xchg=vm-state-client/xchg
|
|
|
|
${coreutils}/bin/mkdir $out
|
|
|
|
${coreutils}/bin/mkdir -p $xchg
|
|
|
|
|
|
|
|
for i in $passAsFile; do
|
|
|
|
i2=''${i}Path
|
|
|
|
_basename=$(${coreutils}/bin/basename ''${!i2})
|
|
|
|
${coreutils}/bin/cp ''${!i2} $xchg/$_basename
|
|
|
|
eval $i2=/tmp/xchg/$_basename
|
|
|
|
${coreutils}/bin/ls -la $xchg
|
|
|
|
done
|
|
|
|
|
|
|
|
unset i i2 _basename
|
|
|
|
export | ${gnugrep}/bin/grep -v '^xchg=' > $xchg/saved-env
|
|
|
|
unset xchg
|
|
|
|
|
|
|
|
export tests='${testScript}'
|
2020-10-24 22:17:32 +02:00
|
|
|
${mkTestDriver qemu}/bin/nixos-test-driver --keep-vm-state ${vm.config.system.build.vm}/bin/run-*-vm
|
2019-09-06 09:25:22 +02:00
|
|
|
''; # */
|
|
|
|
|
|
|
|
in
|
2020-10-23 23:13:38 +02:00
|
|
|
lib.overrideDerivation drv (attrs: {
|
|
|
|
requiredSystemFeatures = [ "kvm" ];
|
|
|
|
builder = "${bash}/bin/sh";
|
|
|
|
args = [ "-e" vmRunCommand ];
|
|
|
|
origArgs = attrs.args;
|
|
|
|
origBuilder = attrs.builder;
|
|
|
|
});
|
2019-09-06 09:25:22 +02:00
|
|
|
|
|
|
|
|
2020-10-23 23:13:38 +02:00
|
|
|
runInMachineWithX = { require ? [ ], ... } @ args:
|
2019-09-06 09:25:22 +02:00
|
|
|
let
|
|
|
|
client =
|
|
|
|
{ ... }:
|
|
|
|
{
|
|
|
|
inherit require;
|
2020-02-09 22:23:35 +01:00
|
|
|
imports = [
|
|
|
|
../tests/common/auto.nix
|
|
|
|
];
|
2019-09-06 09:25:22 +02:00
|
|
|
virtualisation.memorySize = 1024;
|
|
|
|
services.xserver.enable = true;
|
2020-02-09 22:23:35 +01:00
|
|
|
test-support.displayManager.auto.enable = true;
|
2019-12-10 15:10:30 +01:00
|
|
|
services.xserver.displayManager.defaultSession = "none+icewm";
|
2019-09-06 09:25:22 +02:00
|
|
|
services.xserver.windowManager.icewm.enable = true;
|
|
|
|
};
|
|
|
|
in
|
2020-10-23 23:13:38 +02:00
|
|
|
runInMachine ({
|
|
|
|
machine = client;
|
|
|
|
preBuild =
|
|
|
|
''
|
|
|
|
client.wait_for_x()
|
|
|
|
'';
|
|
|
|
} // args);
|
2019-09-06 09:25:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
simpleTest = as: (makeTest as).test;
|
|
|
|
|
|
|
|
}
|