1{ system, minimal ? false }: 2 3with import ./build-vms.nix { inherit system minimal; }; 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 : "${qemu_kvm}/bin:${vde2}/bin:${netpbm}/bin:${coreutils}/bin" \ 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 testDriverName = "nixos-test-driver-${name}"; 82 83 nodes = buildVirtualNetwork ( 84 t.nodes or (if t ? machine then { machine = t.machine; } else { })); 85 86 testScript' = 87 # Call the test script with the computed nodes. 88 if builtins.isFunction testScript 89 then testScript { inherit nodes; } 90 else testScript; 91 92 vlans = map (m: m.config.virtualisation.vlans) (lib.attrValues nodes); 93 94 vms = map (m: m.config.system.build.vm) (lib.attrValues nodes); 95 96 ocrProg = tesseract.override { enableLanguages = [ "eng" ]; }; 97 98 # Generate onvenience wrappers for running the test driver 99 # interactively with the specified network, and for starting the 100 # VMs from the command line. 101 driver = runCommand testDriverName 102 { buildInputs = [ makeWrapper]; 103 testScript = testScript'; 104 preferLocalBuild = true; 105 testName = name; 106 } 107 '' 108 mkdir -p $out/bin 109 echo "$testScript" > $out/test-script 110 ln -s ${testDriver}/bin/nixos-test-driver $out/bin/ 111 vms="$(for i in ${toString vms}; do echo $i/bin/run-*-vm; done)" 112 wrapProgram $out/bin/nixos-test-driver \ 113 --add-flags "$vms" \ 114 ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \ 115 --run "testScript=\"\$(cat $out/test-script)\"" \ 116 --set testScript '"$testScript"' \ 117 --set VLANS '"${toString vlans}"' 118 ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms 119 wrapProgram $out/bin/nixos-run-vms \ 120 --add-flags "$vms" \ 121 ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \ 122 --set tests '"startAll; joinAll;"' \ 123 --set VLANS '"${toString vlans}"' \ 124 ${lib.optionalString (builtins.length vms == 1) "--set USE_SERIAL 1"} 125 ''; # " 126 127 passMeta = drv: drv // lib.optionalAttrs (t ? meta) { 128 meta = (drv.meta or {}) // t.meta; 129 }; 130 131 test = passMeta (runTests driver); 132 report = passMeta (releaseTools.gcovReport { coverageRuns = [ test ]; }); 133 134 in (if makeCoverageReport then report else test) // { 135 inherit nodes driver test; 136 }; 137 138 runInMachine = 139 { drv 140 , machine 141 , preBuild ? "" 142 , postBuild ? "" 143 , ... # ??? 144 }: 145 let 146 vm = buildVM { } 147 [ machine 148 { key = "run-in-machine"; 149 networking.hostName = "client"; 150 nix.readOnlyStore = false; 151 } 152 ]; 153 154 buildrunner = writeText "vm-build" '' 155 source $1 156 157 ${coreutils}/bin/mkdir -p $TMPDIR 158 cd $TMPDIR 159 160 $origBuilder $origArgs 161 162 exit $? 163 ''; 164 165 testScript = '' 166 startAll; 167 $client->waitForUnit("multi-user.target"); 168 ${preBuild} 169 $client->succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2"); 170 ${postBuild} 171 $client->succeed("sync"); # flush all data before pulling the plug 172 ''; 173 174 vmRunCommand = writeText "vm-run" '' 175 ${coreutils}/bin/mkdir $out 176 ${coreutils}/bin/mkdir -p vm-state-client/xchg 177 export > vm-state-client/xchg/saved-env 178 export tests='${testScript}' 179 ${testDriver}/bin/nixos-test-driver ${vm.config.system.build.vm}/bin/run-*-vm 180 ''; # */ 181 182 in 183 lib.overrideDerivation drv (attrs: { 184 requiredSystemFeatures = [ "kvm" ]; 185 builder = "${bash}/bin/sh"; 186 args = ["-e" vmRunCommand]; 187 origArgs = attrs.args; 188 origBuilder = attrs.builder; 189 }); 190 191 192 runInMachineWithX = { require ? [], ... } @ args: 193 let 194 client = 195 { config, pkgs, ... }: 196 { 197 inherit require; 198 virtualisation.memorySize = 1024; 199 services.xserver.enable = true; 200 services.xserver.displayManager.slim.enable = false; 201 services.xserver.displayManager.auto.enable = true; 202 services.xserver.windowManager.default = "icewm"; 203 services.xserver.windowManager.icewm.enable = true; 204 services.xserver.desktopManager.default = "none"; 205 }; 206 in 207 runInMachine ({ 208 machine = client; 209 preBuild = 210 '' 211 $client->waitForX; 212 ''; 213 } // args); 214 215 216 simpleTest = as: (makeTest as).test; 217 218}