From 2875d292933fdbd9030caf3e281e10fdeaa9fe3e Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Thu, 7 Aug 2025 19:17:16 -0700 Subject: [PATCH] add testing infra --- .gitignore | 1 + flake.nix | 5 +++ lib.nix | 54 ++++++++++++++++-------------- tests/tests.nix | 9 +++++ tests/zfs.nix | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 .gitignore create mode 100644 tests/tests.nix create mode 100644 tests/zfs.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4a847d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/result diff --git a/flake.nix b/flake.nix index 8c258c3..4e75ea1 100644 --- a/flake.nix +++ b/flake.nix @@ -220,5 +220,10 @@ path = deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.muffin; }; }; + + tests = import ./tests/tests.nix { + inherit pkgs lib; + config = self.nixosConfigurations.muffin.config; + }; }; } diff --git a/lib.nix b/lib.nix index 08df3d1..1437931 100644 --- a/lib.nix +++ b/lib.nix @@ -9,34 +9,38 @@ inputs.nixpkgs.lib.extend ( lib = prev; in { - ensureZfsMounts = - dirs: - pkgs.writeShellApplication { - name = "zfslistmounted"; - runtimeInputs = with pkgs; [ - zfs - gnugrep - gawk - coreutils - ]; + # Should probably be moved to a package later instead of this + ensureZfsMounts = pkgs.writeShellApplication { + name = "zfsEnsureMounted"; + runtimeInputs = with pkgs; [ + zfs + gnugrep + gawk + coreutils + ]; - text = '' - #!/bin/sh + text = '' + #!/bin/sh -x - TARGETS=$(echo "${lib.strings.concatStringsSep "\n" dirs}" | sort | uniq) - MOUNTED=$(zfs list -o mountpoint,mounted -H | awk '$2 == "yes" {print $1}' | sort | uniq) - NUM_MATCHED=$(echo "$MOUNTED" | grep -Ec '${lib.strings.concatStringsSep "\|" dirs}') - if [[ "$NUM_MATCHED" -eq "${toString (lib.length dirs)}" ]]; then - exit 0 - fi + if [[ "$#" -eq "0" ]]; then + echo "no arguments passed" + exit 1 + fi - FOUND=$(printf "%s\n%s" "$TARGETS" "$MOUNTED" | sort | uniq -c | awk '$1 == "2" {print $2}' | sort) - MISSING=$(printf "%s\n%s" "$FOUND" "$TARGETS" | sort | uniq -u | sort) + TARGETS=$(echo "$@" | sort | uniq) + MOUNTED=$(zfs list -o mountpoint,mounted -H | awk '$2 == "yes" {print $1}' | sort | uniq) + NUM_MATCHED=$(echo "$MOUNTED" | grep -Ec "$(echo "$@" | tr ' ' '\|')") # does not properly handle paths with strings + if [[ "$NUM_MATCHED" -eq "$#" ]]; then + exit 0 + fi - echo "FAILURE, missing: $MISSING" 1>&2 - exit 1 - ''; - }; + FOUND=$(printf "%s\n%s" "$TARGETS" "$MOUNTED" | sort | uniq -c | awk '$1 == "2" {print $2}' | sort) + MISSING=$(printf "%s\n%s" "$FOUND" "$TARGETS" | sort | uniq -u | sort) + + echo "FAILURE, missing: $MISSING" 1>&2 + exit 1 + ''; + }; serviceMountDeps = serviceName: dirs: { systemd.services."${serviceName}_mounts" = { @@ -46,7 +50,7 @@ inputs.nixpkgs.lib.extend ( serviceConfig = { Type = "oneshot"; RemainAfterExit = true; - ExecStart = lib.getExe (final.ensureZfsMounts dirs); + ExecStart = "${lib.getExe final.ensureZfsMounts} ${lib.strings.concatStringsSep " " dirs}"; }; }; diff --git a/tests/tests.nix b/tests/tests.nix new file mode 100644 index 0000000..b33fdcd --- /dev/null +++ b/tests/tests.nix @@ -0,0 +1,9 @@ +{ + config, + lib, + pkgs, + ... +}: +{ + zfsTest = import ./zfs.nix { inherit config lib pkgs; }; +} diff --git a/tests/zfs.nix b/tests/zfs.nix new file mode 100644 index 0000000..4ac0fcd --- /dev/null +++ b/tests/zfs.nix @@ -0,0 +1,87 @@ +{ + config, + lib, + pkgs, + ... +}: +pkgs.testers.runNixOSTest { + name = "test of tests"; + + nodes.machine = + { pkgs, ... }: + { + imports = [ + (lib.serviceMountDeps "foobar" [ "/mnt/foobar_data" ]) + (lib.serviceMountDeps "foobarSadge" [ + "/mnt/foobar_data" + "/mnt/does_not_exist_lol" + ]) + + ]; + virtualisation = { + emptyDiskImages = [ + 4096 + ]; + useBootLoader = true; + useEFIBoot = true; + }; + boot.loader.systemd-boot.enable = true; + boot.loader.timeout = 0; + boot.loader.efi.canTouchEfiVariables = true; + networking.hostId = "deadbeef"; + boot.kernelPackages = config.boot.kernelPackages; + boot.zfs.package = config.boot.zfs.package; + boot.supportedFilesystems = [ "zfs" ]; + + environment.systemPackages = [ + pkgs.parted + lib.ensureZfsMounts + ]; + + systemd.services.foobar = { + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${lib.getExe pkgs.bash} -c \"true\""; + }; + }; + + systemd.services.foobarSadge = { + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${lib.getExe pkgs.bash} -c \"true\""; + }; + }; + }; + + testScript = '' + start_all() + machine.wait_for_unit("multi-user.target") + machine.succeed( + "parted --script /dev/vdb mklabel msdos", + "parted --script /dev/vdb -- mkpart primary 1024M -1s", + ) + + machine.fail("zfsEnsureMounted") + machine.fail("zfsEnsureMounted /mnt/test_mountpoint") + + machine.succeed("zpool create rpool /dev/vdb1") + machine.succeed("zfs create -o mountpoint=/mnt/test_mountpoint rpool/test") + + machine.succeed("zfsEnsureMounted /mnt/test_mountpoint") + + machine.fail("zfsEnsureMounted /mnt/does_not_exist_lol") + machine.fail("zfsEnsureMounted /mnt/test_mountpoint /mnt/does_not_exist_lol") + + machine.succeed("zfs create -o mountpoint=/mnt/test_mountpoint_dos rpool/test2") + + machine.succeed("zfsEnsureMounted /mnt/test_mountpoint /mnt/test_mountpoint_dos") + + + machine.succeed("zfs create -o mountpoint=/mnt/foobar_data rpool/foobar") + machine.succeed("systemctl start foobar") + + machine.fail("systemctl start foobarSadge") + ''; +}