about summary refs log tree commit diff
path: root/nixpkgs/nixos/tests
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2023-10-31 22:19:45 +0100
committerAlyssa Ross <hi@alyssa.is>2023-10-31 22:19:45 +0100
commit78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc (patch)
treefd9cfb92edfaa37c919be8d24063b8a6c6d94c83 /nixpkgs/nixos/tests
parent7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769 (diff)
parent0cbe9f69c234a7700596e943bfae7ef27a31b735 (diff)
downloadnixlib-78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc.tar
nixlib-78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc.tar.gz
nixlib-78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc.tar.bz2
nixlib-78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc.tar.lz
nixlib-78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc.tar.xz
nixlib-78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc.tar.zst
nixlib-78ba0c65b7bf9a64c12ca8c08f2e0220afdc8dbc.zip
Merge commit '0cbe9f69c234a7700596e943bfae7ef27a31b735' into HEAD
Diffstat (limited to 'nixpkgs/nixos/tests')
-rw-r--r--nixpkgs/nixos/tests/activation/nix-channel.nix16
-rw-r--r--nixpkgs/nixos/tests/activation/var.nix18
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix15
-rw-r--r--nixpkgs/nixos/tests/bittorrent.nix2
-rw-r--r--nixpkgs/nixos/tests/c2fmzq.nix75
-rw-r--r--nixpkgs/nixos/tests/containers-imperative.nix4
-rw-r--r--nixpkgs/nixos/tests/goss.nix53
-rw-r--r--nixpkgs/nixos/tests/grafana/provision/default.nix17
-rw-r--r--nixpkgs/nixos/tests/installer-systemd-stage-1.nix8
-rw-r--r--nixpkgs/nixos/tests/installer.nix4
-rw-r--r--nixpkgs/nixos/tests/netdata.nix4
-rw-r--r--nixpkgs/nixos/tests/nextcloud/basic.nix2
-rw-r--r--nixpkgs/nixos/tests/nixos-test-driver/timeout.nix15
-rw-r--r--nixpkgs/nixos/tests/non-switchable-system.nix15
-rw-r--r--nixpkgs/nixos/tests/opensearch.nix11
-rw-r--r--nixpkgs/nixos/tests/openssh.nix31
-rw-r--r--nixpkgs/nixos/tests/restic.nix18
-rw-r--r--nixpkgs/nixos/tests/stunnel.nix13
-rw-r--r--nixpkgs/nixos/tests/systemd-timesyncd.nix13
-rw-r--r--nixpkgs/nixos/tests/tsja.nix32
20 files changed, 322 insertions, 44 deletions
diff --git a/nixpkgs/nixos/tests/activation/nix-channel.nix b/nixpkgs/nixos/tests/activation/nix-channel.nix
new file mode 100644
index 000000000000..8416ff0347ac
--- /dev/null
+++ b/nixpkgs/nixos/tests/activation/nix-channel.nix
@@ -0,0 +1,16 @@
+{ lib, ... }:
+
+{
+
+  name = "activation-nix-channel";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = {
+    nix.channel.enable = true;
+  };
+
+  testScript = ''
+    print(machine.succeed("cat /root/.nix-channels"))
+  '';
+}
diff --git a/nixpkgs/nixos/tests/activation/var.nix b/nixpkgs/nixos/tests/activation/var.nix
new file mode 100644
index 000000000000..1a546a7671c5
--- /dev/null
+++ b/nixpkgs/nixos/tests/activation/var.nix
@@ -0,0 +1,18 @@
+{ lib, ... }:
+
+{
+
+  name = "activation-var";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = { };
+
+  testScript = ''
+    assert machine.succeed("stat -c '%a' /var/tmp") == "1777\n"
+    assert machine.succeed("stat -c '%a' /var/empty") == "555\n"
+    assert machine.succeed("stat -c '%U' /var/empty") == "root\n"
+    assert machine.succeed("stat -c '%G' /var/empty") == "root\n"
+    assert "i" in machine.succeed("lsattr -d /var/empty")
+  '';
+}
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index 3531930d863a..2f6d5a8dae88 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -90,6 +90,14 @@ in {
     lib-extend = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./nixos-test-driver/lib-extend.nix {};
     node-name = runTest ./nixos-test-driver/node-name.nix;
     busybox = runTest ./nixos-test-driver/busybox.nix;
+    driver-timeout = pkgs.runCommand "ensure-timeout-induced-failure" {
+      failed = pkgs.testers.testBuildFailure ((runTest ./nixos-test-driver/timeout.nix).config.rawTestDerivation);
+    } ''
+      grep -F "timeout reached; test terminating" $failed/testBuildFailure.log
+      # The program will always be terminated by SIGTERM (143) if it waits for the deadline thread.
+      [[ 143 = $(cat $failed/testBuildFailure.exit) ]]
+      touch $out
+    '';
   };
 
   # NixOS vm tests and non-vm unit tests
