1 # Test configuration switching.
3 import ./make-test-python.nix ({ pkgs, ...} : let
5 # Simple service that can either be socket-activated or that will
6 # listen on port 1234 if not socket-activated.
7 # A connection to the socket causes 'hello' to be written to the client.
8 socketTest = pkgs.writeScript "socket-test.py" /* python */ ''
9 #!${pkgs.python3}/bin/python3
11 from socketserver import TCPServer, StreamRequestHandler
16 class Handler(StreamRequestHandler):
18 self.wfile.write("hello".encode("utf-8"))
21 class Server(TCPServer):
22 def __init__(self, server_address, handler_cls):
23 listenFds = os.getenv('LISTEN_FDS')
24 if listenFds is None or int(listenFds) < 1:
25 print(f'Binding to {server_address}')
27 self, server_address, handler_cls, bind_and_activate=True)
30 self, server_address, handler_cls, bind_and_activate=False)
32 print(f'Got activated by {os.getenv("LISTEN_FDNAMES")} '
33 f'with {listenFds} FDs')
34 self.socket = socket.fromfd(3, self.address_family,
38 if __name__ == "__main__":
39 server = Server(("localhost", 1234), Handler)
40 server.serve_forever()
45 meta = with pkgs.lib.maintainers; {
46 maintainers = [ gleber das_j ];
50 machine = { pkgs, lib, ... }: {
51 environment.systemPackages = [ pkgs.socat ]; # for the socket activation stuff
52 users.mutableUsers = false;
54 # For boot/switch testing
55 system.build.installBootLoader = lib.mkForce (pkgs.writeShellScript "install-dummy-loader" ''
56 echo "installing dummy bootloader"
57 touch /tmp/bootloader-installed
60 specialisation = rec {
61 simpleService.configuration = {
62 systemd.services.test = {
63 wantedBy = [ "multi-user.target" ];
66 RemainAfterExit = true;
67 ExecStart = "${pkgs.coreutils}/bin/true";
68 ExecReload = "${pkgs.coreutils}/bin/true";
73 simpleServiceDifferentDescription.configuration = {
74 imports = [ simpleService.configuration ];
75 systemd.services.test.description = "Test unit";
78 simpleServiceModified.configuration = {
79 imports = [ simpleService.configuration ];
80 systemd.services.test.serviceConfig.X-Test = true;
83 simpleServiceNostop.configuration = {
84 imports = [ simpleService.configuration ];
85 systemd.services.test.stopIfChanged = false;
88 simpleServiceReload.configuration = {
89 imports = [ simpleService.configuration ];
90 systemd.services.test = {
91 reloadIfChanged = true;
92 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
96 simpleServiceNorestart.configuration = {
97 imports = [ simpleService.configuration ];
98 systemd.services.test.restartIfChanged = false;
101 simpleServiceFailing.configuration = {
102 imports = [ simpleServiceModified.configuration ];
103 systemd.services.test.serviceConfig.ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false";
106 autorestartService.configuration = {
107 # A service that immediately goes into restarting (but without failing)
108 systemd.services.autorestart = {
109 wantedBy = [ "multi-user.target" ];
113 RestartSec = "20y"; # Should be long enough
114 ExecStart = "${pkgs.coreutils}/bin/true";
119 autorestartServiceFailing.configuration = {
120 imports = [ autorestartService.configuration ];
121 systemd.services.autorestart.serviceConfig = {
122 ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false";
126 simpleServiceWithExtraSection.configuration = {
127 imports = [ simpleServiceNostop.configuration ];
128 systemd.packages = [ (pkgs.writeTextFile {
129 name = "systemd-extra-section";
130 destination = "/etc/systemd/system/test.service";
138 simpleServiceWithExtraSectionOtherName.configuration = {
139 imports = [ simpleServiceNostop.configuration ];
140 systemd.packages = [ (pkgs.writeTextFile {
141 name = "systemd-extra-section";
142 destination = "/etc/systemd/system/test.service";
150 simpleServiceWithInstallSection.configuration = {
151 imports = [ simpleServiceNostop.configuration ];
152 systemd.packages = [ (pkgs.writeTextFile {
153 name = "systemd-extra-section";
154 destination = "/etc/systemd/system/test.service";
157 WantedBy=multi-user.target
162 simpleServiceWithExtraKey.configuration = {
163 imports = [ simpleServiceNostop.configuration ];
164 systemd.services.test.serviceConfig."X-Test" = "test";
167 simpleServiceWithExtraKeyOtherValue.configuration = {
168 imports = [ simpleServiceNostop.configuration ];
169 systemd.services.test.serviceConfig."X-Test" = "test2";
172 simpleServiceWithExtraKeyOtherName.configuration = {
173 imports = [ simpleServiceNostop.configuration ];
174 systemd.services.test.serviceConfig."X-Test2" = "test";
177 simpleServiceReloadTrigger.configuration = {
178 imports = [ simpleServiceNostop.configuration ];
179 systemd.services.test.reloadTriggers = [ "/dev/null" ];
182 simpleServiceReloadTriggerModified.configuration = {
183 imports = [ simpleServiceNostop.configuration ];
184 systemd.services.test.reloadTriggers = [ "/dev/zero" ];
187 simpleServiceReloadTriggerModifiedAndSomethingElse.configuration = {
188 imports = [ simpleServiceNostop.configuration ];
189 systemd.services.test = {
190 reloadTriggers = [ "/dev/zero" ];
191 serviceConfig."X-Test" = "test";
195 simpleServiceReloadTriggerModifiedSomethingElse.configuration = {
196 imports = [ simpleServiceNostop.configuration ];
197 systemd.services.test.serviceConfig."X-Test" = "test";
200 unitWithBackslash.configuration = {
201 systemd.services."escaped\\x2ddash" = {
202 wantedBy = [ "multi-user.target" ];
205 RemainAfterExit = true;
206 ExecStart = "${pkgs.coreutils}/bin/true";
207 ExecReload = "${pkgs.coreutils}/bin/true";
212 unitWithBackslashModified.configuration = {
213 imports = [ unitWithBackslash.configuration ];
214 systemd.services."escaped\\x2ddash".serviceConfig.X-Test = "test";
217 unitStartingWithDash.configuration = {
218 systemd.services."-" = {
219 wantedBy = [ "multi-user.target" ];
222 RemainAfterExit = true;
223 ExecStart = "${pkgs.coreutils}/bin/true";
228 unitStartingWithDashModified.configuration = {
229 imports = [ unitStartingWithDash.configuration ];
230 systemd.services."-" = {
231 reloadIfChanged = true;
232 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
236 unitWithRequirement.configuration = {
237 systemd.services.required-service = {
238 wantedBy = [ "multi-user.target" ];
241 RemainAfterExit = true;
242 ExecStart = "${pkgs.coreutils}/bin/true";
243 ExecReload = "${pkgs.coreutils}/bin/true";
246 systemd.services.test-service = {
247 wantedBy = [ "multi-user.target" ];
248 requires = [ "required-service.service" ];
251 RemainAfterExit = true;
252 ExecStart = "${pkgs.coreutils}/bin/true";
253 ExecReload = "${pkgs.coreutils}/bin/true";
258 unitWithRequirementModified.configuration = {
259 imports = [ unitWithRequirement.configuration ];
260 systemd.services.required-service.serviceConfig.X-Test = "test";
261 systemd.services.test-service.reloadTriggers = [ "test" ];
264 unitWithRequirementModifiedNostart.configuration = {
265 imports = [ unitWithRequirement.configuration ];
266 systemd.services.test-service.unitConfig.RefuseManualStart = true;
269 restart-and-reload-by-activation-script.configuration = {
270 systemd.services = rec {
272 # No wantedBy so we can check if the activation script restart triggers them
275 RemainAfterExit = true;
276 ExecStart = "${pkgs.coreutils}/bin/true";
277 ExecReload = "${pkgs.coreutils}/bin/true";
281 simple-restart-service = simple-service // {
282 stopIfChanged = false;
285 simple-reload-service = simple-service // {
286 reloadIfChanged = true;
289 no-restart-service = simple-service // {
290 restartIfChanged = false;
293 reload-triggers = simple-service // {
294 wantedBy = [ "multi-user.target" ];
297 reload-triggers-and-restart-by-as = simple-service;
299 reload-triggers-and-restart = simple-service // {
300 stopIfChanged = false; # easier to check for this
301 wantedBy = [ "multi-user.target" ];
305 system.activationScripts.restart-and-reload-test = {
306 supportsDryActivation = true;
309 if [ "$NIXOS_ACTION" = dry-activate ]; then
310 f=/run/nixos/dry-activation-restart-list
311 g=/run/nixos/dry-activation-reload-list
313 f=/run/nixos/activation-restart-list
314 g=/run/nixos/activation-reload-list
317 simple-service.service
318 simple-restart-service.service
319 simple-reload-service.service
320 no-restart-service.service
321 reload-triggers-and-restart-by-as.service
325 reload-triggers.service
326 reload-triggers-and-restart-by-as.service
327 reload-triggers-and-restart.service
333 restart-and-reload-by-activation-script-modified.configuration = {
334 imports = [ restart-and-reload-by-activation-script.configuration ];
335 systemd.services.reload-triggers-and-restart.serviceConfig.X-Modified = "test";
338 simple-socket.configuration = {
339 systemd.services.socket-activated = {
340 description = "A socket-activated service";
341 stopIfChanged = lib.mkDefault false;
343 ExecStart = socketTest;
344 ExecReload = "${pkgs.coreutils}/bin/true";
347 systemd.sockets.socket-activated = {
348 wantedBy = [ "sockets.target" ];
349 listenStreams = [ "/run/test.sock" ];
350 socketConfig.SocketMode = lib.mkDefault "0777";
354 simple-socket-service-modified.configuration = {
355 imports = [ simple-socket.configuration ];
356 systemd.services.socket-activated.serviceConfig.X-Test = "test";
359 simple-socket-stop-if-changed.configuration = {
360 imports = [ simple-socket.configuration ];
361 systemd.services.socket-activated.stopIfChanged = true;
364 simple-socket-stop-if-changed-and-reloadtrigger.configuration = {
365 imports = [ simple-socket.configuration ];
366 systemd.services.socket-activated = {
367 stopIfChanged = true;
368 reloadTriggers = [ "test" ];
372 mount.configuration = {
375 description = "Testmount";
378 where = "/testmount";
380 wantedBy = [ "local-fs.target" ];
385 mountModified.configuration = {
388 description = "Testmount";
391 where = "/testmount";
392 options = "size=10M";
393 wantedBy = [ "local-fs.target" ];
398 timer.configuration = {
399 systemd.timers.test-timer = {
400 wantedBy = [ "timers.target" ];
401 timerConfig.OnCalendar = "@1395716396"; # chosen by fair dice roll
403 systemd.services.test-timer = {
406 ExecStart = "${pkgs.coreutils}/bin/true";
411 timerModified.configuration = {
412 imports = [ timer.configuration ];
413 systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00";
416 hybridSleepModified.configuration = {
417 systemd.targets.hybrid-sleep.unitConfig.X-Test = true;
420 target.configuration = {
421 systemd.targets.test-target.wantedBy = [ "multi-user.target" ];
422 # We use this service to figure out whether the target was modified.
423 # This is the only way because targets are filtered and therefore not
424 # printed when they are started/stopped.
425 systemd.services.test-service = {
426 bindsTo = [ "test-target.target" ];
427 serviceConfig.ExecStart = "${pkgs.coreutils}/bin/sleep infinity";
431 targetModified.configuration = {
432 imports = [ target.configuration ];
433 systemd.targets.test-target.unitConfig.X-Test = true;
436 targetModifiedStopOnReconfig.configuration = {
437 imports = [ target.configuration ];
438 systemd.targets.test-target.unitConfig.X-StopOnReconfiguration = true;
441 path.configuration = {
442 systemd.paths.test-watch = {
443 wantedBy = [ "paths.target" ];
444 pathConfig.PathExists = "/testpath";
446 systemd.services.test-watch = {
449 RemainAfterExit = true;
450 ExecStart = "${pkgs.coreutils}/bin/touch /testpath-modified";
455 pathModified.configuration = {
456 imports = [ path.configuration ];
457 systemd.paths.test-watch.pathConfig.PathExists = lib.mkForce "/testpath2";
460 slice.configuration = {
461 systemd.slices.testslice.sliceConfig.MemoryMax = "1"; # don't allow memory allocation
462 systemd.services.testservice = {
465 RemainAfterExit = true;
466 ExecStart = "${pkgs.coreutils}/bin/true";
467 Slice = "testslice.slice";
472 sliceModified.configuration = {
473 imports = [ slice.configuration ];
474 systemd.slices.testslice.sliceConfig.MemoryMax = lib.mkForce null;
480 users.mutableUsers = true;
484 testScript = { nodes, ... }: let
485 originalSystem = nodes.machine.config.system.build.toplevel;
486 otherSystem = nodes.other.config.system.build.toplevel;
487 machine = nodes.machine.config.system.build.toplevel;
489 # Ensures failures pass through using pipefail, otherwise failing to
490 # switch-to-configuration is hidden by the success of `tee`.
491 stderrRunner = pkgs.writeScript "stderr-runner" ''
492 #! ${pkgs.runtimeShell}
495 exec env -i "$@" | tee /dev/stderr
498 def switch_to_specialisation(system, name, action="test", fail=False):
500 stc = f"{system}/bin/switch-to-configuration"
502 stc = f"{system}/specialisation/{name}/bin/switch-to-configuration"
503 out = machine.fail(f"{stc} {action} 2>&1") if fail \
504 else machine.succeed(f"{stc} {action} 2>&1")
505 assert_lacks(out, "switch-to-configuration line") # Perl warnings
508 def assert_contains(haystack, needle):
509 if needle not in haystack:
510 print("The haystack that will cause the following exception is:")
514 raise Exception(f"Expected string '{needle}' was not found")
516 def assert_lacks(haystack, needle):
517 if needle in haystack:
518 print("The haystack that will cause the following exception is:")
520 print(haystack, end="")
522 raise Exception(f"Unexpected string '{needle}' was found")
525 machine.wait_for_unit("multi-user.target")
528 "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test"
530 # This tests whether the /etc/os-release parser works which is a fallback
531 # when /etc/NIXOS is missing. If the parser does not work, switch-to-configuration
533 machine.succeed("rm /etc/NIXOS")
535 "${stderrRunner} ${otherSystem}/bin/switch-to-configuration test"
539 with subtest("actions"):
541 machine.fail("test -f /tmp/bootloader-installed")
542 out = switch_to_specialisation("${machine}", "simpleService", action="boot")
543 assert_contains(out, "installing dummy bootloader")
544 assert_lacks(out, "activating the configuration...") # good indicator of a system activation
545 machine.succeed("test -f /tmp/bootloader-installed")
546 machine.succeed("rm /tmp/bootloader-installed")
549 machine.fail("test -f /tmp/bootloader-installed")
550 out = switch_to_specialisation("${machine}", "", action="switch")
551 assert_contains(out, "installing dummy bootloader")
552 assert_contains(out, "activating the configuration...") # good indicator of a system activation
553 machine.succeed("test -f /tmp/bootloader-installed")
555 # test and dry-activate actions are tested further down below
557 with subtest("services"):
558 switch_to_specialisation("${machine}", "")
559 # Nothing happens when nothing is changed
560 out = switch_to_specialisation("${machine}", "")
561 assert_lacks(out, "stopping the following units:")
562 assert_lacks(out, "NOT restarting the following changed units:")
563 assert_lacks(out, "reloading the following units:")
564 assert_lacks(out, "\nrestarting the following units:")
565 assert_lacks(out, "\nstarting the following units:")
566 assert_lacks(out, "the following new units were started:")
568 # Start a simple service
569 out = switch_to_specialisation("${machine}", "simpleService")
570 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader
571 assert_lacks(out, "stopping the following units:")
572 assert_lacks(out, "NOT restarting the following changed units:")
573 assert_contains(out, "reloading the following units: dbus.service\n") # huh
574 assert_lacks(out, "\nrestarting the following units:")
575 assert_lacks(out, "\nstarting the following units:")
576 assert_contains(out, "the following new units were started: test.service\n")
578 # Not changing anything doesn't do anything
579 out = switch_to_specialisation("${machine}", "simpleService")
580 assert_lacks(out, "stopping the following units:")
581 assert_lacks(out, "NOT restarting the following changed units:")
582 assert_lacks(out, "reloading the following units:")
583 assert_lacks(out, "\nrestarting the following units:")
584 assert_lacks(out, "\nstarting the following units:")
585 assert_lacks(out, "the following new units were started:")
587 # Only changing the description does nothing
588 out = switch_to_specialisation("${machine}", "simpleServiceDifferentDescription")
589 assert_lacks(out, "stopping the following units:")
590 assert_lacks(out, "NOT restarting the following changed units:")
591 assert_lacks(out, "reloading the following units:")
592 assert_lacks(out, "\nrestarting the following units:")
593 assert_lacks(out, "\nstarting the following units:")
594 assert_lacks(out, "the following new units were started:")
596 # Restart the simple service
597 out = switch_to_specialisation("${machine}", "simpleServiceModified")
598 assert_contains(out, "stopping the following units: test.service\n")
599 assert_lacks(out, "NOT restarting the following changed units:")
600 assert_lacks(out, "reloading the following units:")
601 assert_lacks(out, "\nrestarting the following units:")
602 assert_contains(out, "\nstarting the following units: test.service\n")
603 assert_lacks(out, "the following new units were started:")
605 # Restart the service with stopIfChanged=false
606 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
607 assert_lacks(out, "stopping the following units:")
608 assert_lacks(out, "NOT restarting the following changed units:")
609 assert_lacks(out, "reloading the following units:")
610 assert_contains(out, "\nrestarting the following units: test.service\n")
611 assert_lacks(out, "\nstarting the following units:")
612 assert_lacks(out, "the following new units were started:")
614 # Reload the service with reloadIfChanged=true
615 out = switch_to_specialisation("${machine}", "simpleServiceReload")
616 assert_lacks(out, "stopping the following units:")
617 assert_lacks(out, "NOT restarting the following changed units:")
618 assert_contains(out, "reloading the following units: test.service\n")
619 assert_lacks(out, "\nrestarting the following units:")
620 assert_lacks(out, "\nstarting the following units:")
621 assert_lacks(out, "the following new units were started:")
623 # Nothing happens when restartIfChanged=false
624 out = switch_to_specialisation("${machine}", "simpleServiceNorestart")
625 assert_lacks(out, "stopping the following units:")
626 assert_contains(out, "NOT restarting the following changed units: test.service\n")
627 assert_lacks(out, "reloading the following units:")
628 assert_lacks(out, "\nrestarting the following units:")
629 assert_lacks(out, "\nstarting the following units:")
630 assert_lacks(out, "the following new units were started:")
632 # Dry mode shows different messages
633 out = switch_to_specialisation("${machine}", "simpleService", action="dry-activate")
634 assert_lacks(out, "stopping the following units:")
635 assert_lacks(out, "NOT restarting the following changed units:")
636 assert_lacks(out, "reloading the following units:")
637 assert_lacks(out, "\nrestarting the following units:")
638 assert_lacks(out, "\nstarting the following units:")
639 assert_lacks(out, "the following new units were started:")
640 assert_contains(out, "would start the following units: test.service\n")
642 # Ensure \ works in unit names
643 out = switch_to_specialisation("${machine}", "unitWithBackslash")
644 assert_contains(out, "stopping the following units: test.service\n")
645 assert_lacks(out, "NOT restarting the following changed units:")
646 assert_lacks(out, "reloading the following units:")
647 assert_lacks(out, "\nrestarting the following units:")
648 assert_lacks(out, "\nstarting the following units:")
649 assert_contains(out, "the following new units were started: escaped\\x2ddash.service\n")
651 out = switch_to_specialisation("${machine}", "unitWithBackslashModified")
652 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
653 assert_lacks(out, "NOT restarting the following changed units:")
654 assert_lacks(out, "reloading the following units:")
655 assert_lacks(out, "\nrestarting the following units:")
656 assert_contains(out, "\nstarting the following units: escaped\\x2ddash.service\n")
657 assert_lacks(out, "the following new units were started:")
659 # Ensure units can start with a dash
660 out = switch_to_specialisation("${machine}", "unitStartingWithDash")
661 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
662 assert_lacks(out, "NOT restarting the following changed units:")
663 assert_lacks(out, "reloading the following units:")
664 assert_lacks(out, "\nrestarting the following units:")
665 assert_lacks(out, "\nstarting the following units:")
666 assert_contains(out, "the following new units were started: -.service\n")
668 # The regression only occurs when reloading units
669 out = switch_to_specialisation("${machine}", "unitStartingWithDashModified")
670 assert_lacks(out, "stopping the following units:")
671 assert_lacks(out, "NOT restarting the following changed units:")
672 assert_contains(out, "reloading the following units: -.service")
673 assert_lacks(out, "\nrestarting the following units:")
674 assert_lacks(out, "\nstarting the following units:")
675 assert_lacks(out, "the following new units were started:")
677 # Ensure units that require changed units are properly reloaded
678 out = switch_to_specialisation("${machine}", "unitWithRequirement")
679 assert_contains(out, "stopping the following units: -.service\n")
680 assert_lacks(out, "NOT restarting the following changed units:")
681 assert_lacks(out, "reloading the following units:")
682 assert_lacks(out, "\nrestarting the following units:")
683 assert_lacks(out, "\nstarting the following units:")
684 assert_contains(out, "the following new units were started: required-service.service, test-service.service\n")
686 out = switch_to_specialisation("${machine}", "unitWithRequirementModified")
687 assert_contains(out, "stopping the following units: required-service.service\n")
688 assert_lacks(out, "NOT restarting the following changed units:")
689 assert_lacks(out, "reloading the following units:")
690 assert_lacks(out, "\nrestarting the following units:")
691 assert_contains(out, "\nstarting the following units: required-service.service, test-service.service\n")
692 assert_lacks(out, "the following new units were started:")
694 # Unless the unit asks to be not restarted
695 out = switch_to_specialisation("${machine}", "unitWithRequirementModifiedNostart")
696 assert_contains(out, "stopping the following units: required-service.service\n")
697 assert_lacks(out, "NOT restarting the following changed units:")
698 assert_lacks(out, "reloading the following units:")
699 assert_lacks(out, "\nrestarting the following units:")
700 assert_contains(out, "\nstarting the following units: required-service.service\n")
701 assert_lacks(out, "the following new units were started:")
703 with subtest("failing units"):
704 # Let the simple service fail
705 switch_to_specialisation("${machine}", "simpleServiceModified")
706 out = switch_to_specialisation("${machine}", "simpleServiceFailing", fail=True)
707 assert_contains(out, "stopping the following units: test.service\n")
708 assert_lacks(out, "NOT restarting the following changed units:")
709 assert_lacks(out, "reloading the following units:")
710 assert_lacks(out, "\nrestarting the following units:")
711 assert_contains(out, "\nstarting the following units: test.service\n")
712 assert_lacks(out, "the following new units were started:")
713 assert_contains(out, "warning: the following units failed: test.service\n")
714 assert_contains(out, "Main PID:") # output of systemctl
716 # A unit that gets into autorestart without failing is not treated as failed
717 out = switch_to_specialisation("${machine}", "autorestartService")
718 assert_lacks(out, "stopping the following units:")
719 assert_lacks(out, "NOT restarting the following changed units:")
720 assert_lacks(out, "reloading the following units:")
721 assert_lacks(out, "\nrestarting the following units:")
722 assert_lacks(out, "\nstarting the following units:")
723 assert_contains(out, "the following new units were started: autorestart.service\n")
724 machine.systemctl('stop autorestart.service') # cancel the 20y timer
726 # Switching to the same system should do nothing (especially not treat the unit as failed)
727 out = switch_to_specialisation("${machine}", "autorestartService")
728 assert_lacks(out, "stopping the following units:")
729 assert_lacks(out, "NOT restarting the following changed units:")
730 assert_lacks(out, "reloading the following units:")
731 assert_lacks(out, "\nrestarting the following units:")
732 assert_lacks(out, "\nstarting the following units:")
733 assert_contains(out, "the following new units were started: autorestart.service\n")
734 machine.systemctl('stop autorestart.service') # cancel the 20y timer
736 # If systemd thinks the unit has failed and is in autorestart, we should show it as failed
737 out = switch_to_specialisation("${machine}", "autorestartServiceFailing", fail=True)
738 assert_lacks(out, "stopping the following units:")
739 assert_lacks(out, "NOT restarting the following changed units:")
740 assert_lacks(out, "reloading the following units:")
741 assert_lacks(out, "\nrestarting the following units:")
742 assert_lacks(out, "\nstarting the following units:")
743 assert_lacks(out, "the following new units were started:")
744 assert_contains(out, "warning: the following units failed: autorestart.service\n")
745 assert_contains(out, "Main PID:") # output of systemctl
747 with subtest("unit file parser"):
748 # Switch to a well-known state
749 switch_to_specialisation("${machine}", "simpleServiceNostop")
752 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSection")
753 assert_lacks(out, "stopping the following units:")
754 assert_lacks(out, "NOT restarting the following changed units:")
755 assert_lacks(out, "reloading the following units:")
756 assert_contains(out, "\nrestarting the following units: test.service\n")
757 assert_lacks(out, "\nstarting the following units:")
758 assert_lacks(out, "the following new units were started:")
761 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSectionOtherName")
762 assert_lacks(out, "stopping the following units:")
763 assert_lacks(out, "NOT restarting the following changed units:")
764 assert_lacks(out, "reloading the following units:")
765 assert_contains(out, "\nrestarting the following units: test.service\n")
766 assert_lacks(out, "\nstarting the following units:")
767 assert_lacks(out, "the following new units were started:")
770 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
771 assert_lacks(out, "stopping the following units:")
772 assert_lacks(out, "NOT restarting the following changed units:")
773 assert_lacks(out, "reloading the following units:")
774 assert_contains(out, "\nrestarting the following units: test.service\n")
775 assert_lacks(out, "\nstarting the following units:")
776 assert_lacks(out, "the following new units were started:")
778 # [Install] section is ignored
779 out = switch_to_specialisation("${machine}", "simpleServiceWithInstallSection")
780 assert_lacks(out, "stopping the following units:")
781 assert_lacks(out, "NOT restarting the following changed units:")
782 assert_lacks(out, "reloading the following units:")
783 assert_lacks(out, "\nrestarting the following units:")
784 assert_lacks(out, "\nstarting the following units:")
785 assert_lacks(out, "the following new units were started:")
788 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKey")
789 assert_lacks(out, "stopping the following units:")
790 assert_lacks(out, "NOT restarting the following changed units:")
791 assert_lacks(out, "reloading the following units:")
792 assert_contains(out, "\nrestarting the following units: test.service\n")
793 assert_lacks(out, "\nstarting the following units:")
794 assert_lacks(out, "the following new units were started:")
797 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherValue")
798 assert_lacks(out, "stopping the following units:")
799 assert_lacks(out, "NOT restarting the following changed units:")
800 assert_lacks(out, "reloading the following units:")
801 assert_contains(out, "\nrestarting the following units: test.service\n")
802 assert_lacks(out, "\nstarting the following units:")
803 assert_lacks(out, "the following new units were started:")
806 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherName")
807 assert_lacks(out, "stopping the following units:")
808 assert_lacks(out, "NOT restarting the following changed units:")
809 assert_lacks(out, "reloading the following units:")
810 assert_contains(out, "\nrestarting the following units: test.service\n")
811 assert_lacks(out, "\nstarting the following units:")
812 assert_lacks(out, "the following new units were started:")
815 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
816 assert_lacks(out, "stopping the following units:")
817 assert_lacks(out, "NOT restarting the following changed units:")
818 assert_lacks(out, "reloading the following units:")
819 assert_contains(out, "\nrestarting the following units: test.service\n")
820 assert_lacks(out, "\nstarting the following units:")
821 assert_lacks(out, "the following new units were started:")
823 # Add a reload trigger
824 out = switch_to_specialisation("${machine}", "simpleServiceReloadTrigger")
825 assert_lacks(out, "stopping the following units:")
826 assert_lacks(out, "NOT restarting the following changed units:")
827 assert_contains(out, "reloading the following units: test.service\n")
828 assert_lacks(out, "\nrestarting the following units:")
829 assert_lacks(out, "\nstarting the following units:")
830 assert_lacks(out, "the following new units were started:")
832 # Modify the reload trigger
833 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModified")
834 assert_lacks(out, "stopping the following units:")
835 assert_lacks(out, "NOT restarting the following changed units:")
836 assert_contains(out, "reloading the following units: test.service\n")
837 assert_lacks(out, "\nrestarting the following units:")
838 assert_lacks(out, "\nstarting the following units:")
839 assert_lacks(out, "the following new units were started:")
841 # Modify the reload trigger and something else
842 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedAndSomethingElse")
843 assert_lacks(out, "stopping the following units:")
844 assert_lacks(out, "NOT restarting the following changed units:")
845 assert_lacks(out, "reloading the following units:")
846 assert_contains(out, "\nrestarting the following units: test.service\n")
847 assert_lacks(out, "\nstarting the following units:")
848 assert_lacks(out, "the following new units were started:")
850 # Remove the reload trigger
851 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedSomethingElse")
852 assert_lacks(out, "stopping the following units:")
853 assert_lacks(out, "NOT restarting the following changed units:")
854 assert_lacks(out, "reloading the following units:")
855 assert_lacks(out, "\nrestarting the following units:")
856 assert_lacks(out, "\nstarting the following units:")
857 assert_lacks(out, "the following new units were started:")
859 with subtest("restart and reload by activation script"):
860 switch_to_specialisation("${machine}", "simpleServiceNorestart")
861 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
862 assert_contains(out, "stopping the following units: test.service\n")
863 assert_lacks(out, "NOT restarting the following changed units:")
864 assert_lacks(out, "reloading the following units:")
865 assert_lacks(out, "restarting the following units:")
866 assert_contains(out, "\nstarting the following units: no-restart-service.service, reload-triggers-and-restart-by-as.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n")
867 assert_contains(out, "the following new units were started: no-restart-service.service, reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, reload-triggers.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n")
868 # Switch to the same system where the example services get restarted
869 # and reloaded by the activation script
870 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
871 assert_lacks(out, "stopping the following units:")
872 assert_lacks(out, "NOT restarting the following changed units:")
873 assert_contains(out, "reloading the following units: reload-triggers-and-restart.service, reload-triggers.service, simple-reload-service.service\n")
874 assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, simple-restart-service.service, simple-service.service\n")
875 assert_lacks(out, "\nstarting the following units:")
876 assert_lacks(out, "the following new units were started:")
877 # Switch to the same system and see if the service gets restarted when it's modified
878 # while the fact that it's supposed to be reloaded by the activation script is ignored.
879 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified")
880 assert_lacks(out, "stopping the following units:")
881 assert_lacks(out, "NOT restarting the following changed units:")
882 assert_contains(out, "reloading the following units: reload-triggers.service, simple-reload-service.service\n")
883 assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n")
884 assert_lacks(out, "\nstarting the following units:")
885 assert_lacks(out, "the following new units were started:")
886 # The same, but in dry mode
887 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate")
888 assert_lacks(out, "would stop the following units:")
889 assert_lacks(out, "would NOT stop the following changed units:")
890 assert_contains(out, "would reload the following units: reload-triggers.service, simple-reload-service.service\n")
891 assert_contains(out, "would restart the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n")
892 assert_lacks(out, "\nwould start the following units:")
894 with subtest("socket-activated services"):
895 # Socket-activated services don't get started, just the socket
896 machine.fail("[ -S /run/test.sock ]")
897 out = switch_to_specialisation("${machine}", "simple-socket")
898 # assert_lacks(out, "stopping the following units:") not relevant
899 assert_lacks(out, "NOT restarting the following changed units:")
900 assert_lacks(out, "reloading the following units:")
901 assert_lacks(out, "\nrestarting the following units:")
902 assert_lacks(out, "\nstarting the following units:")
903 assert_contains(out, "the following new units were started: socket-activated.socket\n")
904 machine.succeed("[ -S /run/test.sock ]")
906 # Changing a non-activated service does nothing
907 out = switch_to_specialisation("${machine}", "simple-socket-service-modified")
908 assert_lacks(out, "stopping the following units:")
909 assert_lacks(out, "NOT restarting the following changed units:")
910 assert_lacks(out, "reloading the following units:")
911 assert_lacks(out, "\nrestarting the following units:")
912 assert_lacks(out, "\nstarting the following units:")
913 assert_lacks(out, "the following new units were started:")
914 machine.succeed("[ -S /run/test.sock ]")
915 # The unit is properly activated when the socket is accessed
916 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
917 raise Exception("Socket was not properly activated") # idk how that would happen tbh
919 # Changing an activated service with stopIfChanged=false restarts the service
920 out = switch_to_specialisation("${machine}", "simple-socket")
921 assert_lacks(out, "stopping the following units:")
922 assert_lacks(out, "NOT restarting the following changed units:")
923 assert_lacks(out, "reloading the following units:")
924 assert_contains(out, "\nrestarting the following units: socket-activated.service\n")
925 assert_lacks(out, "\nstarting the following units:")
926 assert_lacks(out, "the following new units were started:")
927 machine.succeed("[ -S /run/test.sock ]")
928 # Socket-activation of the unit still works
929 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
930 raise Exception("Socket was not properly activated after the service was restarted")
932 # Changing an activated service with stopIfChanged=true stops the service and
933 # socket and starts the socket
934 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed")
935 assert_contains(out, "stopping the following units: socket-activated.service, socket-activated.socket\n")
936 assert_lacks(out, "NOT restarting the following changed units:")
937 assert_lacks(out, "reloading the following units:")
938 assert_lacks(out, "\nrestarting the following units:")
939 assert_contains(out, "\nstarting the following units: socket-activated.socket\n")
940 assert_lacks(out, "the following new units were started:")
941 machine.succeed("[ -S /run/test.sock ]")
942 # Socket-activation of the unit still works
943 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
944 raise Exception("Socket was not properly activated after the service was restarted")
946 # Changing a reload trigger of a socket-activated unit only reloads it
947 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed-and-reloadtrigger")
948 assert_lacks(out, "stopping the following units:")
949 assert_lacks(out, "NOT restarting the following changed units:")
950 assert_contains(out, "reloading the following units: socket-activated.service\n")
951 assert_lacks(out, "\nrestarting the following units:")
952 assert_lacks(out, "\nstarting the following units: socket-activated.socket")
953 assert_lacks(out, "the following new units were started:")
954 machine.succeed("[ -S /run/test.sock ]")
955 # Socket-activation of the unit still works
956 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
957 raise Exception("Socket was not properly activated after the service was restarted")
959 with subtest("mounts"):
960 switch_to_specialisation("${machine}", "mount")
961 out = machine.succeed("mount | grep 'on /testmount'")
962 assert_contains(out, "size=1024k")
963 out = switch_to_specialisation("${machine}", "mountModified")
964 assert_lacks(out, "stopping the following units:")
965 assert_lacks(out, "NOT restarting the following changed units:")
966 assert_contains(out, "reloading the following units: testmount.mount\n")
967 assert_lacks(out, "\nrestarting the following units:")
968 assert_lacks(out, "\nstarting the following units:")
969 assert_lacks(out, "the following new units were started:")
971 out = machine.succeed("mount | grep 'on /testmount'")
972 assert_contains(out, "size=10240k")
974 with subtest("timers"):
975 switch_to_specialisation("${machine}", "timer")
976 out = machine.succeed("systemctl show test-timer.timer")
977 assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC")
978 out = switch_to_specialisation("${machine}", "timerModified")
979 assert_lacks(out, "stopping the following units:")
980 assert_lacks(out, "NOT restarting the following units:")
981 assert_lacks(out, "reloading the following units:")
982 assert_contains(out, "\nrestarting the following units: test-timer.timer\n")
983 assert_lacks(out, "\nstarting the following units:")
984 assert_lacks(out, "the following new units were started:")
986 out = machine.succeed("systemctl show test-timer.timer")
987 assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00")
989 with subtest("targets"):
990 # Modifying some special targets like hybrid-sleep.target does nothing
991 out = switch_to_specialisation("${machine}", "hybridSleepModified")
992 assert_contains(out, "stopping the following units: test-timer.timer\n")
993 assert_lacks(out, "NOT restarting the following changed units:")
994 assert_lacks(out, "reloading the following units:")
995 assert_lacks(out, "\nrestarting the following units:")
996 assert_lacks(out, "\nstarting the following units:")
997 assert_lacks(out, "the following new units were started:")
999 # Adding a new target starts it
1000 out = switch_to_specialisation("${machine}", "target")
1001 assert_lacks(out, "stopping the following units:")
1002 assert_lacks(out, "NOT restarting the following changed units:")
1003 assert_lacks(out, "reloading the following units:")
1004 assert_lacks(out, "\nrestarting the following units:")
1005 assert_lacks(out, "\nstarting the following units:")
1006 assert_contains(out, "the following new units were started: test-target.target\n")
1008 # Changing a target doesn't print anything because the unit is filtered
1009 machine.systemctl("start test-service.service")
1010 out = switch_to_specialisation("${machine}", "targetModified")
1011 assert_lacks(out, "stopping the following units:")
1012 assert_lacks(out, "NOT restarting the following changed units:")
1013 assert_lacks(out, "reloading the following units:")
1014 assert_lacks(out, "\nrestarting the following units:")
1015 assert_lacks(out, "\nstarting the following units:")
1016 assert_lacks(out, "the following new units were started:")
1017 machine.succeed("systemctl is-active test-service.service") # target was not restarted
1019 # With X-StopOnReconfiguration, the target gets stopped and started
1020 out = switch_to_specialisation("${machine}", "targetModifiedStopOnReconfig")
1021 assert_lacks(out, "stopping the following units:")
1022 assert_lacks(out, "NOT restarting the following changed units:")
1023 assert_lacks(out, "reloading the following units:")
1024 assert_lacks(out, "\nrestarting the following units:")
1025 assert_lacks(out, "\nstarting the following units:")
1026 assert_lacks(out, "the following new units were started:")
1027 machine.fail("systemctl is-active test-service.servce") # target was restarted
1029 # Remove the target by switching to the old specialisation
1030 out = switch_to_specialisation("${machine}", "timerModified")
1031 assert_contains(out, "stopping the following units: test-target.target\n")
1032 assert_lacks(out, "NOT restarting the following changed units:")
1033 assert_lacks(out, "reloading the following units:")
1034 assert_lacks(out, "\nrestarting the following units:")
1035 assert_lacks(out, "\nstarting the following units:")
1036 assert_contains(out, "the following new units were started: test-timer.timer\n")
1038 with subtest("paths"):
1039 out = switch_to_specialisation("${machine}", "path")
1040 assert_contains(out, "stopping the following units: test-timer.timer\n")
1041 assert_lacks(out, "NOT restarting the following changed units:")
1042 assert_lacks(out, "reloading the following units:")
1043 assert_lacks(out, "\nrestarting the following units:")
1044 assert_lacks(out, "\nstarting the following units:")
1045 assert_contains(out, "the following new units were started: test-watch.path\n")
1046 machine.fail("test -f /testpath-modified")
1048 # touch the file, unit should be triggered
1049 machine.succeed("touch /testpath")
1050 machine.wait_until_succeeds("test -f /testpath-modified")
1051 machine.succeed("rm /testpath /testpath-modified")
1052 machine.systemctl("stop test-watch.service")
1053 switch_to_specialisation("${machine}", "pathModified")
1054 machine.succeed("touch /testpath")
1055 machine.fail("test -f /testpath-modified")
1056 machine.succeed("touch /testpath2")
1057 machine.wait_until_succeeds("test -f /testpath-modified")
1059 # This test ensures that changes to slice configuration get applied.
1060 # We test this by having a slice that allows no memory allocation at
1061 # all and starting a service within it. If the service crashes, the slice
1062 # is applied and if we modify the slice to allow memory allocation, the
1063 # service should successfully start.
1064 with subtest("slices"):
1065 machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing
1066 out = switch_to_specialisation("${machine}", "slice")
1067 # assert_lacks(out, "stopping the following units:") not relevant
1068 assert_lacks(out, "NOT restarting the following changed units:")
1069 assert_lacks(out, "reloading the following units:")
1070 assert_lacks(out, "\nrestarting the following units:")
1071 assert_lacks(out, "\nstarting the following units:")
1072 assert_lacks(out, "the following new units were started:")
1073 machine.fail("systemctl start testservice.service")
1075 out = switch_to_specialisation("${machine}", "sliceModified")
1076 assert_lacks(out, "stopping the following units:")
1077 assert_lacks(out, "NOT restarting the following changed units:")
1078 assert_lacks(out, "reloading the following units:")
1079 assert_lacks(out, "\nrestarting the following units:")
1080 assert_lacks(out, "\nstarting the following units:")
1081 assert_lacks(out, "the following new units were started:")
1082 machine.succeed("systemctl start testservice.service")
1083 machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing