1{ lib, ... }:
2{
3 name = "systemd-lock-handler";
4
5 meta.maintainers = with lib.maintainers; [ liff ];
6
7 enableOCR = true;
8
9 nodes.machine =
10 {
11 config,
12 pkgs,
13 lib,
14 ...
15 }:
16 let
17 touch = "${lib.getBin pkgs.coreutils}/bin/touch";
18 in
19 {
20 imports = [ common/wayland-cage.nix ];
21
22 services.systemd-lock-handler.enable = true;
23
24 systemd.user.services = {
25 test-lock = {
26 partOf = [ "lock.target" ];
27 onSuccess = [ "unlock.target" ];
28 before = [ "lock.target" ];
29 wantedBy = [ "lock.target" ];
30 serviceConfig.ExecStart = "${touch} /tmp/lock.target.activated";
31 };
32 test-unlock = {
33 partOf = [ "unlock.target" ];
34 after = [ "unlock.target" ];
35 wantedBy = [ "unlock.target" ];
36 serviceConfig.ExecStart = "${touch} /tmp/unlock.target.activated";
37 };
38 test-sleep = {
39 partOf = [ "sleep.target" ];
40 before = [ "sleep.target" ];
41 wantedBy = [ "sleep.target" ];
42 serviceConfig.ExecStart = "${touch} /tmp/sleep.target.activated";
43 };
44 };
45 };
46
47 testScript = ''
48 machine.wait_for_unit('graphical.target')
49 machine.wait_for_text('alice@machine')
50
51 machine.send_chars('loginctl lock-session\n')
52 machine.wait_for_file('/tmp/lock.target.activated')
53 machine.wait_for_file('/tmp/unlock.target.activated')
54
55 machine.send_chars('systemctl suspend\n')
56 # wait_for_file won’t complete before the machine is asleep,
57 # so we’ll watch the log instead.
58 machine.wait_for_console_text('Started test-sleep.service.')
59
60 # The VM is asleep, regular shutdown won’t work.
61 machine.crash()
62 '';
63}