summary refs log tree commit diff
path: root/nixos/tests
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/tests')
-rw-r--r--nixos/tests/boot.nix1
-rw-r--r--nixos/tests/borgbackup.nix21
-rw-r--r--nixos/tests/cloud-init.nix1
-rw-r--r--nixos/tests/docker-tools.nix39
-rw-r--r--nixos/tests/ec2.nix1
-rw-r--r--nixos/tests/elk.nix172
-rw-r--r--nixos/tests/fwupd.nix19
-rw-r--r--nixos/tests/gjs.nix19
-rw-r--r--nixos/tests/home-assistant.nix46
-rw-r--r--nixos/tests/installer.nix1
-rw-r--r--nixos/tests/keymap.nix1
-rw-r--r--nixos/tests/kubernetes/base.nix3
-rw-r--r--nixos/tests/kubernetes/certs.nix11
-rw-r--r--nixos/tests/kubernetes/dns.nix2
-rw-r--r--nixos/tests/kubernetes/kubernetes-common.nix4
-rw-r--r--nixos/tests/make-test.nix2
-rw-r--r--nixos/tests/matrix-synapse.nix30
-rw-r--r--nixos/tests/misc.nix5
-rw-r--r--nixos/tests/netdata.nix31
-rw-r--r--nixos/tests/networking.nix100
-rw-r--r--nixos/tests/plotinus.nix27
-rw-r--r--nixos/tests/predictable-interface-names.nix27
-rw-r--r--nixos/tests/rspamd.nix140
-rw-r--r--nixos/tests/rxe.nix53
-rw-r--r--nixos/tests/statsd.nix2
-rw-r--r--nixos/tests/sudo.nix93
-rw-r--r--nixos/tests/yabar.nix25
27 files changed, 775 insertions, 101 deletions
diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix
index 69ab4755e444..fc52cd09f209 100644
--- a/nixos/tests/boot.nix
+++ b/nixos/tests/boot.nix
@@ -1,7 +1,6 @@
 { system ? builtins.currentSystem }:
 
 with import ../lib/testing.nix { inherit system; };
-with import ../lib/qemu-flags.nix;
 with pkgs.lib;
 
 let
diff --git a/nixos/tests/borgbackup.nix b/nixos/tests/borgbackup.nix
new file mode 100644
index 000000000000..123b02be7251
--- /dev/null
+++ b/nixos/tests/borgbackup.nix
@@ -0,0 +1,21 @@
+import ./make-test.nix ({ pkgs, ...}: {
+  name = "borgbackup";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ mic92 ];
+  };
+
+  nodes = {
+    machine = { config, pkgs, ... }: {
+      environment.systemPackages = [ pkgs.borgbackup ];
+    };
+  };
+
+  testScript = ''
+    my $borg = "BORG_PASSPHRASE=supersecret borg";
+    $machine->succeed("$borg init --encryption=repokey /tmp/backup");
+    $machine->succeed("mkdir /tmp/data/ && echo 'data' >/tmp/data/file");
+    $machine->succeed("$borg create --stats /tmp/backup::test /tmp/data");
+    $machine->succeed("$borg extract /tmp/backup::test");
+    $machine->succeed('c=$(cat data/file) && echo "c = $c" >&2 && [[ "$c" == "data" ]]');
+  '';
+})
diff --git a/nixos/tests/cloud-init.nix b/nixos/tests/cloud-init.nix
index c0add7eff360..2a258e4bff54 100644
--- a/nixos/tests/cloud-init.nix
+++ b/nixos/tests/cloud-init.nix
@@ -1,7 +1,6 @@
 { system ? builtins.currentSystem }:
 
 with import ../lib/testing.nix { inherit system; };
-with import ../lib/qemu-flags.nix;
 with pkgs.lib;
 
 let
diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix
new file mode 100644
index 000000000000..e52a4c3f884e
--- /dev/null
+++ b/nixos/tests/docker-tools.nix
@@ -0,0 +1,39 @@
+# this test creates a simple GNU image with docker tools and sees if it executes
+
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "docker-tools";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ ];
+  };
+
+  nodes = {
+    docker =
+      { config, pkgs, ... }: {
+        virtualisation = {
+          diskSize = 1024;
+          docker.enable = true;
+        };
+      };
+  };
+
+  testScript =
+    ''
+      $docker->waitForUnit("sockets.target");
+
+      $docker->succeed("docker load --input='${pkgs.dockerTools.examples.bash}'");
+      $docker->succeed("docker run ${pkgs.dockerTools.examples.bash.imageName} /bin/bash --version");
+
+      $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nix}'");
+      $docker->succeed("docker run ${pkgs.dockerTools.examples.nix.imageName} /bin/nix-store -qR ${pkgs.nix}");
+
+      # To test the pullImage tool
+      $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nixFromDockerHub}'");
+      $docker->succeed("docker run nixos/nix:1.11 nix-store --version");
+
+      # To test runAsRoot and entry point
+      $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nginx}'");
+      $docker->succeed("docker run --name nginx -d -p 8000:80 ${pkgs.dockerTools.examples.nginx.imageName}");
+      $docker->waitUntilSucceeds('curl http://localhost:8000/');
+      $docker->succeed("docker rm --force nginx");
+    '';
+})
diff --git a/nixos/tests/ec2.nix b/nixos/tests/ec2.nix
index 4ec7e56cc6cb..f585fa2ec237 100644
--- a/nixos/tests/ec2.nix
+++ b/nixos/tests/ec2.nix
@@ -1,7 +1,6 @@
 { system ? builtins.currentSystem }:
 
 with import ../lib/testing.nix { inherit system; };
