test_cli_commands.py (14256B)
1 import platform 2 from subprocess import DEVNULL 3 4 from milc import cli 5 6 is_windows = 'windows' in platform.platform().lower() 7 8 9 def check_subcommand(command, *args): 10 cmd = ['qmk', command, *args] 11 result = cli.run(cmd, stdin=DEVNULL, combined_output=True) 12 return result 13 14 15 def 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 24 def 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 34 def test_format_c(): 35 result = check_subcommand('format-c', '-n', 'quantum/matrix.c') 36 check_returncode(result) 37 38 39 def test_format_c_all(): 40 result = check_subcommand('format-c', '-n', '-a') 41 check_returncode(result, [0, 1]) 42 43 44 def test_compile(): 45 result = check_subcommand('compile', '-kb', 'handwired/pytest/basic', '-km', 'default', '-n') 46 check_returncode(result) 47 48 49 def test_compile_json(): 50 result = check_subcommand('compile', '-kb', 'handwired/pytest/basic', '-km', 'default_json', '-n') 51 check_returncode(result) 52 53 54 def test_flash(): 55 result = check_subcommand('flash', '-kb', 'handwired/pytest/basic', '-km', 'default', '-n') 56 check_returncode(result) 57 58 59 def test_flash_bootloaders(): 60 result = check_subcommand('flash', '-b') 61 check_returncode(result, [1]) 62 63 64 def 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 70 def 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 77 def test_hello(): 78 result = check_subcommand('hello') 79 check_returncode(result) 80 assert 'Hello,' in result.stdout 81 82 83 def 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 89 def 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 97 def 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 104 def 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 111 def 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 117 def 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 123 def 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 129 def 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 135 def 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 141 def 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 156 const 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 171 def 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 179 def 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 194 const 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 209 def 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 215 def 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 224 def 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 237 def 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 249 def 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 264 def 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 270 def 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 276 def 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 282 def test_generate_api(): 283 result = check_subcommand('generate-api', '--dry-run', '--filter', 'handwired/pytest') 284 check_returncode(result) 285 286 287 def 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 294 def 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 309 def 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 316 def 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 322 def 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 328 def 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 334 def 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 340 def 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 346 def 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 356 def 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 366 def 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 375 def 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 384 def 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