1 { system ? builtins.currentSystem,
3 pkgs ? import ../.. { inherit system config; }
6 with import ../lib/testing-python.nix { inherit system pkgs; };
9 readyFile = "/tmp/readerReady";
10 resultFile = "/tmp/readerResult";
12 testReader = pkgs.writeScript "test-input-reader" ''
13 rm -f ${resultFile} ${resultFile}.tmp
14 logger "testReader: START: expecting '$1'."
16 read -r -N ''${#1} -t 60 chars
19 if [ "$chars" == "$1" ]; then
20 logger -s "testReader: PASS: Got '$1' as expected." 2>${resultFile}.tmp
22 logger -s "testReader: FAIL: Expected '$1' but got '$chars'." 2>${resultFile}.tmp
24 # rename after the file is written to prevent a race condition
25 mv ${resultFile}.tmp ${resultFile}
29 mkKeyboardTest = layout: { extraConfig ? {}, tests }: with pkgs.lib; makeTest {
30 name = "keymap-${layout}";
32 nodes.machine.console.keyMap = mkOverride 900 layout;
33 nodes.machine.services.xserver.desktopManager.xterm.enable = false;
34 nodes.machine.services.xserver.xkb.layout = mkOverride 900 layout;
35 nodes.machine.imports = [ ./common/x11.nix extraConfig ];
42 def run_test_case(cmd, inputs, expected):
43 assert len(inputs) == len(expected)
44 machine.execute("rm -f ${readyFile} ${resultFile}")
46 # set up process that expects all the keys to be entered
48 "${pkgs.systemd}/bin/systemd-cat -t input-test-reader -- {} {} {} &".format(
51 shlex.quote("".join(expected)),
55 # wait for reader to be ready
56 machine.wait_for_file("${readyFile}")
62 # wait for result and check
63 machine.wait_for_file("${resultFile}")
64 machine.succeed("grep -q 'PASS:' ${resultFile}")
67 with open("${pkgs.writeText "tests.json" (builtins.toJSON tests)}") as json_file:
68 tests = json.load(json_file)
70 # These environments used to run in the opposite order, causing the
71 # following error at openvt startup.
73 # openvt: Couldn't deallocate console 1
75 # This error did not appear in successful runs.
76 # I don't know the exact cause, but I it seems that openvt and X are
77 # fighting over the virtual terminal. This does not appear to be a problem
78 # when the X test runs first.
79 keymap_environments = {
80 "Xorg Keymap": "env DISPLAY=:0 xterm -title testterm -class testterm -fullscreen -e",
81 "VT Keymap": "openvt -c 2 -sw --",
86 for test_case_name, test_data in tests.items():
87 for keymap_env_name, command in keymap_environments.items():
88 with subtest(f"{test_case_name} - {keymap_env_name}"):
97 in pkgs.lib.mapAttrs mkKeyboardTest {
100 azqw.qwerty = [ "q" "w" ];
101 azqw.expect = [ "a" "z" ];
102 altgr.qwerty = [ "alt_r-2" "alt_r-3" "alt_r-4" "alt_r-5" "alt_r-6" ];
103 altgr.expect = [ "~" "#" "{" "[" "|" ];
106 extraConfig.console.keyMap = "fr";
107 extraConfig.services.xserver.xkb.layout = "fr";
112 layer1.qwerty = [ "f" "j" ];
113 layer1.expect = [ "e" "n" ];
114 layer2.qwerty = [ "shift-f" "shift-j" "shift-6" ];
115 layer2.expect = [ "E" "N" "$" ];
116 layer3.qwerty = [ "caps_lock-d" "caps_lock-f" ];
117 layer3.expect = [ "{" "}" ];
120 extraConfig.console.keyMap = "bone";
121 extraConfig.services.xserver.xkb.layout = "de";
122 extraConfig.services.xserver.xkb.variant = "bone";
127 homerow.qwerty = [ "a" "s" "d" "f" "j" "k" "l" "semicolon" ];
128 homerow.expect = [ "a" "r" "s" "t" "n" "e" "i" "o" ];
131 extraConfig.console.keyMap = "colemak";
132 extraConfig.services.xserver.xkb.layout = "us";
133 extraConfig.services.xserver.xkb.variant = "colemak";
138 homerow.qwerty = [ "a" "s" "d" "f" "j" "k" "l" "semicolon" ];
139 homerow.expect = [ "a" "o" "e" "u" "h" "t" "n" "s" ];
140 symbols.qwerty = [ "q" "w" "e" "minus" "equal" ];
141 symbols.expect = [ "'" "," "." "[" "]" ];
144 extraConfig.console.keyMap = "dvorak";
145 extraConfig.services.xserver.xkb.layout = "us";
146 extraConfig.services.xserver.xkb.variant = "dvorak";
149 dvorak-programmer = {
151 homerow.qwerty = [ "a" "s" "d" "f" "j" "k" "l" "semicolon" ];
152 homerow.expect = [ "a" "o" "e" "u" "h" "t" "n" "s" ];
153 numbers.qwerty = map (x: "shift-${x}")
154 [ "1" "2" "3" "4" "5" "6" "7" "8" "9" "0" "minus" ];
155 numbers.expect = [ "%" "7" "5" "3" "1" "9" "0" "2" "4" "6" "8" ];
156 symbols.qwerty = [ "1" "2" "3" "4" "5" "6" "7" "8" "9" "0" "minus" ];
157 symbols.expect = [ "&" "[" "{" "}" "(" "=" "*" ")" "+" "]" "!" ];
160 extraConfig.console.keyMap = "dvorak-programmer";
161 extraConfig.services.xserver.xkb.layout = "us";
162 extraConfig.services.xserver.xkb.variant = "dvp";
167 layer1.qwerty = [ "f" "j" ];
168 layer1.expect = [ "e" "n" ];
169 layer2.qwerty = [ "shift-f" "shift-j" "shift-6" ];
170 layer2.expect = [ "E" "N" "$" ];
171 layer3.qwerty = [ "caps_lock-d" "caps_lock-f" ];
172 layer3.expect = [ "{" "}" ];
175 extraConfig.console.keyMap = "neo";
176 extraConfig.services.xserver.xkb.layout = "de";
177 extraConfig.services.xserver.xkb.variant = "neo";
182 zy.qwerty = [ "z" "y" ];
183 zy.expect = [ "y" "z" ];
184 altgr.qwerty = map (x: "alt_r-${x}")
185 [ "q" "less" "7" "8" "9" "0" ];
186 altgr.expect = [ "@" "|" "{" "[" "]" "}" ];
189 extraConfig.console.keyMap = "de";
190 extraConfig.services.xserver.xkb.layout = "de";
195 us.qwerty = [ "a" "b" "g" "d" "z" "shift-2" "shift-3" ];
196 us.expect = [ "a" "b" "g" "d" "z" "@" "#" ];
197 greek.qwerty = map (x: "alt_r-${x}")
198 [ "a" "b" "g" "d" "z" ];
199 greek.expect = [ "α" "β" "γ" "δ" "ζ" ];
202 extraConfig.console.useXkbConfig = true;
203 extraConfig.services.xserver.xkb.layout = "us-greek";
204 extraConfig.services.xserver.xkb.extraLayouts.us-greek =
205 { description = "US layout with alt-gr greek";
206 languages = [ "eng" ];
207 symbolsFile = pkgs.writeText "us-greek" ''
208 xkb_symbols "us-greek"
211 include "level3(ralt_switch)"
212 key <LatA> { [ a, A, Greek_alpha ] };
213 key <LatB> { [ b, B, Greek_beta ] };
214 key <LatG> { [ g, G, Greek_gamma ] };
215 key <LatD> { [ d, D, Greek_delta ] };
216 key <LatZ> { [ z, Z, Greek_zeta ] };