@@ -153,6 +161,7 @@ in {
   budgie = handleTest ./budgie.nix {};
   buildbot = handleTest ./buildbot.nix {};
   buildkite-agents = handleTest ./buildkite-agents.nix {};
+  c2fmzq = handleTest ./c2fmzq.nix {};
   caddy = handleTest ./caddy.nix {};
   cadvisor = handleTestOn ["x86_64-linux"] ./cadvisor.nix {};
   cage = handleTest ./cage.nix {};
@@ -265,6 +274,8 @@ in {
   esphome = handleTest ./esphome.nix {};
   etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; };
   activation = pkgs.callPackage ../modules/system/activation/test.nix { };
+  activation-var = runTest ./activation/var.nix;
+  activation-nix-channel = runTest ./activation/nix-channel.nix;
   etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {};
   etcd-cluster = handleTestOn ["x86_64-linux"] ./etcd-cluster.nix {};
   etebase-server = handleTest ./etebase-server.nix {};
@@ -288,6 +299,7 @@ in {
   firewall-nftables = handleTest ./firewall.nix { nftables = true; };
   fish = handleTest ./fish.nix {};
   flannel = handleTestOn ["x86_64-linux"] ./flannel.nix {};
+  floorp = handleTest ./firefox.nix { firefoxPackage = pkgs.floorp; };
   fluentd = handleTest ./fluentd.nix {};
   fluidd = handleTest ./fluidd.nix {};
   fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {};
@@ -327,6 +339,7 @@ in {
   gollum = handleTest ./gollum.nix {};
   gonic = handleTest ./gonic.nix {};
   google-oslogin = handleTest ./google-oslogin {};
+  goss = handleTest ./goss.nix {};
   gotify-server = handleTest ./gotify-server.nix {};
   gotosocial = runTest ./web-apps/gotosocial.nix;
   grafana = handleTest ./grafana {};
@@ -577,6 +590,7 @@ in {
   node-red = handleTest ./node-red.nix {};
   nomad = handleTest ./nomad.nix {};
   non-default-filesystems = handleTest ./non-default-filesystems.nix {};
+  non-switchable-system = runTest ./non-switchable-system.nix;
   noto-fonts = handleTest ./noto-fonts.nix {};
   noto-fonts-cjk-qt-default-weight = handleTest ./noto-fonts-cjk-qt-default-weight.nix {};
   novacomd = handleTestOn ["x86_64-linux"] ./novacomd.nix {};
@@ -847,6 +861,7 @@ in {
   trezord = handleTest ./trezord.nix {};
   trickster = handleTest ./trickster.nix {};
   trilium-server = handleTestOn ["x86_64-linux"] ./trilium-server.nix {};
+  tsja = handleTest ./tsja.nix {};
   tsm-client-gui = handleTest ./tsm-client-gui.nix {};
   txredisapi = handleTest ./txredisapi.nix {};
   tuptime = handleTest ./tuptime.nix {};
diff --git a/nixpkgs/nixos/tests/bittorrent.nix b/nixpkgs/nixos/tests/bittorrent.nix
index 11420cba9dce..4a73fea6a09d 100644
--- a/nixpkgs/nixos/tests/bittorrent.nix
+++ b/nixpkgs/nixos/tests/bittorrent.nix
@@ -148,7 +148,7 @@ in
       )
 
       # Bring down the initial seeder.
-      # tracker.stop_job("transmission")
+      tracker.stop_job("transmission")
 
       # Now download from the second client.  This can only succeed if
       # the first client created a NAT hole in the router.
diff --git a/nixpkgs/nixos/tests/c2fmzq.nix b/nixpkgs/nixos/tests/c2fmzq.nix
new file mode 100644
index 000000000000..d8ec816c7d29
--- /dev/null
+++ b/nixpkgs/nixos/tests/c2fmzq.nix
@@ -0,0 +1,75 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "c2FmZQ";
+  meta.maintainers = with lib.maintainers; [ hmenke ];
+
+  nodes.machine = {
+    services.c2fmzq-server = {
+      enable = true;
+      port = 8080;
+      passphraseFile = builtins.toFile "pwfile" "hunter2"; # don't do this on real deployments
+      settings = {
+        verbose = 3; # debug
+      };
+    };
+    environment = {
+      sessionVariables = {
+        C2FMZQ_PASSPHRASE = "lol";
+        C2FMZQ_API_SERVER = "http://localhost:8080";
+      };
+      systemPackages = [
+        pkgs.c2fmzq
+        (pkgs.writeScriptBin "c2FmZQ-client-wrapper" ''
+          #!${pkgs.expect}/bin/expect -f
+          spawn c2FmZQ-client {*}$argv
+          expect {
+            "Enter password:" { send "$env(PASSWORD)\r" }
+            "Type YES to confirm:" { send "YES\r" }
+            timeout { exit 1 }
+            eof { exit 0 }
+          }
+          interact
+        '')
+      ];
+    };
+  };
+
+  testScript = { nodes, ... }: ''
+    machine.start()
+    machine.wait_for_unit("c2fmzq-server.service")
+    machine.wait_for_open_port(8080)
+
+    with subtest("Create accounts for alice and bob"):
+        machine.succeed("PASSWORD=foobar c2FmZQ-client-wrapper -- -v 3 create-account alice@example.com")
+        machine.succeed("PASSWORD=fizzbuzz c2FmZQ-client-wrapper -- -v 3 create-account bob@example.com")
+
+    with subtest("Log in as alice"):
+        machine.succeed("PASSWORD=foobar c2FmZQ-client-wrapper -- -v 3 login alice@example.com")
+        msg = machine.succeed("c2FmZQ-client -v 3 status")
+        assert "Logged in as alice@example.com" in msg, f"ERROR: Not logged in as alice:\n{msg}"
+
+    with subtest("Create a new album, upload a file, and delete the uploaded file"):
+        machine.succeed("c2FmZQ-client -v 3 create-album 'Rarest Memes'")
+        machine.succeed("echo 'pls do not steal' > meme.txt")
+        machine.succeed("c2FmZQ-client -v 3 import meme.txt 'Rarest Memes'")
+        machine.succeed("c2FmZQ-client -v 3 sync")
+        machine.succeed("rm meme.txt")
+
+    with subtest("Share the album with bob"):
+        machine.succeed("c2FmZQ-client-wrapper -- -v 3 share 'Rarest Memes' bob@example.com")
+
+    with subtest("Log in as bob"):
+        machine.succeed("PASSWORD=fizzbuzz c2FmZQ-client-wrapper -- -v 3 login bob@example.com")
+        msg = machine.succeed("c2FmZQ-client -v 3 status")
+        assert "Logged in as bob@example.com" in msg, f"ERROR: Not logged in as bob:\n{msg}"
+
+    with subtest("Download the shared file"):
+        machine.succeed("c2FmZQ-client -v 3 download 'shared/Rarest Memes/meme.txt'")
+        machine.succeed("c2FmZQ-client -v 3 export 'shared/Rarest Memes/meme.txt' .")
+        msg = machine.succeed("cat meme.txt")
+        assert "pls do not steal\n" == msg, f"File content is not the same:\n{msg}"
+
+    with subtest("Test that PWA is served"):
+        msg = machine.succeed("curl -sSfL http://localhost:8080")
+        assert "c2FmZQ" in msg, f"Could not find 'c2FmZQ' in the output:\n{msg}"
+  '';
+})
diff --git a/nixpkgs/nixos/tests/containers-imperative.nix b/nixpkgs/nixos/tests/containers-imperative.nix
index 22b664a90e17..18bec1db78e8 100644
--- a/nixpkgs/nixos/tests/containers-imperative.nix
+++ b/nixpkgs/nixos/tests/containers-imperative.nix
@@ -21,9 +21,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
           modules = lib.singleton {
             nixpkgs = { inherit (config.nixpkgs) localSystem; };
 
-            containers.foo.config = {
-              system.stateVersion = "18.03";
-            };
+            containers.foo.config = {};
           };
 
           # The system is inherited from the host above.
diff --git a/nixpkgs/nixos/tests/goss.nix b/nixpkgs/nixos/tests/goss.nix
new file mode 100644
index 000000000000..6b772d19215e
--- /dev/null
+++ b/nixpkgs/nixos/tests/goss.nix
@@ -0,0 +1,53 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "goss";
+  meta.maintainers = [ lib.maintainers.anthonyroussel ];
+
+  nodes.machine = {
+    environment.systemPackages = [ pkgs.jq ];
+
+    services.goss = {
+      enable = true;
+
+      environment = {
+        GOSS_FMT = "json";
+      };
+
+      settings = {
+        addr."tcp://localhost:8080" = {
+          reachable = true;
+          local-address = "127.0.0.1";
+        };
+        command."check-goss-version" = {
+          exec = "${lib.getExe pkgs.goss} --version";
+          exit-status = 0;
+        };
+        dns.localhost.resolvable = true;
+        file."/nix" = {
+          filetype = "directory";
+          exists = true;
+        };
+        group.root.exists = true;
+        kernel-param."kernel.ostype".value = "Linux";
+        service.goss = {
+          enabled = true;
+          running = true;
+        };
+        user.root.exists = true;
+      };
+    };
+  };
+
+  testScript = ''
+    import json
+
+    machine.wait_for_unit("goss.service")
+    machine.wait_for_open_port(8080)
+
+    with subtest("returns health status"):
+      result = json.loads(machine.succeed("curl -sS http://localhost:8080/healthz"))
+
+      assert len(result["results"]) == 10, f".results should be an array of 10 items, was {result['results']!r}"
+      assert result["summary"]["failed-count"] == 0, f".summary.failed-count should be zero, was {result['summary']['failed-count']}"
+      assert result["summary"]["test-count"] == 10, f".summary.test-count should be 10, was {result['summary']['test-count']}"
+    '';
+})
diff --git a/nixpkgs/nixos/tests/grafana/provision/default.nix b/nixpkgs/nixos/tests/grafana/provision/default.nix
index 96378452ade3..d33d16ce1209 100644
--- a/nixpkgs/nixos/tests/grafana/provision/default.nix
+++ b/nixpkgs/nixos/tests/grafana/provision/default.nix
@@ -22,15 +22,14 @@ let
       };
     };
 
-    system.activationScripts.setup-grafana = {
-      deps = [ "users" ];
-      text = ''
-        mkdir -p /var/lib/grafana/dashboards
-        chown -R grafana:grafana /var/lib/grafana
-        chmod 0700 -R /var/lib/grafana/dashboards
-        cp ${pkgs.writeText "test.json" (builtins.readFile ./test_dashboard.json)} /var/lib/grafana/dashboards/
-      '';
-    };
+    systemd.tmpfiles.rules =
+      let
+        dashboard = pkgs.writeText "test.json" (builtins.readFile ./test_dashboard.json);
+      in
+      [
+        "d /var/lib/grafana/dashboards 0700 grafana grafana -"
+        "C+ /var/lib/grafana/dashboards/test.json - - - - ${dashboard}"
+      ];
   };
 
   extraNodeConfs = {
diff --git a/nixpkgs/nixos/tests/installer-systemd-stage-1.nix b/nixpkgs/nixos/tests/installer-systemd-stage-1.nix
index 85155a6c682b..608a21ef6372 100644
--- a/nixpkgs/nixos/tests/installer-systemd-stage-1.nix
+++ b/nixpkgs/nixos/tests/installer-systemd-stage-1.nix
@@ -12,11 +12,11 @@
     btrfsSubvolDefault
     btrfsSubvolEscape
     btrfsSubvols
-    # encryptedFSWithKeyfile
+    encryptedFSWithKeyfile
     # grub1
-    # luksroot
-    # luksroot-format1
-    # luksroot-format2
+    luksroot
+    luksroot-format1
+    luksroot-format2
     # lvm
     separateBoot
     separateBootFat
diff --git a/nixpkgs/nixos/tests/installer.nix b/nixpkgs/nixos/tests/installer.nix
index 9ff1d8f5d039..15ece034898a 100644
--- a/nixpkgs/nixos/tests/installer.nix
+++ b/nixpkgs/nixos/tests/installer.nix
@@ -515,7 +515,7 @@ let
       enableOCR = true;
       preBootCommands = ''
         machine.start()
-        machine.wait_for_text("Passphrase for")
+        machine.wait_for_text("[Pp]assphrase for")
         machine.send_chars("supersecret\n")
       '';
     };
@@ -781,7 +781,7 @@ in {
         encrypted.enable = true;
         encrypted.blkDev = "/dev/vda3";
         encrypted.label = "crypt";
-        encrypted.keyFile = "/mnt-root/keyfile";
+        encrypted.keyFile = "/${if systemdStage1 then "sysroot" else "mnt-root"}/keyfile";
       };
     '';
   };
diff --git a/nixpkgs/nixos/tests/netdata.nix b/nixpkgs/nixos/tests/netdata.nix
index c5f7294f79ab..e3438f63404e 100644
--- a/nixpkgs/nixos/tests/netdata.nix
+++ b/nixpkgs/nixos/tests/netdata.nix
@@ -30,8 +30,8 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     # check if netdata can read disk ops for root owned processes.
     # if > 0, successful. verifies both netdata working and
     # apps.plugin has elevated capabilities.
-    url = "http://localhost:19999/api/v1/data\?chart=users.pwrites"
-    filter = '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0'
+    url = "http://localhost:19999/api/v1/data\?chart=user.root_disk_physical_io"
+    filter = '[.data[range(10)][2]] | add | . < 0'
     cmd = f"curl -s {url} | jq -e '{filter}'"
     netdata.wait_until_succeeds(cmd)
 
diff --git a/nixpkgs/nixos/tests/nextcloud/basic.nix b/nixpkgs/nixos/tests/nextcloud/basic.nix
index b7af6d6d7364..ab1d8353dba0 100644
--- a/nixpkgs/nixos/tests/nextcloud/basic.nix
+++ b/nixpkgs/nixos/tests/nextcloud/basic.nix
@@ -37,8 +37,6 @@ in {
         "d /var/lib/nextcloud-data 0750 nextcloud nginx - -"
       ];
 
