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);
614 def switch_to_specialisation(system, name, action="test", fail=False):
616 switcher = f"{system}/bin/switch-to-configuration"
618 switcher = f"{system}/specialisation/{name}/bin/switch-to-configuration"
619 return run_switch(switcher, action, fail)
621 # like above but stc = switcher
622 def run_switch(switcher, action="test", fail=False):
623 out = machine.fail(f"{switcher} {action} 2>&1") if fail \
624 else machine.succeed(f"{switcher} {action} 2>&1")
625 assert_lacks(out, "switch-to-configuration line") # Perl warnings
628 def assert_contains(haystack, needle):
629 if needle not in haystack:
630 print("The haystack that will cause the following exception is:")
634 raise Exception(f"Expected string '{needle}' was not found")
636 def assert_lacks(haystack, needle):
637 if needle in haystack:
638 print("The haystack that will cause the following exception is:")
640 print(haystack, end="")
642 raise Exception(f"Unexpected string '{needle}' was found")
645 machine.wait_for_unit("multi-user.target")
648 "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test"
650 # This tests whether the /etc/os-release parser works which is a fallback
651 # when /etc/NIXOS is missing. If the parser does not work, switch-to-configuration
653 machine.succeed("rm /etc/NIXOS")
655 "${stderrRunner} ${otherSystem}/bin/switch-to-configuration test"
659 with subtest("actions"):
661 machine.fail("test -f /tmp/bootloader-installed")
662 out = switch_to_specialisation("${machine}", "simpleService", action="boot")
663 assert_contains(out, "installing dummy bootloader")
664 assert_lacks(out, "activating the configuration...") # good indicator of a system activation
665 machine.succeed("test -f /tmp/bootloader-installed")
666 machine.succeed("rm /tmp/bootloader-installed")
669 machine.fail("test -f /tmp/bootloader-installed")
670 out = switch_to_specialisation("${machine}", "", action="switch")
671 assert_contains(out, "installing dummy bootloader")
672 assert_contains(out, "activating the configuration...") # good indicator of a system activation
673 machine.succeed("test -f /tmp/bootloader-installed")
675 # test and dry-activate actions are tested further down below
677 # invalid action fails the script
678 switch_to_specialisation("${machine}", "", action="broken-action", fail=True)
679 # no action fails the script
680 assert "Usage:" in machine.fail("${machine}/bin/switch-to-configuration 2>&1")
682 with subtest("init interface version"):
683 # Do not try to switch to an invalid init interface version
684 assert "incompatible" in switch_to_specialisation("${machine}", "brokenInitInterface", fail=True)
686 with subtest("systemd restarts"):
687 # systemd is restarted when its system.conf changes
688 out = switch_to_specialisation("${machine}", "modifiedSystemConf")
689 assert_contains(out, "restarting systemd...")
691 with subtest("continuing from an aborted switch"):
692 # An aborted switch will write into a file what it tried to start
693 # and a second switch should continue from this
694 machine.succeed("echo dbus.service > /run/nixos/start-list")
695 out = switch_to_specialisation("${machine}", "modifiedSystemConf")
696 assert_contains(out, "starting the following units: dbus.service\n")
698 with subtest("fstab mounts"):
699 switch_to_specialisation("${machine}", "")
701 out = switch_to_specialisation("${machine}", "addedMount")
702 assert_lacks(out, "stopping the following units:")
703 assert_lacks(out, "NOT restarting the following changed units:")
704 assert_lacks(out, "\nrestarting the following units:")
705 assert_lacks(out, "\nstarting the following units:")
706 assert_contains(out, "the following new units were started: test.mount\n")
707 # modify the mountpoint's options
708 out = switch_to_specialisation("${machine}", "addedMountOptsModified")
709 assert_lacks(out, "stopping the following units:")
710 assert_lacks(out, "NOT restarting the following changed units:")
711 assert_contains(out, "reloading the following units: test.mount\n")
712 assert_lacks(out, "\nrestarting the following units:")
713 assert_lacks(out, "\nstarting the following units:")
714 assert_lacks(out, "the following new units were started:")
716 out = switch_to_specialisation("${machine}", "addedMountDevModified")
717 assert_lacks(out, "stopping the following units:")
718 assert_lacks(out, "NOT restarting the following changed units:")
719 assert_lacks(out, "reloading the following units:")
720 assert_contains(out, "\nrestarting the following units: test.mount\n")
721 assert_lacks(out, "\nstarting the following units:")
722 assert_lacks(out, "the following new units were started:")
724 out = switch_to_specialisation("${machine}", "addedMount")
725 assert_lacks(out, "stopping the following units:")
726 assert_lacks(out, "NOT restarting the following changed units:")
727 assert_lacks(out, "reloading the following units:")
728 assert_contains(out, "\nrestarting the following units: test.mount\n")
729 assert_lacks(out, "\nstarting the following units:")
730 assert_lacks(out, "the following new units were started:")
732 out = switch_to_specialisation("${machine}", "")
733 assert_contains(out, "stopping the following units: test.mount\n")
734 assert_lacks(out, "NOT restarting the following changed units:")
735 assert_contains(out, "reloading the following units: dbus.service\n")
736 assert_lacks(out, "\nrestarting the following units:")
737 assert_lacks(out, "\nstarting the following units:")
738 assert_lacks(out, "the following new units were started:")
739 # change something about the / mount
740 out = switch_to_specialisation("${machine}", "storeMountModified")
741 assert_lacks(out, "stopping the following units:")
742 assert_contains(out, "NOT restarting the following changed units: -.mount")
743 assert_contains(out, "reloading the following units: dbus.service\n")
744 assert_lacks(out, "\nrestarting the following units:")
745 assert_lacks(out, "\nstarting the following units:")
746 assert_lacks(out, "the following new units were started:")
748 with subtest("swaps"):
749 switch_to_specialisation("${machine}", "")
751 out = switch_to_specialisation("${machine}", "swap")
752 assert_lacks(out, "stopping the following units:")
753 assert_lacks(out, "NOT restarting the following changed units:")
754 assert_contains(out, "reloading the following units: dbus.service\n")
755 assert_lacks(out, "\nrestarting the following units:")
756 assert_lacks(out, "\nstarting the following units:")
757 assert_contains(out, "the following new units were started: swapfile.swap")
759 out = switch_to_specialisation("${machine}", "")
760 assert_contains(out, "stopping swap device: /swapfile")
761 assert_lacks(out, "stopping the following units:")
762 assert_lacks(out, "NOT restarting the following changed units:")
763 assert_contains(out, "reloading the following units: dbus.service\n")
764 assert_lacks(out, "\nrestarting the following units:")
765 assert_lacks(out, "\nstarting the following units:")
766 assert_lacks(out, "the following new units were started:")
768 with subtest("services"):
769 switch_to_specialisation("${machine}", "")
770 # Nothing happens when nothing is changed
771 out = switch_to_specialisation("${machine}", "")
772 assert_lacks(out, "stopping the following units:")
773 assert_lacks(out, "NOT restarting the following changed units:")
774 assert_lacks(out, "reloading the following units:")
775 assert_lacks(out, "\nrestarting the following units:")
776 assert_lacks(out, "\nstarting the following units:")
777 assert_lacks(out, "the following new units were started:")
779 # Start a simple service
780 out = switch_to_specialisation("${machine}", "simpleService")
781 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader
782 assert_lacks(out, "stopping the following units:")
783 assert_lacks(out, "NOT restarting the following changed units:")
784 assert_contains(out, "reloading the following units: dbus.service\n") # huh
785 assert_lacks(out, "\nrestarting the following units:")
786 assert_lacks(out, "\nstarting the following units:")
787 assert_contains(out, "the following new units were started: test.service\n")
789 # Not changing anything doesn't do anything
790 out = switch_to_specialisation("${machine}", "simpleService")
791 assert_lacks(out, "stopping the following units:")
792 assert_lacks(out, "NOT restarting the following changed units:")
793 assert_lacks(out, "reloading the following units:")
794 assert_lacks(out, "\nrestarting the following units:")
795 assert_lacks(out, "\nstarting the following units:")
796 assert_lacks(out, "the following new units were started:")
798 # Only changing the description does nothing
799 out = switch_to_specialisation("${machine}", "simpleServiceDifferentDescription")
800 assert_lacks(out, "stopping the following units:")
801 assert_lacks(out, "NOT restarting the following changed units:")
802 assert_lacks(out, "reloading the following units:")
803 assert_lacks(out, "\nrestarting the following units:")
804 assert_lacks(out, "\nstarting the following units:")
805 assert_lacks(out, "the following new units were started:")
807 # Restart the simple service
808 out = switch_to_specialisation("${machine}", "simpleServiceModified")
809 assert_contains(out, "stopping the following units: test.service\n")
810 assert_lacks(out, "NOT restarting the following changed units:")
811 assert_lacks(out, "reloading the following units:")
812 assert_lacks(out, "\nrestarting the following units:")
813 assert_contains(out, "\nstarting the following units: test.service\n")
814 assert_lacks(out, "the following new units were started:")
816 # Restart the service with stopIfChanged=false
817 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
818 assert_lacks(out, "stopping the following units:")
819 assert_lacks(out, "NOT restarting the following changed units:")
820 assert_lacks(out, "reloading the following units:")
821 assert_contains(out, "\nrestarting the following units: test.service\n")
822 assert_lacks(out, "\nstarting the following units:")
823 assert_lacks(out, "the following new units were started:")
825 # Reload the service with reloadIfChanged=true
826 out = switch_to_specialisation("${machine}", "simpleServiceReload")
827 assert_lacks(out, "stopping the following units:")
828 assert_lacks(out, "NOT restarting the following changed units:")
829 assert_contains(out, "reloading the following units: test.service\n")
830 assert_lacks(out, "\nrestarting the following units:")
831 assert_lacks(out, "\nstarting the following units:")
832 assert_lacks(out, "the following new units were started:")
834 # Nothing happens when restartIfChanged=false
835 out = switch_to_specialisation("${machine}", "simpleServiceNorestart")
836 assert_lacks(out, "stopping the following units:")
837 assert_contains(out, "NOT restarting the following changed units: test.service\n")
838 assert_lacks(out, "reloading the following units:")
839 assert_lacks(out, "\nrestarting the following units:")
840 assert_lacks(out, "\nstarting the following units:")
841 assert_lacks(out, "the following new units were started:")
843 # Dry mode shows different messages
844 out = switch_to_specialisation("${machine}", "simpleService", action="dry-activate")
845 assert_lacks(out, "stopping the following units:")
846 assert_lacks(out, "NOT restarting the following changed units:")
847 assert_lacks(out, "reloading the following units:")
848 assert_lacks(out, "\nrestarting the following units:")
849 assert_lacks(out, "\nstarting the following units:")
850 assert_lacks(out, "the following new units were started:")
851 assert_contains(out, "would start the following units: test.service\n")
853 out = switch_to_specialisation("${machine}", "", action="test")
855 # Ensure the service can be started when the activation script isn't in toplevel
856 # This is a lot like "Start a simple service", except activation-only deps could be gc-ed
857 out = run_switch("${nodes.machine.specialisation.simpleServiceSeparateActivationScript.configuration.system.build.separateActivationScript}/bin/switch-to-configuration");
858 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader
859 assert_lacks(out, "stopping the following units:")
860 assert_lacks(out, "NOT restarting the following changed units:")
861 assert_contains(out, "reloading the following units: dbus.service\n") # huh
862 assert_lacks(out, "\nrestarting the following units:")
863 assert_lacks(out, "\nstarting the following units:")
864 assert_contains(out, "the following new units were started: test.service\n")
865 machine.succeed("! test -e /run/current-system/activate")
866 machine.succeed("! test -e /run/current-system/dry-activate")
867 machine.succeed("! test -e /run/current-system/bin/switch-to-configuration")
869 # Ensure \ works in unit names
870 out = switch_to_specialisation("${machine}", "unitWithBackslash")
871 assert_contains(out, "stopping the following units: test.service\n")
872 assert_lacks(out, "NOT restarting the following changed units:")
873 assert_lacks(out, "reloading the following units:")
874 assert_lacks(out, "\nrestarting the following units:")
875 assert_lacks(out, "\nstarting the following units:")
876 assert_contains(out, "the following new units were started: escaped\\x2ddash.service\n")
878 out = switch_to_specialisation("${machine}", "unitWithBackslashModified")
879 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
880 assert_lacks(out, "NOT restarting the following changed units:")
881 assert_lacks(out, "reloading the following units:")
882 assert_lacks(out, "\nrestarting the following units:")
883 assert_contains(out, "\nstarting the following units: escaped\\x2ddash.service\n")
884 assert_lacks(out, "the following new units were started:")
886 # Ensure units can start with a dash
887 out = switch_to_specialisation("${machine}", "unitStartingWithDash")
888 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
889 assert_lacks(out, "NOT restarting the following changed units:")
890 assert_lacks(out, "reloading the following units:")
891 assert_lacks(out, "\nrestarting the following units:")
892 assert_lacks(out, "\nstarting the following units:")
893 assert_contains(out, "the following new units were started: -.service\n")
895 # The regression only occurs when reloading units
896 out = switch_to_specialisation("${machine}", "unitStartingWithDashModified")
897 assert_lacks(out, "stopping the following units:")
898 assert_lacks(out, "NOT restarting the following changed units:")
899 assert_contains(out, "reloading the following units: -.service")
900 assert_lacks(out, "\nrestarting the following units:")
901 assert_lacks(out, "\nstarting the following units:")
902 assert_lacks(out, "the following new units were started:")
904 # Ensure units that require changed units are properly reloaded
905 out = switch_to_specialisation("${machine}", "unitWithRequirement")
906 assert_contains(out, "stopping the following units: -.service\n")
907 assert_lacks(out, "NOT restarting the following changed units:")
908 assert_lacks(out, "reloading the following units:")
909 assert_lacks(out, "\nrestarting the following units:")
910 assert_lacks(out, "\nstarting the following units:")
911 assert_contains(out, "the following new units were started: required-service.service, test-service.service\n")
913 out = switch_to_specialisation("${machine}", "unitWithRequirementModified")
914 assert_contains(out, "stopping the following units: required-service.service\n")
915 assert_lacks(out, "NOT restarting the following changed units:")
916 assert_lacks(out, "reloading the following units:")
917 assert_lacks(out, "\nrestarting the following units:")
918 assert_contains(out, "\nstarting the following units: required-service.service, test-service.service\n")
919 assert_lacks(out, "the following new units were started:")
921 # Unless the unit asks to be not restarted
922 out = switch_to_specialisation("${machine}", "unitWithRequirementModifiedNostart")
923 assert_contains(out, "stopping the following units: required-service.service\n")
924 assert_lacks(out, "NOT restarting the following changed units:")
925 assert_lacks(out, "reloading the following units:")
926 assert_lacks(out, "\nrestarting the following units:")
927 assert_contains(out, "\nstarting the following units: required-service.service\n")
928 assert_lacks(out, "the following new units were started:")
930 # Ensure templated units are restarted when the base unit changes
931 switch_to_specialisation("${machine}", "unitWithTemplate")
932 out = switch_to_specialisation("${machine}", "unitWithTemplateModified")
933 assert_contains(out, "stopping the following units: instantiated@one.service, instantiated@two.service\n")
934 assert_lacks(out, "NOT restarting the following changed units:")
935 assert_lacks(out, "reloading the following units:")
936 assert_lacks(out, "\nrestarting the following units:")
937 assert_contains(out, "\nstarting the following units: instantiated@one.service, instantiated@two.service\n")
938 assert_lacks(out, "the following new units were started:")
940 with subtest("failing units"):
941 # Let the simple service fail
942 switch_to_specialisation("${machine}", "simpleServiceModified")
943 out = switch_to_specialisation("${machine}", "simpleServiceFailing", fail=True)
944 assert_contains(out, "stopping the following units: test.service\n")
945 assert_lacks(out, "NOT restarting the following changed units:")
946 assert_lacks(out, "reloading the following units:")
947 assert_lacks(out, "\nrestarting the following units:")
948 assert_contains(out, "\nstarting the following units: test.service\n")
949 assert_lacks(out, "the following new units were started:")
950 assert_contains(out, "warning: the following units failed: test.service\n")
951 assert_contains(out, "Main PID:") # output of systemctl
953 # A unit that gets into autorestart without failing is not treated as failed
954 out = switch_to_specialisation("${machine}", "autorestartService")
955 assert_lacks(out, "stopping the following units:")
956 assert_lacks(out, "NOT restarting the following changed units:")
957 assert_lacks(out, "reloading the following units:")
958 assert_lacks(out, "\nrestarting the following units:")
959 assert_lacks(out, "\nstarting the following units:")
960 assert_contains(out, "the following new units were started: autorestart.service\n")
961 machine.systemctl('stop autorestart.service') # cancel the 20y timer
963 # Switching to the same system should do nothing (especially not treat the unit as failed)
964 out = switch_to_specialisation("${machine}", "autorestartService")
965 assert_lacks(out, "stopping the following units:")
966 assert_lacks(out, "NOT restarting the following changed units:")
967 assert_lacks(out, "reloading the following units:")
968 assert_lacks(out, "\nrestarting the following units:")
969 assert_lacks(out, "\nstarting the following units:")
970 assert_contains(out, "the following new units were started: autorestart.service\n")
971 machine.systemctl('stop autorestart.service') # cancel the 20y timer
973 # If systemd thinks the unit has failed and is in autorestart, we should show it as failed
974 out = switch_to_specialisation("${machine}", "autorestartServiceFailing", fail=True)
975 assert_lacks(out, "stopping the following units:")
976 assert_lacks(out, "NOT restarting the following changed units:")
977 assert_lacks(out, "reloading the following units:")
978 assert_lacks(out, "\nrestarting the following units:")
979 assert_lacks(out, "\nstarting the following units:")
980 assert_lacks(out, "the following new units were started:")
981 assert_contains(out, "warning: the following units failed: autorestart.service\n")
982 assert_contains(out, "Main PID:") # output of systemctl
984 with subtest("unit file parser"):
985 # Switch to a well-known state
986 switch_to_specialisation("${machine}", "simpleServiceNostop")
989 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSection")
990 assert_lacks(out, "stopping the following units:")
991 assert_lacks(out, "NOT restarting the following changed units:")
992 assert_lacks(out, "reloading the following units:")
993 assert_contains(out, "\nrestarting the following units: test.service\n")
994 assert_lacks(out, "\nstarting the following units:")
995 assert_lacks(out, "the following new units were started:")
998 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSectionOtherName")
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_contains(out, "\nrestarting the following units: test.service\n")
1003 assert_lacks(out, "\nstarting the following units:")
1004 assert_lacks(out, "the following new units were started:")
1007 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
1008 assert_lacks(out, "stopping the following units:")
1009 assert_lacks(out, "NOT restarting the following changed units:")
1010 assert_lacks(out, "reloading the following units:")
1011 assert_contains(out, "\nrestarting the following units: test.service\n")
1012 assert_lacks(out, "\nstarting the following units:")
1013 assert_lacks(out, "the following new units were started:")
1015 # [Install] section is ignored
1016 out = switch_to_specialisation("${machine}", "simpleServiceWithInstallSection")
1017 assert_lacks(out, "stopping the following units:")
1018 assert_lacks(out, "NOT restarting the following changed units:")
1019 assert_lacks(out, "reloading the following units:")
1020 assert_lacks(out, "\nrestarting the following units:")
1021 assert_lacks(out, "\nstarting the following units:")
1022 assert_lacks(out, "the following new units were started:")
1025 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKey")
1026 assert_lacks(out, "stopping the following units:")
1027 assert_lacks(out, "NOT restarting the following changed units:")
1028 assert_lacks(out, "reloading the following units:")
1029 assert_contains(out, "\nrestarting the following units: test.service\n")
1030 assert_lacks(out, "\nstarting the following units:")
1031 assert_lacks(out, "the following new units were started:")
1034 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherValue")
1035 assert_lacks(out, "stopping the following units:")
1036 assert_lacks(out, "NOT restarting the following changed units:")
1037 assert_lacks(out, "reloading the following units:")
1038 assert_contains(out, "\nrestarting the following units: test.service\n")
1039 assert_lacks(out, "\nstarting the following units:")
1040 assert_lacks(out, "the following new units were started:")
1043 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherName")
1044 assert_lacks(out, "stopping the following units:")
1045 assert_lacks(out, "NOT restarting the following changed units:")
1046 assert_lacks(out, "reloading the following units:")
1047 assert_contains(out, "\nrestarting the following units: test.service\n")
1048 assert_lacks(out, "\nstarting the following units:")
1049 assert_lacks(out, "the following new units were started:")
1052 out = switch_to_specialisation("${machine}", "simpleServiceNostop")
1053 assert_lacks(out, "stopping the following units:")
1054 assert_lacks(out, "NOT restarting the following changed units:")
1055 assert_lacks(out, "reloading the following units:")
1056 assert_contains(out, "\nrestarting the following units: test.service\n")
1057 assert_lacks(out, "\nstarting the following units:")
1058 assert_lacks(out, "the following new units were started:")
1060 # Add a reload trigger
1061 out = switch_to_specialisation("${machine}", "simpleServiceReloadTrigger")
1062 assert_lacks(out, "stopping the following units:")
1063 assert_lacks(out, "NOT restarting the following changed units:")
1064 assert_contains(out, "reloading the following units: test.service\n")
1065 assert_lacks(out, "\nrestarting the following units:")
1066 assert_lacks(out, "\nstarting the following units:")
1067 assert_lacks(out, "the following new units were started:")
1069 # Modify the reload trigger
1070 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModified")
1071 assert_lacks(out, "stopping the following units:")
1072 assert_lacks(out, "NOT restarting the following changed units:")
1073 assert_contains(out, "reloading the following units: test.service\n")
1074 assert_lacks(out, "\nrestarting the following units:")
1075 assert_lacks(out, "\nstarting the following units:")
1076 assert_lacks(out, "the following new units were started:")
1078 # Modify the reload trigger and something else
1079 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedAndSomethingElse")
1080 assert_lacks(out, "stopping the following units:")
1081 assert_lacks(out, "NOT restarting the following changed units:")
1082 assert_lacks(out, "reloading the following units:")
1083 assert_contains(out, "\nrestarting the following units: test.service\n")
1084 assert_lacks(out, "\nstarting the following units:")
1085 assert_lacks(out, "the following new units were started:")
1087 # Remove the reload trigger
1088 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedSomethingElse")
1089 assert_lacks(out, "stopping the following units:")
1090 assert_lacks(out, "NOT restarting the following changed units:")
1091 assert_lacks(out, "reloading the following units:")
1092 assert_lacks(out, "\nrestarting the following units:")
1093 assert_lacks(out, "\nstarting the following units:")
1094 assert_lacks(out, "the following new units were started:")
1096 with subtest("restart and reload by activation script"):
1097 switch_to_specialisation("${machine}", "simpleServiceNorestart")
1098 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
1099 assert_contains(out, "stopping the following units: test.service\n")
1100 assert_lacks(out, "NOT restarting the following changed units:")
1101 assert_lacks(out, "reloading the following units:")
1102 assert_lacks(out, "restarting the following units:")
1103 assert_contains(out, "\nstarting the following units: ${sortedUnits [
1104 "no-restart-service.service"
1105 "reload-triggers-and-restart-by-as.service"
1106 "simple-reload-service.service"
1107 "simple-restart-service.service"
1108 "simple-service.service"
1109 "templated-no-restart-service@instance.service"
1110 "templated-reload-triggers-and-restart-by-as@instance.service"
1111 "templated-simple-reload-service@instance.service"
1112 "templated-simple-restart-service@instance.service"
1113 "templated-simple-service@instance.service"
1115 assert_contains(out, "the following new units were started: ${sortedUnits [
1116 "no-restart-service.service"
1117 "reload-triggers-and-restart-by-as.service"
1118 "reload-triggers-and-restart.service"
1119 "reload-triggers.service"
1120 "simple-reload-service.service"
1121 "simple-restart-service.service"
1122 "simple-service.service"
1123 "system-templated\\\\x2dno\\\\x2drestart\\\\x2dservice.slice"
1124 "system-templated\\\\x2dreload\\\\x2dtriggers.slice"
1125 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart.slice"
1126 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart\\\\x2dby\\\\x2das.slice"
1127 "system-templated\\\\x2dsimple\\\\x2dreload\\\\x2dservice.slice"
1128 "system-templated\\\\x2dsimple\\\\x2drestart\\\\x2dservice.slice"
1129 "system-templated\\\\x2dsimple\\\\x2dservice.slice"
1130 "templated-no-restart-service@instance.service"
1131 "templated-reload-triggers-and-restart-by-as@instance.service"
1132 "templated-reload-triggers-and-restart@instance.service"
1133 "templated-reload-triggers@instance.service"
1134 "templated-simple-reload-service@instance.service"
1135 "templated-simple-restart-service@instance.service"
1136 "templated-simple-service@instance.service"
1138 # Switch to the same system where the example services get restarted
1139 # and reloaded by the activation script
1140 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
1141 assert_lacks(out, "stopping the following units:")
1142 assert_lacks(out, "NOT restarting the following changed units:")
1143 assert_contains(out, "reloading the following units: ${sortedUnits [
1144 "reload-triggers-and-restart.service"
1145 "reload-triggers.service"
1146 "simple-reload-service.service"
1147 "templated-reload-triggers-and-restart@instance.service"
1148 "templated-reload-triggers@instance.service"
1149 "templated-simple-reload-service@instance.service"
1151 assert_contains(out, "restarting the following units: ${sortedUnits [
1152 "reload-triggers-and-restart-by-as.service"
1153 "simple-restart-service.service"
1154 "simple-service.service"
1155 "templated-reload-triggers-and-restart-by-as@instance.service"
1156 "templated-simple-restart-service@instance.service"
1157 "templated-simple-service@instance.service"
1159 assert_lacks(out, "\nstarting the following units:")
1160 assert_lacks(out, "the following new units were started:")
1161 # Switch to the same system and see if the service gets restarted when it's modified
1162 # while the fact that it's supposed to be reloaded by the activation script is ignored.
1163 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified")
1164 assert_lacks(out, "stopping the following units:")
1165 assert_lacks(out, "NOT restarting the following changed units:")
1166 assert_contains(out, "reloading the following units: ${sortedUnits [
1167 "reload-triggers.service"
1168 "simple-reload-service.service"
1169 "templated-reload-triggers@instance.service"
1170 "templated-simple-reload-service@instance.service"
1172 assert_contains(out, "restarting the following units: ${sortedUnits [
1173 "reload-triggers-and-restart-by-as.service"
1174 "reload-triggers-and-restart.service"
1175 "simple-restart-service.service"
1176 "simple-service.service"
1177 "templated-reload-triggers-and-restart-by-as@instance.service"
1178 "templated-reload-triggers-and-restart@instance.service"
1179 "templated-simple-restart-service@instance.service"
1180 "templated-simple-service@instance.service"
1182 assert_lacks(out, "\nstarting the following units:")
1183 assert_lacks(out, "the following new units were started:")
1184 # The same, but in dry mode
1185 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate")
1186 assert_lacks(out, "would stop the following units:")
1187 assert_lacks(out, "would NOT stop the following changed units:")
1188 assert_contains(out, "would reload the following units: ${sortedUnits [
1189 "reload-triggers.service"
1190 "simple-reload-service.service"
1191 "templated-reload-triggers@instance.service"
1192 "templated-simple-reload-service@instance.service"
1194 assert_contains(out, "would restart the following units: ${sortedUnits [
1195 "reload-triggers-and-restart-by-as.service"
1196 "reload-triggers-and-restart.service"
1197 "simple-restart-service.service"
1198 "simple-service.service"
1199 "templated-reload-triggers-and-restart-by-as@instance.service"
1200 "templated-reload-triggers-and-restart@instance.service"
1201 "templated-simple-restart-service@instance.service"
1202 "templated-simple-service@instance.service"
1204 assert_lacks(out, "\nwould start the following units:")
1206 with subtest("socket-activated services"):
1207 # Socket-activated services don't get started, just the socket
1208 machine.fail("[ -S /run/test.sock ]")
1209 out = switch_to_specialisation("${machine}", "simple-socket")
1210 # assert_lacks(out, "stopping the following units:") not relevant
1211 assert_lacks(out, "NOT restarting the following changed units:")
1212 assert_lacks(out, "reloading the following units:")
1213 assert_lacks(out, "\nrestarting the following units:")
1214 assert_lacks(out, "\nstarting the following units:")
1215 assert_contains(out, "the following new units were started: socket-activated.socket\n")
1216 machine.succeed("[ -S /run/test.sock ]")
1218 # Changing a non-activated service does nothing
1219 out = switch_to_specialisation("${machine}", "simple-socket-service-modified")
1220 assert_lacks(out, "stopping the following units:")
1221 assert_lacks(out, "NOT restarting the following changed units:")
1222 assert_lacks(out, "reloading the following units:")
1223 assert_lacks(out, "\nrestarting the following units:")
1224 assert_lacks(out, "\nstarting the following units:")
1225 assert_lacks(out, "the following new units were started:")
1226 machine.succeed("[ -S /run/test.sock ]")
1227 # The unit is properly activated when the socket is accessed
1228 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1229 raise Exception("Socket was not properly activated") # idk how that would happen tbh
1231 # Changing an activated service with stopIfChanged=false restarts the service
1232 out = switch_to_specialisation("${machine}", "simple-socket")
1233 assert_lacks(out, "stopping the following units:")
1234 assert_lacks(out, "NOT restarting the following changed units:")
1235 assert_lacks(out, "reloading the following units:")
1236 assert_contains(out, "\nrestarting the following units: socket-activated.service\n")
1237 assert_lacks(out, "\nstarting the following units:")
1238 assert_lacks(out, "the following new units were started:")
1239 machine.succeed("[ -S /run/test.sock ]")
1240 # Socket-activation of the unit still works
1241 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1242 raise Exception("Socket was not properly activated after the service was restarted")
1244 # Changing an activated service with stopIfChanged=true stops the service and
1245 # socket and starts the socket
1246 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed")
1247 assert_contains(out, "stopping the following units: socket-activated.service, socket-activated.socket\n")
1248 assert_lacks(out, "NOT restarting the following changed units:")
1249 assert_lacks(out, "reloading the following units:")
1250 assert_lacks(out, "\nrestarting the following units:")
1251 assert_contains(out, "\nstarting the following units: socket-activated.socket\n")
1252 assert_lacks(out, "the following new units were started:")
1253 machine.succeed("[ -S /run/test.sock ]")
1254 # Socket-activation of the unit still works
1255 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1256 raise Exception("Socket was not properly activated after the service was restarted")
1258 # Changing a reload trigger of a socket-activated unit only reloads it
1259 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed-and-reloadtrigger")
1260 assert_lacks(out, "stopping the following units:")
1261 assert_lacks(out, "NOT restarting the following changed units:")
1262 assert_contains(out, "reloading the following units: socket-activated.service\n")
1263 assert_lacks(out, "\nrestarting the following units:")
1264 assert_lacks(out, "\nstarting the following units: socket-activated.socket")
1265 assert_lacks(out, "the following new units were started:")
1266 machine.succeed("[ -S /run/test.sock ]")
1267 # Socket-activation of the unit still works
1268 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
1269 raise Exception("Socket was not properly activated after the service was restarted")
1271 with subtest("mounts"):
1272 switch_to_specialisation("${machine}", "mount")
1273 out = machine.succeed("mount | grep 'on /testmount'")
1274 assert_contains(out, "size=1024k")
1275 # Changing options reloads the unit
1276 out = switch_to_specialisation("${machine}", "mountOptionsModified")
1277 assert_lacks(out, "stopping the following units:")
1278 assert_lacks(out, "NOT restarting the following changed units:")
1279 assert_contains(out, "reloading the following units: testmount.mount\n")
1280 assert_lacks(out, "\nrestarting the following units:")
1281 assert_lacks(out, "\nstarting the following units:")
1282 assert_lacks(out, "the following new units were started:")
1284 out = machine.succeed("mount | grep 'on /testmount'")
1285 assert_contains(out, "size=10240k")
1286 # Changing anything but `Options=` restarts the unit
1287 out = switch_to_specialisation("${machine}", "mountModified")
1288 assert_lacks(out, "stopping the following units:")
1289 assert_lacks(out, "NOT restarting the following changed units:")
1290 assert_lacks(out, "reloading the following units:")
1291 assert_contains(out, "\nrestarting the following units: testmount.mount\n")
1292 assert_lacks(out, "\nstarting the following units:")
1293 assert_lacks(out, "the following new units were started:")
1295 out = machine.succeed("mount | grep 'on /testmount'")
1296 assert_contains(out, "ramfs")
1298 with subtest("timers"):
1299 switch_to_specialisation("${machine}", "timer")
1300 out = machine.succeed("systemctl show test-timer.timer")
1301 assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC")
1302 out = switch_to_specialisation("${machine}", "timerModified")
1303 assert_lacks(out, "stopping the following units:")
1304 assert_lacks(out, "NOT restarting the following units:")
1305 assert_lacks(out, "reloading the following units:")
1306 assert_contains(out, "\nrestarting the following units: test-timer.timer\n")
1307 assert_lacks(out, "\nstarting the following units:")
1308 assert_lacks(out, "the following new units were started:")
1310 out = machine.succeed("systemctl show test-timer.timer")
1311 assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00")
1313 with subtest("targets"):
1314 # Modifying some special targets like hybrid-sleep.target does nothing
1315 out = switch_to_specialisation("${machine}", "hybridSleepModified")
1316 assert_contains(out, "stopping the following units: test-timer.timer\n")
1317 assert_lacks(out, "NOT restarting the following changed units:")
1318 assert_lacks(out, "reloading the following units:")
1319 assert_lacks(out, "\nrestarting the following units:")
1320 assert_lacks(out, "\nstarting the following units:")
1321 assert_lacks(out, "the following new units were started:")
1323 # Adding a new target starts it
1324 out = switch_to_specialisation("${machine}", "target")
1325 assert_lacks(out, "stopping the following units:")
1326 assert_lacks(out, "NOT restarting the following changed units:")
1327 assert_lacks(out, "reloading the following units:")
1328 assert_lacks(out, "\nrestarting the following units:")
1329 assert_lacks(out, "\nstarting the following units:")
1330 assert_contains(out, "the following new units were started: test-target.target\n")
1332 # Changing a target doesn't print anything because the unit is filtered
1333 machine.systemctl("start test-service.service")
1334 out = switch_to_specialisation("${machine}", "targetModified")
1335 assert_lacks(out, "stopping the following units:")
1336 assert_lacks(out, "NOT restarting the following changed units:")
1337 assert_lacks(out, "reloading the following units:")
1338 assert_lacks(out, "\nrestarting the following units:")
1339 assert_lacks(out, "\nstarting the following units:")
1340 assert_lacks(out, "the following new units were started:")
1341 machine.succeed("systemctl is-active test-service.service") # target was not restarted
1343 # With X-StopOnReconfiguration, the target gets stopped and started
1344 out = switch_to_specialisation("${machine}", "targetModifiedStopOnReconfig")
1345 assert_lacks(out, "stopping the following units:")
1346 assert_lacks(out, "NOT restarting the following changed units:")
1347 assert_lacks(out, "reloading the following units:")
1348 assert_lacks(out, "\nrestarting the following units:")
1349 assert_lacks(out, "\nstarting the following units:")
1350 assert_lacks(out, "the following new units were started:")
1351 machine.fail("systemctl is-active test-service.servce") # target was restarted
1353 # Remove the target by switching to the old specialisation
1354 out = switch_to_specialisation("${machine}", "timerModified")
1355 assert_contains(out, "stopping the following units: test-target.target\n")
1356 assert_lacks(out, "NOT restarting the following changed units:")
1357 assert_lacks(out, "reloading the following units:")
1358 assert_lacks(out, "\nrestarting the following units:")
1359 assert_lacks(out, "\nstarting the following units:")
1360 assert_contains(out, "the following new units were started: test-timer.timer\n")
1362 with subtest("paths"):
1363 out = switch_to_specialisation("${machine}", "path")
1364 assert_contains(out, "stopping the following units: test-timer.timer\n")
1365 assert_lacks(out, "NOT restarting the following changed units:")
1366 assert_lacks(out, "reloading the following units:")
1367 assert_lacks(out, "\nrestarting the following units:")
1368 assert_lacks(out, "\nstarting the following units:")
1369 assert_contains(out, "the following new units were started: test-watch.path\n")
1370 machine.fail("test -f /testpath-modified")
1372 # touch the file, unit should be triggered
1373 machine.succeed("touch /testpath")
1374 machine.wait_until_succeeds("test -f /testpath-modified")
1375 machine.succeed("rm /testpath /testpath-modified")
1376 machine.systemctl("stop test-watch.service")
1377 switch_to_specialisation("${machine}", "pathModified")
1378 machine.succeed("touch /testpath")
1379 machine.fail("test -f /testpath-modified")
1380 machine.succeed("touch /testpath2")
1381 machine.wait_until_succeeds("test -f /testpath-modified")
1383 # This test ensures that changes to slice configuration get applied.
1384 # We test this by having a slice that allows no memory allocation at
1385 # all and starting a service within it. If the service crashes, the slice
1386 # is applied and if we modify the slice to allow memory allocation, the
1387 # service should successfully start.
1388 with subtest("slices"):
1389 machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing
1390 out = switch_to_specialisation("${machine}", "slice")
1391 # assert_lacks(out, "stopping the following units:") not relevant
1392 assert_lacks(out, "NOT restarting the following changed units:")
1393 assert_lacks(out, "reloading the following units:")
1394 assert_lacks(out, "\nrestarting the following units:")
1395 assert_lacks(out, "\nstarting the following units:")
1396 assert_lacks(out, "the following new units were started:")
1397 machine.fail("systemctl start testservice.service")
1399 out = switch_to_specialisation("${machine}", "sliceModified")
1400 assert_lacks(out, "stopping the following units:")
1401 assert_lacks(out, "NOT restarting the following changed units:")
1402 assert_lacks(out, "reloading the following units:")
1403 assert_lacks(out, "\nrestarting the following units:")
1404 assert_lacks(out, "\nstarting the following units:")
1405 assert_lacks(out, "the following new units were started:")
1406 machine.succeed("systemctl start testservice.service")
1407 machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing