at 18.03-beta 7.6 kB view raw
1{ system, minimal ? false, config ? {} }: 2 3with import ./build-vms.nix { inherit system minimal config; }; 4with pkgs; 5 6rec { 7 8 inherit pkgs; 9 10 11 testDriver = stdenv.mkDerivation { 12 name = "nixos-test-driver"; 13 14 buildInputs = [ makeWrapper perl ]; 15 16 unpackPhase = "true"; 17 18 preferLocalBuild = true; 19 20 installPhase = 21 '' 22 mkdir -p $out/bin 23 cp ${./test-driver/test-driver.pl} $out/bin/nixos-test-driver 24 chmod u+x $out/bin/nixos-test-driver 25 26 libDir=$out/lib/perl5/site_perl 27 mkdir -p $libDir 28 cp ${./test-driver/Machine.pm} $libDir/Machine.pm 29 cp ${./test-driver/Logger.pm} $libDir/Logger.pm 30 31 wrapProgram $out/bin/nixos-test-driver \ 32 --prefix PATH : "${lib.makeBinPath [ qemu_test vde2 netpbm coreutils ]}" \ 33 --prefix PERL5LIB : "${with perlPackages; lib.makePerlPath [ TermReadLineGnu XMLWriter IOTty FileSlurp ]}:$out/lib/perl5/site_perl" 34 ''; 35 }; 36 37 38 # Run an automated test suite in the given virtual network. 39 # `driver' is the script that runs the network. 40 runTests = driver: 41 stdenv.mkDerivation { 42 name = "vm-test-run-${driver.testName}"; 43 44 requiredSystemFeatures = [ "kvm" "nixos-test" ]; 45 46 buildInputs = [ libxslt ]; 47 48 buildCommand = 49 '' 50 mkdir -p $out/nix-support 51 52 LOGFILE=$out/log.xml tests='eval $ENV{testScript}; die $@ if $@;' ${driver}/bin/nixos-test-driver 53 54 # Generate a pretty-printed log. 55 xsltproc --output $out/log.html ${./test-driver/log2html.xsl} $out/log.xml 56 ln -s ${./test-driver/logfile.css} $out/logfile.css 57 ln -s ${./test-driver/treebits.js} $out/treebits.js 58 ln -s ${jquery}/js/jquery.min.js $out/ 59 ln -s ${jquery-ui}/js/jquery-ui.min.js $out/ 60 61 touch $out/nix-support/hydra-build-products 62 echo "report testlog $out log.html" >> $out/nix-support/hydra-build-products 63 64 for i in */xchg/coverage-data; do 65 mkdir -p $out/coverage-data 66 mv $i $out/coverage-data/$(dirname $(dirname $i)) 67 done 68 ''; # */ 69 }; 70 71 72 makeTest = 73 { testScript 74 , makeCoverageReport ? false 75 , enableOCR ? false 76 , name ? "unnamed" 77 , ... 78 } @ t: 79 80 let 81 # A standard store path to the vm monitor is built like this: 82 # /tmp/nix-build-vm-test-run-$name.drv-0/vm-state-machine/monitor 83 # The max filename length of a unix domain socket is 108 bytes. 84 # This means $name can at most be 50 bytes long. 85 maxTestNameLen = 50; 86 testNameLen = builtins.stringLength name; 87 88 testDriverName = with builtins; 89 if testNameLen > maxTestNameLen then 90 abort ("The name of the test '${name}' must not be longer than ${toString maxTestNameLen} " + 91 "it's currently ${toString testNameLen} characters long.") 92 else 93 "nixos-test-driver-${name}"; 94 95 nodes = buildVirtualNetwork ( 96 t.nodes or (if t ? machine then { machine = t.machine; } else { })); 97 98 testScript' = 99 # Call the test script with the computed nodes. 100 if lib.isFunction testScript 101 then testScript { inherit nodes; } 102 else testScript; 103 104 vlans = map (m: m.config.virtualisation.vlans) (lib.attrValues nodes); 105 106 vms = map (m: m.config.system.build.vm) (lib.attrValues nodes); 107 108 ocrProg = tesseract_4.override { enableLanguages = [ "eng" ]; }; 109 110 # Generate onvenience wrappers for running the test driver 111 # interactively with the specified network, and for starting the 112 # VMs from the command line. 113 driver = runCommand testDriverName 114 { buildInputs = [ makeWrapper]; 115 testScript = testScript'; 116 preferLocalBuild = true; 117 testName = name; 118 } 119 '' 120 mkdir -p $out/bin 121 echo "$testScript" > $out/test-script 122 ln -s ${testDriver}/bin/nixos-test-driver $out/bin/ 123 vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done)) 124 wrapProgram $out/bin/nixos-test-driver \ 125 --add-flags "''${vms[*]}" \ 126 ${lib.optionalString enableOCR 127 "--prefix PATH : '${ocrProg}/bin:${imagemagick}/bin'"} \ 128 --run "export testScript=\"\$(cat $out/test-script)\"" \ 129 --set VLANS '${toString vlans}' 130 ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms 131 wrapProgram $out/bin/nixos-run-vms \ 132 --add-flags "''${vms[*]}" \ 133 ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \ 134 --set tests 'startAll; joinAll;' \ 135 --set VLANS '${toString vlans}' \ 136 ${lib.optionalString (builtins.length vms == 1) "--set USE_SERIAL 1"} 137 ''; # " 138 139 passMeta = drv: drv // lib.optionalAttrs (t ? meta) { 140 meta = (drv.meta or {}) // t.meta; 141 }; 142 143 test = passMeta (runTests driver); 144 report = passMeta (releaseTools.gcovReport { coverageRuns = [ test ]; }); 145 146 in (if makeCoverageReport then report else test) // { 147 inherit nodes driver test; 148 }; 149 150 runInMachine = 151 { drv 152 , machine 153 , preBuild ? "" 154 , postBuild ? "" 155 , ... # ??? 156 }: 157 let 158 vm = buildVM { } 159 [ machine 160 { key = "run-in-machine"; 161 networking.hostName = "client"; 162 nix.readOnlyStore = false; 163 virtualisation.writableStore = false; 164 } 165 ]; 166 167 buildrunner = writeText "vm-build" '' 168 source $1 169 170 ${coreutils}/bin/mkdir -p $TMPDIR 171 cd $TMPDIR 172 173 exec $origBuilder $origArgs 174 ''; 175 176 testScript = '' 177 startAll; 178 $client->waitForUnit("multi-user.target"); 179 ${preBuild} 180 $client->succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2"); 181 ${postBuild} 182 $client->succeed("sync"); # flush all data before pulling the plug 183 ''; 184 185 vmRunCommand = writeText "vm-run" '' 186 xchg=vm-state-client/xchg 187 ${coreutils}/bin/mkdir $out 188 ${coreutils}/bin/mkdir -p $xchg 189 190 for i in $passAsFile; do 191 i2=''${i}Path 192 _basename=$(${coreutils}/bin/basename ''${!i2}) 193 ${coreutils}/bin/cp ''${!i2} $xchg/$_basename 194 eval $i2=/tmp/xchg/$_basename 195 ${coreutils}/bin/ls -la $xchg 196 done 197 198 unset i i2 _basename 199 export | ${gnugrep}/bin/grep -v '^xchg=' > $xchg/saved-env 200 unset xchg 201 202 export tests='${testScript}' 203 ${testDriver}/bin/nixos-test-driver ${vm.config.system.build.vm}/bin/run-*-vm 204 ''; # */ 205 206 in 207 lib.overrideDerivation drv (attrs: { 208 requiredSystemFeatures = [ "kvm" ]; 209 builder = "${bash}/bin/sh"; 210 args = ["-e" vmRunCommand]; 211 origArgs = attrs.args; 212 origBuilder = attrs.builder; 213 }); 214 215 216 runInMachineWithX = { require ? [], ... } @ args: 217 let 218 client = 219 { config, pkgs, ... }: 220 { 221 inherit require; 222 virtualisation.memorySize = 1024; 223 services.xserver.enable = true; 224 services.xserver.displayManager.slim.enable = false; 225 services.xserver.displayManager.auto.enable = true; 226 services.xserver.windowManager.default = "icewm"; 227 services.xserver.windowManager.icewm.enable = true; 228 services.xserver.desktopManager.default = "none"; 229 }; 230 in 231 runInMachine ({ 232 machine = client; 233 preBuild = 234 '' 235 $client->waitForX; 236 ''; 237 } // args); 238 239 240 simpleTest = as: (makeTest as).test; 241 242}