-with import ../lib/qemu-flags.nix;
 with pkgs.lib;
 
 let
diff --git a/nixos/tests/elk.nix b/nixos/tests/elk.nix
index 65ff1cac070b..ed656b3628b9 100644
--- a/nixos/tests/elk.nix
+++ b/nixos/tests/elk.nix
@@ -1,95 +1,107 @@
-# Test the ELK stack: Elasticsearch, Logstash and Kibana.
-
-import ./make-test.nix ({ pkgs, ...} :
+{ system ? builtins.currentSystem }:
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
 let
   esUrl = "http://localhost:9200";
-in {
-  name = "ELK";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ eelco chaoflow offline basvandijk ];
-  };
 
-  nodes = {
-    one =
-      { config, pkgs, ... }: {
-          # Not giving the machine at least 2060MB results in elasticsearch failing with the following error:
-          #
-          #   OpenJDK 64-Bit Server VM warning:
-          #     INFO: os::commit_memory(0x0000000085330000, 2060255232, 0)
-          #     failed; error='Cannot allocate memory' (errno=12)
-          #
-          #   There is insufficient memory for the Java Runtime Environment to continue.
-          #   Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory.
-          #
-          # When setting this to 2500 I got "Kernel panic - not syncing: Out of
-          # memory: compulsory panic_on_oom is enabled" so lets give it even a
-          # bit more room:
-          virtualisation.memorySize = 3000;
+  mkElkTest = name : elk : makeTest {
+    inherit name;
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ eelco chaoflow offline basvandijk ];
+    };
+    nodes = {
+      one =
+        { config, pkgs, ... }: {
+            # Not giving the machine at least 2060MB results in elasticsearch failing with the following error:
+            #
+            #   OpenJDK 64-Bit Server VM warning:
+            #     INFO: os::commit_memory(0x0000000085330000, 2060255232, 0)
+            #     failed; error='Cannot allocate memory' (errno=12)
+            #
+            #   There is insufficient memory for the Java Runtime Environment to continue.
+            #   Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory.
+            #
+            # When setting this to 2500 I got "Kernel panic - not syncing: Out of
+            # memory: compulsory panic_on_oom is enabled" so lets give it even a
+            # bit more room:
+            virtualisation.memorySize = 3000;
 
-          # For querying JSON objects returned from elasticsearch and kibana.
-          environment.systemPackages = [ pkgs.jq ];
+            # For querying JSON objects returned from elasticsearch and kibana.
+            environment.systemPackages = [ pkgs.jq ];
 
-          services = {
-            logstash = {
-              enable = true;
-              package = pkgs.logstash5;
-              inputConfig = ''
-                exec { command => "echo -n flowers" interval => 1 type => "test" }
-                exec { command => "echo -n dragons" interval => 1 type => "test" }
-              '';
-              filterConfig = ''
-                if [message] =~ /dragons/ {
-                  drop {}
-                }
-              '';
-              outputConfig = ''
-                file {
-                  path => "/tmp/logstash.out"
-                  codec => line { format => "%{message}" }
-                }
-                elasticsearch {
-                  hosts => [ "${esUrl}" ]
-                }
-              '';
-            };
+            services = {
+              logstash = {
+                enable = true;
+                package = elk.logstash;
+                inputConfig = ''
+                  exec { command => "echo -n flowers" interval => 1 type => "test" }
+                  exec { command => "echo -n dragons" interval => 1 type => "test" }
+                '';
+                filterConfig = ''
+                  if [message] =~ /dragons/ {
+                    drop {}
+                  }
+                '';
+                outputConfig = ''
+                  file {
+                    path => "/tmp/logstash.out"
+                    codec => line { format => "%{message}" }
+                  }
+                  elasticsearch {
+                    hosts => [ "${esUrl}" ]
+                  }
+                '';
+              };
 
-            elasticsearch = {
-              enable = true;
-              package = pkgs.elasticsearch5;
-            };
+              elasticsearch = {
+                enable = true;
+                package = elk.elasticsearch;
+              };
 
-            kibana = {
-              enable = true;
-              package = pkgs.kibana5;
-              elasticsearch.url = esUrl;
+              kibana = {
+                enable = true;
+                package = elk.kibana;
+                elasticsearch.url = esUrl;
+              };
             };
           };
-        };
-    };
+      };
 
-  testScript = ''
-    startAll;
+    testScript = ''
+      startAll;
 
-    $one->waitForUnit("elasticsearch.service");
+      $one->waitForUnit("elasticsearch.service");
 
-    # Continue as long as the status is not "red". The status is probably
-    # "yellow" instead of "green" because we are using a single elasticsearch
-    # node which elasticsearch considers risky.
-    #
-    # TODO: extend this test with multiple elasticsearch nodes and see if the status turns "green".
-    $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_cluster/health' | jq .status | grep -v red");
+      # Continue as long as the status is not "red". The status is probably
+      # "yellow" instead of "green" because we are using a single elasticsearch
+      # node which elasticsearch considers risky.
+      #
+      # TODO: extend this test with multiple elasticsearch nodes and see if the status turns "green".
+      $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_cluster/health' | jq .status | grep -v red");
 
-    # Perform some simple logstash tests.
-    $one->waitForUnit("logstash.service");
-    $one->waitUntilSucceeds("cat /tmp/logstash.out | grep flowers");
-    $one->waitUntilSucceeds("cat /tmp/logstash.out | grep -v dragons");
+      # Perform some simple logstash tests.
+      $one->waitForUnit("logstash.service");
+      $one->waitUntilSucceeds("cat /tmp/logstash.out | grep flowers");
+      $one->waitUntilSucceeds("cat /tmp/logstash.out | grep -v dragons");
 
-    # See if kibana is healthy.
-    $one->waitForUnit("kibana.service");
-    $one->waitUntilSucceeds("curl --silent --show-error 'http://localhost:5601/api/status' | jq .status.overall.state | grep green");
+      # See if kibana is healthy.
+      $one->waitForUnit("kibana.service");
+      $one->waitUntilSucceeds("curl --silent --show-error 'http://localhost:5601/api/status' | jq .status.overall.state | grep green");
 
-    # See if logstash messages arive in elasticsearch.
-    $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"flowers\"}}}' | jq .hits.total | grep -v 0");
-    $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"dragons\"}}}' | jq .hits.total | grep 0");
-  '';
-})
+      # See if logstash messages arive in elasticsearch.
+      $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"flowers\"}}}' | jq .hits.total | grep -v 0");
+      $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"dragons\"}}}' | jq .hits.total | grep 0");
+    '';
+  };
+in mapAttrs mkElkTest {
+  "ELK-5" = {
+    elasticsearch = pkgs.elasticsearch5;
+    logstash      = pkgs.logstash5;
+    kibana        = pkgs.kibana5;
+  };
+  "ELK-6" = {
+    elasticsearch = pkgs.elasticsearch6;
+    logstash      = pkgs.logstash6;
+    kibana        = pkgs.kibana6;
+  };
+}
diff --git a/nixos/tests/fwupd.nix b/nixos/tests/fwupd.nix
new file mode 100644
index 000000000000..bf4ef25130b3
--- /dev/null
+++ b/nixos/tests/fwupd.nix
@@ -0,0 +1,19 @@
+# run installed tests
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "fwupd";
+
+  meta = {
+    maintainers = pkgs.fwupd.meta.maintainers;
+  };
+
+  machine = { config, pkgs, ... }: {
+    services.fwupd.enable = true;
+    environment.systemPackages = with pkgs; [ gnome-desktop-testing ];
+    environment.variables.XDG_DATA_DIRS = [ "${pkgs.fwupd.installedTests}/share" ];
+    virtualisation.memorySize = 768;
+  };
+
+  testScript = ''
+    $machine->succeed("gnome-desktop-testing-runner");
+  '';
+})
diff --git a/nixos/tests/gjs.nix b/nixos/tests/gjs.nix
new file mode 100644
index 000000000000..e6002ef98dd0
--- /dev/null
+++ b/nixos/tests/gjs.nix
@@ -0,0 +1,19 @@
+# run installed tests
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "gjs";
+
+  meta = {
+    maintainers = pkgs.gnome3.gjs.meta.maintainers;
+  };
+
+  machine = { pkgs, ... }: {
+    imports = [ ./common/x11.nix ];
+    environment.systemPackages = with pkgs; [ gnome-desktop-testing ];
+    environment.variables.XDG_DATA_DIRS = [ "${pkgs.gnome3.gjs.installedTests}/share" ];
+  };
+
+  testScript = ''
+    $machine->waitForX;
+    $machine->succeed("gnome-desktop-testing-runner");
+  '';
+})
diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix
new file mode 100644
index 000000000000..5d7e0ec65e73
--- /dev/null
+++ b/nixos/tests/home-assistant.nix
@@ -0,0 +1,46 @@
+import ./make-test.nix ({ pkgs, ... }:
+
+let
+  configDir = "/var/lib/foobar";
+
+in {
+  name = "home-assistant";
+
+  nodes = {
+    hass =
+      { config, pkgs, ... }:
+      {
+        services.home-assistant = {
+          inherit configDir;
+          enable = true;
+          config = {
+            homeassistant = {
+              name = "Home";
+              time_zone = "UTC";
+              latitude = "0.0";
+              longitude = "0.0";
+              elevation = 0;
+            };
+            frontend = { };
+            http = { };
+          };
+        };
+      };
+  };
+
+  testScript = ''
+    startAll;
+    $hass->waitForUnit("home-assistant.service");
+    
+    # Since config is specified using a Nix attribute set,
+    # configuration.yaml is a link to the Nix store
+    $hass->succeed("test -L ${configDir}/configuration.yaml");
+
+    # Check that Home Assistant's web interface and API can be reached
+    $hass->waitForOpenPort(8123);
+    $hass->succeed("curl --fail http://localhost:8123/states");
+    $hass->succeed("curl --fail http://localhost:8123/api/ | grep 'API running'");
+
+    $hass->fail("cat ${configDir}/home-assistant.log | grep -qF ERROR");
+  '';
+})
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 90ac5b933f32..637cbb45709d 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -1,7 +1,6 @@
 { system ? builtins.currentSystem }:
 
 with import ../lib/testing.nix { inherit system; };
-with import ../lib/qemu-flags.nix;
 with pkgs.lib;
 
 let
diff --git a/nixos/tests/keymap.nix b/nixos/tests/keymap.nix
index c431c1a34174..eec674e227df 100644
--- a/nixos/tests/keymap.nix
+++ b/nixos/tests/keymap.nix
@@ -46,6 +46,7 @@ let
   in makeTest {
     name = "keymap-${layout}";
 
+    machine.services.xserver.desktopManager.xterm.enable = false;
     machine.i18n.consoleKeyMap = mkOverride 900 layout;
     machine.services.xserver.layout = mkOverride 900 layout;
     machine.imports = [ ./common/x11.nix extraConfig ];
diff --git a/nixos/tests/kubernetes/base.nix b/nixos/tests/kubernetes/base.nix
index acf2e0250819..27b99aacab7d 100644
--- a/nixos/tests/kubernetes/base.nix
+++ b/nixos/tests/kubernetes/base.nix
@@ -1,14 +1,13 @@
 { system ? builtins.currentSystem }:
 
 with import ../../lib/testing.nix { inherit system; };
-with import ../../lib/qemu-flags.nix;
 with pkgs.lib;
 
 let
   mkKubernetesBaseTest =
     { name, domain ? "my.zyx", test, machines
     , pkgs ? import <nixpkgs> { inherit system; }
-    , certs ? import ./certs.nix { inherit pkgs; externalDomain = domain; }
+    , certs ? import ./certs.nix { inherit pkgs; externalDomain = domain; kubelets = attrNames machines; }
     , extraConfiguration ? null }:
     let
       masterName = head (filter (machineName: any (role: role == "master") machines.${machineName}.roles) (attrNames machines));
diff --git a/nixos/tests/kubernetes/certs.nix b/nixos/tests/kubernetes/certs.nix
index f108e35b98cd..d3eff910c467 100644
--- a/nixos/tests/kubernetes/certs.nix
+++ b/nixos/tests/kubernetes/certs.nix
@@ -2,7 +2,8 @@
   pkgs ? import <nixpkgs> {},
   internalDomain ? "cloud.yourdomain.net",
   externalDomain ? "myawesomecluster.cluster.yourdomain.net",
-  serviceClusterIp ? "10.0.0.1"
+  serviceClusterIp ? "10.0.0.1",
+  kubelets
 }:
 let
   runWithCFSSL = name: cmd:
@@ -123,9 +124,10 @@ let
   };
 
   apiserver-client = {
-    kubelet = createClientCertKey {
+    kubelet = hostname: createClientCertKey {
       inherit ca;
-      cn = "apiserver-client-kubelet";
+      name = "apiserver-client-kubelet-${hostname}";
+      cn = "system:node:${hostname}.${externalDomain}";
       groups = ["system:nodes"];
     };
 
@@ -175,10 +177,9 @@ in {
     paths = [
       (writeCFSSL (noKey ca))
       (writeCFSSL kubelet)
-      (writeCFSSL apiserver-client.kubelet)
       (writeCFSSL apiserver-client.kube-proxy)
       (writeCFSSL etcd-client)
-    ];
+    ] ++ map (hostname: writeCFSSL (apiserver-client.kubelet hostname)) kubelets;
   };
 
   admin = writeCFSSL apiserver-client.admin;
diff --git a/nixos/tests/kubernetes/dns.nix b/nixos/tests/kubernetes/dns.nix
index 74d98dabec8d..8c488d271bcd 100644
--- a/nixos/tests/kubernetes/dns.nix
+++ b/nixos/tests/kubernetes/dns.nix
@@ -3,7 +3,7 @@ with import ./base.nix { inherit system; };
 let
   domain = "my.zyx";
 
-  certs = import ./certs.nix { externalDomain = domain; };
+  certs = import ./certs.nix { externalDomain = domain; kubelets = [ "machine1" "machine2" ]; };
 
   redisPod = pkgs.writeText "redis-pod.json" (builtins.toJSON {
     kind = "Pod";
diff --git a/nixos/tests/kubernetes/kubernetes-common.nix b/nixos/tests/kubernetes/kubernetes-common.nix
index 00a5c9aba4e3..ddf427e1b01a 100644
--- a/nixos/tests/kubernetes/kubernetes-common.nix
+++ b/nixos/tests/kubernetes/kubernetes-common.nix
@@ -29,8 +29,8 @@ let
       tlsKeyFile = "${certs.worker}/kubelet-key.pem";
       hostname = "${config.networking.hostName}.${config.networking.domain}";
       kubeconfig = {
-        certFile = "${certs.worker}/apiserver-client-kubelet.pem";
-        keyFile = "${certs.worker}/apiserver-client-kubelet-key.pem";
+        certFile = "${certs.worker}/apiserver-client-kubelet-${config.networking.hostName}.pem";
+        keyFile = "${certs.worker}/apiserver-client-kubelet-${config.networking.hostName}-key.pem";
       };
     };
     controllerManager = {
diff --git a/nixos/tests/make-test.nix b/nixos/tests/make-test.nix
index f3e26aa7e74d..ee4ba310ad50 100644
--- a/nixos/tests/make-test.nix
+++ b/nixos/tests/make-test.nix
@@ -2,4 +2,4 @@ f: { system ? builtins.currentSystem, ... } @ args:
 
 with import ../lib/testing.nix { inherit system; };
 
-makeTest (if builtins.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
+makeTest (if pkgs.lib.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
diff --git a/nixos/tests/matrix-synapse.nix b/nixos/tests/matrix-synapse.nix
new file mode 100644
index 000000000000..113fb622588b
--- /dev/null
+++ b/nixos/tests/matrix-synapse.nix
@@ -0,0 +1,30 @@
+import ./make-test.nix ({ pkgs, ... } : {
+
+  name = "matrix-synapse";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ corngood ];
+  };
+
+  nodes = {
+    server_postgres = args: {
+      services.matrix-synapse.enable = true;
+      services.matrix-synapse.database_type = "psycopg2";
+    };
+
+    server_sqlite = args: {
+      services.matrix-synapse.enable = true;
+      services.matrix-synapse.database_type = "sqlite3";
+    };
+  };
+
+  testScript = ''
+    startAll;
+    $server_postgres->waitForUnit("matrix-synapse.service");
+    $server_postgres->waitUntilSucceeds("curl -Lk https://localhost:8448/");
+    $server_postgres->requireActiveUnit("postgresql.service");
+    $server_sqlite->waitForUnit("matrix-synapse.service");
+    $server_sqlite->waitUntilSucceeds("curl -Lk https://localhost:8448/");
+    $server_sqlite->mustSucceed("[ -e /var/lib/matrix-synapse/homeserver.db ]");
+  '';
+
+})
diff --git a/nixos/tests/misc.nix b/nixos/tests/misc.nix
index 79290861cb0b..6de17518214c 100644
--- a/nixos/tests/misc.nix
+++ b/nixos/tests/misc.nix
@@ -115,11 +115,6 @@ import ./make-test.nix ({ pkgs, ...} : {
           $machine->succeed("nix-store -qR /run/current-system | grep nixos-");
       };
 
-      # Test sudo
-      subtest "sudo", sub {
-          $machine->succeed("su - sybil -c 'sudo true'");
-      };
-
       # Test sysctl
       subtest "sysctl", sub {
           $machine->waitForUnit("systemd-sysctl.service");
diff --git a/nixos/tests/netdata.nix b/nixos/tests/netdata.nix
new file mode 100644
index 000000000000..58733c1b3379
--- /dev/null
+++ b/nixos/tests/netdata.nix
@@ -0,0 +1,31 @@
+# This test runs netdata and checks for data via apps.plugin
+
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "netdata";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ cransom ];
+  };
+
+  nodes = {
+    netdata =
+      { config, pkgs, ... }:
+        {
+          environment.systemPackages = with pkgs; [ curl jq ];
+          services.netdata.enable = true;
+        };
+    };
+
+  testScript = ''
+    startAll;
+
+    $netdata->waitForUnit("netdata.service");
+    # check if netdata can read disk ops for root owned processes. 
+    # if > 0, successful. verifies both netdata working and 
+    # apps.plugin has elevated capabilities.
+    my $cmd = <<'CMD';
+    curl -s http://localhost:19999/api/v1/data\?chart=users.pwrites | \
+       jq -e '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0'
+    CMD
+    $netdata->waitUntilSucceeds($cmd);
+  '';
+})
diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix
index 7708775f73f3..fa3dc0538729 100644
--- a/nixos/tests/networking.nix
+++ b/nixos/tests/networking.nix
@@ -433,6 +433,106 @@ let
           $client2->succeed("ip addr show dev vlan >&2");
         '';
     };
+    virtual = {
+      name = "Virtual";
+      machine = {
+        networking.interfaces."tap0" = {
+          ip4 = [ { address = "192.168.1.1"; prefixLength = 24; } ];
+          ip6 = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
+          virtual = true;
+        };
+        networking.interfaces."tun0" = {
+          ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ];
+          ip6 = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
+          virtual = true;
+        };
+      };
+
+      testScript = ''
+        my $targetList = <<'END';
+        tap0: tap UNKNOWN_FLAGS:800 user 0
+        tun0: tun UNKNOWN_FLAGS:800 user 0
+        END
+
+        # Wait for networking to come up
+        $machine->start;
+        $machine->waitForUnit("network.target");
+
+        # Test interfaces set up
+        my $list = $machine->succeed("ip tuntap list | sort");
+        "$list" eq "$targetList" or die(
+          "The list of virtual interfaces does not match the expected one:\n",
+          "Result:\n", "$list\n",
+          "Expected:\n", "$targetList\n"
+        );
+
+        # Test interfaces clean up
+        $machine->succeed("systemctl stop network-addresses-tap0");
+        $machine->succeed("systemctl stop network-addresses-tun0");
+        my $residue = $machine->succeed("ip tuntap list");
+        $residue eq "" or die(
+          "Some virtual interface has not been properly cleaned:\n",
+          "$residue\n"
+        );
+      '';
+    };
+    privacy = {
+      name = "Privacy";
+      nodes.router = { config, pkgs, ... }: {
+        virtualisation.vlans = [ 1 ];
+        boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
+        networking = {
+          useNetworkd = networkd;
+          interfaces.eth1 = {
+            ipv6Address = "fd00:1234:5678:1::1";
+            ipv6PrefixLength = 64;
+          };
+        };
+        services.radvd = {
+          enable = true;
+          config = ''
+            interface eth1 {
+              AdvSendAdvert on;
+              AdvManagedFlag on;
+              AdvOtherConfigFlag on;
+
+              prefix fd00:1234:5678:1::/64 {
+                AdvAutonomous on;
+                AdvOnLink on;
+              };
+            };
+          '';
+        };
+      };
+      nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+        virtualisation.vlans = [ 1 ];
+        networking = {
+          useNetworkd = networkd;
+          useDHCP = true;
+          interfaces.eth1 = {
+            preferTempAddress = true;
+            ip4 = mkOverride 0 [ ];
+            ip6 = mkOverride 0 [ ];
+          };
+        };
+      };
+      testScript = { nodes, ... }:
+        ''
+          startAll;
+
+          $client->waitForUnit("network.target");
+          $router->waitForUnit("network-online.target");
+
+          # Wait until we have an ip address
+          $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'");
+
+          # Test vlan 1
+          $client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
+
+          # Test address used is temporary
+          $client->succeed("! ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'");
+        '';
+    };
   };
 
 in mapAttrs (const (attrs: makeTest (attrs // {
diff --git a/nixos/tests/plotinus.nix b/nixos/tests/plotinus.nix
new file mode 100644
index 000000000000..557d65f7960a
--- /dev/null
+++ b/nixos/tests/plotinus.nix
@@ -0,0 +1,27 @@
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "plotinus";
+  meta = {
+    maintainers = pkgs.plotinus.meta.maintainers;
+  };
+
+  machine =
+    { config, pkgs, ... }:
+
+    { imports = [ ./common/x11.nix ];
+      programs.plotinus.enable = true;
+      environment.systemPackages = [ pkgs.gnome3.gnome-calculator pkgs.xdotool ];
+    };
+
+  testScript =
+    ''
+      $machine->waitForX;
+      $machine->execute("xterm -e 'gnome-calculator' &");
+      $machine->waitForWindow(qr/Calculator/);
+      $machine->execute("xdotool key ctrl+shift+p");
+      $machine->sleep(1); # wait for the popup
+      $machine->execute("xdotool key p r e f e r e n c e s Return");
+      $machine->waitForWindow(qr/Preferences/);
+      $machine->screenshot("screen");
+    '';
+
+})
diff --git a/nixos/tests/predictable-interface-names.nix b/nixos/tests/predictable-interface-names.nix
new file mode 100644
index 000000000000..b4c2039923cf
--- /dev/null
+++ b/nixos/tests/predictable-interface-names.nix
@@ -0,0 +1,27 @@
+{ system ? builtins.currentSystem
+, pkgs ? import ../.. { inherit system; }
+}:
+with import ../lib/testing.nix { inherit system; };
+let boolToString = x: if x then "yes" else "no"; in
+let testWhenSetTo = predictable: withNetworkd:
+makeTest {
+  name = "${if predictable then "" else "un"}predictableInterfaceNames${if withNetworkd then "-with-networkd" else ""}";
+  meta = {};
+
+  machine = { config, pkgs, ... }: {
+    networking.usePredictableInterfaceNames = pkgs.stdenv.lib.mkForce predictable;
+    networking.useNetworkd = withNetworkd;
+    networking.dhcpcd.enable = !withNetworkd;
+  };
+
+  testScript = ''
+    print $machine->succeed("ip link");
+    $machine->succeed("ip link show ${if predictable then "ens3" else "eth0"}");
+    $machine->fail("ip link show ${if predictable then "eth0" else "ens3"}");
+  '';
+}; in
+with pkgs.stdenv.lib.lists;
+with pkgs.stdenv.lib.attrsets;
+listToAttrs (map (drv: nameValuePair drv.name drv) (
+crossLists testWhenSetTo [[true false] [true false]]
+))
diff --git a/nixos/tests/rspamd.nix b/nixos/tests/rspamd.nix
new file mode 100644
index 000000000000..6b2e2dd3a531
--- /dev/null
+++ b/nixos/tests/rspamd.nix
@@ -0,0 +1,140 @@
+{ system ? builtins.currentSystem }:
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
+let
+  initMachine = ''
+    startAll
+    $machine->waitForUnit("rspamd.service");
+    $machine->succeed("id \"rspamd\" >/dev/null");
+  '';
+  checkSocket = socket: user: group: mode: ''
+    $machine->succeed("ls ${socket} >/dev/null");
+    $machine->succeed("[[ \"\$(stat -c %U ${socket})\" == \"${user}\" ]]");
+    $machine->succeed("[[ \"\$(stat -c %G ${socket})\" == \"${group}\" ]]");
+    $machine->succeed("[[ \"\$(stat -c %a ${socket})\" == \"${mode}\" ]]");
+  '';
+  simple = name: socketActivation: enableIPv6: makeTest {
+    name = "rspamd-${name}";
+    machine = {
+      services.rspamd = {
+        enable = true;
+        socketActivation = socketActivation;
+      };
+      networking.enableIPv6 = enableIPv6;
+    };
+    testScript = ''
+      startAll
+      $machine->waitForUnit("multi-user.target");
+      $machine->waitForOpenPort(11334);
+      $machine->waitForUnit("rspamd.service");
+      $machine->succeed("id \"rspamd\" >/dev/null");
+      ${checkSocket "/run/rspamd/rspamd.sock" "rspamd" "rspamd" "660" }
+      sleep 10;
+      $machine->log($machine->succeed("cat /etc/rspamd.conf"));
+      $machine->log($machine->succeed("systemctl cat rspamd.service"));
+      ${if socketActivation then ''
+        $machine->log($machine->succeed("systemctl cat rspamd-controller-1.socket"));
+        $machine->log($machine->succeed("systemctl cat rspamd-normal-1.socket"));
+      '' else ''
+        $machine->fail("systemctl cat rspamd-controller-1.socket");
+        $machine->fail("systemctl cat rspamd-normal-1.socket");
+      ''}
+      $machine->log($machine->succeed("curl http://localhost:11334/auth"));
+      $machine->log($machine->succeed("curl http://127.0.0.1:11334/auth"));
+      ${optionalString enableIPv6 ''
+        $machine->log($machine->succeed("curl http://[::1]:11334/auth"));
+      ''}
+    '';
+  };
+in
+{
+  simple = simple "simple" false true;
+  ipv4only = simple "ipv4only" false false;
+  simple-socketActivated = simple "simple-socketActivated" true true;
+  ipv4only-socketActivated = simple "ipv4only-socketActivated" true false;
+  deprecated = makeTest {
+    name = "rspamd-deprecated";
+    machine = {
+      services.rspamd = {
+        enable = true;
+        bindSocket = [ "/run/rspamd.sock mode=0600 user=root group=root" ];
+        bindUISocket = [ "/run/rspamd-worker.sock mode=0666 user=root group=root" ];
+      };
+    };
+
+    testScript = ''
+      ${initMachine}
+      $machine->waitForFile("/run/rspamd.sock");
+      ${checkSocket "/run/rspamd.sock" "root" "root" "600" }
+      ${checkSocket "/run/rspamd-worker.sock" "root" "root" "666" }
+      $machine->log($machine->succeed("cat /etc/rspamd.conf"));
+      $machine->fail("systemctl cat rspamd-normal-1.socket");
+      $machine->log($machine->succeed("rspamc -h /run/rspamd-worker.sock stat"));
+      $machine->log($machine->succeed("curl --unix-socket /run/rspamd-worker.sock http://localhost/ping"));
+    '';
+  };
+
+  bindports = makeTest {
+    name = "rspamd-bindports";
+    machine = {
+      services.rspamd = {
+        enable = true;
+        socketActivation = false;
+        workers.normal.bindSockets = [{
+          socket = "/run/rspamd.sock";
+          mode = "0600";
+          owner = "root";
+          group = "root";
+        }];
+        workers.controller.bindSockets = [{
+          socket = "/run/rspamd-worker.sock";
+          mode = "0666";
+          owner = "root";
+          group = "root";
+        }];
+      };
+    };
+
+    testScript = ''
+      ${initMachine}
+      $machine->waitForFile("/run/rspamd.sock");
+      ${checkSocket "/run/rspamd.sock" "root" "root" "600" }
+      ${checkSocket "/run/rspamd-worker.sock" "root" "root" "666" }
+      $machine->log($machine->succeed("cat /etc/rspamd.conf"));
+      $machine->fail("systemctl cat rspamd-normal-1.socket");
+      $machine->log($machine->succeed("rspamc -h /run/rspamd-worker.sock stat"));
+      $machine->log($machine->succeed("curl --unix-socket /run/rspamd-worker.sock http://localhost/ping"));
+    '';
+  };
+  socketActivated = makeTest {
+    name = "rspamd-socketActivated";
+    machine = {
+      services.rspamd = {
+        enable = true;
+        workers.normal.bindSockets = [{
+          socket = "/run/rspamd.sock";
+          mode = "0600";
+          owner = "root";
+          group = "root";
+        }];
+        workers.controller.bindSockets = [{
+          socket = "/run/rspamd-worker.sock";
+          mode = "0666";
+          owner = "root";
+          group = "root";
+        }];
+      };
+    };
+
+    testScript = ''
+      startAll
+      $machine->waitForFile("/run/rspamd.sock");
+      ${checkSocket "/run/rspamd.sock" "root" "root" "600" }
+      ${checkSocket "/run/rspamd-worker.sock" "root" "root" "666" }
+      $machine->log($machine->succeed("cat /etc/rspamd.conf"));
+      $machine->log($machine->succeed("systemctl cat rspamd-normal-1.socket"));
+      $machine->log($machine->succeed("rspamc -h /run/rspamd-worker.sock stat"));
+      $machine->log($machine->succeed("curl --unix-socket /run/rspamd-worker.sock http://localhost/ping"));
+    '';
+  };
+}
diff --git a/nixos/tests/rxe.nix b/nixos/tests/rxe.nix
new file mode 100644
index 000000000000..cfe64a75a635
--- /dev/null
+++ b/nixos/tests/rxe.nix
@@ -0,0 +1,53 @@
+import ./make-test.nix ({ pkgs, ... } :
+
+let
+  node = { config, pkgs, lib, ... } : {
+    networking = {
+      firewall = {
+        allowedUDPPorts = [ 4791 ]; # open RoCE port
+        allowedTCPPorts = [ 4800 ]; # port for test utils
+      };
+      rxe = {
+        enable = true;
+        interfaces = [ "eth1" ];
+      };
+    };
+
+    environment.systemPackages = with pkgs; [ rdma-core screen ];
+  };
+
+in {
+  name = "rxe";
+
+  nodes = {
+    server = node;
+    client = node;
+  };
+
+  testScript = ''
+    # Test if rxe interface comes up
+    $server->waitForUnit("default.target");
+    $server->succeed("systemctl status rxe.service");
+    $server->succeed("ibv_devices | grep rxe0");
+
+    $client->waitForUnit("default.target");
+
+    # ping pong test
+    $server->succeed("screen -dmS rc_pingpong ibv_rc_pingpong -p 4800 -g0");
+    $client->succeed("sleep 2; ibv_rc_pingpong -p 4800 -g0 server");
+
+    $server->succeed("screen -dmS uc_pingpong ibv_uc_pingpong -p 4800 -g0");
+    $client->succeed("sleep 2; ibv_uc_pingpong -p 4800 -g0 server");
+
+    $server->succeed("screen -dmS ud_pingpong ibv_ud_pingpong -p 4800 -s 1024 -g0");
+    $client->succeed("sleep 2; ibv_ud_pingpong -p 4800 -s 1024 -g0 server");
+
+    $server->succeed("screen -dmS srq_pingpong ibv_srq_pingpong -p 4800 -g0");
+    $client->succeed("sleep 2; ibv_srq_pingpong -p 4800 -g0 server");
+
+    $server->succeed("screen -dmS rping rping -s -a server -C 10");
+    $client->succeed("sleep 2; rping -c -a server -C 10");
+  '';
+})
+
+
diff --git a/nixos/tests/statsd.nix b/nixos/tests/statsd.nix
index d6bbc3901630..a9d7dc61cb60 100644
--- a/nixos/tests/statsd.nix
+++ b/nixos/tests/statsd.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, lib }:
+import ./make-test.nix ({ pkgs, lib, ... }:
 
 with lib;
 
diff --git a/nixos/tests/sudo.nix b/nixos/tests/sudo.nix
new file mode 100644
index 000000000000..35addb0ee805
--- /dev/null
+++ b/nixos/tests/sudo.nix
@@ -0,0 +1,93 @@
+# Some tests to ensure sudo is working properly.
+
+let
+  password = "helloworld";
+
+in
+  import ./make-test.nix ({ pkgs, ...} : {
+    name = "sudo";
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ lschuermann ];
+    };
+
+    machine =
+      { config, lib, pkgs, ... }:
+      with lib;
+      {
+        users.extraGroups = { foobar = {}; barfoo = {}; baz = { gid = 1337; }; };
+        users.users = {
+          test0 = { isNormalUser = true; extraGroups = [ "wheel" ]; };
+          test1 = { isNormalUser = true; password = password; };
+          test2 = { isNormalUser = true; extraGroups = [ "foobar" ]; password = password; };
+          test3 = { isNormalUser = true; extraGroups = [ "barfoo" ]; };
+          test4 = { isNormalUser = true; extraGroups = [ "baz" ]; };
+          test5 = { isNormalUser = true; };
+        };
+
+        security.sudo = {
+          enable = true;
+          wheelNeedsPassword = false;
+
+          extraRules = [
+            # SUDOERS SYNTAX CHECK (Test whether the module produces a valid output;
+            # errors being detected by the visudo checks.
+
+            # These should not create any entries
+            { users = [ "notest1" ]; commands = [ ]; }
+            { commands = [ { command = "ALL"; options = [ ]; } ]; }
+
+            # Test defining commands with the options syntax, though not setting any options
+            { users = [ "notest2" ]; commands = [ { command = "ALL"; options = [ ]; } ]; }
+
+
+            # CONFIGURATION FOR TEST CASES
+            { users = [ "test1" ]; groups = [ "foobar" ]; commands = [ "ALL" ]; }
+            { groups = [ "barfoo" 1337 ]; commands = [ { command = "ALL"; options = [ "NOPASSWD" "NOSETENV" ]; } ]; }
+            { users = [ "test5" ]; commands = [ { command = "ALL"; options = [ "NOPASSWD" "SETENV" ]; } ]; runAs = "test1:barfoo"; }
+          ];
+        };
+      };
+
+    testScript =
+      ''
+        subtest "users in wheel group should have passwordless sudo", sub {
+            $machine->succeed("su - test0 -c \"sudo -u root true\"");
+        };
+
+        subtest "test1 user should have sudo with password", sub {
+            $machine->succeed("su - test1 -c \"echo ${password} | sudo -S -u root true\"");
+        };
+
+        subtest "test1 user should not be able to use sudo without password", sub {
+            $machine->fail("su - test1 -c \"sudo -n -u root true\"");
+        };
+
+        subtest "users in group 'foobar' should be able to use sudo with password", sub {
+            $machine->succeed("sudo -u test2 echo ${password} | sudo -S -u root true");
+        };
+
+        subtest "users in group 'barfoo' should be able to use sudo without password", sub {
+            $machine->succeed("sudo -u test3 sudo -n -u root true");
+        };
+
+        subtest "users in group 'baz' (GID 1337) should be able to use sudo without password", sub {
+            $machine->succeed("sudo -u test4 sudo -n -u root echo true");
+        };
+
+        subtest "test5 user should be able to run commands under test1", sub {
+            $machine->succeed("sudo -u test5 sudo -n -u test1 true");
+        };
+
+        subtest "test5 user should not be able to run commands under root", sub {
+            $machine->fail("sudo -u test5 sudo -n -u root true");
+        };
+
+        subtest "test5 user should be able to keep his environment", sub {
+            $machine->succeed("sudo -u test5 sudo -n -E -u test1 true");
+        };
+
+        subtest "users in group 'barfoo' should not be able to keep their environment", sub {
+            $machine->fail("sudo -u test3 sudo -n -E -u root true");
+        };
+      '';
+  })
diff --git a/nixos/tests/yabar.nix b/nixos/tests/yabar.nix
new file mode 100644
index 000000000000..40ca91e8064d
--- /dev/null
+++ b/nixos/tests/yabar.nix
@@ -0,0 +1,25 @@
+import ./make-test.nix ({ pkgs, lib }:
+
+with lib;
+
+{
+  name = "yabar";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ ma27 ];
+  };
+
+  nodes.yabar = {
+    imports = [ ./common/x11.nix ./common/user-account.nix ];
+
+    services.xserver.displayManager.auto.user = "bob";
+
+    programs.yabar.enable = true;
+  };
+
+  testScript = ''
+    $yabar->start;
+    $yabar->waitForX;
+
+    $yabar->waitForUnit("yabar.service", "bob");
+  '';
+})