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