-      system.stateVersion = "22.11"; # stateVersion >=21.11 to make sure that we use OpenSSL3
-
       services.nextcloud = {
         enable = true;
         datadir = "/var/lib/nextcloud-data";
diff --git a/nixpkgs/nixos/tests/nixos-test-driver/timeout.nix b/nixpkgs/nixos/tests/nixos-test-driver/timeout.nix
new file mode 100644
index 000000000000..29bd85d2498e
--- /dev/null
+++ b/nixpkgs/nixos/tests/nixos-test-driver/timeout.nix
@@ -0,0 +1,15 @@
+{
+  name = "Test that sleep of 6 seconds fails a timeout of 5 seconds";
+  globalTimeout = 5;
+
+  nodes = {
+    machine = ({ pkgs, ... }: {
+    });
+  };
+
+  testScript = ''
+    start_all()
+    machine.wait_for_unit("multi-user.target")
+    machine.succeed("sleep 6")
+  '';
+}
diff --git a/nixpkgs/nixos/tests/non-switchable-system.nix b/nixpkgs/nixos/tests/non-switchable-system.nix
new file mode 100644
index 000000000000..54bede75453b
--- /dev/null
+++ b/nixpkgs/nixos/tests/non-switchable-system.nix
@@ -0,0 +1,15 @@
+{ lib, ... }:
+
+{
+  name = "non-switchable-system";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = {
+    system.switch.enable = false;
+  };
+
+  testScript = ''
+    machine.succeed("test ! -e /run/current-system/bin/switch-to-configuration")
+  '';
+}
diff --git a/nixpkgs/nixos/tests/opensearch.nix b/nixpkgs/nixos/tests/opensearch.nix
index c0caf950cb9c..2887ac967765 100644
--- a/nixpkgs/nixos/tests/opensearch.nix
+++ b/nixpkgs/nixos/tests/opensearch.nix
@@ -31,14 +31,9 @@ in
       services.opensearch.dataDir = "/var/opensearch_test";
       services.opensearch.user = "open_search";
       services.opensearch.group = "open_search";
-      system.activationScripts.createDirectory = {
-        text = ''
-          mkdir -p "/var/opensearch_test"
-          chown open_search:open_search /var/opensearch_test
-          chmod 0700 /var/opensearch_test
-        '';
-        deps = [ "users" "groups" ];
-      };
+      systemd.tmpfiles.rules = [
+        "d /var/opensearch_test 0700 open_search open_search -"
+      ];
       users = {
         groups.open_search = {};
         users.open_search = {
diff --git a/nixpkgs/nixos/tests/openssh.nix b/nixpkgs/nixos/tests/openssh.nix
index 88d3e54ee76c..881eb9d7d91c 100644
--- a/nixpkgs/nixos/tests/openssh.nix
+++ b/nixpkgs/nixos/tests/openssh.nix
@@ -82,6 +82,19 @@ in {
         };
       };
 
+    server_allowedusers =
+      { ... }:
+
+      {
+        services.openssh = { enable = true; settings.AllowUsers = [ "alice" "bob" ]; };
+        users.groups = { alice = { }; bob = { }; carol = { }; };
+        users.users = {
+          alice = { isNormalUser = true; group = "alice"; openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; };
+          bob = { isNormalUser = true; group = "bob"; openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; };
+          carol = { isNormalUser = true; group = "carol"; openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; };
+        };
+      };
+
     client =
       { ... }: { };
 
@@ -147,5 +160,23 @@ in {
 
     with subtest("match-rules"):
         server_match_rule.succeed("ss -nlt | grep '127.0.0.1:22'")
+
+    with subtest("allowed-users"):
+        client.succeed(
+            "cat ${snakeOilPrivateKey} > privkey.snakeoil"
+        )
+        client.succeed("chmod 600 privkey.snakeoil")
+        client.succeed(
+            "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil alice@server_allowedusers true",
+            timeout=30
+        )
+        client.succeed(
+            "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil bob@server_allowedusers true",
+            timeout=30
+        )
+        client.fail(
+            "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil carol@server_allowedusers true",
+            timeout=30
+        )
   '';
 })
diff --git a/nixpkgs/nixos/tests/restic.nix b/nixpkgs/nixos/tests/restic.nix
index 3b9ea2f85b1e..54fdc1d3995c 100644
--- a/nixpkgs/nixos/tests/restic.nix
+++ b/nixpkgs/nixos/tests/restic.nix
@@ -21,7 +21,10 @@ import ./make-test-python.nix (
       unpackPhase = "true";
       installPhase = ''
         mkdir $out
-        touch $out/some_file
+        echo some_file > $out/some_file
+        echo some_other_file > $out/some_other_file
+        mkdir $out/a_dir
+        echo a_file > $out/a_dir/a_file
       '';
     };
 
@@ -53,9 +56,13 @@ import ./make-test-python.nix (
               initialize = true;
             };
             remote-from-file-backup = {
-              inherit passwordFile paths exclude pruneOpts;
+              inherit passwordFile exclude pruneOpts;
               initialize = true;
               repositoryFile = pkgs.writeText "repositoryFile" remoteFromFileRepository;
+              paths = [ "/opt/a_dir" ];
+              dynamicFilesFrom = ''
+                find /opt -mindepth 1 -maxdepth 1 ! -name a_dir # all files in /opt except for a_dir
+              '';
             };
             rclonebackup = {
               inherit passwordFile paths exclude pruneOpts;
@@ -123,13 +130,18 @@ import ./make-test-python.nix (
           "systemctl start restic-backups-remote-from-file-backup.service",
           'restic-remote-from-file-backup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
 
+          # test that restoring that snapshot produces the same directory
+          "mkdir /tmp/restore-2",
+          "${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} restore latest -t /tmp/restore-2",
+          "diff -ru ${testDir} /tmp/restore-2/opt",
+
           # test that rclonebackup produces a snapshot
           "systemctl start restic-backups-rclonebackup.service",
           'restic-rclonebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
 
           # test that custompackage runs both `restic backup` and `restic check` with reasonable commandlines
           "systemctl start restic-backups-custompackage.service",
-          "grep 'backup.* /opt' /root/fake-restic.log",
+          "grep 'backup' /root/fake-restic.log",
           "grep 'check.* --some-check-option' /root/fake-restic.log",
 
           # test that we can create four snapshots in remotebackup and rclonebackup
diff --git a/nixpkgs/nixos/tests/stunnel.nix b/nixpkgs/nixos/tests/stunnel.nix
index 22c087290fc7..07fba435d4df 100644
--- a/nixpkgs/nixos/tests/stunnel.nix
+++ b/nixpkgs/nixos/tests/stunnel.nix
@@ -17,11 +17,16 @@ let
     };
   };
   makeCert = { config, pkgs, ... }: {
-    system.activationScripts.create-test-cert = stringAfter [ "users" ] ''
-      ${pkgs.openssl}/bin/openssl req -batch -x509 -newkey rsa -nodes -out /test-cert.pem -keyout /test-key.pem -subj /CN=${config.networking.hostName}
-      ( umask 077; cat /test-key.pem /test-cert.pem > /test-key-and-cert.pem )
-      chown stunnel /test-key.pem /test-key-and-cert.pem
+    systemd.services.create-test-cert = {
+      wantedBy = [ "sysinit.target" ];
+      before = [ "sysinit.target" ];
+      unitConfig.DefaultDependencies = false;
+      script = ''
+        ${pkgs.openssl}/bin/openssl req -batch -x509 -newkey rsa -nodes -out /test-cert.pem -keyout /test-key.pem -subj /CN=${config.networking.hostName}
+        ( umask 077; cat /test-key.pem /test-cert.pem > /test-key-and-cert.pem )
+        chown stunnel /test-key.pem /test-key-and-cert.pem
     '';
+    };
   };
   serverCommon = { pkgs, ... }: {
     networking.firewall.allowedTCPPorts = [ 443 ];
diff --git a/nixpkgs/nixos/tests/systemd-timesyncd.nix b/nixpkgs/nixos/tests/systemd-timesyncd.nix
index 43abd36c47d9..f38d06be1516 100644
--- a/nixpkgs/nixos/tests/systemd-timesyncd.nix
+++ b/nixpkgs/nixos/tests/systemd-timesyncd.nix
@@ -15,12 +15,13 @@ in {
       # create the path that should be migrated by our activation script when
       # upgrading to a newer nixos version
       system.stateVersion = "19.03";
-      system.activationScripts.simulate-old-timesync-state-dir = lib.mkBefore ''
-        rm -f /var/lib/systemd/timesync
-        mkdir -p /var/lib/systemd /var/lib/private/systemd/timesync
-        ln -s /var/lib/private/systemd/timesync /var/lib/systemd/timesync
-        chown systemd-timesync: /var/lib/private/systemd/timesync
-      '';
+      systemd.tmpfiles.rules = [
+        "r /var/lib/systemd/timesync -"
+        "d /var/lib/systemd -"
+        "d /var/lib/private/systemd/timesync -"
+        "L /var/lib/systemd/timesync - - - - /var/lib/private/systemd/timesync"
+        "d /var/lib/private/systemd/timesync - systemd-timesync systemd-timesync -"
+      ];
     });
   };
 
diff --git a/nixpkgs/nixos/tests/tsja.nix b/nixpkgs/nixos/tests/tsja.nix
new file mode 100644
index 000000000000..176783088d8d
--- /dev/null
+++ b/nixpkgs/nixos/tests/tsja.nix
@@ -0,0 +1,32 @@
+import ./make-test-python.nix ({ pkgs, lib, ...} : {
+  name = "tsja";
+  meta = {
+    maintainers = with lib.maintainers; [ chayleaf ];
+  };
+
+  nodes = {
+    master =
+      { config, ... }:
+
+      {
+        services.postgresql = {
+          enable = true;
+          extraPlugins = with config.services.postgresql.package.pkgs; [
+            tsja
+          ];
+        };
+      };
+  };
+
+  testScript = ''
+    start_all()
+    master.wait_for_unit("postgresql")
+    master.succeed("sudo -u postgres psql -f /run/current-system/sw/share/postgresql/extension/libtsja_dbinit.sql")
+    # make sure "日本語" is parsed as a separate lexeme
+    master.succeed("""
+      sudo -u postgres \\
+        psql -c "SELECT * FROM ts_debug('japanese', 'PostgreSQLで日本語のテキスト検索ができます。')" \\
+          | grep "{日本語}"
+    """)
+  '';
+})