about summary refs log tree commit diff
path: root/nixos/tests/keyd.nix
diff options
context:
space:
mode:
authorwoojiq <yurii.shymon@gmail.com>2023-03-15 15:15:38 +0200
committerpennae <82953136+pennae@users.noreply.github.com>2023-03-22 15:12:29 +0100
commit296e7f92cde7cd3cba094400d9bfdd614a04fcea (patch)
treea8069dec6bf8fdfee0560026ab8cc88628f9f045 /nixos/tests/keyd.nix
parenta747c1d84105d7de357c1fe91a79a610d8fbbb1e (diff)
keyd: add keyd service and test
The keyd package already exists, but without a systemd service.

Keyd requires write access to /var/run to create its socket. Currently
the directory it uses can be changed with an environment variable, but
the keyd repo state suggests that this may turn into a compile-time
option. with that set, and some supplementary groups added, we can run
the service under DynamicUser.

Co-authored-by: pennae <82953136+pennae@users.noreply.github.com>
Diffstat (limited to 'nixos/tests/keyd.nix')
-rw-r--r--nixos/tests/keyd.nix82
1 files changed, 82 insertions, 0 deletions
diff --git a/nixos/tests/keyd.nix b/nixos/tests/keyd.nix
new file mode 100644
index 0000000000000..d492cc194895c
--- /dev/null
+++ b/nixos/tests/keyd.nix
@@ -0,0 +1,82 @@
+# The test template is taken from the `./keymap.nix`
+{ system ? builtins.currentSystem
+, config ? { }
+, pkgs ? import ../.. { inherit system config; }
+}:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+
+let
+  readyFile = "/tmp/readerReady";
+  resultFile = "/tmp/readerResult";
+
+  testReader = pkgs.writeScript "test-input-reader" ''
+    rm -f ${resultFile} ${resultFile}.tmp
+    logger "testReader: START: Waiting for $1 characters, expecting '$2'."
+    touch ${readyFile}
+    read -r -N $1 chars
+    rm -f ${readyFile}
+    if [ "$chars" == "$2" ]; then
+      logger -s "testReader: PASS: Got '$2' as expected." 2>${resultFile}.tmp
+    else
+      logger -s "testReader: FAIL: Expected '$2' but got '$chars'." 2>${resultFile}.tmp
+    fi
+    # rename after the file is written to prevent a race condition
+    mv  ${resultFile}.tmp ${resultFile}
+  '';
+
+
+  mkKeyboardTest = name: { settings, test }: with pkgs.lib; makeTest {
+    inherit name;
+
+    nodes.machine = {
+      services.keyd = {
+        enable = true;
+        inherit settings;
+      };
+    };
+
+    testScript = ''
+      import shlex
+
+      machine.wait_for_unit("keyd.service")
+
+      def run_test_case(cmd, test_case_name, inputs, expected):
+          with subtest(test_case_name):
+              assert len(inputs) == len(expected)
+              machine.execute("rm -f ${readyFile} ${resultFile}")
+              # set up process that expects all the keys to be entered
+              machine.succeed(
+                  "{} {} {} {} >&2 &".format(
+                      cmd,
+                      "${testReader}",
+                      len(inputs),
+                      shlex.quote("".join(expected)),
+                  )
+              )
+              # wait for reader to be ready
+              machine.wait_for_file("${readyFile}")
+              # send all keys
+              for key in inputs:
+                  machine.send_key(key)
+              # wait for result and check
+              machine.wait_for_file("${resultFile}")
+              machine.succeed("grep -q 'PASS:' ${resultFile}")
+      test = ${builtins.toJSON test}
+      run_test_case("openvt -sw --", "${name}", test["press"], test["expect"])
+    '';
+  };
+
+in
+pkgs.lib.mapAttrs mkKeyboardTest {
+  swap-ab_and_ctrl-as-shift = {
+    test.press = [ "a" "ctrl-b" "c" ];
+    test.expect = [ "b" "A" "c" ];
+
+    settings.main = {
+      "a" = "b";
+      "b" = "a";
+      "control" = "oneshot(shift)";
+    };
+  };
+}