diff options
author | Janne Heß <janne@hess.ooo> | 2021-12-09 12:30:48 +0100 |
---|---|---|
committer | Janne Heß <janne@hess.ooo> | 2021-12-09 12:30:48 +0100 |
commit | efcdc01d629b05e52137ecdc288d363ac5cb5128 (patch) | |
tree | 57fa515737ad0ec1cf0fe81808912613680d1811 /nixos | |
parent | 393c72184986e66f2e72cf0d7e6c0476447c10b6 (diff) | |
download | nixpkgs-efcdc01d629b05e52137ecdc288d363ac5cb5128.tar nixpkgs-efcdc01d629b05e52137ecdc288d363ac5cb5128.tar.gz nixpkgs-efcdc01d629b05e52137ecdc288d363ac5cb5128.tar.bz2 nixpkgs-efcdc01d629b05e52137ecdc288d363ac5cb5128.tar.lz nixpkgs-efcdc01d629b05e52137ecdc288d363ac5cb5128.tar.xz nixpkgs-efcdc01d629b05e52137ecdc288d363ac5cb5128.tar.zst nixpkgs-efcdc01d629b05e52137ecdc288d363ac5cb5128.zip |
nixos/switchTest: Massively extend the test
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/tests/switch-test.nix | 301 |
1 files changed, 296 insertions, 5 deletions
diff --git a/nixos/tests/switch-test.nix b/nixos/tests/switch-test.nix index 78adf7ffa7d..daad9134885 100644 --- a/nixos/tests/switch-test.nix +++ b/nixos/tests/switch-test.nix @@ -3,21 +3,138 @@ import ./make-test-python.nix ({ pkgs, ...} : { name = "switch-test"; meta = with pkgs.lib.maintainers; { - maintainers = [ gleber ]; + maintainers = [ gleber das_j ]; }; nodes = { - machine = { ... }: { + machine = { pkgs, lib, ... }: { users.mutableUsers = false; + + specialisation = rec { + simpleService.configuration = { + systemd.services.test = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.coreutils}/bin/true"; + }; + }; + }; + + simpleServiceModified.configuration = { + imports = [ simpleService.configuration ]; + systemd.services.test.serviceConfig.X-Test = true; + }; + + simpleServiceNostop.configuration = { + imports = [ simpleService.configuration ]; + systemd.services.test.stopIfChanged = false; + }; + + simpleServiceReload.configuration = { + imports = [ simpleService.configuration ]; + systemd.services.test = { + reloadIfChanged = true; + serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true"; + }; + }; + + simpleServiceNorestart.configuration = { + imports = [ simpleService.configuration ]; + systemd.services.test.restartIfChanged = false; + }; + + mount.configuration = { + systemd.mounts = [ + { + description = "Testmount"; + what = "tmpfs"; + type = "tmpfs"; + where = "/testmount"; + options = "size=1M"; + wantedBy = [ "local-fs.target" ]; + } + ]; + }; + + mountModified.configuration = { + systemd.mounts = [ + { + description = "Testmount"; + what = "tmpfs"; + type = "tmpfs"; + where = "/testmount"; + options = "size=10M"; + wantedBy = [ "local-fs.target" ]; + } + ]; + }; + + timer.configuration = { + systemd.timers.test-timer = { + wantedBy = [ "timers.target" ]; + timerConfig.OnCalendar = "@1395716396"; # chosen by fair dice roll + }; + systemd.services.test-timer = { + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.coreutils}/bin/true"; + }; + }; + }; + + timerModified.configuration = { + imports = [ timer.configuration ]; + systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00"; + }; + + path.configuration = { + systemd.paths.test-watch = { + wantedBy = [ "paths.target" ]; + pathConfig.PathExists = "/testpath"; + }; + systemd.services.test-watch = { + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.coreutils}/bin/touch /testpath-modified"; + }; + }; + }; + + pathModified.configuration = { + imports = [ path.configuration ]; + systemd.paths.test-watch.pathConfig.PathExists = lib.mkForce "/testpath2"; + }; + + slice.configuration = { + systemd.slices.testslice.sliceConfig.MemoryMax = "1"; # don't allow memory allocation + systemd.services.testservice = { + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.coreutils}/bin/true"; + Slice = "testslice.slice"; + }; + }; + }; + + sliceModified.configuration = { + imports = [ slice.configuration ]; + systemd.slices.testslice.sliceConfig.MemoryMax = lib.mkForce null; + }; + }; }; - other = { ... }: { + + other = { users.mutableUsers = true; }; }; - testScript = {nodes, ...}: let + testScript = { nodes, ... }: let originalSystem = nodes.machine.config.system.build.toplevel; otherSystem = nodes.other.config.system.build.toplevel; + machine = nodes.machine.config.system.build.toplevel; # Ensures failures pass through using pipefail, otherwise failing to # switch-to-configuration is hidden by the success of `tee`. @@ -27,12 +144,186 @@ import ./make-test-python.nix ({ pkgs, ...} : { set -o pipefail exec env -i "$@" | tee /dev/stderr ''; - in '' + in /* python */ '' + def switch_to_specialisation(system, name, action="test"): + if name == "": + stc = f"{system}/bin/switch-to-configuration" + else: + stc = f"{system}/specialisation/{name}/bin/switch-to-configuration" + out = machine.succeed(f"{stc} {action} 2>&1") + assert_lacks(out, "switch-to-configuration line") # Perl warnings + return out + + def assert_contains(haystack, needle): + if needle not in haystack: + print("The haystack that will cause the following exception is:") + print("---") + print(haystack) + print("---") + raise Exception(f"Expected string '{needle}' was not found") + + def assert_lacks(haystack, needle): + if needle in haystack: + print("The haystack that will cause the following exception is:") + print("---") + print(haystack, end="") + print("---") + raise Exception(f"Unexpected string '{needle}' was found") + + machine.succeed( "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test" ) machine.succeed( "${stderrRunner} ${otherSystem}/bin/switch-to-configuration test" ) + + with subtest("services"): + switch_to_specialisation("${machine}", "") + # Nothing happens when nothing is changed + out = switch_to_specialisation("${machine}", "") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "NOT restarting the following changed units:") + assert_lacks(out, "reloading the following units:") + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + + # Start a simple service + out = switch_to_specialisation("${machine}", "simpleService") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "NOT restarting the following changed units:") + assert_contains(out, "reloading the following units: dbus.service\n") # huh + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_contains(out, "the following new units were started: test.service\n") + assert_lacks(out, "as well:") + + # Not changing anything doesn't do anything + out = switch_to_specialisation("${machine}", "simpleService") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "NOT restarting the following changed units:") + assert_lacks(out, "reloading the following units:") + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + + # Restart the simple service + out = switch_to_specialisation("${machine}", "simpleServiceModified") + assert_contains(out, "stopping the following units: test.service\n") + assert_lacks(out, "NOT restarting the following changed units:") + assert_lacks(out, "reloading the following units:") + assert_lacks(out, "\nrestarting the following units:") + assert_contains(out, "\nstarting the following units: test.service\n") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + + # Restart the service with stopIfChanged=false + out = switch_to_specialisation("${machine}", "simpleServiceNostop") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "NOT restarting the following changed units:") + assert_lacks(out, "reloading the following units:") + assert_contains(out, "\nrestarting the following units: test.service\n") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + + # Reload the service with reloadIfChanged=true + out = switch_to_specialisation("${machine}", "simpleServiceReload") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "NOT restarting the following changed units:") + assert_contains(out, "reloading the following units: test.service\n") + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + + # Nothing happens when restartIfChanged=false + out = switch_to_specialisation("${machine}", "simpleServiceNorestart") + assert_lacks(out, "stopping the following units:") + assert_contains(out, "NOT restarting the following changed units: test.service\n") + assert_lacks(out, "reloading the following units:") + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + + # Dry mode shows different messages + out = switch_to_specialisation("${machine}", "simpleService", action="dry-activate") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "NOT restarting the following changed units:") + assert_lacks(out, "reloading the following units:") + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + assert_contains(out, "would start the following units: test.service\n") + + with subtest("mounts"): + switch_to_specialisation("${machine}", "mount") + out = machine.succeed("mount | grep 'on /testmount'") + assert_contains(out, "size=1024k") + out = switch_to_specialisation("${machine}", "mountModified") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "NOT restarting the following changed units:") + assert_contains(out, "reloading the following units: testmount.mount\n") + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + # It changed + out = machine.succeed("mount | grep 'on /testmount'") + assert_contains(out, "size=10240k") + + with subtest("timers"): + switch_to_specialisation("${machine}", "timer") + out = machine.succeed("systemctl show test-timer.timer") + assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC") + out = switch_to_specialisation("${machine}", "timerModified") + assert_lacks(out, "stopping the following units:") + assert_lacks(out, "reloading the following units:") + assert_contains(out, "restarting the following units: test-timer.timer\n") + assert_lacks(out, "\nstarting the following units:") + assert_lacks(out, "the following new units were started:") + assert_lacks(out, "as well:") + # It changed + out = machine.succeed("systemctl show test-timer.timer") + assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00") + + with subtest("paths"): + out = switch_to_specialisation("${machine}", "path") + assert_contains(out, "stopping the following units: test-timer.timer\n") + assert_lacks(out, "NOT restarting the following changed units:") + assert_lacks(out, "reloading the following units:") + assert_lacks(out, "\nrestarting the following units:") + assert_lacks(out, "\nstarting the following units:") + assert_contains(out, "the following new units were started: test-watch.path") + assert_lacks(out, "as well:") + machine.fail("test -f /testpath-modified") + + # touch the file, unit should be triggered + machine.succeed("touch /testpath") + machine.wait_until_succeeds("test -f /testpath-modified") + machine.succeed("rm /testpath /testpath-modified") + switch_to_specialisation("${machine}", "pathModified") + machine.succeed("touch /testpath") + machine.fail("test -f /testpath-modified") + machine.succeed("touch /testpath2") + machine.wait_until_succeeds("test -f /testpath-modified") + + # This test ensures that changes to slice configuration get applied. + # We test this by having a slice that allows no memory allocation at + # all and starting a service within it. If the service crashes, the slice + # is applied and if we modify the slice to allow memory allocation, the + # service should successfully start. + with subtest("slices"): + machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing + out = switch_to_specialisation("${machine}", "slice") + machine.fail("systemctl start testservice.service") + out = switch_to_specialisation("${machine}", "sliceModified") + machine.succeed("systemctl start testservice.service") + machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing ''; }) |