at 23.05-pre 6.4 kB view raw
1{ config, lib, hostPkgs, ... }: 2let 3 inherit (lib) mkOption types literalMD mdDoc; 4 5 # Reifies and correctly wraps the python test driver for 6 # the respective qemu version and with or without ocr support 7 testDriver = hostPkgs.callPackage ../test-driver { 8 inherit (config) enableOCR extraPythonPackages; 9 qemu_pkg = config.qemu.package; 10 imagemagick_light = hostPkgs.imagemagick_light.override { inherit (hostPkgs) libtiff; }; 11 tesseract4 = hostPkgs.tesseract4.override { enableLanguages = [ "eng" ]; }; 12 }; 13 14 15 vlans = map (m: m.virtualisation.vlans) (lib.attrValues config.nodes); 16 vms = map (m: m.system.build.vm) (lib.attrValues config.nodes); 17 18 nodeHostNames = 19 let 20 nodesList = map (c: c.system.name) (lib.attrValues config.nodes); 21 in 22 nodesList ++ lib.optional (lib.length nodesList == 1 && !lib.elem "machine" nodesList) "machine"; 23 24 # TODO: This is an implementation error and needs fixing 25 # the testing famework cannot legitimately restrict hostnames further 26 # beyond RFC1035 27 invalidNodeNames = lib.filter 28 (node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null) 29 nodeHostNames; 30 31 uniqueVlans = lib.unique (builtins.concatLists vlans); 32 vlanNames = map (i: "vlan${toString i}: VLan;") uniqueVlans; 33 machineNames = map (name: "${name}: Machine;") nodeHostNames; 34 35 withChecks = 36 if lib.length invalidNodeNames > 0 then 37 throw '' 38 Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})! 39 All machines are referenced as python variables in the testing framework which will break the 40 script when special characters are used. 41 42 This is an IMPLEMENTATION ERROR and needs to be fixed. Meanwhile, 43 please stick to alphanumeric chars and underscores as separation. 44 '' 45 else 46 lib.warnIf config.skipLint "Linting is disabled"; 47 48 driver = 49 hostPkgs.runCommand "nixos-test-driver-${config.name}" 50 { 51 # inherit testName; TODO (roberth): need this? 52 nativeBuildInputs = [ 53 hostPkgs.makeWrapper 54 ] ++ lib.optionals (!config.skipTypeCheck) [ hostPkgs.mypy ]; 55 buildInputs = [ testDriver ]; 56 testScript = config.testScriptString; 57 preferLocalBuild = true; 58 passthru = config.passthru; 59 meta = config.meta // { 60 mainProgram = "nixos-test-driver"; 61 }; 62 } 63 '' 64 mkdir -p $out/bin 65 66 vmStartScripts=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done)) 67 68 ${lib.optionalString (!config.skipTypeCheck) '' 69 # prepend type hints so the test script can be type checked with mypy 70 cat "${../test-script-prepend.py}" >> testScriptWithTypes 71 echo "${builtins.toString machineNames}" >> testScriptWithTypes 72 echo "${builtins.toString vlanNames}" >> testScriptWithTypes 73 echo -n "$testScript" >> testScriptWithTypes 74 75 cat -n testScriptWithTypes 76 77 mypy --no-implicit-optional \ 78 --pretty \ 79 --no-color-output \ 80 testScriptWithTypes 81 ''} 82 83 echo -n "$testScript" >> $out/test-script 84 85 ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver 86 87 ${testDriver}/bin/generate-driver-symbols 88 ${lib.optionalString (!config.skipLint) '' 89 PYFLAKES_BUILTINS="$( 90 echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)}, 91 < ${lib.escapeShellArg "driver-symbols"} 92 )" ${hostPkgs.python3Packages.pyflakes}/bin/pyflakes $out/test-script 93 ''} 94 95 # set defaults through environment 96 # see: ./test-driver/test-driver.py argparse implementation 97 wrapProgram $out/bin/nixos-test-driver \ 98 --set startScripts "''${vmStartScripts[*]}" \ 99 --set testScript "$out/test-script" \ 100 --set vlans '${toString vlans}' \ 101 ${lib.escapeShellArgs (lib.concatMap (arg: ["--add-flags" arg]) config.extraDriverArgs)} 102 ''; 103 104in 105{ 106 options = { 107 108 driver = mkOption { 109 description = mdDoc "Package containing a script that runs the test."; 110 type = types.package; 111 defaultText = literalMD "set by the test framework"; 112 }; 113 114 hostPkgs = mkOption { 115 description = mdDoc "Nixpkgs attrset used outside the nodes."; 116 type = types.raw; 117 example = lib.literalExpression '' 118 import nixpkgs { inherit system config overlays; } 119 ''; 120 }; 121 122 qemu.package = mkOption { 123 description = mdDoc "Which qemu package to use for the virtualisation of [{option}`nodes`](#test-opt-nodes)."; 124 type = types.package; 125 default = hostPkgs.qemu_test; 126 defaultText = "hostPkgs.qemu_test"; 127 }; 128 129 enableOCR = mkOption { 130 description = mdDoc '' 131 Whether to enable Optical Character Recognition functionality for 132 testing graphical programs. See [Machine objects](`ssec-machine-objects`). 133 ''; 134 type = types.bool; 135 default = false; 136 }; 137 138 extraPythonPackages = mkOption { 139 description = mdDoc '' 140 Python packages to add to the test driver. 141 142 The argument is a Python package set, similar to `pkgs.pythonPackages`. 143 ''; 144 example = lib.literalExpression '' 145 p: [ p.numpy ] 146 ''; 147 type = types.functionTo (types.listOf types.package); 148 default = ps: [ ]; 149 }; 150 151 extraDriverArgs = mkOption { 152 description = mdDoc '' 153 Extra arguments to pass to the test driver. 154 155 They become part of [{option}`driver`](#test-opt-driver) via `wrapProgram`. 156 ''; 157 type = types.listOf types.str; 158 default = []; 159 }; 160 161 skipLint = mkOption { 162 type = types.bool; 163 default = false; 164 description = mdDoc '' 165 Do not run the linters. This may speed up your iteration cycle, but it is not something you should commit. 166 ''; 167 }; 168 169 skipTypeCheck = mkOption { 170 type = types.bool; 171 default = false; 172 description = mdDoc '' 173 Disable type checking. This must not be enabled for new NixOS tests. 174 175 This may speed up your iteration cycle, unless you're working on the [{option}`testScript`](#test-opt-testScript). 176 ''; 177 }; 178 }; 179 180 config = { 181 _module.args.hostPkgs = config.hostPkgs; 182 183 driver = withChecks driver; 184 185 # make available on the test runner 186 passthru.driver = config.driver; 187 }; 188}