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