summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/release-combined.nix4
-rw-r--r--nixos/release.nix62
-rw-r--r--nixos/tests/boot.nix8
-rw-r--r--nixos/tests/chromium.nix135
-rw-r--r--nixos/tests/networking.nix741
-rw-r--r--nixos/tests/virtualbox.nix220
6 files changed, 578 insertions, 592 deletions
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index 06890b458efa..958e587444d8 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -48,7 +48,7 @@ in rec {
         (all nixos.ova)
 
         #(all nixos.tests.containers)
-        (all nixos.tests.chromium)
+        (all nixos.tests.chromium.stable)
         (all nixos.tests.firefox)
         (all nixos.tests.firewall)
         nixos.tests.gnome3.x86_64-linux # FIXME: i686-linux
@@ -63,7 +63,7 @@ in rec {
         (all nixos.tests.installer.btrfsSimple)
         (all nixos.tests.installer.btrfsSubvols)
         (all nixos.tests.installer.btrfsSubvolDefault)
-        (all nixos.tests.bootBiosCdrom)
+        (all nixos.tests.boot.biosCdrom)
         (all nixos.tests.ipv6)
         (all nixos.tests.kde4)
         #(all nixos.tests.lightdm)
diff --git a/nixos/release.nix b/nixos/release.nix
index d8ef23199cb2..fb74766e67c6 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -13,7 +13,25 @@ let
 
   forAllSystems = genAttrs supportedSystems;
 
-  callTest = fn: args: forAllSystems (system: hydraJob (import fn ({ inherit system; } // args)));
+  importTest = fn: args: system: import fn ({
+    inherit system;
+  } // args);
+
+  callTest = fn: args: forAllSystems (system: hydraJob (importTest fn args system));
+
+  callSubTests = fn: args: let
+    discover = attrs: let
+      subTests = filterAttrs (const (hasAttr "test")) attrs;
+    in mapAttrs (const (t: hydraJob t.test)) subTests;
+
+    discoverForSystem = system: mapAttrs (_: test: {
+      ${system} = test;
+    }) (discover (importTest fn args system));
+
+  # If the test is only for a particular system, use only the specified
+  # system instead of generating attributes for all available systems.
+  in if args ? system then discover (import fn args)
+     else foldAttrs (a: b: a // b) {} (map discoverForSystem supportedSystems);
 
   pkgs = import nixpkgs { system = "x86_64-linux"; };
 
@@ -215,8 +233,9 @@ in rec {
   tests.avahi = callTest tests/avahi.nix {};
   tests.bittorrent = callTest tests/bittorrent.nix {};
   tests.blivet = callTest tests/blivet.nix {};
+  tests.boot = callSubTests tests/boot.nix {};
   tests.cadvisor = hydraJob (import tests/cadvisor.nix { system = "x86_64-linux"; });
-  tests.chromium = callTest tests/chromium.nix {};
+  tests.chromium = callSubTests tests/chromium.nix {};
   tests.cjdns = callTest tests/cjdns.nix {};
   tests.containers = callTest tests/containers.nix {};
   tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; });
@@ -232,18 +251,7 @@ in rec {
   tests.gnome3-gdm = callTest tests/gnome3-gdm.nix {};
   tests.grsecurity = callTest tests/grsecurity.nix {};
   tests.i3wm = callTest tests/i3wm.nix {};
-  tests.installer.grub1 = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).grub1.test);
-  tests.installer.lvm = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).lvm.test);
-  tests.installer.luksroot = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).luksroot.test);
-  tests.installer.separateBoot = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).separateBoot.test);
-  tests.installer.separateBootFat = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).separateBootFat.test);
-  tests.installer.simple = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simple.test);
-  tests.installer.simpleLabels = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simpleLabels.test);
-  tests.installer.simpleProvided = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simpleProvided.test);
-  tests.installer.swraid = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).swraid.test);
-  tests.installer.btrfsSimple = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSimple.test);
-  tests.installer.btrfsSubvols = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSubvols.test);
-  tests.installer.btrfsSubvolDefault = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSubvolDefault.test);
+  tests.installer = callSubTests tests/installer.nix {};
   tests.influxdb = callTest tests/influxdb.nix {};
   tests.ipv6 = callTest tests/ipv6.nix {};
   tests.jenkins = callTest tests/jenkins.nix {};
@@ -262,24 +270,8 @@ in rec {
   tests.mysqlReplication = callTest tests/mysql-replication.nix {};
   tests.nat.firewall = callTest tests/nat.nix { withFirewall = true; };
   tests.nat.standalone = callTest tests/nat.nix { withFirewall = false; };
-  tests.networking.networkd.loopback = callTest tests/networking.nix { networkd = true; test = "loopback"; };
-  tests.networking.networkd.static = callTest tests/networking.nix { networkd = true; test = "static"; };
-  tests.networking.networkd.dhcpSimple = callTest tests/networking.nix { networkd = true; test = "dhcpSimple"; };
-  tests.networking.networkd.dhcpOneIf = callTest tests/networking.nix { networkd = true; test = "dhcpOneIf"; };
-  tests.networking.networkd.bond = callTest tests/networking.nix { networkd = true; test = "bond"; };
-  tests.networking.networkd.bridge = callTest tests/networking.nix { networkd = true; test = "bridge"; };
-  tests.networking.networkd.macvlan = callTest tests/networking.nix { networkd = true; test = "macvlan"; };
-  tests.networking.networkd.sit = callTest tests/networking.nix { networkd = true; test = "sit"; };
-  tests.networking.networkd.vlan = callTest tests/networking.nix { networkd = true; test = "vlan"; };
-  tests.networking.scripted.loopback = callTest tests/networking.nix { networkd = false; test = "loopback"; };
-  tests.networking.scripted.static = callTest tests/networking.nix { networkd = false; test = "static"; };
-  tests.networking.scripted.dhcpSimple = callTest tests/networking.nix { networkd = false; test = "dhcpSimple"; };
-  tests.networking.scripted.dhcpOneIf = callTest tests/networking.nix { networkd = false; test = "dhcpOneIf"; };
-  tests.networking.scripted.bond = callTest tests/networking.nix { networkd = false; test = "bond"; };
-  tests.networking.scripted.bridge = callTest tests/networking.nix { networkd = false; test = "bridge"; };
-  tests.networking.scripted.macvlan = callTest tests/networking.nix { networkd = false; test = "macvlan"; };
-  tests.networking.scripted.sit = callTest tests/networking.nix { networkd = false; test = "sit"; };
-  tests.networking.scripted.vlan = callTest tests/networking.nix { networkd = false; test = "vlan"; };
+  tests.networking.networkd = callSubTests tests/networking.nix { networkd = true; };
+  tests.networking.scripted = callSubTests tests/networking.nix { networkd = false; };
   # TODO: put in networking.nix after the test becomes more complete
   tests.networkingProxy = callTest tests/networking-proxy.nix {};
   tests.nfs3 = callTest tests/nfs.nix { version = 3; };
@@ -299,12 +291,8 @@ in rec {
   tests.simple = callTest tests/simple.nix {};
   tests.tomcat = callTest tests/tomcat.nix {};
   tests.udisks2 = callTest tests/udisks2.nix {};
-  tests.virtualbox = hydraJob (import tests/virtualbox.nix { system = "x86_64-linux"; });
+  tests.virtualbox = callSubTests tests/virtualbox.nix { system = "x86_64-linux"; };
   tests.xfce = callTest tests/xfce.nix {};
-  tests.bootBiosCdrom = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootBiosCdrom);
-  tests.bootBiosUsb = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootBiosUsb);
-  tests.bootUefiCdrom = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootUefiCdrom);
-  tests.bootUefiUsb = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootUefiUsb);
 
 
   /* Build a bunch of typical closures so that Hydra can keep track of
diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix
index 6a1d330155e1..905d16458825 100644
--- a/nixos/tests/boot.nix
+++ b/nixos/tests/boot.nix
@@ -30,17 +30,17 @@ let
         '';
     };
 in {
-    bootBiosCdrom = makeBootTest "bios-cdrom" ''
+    biosCdrom = makeBootTest "bios-cdrom" ''
         cdrom => glob("${iso}/iso/*.iso")
       '';
-    bootBiosUsb = makeBootTest "bios-usb" ''
+    biosUsb = makeBootTest "bios-usb" ''
         usb => glob("${iso}/iso/*.iso")
       '';
-    bootUefiCdrom = makeBootTest "uefi-cdrom" ''
+    uefiCdrom = makeBootTest "uefi-cdrom" ''
         cdrom => glob("${iso}/iso/*.iso"),
         bios => '${pkgs.OVMF}/FV/OVMF.fd'
       '';
-    bootUefiUsb = makeBootTest "uefi-usb" ''
+    uefiUsb = makeBootTest "uefi-usb" ''
         usb => glob("${iso}/iso/*.iso"),
         bios => '${pkgs.OVMF}/FV/OVMF.fd'
       '';
diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix
index 6c61087760dd..974af6888b69 100644
--- a/nixos/tests/chromium.nix
+++ b/nixos/tests/chromium.nix
@@ -1,13 +1,10 @@
-import ./make-test.nix (
-{ pkgs
-, channelMap ? {
-    stable = pkgs.chromium;
-    #beta   = pkgs.chromiumBeta;
-    #dev    = pkgs.chromiumDev;
-  }
-, ...
-}: rec {
-  name = "chromium";
+{ system ? builtins.currentSystem }:
+
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
+
+mapAttrs (channel: chromiumPkg: makeTest rec {
+  name = "chromium-${channel}";
   meta = with pkgs.stdenv.lib.maintainers; {
     maintainers = [ aszlig ];
   };
@@ -16,6 +13,7 @@ import ./make-test.nix (
 
   machine.imports = [ ./common/x11.nix ];
   machine.virtualisation.memorySize = 2047;
+  machine.environment.systemPackages = [ chromiumPkg ];
 
   startupHTML = pkgs.writeText "chromium-startup.html" ''
     <!DOCTYPE html>
@@ -105,74 +103,65 @@ import ./make-test.nix (
       closeWin;
     }
 
-    sub chromiumTest {
-      my ($channel, $pkg, $code) = @_;
-      $machine->waitForX;
-
-      my $url = "file://${startupHTML}";
-      my $args = "--user-data-dir=/tmp/chromium-$channel";
-      $machine->execute(
-        "ulimit -c unlimited; ".
-        "$pkg/bin/chromium $args \"$url\" & disown"
-      );
-      $machine->waitForText(qr/Type to search or enter a URL to navigate/);
-      $machine->waitUntilSucceeds("${xdo "check-startup" ''
-        search --sync --onlyvisible --name "startup done"
-        # close first start help popup
-        key -delay 1000 Escape
+    $machine->waitForX;
+
+    my $url = "file://${startupHTML}";
+    my $args = "--user-data-dir=/tmp/chromium-${channel}";
+    $machine->execute(
+      "ulimit -c unlimited; ".
+      "chromium $args \"$url\" & disown"
+    );
+    $machine->waitForText(qr/Type to search or enter a URL to navigate/);
+    $machine->waitUntilSucceeds("${xdo "check-startup" ''
+      search --sync --onlyvisible --name "startup done"
+      # close first start help popup
+      key -delay 1000 Escape
+      windowfocus --sync
+      windowactivate --sync
+    ''}");
+
+    createAndWaitForNewWin;
+    $machine->screenshot("empty_windows");
+    closeWin;
+
+    $machine->screenshot("startup_done");
+
+    testNewWin "check sandbox", sub {
+      $machine->succeed("${xdo "type-url" ''
+        search --sync --onlyvisible --name "new tab"
         windowfocus --sync
-        windowactivate --sync
+        type --delay 1000 "chrome://sandbox"
       ''}");
 
-      createAndWaitForNewWin;
-      $machine->screenshot($channel."_emptywin");
-      closeWin;
-
-      $machine->screenshot($channel."_startup_done");
-
-      subtest("Chromium $channel", $code);
-
-      $machine->shutdown;
-    }
-
-    for (${let
-      mkArray = name: pkg: "[\"${name}\", \"${pkg}\"]";
-      chanArrays = pkgs.lib.mapAttrsToList mkArray channelMap;
-    in pkgs.lib.concatStringsSep ", " chanArrays}) {
-      my ($channel, $pkg) = @$_;
-      chromiumTest $channel, $pkg, sub {
-        testNewWin "check sandbox", sub {
-          $machine->succeed("${xdo "type-url" ''
-            search --sync --onlyvisible --name "new tab"
-            windowfocus --sync
-            type --delay 1000 "chrome://sandbox"
-          ''}");
+      $machine->succeed("${xdo "submit-url" ''
+        search --sync --onlyvisible --name "new tab"
+        windowfocus --sync
+        key --delay 1000 Return
+      ''}");
 
-          $machine->succeed("${xdo "submit-url" ''
-            search --sync --onlyvisible --name "new tab"
-            windowfocus --sync
-            key --delay 1000 Return
-          ''}");
+      $machine->screenshot("sandbox_info");
 
-          $machine->screenshot($channel."_sandbox");
+      $machine->succeed("${xdo "submit-url" ''
+        search --sync --onlyvisible --name "sandbox status"
+        windowfocus --sync
+      ''}");
+      $machine->succeed("${xdo "submit-url" ''
+        key --delay 1000 Ctrl+a Ctrl+c
+      ''}");
 
-          $machine->succeed("${xdo "submit-url" ''
-            search --sync --onlyvisible --name "sandbox status"
-            windowfocus --sync
-          ''}");
-          $machine->succeed("${xdo "submit-url" ''
-            key --delay 1000 Ctrl+a Ctrl+c
-          ''}");
+      my $clipboard = $machine->succeed("${pkgs.xclip}/bin/xclip -o");
+      die "sandbox not working properly: $clipboard"
+      unless $clipboard =~ /namespace sandbox.*yes/mi
+          && $clipboard =~ /pid namespaces.*yes/mi
+          && $clipboard =~ /network namespaces.*yes/mi
+          && $clipboard =~ /seccomp.*sandbox.*yes/mi
+          && $clipboard =~ /you are adequately sandboxed/mi;
+    };
 
-          my $clipboard = $machine->succeed("${pkgs.xclip}/bin/xclip -o");
-          die "sandbox not working properly: $clipboard"
-          unless $clipboard =~ /namespace sandbox.*yes/mi
-              && $clipboard =~ /pid namespaces.*yes/mi
-              && $clipboard =~ /network namespaces.*yes/mi
-              && $clipboard =~ /seccomp.*sandbox.*yes/mi
-              && $clipboard =~ /you are adequately sandboxed/mi;
-        };
-      };
-    }
+    $machine->shutdown;
   '';
-})
+}) {
+  stable = pkgs.chromium;
+  beta   = pkgs.chromiumBeta;
+  dev    = pkgs.chromiumDev;
+}
diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix
index 813d7c2bf516..d5a0a9b798f5 100644
--- a/nixos/tests/networking.nix
+++ b/nixos/tests/networking.nix
@@ -1,406 +1,411 @@
-import ./make-test.nix ({ pkgs, networkd, test, ... }:
-  let
-    router = { config, pkgs, ... }:
-      with pkgs.lib;
-      let
-        vlanIfs = range 1 (length config.virtualisation.vlans);
-      in {
-        virtualisation.vlans = [ 1 2 3 ];
+{ system ? builtins.currentSystem, networkd }:
+
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
+
+let
+  router = { config, pkgs, ... }:
+    with pkgs.lib;
+    let
+      vlanIfs = range 1 (length config.virtualisation.vlans);
+    in {
+      virtualisation.vlans = [ 1 2 3 ];
+      networking = {
+        useDHCP = false;
+        useNetworkd = networkd;
+        firewall.allowPing = true;
+        interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n:
+          nameValuePair "eth${toString n}" {
+            ipAddress = "192.168.${toString n}.1";
+            prefixLength = 24;
+          })));
+      };
+      services.dhcpd = {
+        enable = true;
+        interfaces = map (n: "eth${toString n}") vlanIfs;
+        extraConfig = ''
+          option subnet-mask 255.255.255.0;
+        '' + flip concatMapStrings vlanIfs (n: ''
+          subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
+            option broadcast-address 192.168.${toString n}.255;
+            option routers 192.168.${toString n}.1;
+            range 192.168.${toString n}.2 192.168.${toString n}.254;
+          }
+        '');
+      };
+    };
+
+  testCases = {
+    loopback = {
+      name = "Loopback";
+      machine.networking.useNetworkd = networkd;
+      testScript = ''
+        startAll;
+        $machine->waitForUnit("network-interfaces.target");
+        $machine->waitForUnit("network.target");
+        $machine->succeed("ip addr show lo | grep -q 'inet 127.0.0.1/8 '");
+        $machine->succeed("ip addr show lo | grep -q 'inet6 ::1/128 '");
+      '';
+    };
+    static = {
+      name = "Static";
+      nodes.router = router;
+      nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 2 ];
         networking = {
-          useDHCP = false;
           useNetworkd = networkd;
           firewall.allowPing = true;
-          interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n:
-            nameValuePair "eth${toString n}" {
-              ipAddress = "192.168.${toString n}.1";
-              prefixLength = 24;
-            })));
-        };
-        services.dhcpd = {
-          enable = true;
-          interfaces = map (n: "eth${toString n}") vlanIfs;
-          extraConfig = ''
-            option subnet-mask 255.255.255.0;
-          '' + flip concatMapStrings vlanIfs (n: ''
-            subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
-              option broadcast-address 192.168.${toString n}.255;
-              option routers 192.168.${toString n}.1;
-              range 192.168.${toString n}.2 192.168.${toString n}.254;
-            }
-          '');
+          useDHCP = false;
+          defaultGateway = "192.168.1.1";
+          interfaces.eth1.ip4 = mkOverride 0 [
+            { address = "192.168.1.2"; prefixLength = 24; }
+            { address = "192.168.1.3"; prefixLength = 32; }
+            { address = "192.168.1.10"; prefixLength = 32; }
+          ];
+          interfaces.eth2.ip4 = mkOverride 0 [
+            { address = "192.168.2.2"; prefixLength = 24; }
+          ];
         };
       };
-    testCases = {
-      loopback = {
-        name = "Loopback";
-        machine.networking.useNetworkd = networkd;
-        testScript = ''
+      testScript = { nodes, ... }:
+        ''
           startAll;
-          $machine->waitForUnit("network-interfaces.target");
-          $machine->waitForUnit("network.target");
-          $machine->succeed("ip addr show lo | grep -q 'inet 127.0.0.1/8 '");
-          $machine->succeed("ip addr show lo | grep -q 'inet6 ::1/128 '");
+
+          $client->waitForUnit("network-interfaces.target");
+          $client->waitForUnit("network.target");
+          $router->waitForUnit("network-interfaces.target");
+          $router->waitForUnit("network.target");
+
+          # Make sure dhcpcd is not started
+          $client->fail("systemctl status dhcpcd.service");
+
+          # Test vlan 1
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.10");
+
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.10");
+
+          # Test vlan 2
+          $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
+          $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
+
+          $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
+          $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
+
+          # Test default gateway
+          $router->waitUntilSucceeds("ping -c 1 192.168.3.1");
+          $client->waitUntilSucceeds("ping -c 1 192.168.3.1");
         '';
-      };
-      static = {
-        name = "Static";
-        nodes.router = router;
-        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ 1 2 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = false;
-            defaultGateway = "192.168.1.1";
-            interfaces.eth1.ip4 = mkOverride 0 [
-              { address = "192.168.1.2"; prefixLength = 24; }
-              { address = "192.168.1.3"; prefixLength = 32; }
-              { address = "192.168.1.10"; prefixLength = 32; }
-            ];
-            interfaces.eth2.ip4 = mkOverride 0 [
-              { address = "192.168.2.2"; prefixLength = 24; }
-            ];
-          };
+    };
+    dhcpSimple = {
+      name = "SimpleDHCP";
+      nodes.router = router;
+      nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 2 ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          useDHCP = true;
+          interfaces.eth1.ip4 = mkOverride 0 [ ];
+          interfaces.eth2.ip4 = mkOverride 0 [ ];
         };
-        testScript = { nodes, ... }:
-          ''
-            startAll;
-
-            $client->waitForUnit("network-interfaces.target");
-            $client->waitForUnit("network.target");
-            $router->waitForUnit("network-interfaces.target");
-            $router->waitForUnit("network.target");
-
-            # Make sure dhcpcd is not started
-            $client->fail("systemctl status dhcpcd.service");
-
-            # Test vlan 1
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.10");
-
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.10");
-
-            # Test vlan 2
-            $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
-            $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
-
-            $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
-            $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
-
-            # Test default gateway
-            $router->waitUntilSucceeds("ping -c 1 192.168.3.1");
-            $client->waitUntilSucceeds("ping -c 1 192.168.3.1");
-          '';
       };
-      dhcpSimple = {
-        name = "SimpleDHCP";
-        nodes.router = router;
-        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ 1 2 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = true;
-            interfaces.eth1.ip4 = mkOverride 0 [ ];
-            interfaces.eth2.ip4 = mkOverride 0 [ ];
-          };
-        };
-        testScript = { nodes, ... }:
-          ''
-            startAll;
+      testScript = { nodes, ... }:
+        ''
+          startAll;
 
-            $client->waitForUnit("network-interfaces.target");
-            $client->waitForUnit("network.target");
-            $router->waitForUnit("network-interfaces.target");
-            $router->waitForUnit("network.target");
+          $client->waitForUnit("network-interfaces.target");
+          $client->waitForUnit("network.target");
+          $router->waitForUnit("network-interfaces.target");
+          $router->waitForUnit("network.target");
 
-            # Wait until we have an ip address on each interface
-            $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
-            $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'");
+          # Wait until we have an ip address on each interface
+          $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
+          $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'");
 
-            # Test vlan 1
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          # Test vlan 1
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
 
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
 
-            # Test vlan 2
-            $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
-            $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
+          # Test vlan 2
+          $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
+          $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
 
-            $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
-            $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
-          '';
-      };
-      dhcpOneIf = {
-        name = "OneInterfaceDHCP";
-        nodes.router = router;
-        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ 1 2 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = false;
-            interfaces.eth1 = {
-              ip4 = mkOverride 0 [ ];
-              useDHCP = true;
-            };
-            interfaces.eth2.ip4 = mkOverride 0 [ ];
+          $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
+          $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
+        '';
+    };
+    dhcpOneIf = {
+      name = "OneInterfaceDHCP";
+      nodes.router = router;
+      nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 2 ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          useDHCP = false;
+          interfaces.eth1 = {
+            ip4 = mkOverride 0 [ ];
+            useDHCP = true;
           };
+          interfaces.eth2.ip4 = mkOverride 0 [ ];
         };
-        testScript = { nodes, ... }:
-          ''
-            startAll;
+      };
+      testScript = { nodes, ... }:
+        ''
+          startAll;
 
-            # Wait for networking to come up
-            $client->waitForUnit("network-interfaces.target");
-            $client->waitForUnit("network.target");
-            $router->waitForUnit("network-interfaces.target");
-            $router->waitForUnit("network.target");
+          # Wait for networking to come up
+          $client->waitForUnit("network-interfaces.target");
+          $client->waitForUnit("network.target");
+          $router->waitForUnit("network-interfaces.target");
+          $router->waitForUnit("network.target");
 
-            # Wait until we have an ip address on each interface
-            $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
+          # Wait until we have an ip address on each interface
+          $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
 
-            # Test vlan 1
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          # Test vlan 1
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
 
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
 
-            # Test vlan 2
-            $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
-            $client->fail("ping -c 1 192.168.2.2");
+          # Test vlan 2
+          $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
+          $client->fail("ping -c 1 192.168.2.2");
 
-            $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
-            $router->fail("ping -c 1 192.168.2.2");
-          '';
-      };
-      bond = let
-        node = address: { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ 1 2 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = false;
-            bonds.bond = {
-              mode = "balance-rr";
-              interfaces = [ "eth1" "eth2" ];
-            };
-            interfaces.eth1.ip4 = mkOverride 0 [ ];
-            interfaces.eth2.ip4 = mkOverride 0 [ ];
-            interfaces.bond.ip4 = mkOverride 0
-              [ { inherit address; prefixLength = 30; } ];
+          $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
+          $router->fail("ping -c 1 192.168.2.2");
+        '';
+    };
+    bond = let
+      node = address: { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 2 ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          useDHCP = false;
+          bonds.bond = {
+            mode = "balance-rr";
+            interfaces = [ "eth1" "eth2" ];
           };
+          interfaces.eth1.ip4 = mkOverride 0 [ ];
+          interfaces.eth2.ip4 = mkOverride 0 [ ];
+          interfaces.bond.ip4 = mkOverride 0
+            [ { inherit address; prefixLength = 30; } ];
         };
-      in {
-        name = "Bond";
-        nodes.client1 = node "192.168.1.1";
-        nodes.client2 = node "192.168.1.2";
-        testScript = { nodes, ... }:
-          ''
-            startAll;
-
-            # Wait for networking to come up
-            $client1->waitForUnit("network-interfaces.target");
-            $client1->waitForUnit("network.target");
-            $client2->waitForUnit("network-interfaces.target");
-            $client2->waitForUnit("network.target");
-
-            # Test bonding
-            $client1->waitUntilSucceeds("ping -c 2 192.168.1.1");
-            $client1->waitUntilSucceeds("ping -c 2 192.168.1.2");
-
-            $client2->waitUntilSucceeds("ping -c 2 192.168.1.1");
-            $client2->waitUntilSucceeds("ping -c 2 192.168.1.2");
-          '';
       };
-      bridge = let
-        node = { address, vlan }: { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ vlan ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = false;
-            interfaces.eth1.ip4 = mkOverride 0
-              [ { inherit address; prefixLength = 24; } ];
-          };
+    in {
+      name = "Bond";
+      nodes.client1 = node "192.168.1.1";
+      nodes.client2 = node "192.168.1.2";
+      testScript = { nodes, ... }:
+        ''
+          startAll;
+
+          # Wait for networking to come up
+          $client1->waitForUnit("network-interfaces.target");
+          $client1->waitForUnit("network.target");
+          $client2->waitForUnit("network-interfaces.target");
+          $client2->waitForUnit("network.target");
+
+          # Test bonding
+          $client1->waitUntilSucceeds("ping -c 2 192.168.1.1");
+          $client1->waitUntilSucceeds("ping -c 2 192.168.1.2");
+
+          $client2->waitUntilSucceeds("ping -c 2 192.168.1.1");
+          $client2->waitUntilSucceeds("ping -c 2 192.168.1.2");
+        '';
+    };
+    bridge = let
+      node = { address, vlan }: { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ vlan ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          useDHCP = false;
+          interfaces.eth1.ip4 = mkOverride 0
+            [ { inherit address; prefixLength = 24; } ];
         };
-      in {
-        name = "Bridge";
-        nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
-        nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
-        nodes.router = { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ 1 2 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = false;
-            bridges.bridge.interfaces = [ "eth1" "eth2" ];
-            interfaces.eth1.ip4 = mkOverride 0 [ ];
-            interfaces.eth2.ip4 = mkOverride 0 [ ];
-            interfaces.bridge.ip4 = mkOverride 0
-              [ { address = "192.168.1.1"; prefixLength = 24; } ];
-          };
+      };
+    in {
+      name = "Bridge";
+      nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
+      nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
+      nodes.router = { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 2 ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          useDHCP = false;
+          bridges.bridge.interfaces = [ "eth1" "eth2" ];
+          interfaces.eth1.ip4 = mkOverride 0 [ ];
+          interfaces.eth2.ip4 = mkOverride 0 [ ];
+          interfaces.bridge.ip4 = mkOverride 0
+            [ { address = "192.168.1.1"; prefixLength = 24; } ];
         };
-        testScript = { nodes, ... }:
-          ''
-            startAll;
-
-            # Wait for networking to come up
-            $client1->waitForUnit("network-interfaces.target");
-            $client1->waitForUnit("network.target");
-            $client2->waitForUnit("network-interfaces.target");
-            $client2->waitForUnit("network.target");
-            $router->waitForUnit("network-interfaces.target");
-            $router->waitForUnit("network.target");
-
-            # Test bridging
-            $client1->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $client1->waitUntilSucceeds("ping -c 1 192.168.1.2");
-            $client1->waitUntilSucceeds("ping -c 1 192.168.1.3");
-
-            $client2->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $client2->waitUntilSucceeds("ping -c 1 192.168.1.2");
-            $client2->waitUntilSucceeds("ping -c 1 192.168.1.3");
-
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
-          '';
       };
-      macvlan = {
-        name = "MACVLAN";
-        nodes.router = router;
-        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ 1 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = true;
-            macvlans.macvlan.interface = "eth1";
-            interfaces.eth1.ip4 = mkOverride 0 [ ];
-          };
+      testScript = { nodes, ... }:
+        ''
+          startAll;
+
+          # Wait for networking to come up
+          $client1->waitForUnit("network-interfaces.target");
+          $client1->waitForUnit("network.target");
+          $client2->waitForUnit("network-interfaces.target");
+          $client2->waitForUnit("network.target");
+          $router->waitForUnit("network-interfaces.target");
+          $router->waitForUnit("network.target");
+
+          # Test bridging
+          $client1->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $client1->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $client1->waitUntilSucceeds("ping -c 1 192.168.1.3");
+
+          $client2->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $client2->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $client2->waitUntilSucceeds("ping -c 1 192.168.1.3");
+
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
+        '';
+    };
+    macvlan = {
+      name = "MACVLAN";
+      nodes.router = router;
+      nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          useDHCP = true;
+          macvlans.macvlan.interface = "eth1";
+          interfaces.eth1.ip4 = mkOverride 0 [ ];
         };
-        testScript = { nodes, ... }:
-          ''
-            startAll;
-
-            # Wait for networking to come up
-            $client->waitForUnit("network-interfaces.target");
-            $client->waitForUnit("network.target");
-            $router->waitForUnit("network-interfaces.target");
-            $router->waitForUnit("network.target");
-
-            # Wait until we have an ip address on each interface
-            $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
-            $client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'");
-
-            # Print diagnosting information
-            $router->succeed("ip addr >&2");
-            $client->succeed("ip addr >&2");
-
-            # Test macvlan creates routable ips
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
-            $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
-
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
-            $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
-          '';
       };
-      sit = let
-        node = { address4, remote, address6 }: { config, pkgs, ... }: with pkgs.lib; {
-          virtualisation.vlans = [ 1 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.enable = false;
-            useDHCP = false;
-            sits.sit = {
-              inherit remote;
-              local = address4;
-              dev = "eth1";
-            };
-            interfaces.eth1.ip4 = mkOverride 0
-              [ { address = address4; prefixLength = 24; } ];
-            interfaces.sit.ip6 = mkOverride 0
-              [ { address = address6; prefixLength = 64; } ];
+      testScript = { nodes, ... }:
+        ''
+          startAll;
+
+          # Wait for networking to come up
+          $client->waitForUnit("network-interfaces.target");
+          $client->waitForUnit("network.target");
+          $router->waitForUnit("network-interfaces.target");
+          $router->waitForUnit("network.target");
+
+          # Wait until we have an ip address on each interface
+          $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
+          $client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'");
+
+          # Print diagnosting information
+          $router->succeed("ip addr >&2");
+          $client->succeed("ip addr >&2");
+
+          # Test macvlan creates routable ips
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
+
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+          $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
+        '';
+    };
+    sit = let
+      node = { address4, remote, address6 }: { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.enable = false;
+          useDHCP = false;
+          sits.sit = {
+            inherit remote;
+            local = address4;
+            dev = "eth1";
           };
+          interfaces.eth1.ip4 = mkOverride 0
+            [ { address = address4; prefixLength = 24; } ];
+          interfaces.sit.ip6 = mkOverride 0
+            [ { address = address6; prefixLength = 64; } ];
         };
-      in {
-        name = "Sit";
-        nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
-        nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
-        testScript = { nodes, ... }:
-          ''
-            startAll;
-
-            # Wait for networking to be configured
-            $client1->waitForUnit("network-interfaces.target");
-            $client1->waitForUnit("network.target");
-            $client2->waitForUnit("network-interfaces.target");
-            $client2->waitForUnit("network.target");
-
-            # Print diagnostic information
-            $client1->succeed("ip addr >&2");
-            $client2->succeed("ip addr >&2");
-
-            # Test ipv6
-            $client1->waitUntilSucceeds("ping6 -c 1 fc00::1");
-            $client1->waitUntilSucceeds("ping6 -c 1 fc00::2");
-
-            $client2->waitUntilSucceeds("ping6 -c 1 fc00::1");
-            $client2->waitUntilSucceeds("ping6 -c 1 fc00::2");
-          '';
       };
-      vlan = let
-        node = address: { config, pkgs, ... }: with pkgs.lib; {
-          #virtualisation.vlans = [ 1 ];
-          networking = {
-            useNetworkd = networkd;
-            firewall.allowPing = true;
-            useDHCP = false;
-            vlans.vlan = {
-              id = 1;
-              interface = "eth0";
-            };
-            interfaces.eth0.ip4 = mkOverride 0 [ ];
-            interfaces.eth1.ip4 = mkOverride 0 [ ];
-            interfaces.vlan.ip4 = mkOverride 0
-              [ { inherit address; prefixLength = 24; } ];
+    in {
+      name = "Sit";
+      nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
+      nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
+      testScript = { nodes, ... }:
+        ''
+          startAll;
+
+          # Wait for networking to be configured
+          $client1->waitForUnit("network-interfaces.target");
+          $client1->waitForUnit("network.target");
+          $client2->waitForUnit("network-interfaces.target");
+          $client2->waitForUnit("network.target");
+
+          # Print diagnostic information
+          $client1->succeed("ip addr >&2");
+          $client2->succeed("ip addr >&2");
+
+          # Test ipv6
+          $client1->waitUntilSucceeds("ping6 -c 1 fc00::1");
+          $client1->waitUntilSucceeds("ping6 -c 1 fc00::2");
+
+          $client2->waitUntilSucceeds("ping6 -c 1 fc00::1");
+          $client2->waitUntilSucceeds("ping6 -c 1 fc00::2");
+        '';
+    };
+    vlan = let
+      node = address: { config, pkgs, ... }: with pkgs.lib; {
+        #virtualisation.vlans = [ 1 ];
+        networking = {
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          useDHCP = false;
+          vlans.vlan = {
+            id = 1;
+            interface = "eth0";
           };
+          interfaces.eth0.ip4 = mkOverride 0 [ ];
+          interfaces.eth1.ip4 = mkOverride 0 [ ];
+          interfaces.vlan.ip4 = mkOverride 0
+            [ { inherit address; prefixLength = 24; } ];
         };
-      in {
-        name = "vlan";
-        nodes.client1 = node "192.168.1.1";
-        nodes.client2 = node "192.168.1.2";
-        testScript = { nodes, ... }:
-          ''
-            startAll;
-
-            # Wait for networking to be configured
-            $client1->waitForUnit("network-interfaces.target");
-            $client1->waitForUnit("network.target");
-            $client2->waitForUnit("network-interfaces.target");
-            $client2->waitForUnit("network.target");
-
-            # Test vlan is setup
-            $client1->succeed("ip addr show dev vlan >&2");
-            $client2->succeed("ip addr show dev vlan >&2");
-          '';
       };
+    in {
+      name = "vlan";
+      nodes.client1 = node "192.168.1.1";
+      nodes.client2 = node "192.168.1.2";
+      testScript = { nodes, ... }:
+        ''
+          startAll;
+
+          # Wait for networking to be configured
+          $client1->waitForUnit("network-interfaces.target");
+          $client1->waitForUnit("network.target");
+          $client2->waitForUnit("network-interfaces.target");
+          $client2->waitForUnit("network.target");
+
+          # Test vlan is setup
+          $client1->succeed("ip addr show dev vlan >&2");
+          $client2->succeed("ip addr show dev vlan >&2");
+        '';
     };
-    case = testCases.${test};
-  in case // {
-    name = "${case.name}-Networking-${if networkd then "Networkd" else "Scripted"}";
-    meta = with pkgs.stdenv.lib.maintainers; {
-      maintainers = [ wkennington ];
-    };
-  })
+  };
+
+in mapAttrs (const (attrs: makeTest (attrs // {
+  name = "${attrs.name}-Networking-${if networkd then "Networkd" else "Scripted"}";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ wkennington ];
+  };
+}))) testCases
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index 01fcd15fd8bb..da4c0bddc348 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -1,7 +1,9 @@
-{ debug ? false, ... } @ args:
+{ system ? builtins.currentSystem, debug ? false }:
 
-import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
 
+let
   testVMConfig = vmName: attrs: { config, pkgs, ... }: let
     guestAdditions = pkgs.linuxPackages.virtualboxGuestAdditions;
 
@@ -314,138 +316,140 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
     test2.vmScript = dhcpScript;
   };
 
-in {
-  name = "virtualbox";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ aszlig wkennington ];
-  };
+  mkVBoxTest = name: testScript: makeTest {
+    name = "virtualbox-${name}";
+
+    machine = { lib, config, ... }: {
+      imports = let
+        mkVMConf = name: val: val.machine // { key = "${name}-config"; };
+        vmConfigs = mapAttrsToList mkVMConf vboxVMs;
+      in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs;
+      virtualisation.memorySize = 2048;
+      virtualisation.virtualbox.host.enable = true;
+      users.extraUsers.alice.extraGroups = let
+        inherit (config.virtualisation.virtualbox.host) enableHardening;
+      in lib.mkIf enableHardening (lib.singleton "vboxusers");
+    };
 
-  machine = { pkgs, lib, config, ... }: {
-    imports = let
-      mkVMConf = name: val: val.machine // { key = "${name}-config"; };
-      vmConfigs = mapAttrsToList mkVMConf vboxVMs;
-    in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs;
-    virtualisation.memorySize = 2048;
-    virtualisation.virtualbox.host.enable = true;
-    users.extraUsers.alice.extraGroups = let
-      inherit (config.virtualisation.virtualbox.host) enableHardening;
-    in lib.mkIf enableHardening (lib.singleton "vboxusers");
-  };
+    testScript = ''
+      sub ru ($) {
+        my $esc = $_[0] =~ s/'/'\\${"'"}'/gr;
+        return "su - alice -c '$esc'";
+      }
 
-  testScript = ''
-    sub ru ($) {
-      my $esc = $_[0] =~ s/'/'\\${"'"}'/gr;
-      return "su - alice -c '$esc'";
-    }
+      sub vbm {
+        $machine->succeed(ru("VBoxManage ".$_[0]));
+      };
 
-    sub vbm {
-      $machine->succeed(ru("VBoxManage ".$_[0]));
-    };
+      sub removeUUIDs {
+        return join("\n", grep { $_ !~ /^UUID:/ } split(/\n/, $_[0]))."\n";
+      }
 
-    ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)}
+      ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)}
 
-    $machine->waitForX;
+      $machine->waitForX;
 
-    ${mkLog "$HOME/.config/VirtualBox/VBoxSVC.log" "HOST-SVC"}
+      ${mkLog "$HOME/.config/VirtualBox/VBoxSVC.log" "HOST-SVC"}
 
-    createVM_simple;
+      ${testScript}
+    '';
 
-    subtest "simple-gui", sub {
-      $machine->succeed(ru "VirtualBox &");
-      $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/);
-      $machine->sleep(5);
-      $machine->screenshot("gui_manager_started");
-      $machine->sendKeys("ret");
-      $machine->screenshot("gui_manager_sent_startup");
-      waitForStartup_simple (sub {
-        $machine->sendKeys("ret");
-      });
-      $machine->screenshot("gui_started");
-      waitForVMBoot_simple;
-      $machine->screenshot("gui_booted");
-      shutdownVM_simple;
-      $machine->sleep(5);
-      $machine->screenshot("gui_stopped");
-      $machine->sendKeys("ctrl-q");
-      $machine->sleep(5);
-      $machine->screenshot("gui_manager_stopped");
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ aszlig wkennington ];
     };
+  };
 
-    cleanup_simple;
+in mapAttrs mkVBoxTest {
+  simple-gui = ''
+    createVM_simple;
+    $machine->succeed(ru "VirtualBox &");
+    $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/);
+    $machine->sleep(5);
+    $machine->screenshot("gui_manager_started");
+    $machine->sendKeys("ret");
+    $machine->screenshot("gui_manager_sent_startup");
+    waitForStartup_simple (sub {
+      $machine->sendKeys("ret");
+    });
+    $machine->screenshot("gui_started");
+    waitForVMBoot_simple;
+    $machine->screenshot("gui_booted");
+    shutdownVM_simple;
+    $machine->sleep(5);
+    $machine->screenshot("gui_stopped");
+    $machine->sendKeys("ctrl-q");
+    $machine->sleep(5);
+    $machine->screenshot("gui_manager_stopped");
+  '';
 
-    subtest "simple-cli", sub {
-      vbm("startvm simple");
-      waitForStartup_simple;
-      $machine->screenshot("cli_started");
-      waitForVMBoot_simple;
-      $machine->screenshot("cli_booted");
-      shutdownVM_simple;
-    };
+  simple-cli = ''
+    createVM_simple;
+    vbm("startvm simple");
+    waitForStartup_simple;
+    $machine->screenshot("cli_started");
+    waitForVMBoot_simple;
+    $machine->screenshot("cli_booted");
 
-    subtest "privilege-escalation", sub {
+    $machine->nest("Checking for privilege escalation", sub {
       $machine->fail("test -e '/root/VirtualBox VMs'");
       $machine->fail("test -e '/root/.config/VirtualBox'");
       $machine->succeed("test -e '/home/alice/VirtualBox VMs'");
-    };
-
-    destroyVM_simple;
+    });
 
-    sub removeUUIDs {
-      return join("\n", grep { $_ !~ /^UUID:/ } split(/\n/, $_[0]))."\n";
-    }
+    shutdownVM_simple;
+  '';
 
-    subtest "host-usb-permissions", sub {
-      my $userUSB = removeUUIDs vbm("list usbhost");
-      print STDERR $userUSB;
-      my $rootUSB = removeUUIDs $machine->succeed("VBoxManage list usbhost");
-      print STDERR $rootUSB;
+  host-usb-permissions = ''
+    my $userUSB = removeUUIDs vbm("list usbhost");
+    print STDERR $userUSB;
+    my $rootUSB = removeUUIDs $machine->succeed("VBoxManage list usbhost");
+    print STDERR $rootUSB;
 
-      die "USB host devices differ for root and normal user"
-        if $userUSB ne $rootUSB;
-      die "No USB host devices found" if $userUSB =~ /<none>/;
-    };
+    die "USB host devices differ for root and normal user"
+      if $userUSB ne $rootUSB;
+    die "No USB host devices found" if $userUSB =~ /<none>/;
+  '';
 
-    subtest "systemd-detect-virt", sub {
-      createVM_detectvirt;
-      vbm("startvm detectvirt");
-      waitForStartup_detectvirt;
-      waitForVMBoot_detectvirt;
-      shutdownVM_detectvirt;
-      my $result = $machine->succeed("cat '$detectvirt_sharepath/result'");
-      chomp $result;
-      destroyVM_detectvirt;
-      die "systemd-detect-virt returned \"$result\" instead of \"oracle\""
-        if $result ne "oracle";
-    };
+  systemd-detect-virt = ''
+    createVM_detectvirt;
+    vbm("startvm detectvirt");
+    waitForStartup_detectvirt;
+    waitForVMBoot_detectvirt;
+    shutdownVM_detectvirt;
+    my $result = $machine->succeed("cat '$detectvirt_sharepath/result'");
+    chomp $result;
+    destroyVM_detectvirt;
+    die "systemd-detect-virt returned \"$result\" instead of \"oracle\""
+      if $result ne "oracle";
+  '';
 
-    subtest "net-hostonlyif", sub {
-      createVM_test1;
-      createVM_test2;
+  net-hostonlyif = ''
+    createVM_test1;
+    createVM_test2;
 
-      vbm("startvm test1");
-      waitForStartup_test1;
-      waitForVMBoot_test1;
+    vbm("startvm test1");
+    waitForStartup_test1;
+    waitForVMBoot_test1;
 
-      vbm("startvm test2");
-      waitForStartup_test2;
-      waitForVMBoot_test2;
+    vbm("startvm test2");
+    waitForStartup_test2;
+    waitForVMBoot_test2;
 
-      $machine->screenshot("net_booted");
+    $machine->screenshot("net_booted");
 
-      my $test1IP = waitForIP_test1 1;
-      my $test2IP = waitForIP_test2 1;
+    my $test1IP = waitForIP_test1 1;
+    my $test2IP = waitForIP_test2 1;
 
-      $machine->succeed("echo '$test2IP' | netcat -c '$test1IP' 1234");
-      $machine->succeed("echo '$test1IP' | netcat -c '$test2IP' 1234");
+    $machine->succeed("echo '$test2IP' | netcat -c '$test1IP' 1234");
+    $machine->succeed("echo '$test1IP' | netcat -c '$test2IP' 1234");
 
-      $machine->waitUntilSucceeds("netcat -c '$test1IP' 5678 >&2");
-      $machine->waitUntilSucceeds("netcat -c '$test2IP' 5678 >&2");
+    $machine->waitUntilSucceeds("netcat -c '$test1IP' 5678 >&2");
+    $machine->waitUntilSucceeds("netcat -c '$test2IP' 5678 >&2");
 
-      shutdownVM_test1;
-      shutdownVM_test2;
+    shutdownVM_test1;
+    shutdownVM_test2;
 
-      destroyVM_test1;
-      destroyVM_test2;
-    };
+    destroyVM_test1;
+    destroyVM_test2;
   '';
-}) args
+}