1 # Test configuration switching.
3 import ./make-test-python.nix ({ lib, pkgs, ng, ...} : 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 system.switch.enableNg = ng;
53 environment.systemPackages = [ pkgs.socat ]; # for the socket activation stuff
54 users.mutableUsers = false;
56 # For boot/switch testing
57 system.build.installBootLoader = lib.mkForce (pkgs.writeShellScript "install-dummy-loader" ''
58 echo "installing dummy bootloader"
59 touch /tmp/bootloader-installed
62 specialisation = rec {
63 brokenInitInterface.configuration.config.system.extraSystemBuilderCmds = ''
64 echo "systemd 0" > $out/init-interface-version
67 modifiedSystemConf.configuration.systemd.extraConfig = ''
71 addedMount.configuration.virtualisation.fileSystems."/test" = {
76 addedMountOptsModified.configuration = {
77 imports = [ addedMount.configuration ];
78 virtualisation.fileSystems."/test".options = [ "x-test" ];
81 addedMountDevModified.configuration = {
82 imports = [ addedMountOptsModified.configuration ];
83 virtualisation.fileSystems."/test".device = lib.mkForce "ramfs";
86 storeMountModified.configuration = {
87 virtualisation.fileSystems."/".device = lib.mkForce "auto";
90 swap.configuration.swapDevices = lib.mkVMOverride [
91 { device = "/swapfile"; size = 1; }
94 simpleService.configuration = {
95 systemd.services.test = {
96 wantedBy = [ "multi-user.target" ];
99 RemainAfterExit = true;
100 ExecStart = "${pkgs.coreutils}/bin/true";
101 ExecReload = "${pkgs.coreutils}/bin/true";
106 simpleServiceSeparateActivationScript.configuration = {
107 system.activatable = false;
108 systemd.services.test = {
109 wantedBy = [ "multi-user.target" ];
112 RemainAfterExit = true;
113 ExecStart = "${pkgs.coreutils}/bin/true";
114 ExecReload = "${pkgs.coreutils}/bin/true";
119 simpleServiceDifferentDescription.configuration = {
120 imports = [ simpleService.configuration ];
121 systemd.services.test.description = "Test unit";
124 simpleServiceModified.configuration = {
125 imports = [ simpleService.configuration ];
126 systemd.services.test.serviceConfig.X-Test = true;
129 simpleServiceNostop.configuration = {
130 imports = [ simpleService.configuration ];
131 systemd.services.test.stopIfChanged = false;
134 simpleServiceReload.configuration = {
135 imports = [ simpleService.configuration ];
136 systemd.services.test = {
137 reloadIfChanged = true;
138 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
142 simpleServiceNorestart.configuration = {
143 imports = [ simpleService.configuration ];
144 systemd.services.test.restartIfChanged = false;
147 simpleServiceFailing.configuration = {
148 imports = [ simpleServiceModified.configuration ];
149 systemd.services.test.serviceConfig.ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false";
152 autorestartService.configuration = {
153 # A service that immediately goes into restarting (but without failing)
154 systemd.services.autorestart = {
155 wantedBy = [ "multi-user.target" ];
159 RestartSec = "20y"; # Should be long enough
160 ExecStart = "${pkgs.coreutils}/bin/true";
165 autorestartServiceFailing.configuration = {
166 imports = [ autorestartService.configuration ];
167 systemd.services.autorestart.serviceConfig = {
168 ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false";
172 simpleServiceWithExtraSection.configuration = {
173 imports = [ simpleServiceNostop.configuration ];
174 systemd.packages = [ (pkgs.writeTextFile {
175 name = "systemd-extra-section";
176 destination = "/etc/systemd/system/test.service";
184 simpleServiceWithExtraSectionOtherName.configuration = {
185 imports = [ simpleServiceNostop.configuration ];
186 systemd.packages = [ (pkgs.writeTextFile {
187 name = "systemd-extra-section";
188 destination = "/etc/systemd/system/test.service";
196 simpleServiceWithInstallSection.configuration = {
197 imports = [ simpleServiceNostop.configuration ];
198 systemd.packages = [ (pkgs.writeTextFile {
199 name = "systemd-extra-section";
200 destination = "/etc/systemd/system/test.service";
203 WantedBy=multi-user.target
208 simpleServiceWithExtraKey.configuration = {
209 imports = [ simpleServiceNostop.configuration ];
210 systemd.services.test.serviceConfig."X-Test" = "test";
213 simpleServiceWithExtraKeyOtherValue.configuration = {
214 imports = [ simpleServiceNostop.configuration ];
215 systemd.services.test.serviceConfig."X-Test" = "test2";
218 simpleServiceWithExtraKeyOtherName.configuration = {
219 imports = [ simpleServiceNostop.configuration ];
220 systemd.services.test.serviceConfig."X-Test2" = "test";
223 simpleServiceReloadTrigger.configuration = {
224 imports = [ simpleServiceNostop.configuration ];
225 systemd.services.test.reloadTriggers = [ "/dev/null" ];
228 simpleServiceReloadTriggerModified.configuration = {
229 imports = [ simpleServiceNostop.configuration ];
230 systemd.services.test.reloadTriggers = [ "/dev/zero" ];
233 simpleServiceReloadTriggerModifiedAndSomethingElse.configuration = {
234 imports = [ simpleServiceNostop.configuration ];
235 systemd.services.test = {
236 reloadTriggers = [ "/dev/zero" ];
237 serviceConfig."X-Test" = "test";
241 simpleServiceReloadTriggerModifiedSomethingElse.configuration = {
242 imports = [ simpleServiceNostop.configuration ];
243 systemd.services.test.serviceConfig."X-Test" = "test";
246 unitWithBackslash.configuration = {
247 systemd.services."escaped\\x2ddash" = {
248 wantedBy = [ "multi-user.target" ];
251 RemainAfterExit = true;
252 ExecStart = "${pkgs.coreutils}/bin/true";
253 ExecReload = "${pkgs.coreutils}/bin/true";
258 unitWithBackslashModified.configuration = {
259 imports = [ unitWithBackslash.configuration ];
260 systemd.services."escaped\\x2ddash".serviceConfig.X-Test = "test";
263 unitWithMultilineValue.configuration = {
264 systemd.services.test.serviceConfig.ExecStart = ''
265 ${pkgs.coreutils}/bin/true \
272 unitStartingWithDash.configuration = {
273 systemd.services."-" = {
274 wantedBy = [ "multi-user.target" ];
277 RemainAfterExit = true;
278 ExecStart = "${pkgs.coreutils}/bin/true";
283 unitStartingWithDashModified.configuration = {
284 imports = [ unitStartingWithDash.configuration ];
285 systemd.services."-" = {
286 reloadIfChanged = true;
287 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
291 unitWithRequirement.configuration = {
292 systemd.services.required-service = {
293 wantedBy = [ "multi-user.target" ];
296 RemainAfterExit = true;
297 ExecStart = "${pkgs.coreutils}/bin/true";
298 ExecReload = "${pkgs.coreutils}/bin/true";
301 systemd.services.test-service = {
302 wantedBy = [ "multi-user.target" ];
303 requires = [ "required-service.service" ];
306 RemainAfterExit = true;
307 ExecStart = "${pkgs.coreutils}/bin/true";
308 ExecReload = "${pkgs.coreutils}/bin/true";
313 unitWithRequirementModified.configuration = {
314 imports = [ unitWithRequirement.configuration ];
315 systemd.services.required-service.serviceConfig.X-Test = "test";
316 systemd.services.test-service.reloadTriggers = [ "test" ];
319 unitWithRequirementModifiedNostart.configuration = {
320 imports = [ unitWithRequirement.configuration ];
321 systemd.services.test-service.unitConfig.RefuseManualStart = true;
324 unitWithTemplate.configuration = {
325 systemd.services."instantiated@".serviceConfig = {
327 RemainAfterExit = true;
328 ExecStart = "${pkgs.coreutils}/bin/true";
329 ExecReload = "${pkgs.coreutils}/bin/true";
331 systemd.services."instantiated@one" = {
332 wantedBy = [ "multi-user.target" ];
333 overrideStrategy = "asDropin";
335 systemd.services."instantiated@two" = {
336 wantedBy = [ "multi-user.target" ];
337 overrideStrategy = "asDropin";
341 unitWithTemplateModified.configuration = {
342 imports = [ unitWithTemplate.configuration ];
343 systemd.services."instantiated@".serviceConfig.X-Test = "test";
346 restart-and-reload-by-activation-script.configuration = {
347 systemd.services = rec {
349 # No wantedBy so we can check if the activation script restart triggers them
352 RemainAfterExit = true;
353 ExecStart = "${pkgs.coreutils}/bin/true";
354 ExecReload = "${pkgs.coreutils}/bin/true";
357 "templated-simple-service@" = simple-service;
358 "templated-simple-service@instance".overrideStrategy = "asDropin";
360 simple-restart-service = simple-service // {
361 stopIfChanged = false;
363 "templated-simple-restart-service@" = simple-restart-service;
364 "templated-simple-restart-service@instance".overrideStrategy = "asDropin";
366 simple-reload-service = simple-service // {
367 reloadIfChanged = true;
369 "templated-simple-reload-service@" = simple-reload-service;
370 "templated-simple-reload-service@instance".overrideStrategy = "asDropin";
372 no-restart-service = simple-service // {
373 restartIfChanged = false;
375 "templated-no-restart-service@" = no-restart-service;
376 "templated-no-restart-service@instance".overrideStrategy = "asDropin";
378 reload-triggers = simple-service // {
379 wantedBy = [ "multi-user.target" ];
381 "templated-reload-triggers@" = simple-service;
382 "templated-reload-triggers@instance" = {
383 overrideStrategy = "asDropin";
384 wantedBy = [ "multi-user.target" ];
387 reload-triggers-and-restart-by-as = simple-service;
388 "templated-reload-triggers-and-restart-by-as@" = reload-triggers-and-restart-by-as;
389 "templated-reload-triggers-and-restart-by-as@instance".overrideStrategy = "asDropin";
391 reload-triggers-and-restart = simple-service // {
392 stopIfChanged = false; # easier to check for this
393 wantedBy = [ "multi-user.target" ];
395 "templated-reload-triggers-and-restart@" = simple-service;
396 "templated-reload-triggers-and-restart@instance" = {
397 overrideStrategy = "asDropin";
398 stopIfChanged = false; # easier to check for this
399 wantedBy = [ "multi-user.target" ];
403 system.activationScripts.restart-and-reload-test = {
404 supportsDryActivation = true;
407 if [ "$NIXOS_ACTION" = dry-activate ]; then
408 f=/run/nixos/dry-activation-restart-list
409 g=/run/nixos/dry-activation-reload-list
411 f=/run/nixos/activation-restart-list
412 g=/run/nixos/activation-reload-list
415 simple-service.service
416 simple-restart-service.service
417 simple-reload-service.service
418 no-restart-service.service
419 reload-triggers-and-restart-by-as.service
420 templated-simple-service@instance.service
421 templated-simple-restart-service@instance.service
422 templated-simple-reload-service@instance.service
423 templated-no-restart-service@instance.service
424 templated-reload-triggers-and-restart-by-as@instance.service
428 reload-triggers.service
429 reload-triggers-and-restart-by-as.service
430 reload-triggers-and-restart.service
431 templated-reload-triggers@instance.service
432 templated-reload-triggers-and-restart-by-as@instance.service
433 templated-reload-triggers-and-restart@instance.service
439 restart-and-reload-by-activation-script-modified.configuration = {
440 imports = [ restart-and-reload-by-activation-script.configuration ];
441 systemd.services.reload-triggers-and-restart.serviceConfig.X-Modified = "test";
442 systemd.services."templated-reload-triggers-and-restart@instance" = {
443 overrideStrategy = "asDropin";
444 serviceConfig.X-Modified = "test";
448 simple-socket.configuration = {
449 systemd.services.socket-activated = {
450 description = "A socket-activated service";
451 stopIfChanged = lib.mkDefault false;
453 ExecStart = socketTest;
454 ExecReload = "${pkgs.coreutils}/bin/true";
457 systemd.sockets.socket-activated = {
458 wantedBy = [ "sockets.target" ];
459 listenStreams = [ "/run/test.sock" ];
460 socketConfig.SocketMode = lib.mkDefault "0777";
464 simple-socket-service-modified.configuration = {
465 imports = [ simple-socket.configuration ];
466 systemd.services.socket-activated.serviceConfig.X-Test = "test";
469 simple-socket-stop-if-changed.configuration = {
470 imports = [ simple-socket.configuration ];
471 systemd.services.socket-activated.stopIfChanged = true;
474 simple-socket-stop-if-changed-and-reloadtrigger.configuration = {
475 imports = [ simple-socket.configuration ];
476 systemd.services.socket-activated = {
477 stopIfChanged = true;
478 reloadTriggers = [ "test" ];
482 mount.configuration = {
485 description = "Testmount";
488 where = "/testmount";
490 wantedBy = [ "local-fs.target" ];
495 mountOptionsModified.configuration = {
498 description = "Testmount";
501 where = "/testmount";
502 options = "size=10M";
503 wantedBy = [ "local-fs.target" ];
508 mountModified.configuration = {
511 description = "Testmount";
514 where = "/testmount";
515 options = "size=10M";
516 wantedBy = [ "local-fs.target" ];
521 timer.configuration = {
522 systemd.timers.test-timer = {
523 wantedBy = [ "timers.target" ];
524 timerConfig.OnCalendar = "@1395716396"; # chosen by fair dice roll
526 systemd.services.test-timer = {
529 ExecStart = "${pkgs.coreutils}/bin/true";
534 timerModified.configuration = {
535 imports = [ timer.configuration ];
536 systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00";
539 hybridSleepModified.configuration = {
540 systemd.targets.hybrid-sleep.unitConfig.X-Test = true;
543 target.configuration = {
544 systemd.targets.test-target.wantedBy = [ "multi-user.target" ];
545 # We use this service to figure out whether the target was modified.
546 # This is the only way because targets are filtered and therefore not
547 # printed when they are started/stopped.
548 systemd.services.test-service = {
549 bindsTo = [ "test-target.target" ];
550 serviceConfig.ExecStart = "${pkgs.coreutils}/bin/sleep infinity";
554 targetModified.configuration = {
555 imports = [ target.configuration ];
556 systemd.targets.test-target.unitConfig.X-Test = true;
559 targetModifiedStopOnReconfig.configuration = {
560 imports = [ target.configuration ];
561 systemd.targets.test-target.unitConfig.X-StopOnReconfiguration = true;
564 path.configuration = {
565 systemd.paths.test-watch = {
566 wantedBy = [ "paths.target" ];
567 pathConfig.PathExists = "/testpath";
569 systemd.services.test-watch = {
572 RemainAfterExit = true;
573 ExecStart = "${pkgs.coreutils}/bin/touch /testpath-modified";
578 pathModified.configuration = {
579 imports = [ path.configuration ];
580 systemd.paths.test-watch.pathConfig.PathExists = lib.mkForce "/testpath2";
583 slice.configuration = {
584 systemd.slices.testslice.sliceConfig.MemoryMax = "1"; # don't allow memory allocation
585 systemd.services.testservice = {
588 RemainAfterExit = true;
589 ExecStart = "${pkgs.coreutils}/bin/true";
590 Slice = "testslice.slice";
595 sliceModified.configuration = {
596 imports = [ slice.configuration ];
597 systemd.slices.testslice.sliceConfig.MemoryMax = lib.mkForce null;
603 system.switch.enable = true;
604 users.mutableUsers = true;
608 testScript = { nodes, ... }: let
609 originalSystem = nodes.machine.system.build.toplevel;
610 otherSystem = nodes.other.system.build.toplevel;
611 machine = nodes.machine.system.build.toplevel;
613 # Ensures failures pass through using pipefail, otherwise failing to
614 # switch-to-configuration is hidden by the success of `tee`.
615 stderrRunner = pkgs.writeScript "stderr-runner" ''
616 #! ${pkgs.runtimeShell}
619 exec env -i "$@" | tee /dev/stderr
622 # Returns a comma separated representation of the given list in sorted
623 # order, that matches the output format of switch-to-configuration.pl
624 sortedUnits = xs: lib.concatStringsSep ", " (builtins.sort builtins.lessThan xs);
627 "dbus" = "dbus.service";
628 "broker" = "dbus-broker.service";
629 }.${nodes.machine.services.dbus.implementation};
631 def switch_to_specialisation(system, name, action="test", fail=False):
633 switcher = f"{system}/bin/switch-to-configuration"
635 switcher = f"{system}/specialisation/{name}/bin/switch-to-configuration"
636 return run_switch(switcher, action, fail)
638 # like above but stc = switcher
639 def run_switch(switcher, action="test", fail=False):
640 out = machine.fail(f"{switcher} {action} 2>&1") if fail \
641 else machine.succeed(f"{switcher} {action} 2>&1")
642 assert_lacks(out, "switch-to-configuration line") # Perl warnings
645 def assert_contains(haystack, needle):
646 if needle not in haystack:
647 print("The haystack that will cause the following exception is:")
651 raise Exception(f"Expected string '{needle}' was not found")
653 def assert_lacks(haystack, needle):
654 if needle in haystack:
655 print("The haystack that will cause the following exception is:")
657 print(haystack, end="")
659 raise Exception(f"Unexpected string '{needle}' was found")
662 machine.wait_for_unit("multi-user.target")
665 "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test"
667 # This tests whether the /etc/os-release parser works which is a fallback
668 # when /etc/NIXOS is missing. If the parser does not work, switch-to-configuration
670 machine.succeed("rm /etc/NIXOS")
672 "${stderrRunner} ${otherSystem}/bin/switch-to-configuration test"
676 with subtest("actions"):
678 machine.fail("test -f /tmp/bootloader-installed")
679 out = switch_to_specialisation("${machine}", "simpleService", action="boot")
680 assert_contains(out, "installing dummy bootloader")
681 assert_lacks(out, "activating the configuration...") # good indicator of a system activation
682 machine.succeed("test -f /tmp/bootloader-installed")
683 machine.succeed("rm /tmp/bootloader-installed")
686 machine.fail("test -f /tmp/bootloader-installed")
687 out = switch_to_specialisation("${machine}", "", action="switch")
688 assert_contains(out, "installing dummy bootloader")
689 assert_contains(out, "activating the configuration...") # good indicator of a system activation
690 machine.succeed("test -f /tmp/bootloader-installed")
692 # test and dry-activate actions are tested further down below
694 # invalid action fails the script
695 switch_to_specialisation("${machine}", "", action="broken-action", fail=True)
696 # no action fails the script
697 assert "Usage:" in machine.fail("${machine}/bin/switch-to-configuration 2>&1")
699 with subtest("init interface version"):
700 # Do not try to switch to an invalid init interface version
701 assert "incompatible" in switch_to_specialisation("${machine}", "brokenInitInterface", fail=True)
703 with subtest("systemd restarts"):
704 # systemd is restarted when its system.conf changes
705 out = switch_to_specialisation("${machine}", "modifiedSystemConf")
706 assert_contains(out, "restarting systemd...")
708 with subtest("continuing from an aborted switch"):
709 # An aborted switch will write into a file what it tried to start
710 # and a second switch should continue from this
711 machine.succeed("echo ${dbusService} > /run/nixos/start-list")
712 out = switch_to_specialisation("${machine}", "modifiedSystemConf")
713 assert_contains(out, "starting the following units: ${dbusService}\n")
715 with subtest("fstab mounts"):
716 switch_to_specialisation("${machine}", "")
718 out = switch_to_specialisation("${machine}", "addedMount")
719 assert_lacks(out, "stopping the following units:")
720 assert_lacks(out, "NOT restarting the following changed 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: test.mount\n")
724 # modify the mountpoint's options
725 out = switch_to_specialisation("${machine}", "addedMountOptsModified")
726 assert_lacks(out, "stopping the following units:")
727 assert_lacks(out, "NOT restarting the following changed units:")
728 assert_contains(out, "reloading the following units: test.mount\n")
729 assert_lacks(out, "\nrestarting the following units:")
730 assert_lacks(out, "\nstarting the following units:")
731 assert_lacks(out, "the following new units were started:")
733 out = switch_to_specialisation("${machine}", "addedMountDevModified")
734 assert_lacks(out, "stopping the following units:")
735 assert_lacks(out, "NOT restarting the following changed units:")
736 assert_lacks(out, "reloading the following units:")
737 assert_contains(out, "\nrestarting the following units: test.mount\n")
738 assert_lacks(out, "\nstarting the following units:")
739 assert_lacks(out, "the following new units were started:")
741 out = switch_to_specialisation("${machine}", "addedMount")
742 assert_lacks(out, "stopping the following units:")
743 assert_lacks(out, "NOT restarting the following changed units:")
744 assert_lacks(out, "reloading the following units:")
745 assert_contains(out, "\nrestarting the following units: test.mount\n")
746 assert_lacks(out, "\nstarting the following units:")
747 assert_lacks(out, "the following new units were started:")
749 out = switch_to_specialisation("${machine}", "")
750 assert_contains(out, "stopping the following units: test.mount\n")
751 assert_lacks(out, "NOT restarting the following changed units:")
752 assert_contains(out, "reloading the following units: ${dbusService}\n")
753 assert_lacks(out, "\nrestarting the following units:")
754 assert_lacks(out, "\nstarting the following units:")
755 assert_lacks(out, "the following new units were started:")
756 # change something about the / mount
757 out = switch_to_specialisation("${machine}", "storeMountModified")
758 assert_lacks(out, "stopping the following units:")
759 assert_contains(out, "NOT restarting the following changed units: -.mount")
760 assert_contains(out, "reloading the following units: ${dbusService}\n")
761 assert_lacks(out, "\nrestarting the following units:")
762 assert_lacks(out, "\nstarting the following units:")
763 assert_lacks(out, "the following new units were started:")
765 with subtest("swaps"):
766 switch_to_specialisation("${machine}", "")
768 out = switch_to_specialisation("${machine}", "swap")
769 assert_lacks(out, "stopping the following units:")
770 assert_lacks(out, "NOT restarting the following changed units:")
771 assert_contains(out, "reloading the following units: ${dbusService}\n")
772 assert_lacks(out, "\nrestarting the following units:")
773 assert_lacks(out, "\nstarting the following units:")
774 assert_contains(out, "the following new units were started: swapfile.swap")
776 out = switch_to_specialisation("${machine}", "")
777 assert_contains(out, "stopping swap device: /swapfile")
778 assert_lacks(out, "stopping the following units:")
779 assert_lacks(out, "NOT restarting the following changed units:")
780 assert_contains(out, "reloading the following units: ${dbusService}\n")
781 assert_lacks(out, "\nrestarting the following units:")
782 assert_lacks(out, "\nstarting the following units:")
783 assert_lacks(out, "the following new units were started:")
785 with subtest("services"):
786 switch_to_specialisation("${machine}", "")
787 # Nothing happens when nothing is changed
788 out = switch_to_specialisation("${machine}", "")
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_lacks(out, "\nrestarting the following units:")
793 assert_lacks(out, "\nstarting the following units:")
794 assert_lacks(out, "the following new units were started:")
796 # Start a simple service
797 out = switch_to_specialisation("${machine}", "simpleService")
798 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader
799 assert_lacks(out, "stopping the following units:")
800 assert_lacks(out, "NOT restarting the following changed units:")
801 assert_contains(out, "reloading the following units: ${dbusService}\n") # huh
802 assert_lacks(out, "\nrestarting the following units:")
803 assert_lacks(out, "\nstarting the following units:")
804 assert_contains(out, "the following new units were started: test.service\n")
806 # Not changing anything doesn't do anything
807 out = switch_to_specialisation("${machine}", "simpleService")
808 assert_lacks(out, "stopping the following units:")
809 assert_lacks(out, "NOT restarting the following changed units:")
810 assert_lacks(out, "reloading the following units:")
811 assert_lacks(out, "\nrestarting the following units:")
812 assert_lacks(out, "\nstarting the following units:")
813 assert_lacks(out, "the following new units were started:")
815 # Only changing the description does nothing
816 out = switch_to_specialisation("${machine}", "simpleServiceDifferentDescription")
817 assert_lacks(out, "stopping the following units:")
818 assert_lacks(out, "NOT restarting the following changed units:")
819 assert_lacks(out, "reloading the following units:")
820 assert_lacks(out, "\nrestarting the following units:")
821 assert_lacks(out, "\nstarting the following units:")
822 assert_lacks(out, "the following new units were started:")
824 # Restart the simple service
825 out = switch_to_specialisation("${machine}", "simpleServiceModified")
826 assert_contains(out, "stopping the following units: test.service\n")
827 assert_lacks(out, "NOT restarting the following changed units:")
828 assert_lacks(out, "reloading the following units:")
829 assert_lacks(out, "\nrestarting the following units:")
830 assert_contains(out, "\nstarting the following units: test.service\n")
831 assert_lacks(out, "the following new units were started:")
833 # Restart the service with stopIfChanged=false
834 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
835 assert_lacks(out, "stopping the following units:")
836 assert_lacks(out, "NOT restarting the following changed units:")
837 assert_lacks(out, "reloading the following units:")
838 assert_contains(out, "\nrestarting the following units: test.service\n")
839 assert_lacks(out, "\nstarting the following units:")
840 assert_lacks(out, "the following new units were started:")
842 # Reload the service with reloadIfChanged=true
843 out = switch_to_specialisation("${machine}", "simpleServiceReload")
844 assert_lacks(out, "stopping the following units:")
845 assert_lacks(out, "NOT restarting the following changed units:")
846 assert_contains(out, "reloading the following units: test.service\n")
847 assert_lacks(out, "\nrestarting the following units:")
848 assert_lacks(out, "\nstarting the following units:")
849 assert_lacks(out, "the following new units were started:")
851 # Nothing happens when restartIfChanged=false
852 out = switch_to_specialisation("${machine}", "simpleServiceNorestart")
853 assert_lacks(out, "stopping the following units:")
854 assert_contains(out, "NOT restarting the following changed units: test.service\n")
855 assert_lacks(out, "reloading the following units:")
856 assert_lacks(out, "\nrestarting the following units:")
857 assert_lacks(out, "\nstarting the following units:")
858 assert_lacks(out, "the following new units were started:")
860 # Dry mode shows different messages
861 out = switch_to_specialisation("${machine}", "simpleService", action="dry-activate")
862 assert_lacks(out, "stopping the following units:")
863 assert_lacks(out, "NOT restarting the following changed units:")
864 assert_lacks(out, "reloading the following units:")
865 assert_lacks(out, "\nrestarting the following units:")
866 assert_lacks(out, "\nstarting the following units:")
867 assert_lacks(out, "the following new units were started:")
868 assert_contains(out, "would start the following units: test.service\n")
870 out = switch_to_specialisation("${machine}", "", action="test")
872 # Ensure the service can be started when the activation script isn't in toplevel
873 # This is a lot like "Start a simple service", except activation-only deps could be gc-ed
874 out = run_switch("${nodes.machine.specialisation.simpleServiceSeparateActivationScript.configuration.system.build.separateActivationScript}/bin/switch-to-configuration");
875 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader
876 assert_lacks(out, "stopping the following units:")
877 assert_lacks(out, "NOT restarting the following changed units:")
878 assert_contains(out, "reloading the following units: ${dbusService}\n") # huh
879 assert_lacks(out, "\nrestarting the following units:")
880 assert_lacks(out, "\nstarting the following units:")
881 assert_contains(out, "the following new units were started: test.service\n")
882 machine.succeed("! test -e /run/current-system/activate")
883 machine.succeed("! test -e /run/current-system/dry-activate")
884 machine.succeed("! test -e /run/current-system/bin/switch-to-configuration")
886 # Ensure units with multiline values work
887 out = switch_to_specialisation("${machine}", "unitWithMultilineValue")
888 assert_lacks(out, "NOT restarting the following changed units:")
889 assert_lacks(out, "reloading the following units:")
890 assert_lacks(out, "restarting the following units:")
891 assert_lacks(out, "the following new units were started:")
892 assert_contains(out, "starting the following units: test.service")
894 # Ensure \ works in unit names
895 out = switch_to_specialisation("${machine}", "unitWithBackslash")
896 assert_lacks(out, "NOT restarting the following changed units:")
897 assert_lacks(out, "reloading the following units:")
898 assert_lacks(out, "\nrestarting the following units:")
899 assert_lacks(out, "\nstarting the following units:")
900 assert_contains(out, "the following new units were started: escaped\\x2ddash.service\n")
902 out = switch_to_specialisation("${machine}", "unitWithBackslashModified")
903 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
904 assert_lacks(out, "NOT restarting the following changed units:")
905 assert_lacks(out, "reloading the following units:")
906 assert_lacks(out, "\nrestarting the following units:")
907 assert_contains(out, "\nstarting the following units: escaped\\x2ddash.service\n")
908 assert_lacks(out, "the following new units were started:")
910 # Ensure units can start with a dash
911 out = switch_to_specialisation("${machine}", "unitStartingWithDash")
912 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
913 assert_lacks(out, "NOT restarting the following changed units:")
914 assert_lacks(out, "reloading the following units:")
915 assert_lacks(out, "\nrestarting the following units:")
916 assert_lacks(out, "\nstarting the following units:")
917 assert_contains(out, "the following new units were started: -.service\n")
919 # The regression only occurs when reloading units
920 out = switch_to_specialisation("${machine}", "unitStartingWithDashModified")
921 assert_lacks(out, "stopping the following units:")
922 assert_lacks(out, "NOT restarting the following changed units:")
923 assert_contains(out, "reloading the following units: -.service")
924 assert_lacks(out, "\nrestarting the following units:")
925 assert_lacks(out, "\nstarting the following units:")
926 assert_lacks(out, "the following new units were started:")
928 # Ensure units that require changed units are properly reloaded
929 out = switch_to_specialisation("${machine}", "unitWithRequirement")
930 assert_contains(out, "stopping the following units: -.service\n")
931 assert_lacks(out, "NOT restarting the following changed units:")
932 assert_lacks(out, "reloading the following units:")
933 assert_lacks(out, "\nrestarting the following units:")
934 assert_lacks(out, "\nstarting the following units:")
935 assert_contains(out, "the following new units were started: required-service.service, test-service.service\n")
937 out = switch_to_specialisation("${machine}", "unitWithRequirementModified")
938 assert_contains(out, "stopping the following units: required-service.service\n")
939 assert_lacks(out, "NOT restarting the following changed units:")
940 assert_lacks(out, "reloading the following units:")
941 assert_lacks(out, "\nrestarting the following units:")
942 assert_contains(out, "\nstarting the following units: required-service.service, test-service.service\n")
943 assert_lacks(out, "the following new units were started:")
945 # Unless the unit asks to be not restarted
946 out = switch_to_specialisation("${machine}", "unitWithRequirementModifiedNostart")
947 assert_contains(out, "stopping the following units: required-service.service\n")
948 assert_lacks(out, "NOT restarting the following changed units:")
949 assert_lacks(out, "reloading the following units:")
950 assert_lacks(out, "\nrestarting the following units:")
951 assert_contains(out, "\nstarting the following units: required-service.service\n")
952 assert_lacks(out, "the following new units were started:")
954 # Ensure templated units are restarted when the base unit changes
955 switch_to_specialisation("${machine}", "unitWithTemplate")
956 out = switch_to_specialisation("${machine}", "unitWithTemplateModified")
957 assert_contains(out, "stopping the following units: instantiated@one.service, instantiated@two.service\n")
958 assert_lacks(out, "NOT restarting the following changed units:")
959 assert_lacks(out, "reloading the following units:")
960 assert_lacks(out, "\nrestarting the following units:")
961 assert_contains(out, "\nstarting the following units: instantiated@one.service, instantiated@two.service\n")
962 assert_lacks(out, "the following new units were started:")
964 with subtest("failing units"):
965 # Let the simple service fail
966 switch_to_specialisation("${machine}", "simpleServiceModified")
967 out = switch_to_specialisation("${machine}", "simpleServiceFailing", fail=True)
968 assert_contains(out, "stopping the following units: test.service\n")
969 assert_lacks(out, "NOT restarting the following changed units:")
970 assert_lacks(out, "reloading the following units:")
971 assert_lacks(out, "\nrestarting the following units:")
972 assert_contains(out, "\nstarting the following units: test.service\n")
973 assert_lacks(out, "the following new units were started:")
974 assert_contains(out, "warning: the following units failed: test.service\n")
975 assert_contains(out, "Main PID:") # output of systemctl
977 # A unit that gets into autorestart without failing is not treated as failed
978 out = switch_to_specialisation("${machine}", "autorestartService")
979 assert_lacks(out, "stopping the following units:")
980 assert_lacks(out, "NOT restarting the following changed units:")
981 assert_lacks(out, "reloading the following units:")
982 assert_lacks(out, "\nrestarting the following units:")
983 assert_lacks(out, "\nstarting the following units:")
984 assert_contains(out, "the following new units were started: autorestart.service\n")
985 machine.systemctl('stop autorestart.service') # cancel the 20y timer
987 # Switching to the same system should do nothing (especially not treat the unit as failed)
988 out = switch_to_specialisation("${machine}", "autorestartService")
989 assert_lacks(out, "stopping the following units:")
990 assert_lacks(out, "NOT restarting the following changed units:")
991 assert_lacks(out, "reloading the following units:")
992 assert_lacks(out, "\nrestarting the following units:")
993 assert_lacks(out, "\nstarting the following units:")
994 assert_contains(out, "the following new units were started: autorestart.service\n")
995 machine.systemctl('stop autorestart.service') # cancel the 20y timer
997 # If systemd thinks the unit has failed and is in autorestart, we should show it as failed
998 out = switch_to_specialisation("${machine}", "autorestartServiceFailing", fail=True)
999 assert_lacks(out, "stopping the following units:")
1000 assert_lacks(out, "NOT restarting the following changed units:")
1001 assert_lacks(out, "reloading the following units:")
1002 assert_lacks(out, "\nrestarting the following units:")
1003 assert_lacks(out, "\nstarting the following units:")
1004 assert_lacks(out, "the following new units were started:")
1005 assert_contains(out, "warning: the following units failed: autorestart.service\n")
1006 assert_contains(out, "Main PID:") # output of systemctl
1008 with subtest("unit file parser"):
1009 # Switch to a well-known state
1010 switch_to_specialisation("${machine}", "simpleServiceNostop")
1013 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSection")
1014 assert_lacks(out, "stopping the following units:")
1015 assert_lacks(out, "NOT restarting the following changed units:")
1016 assert_lacks(out, "reloading the following units:")
1017 assert_contains(out, "\nrestarting the following units: test.service\n")
1018 assert_lacks(out, "\nstarting the following units:")
1019 assert_lacks(out, "the following new units were started:")
1022 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSectionOtherName")
1023 assert_lacks(out, "stopping the following units:")
1024 assert_lacks(out, "NOT restarting the following changed units:")
1025 assert_lacks(out, "reloading the following units:")
1026 assert_contains(out, "\nrestarting the following units: test.service\n")
1027 assert_lacks(out, "\nstarting the following units:")
1028 assert_lacks(out, "the following new units were started:")
1031 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
1032 assert_lacks(out, "stopping the following units:")
1033 assert_lacks(out, "NOT restarting the following changed units:")
1034 assert_lacks(out, "reloading the following units:")
1035 assert_contains(out, "\nrestarting the following units: test.service\n")
1036 assert_lacks(out, "\nstarting the following units:")
1037 assert_lacks(out, "the following new units were started:")
1039 # [Install] section is ignored
1040 out = switch_to_specialisation("${machine}", "simpleServiceWithInstallSection")
1041 assert_lacks(out, "stopping the following units:")
1042 assert_lacks(out, "NOT restarting the following changed units:")
1043 assert_lacks(out, "reloading the following units:")
1044 assert_lacks(out, "\nrestarting the following units:")
1045 assert_lacks(out, "\nstarting the following units:")
1046 assert_lacks(out, "the following new units were started:")
1049 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKey")
1050 assert_lacks(out, "stopping the following units:")
1051 assert_lacks(out, "NOT restarting the following changed units:")
1052 assert_lacks(out, "reloading the following units:")
1053 assert_contains(out, "\nrestarting the following units: test.service\n")
1054 assert_lacks(out, "\nstarting the following units:")
1055 assert_lacks(out, "the following new units were started:")
1058 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherValue")
1059 assert_lacks(out, "stopping the following units:")
1060 assert_lacks(out, "NOT restarting the following changed units:")
1061 assert_lacks(out, "reloading the following units:")
1062 assert_contains(out, "\nrestarting the following units: test.service\n")
1063 assert_lacks(out, "\nstarting the following units:")
1064 assert_lacks(out, "the following new units were started:")
1067 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherName")
1068 assert_lacks(out, "stopping the following units:")
1069 assert_lacks(out, "NOT restarting the following changed units:")
1070 assert_lacks(out, "reloading the following units:")
1071 assert_contains(out, "\nrestarting the following units: test.service\n")
1072 assert_lacks(out, "\nstarting the following units:")
1073 assert_lacks(out, "the following new units were started:")
1076 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
1077 assert_lacks(out, "stopping the following units:")
1078 assert_lacks(out, "NOT restarting the following changed units:")
1079 assert_lacks(out, "reloading the following units:")
1080 assert_contains(out, "\nrestarting the following units: test.service\n")
1081 assert_lacks(out, "\nstarting the following units:")
1082 assert_lacks(out, "the following new units were started:")
1084 # Add a reload trigger
1085 out = switch_to_specialisation("${machine}", "simpleServiceReloadTrigger")
1086 assert_lacks(out, "stopping the following units:")
1087 assert_lacks(out, "NOT restarting the following changed units:")
1088 assert_contains(out, "reloading the following units: test.service\n")
1089 assert_lacks(out, "\nrestarting the following units:")
1090 assert_lacks(out, "\nstarting the following units:")
1091 assert_lacks(out, "the following new units were started:")
1093 # Modify the reload trigger
1094 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModified")
1095 assert_lacks(out, "stopping the following units:")
1096 assert_lacks(out, "NOT restarting the following changed units:")
1097 assert_contains(out, "reloading the following units: test.service\n")
1098 assert_lacks(out, "\nrestarting the following units:")
1099 assert_lacks(out, "\nstarting the following units:")
1100 assert_lacks(out, "the following new units were started:")
1102 # Modify the reload trigger and something else
1103 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedAndSomethingElse")
1104 assert_lacks(out, "stopping the following units:")
1105 assert_lacks(out, "NOT restarting the following changed units:")
1106 assert_lacks(out, "reloading the following units:")
1107 assert_contains(out, "\nrestarting the following units: test.service\n")
1108 assert_lacks(out, "\nstarting the following units:")
1109 assert_lacks(out, "the following new units were started:")
1111 # Remove the reload trigger
1112 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedSomethingElse")
1113 assert_lacks(out, "stopping the following units:")
1114 assert_lacks(out, "NOT restarting the following changed units:")
1115 assert_lacks(out, "reloading the following units:")
1116 assert_lacks(out, "\nrestarting the following units:")
1117 assert_lacks(out, "\nstarting the following units:")
1118 assert_lacks(out, "the following new units were started:")
1120 with subtest("restart and reload by activation script"):
1121 switch_to_specialisation("${machine}", "simpleServiceNorestart")
1122 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
1123 assert_contains(out, "stopping the following units: test.service\n")
1124 assert_lacks(out, "NOT restarting the following changed units:")
1125 assert_lacks(out, "reloading the following units:")
1126 assert_lacks(out, "restarting the following units:")
1127 assert_contains(out, "\nstarting the following units: ${sortedUnits [
1128 "no-restart-service.service"
1129 "reload-triggers-and-restart-by-as.service"
1130 "simple-reload-service.service"
1131 "simple-restart-service.service"
1132 "simple-service.service"
1133 "templated-no-restart-service@instance.service"
1134 "templated-reload-triggers-and-restart-by-as@instance.service"
1135 "templated-simple-reload-service@instance.service"
1136 "templated-simple-restart-service@instance.service"
1137 "templated-simple-service@instance.service"
1139 assert_contains(out, "the following new units were started: ${sortedUnits [
1140 "no-restart-service.service"
1141 "reload-triggers-and-restart-by-as.service"
1142 "reload-triggers-and-restart.service"
1143 "reload-triggers.service"
1144 "simple-reload-service.service"
1145 "simple-restart-service.service"
1146 "simple-service.service"
1147 "system-templated\\\\x2dno\\\\x2drestart\\\\x2dservice.slice"
1148 "system-templated\\\\x2dreload\\\\x2dtriggers.slice"
1149 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart.slice"
1150 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart\\\\x2dby\\\\x2das.slice"
1151 "system-templated\\\\x2dsimple\\\\x2dreload\\\\x2dservice.slice"
1152 "system-templated\\\\x2dsimple\\\\x2drestart\\\\x2dservice.slice"
1153 "system-templated\\\\x2dsimple\\\\x2dservice.slice"
1154 "templated-no-restart-service@instance.service"
1155 "templated-reload-triggers-and-restart-by-as@instance.service"
1156 "templated-reload-triggers-and-restart@instance.service"
1157 "templated-reload-triggers@instance.service"
1158 "templated-simple-reload-service@instance.service"
1159 "templated-simple-restart-service@instance.service"
1160 "templated-simple-service@instance.service"
1162 # Switch to the same system where the example services get restarted
1163 # and reloaded by the activation script
1164 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
1165 assert_lacks(out, "stopping the following units:")
1166 assert_lacks(out, "NOT restarting the following changed units:")
1167 assert_contains(out, "reloading the following units: ${sortedUnits [
1168 "reload-triggers-and-restart.service"
1169 "reload-triggers.service"
1170 "simple-reload-service.service"
1171 "templated-reload-triggers-and-restart@instance.service"
1172 "templated-reload-triggers@instance.service"
1173 "templated-simple-reload-service@instance.service"
1175 assert_contains(out, "restarting the following units: ${sortedUnits [
1176 "reload-triggers-and-restart-by-as.service"
1177 "simple-restart-service.service"
1178 "simple-service.service"
1179 "templated-reload-triggers-and-restart-by-as@instance.service"
1180 "templated-simple-restart-service@instance.service"
1181 "templated-simple-service@instance.service"
1183 assert_lacks(out, "\nstarting the following units:")
1184 assert_lacks(out, "the following new units were started:")
1185 # Switch to the same system and see if the service gets restarted when it's modified
1186 # while the fact that it's supposed to be reloaded by the activation script is ignored.
1187 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified")
1188 assert_lacks(out, "stopping the following units:")
1189 assert_lacks(out, "NOT restarting the following changed units:")
1190 assert_contains(out, "reloading the following units: ${sortedUnits [
1191 "reload-triggers.service"
1192 "simple-reload-service.service"
1193 "templated-reload-triggers@instance.service"
1194 "templated-simple-reload-service@instance.service"
1196 assert_contains(out, "restarting the following units: ${sortedUnits [
1197 "reload-triggers-and-restart-by-as.service"
1198 "reload-triggers-and-restart.service"
1199 "simple-restart-service.service"
1200 "simple-service.service"
1201 "templated-reload-triggers-and-restart-by-as@instance.service"
1202 "templated-reload-triggers-and-restart@instance.service"
1203 "templated-simple-restart-service@instance.service"
1204 "templated-simple-service@instance.service"
1206 assert_lacks(out, "\nstarting the following units:")
1207 assert_lacks(out, "the following new units were started:")
1208 # The same, but in dry mode
1209 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate")
1210 assert_lacks(out, "would stop the following units:")
1211 assert_lacks(out, "would NOT stop the following changed units:")
1212 assert_contains(out, "would reload the following units: ${sortedUnits [
1213 "reload-triggers.service"
1214 "simple-reload-service.service"
1215 "templated-reload-triggers@instance.service"
1216 "templated-simple-reload-service@instance.service"
1218 assert_contains(out, "would restart the following units: ${sortedUnits [
1219 "reload-triggers-and-restart-by-as.service"
1220 "reload-triggers-and-restart.service"
1221 "simple-restart-service.service"
1222 "simple-service.service"
1223 "templated-reload-triggers-and-restart-by-as@instance.service"
1224 "templated-reload-triggers-and-restart@instance.service"
1225 "templated-simple-restart-service@instance.service"
1226 "templated-simple-service@instance.service"
1228 assert_lacks(out, "\nwould start the following units:")
1230 with subtest("socket-activated services"):
1231 # Socket-activated services don't get started, just the socket
1232 machine.fail("[ -S /run/test.sock ]")
1233 out = switch_to_specialisation("${machine}", "simple-socket")
1234 # assert_lacks(out, "stopping the following units:") not relevant
1235 assert_lacks(out, "NOT restarting the following changed units:")
1236 assert_lacks(out, "reloading the following units:")
1237 assert_lacks(out, "\nrestarting the following units:")
1238 assert_lacks(out, "\nstarting the following units:")
1239 assert_contains(out, "the following new units were started: socket-activated.socket\n")
1240 machine.succeed("[ -S /run/test.sock ]")
1242 # Changing a non-activated service does nothing
1243 out = switch_to_specialisation("${machine}", "simple-socket-service-modified")
1244 assert_lacks(out, "stopping the following units:")
1245 assert_lacks(out, "NOT restarting the following changed units:")
1246 assert_lacks(out, "reloading the following units:")
1247 assert_lacks(out, "\nrestarting the following units:")
1248 assert_lacks(out, "\nstarting the following units:")
1249 assert_lacks(out, "the following new units were started:")
1250 machine.succeed("[ -S /run/test.sock ]")
1251 # The unit is properly activated when the socket is accessed
1252 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1253 raise Exception("Socket was not properly activated") # idk how that would happen tbh
1255 # Changing an activated service with stopIfChanged=false restarts the service
1256 out = switch_to_specialisation("${machine}", "simple-socket")
1257 assert_lacks(out, "stopping the following units:")
1258 assert_lacks(out, "NOT restarting the following changed units:")
1259 assert_lacks(out, "reloading the following units:")
1260 assert_contains(out, "\nrestarting the following units: socket-activated.service\n")
1261 assert_lacks(out, "\nstarting the following units:")
1262 assert_lacks(out, "the following new units were started:")
1263 machine.succeed("[ -S /run/test.sock ]")
1264 # Socket-activation of the unit still works
1265 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1266 raise Exception("Socket was not properly activated after the service was restarted")
1268 # Changing an activated service with stopIfChanged=true stops the service and
1269 # socket and starts the socket
1270 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed")
1271 assert_contains(out, "stopping the following units: socket-activated.service, socket-activated.socket\n")
1272 assert_lacks(out, "NOT restarting the following changed units:")
1273 assert_lacks(out, "reloading the following units:")
1274 assert_lacks(out, "\nrestarting the following units:")
1275 assert_contains(out, "\nstarting the following units: socket-activated.socket\n")
1276 assert_lacks(out, "the following new units were started:")
1277 machine.succeed("[ -S /run/test.sock ]")
1278 # Socket-activation of the unit still works
1279 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1280 raise Exception("Socket was not properly activated after the service was restarted")
1282 # Changing a reload trigger of a socket-activated unit only reloads it
1283 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed-and-reloadtrigger")
1284 assert_lacks(out, "stopping the following units:")
1285 assert_lacks(out, "NOT restarting the following changed units:")
1286 assert_contains(out, "reloading the following units: socket-activated.service\n")
1287 assert_lacks(out, "\nrestarting the following units:")
1288 assert_lacks(out, "\nstarting the following units: socket-activated.socket")
1289 assert_lacks(out, "the following new units were started:")
1290 machine.succeed("[ -S /run/test.sock ]")
1291 # Socket-activation of the unit still works
1292 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1293 raise Exception("Socket was not properly activated after the service was restarted")
1295 with subtest("mounts"):
1296 switch_to_specialisation("${machine}", "mount")
1297 out = machine.succeed("mount | grep 'on /testmount'")
1298 assert_contains(out, "size=1024k")
1299 # Changing options reloads the unit
1300 out = switch_to_specialisation("${machine}", "mountOptionsModified")
1301 assert_lacks(out, "stopping the following units:")
1302 assert_lacks(out, "NOT restarting the following changed units:")
1303 assert_contains(out, "reloading the following units: testmount.mount\n")
1304 assert_lacks(out, "\nrestarting the following units:")
1305 assert_lacks(out, "\nstarting the following units:")
1306 assert_lacks(out, "the following new units were started:")
1308 out = machine.succeed("mount | grep 'on /testmount'")
1309 assert_contains(out, "size=10240k")
1310 # Changing anything but `Options=` restarts the unit
1311 out = switch_to_specialisation("${machine}", "mountModified")
1312 assert_lacks(out, "stopping the following units:")
1313 assert_lacks(out, "NOT restarting the following changed units:")
1314 assert_lacks(out, "reloading the following units:")
1315 assert_contains(out, "\nrestarting the following units: testmount.mount\n")
1316 assert_lacks(out, "\nstarting the following units:")
1317 assert_lacks(out, "the following new units were started:")
1319 out = machine.succeed("mount | grep 'on /testmount'")
1320 assert_contains(out, "ramfs")
1322 with subtest("timers"):
1323 switch_to_specialisation("${machine}", "timer")
1324 out = machine.succeed("systemctl show test-timer.timer")
1325 assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC")
1326 out = switch_to_specialisation("${machine}", "timerModified")
1327 assert_lacks(out, "stopping the following units:")
1328 assert_lacks(out, "NOT restarting the following units:")
1329 assert_lacks(out, "reloading the following units:")
1330 assert_contains(out, "\nrestarting the following units: test-timer.timer\n")
1331 assert_lacks(out, "\nstarting the following units:")
1332 assert_lacks(out, "the following new units were started:")
1334 out = machine.succeed("systemctl show test-timer.timer")
1335 assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00")
1337 with subtest("targets"):
1338 # Modifying some special targets like hybrid-sleep.target does nothing
1339 out = switch_to_specialisation("${machine}", "hybridSleepModified")
1340 assert_contains(out, "stopping the following units: test-timer.timer\n")
1341 assert_lacks(out, "NOT restarting the following changed units:")
1342 assert_lacks(out, "reloading the following units:")
1343 assert_lacks(out, "\nrestarting the following units:")
1344 assert_lacks(out, "\nstarting the following units:")
1345 assert_lacks(out, "the following new units were started:")
1347 # Adding a new target starts it
1348 out = switch_to_specialisation("${machine}", "target")
1349 assert_lacks(out, "stopping the following units:")
1350 assert_lacks(out, "NOT restarting the following changed units:")
1351 assert_lacks(out, "reloading the following units:")
1352 assert_lacks(out, "\nrestarting the following units:")
1353 assert_lacks(out, "\nstarting the following units:")
1354 assert_contains(out, "the following new units were started: test-target.target\n")
1356 # Changing a target doesn't print anything because the unit is filtered
1357 machine.systemctl("start test-service.service")
1358 out = switch_to_specialisation("${machine}", "targetModified")
1359 assert_lacks(out, "stopping the following units:")
1360 assert_lacks(out, "NOT restarting the following changed units:")
1361 assert_lacks(out, "reloading the following units:")
1362 assert_lacks(out, "\nrestarting the following units:")
1363 assert_lacks(out, "\nstarting the following units:")
1364 assert_lacks(out, "the following new units were started:")
1365 machine.succeed("systemctl is-active test-service.service") # target was not restarted
1367 # With X-StopOnReconfiguration, the target gets stopped and started
1368 out = switch_to_specialisation("${machine}", "targetModifiedStopOnReconfig")
1369 assert_lacks(out, "stopping the following units:")
1370 assert_lacks(out, "NOT restarting the following changed units:")
1371 assert_lacks(out, "reloading the following units:")
1372 assert_lacks(out, "\nrestarting the following units:")
1373 assert_lacks(out, "\nstarting the following units:")
1374 assert_lacks(out, "the following new units were started:")
1375 machine.fail("systemctl is-active test-service.servce") # target was restarted
1377 # Remove the target by switching to the old specialisation
1378 out = switch_to_specialisation("${machine}", "timerModified")
1379 assert_contains(out, "stopping the following units: test-target.target\n")
1380 assert_lacks(out, "NOT restarting the following changed units:")
1381 assert_lacks(out, "reloading the following units:")
1382 assert_lacks(out, "\nrestarting the following units:")
1383 assert_lacks(out, "\nstarting the following units:")
1384 assert_contains(out, "the following new units were started: test-timer.timer\n")
1386 with subtest("paths"):
1387 out = switch_to_specialisation("${machine}", "path")
1388 assert_contains(out, "stopping the following units: test-timer.timer\n")
1389 assert_lacks(out, "NOT restarting the following changed units:")
1390 assert_lacks(out, "reloading the following units:")
1391 assert_lacks(out, "\nrestarting the following units:")
1392 assert_lacks(out, "\nstarting the following units:")
1393 assert_contains(out, "the following new units were started: test-watch.path\n")
1394 machine.fail("test -f /testpath-modified")
1396 # touch the file, unit should be triggered
1397 machine.succeed("touch /testpath")
1398 machine.wait_until_succeeds("test -f /testpath-modified")
1399 machine.succeed("rm /testpath /testpath-modified")
1400 machine.systemctl("stop test-watch.service")
1401 switch_to_specialisation("${machine}", "pathModified")
1402 machine.succeed("touch /testpath")
1403 machine.fail("test -f /testpath-modified")
1404 machine.succeed("touch /testpath2")
1405 machine.wait_until_succeeds("test -f /testpath-modified")
1407 # This test ensures that changes to slice configuration get applied.
1408 # We test this by having a slice that allows no memory allocation at
1409 # all and starting a service within it. If the service crashes, the slice
1410 # is applied and if we modify the slice to allow memory allocation, the
1411 # service should successfully start.
1412 with subtest("slices"):
1413 machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing
1414 out = switch_to_specialisation("${machine}", "slice")
1415 # assert_lacks(out, "stopping the following units:") not relevant
1416 assert_lacks(out, "NOT restarting the following changed units:")
1417 assert_lacks(out, "reloading the following units:")
1418 assert_lacks(out, "\nrestarting the following units:")
1419 assert_lacks(out, "\nstarting the following units:")
1420 assert_lacks(out, "the following new units were started:")
1421 machine.fail("systemctl start testservice.service")
1423 out = switch_to_specialisation("${machine}", "sliceModified")
1424 assert_lacks(out, "stopping the following units:")
1425 assert_lacks(out, "NOT restarting the following changed units:")
1426 assert_lacks(out, "reloading the following units:")
1427 assert_lacks(out, "\nrestarting the following units:")
1428 assert_lacks(out, "\nstarting the following units:")
1429 assert_lacks(out, "the following new units were started:")
1430 machine.succeed("systemctl start testservice.service")
1431 machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing