1 # Test configuration switching.
3 import ./make-test-python.nix ({ lib, 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 brokenInitInterface.configuration.config.system.extraSystemBuilderCmds = ''
62 echo "systemd 0" > $out/init-interface-version
65 modifiedSystemConf.configuration.systemd.extraConfig = ''
69 addedMount.configuration.virtualisation.fileSystems."/test" = {
74 addedMountOptsModified.configuration = {
75 imports = [ addedMount.configuration ];
76 virtualisation.fileSystems."/test".options = [ "x-test" ];
79 addedMountDevModified.configuration = {
80 imports = [ addedMountOptsModified.configuration ];
81 virtualisation.fileSystems."/test".device = lib.mkForce "ramfs";
84 storeMountModified.configuration = {
85 virtualisation.fileSystems."/".device = lib.mkForce "auto";
88 swap.configuration.swapDevices = lib.mkVMOverride [
89 { device = "/swapfile"; size = 1; }
92 simpleService.configuration = {
93 systemd.services.test = {
94 wantedBy = [ "multi-user.target" ];
97 RemainAfterExit = true;
98 ExecStart = "${pkgs.coreutils}/bin/true";
99 ExecReload = "${pkgs.coreutils}/bin/true";
104 simpleServiceSeparateActivationScript.configuration = {
105 system.activatable = false;
106 systemd.services.test = {
107 wantedBy = [ "multi-user.target" ];
110 RemainAfterExit = true;
111 ExecStart = "${pkgs.coreutils}/bin/true";
112 ExecReload = "${pkgs.coreutils}/bin/true";
117 simpleServiceDifferentDescription.configuration = {
118 imports = [ simpleService.configuration ];
119 systemd.services.test.description = "Test unit";
122 simpleServiceModified.configuration = {
123 imports = [ simpleService.configuration ];
124 systemd.services.test.serviceConfig.X-Test = true;
127 simpleServiceNostop.configuration = {
128 imports = [ simpleService.configuration ];
129 systemd.services.test.stopIfChanged = false;
132 simpleServiceReload.configuration = {
133 imports = [ simpleService.configuration ];
134 systemd.services.test = {
135 reloadIfChanged = true;
136 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
140 simpleServiceNorestart.configuration = {
141 imports = [ simpleService.configuration ];
142 systemd.services.test.restartIfChanged = false;
145 simpleServiceFailing.configuration = {
146 imports = [ simpleServiceModified.configuration ];
147 systemd.services.test.serviceConfig.ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false";
150 autorestartService.configuration = {
151 # A service that immediately goes into restarting (but without failing)
152 systemd.services.autorestart = {
153 wantedBy = [ "multi-user.target" ];
157 RestartSec = "20y"; # Should be long enough
158 ExecStart = "${pkgs.coreutils}/bin/true";
163 autorestartServiceFailing.configuration = {
164 imports = [ autorestartService.configuration ];
165 systemd.services.autorestart.serviceConfig = {
166 ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false";
170 simpleServiceWithExtraSection.configuration = {
171 imports = [ simpleServiceNostop.configuration ];
172 systemd.packages = [ (pkgs.writeTextFile {
173 name = "systemd-extra-section";
174 destination = "/etc/systemd/system/test.service";
182 simpleServiceWithExtraSectionOtherName.configuration = {
183 imports = [ simpleServiceNostop.configuration ];
184 systemd.packages = [ (pkgs.writeTextFile {
185 name = "systemd-extra-section";
186 destination = "/etc/systemd/system/test.service";
194 simpleServiceWithInstallSection.configuration = {
195 imports = [ simpleServiceNostop.configuration ];
196 systemd.packages = [ (pkgs.writeTextFile {
197 name = "systemd-extra-section";
198 destination = "/etc/systemd/system/test.service";
201 WantedBy=multi-user.target
206 simpleServiceWithExtraKey.configuration = {
207 imports = [ simpleServiceNostop.configuration ];
208 systemd.services.test.serviceConfig."X-Test" = "test";
211 simpleServiceWithExtraKeyOtherValue.configuration = {
212 imports = [ simpleServiceNostop.configuration ];
213 systemd.services.test.serviceConfig."X-Test" = "test2";
216 simpleServiceWithExtraKeyOtherName.configuration = {
217 imports = [ simpleServiceNostop.configuration ];
218 systemd.services.test.serviceConfig."X-Test2" = "test";
221 simpleServiceReloadTrigger.configuration = {
222 imports = [ simpleServiceNostop.configuration ];
223 systemd.services.test.reloadTriggers = [ "/dev/null" ];
226 simpleServiceReloadTriggerModified.configuration = {
227 imports = [ simpleServiceNostop.configuration ];
228 systemd.services.test.reloadTriggers = [ "/dev/zero" ];
231 simpleServiceReloadTriggerModifiedAndSomethingElse.configuration = {
232 imports = [ simpleServiceNostop.configuration ];
233 systemd.services.test = {
234 reloadTriggers = [ "/dev/zero" ];
235 serviceConfig."X-Test" = "test";
239 simpleServiceReloadTriggerModifiedSomethingElse.configuration = {
240 imports = [ simpleServiceNostop.configuration ];
241 systemd.services.test.serviceConfig."X-Test" = "test";
244 unitWithBackslash.configuration = {
245 systemd.services."escaped\\x2ddash" = {
246 wantedBy = [ "multi-user.target" ];
249 RemainAfterExit = true;
250 ExecStart = "${pkgs.coreutils}/bin/true";
251 ExecReload = "${pkgs.coreutils}/bin/true";
256 unitWithBackslashModified.configuration = {
257 imports = [ unitWithBackslash.configuration ];
258 systemd.services."escaped\\x2ddash".serviceConfig.X-Test = "test";
261 unitStartingWithDash.configuration = {
262 systemd.services."-" = {
263 wantedBy = [ "multi-user.target" ];
266 RemainAfterExit = true;
267 ExecStart = "${pkgs.coreutils}/bin/true";
272 unitStartingWithDashModified.configuration = {
273 imports = [ unitStartingWithDash.configuration ];
274 systemd.services."-" = {
275 reloadIfChanged = true;
276 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
280 unitWithRequirement.configuration = {
281 systemd.services.required-service = {
282 wantedBy = [ "multi-user.target" ];
285 RemainAfterExit = true;
286 ExecStart = "${pkgs.coreutils}/bin/true";
287 ExecReload = "${pkgs.coreutils}/bin/true";
290 systemd.services.test-service = {
291 wantedBy = [ "multi-user.target" ];
292 requires = [ "required-service.service" ];
295 RemainAfterExit = true;
296 ExecStart = "${pkgs.coreutils}/bin/true";
297 ExecReload = "${pkgs.coreutils}/bin/true";
302 unitWithRequirementModified.configuration = {
303 imports = [ unitWithRequirement.configuration ];
304 systemd.services.required-service.serviceConfig.X-Test = "test";
305 systemd.services.test-service.reloadTriggers = [ "test" ];
308 unitWithRequirementModifiedNostart.configuration = {
309 imports = [ unitWithRequirement.configuration ];
310 systemd.services.test-service.unitConfig.RefuseManualStart = true;
313 unitWithTemplate.configuration = {
314 systemd.services."instantiated@".serviceConfig = {
316 RemainAfterExit = true;
317 ExecStart = "${pkgs.coreutils}/bin/true";
318 ExecReload = "${pkgs.coreutils}/bin/true";
320 systemd.services."instantiated@one" = {
321 wantedBy = [ "multi-user.target" ];
322 overrideStrategy = "asDropin";
324 systemd.services."instantiated@two" = {
325 wantedBy = [ "multi-user.target" ];
326 overrideStrategy = "asDropin";
330 unitWithTemplateModified.configuration = {
331 imports = [ unitWithTemplate.configuration ];
332 systemd.services."instantiated@".serviceConfig.X-Test = "test";
335 restart-and-reload-by-activation-script.configuration = {
336 systemd.services = rec {
338 # No wantedBy so we can check if the activation script restart triggers them
341 RemainAfterExit = true;
342 ExecStart = "${pkgs.coreutils}/bin/true";
343 ExecReload = "${pkgs.coreutils}/bin/true";
346 "templated-simple-service@" = simple-service;
347 "templated-simple-service@instance".overrideStrategy = "asDropin";
349 simple-restart-service = simple-service // {
350 stopIfChanged = false;
352 "templated-simple-restart-service@" = simple-restart-service;
353 "templated-simple-restart-service@instance".overrideStrategy = "asDropin";
355 simple-reload-service = simple-service // {
356 reloadIfChanged = true;
358 "templated-simple-reload-service@" = simple-reload-service;
359 "templated-simple-reload-service@instance".overrideStrategy = "asDropin";
361 no-restart-service = simple-service // {
362 restartIfChanged = false;
364 "templated-no-restart-service@" = no-restart-service;
365 "templated-no-restart-service@instance".overrideStrategy = "asDropin";
367 reload-triggers = simple-service // {
368 wantedBy = [ "multi-user.target" ];
370 "templated-reload-triggers@" = simple-service;
371 "templated-reload-triggers@instance" = {
372 overrideStrategy = "asDropin";
373 wantedBy = [ "multi-user.target" ];
376 reload-triggers-and-restart-by-as = simple-service;
377 "templated-reload-triggers-and-restart-by-as@" = reload-triggers-and-restart-by-as;
378 "templated-reload-triggers-and-restart-by-as@instance".overrideStrategy = "asDropin";
380 reload-triggers-and-restart = simple-service // {
381 stopIfChanged = false; # easier to check for this
382 wantedBy = [ "multi-user.target" ];
384 "templated-reload-triggers-and-restart@" = simple-service;
385 "templated-reload-triggers-and-restart@instance" = {
386 overrideStrategy = "asDropin";
387 stopIfChanged = false; # easier to check for this
388 wantedBy = [ "multi-user.target" ];
392 system.activationScripts.restart-and-reload-test = {
393 supportsDryActivation = true;
396 if [ "$NIXOS_ACTION" = dry-activate ]; then
397 f=/run/nixos/dry-activation-restart-list
398 g=/run/nixos/dry-activation-reload-list
400 f=/run/nixos/activation-restart-list
401 g=/run/nixos/activation-reload-list
404 simple-service.service
405 simple-restart-service.service
406 simple-reload-service.service
407 no-restart-service.service
408 reload-triggers-and-restart-by-as.service
409 templated-simple-service@instance.service
410 templated-simple-restart-service@instance.service
411 templated-simple-reload-service@instance.service
412 templated-no-restart-service@instance.service
413 templated-reload-triggers-and-restart-by-as@instance.service
417 reload-triggers.service
418 reload-triggers-and-restart-by-as.service
419 reload-triggers-and-restart.service
420 templated-reload-triggers@instance.service
421 templated-reload-triggers-and-restart-by-as@instance.service
422 templated-reload-triggers-and-restart@instance.service
428 restart-and-reload-by-activation-script-modified.configuration = {
429 imports = [ restart-and-reload-by-activation-script.configuration ];
430 systemd.services.reload-triggers-and-restart.serviceConfig.X-Modified = "test";
431 systemd.services."templated-reload-triggers-and-restart@instance" = {
432 overrideStrategy = "asDropin";
433 serviceConfig.X-Modified = "test";
437 simple-socket.configuration = {
438 systemd.services.socket-activated = {
439 description = "A socket-activated service";
440 stopIfChanged = lib.mkDefault false;
442 ExecStart = socketTest;
443 ExecReload = "${pkgs.coreutils}/bin/true";
446 systemd.sockets.socket-activated = {
447 wantedBy = [ "sockets.target" ];
448 listenStreams = [ "/run/test.sock" ];
449 socketConfig.SocketMode = lib.mkDefault "0777";
453 simple-socket-service-modified.configuration = {
454 imports = [ simple-socket.configuration ];
455 systemd.services.socket-activated.serviceConfig.X-Test = "test";
458 simple-socket-stop-if-changed.configuration = {
459 imports = [ simple-socket.configuration ];
460 systemd.services.socket-activated.stopIfChanged = true;
463 simple-socket-stop-if-changed-and-reloadtrigger.configuration = {
464 imports = [ simple-socket.configuration ];
465 systemd.services.socket-activated = {
466 stopIfChanged = true;
467 reloadTriggers = [ "test" ];
471 mount.configuration = {
474 description = "Testmount";
477 where = "/testmount";
479 wantedBy = [ "local-fs.target" ];
484 mountOptionsModified.configuration = {
487 description = "Testmount";
490 where = "/testmount";
491 options = "size=10M";
492 wantedBy = [ "local-fs.target" ];
497 mountModified.configuration = {
500 description = "Testmount";
503 where = "/testmount";
504 options = "size=10M";
505 wantedBy = [ "local-fs.target" ];
510 timer.configuration = {
511 systemd.timers.test-timer = {
512 wantedBy = [ "timers.target" ];
513 timerConfig.OnCalendar = "@1395716396"; # chosen by fair dice roll
515 systemd.services.test-timer = {
518 ExecStart = "${pkgs.coreutils}/bin/true";
523 timerModified.configuration = {
524 imports = [ timer.configuration ];
525 systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00";
528 hybridSleepModified.configuration = {
529 systemd.targets.hybrid-sleep.unitConfig.X-Test = true;
532 target.configuration = {
533 systemd.targets.test-target.wantedBy = [ "multi-user.target" ];
534 # We use this service to figure out whether the target was modified.
535 # This is the only way because targets are filtered and therefore not
536 # printed when they are started/stopped.
537 systemd.services.test-service = {
538 bindsTo = [ "test-target.target" ];
539 serviceConfig.ExecStart = "${pkgs.coreutils}/bin/sleep infinity";
543 targetModified.configuration = {
544 imports = [ target.configuration ];
545 systemd.targets.test-target.unitConfig.X-Test = true;
548 targetModifiedStopOnReconfig.configuration = {
549 imports = [ target.configuration ];
550 systemd.targets.test-target.unitConfig.X-StopOnReconfiguration = true;
553 path.configuration = {
554 systemd.paths.test-watch = {
555 wantedBy = [ "paths.target" ];
556 pathConfig.PathExists = "/testpath";
558 systemd.services.test-watch = {
561 RemainAfterExit = true;
562 ExecStart = "${pkgs.coreutils}/bin/touch /testpath-modified";
567 pathModified.configuration = {
568 imports = [ path.configuration ];
569 systemd.paths.test-watch.pathConfig.PathExists = lib.mkForce "/testpath2";
572 slice.configuration = {
573 systemd.slices.testslice.sliceConfig.MemoryMax = "1"; # don't allow memory allocation
574 systemd.services.testservice = {
577 RemainAfterExit = true;
578 ExecStart = "${pkgs.coreutils}/bin/true";
579 Slice = "testslice.slice";
584 sliceModified.configuration = {
585 imports = [ slice.configuration ];
586 systemd.slices.testslice.sliceConfig.MemoryMax = lib.mkForce null;
592 users.mutableUsers = true;
596 testScript = { nodes, ... }: let
597 originalSystem = nodes.machine.system.build.toplevel;
598 otherSystem = nodes.other.system.build.toplevel;
599 machine = nodes.machine.system.build.toplevel;
601 # Ensures failures pass through using pipefail, otherwise failing to
602 # switch-to-configuration is hidden by the success of `tee`.
603 stderrRunner = pkgs.writeScript "stderr-runner" ''
604 #! ${pkgs.runtimeShell}
607 exec env -i "$@" | tee /dev/stderr
610 # Returns a comma separated representation of the given list in sorted
611 # order, that matches the output format of switch-to-configuration.pl
612 sortedUnits = xs: lib.concatStringsSep ", " (builtins.sort builtins.lessThan xs);
615 "dbus" = "dbus.service";
616 "broker" = "dbus-broker.service";
617 }.${nodes.machine.services.dbus.implementation};
619 def switch_to_specialisation(system, name, action="test", fail=False):
621 switcher = f"{system}/bin/switch-to-configuration"
623 switcher = f"{system}/specialisation/{name}/bin/switch-to-configuration"
624 return run_switch(switcher, action, fail)
626 # like above but stc = switcher
627 def run_switch(switcher, action="test", fail=False):
628 out = machine.fail(f"{switcher} {action} 2>&1") if fail \
629 else machine.succeed(f"{switcher} {action} 2>&1")
630 assert_lacks(out, "switch-to-configuration line") # Perl warnings
633 def assert_contains(haystack, needle):
634 if needle not in haystack:
635 print("The haystack that will cause the following exception is:")
639 raise Exception(f"Expected string '{needle}' was not found")
641 def assert_lacks(haystack, needle):
642 if needle in haystack:
643 print("The haystack that will cause the following exception is:")
645 print(haystack, end="")
647 raise Exception(f"Unexpected string '{needle}' was found")
650 machine.wait_for_unit("multi-user.target")
653 "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test"
655 # This tests whether the /etc/os-release parser works which is a fallback
656 # when /etc/NIXOS is missing. If the parser does not work, switch-to-configuration
658 machine.succeed("rm /etc/NIXOS")
660 "${stderrRunner} ${otherSystem}/bin/switch-to-configuration test"
664 with subtest("actions"):
666 machine.fail("test -f /tmp/bootloader-installed")
667 out = switch_to_specialisation("${machine}", "simpleService", action="boot")
668 assert_contains(out, "installing dummy bootloader")
669 assert_lacks(out, "activating the configuration...") # good indicator of a system activation
670 machine.succeed("test -f /tmp/bootloader-installed")
671 machine.succeed("rm /tmp/bootloader-installed")
674 machine.fail("test -f /tmp/bootloader-installed")
675 out = switch_to_specialisation("${machine}", "", action="switch")
676 assert_contains(out, "installing dummy bootloader")
677 assert_contains(out, "activating the configuration...") # good indicator of a system activation
678 machine.succeed("test -f /tmp/bootloader-installed")
680 # test and dry-activate actions are tested further down below
682 # invalid action fails the script
683 switch_to_specialisation("${machine}", "", action="broken-action", fail=True)
684 # no action fails the script
685 assert "Usage:" in machine.fail("${machine}/bin/switch-to-configuration 2>&1")
687 with subtest("init interface version"):
688 # Do not try to switch to an invalid init interface version
689 assert "incompatible" in switch_to_specialisation("${machine}", "brokenInitInterface", fail=True)
691 with subtest("systemd restarts"):
692 # systemd is restarted when its system.conf changes
693 out = switch_to_specialisation("${machine}", "modifiedSystemConf")
694 assert_contains(out, "restarting systemd...")
696 with subtest("continuing from an aborted switch"):
697 # An aborted switch will write into a file what it tried to start
698 # and a second switch should continue from this
699 machine.succeed("echo ${dbusService} > /run/nixos/start-list")
700 out = switch_to_specialisation("${machine}", "modifiedSystemConf")
701 assert_contains(out, "starting the following units: ${dbusService}\n")
703 with subtest("fstab mounts"):
704 switch_to_specialisation("${machine}", "")
706 out = switch_to_specialisation("${machine}", "addedMount")
707 assert_lacks(out, "stopping the following units:")
708 assert_lacks(out, "NOT restarting the following changed units:")
709 assert_lacks(out, "\nrestarting the following units:")
710 assert_lacks(out, "\nstarting the following units:")
711 assert_contains(out, "the following new units were started: test.mount\n")
712 # modify the mountpoint's options
713 out = switch_to_specialisation("${machine}", "addedMountOptsModified")
714 assert_lacks(out, "stopping the following units:")
715 assert_lacks(out, "NOT restarting the following changed units:")
716 assert_contains(out, "reloading the following units: test.mount\n")
717 assert_lacks(out, "\nrestarting the following units:")
718 assert_lacks(out, "\nstarting the following units:")
719 assert_lacks(out, "the following new units were started:")
721 out = switch_to_specialisation("${machine}", "addedMountDevModified")
722 assert_lacks(out, "stopping the following units:")
723 assert_lacks(out, "NOT restarting the following changed units:")
724 assert_lacks(out, "reloading the following units:")
725 assert_contains(out, "\nrestarting the following units: test.mount\n")
726 assert_lacks(out, "\nstarting the following units:")
727 assert_lacks(out, "the following new units were started:")
729 out = switch_to_specialisation("${machine}", "addedMount")
730 assert_lacks(out, "stopping the following units:")
731 assert_lacks(out, "NOT restarting the following changed units:")
732 assert_lacks(out, "reloading the following units:")
733 assert_contains(out, "\nrestarting the following units: test.mount\n")
734 assert_lacks(out, "\nstarting the following units:")
735 assert_lacks(out, "the following new units were started:")
737 out = switch_to_specialisation("${machine}", "")
738 assert_contains(out, "stopping the following units: test.mount\n")
739 assert_lacks(out, "NOT restarting the following changed units:")
740 assert_contains(out, "reloading the following units: ${dbusService}\n")
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 # change something about the / mount
745 out = switch_to_specialisation("${machine}", "storeMountModified")
746 assert_lacks(out, "stopping the following units:")
747 assert_contains(out, "NOT restarting the following changed units: -.mount")
748 assert_contains(out, "reloading the following units: ${dbusService}\n")
749 assert_lacks(out, "\nrestarting the following units:")
750 assert_lacks(out, "\nstarting the following units:")
751 assert_lacks(out, "the following new units were started:")
753 with subtest("swaps"):
754 switch_to_specialisation("${machine}", "")
756 out = switch_to_specialisation("${machine}", "swap")
757 assert_lacks(out, "stopping the following units:")
758 assert_lacks(out, "NOT restarting the following changed units:")
759 assert_contains(out, "reloading the following units: ${dbusService}\n")
760 assert_lacks(out, "\nrestarting the following units:")
761 assert_lacks(out, "\nstarting the following units:")
762 assert_contains(out, "the following new units were started: swapfile.swap")
764 out = switch_to_specialisation("${machine}", "")
765 assert_contains(out, "stopping swap device: /swapfile")
766 assert_lacks(out, "stopping the following units:")
767 assert_lacks(out, "NOT restarting the following changed units:")
768 assert_contains(out, "reloading the following units: ${dbusService}\n")
769 assert_lacks(out, "\nrestarting the following units:")
770 assert_lacks(out, "\nstarting the following units:")
771 assert_lacks(out, "the following new units were started:")
773 with subtest("services"):
774 switch_to_specialisation("${machine}", "")
775 # Nothing happens when nothing is changed
776 out = switch_to_specialisation("${machine}", "")
777 assert_lacks(out, "stopping the following units:")
778 assert_lacks(out, "NOT restarting the following changed units:")
779 assert_lacks(out, "reloading the following units:")
780 assert_lacks(out, "\nrestarting the following units:")
781 assert_lacks(out, "\nstarting the following units:")
782 assert_lacks(out, "the following new units were started:")
784 # Start a simple service
785 out = switch_to_specialisation("${machine}", "simpleService")
786 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader
787 assert_lacks(out, "stopping the following units:")
788 assert_lacks(out, "NOT restarting the following changed units:")
789 assert_contains(out, "reloading the following units: ${dbusService}\n") # huh
790 assert_lacks(out, "\nrestarting the following units:")
791 assert_lacks(out, "\nstarting the following units:")
792 assert_contains(out, "the following new units were started: test.service\n")
794 # Not changing anything doesn't do anything
795 out = switch_to_specialisation("${machine}", "simpleService")
796 assert_lacks(out, "stopping the following units:")
797 assert_lacks(out, "NOT restarting the following changed units:")
798 assert_lacks(out, "reloading the following units:")
799 assert_lacks(out, "\nrestarting the following units:")
800 assert_lacks(out, "\nstarting the following units:")
801 assert_lacks(out, "the following new units were started:")
803 # Only changing the description does nothing
804 out = switch_to_specialisation("${machine}", "simpleServiceDifferentDescription")
805 assert_lacks(out, "stopping the following units:")
806 assert_lacks(out, "NOT restarting the following changed units:")
807 assert_lacks(out, "reloading the following units:")
808 assert_lacks(out, "\nrestarting the following units:")
809 assert_lacks(out, "\nstarting the following units:")
810 assert_lacks(out, "the following new units were started:")
812 # Restart the simple service
813 out = switch_to_specialisation("${machine}", "simpleServiceModified")
814 assert_contains(out, "stopping the following units: test.service\n")
815 assert_lacks(out, "NOT restarting the following changed units:")
816 assert_lacks(out, "reloading the following units:")
817 assert_lacks(out, "\nrestarting the following units:")
818 assert_contains(out, "\nstarting the following units: test.service\n")
819 assert_lacks(out, "the following new units were started:")
821 # Restart the service with stopIfChanged=false
822 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
823 assert_lacks(out, "stopping the following units:")
824 assert_lacks(out, "NOT restarting the following changed units:")
825 assert_lacks(out, "reloading the following units:")
826 assert_contains(out, "\nrestarting the following units: test.service\n")
827 assert_lacks(out, "\nstarting the following units:")
828 assert_lacks(out, "the following new units were started:")
830 # Reload the service with reloadIfChanged=true
831 out = switch_to_specialisation("${machine}", "simpleServiceReload")
832 assert_lacks(out, "stopping the following units:")
833 assert_lacks(out, "NOT restarting the following changed units:")
834 assert_contains(out, "reloading the following units: test.service\n")
835 assert_lacks(out, "\nrestarting the following units:")
836 assert_lacks(out, "\nstarting the following units:")
837 assert_lacks(out, "the following new units were started:")
839 # Nothing happens when restartIfChanged=false
840 out = switch_to_specialisation("${machine}", "simpleServiceNorestart")
841 assert_lacks(out, "stopping the following units:")
842 assert_contains(out, "NOT restarting the following changed units: test.service\n")
843 assert_lacks(out, "reloading the following units:")
844 assert_lacks(out, "\nrestarting the following units:")
845 assert_lacks(out, "\nstarting the following units:")
846 assert_lacks(out, "the following new units were started:")
848 # Dry mode shows different messages
849 out = switch_to_specialisation("${machine}", "simpleService", action="dry-activate")
850 assert_lacks(out, "stopping the following units:")
851 assert_lacks(out, "NOT restarting the following changed units:")
852 assert_lacks(out, "reloading the following units:")
853 assert_lacks(out, "\nrestarting the following units:")
854 assert_lacks(out, "\nstarting the following units:")
855 assert_lacks(out, "the following new units were started:")
856 assert_contains(out, "would start the following units: test.service\n")
858 out = switch_to_specialisation("${machine}", "", action="test")
860 # Ensure the service can be started when the activation script isn't in toplevel
861 # This is a lot like "Start a simple service", except activation-only deps could be gc-ed
862 out = run_switch("${nodes.machine.specialisation.simpleServiceSeparateActivationScript.configuration.system.build.separateActivationScript}/bin/switch-to-configuration");
863 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader
864 assert_lacks(out, "stopping the following units:")
865 assert_lacks(out, "NOT restarting the following changed units:")
866 assert_contains(out, "reloading the following units: ${dbusService}\n") # huh
867 assert_lacks(out, "\nrestarting the following units:")
868 assert_lacks(out, "\nstarting the following units:")
869 assert_contains(out, "the following new units were started: test.service\n")
870 machine.succeed("! test -e /run/current-system/activate")
871 machine.succeed("! test -e /run/current-system/dry-activate")
872 machine.succeed("! test -e /run/current-system/bin/switch-to-configuration")
874 # Ensure \ works in unit names
875 out = switch_to_specialisation("${machine}", "unitWithBackslash")
876 assert_contains(out, "stopping the following units: test.service\n")
877 assert_lacks(out, "NOT restarting the following changed units:")
878 assert_lacks(out, "reloading the following units:")
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: escaped\\x2ddash.service\n")
883 out = switch_to_specialisation("${machine}", "unitWithBackslashModified")
884 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
885 assert_lacks(out, "NOT restarting the following changed units:")
886 assert_lacks(out, "reloading the following units:")
887 assert_lacks(out, "\nrestarting the following units:")
888 assert_contains(out, "\nstarting the following units: escaped\\x2ddash.service\n")
889 assert_lacks(out, "the following new units were started:")
891 # Ensure units can start with a dash
892 out = switch_to_specialisation("${machine}", "unitStartingWithDash")
893 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
894 assert_lacks(out, "NOT restarting the following changed units:")
895 assert_lacks(out, "reloading the following units:")
896 assert_lacks(out, "\nrestarting the following units:")
897 assert_lacks(out, "\nstarting the following units:")
898 assert_contains(out, "the following new units were started: -.service\n")
900 # The regression only occurs when reloading units
901 out = switch_to_specialisation("${machine}", "unitStartingWithDashModified")
902 assert_lacks(out, "stopping the following units:")
903 assert_lacks(out, "NOT restarting the following changed units:")
904 assert_contains(out, "reloading the following units: -.service")
905 assert_lacks(out, "\nrestarting the following units:")
906 assert_lacks(out, "\nstarting the following units:")
907 assert_lacks(out, "the following new units were started:")
909 # Ensure units that require changed units are properly reloaded
910 out = switch_to_specialisation("${machine}", "unitWithRequirement")
911 assert_contains(out, "stopping the following units: -.service\n")
912 assert_lacks(out, "NOT restarting the following changed units:")
913 assert_lacks(out, "reloading the following units:")
914 assert_lacks(out, "\nrestarting the following units:")
915 assert_lacks(out, "\nstarting the following units:")
916 assert_contains(out, "the following new units were started: required-service.service, test-service.service\n")
918 out = switch_to_specialisation("${machine}", "unitWithRequirementModified")
919 assert_contains(out, "stopping the following units: required-service.service\n")
920 assert_lacks(out, "NOT restarting the following changed units:")
921 assert_lacks(out, "reloading the following units:")
922 assert_lacks(out, "\nrestarting the following units:")
923 assert_contains(out, "\nstarting the following units: required-service.service, test-service.service\n")
924 assert_lacks(out, "the following new units were started:")
926 # Unless the unit asks to be not restarted
927 out = switch_to_specialisation("${machine}", "unitWithRequirementModifiedNostart")
928 assert_contains(out, "stopping the following units: required-service.service\n")
929 assert_lacks(out, "NOT restarting the following changed units:")
930 assert_lacks(out, "reloading the following units:")
931 assert_lacks(out, "\nrestarting the following units:")
932 assert_contains(out, "\nstarting the following units: required-service.service\n")
933 assert_lacks(out, "the following new units were started:")
935 # Ensure templated units are restarted when the base unit changes
936 switch_to_specialisation("${machine}", "unitWithTemplate")
937 out = switch_to_specialisation("${machine}", "unitWithTemplateModified")
938 assert_contains(out, "stopping the following units: instantiated@one.service, instantiated@two.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: instantiated@one.service, instantiated@two.service\n")
943 assert_lacks(out, "the following new units were started:")
945 with subtest("failing units"):
946 # Let the simple service fail
947 switch_to_specialisation("${machine}", "simpleServiceModified")
948 out = switch_to_specialisation("${machine}", "simpleServiceFailing", fail=True)
949 assert_contains(out, "stopping the following units: test.service\n")
950 assert_lacks(out, "NOT restarting the following changed units:")
951 assert_lacks(out, "reloading the following units:")
952 assert_lacks(out, "\nrestarting the following units:")
953 assert_contains(out, "\nstarting the following units: test.service\n")
954 assert_lacks(out, "the following new units were started:")
955 assert_contains(out, "warning: the following units failed: test.service\n")
956 assert_contains(out, "Main PID:") # output of systemctl
958 # A unit that gets into autorestart without failing is not treated as failed
959 out = switch_to_specialisation("${machine}", "autorestartService")
960 assert_lacks(out, "stopping the following units:")
961 assert_lacks(out, "NOT restarting the following changed units:")
962 assert_lacks(out, "reloading the following units:")
963 assert_lacks(out, "\nrestarting the following units:")
964 assert_lacks(out, "\nstarting the following units:")
965 assert_contains(out, "the following new units were started: autorestart.service\n")
966 machine.systemctl('stop autorestart.service') # cancel the 20y timer
968 # Switching to the same system should do nothing (especially not treat the unit as failed)
969 out = switch_to_specialisation("${machine}", "autorestartService")
970 assert_lacks(out, "stopping the following units:")
971 assert_lacks(out, "NOT restarting the following changed units:")
972 assert_lacks(out, "reloading the following units:")
973 assert_lacks(out, "\nrestarting the following units:")
974 assert_lacks(out, "\nstarting the following units:")
975 assert_contains(out, "the following new units were started: autorestart.service\n")
976 machine.systemctl('stop autorestart.service') # cancel the 20y timer
978 # If systemd thinks the unit has failed and is in autorestart, we should show it as failed
979 out = switch_to_specialisation("${machine}", "autorestartServiceFailing", fail=True)
980 assert_lacks(out, "stopping the following units:")
981 assert_lacks(out, "NOT restarting the following changed units:")
982 assert_lacks(out, "reloading the following units:")
983 assert_lacks(out, "\nrestarting the following units:")
984 assert_lacks(out, "\nstarting the following units:")
985 assert_lacks(out, "the following new units were started:")
986 assert_contains(out, "warning: the following units failed: autorestart.service\n")
987 assert_contains(out, "Main PID:") # output of systemctl
989 with subtest("unit file parser"):
990 # Switch to a well-known state
991 switch_to_specialisation("${machine}", "simpleServiceNostop")
994 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSection")
995 assert_lacks(out, "stopping the following units:")
996 assert_lacks(out, "NOT restarting the following changed units:")
997 assert_lacks(out, "reloading the following units:")
998 assert_contains(out, "\nrestarting the following units: test.service\n")
999 assert_lacks(out, "\nstarting the following units:")
1000 assert_lacks(out, "the following new units were started:")
1003 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSectionOtherName")
1004 assert_lacks(out, "stopping the following units:")
1005 assert_lacks(out, "NOT restarting the following changed units:")
1006 assert_lacks(out, "reloading the following units:")
1007 assert_contains(out, "\nrestarting the following units: test.service\n")
1008 assert_lacks(out, "\nstarting the following units:")
1009 assert_lacks(out, "the following new units were started:")
1012 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
1013 assert_lacks(out, "stopping the following units:")
1014 assert_lacks(out, "NOT restarting the following changed units:")
1015 assert_lacks(out, "reloading the following units:")
1016 assert_contains(out, "\nrestarting the following units: test.service\n")
1017 assert_lacks(out, "\nstarting the following units:")
1018 assert_lacks(out, "the following new units were started:")
1020 # [Install] section is ignored
1021 out = switch_to_specialisation("${machine}", "simpleServiceWithInstallSection")
1022 assert_lacks(out, "stopping the following units:")
1023 assert_lacks(out, "NOT restarting the following changed units:")
1024 assert_lacks(out, "reloading the following units:")
1025 assert_lacks(out, "\nrestarting the following units:")
1026 assert_lacks(out, "\nstarting the following units:")
1027 assert_lacks(out, "the following new units were started:")
1030 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKey")
1031 assert_lacks(out, "stopping the following units:")
1032 assert_lacks(out, "NOT restarting the following changed units:")
1033 assert_lacks(out, "reloading the following units:")
1034 assert_contains(out, "\nrestarting the following units: test.service\n")
1035 assert_lacks(out, "\nstarting the following units:")
1036 assert_lacks(out, "the following new units were started:")
1039 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherValue")
1040 assert_lacks(out, "stopping the following units:")
1041 assert_lacks(out, "NOT restarting the following changed units:")
1042 assert_lacks(out, "reloading the following units:")
1043 assert_contains(out, "\nrestarting the following units: test.service\n")
1044 assert_lacks(out, "\nstarting the following units:")
1045 assert_lacks(out, "the following new units were started:")
1048 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherName")
1049 assert_lacks(out, "stopping the following units:")
1050 assert_lacks(out, "NOT restarting the following changed units:")
1051 assert_lacks(out, "reloading the following units:")
1052 assert_contains(out, "\nrestarting the following units: test.service\n")
1053 assert_lacks(out, "\nstarting the following units:")
1054 assert_lacks(out, "the following new units were started:")
1057 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
1058 assert_lacks(out, "stopping the following units:")
1059 assert_lacks(out, "NOT restarting the following changed units:")
1060 assert_lacks(out, "reloading the following units:")
1061 assert_contains(out, "\nrestarting the following units: test.service\n")
1062 assert_lacks(out, "\nstarting the following units:")
1063 assert_lacks(out, "the following new units were started:")
1065 # Add a reload trigger
1066 out = switch_to_specialisation("${machine}", "simpleServiceReloadTrigger")
1067 assert_lacks(out, "stopping the following units:")
1068 assert_lacks(out, "NOT restarting the following changed units:")
1069 assert_contains(out, "reloading the following units: test.service\n")
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:")
1074 # Modify the reload trigger
1075 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModified")
1076 assert_lacks(out, "stopping the following units:")
1077 assert_lacks(out, "NOT restarting the following changed units:")
1078 assert_contains(out, "reloading the following units: test.service\n")
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:")
1083 # Modify the reload trigger and something else
1084 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedAndSomethingElse")
1085 assert_lacks(out, "stopping the following units:")
1086 assert_lacks(out, "NOT restarting the following changed units:")
1087 assert_lacks(out, "reloading the following units:")
1088 assert_contains(out, "\nrestarting the following units: test.service\n")
1089 assert_lacks(out, "\nstarting the following units:")
1090 assert_lacks(out, "the following new units were started:")
1092 # Remove the reload trigger
1093 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedSomethingElse")
1094 assert_lacks(out, "stopping the following units:")
1095 assert_lacks(out, "NOT restarting the following changed units:")
1096 assert_lacks(out, "reloading the following units:")
1097 assert_lacks(out, "\nrestarting the following units:")
1098 assert_lacks(out, "\nstarting the following units:")
1099 assert_lacks(out, "the following new units were started:")
1101 with subtest("restart and reload by activation script"):
1102 switch_to_specialisation("${machine}", "simpleServiceNorestart")
1103 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
1104 assert_contains(out, "stopping the following units: test.service\n")
1105 assert_lacks(out, "NOT restarting the following changed units:")
1106 assert_lacks(out, "reloading the following units:")
1107 assert_lacks(out, "restarting the following units:")
1108 assert_contains(out, "\nstarting the following units: ${sortedUnits [
1109 "no-restart-service.service"
1110 "reload-triggers-and-restart-by-as.service"
1111 "simple-reload-service.service"
1112 "simple-restart-service.service"
1113 "simple-service.service"
1114 "templated-no-restart-service@instance.service"
1115 "templated-reload-triggers-and-restart-by-as@instance.service"
1116 "templated-simple-reload-service@instance.service"
1117 "templated-simple-restart-service@instance.service"
1118 "templated-simple-service@instance.service"
1120 assert_contains(out, "the following new units were started: ${sortedUnits [
1121 "no-restart-service.service"
1122 "reload-triggers-and-restart-by-as.service"
1123 "reload-triggers-and-restart.service"
1124 "reload-triggers.service"
1125 "simple-reload-service.service"
1126 "simple-restart-service.service"
1127 "simple-service.service"
1128 "system-templated\\\\x2dno\\\\x2drestart\\\\x2dservice.slice"
1129 "system-templated\\\\x2dreload\\\\x2dtriggers.slice"
1130 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart.slice"
1131 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart\\\\x2dby\\\\x2das.slice"
1132 "system-templated\\\\x2dsimple\\\\x2dreload\\\\x2dservice.slice"
1133 "system-templated\\\\x2dsimple\\\\x2drestart\\\\x2dservice.slice"
1134 "system-templated\\\\x2dsimple\\\\x2dservice.slice"
1135 "templated-no-restart-service@instance.service"
1136 "templated-reload-triggers-and-restart-by-as@instance.service"
1137 "templated-reload-triggers-and-restart@instance.service"
1138 "templated-reload-triggers@instance.service"
1139 "templated-simple-reload-service@instance.service"
1140 "templated-simple-restart-service@instance.service"
1141 "templated-simple-service@instance.service"
1143 # Switch to the same system where the example services get restarted
1144 # and reloaded by the activation script
1145 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
1146 assert_lacks(out, "stopping the following units:")
1147 assert_lacks(out, "NOT restarting the following changed units:")
1148 assert_contains(out, "reloading the following units: ${sortedUnits [
1149 "reload-triggers-and-restart.service"
1150 "reload-triggers.service"
1151 "simple-reload-service.service"
1152 "templated-reload-triggers-and-restart@instance.service"
1153 "templated-reload-triggers@instance.service"
1154 "templated-simple-reload-service@instance.service"
1156 assert_contains(out, "restarting the following units: ${sortedUnits [
1157 "reload-triggers-and-restart-by-as.service"
1158 "simple-restart-service.service"
1159 "simple-service.service"
1160 "templated-reload-triggers-and-restart-by-as@instance.service"
1161 "templated-simple-restart-service@instance.service"
1162 "templated-simple-service@instance.service"
1164 assert_lacks(out, "\nstarting the following units:")
1165 assert_lacks(out, "the following new units were started:")
1166 # Switch to the same system and see if the service gets restarted when it's modified
1167 # while the fact that it's supposed to be reloaded by the activation script is ignored.
1168 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified")
1169 assert_lacks(out, "stopping the following units:")
1170 assert_lacks(out, "NOT restarting the following changed units:")
1171 assert_contains(out, "reloading the following units: ${sortedUnits [
1172 "reload-triggers.service"
1173 "simple-reload-service.service"
1174 "templated-reload-triggers@instance.service"
1175 "templated-simple-reload-service@instance.service"
1177 assert_contains(out, "restarting the following units: ${sortedUnits [
1178 "reload-triggers-and-restart-by-as.service"
1179 "reload-triggers-and-restart.service"
1180 "simple-restart-service.service"
1181 "simple-service.service"
1182 "templated-reload-triggers-and-restart-by-as@instance.service"
1183 "templated-reload-triggers-and-restart@instance.service"
1184 "templated-simple-restart-service@instance.service"
1185 "templated-simple-service@instance.service"
1187 assert_lacks(out, "\nstarting the following units:")
1188 assert_lacks(out, "the following new units were started:")
1189 # The same, but in dry mode
1190 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate")
1191 assert_lacks(out, "would stop the following units:")
1192 assert_lacks(out, "would NOT stop the following changed units:")
1193 assert_contains(out, "would reload the following units: ${sortedUnits [
1194 "reload-triggers.service"
1195 "simple-reload-service.service"
1196 "templated-reload-triggers@instance.service"
1197 "templated-simple-reload-service@instance.service"
1199 assert_contains(out, "would restart the following units: ${sortedUnits [
1200 "reload-triggers-and-restart-by-as.service"
1201 "reload-triggers-and-restart.service"
1202 "simple-restart-service.service"
1203 "simple-service.service"
1204 "templated-reload-triggers-and-restart-by-as@instance.service"
1205 "templated-reload-triggers-and-restart@instance.service"
1206 "templated-simple-restart-service@instance.service"
1207 "templated-simple-service@instance.service"
1209 assert_lacks(out, "\nwould start the following units:")
1211 with subtest("socket-activated services"):
1212 # Socket-activated services don't get started, just the socket
1213 machine.fail("[ -S /run/test.sock ]")
1214 out = switch_to_specialisation("${machine}", "simple-socket")
1215 # assert_lacks(out, "stopping the following units:") not relevant
1216 assert_lacks(out, "NOT restarting the following changed units:")
1217 assert_lacks(out, "reloading the following units:")
1218 assert_lacks(out, "\nrestarting the following units:")
1219 assert_lacks(out, "\nstarting the following units:")
1220 assert_contains(out, "the following new units were started: socket-activated.socket\n")
1221 machine.succeed("[ -S /run/test.sock ]")
1223 # Changing a non-activated service does nothing
1224 out = switch_to_specialisation("${machine}", "simple-socket-service-modified")
1225 assert_lacks(out, "stopping the following units:")
1226 assert_lacks(out, "NOT restarting the following changed units:")
1227 assert_lacks(out, "reloading the following units:")
1228 assert_lacks(out, "\nrestarting the following units:")
1229 assert_lacks(out, "\nstarting the following units:")
1230 assert_lacks(out, "the following new units were started:")
1231 machine.succeed("[ -S /run/test.sock ]")
1232 # The unit is properly activated when the socket is accessed
1233 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1234 raise Exception("Socket was not properly activated") # idk how that would happen tbh
1236 # Changing an activated service with stopIfChanged=false restarts the service
1237 out = switch_to_specialisation("${machine}", "simple-socket")
1238 assert_lacks(out, "stopping the following units:")
1239 assert_lacks(out, "NOT restarting the following changed units:")
1240 assert_lacks(out, "reloading the following units:")
1241 assert_contains(out, "\nrestarting the following units: socket-activated.service\n")
1242 assert_lacks(out, "\nstarting the following units:")
1243 assert_lacks(out, "the following new units were started:")
1244 machine.succeed("[ -S /run/test.sock ]")
1245 # Socket-activation of the unit still works
1246 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1247 raise Exception("Socket was not properly activated after the service was restarted")
1249 # Changing an activated service with stopIfChanged=true stops the service and
1250 # socket and starts the socket
1251 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed")
1252 assert_contains(out, "stopping the following units: socket-activated.service, socket-activated.socket\n")
1253 assert_lacks(out, "NOT restarting the following changed units:")
1254 assert_lacks(out, "reloading the following units:")
1255 assert_lacks(out, "\nrestarting the following units:")
1256 assert_contains(out, "\nstarting the following units: socket-activated.socket\n")
1257 assert_lacks(out, "the following new units were started:")
1258 machine.succeed("[ -S /run/test.sock ]")
1259 # Socket-activation of the unit still works
1260 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1261 raise Exception("Socket was not properly activated after the service was restarted")
1263 # Changing a reload trigger of a socket-activated unit only reloads it
1264 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed-and-reloadtrigger")
1265 assert_lacks(out, "stopping the following units:")
1266 assert_lacks(out, "NOT restarting the following changed units:")
1267 assert_contains(out, "reloading the following units: socket-activated.service\n")
1268 assert_lacks(out, "\nrestarting the following units:")
1269 assert_lacks(out, "\nstarting the following units: socket-activated.socket")
1270 assert_lacks(out, "the following new units were started:")
1271 machine.succeed("[ -S /run/test.sock ]")
1272 # Socket-activation of the unit still works
1273 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1274 raise Exception("Socket was not properly activated after the service was restarted")
1276 with subtest("mounts"):
1277 switch_to_specialisation("${machine}", "mount")
1278 out = machine.succeed("mount | grep 'on /testmount'")
1279 assert_contains(out, "size=1024k")
1280 # Changing options reloads the unit
1281 out = switch_to_specialisation("${machine}", "mountOptionsModified")
1282 assert_lacks(out, "stopping the following units:")
1283 assert_lacks(out, "NOT restarting the following changed units:")
1284 assert_contains(out, "reloading the following units: testmount.mount\n")
1285 assert_lacks(out, "\nrestarting the following units:")
1286 assert_lacks(out, "\nstarting the following units:")
1287 assert_lacks(out, "the following new units were started:")
1289 out = machine.succeed("mount | grep 'on /testmount'")
1290 assert_contains(out, "size=10240k")
1291 # Changing anything but `Options=` restarts the unit
1292 out = switch_to_specialisation("${machine}", "mountModified")
1293 assert_lacks(out, "stopping the following units:")
1294 assert_lacks(out, "NOT restarting the following changed units:")
1295 assert_lacks(out, "reloading the following units:")
1296 assert_contains(out, "\nrestarting the following units: testmount.mount\n")
1297 assert_lacks(out, "\nstarting the following units:")
1298 assert_lacks(out, "the following new units were started:")
1300 out = machine.succeed("mount | grep 'on /testmount'")
1301 assert_contains(out, "ramfs")
1303 with subtest("timers"):
1304 switch_to_specialisation("${machine}", "timer")
1305 out = machine.succeed("systemctl show test-timer.timer")
1306 assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC")
1307 out = switch_to_specialisation("${machine}", "timerModified")
1308 assert_lacks(out, "stopping the following units:")
1309 assert_lacks(out, "NOT restarting the following units:")
1310 assert_lacks(out, "reloading the following units:")
1311 assert_contains(out, "\nrestarting the following units: test-timer.timer\n")
1312 assert_lacks(out, "\nstarting the following units:")
1313 assert_lacks(out, "the following new units were started:")
1315 out = machine.succeed("systemctl show test-timer.timer")
1316 assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00")
1318 with subtest("targets"):
1319 # Modifying some special targets like hybrid-sleep.target does nothing
1320 out = switch_to_specialisation("${machine}", "hybridSleepModified")
1321 assert_contains(out, "stopping the following units: test-timer.timer\n")
1322 assert_lacks(out, "NOT restarting the following changed units:")
1323 assert_lacks(out, "reloading the following units:")
1324 assert_lacks(out, "\nrestarting the following units:")
1325 assert_lacks(out, "\nstarting the following units:")
1326 assert_lacks(out, "the following new units were started:")
1328 # Adding a new target starts it
1329 out = switch_to_specialisation("${machine}", "target")
1330 assert_lacks(out, "stopping the following units:")
1331 assert_lacks(out, "NOT restarting the following changed units:")
1332 assert_lacks(out, "reloading the following units:")
1333 assert_lacks(out, "\nrestarting the following units:")
1334 assert_lacks(out, "\nstarting the following units:")
1335 assert_contains(out, "the following new units were started: test-target.target\n")
1337 # Changing a target doesn't print anything because the unit is filtered
1338 machine.systemctl("start test-service.service")
1339 out = switch_to_specialisation("${machine}", "targetModified")
1340 assert_lacks(out, "stopping the following units:")
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:")
1346 machine.succeed("systemctl is-active test-service.service") # target was not restarted
1348 # With X-StopOnReconfiguration, the target gets stopped and started
1349 out = switch_to_specialisation("${machine}", "targetModifiedStopOnReconfig")
1350 assert_lacks(out, "stopping the following units:")
1351 assert_lacks(out, "NOT restarting the following changed units:")
1352 assert_lacks(out, "reloading the following units:")
1353 assert_lacks(out, "\nrestarting the following units:")
1354 assert_lacks(out, "\nstarting the following units:")
1355 assert_lacks(out, "the following new units were started:")
1356 machine.fail("systemctl is-active test-service.servce") # target was restarted
1358 # Remove the target by switching to the old specialisation
1359 out = switch_to_specialisation("${machine}", "timerModified")
1360 assert_contains(out, "stopping the following units: test-target.target\n")
1361 assert_lacks(out, "NOT restarting the following changed units:")
1362 assert_lacks(out, "reloading the following units:")
1363 assert_lacks(out, "\nrestarting the following units:")
1364 assert_lacks(out, "\nstarting the following units:")
1365 assert_contains(out, "the following new units were started: test-timer.timer\n")
1367 with subtest("paths"):
1368 out = switch_to_specialisation("${machine}", "path")
1369 assert_contains(out, "stopping the following units: test-timer.timer\n")
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_contains(out, "the following new units were started: test-watch.path\n")
1375 machine.fail("test -f /testpath-modified")
1377 # touch the file, unit should be triggered
1378 machine.succeed("touch /testpath")
1379 machine.wait_until_succeeds("test -f /testpath-modified")
1380 machine.succeed("rm /testpath /testpath-modified")
1381 machine.systemctl("stop test-watch.service")
1382 switch_to_specialisation("${machine}", "pathModified")
1383 machine.succeed("touch /testpath")
1384 machine.fail("test -f /testpath-modified")
1385 machine.succeed("touch /testpath2")
1386 machine.wait_until_succeeds("test -f /testpath-modified")
1388 # This test ensures that changes to slice configuration get applied.
1389 # We test this by having a slice that allows no memory allocation at
1390 # all and starting a service within it. If the service crashes, the slice
1391 # is applied and if we modify the slice to allow memory allocation, the
1392 # service should successfully start.
1393 with subtest("slices"):
1394 machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing
1395 out = switch_to_specialisation("${machine}", "slice")
1396 # assert_lacks(out, "stopping the following units:") not relevant
1397 assert_lacks(out, "NOT restarting the following changed units:")
1398 assert_lacks(out, "reloading the following units:")
1399 assert_lacks(out, "\nrestarting the following units:")
1400 assert_lacks(out, "\nstarting the following units:")
1401 assert_lacks(out, "the following new units were started:")
1402 machine.fail("systemctl start testservice.service")
1404 out = switch_to_specialisation("${machine}", "sliceModified")
1405 assert_lacks(out, "stopping the following units:")
1406 assert_lacks(out, "NOT restarting the following changed units:")
1407 assert_lacks(out, "reloading the following units:")
1408 assert_lacks(out, "\nrestarting the following units:")
1409 assert_lacks(out, "\nstarting the following units:")
1410 assert_lacks(out, "the following new units were started:")
1411 machine.succeed("systemctl start testservice.service")
1412 machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing