summaryrefslogtreecommitdiff
path: root/lib/python/qmk/tests/test_cli_commands.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python/qmk/tests/test_cli_commands.py')
-rw-r--r--lib/python/qmk/tests/test_cli_commands.py408
1 files changed, 408 insertions, 0 deletions
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py
new file mode 100644
index 0000000000..2716459989
--- /dev/null
+++ b/lib/python/qmk/tests/test_cli_commands.py
@@ -0,0 +1,408 @@
1import platform
2from subprocess import DEVNULL
3
4from milc import cli
5
6is_windows = 'windows' in platform.platform().lower()
7
8
9def check_subcommand(command, *args):
10 cmd = ['qmk', command, *args]
11 result = cli.run(cmd, stdin=DEVNULL, combined_output=True)
12 return result
13
14
15def check_subcommand_stdin(file_to_read, command, *args):
16 """Pipe content of a file to a command and return output.
17 """
18 with open(file_to_read, encoding='utf-8') as my_file:
19 cmd = ['qmk', command, *args]
20 result = cli.run(cmd, stdin=my_file, combined_output=True)
21 return result
22
23
24def check_returncode(result, expected=[0]):
25 """Print stdout if `result.returncode` does not match `expected`.
26 """
27 if result.returncode not in expected:
28 print('`%s` stdout:' % ' '.join(result.args))
29 print(result.stdout)
30 print('returncode:', result.returncode)
31 assert result.returncode in expected
32
33
34def test_format_c():
35 result = check_subcommand('format-c', '-n', 'quantum/matrix.c')
36 check_returncode(result)
37
38
39def test_format_c_all():
40 result = check_subcommand('format-c', '-n', '-a')
41 check_returncode(result, [0, 1])
42
43
44def test_compile():
45 result = check_subcommand('compile', '-kb', 'handwired/pytest/basic', '-km', 'default', '-n')
46 check_returncode(result)
47
48
49def test_compile_json():
50 result = check_subcommand('compile', '-kb', 'handwired/pytest/basic', '-km', 'default_json', '-n')
51 check_returncode(result)
52
53
54def test_flash():
55 result = check_subcommand('flash', '-kb', 'handwired/pytest/basic', '-km', 'default', '-n')
56 check_returncode(result)
57
58
59def test_flash_bootloaders():
60 result = check_subcommand('flash', '-b')
61 check_returncode(result, [1])
62
63
64def test_kle2json():
65 result = check_subcommand('kle2json', 'lib/python/qmk/tests/kle.txt', '-f')
66 check_returncode(result)
67 assert 'Wrote out' in result.stdout
68
69
70def test_doctor():
71 result = check_subcommand('doctor', '-n')
72 check_returncode(result, [0, 1])
73 assert 'QMK Doctor is checking your environment.' in result.stdout
74 assert 'QMK is ready to go' in result.stdout
75
76
77def test_hello():
78 result = check_subcommand('hello')
79 check_returncode(result)
80 assert 'Hello,' in result.stdout
81
82
83def test_format_python():
84 result = check_subcommand('format-python', '-n', '-a')
85 check_returncode(result)
86 assert 'Successfully formatted the python code.' in result.stdout
87
88
89def test_list_keyboards():
90 result = check_subcommand('list-keyboards')
91 check_returncode(result)
92 # check to see if a known keyboard is returned
93 # this will fail if handwired/pytest/basic is removed
94 assert 'handwired/pytest/basic' in result.stdout
95
96
97def test_list_keymaps():
98 result = check_subcommand('list-keymaps', '-kb', 'handwired/pytest/basic')
99 check_returncode(result)
100 assert 'default' in result.stdout
101 assert 'default_json' in result.stdout
102
103
104def test_list_keymaps_long():
105 result = check_subcommand('list-keymaps', '--keyboard', 'handwired/pytest/basic')
106 check_returncode(result)
107 assert 'default' in result.stdout
108 assert 'default_json' in result.stdout
109
110
111def test_list_keymaps_community():
112 result = check_subcommand('list-keymaps', '--keyboard', 'handwired/pytest/has_community')
113 check_returncode(result)
114 assert 'test' in result.stdout
115
116
117def test_list_keymaps_kb_only():
118 result = check_subcommand('list-keymaps', '-kb', 'contra')
119 check_returncode(result)
120 assert 'default' in result.stdout
121
122
123def test_list_keymaps_vendor_kb():
124 result = check_subcommand('list-keymaps', '-kb', 'ai03/lunar')
125 check_returncode(result)
126 assert 'default' in result.stdout
127
128
129def test_list_keymaps_vendor_kb_rev():
130 result = check_subcommand('list-keymaps', '-kb', 'kbdfans/kbd67/mkiirgb/v2')
131 check_returncode(result)
132 assert 'default' in result.stdout
133
134
135def test_list_keymaps_no_keyboard_found():
136 result = check_subcommand('list-keymaps', '-kb', 'asdfghjkl')
137 check_returncode(result, [2])
138 assert 'invalid keyboard_folder value' in result.stdout
139
140
141def test_json2c():
142 result = check_subcommand('json2c', 'keyboards/handwired/pytest/basic/keymaps/default_json/keymap.json')
143 check_returncode(result)
144 assert result.stdout == """#include QMK_KEYBOARD_H
145#if __has_include("keymap.h")
146# include "keymap.h"
147#endif
148
149
150/* THIS FILE WAS GENERATED!
151 *
152 * This file was generated by qmk json2c. You may or may not want to
153 * edit it directly.
154 */
155
156const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
157 [0] = LAYOUT_ortho_1x1(KC_A)
158};
159
160
161
162
163#ifdef OTHER_KEYMAP_C
164# include OTHER_KEYMAP_C
165#endif // OTHER_KEYMAP_C
166
167
168"""
169
170
171def test_json2c_macros():
172 result = check_subcommand("json2c", 'keyboards/handwired/pytest/macro/keymaps/default/keymap.json')
173 check_returncode(result)
174 assert 'LAYOUT_ortho_1x1(QK_MACRO_0)' in result.stdout
175 assert 'case QK_MACRO_0:' in result.stdout
176 assert 'SEND_STRING("Hello, World!"SS_TAP(X_ENTER));' in result.stdout
177
178
179def test_json2c_stdin():
180 result = check_subcommand_stdin('keyboards/handwired/pytest/basic/keymaps/default_json/keymap.json', 'json2c', '-')
181 check_returncode(result)
182 assert result.stdout == """#include QMK_KEYBOARD_H
183#if __has_include("keymap.h")
184# include "keymap.h"
185#endif
186
187
188/* THIS FILE WAS GENERATED!
189 *
190 * This file was generated by qmk json2c. You may or may not want to
191 * edit it directly.
192 */
193
194const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
195 [0] = LAYOUT_ortho_1x1(KC_A)
196};
197
198
199
200
201#ifdef OTHER_KEYMAP_C
202# include OTHER_KEYMAP_C
203#endif // OTHER_KEYMAP_C
204
205
206"""
207
208
209def test_json2c_no_json():
210 result = check_subcommand('json2c', 'keyboards/handwired/pytest/basic/keymaps/default/keymap.c')
211 check_returncode(result, [1])
212 assert 'Invalid JSON encountered' in result.stdout
213
214
215def test_info():
216 result = check_subcommand('info', '-kb', 'handwired/pytest/basic')
217 check_returncode(result)
218 assert 'Keyboard Name: pytest' in result.stdout
219 assert 'Processor: atmega32u4' in result.stdout
220 assert 'Layout:' not in result.stdout
221 assert 'k0' not in result.stdout
222
223
224def test_info_keyboard_render():
225 result = check_subcommand('info', '-kb', 'handwired/pytest/basic', '-l')
226 check_returncode(result)
227 assert 'Keyboard Name: pytest' in result.stdout
228 assert 'Processor: atmega32u4' in result.stdout
229 assert 'Layouts:' in result.stdout
230
231 if is_windows:
232 assert '| |' in result.stdout
233 else:
234 assert '│ │' in result.stdout
235
236
237def test_info_keymap_render():
238 result = check_subcommand('info', '-kb', 'handwired/pytest/basic', '-km', 'default_json')
239 check_returncode(result)
240 assert 'Keyboard Name: pytest' in result.stdout
241 assert 'Processor: atmega32u4' in result.stdout
242
243 if is_windows:
244 assert '|A |' in result.stdout
245 else:
246 assert '│A │' in result.stdout
247
248
249def test_info_matrix_render():
250 result = check_subcommand('info', '-kb', 'handwired/pytest/basic', '-m')
251 check_returncode(result)
252 assert 'Keyboard Name: pytest' in result.stdout
253 assert 'Processor: atmega32u4' in result.stdout
254 assert 'LAYOUT_ortho_1x1' in result.stdout
255
256 if is_windows:
257 assert '|0A|' in result.stdout
258 else:
259 assert '│0A│' in result.stdout
260
261 assert 'Matrix for "LAYOUT_ortho_1x1"' in result.stdout
262
263
264def test_c2json():
265 result = check_subcommand("c2json", "-kb", "handwired/pytest/basic", "-km", "default", "keyboards/handwired/pytest/basic/keymaps/default/keymap.c")
266 check_returncode(result)
267 assert result.stdout.strip() == '{"keyboard": "handwired/pytest/basic", "keymap": "default", "layout": "LAYOUT_ortho_1x1", "layers": [["KC_A"]]}'
268
269
270def test_c2json_stdin():
271 result = check_subcommand_stdin("keyboards/handwired/pytest/basic/keymaps/default/keymap.c", "c2json", "-kb", "handwired/pytest/basic", "-km", "default", "-")
272 check_returncode(result)
273 assert result.stdout.strip() == '{"keyboard": "handwired/pytest/basic", "keymap": "default", "layout": "LAYOUT_ortho_1x1", "layers": [["KC_A"]]}'
274
275
276def test_clean():
277 result = check_subcommand('clean', '-a')
278 check_returncode(result)
279 assert (result.stdout.count('done') == 2 and 'userspace' not in result.stdout) or (result.stdout.count('done') == 3 and 'userspace' in result.stdout)
280
281
282def test_generate_api():
283 result = check_subcommand('generate-api', '--dry-run', '--filter', 'handwired/pytest')
284 check_returncode(result)
285
286
287def test_generate_rgb_breathe_table():
288 result = check_subcommand("generate-rgb-breathe-table", "-c", "1.2", "-m", "127")
289 check_returncode(result)
290 assert 'Breathing center: 1.2' in result.stdout
291 assert 'Breathing max: 127' in result.stdout
292
293
294def test_generate_config_h():
295 result = check_subcommand('generate-config-h', '-kb', 'handwired/pytest/basic')
296 check_returncode(result)
297 assert '# define DEVICE_VER 0x0001' in result.stdout
298 assert '# define DIODE_DIRECTION COL2ROW' in result.stdout
299 assert '# define MANUFACTURER "none"' in result.stdout
300 assert '# define PRODUCT "pytest"' in result.stdout
301 assert '# define PRODUCT_ID 0x6465' in result.stdout
302 assert '# define VENDOR_ID 0xFEED' in result.stdout
303 assert '# define MATRIX_COLS 1' in result.stdout
304 assert '# define MATRIX_COL_PINS { F4 }' in result.stdout
305 assert '# define MATRIX_ROWS 1' in result.stdout
306 assert '# define MATRIX_ROW_PINS { F5 }' in result.stdout
307
308
309def test_generate_rules_mk():
310 result = check_subcommand('generate-rules-mk', '-kb', 'handwired/pytest/basic')
311 check_returncode(result)
312 assert 'BOOTLOADER ?= atmel-dfu' in result.stdout
313 assert 'MCU ?= atmega32u4' in result.stdout
314
315
316def test_generate_version_h():
317 result = check_subcommand('generate-version-h')
318 check_returncode(result)
319 assert '#define QMK_VERSION' in result.stdout
320
321
322def test_format_json_keyboard():
323 result = check_subcommand('format-json', '--format', 'keyboard', 'lib/python/qmk/tests/minimal_info.json')
324 check_returncode(result)
325 assert result.stdout == '{\n "keyboard_name": "tester",\n "maintainer": "qmk",\n "layouts": {\n "LAYOUT": {\n "layout": [\n {"label": "KC_A", "matrix": [0, 0], "x": 0, "y": 0}\n ]\n }\n }\n}\n'
326
327
328def test_format_json_keymap():
329 result = check_subcommand('format-json', '--format', 'keymap', 'lib/python/qmk/tests/minimal_keymap.json')
330 check_returncode(result)
331 assert result.stdout == '{\n "version": 1,\n "keyboard": "handwired/pytest/basic",\n "keymap": "test",\n "layout": "LAYOUT_ortho_1x1",\n "layers": [\n [\n "KC_A"\n ]\n ]\n}\n'
332
333
334def test_format_json_keyboard_auto():
335 result = check_subcommand('format-json', '--format', 'auto', 'lib/python/qmk/tests/minimal_info.json')
336 check_returncode(result)
337 assert result.stdout == '{\n "keyboard_name": "tester",\n "maintainer": "qmk",\n "layouts": {\n "LAYOUT": {\n "layout": [\n {"label": "KC_A", "matrix": [0, 0], "x": 0, "y": 0}\n ]\n }\n }\n}\n'
338
339
340def test_format_json_keymap_auto():
341 result = check_subcommand('format-json', '--format', 'auto', 'lib/python/qmk/tests/minimal_keymap.json')
342 check_returncode(result)
343 assert result.stdout == '{\n "keyboard": "handwired/pytest/basic",\n "keymap": "test",\n "layers": [\n ["KC_A"]\n ],\n "layout": "LAYOUT_ortho_1x1",\n "version": 1\n}\n'
344
345
346def test_find_exists():
347 result = check_subcommand('find', '-f', 'exists(rgb_matrix.split_count)', '-p', 'rgb_matrix.split_count')
348 check_returncode(result)
349 values = [s for s in result.stdout.splitlines() if 'rgb_matrix.split_count=' in s]
350 assert len(values) > 0
351 for s in values:
352 assert '=None' not in s
353 assert '=[' in s
354
355
356def test_find_absent():
357 result = check_subcommand('find', '-f', 'absent(rgb_matrix.split_count)', '-p', 'rgb_matrix.split_count')
358 check_returncode(result)
359 values = [s for s in result.stdout.splitlines() if 'rgb_matrix.split_count=' in s]
360 assert len(values) > 0
361 for s in values:
362 assert '=None' in s
363 assert '=[' not in s
364
365
366def test_find_length():
367 result = check_subcommand('find', '-f', 'length(matrix_pins.cols, 6)', '-p', 'matrix_pins.cols')
368 check_returncode(result)
369 values = [s for s in result.stdout.splitlines() if 'matrix_pins.cols=' in s]
370 assert len(values) > 0
371 for s in values:
372 assert s.count(',') == 5
373
374
375def test_find_contains():
376 result = check_subcommand('find', '-f', 'contains(matrix_pins.cols, B1)', '-p', 'matrix_pins.cols')
377 check_returncode(result)
378 values = [s for s in result.stdout.splitlines() if 'matrix_pins.cols=' in s]
379 assert len(values) > 0
380 for s in values:
381 assert "'B1'" in s
382
383
384def test_find_multiple_conditions():
385 # this is intended to match at least 'crkbd/rev1'
386 result = check_subcommand(
387 'find', '-f', 'exists(rgb_matrix.split_count)', '-f', 'contains(matrix_pins.cols, B1)', '-f', 'length(matrix_pins.cols, 6)', '-f', 'absent(eeprom.driver)', '-f', 'ws2812.pin == D3', '-p', 'rgb_matrix.split_count', '-p', 'matrix_pins.cols', '-p',
388 'eeprom.driver', '-p', 'ws2812.pin'
389 )
390 check_returncode(result)
391 rgb_matrix_split_count_values = [s for s in result.stdout.splitlines() if 'rgb_matrix.split_count=' in s]
392 assert len(rgb_matrix_split_count_values) > 0
393 for s in rgb_matrix_split_count_values:
394 assert '=None' not in s
395 assert '=[' in s
396 matrix_pins_cols_values = [s for s in result.stdout.splitlines() if 'matrix_pins.cols=' in s]
397 assert len(matrix_pins_cols_values) > 0
398 for s in matrix_pins_cols_values:
399 assert s.count(',') == 5
400 assert "'B1'" in s
401 eeprom_driver_values = [s for s in result.stdout.splitlines() if 'eeprom.driver=' in s]
402 assert len(eeprom_driver_values) > 0
403 for s in eeprom_driver_values:
404 assert '=None' in s
405 ws2812_pin_values = [s for s in result.stdout.splitlines() if 'ws2812.pin=' in s]
406 assert len(ws2812_pin_values) > 0
407 for s in ws2812_pin_values:
408 assert '=D3' in s