lenient-mode.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. * Copyright © 2009 Dan Nicholson
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "config.h"
  6. #include "features/enums.h"
  7. #include "test-config.h"
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include "xkbcommon/xkbcommon.h"
  12. #include "test.h"
  13. #include "utils.h"
  14. #define GOLDEN_TESTS_OUTPUTS "keymaps/"
  15. struct keymap_test_data {
  16. /** Keymap string to compile */
  17. const char * const keymap;
  18. /** Resulting file *path* to reference serialization,
  19. * or NULL if the keymap string should not compile. */
  20. const char * const expected;
  21. /** Optionally skip the test */
  22. bool skip;
  23. };
  24. static const struct {
  25. const char* name;
  26. enum xkb_keymap_compile_flags flags;
  27. bool fail;
  28. } modes[] = {
  29. {
  30. "strict",
  31. (TEST_KEYMAP_COMPILE_FLAGS | XKB_KEYMAP_COMPILE_STRICT_MODE),
  32. true
  33. },
  34. {
  35. "lax",
  36. (TEST_KEYMAP_COMPILE_FLAGS & ~XKB_KEYMAP_COMPILE_STRICT_MODE),
  37. false
  38. },
  39. };
  40. /* Our keymap compiler is the xkbcommon buffer compiler */
  41. static struct xkb_keymap *
  42. compile_buffer(struct xkb_context *context, enum xkb_keymap_format format,
  43. const char *buf, size_t len, void *private)
  44. {
  45. return test_compile_buffer2(context, format,
  46. *(enum xkb_keymap_compile_flags*)private,
  47. buf, len);
  48. }
  49. static void
  50. test_unknown_declaration_statements(struct xkb_context *ctx, bool update_files)
  51. {
  52. static const struct keymap_test_data tests[] = {
  53. /*
  54. * Keycodes
  55. */
  56. {
  57. .keymap = "default xkb_keymap { xkb_keycodes { xxx \"1\" = \"xxx\"; }; };",
  58. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  59. },
  60. {
  61. .keymap = "default xkb_keymap { xkb_keycodes { xxx 1 = yyy; }; };",
  62. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  63. },
  64. {
  65. .keymap = "default xkb_keymap { xkb_keycodes { xxx 1.23 = Group1; }; };",
  66. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  67. },
  68. {
  69. .keymap = "default xkb_keymap { xkb_keycodes { xxx <> = 1 + 1; }; };",
  70. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  71. },
  72. /*
  73. * Types
  74. */
  75. {
  76. .keymap = "default xkb_keymap { xkb_types { xxx \"1\" = \"xxx\"; }; };",
  77. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  78. },
  79. {
  80. .keymap = "default xkb_keymap { xkb_types { xxx 1 = yyy; }; };",
  81. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  82. },
  83. {
  84. .keymap = "default xkb_keymap { xkb_types { xxx 1.23 = Group1; }; };",
  85. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  86. },
  87. {
  88. .keymap = "default xkb_keymap { xkb_types { xxx <> = 1 + 1; }; };",
  89. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  90. },
  91. /*
  92. * Compat
  93. */
  94. {
  95. .keymap = "default xkb_keymap { xkb_compat { xxx \"1\" = \"xxx\"; }; };",
  96. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  97. },
  98. {
  99. .keymap = "default xkb_keymap { xkb_compat { xxx 1 = yyy; }; };",
  100. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  101. },
  102. {
  103. .keymap = "default xkb_keymap { xkb_compat { xxx 1.23 = Group1; }; };",
  104. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  105. },
  106. {
  107. .keymap = "default xkb_keymap { xkb_compat { xxx <> = 1 + 1; }; };",
  108. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  109. },
  110. /*
  111. * Symbols
  112. */
  113. {
  114. .keymap = "default xkb_keymap { xkb_symbols { xxx \"1\" = \"xxx\"; }; };",
  115. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  116. },
  117. {
  118. .keymap = "default xkb_keymap { xkb_symbols { xxx 1 = yyy; }; };",
  119. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  120. },
  121. {
  122. .keymap = "default xkb_keymap { xkb_symbols { xxx 1.23 = Group1; }; };",
  123. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  124. },
  125. {
  126. .keymap = "default xkb_keymap { xkb_symbols { xxx <> = 1 + 1; }; };",
  127. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  128. },
  129. };
  130. for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) {
  131. fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k);
  132. for (size_t m = 0; m < ARRAY_SIZE(modes); m++) {
  133. assert(test_compile_output(
  134. ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT,
  135. compile_buffer, (void*)&modes[m].flags, modes[m].name,
  136. tests[k].keymap, strlen(tests[k].keymap),
  137. (modes[m].fail ? NULL : tests[k].expected), update_files
  138. ));
  139. }
  140. }
  141. }
  142. static void
  143. test_unknown_compound_statements(struct xkb_context *ctx, bool update_files)
  144. {
  145. static const struct keymap_test_data tests[] = {
  146. /*
  147. * Keycodes
  148. */
  149. {
  150. .keymap = "default xkb_keymap { xkb_keycodes { xxx {}; }; };",
  151. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  152. },
  153. {
  154. .keymap = "default xkb_keymap { xkb_keycodes { xxx \"yyy\" {}; }; };",
  155. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  156. },
  157. {
  158. .keymap = "default xkb_keymap { xkb_keycodes { xxx.yyy = 0; }; };",
  159. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  160. },
  161. /*
  162. * Types
  163. */
  164. {
  165. .keymap = "default xkb_keymap { xkb_types { xxx { yyy = 1; }; }; };",
  166. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  167. },
  168. {
  169. .keymap = "default xkb_keymap { xkb_types { xxx 1 { yyy[1] = true; }; }; };",
  170. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  171. },
  172. {
  173. .keymap = "default xkb_keymap { xkb_types { xxx.yyy = 0; }; };",
  174. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  175. },
  176. /*
  177. * Compat
  178. */
  179. {
  180. .keymap = "default xkb_keymap { xkb_compat { xxx 1.23 {}; }; };",
  181. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  182. },
  183. {
  184. .keymap = "default xkb_keymap { xkb_compat { xxx.yyy = 0; }; };",
  185. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  186. },
  187. /*
  188. * Symbols
  189. */
  190. {
  191. .keymap = "default xkb_keymap { xkb_symbols { xxx <> { a[<>] = {}; }; }; };",
  192. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  193. },
  194. {
  195. .keymap = "default xkb_keymap { xkb_symbols { xxx.yyy = 0; }; };",
  196. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  197. },
  198. };
  199. for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) {
  200. fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k);
  201. for (size_t m = 0; m < ARRAY_SIZE(modes); m++) {
  202. assert(test_compile_output(
  203. ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT,
  204. compile_buffer, (void*)&modes[m].flags, modes[m].name,
  205. tests[k].keymap, strlen(tests[k].keymap),
  206. (modes[m].fail ? NULL : tests[k].expected), update_files
  207. ));
  208. }
  209. }
  210. }
  211. static void
  212. test_unknown_fields(struct xkb_context *ctx, bool update_files)
  213. {
  214. static const struct keymap_test_data tests[] = {
  215. /*
  216. * Keycodes
  217. */
  218. {
  219. .keymap = "default xkb_keymap { xkb_keycodes { xxx = 0; }; };",
  220. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  221. },
  222. /*
  223. * Types
  224. */
  225. {
  226. .keymap = "default xkb_keymap { xkb_types { xxx = 0; }; };",
  227. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  228. },
  229. {
  230. .keymap = "default xkb_keymap { xkb_types { type \"1\" { xxx = 0; }; }; };",
  231. .expected = GOLDEN_TESTS_OUTPUTS "lax-types-unknown-type-field.xkb"
  232. },
  233. /*
  234. * Compat
  235. */
  236. {
  237. .keymap = "default xkb_keymap { xkb_compat { xxx = 0; }; };",
  238. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  239. },
  240. {
  241. .keymap = "default xkb_keymap { xkb_compat { interpret A { xxx = 0; }; }; };",
  242. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-interpret-field.xkb"
  243. },
  244. {
  245. .keymap = "default xkb_keymap { xkb_compat { indicator \"1\" { xxx = 0; }; }; };",
  246. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-indicator-field.xkb"
  247. },
  248. /*
  249. * Symbols
  250. */
  251. {
  252. .keymap = "default xkb_keymap { xkb_symbols { xxx = 0; }; };",
  253. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  254. },
  255. {
  256. .keymap =
  257. "default xkb_keymap {\n"
  258. " xkb_keycodes { <> = 1; };\n"
  259. " xkb_symbols { key <> { xxx = 0, [none], [NoAction()] }; };\n"
  260. "};",
  261. .expected = GOLDEN_TESTS_OUTPUTS "lax-symbols-unknown-key-field.xkb"
  262. },
  263. };
  264. for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) {
  265. fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k);
  266. for (size_t m = 0; m < ARRAY_SIZE(modes); m++) {
  267. assert(test_compile_output(
  268. ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT,
  269. compile_buffer, (void*)&modes[m].flags, modes[m].name,
  270. tests[k].keymap, strlen(tests[k].keymap),
  271. (modes[m].fail ? NULL : tests[k].expected), update_files
  272. ));
  273. }
  274. }
  275. }
  276. static void
  277. test_unknown_values(struct xkb_context *ctx, bool update_files)
  278. {
  279. static const struct keymap_test_data tests[] = {
  280. /*
  281. * Keycodes
  282. */
  283. {
  284. .keymap =
  285. "default xkb_keymap {\n"
  286. " xkb_keycodes {\n"
  287. " minimum = xxx;\n"
  288. " maximum = \"x\";\n"
  289. " maximum[0] = 1;\n"
  290. " };\n"
  291. "};",
  292. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  293. },
  294. /*
  295. * Types
  296. */
  297. // TODO: types fields
  298. // {
  299. // .keymap =
  300. // "default xkb_keymap {\n"
  301. // " xkb_types {};\n"
  302. // "};",
  303. // .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  304. // },
  305. /*
  306. * Compat
  307. */
  308. // TODO: interpret & LEDs fields
  309. // {
  310. // .keymap =
  311. // "default xkb_keymap {\n"
  312. // " xkb_compat {\n"
  313. // " interpret. = \"\";\n"
  314. // " };\n"
  315. // "};",
  316. // .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  317. // },
  318. /*
  319. * Symbols
  320. */
  321. // {
  322. // .keymap =
  323. // "default xkb_keymap {\n"
  324. // " xkb_symbols {};\n"
  325. // "};",
  326. // .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  327. // },
  328. };
  329. for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) {
  330. fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k);
  331. for (size_t m = 0; m < ARRAY_SIZE(modes); m++) {
  332. assert(test_compile_output(
  333. ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT,
  334. compile_buffer, (void*)&modes[m].flags, modes[m].name,
  335. tests[k].keymap, strlen(tests[k].keymap),
  336. (modes[m].fail ? NULL : tests[k].expected), update_files
  337. ));
  338. }
  339. }
  340. }
  341. static void
  342. test_actions(struct xkb_context *ctx, bool update_files)
  343. {
  344. static const struct keymap_test_data tests[] = {
  345. /*
  346. * Compat
  347. */
  348. {
  349. .keymap = "default xkb_keymap { xkb_compat { SetMods.xxx = 0; }; };",
  350. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  351. },
  352. {
  353. .keymap = "default xkb_keymap { xkb_compat { SetMods.mods = xxx; }; };",
  354. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  355. },
  356. {
  357. .keymap = "default xkb_keymap { xkb_compat { SetMods.mods = \"0\"; }; };",
  358. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  359. },
  360. {
  361. .keymap = "default xkb_keymap { xkb_compat { SetMods.mods[0] = 0; }; };",
  362. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  363. },
  364. {
  365. .keymap = "default xkb_keymap { xkb_compat { XXX.xxx = 0; }; };",
  366. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  367. },
  368. {
  369. .keymap =
  370. "default xkb_keymap {\n"
  371. " xkb_compat { interpret A { action = XXX(); }; };\n"
  372. "};",
  373. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-interpret-field.xkb"
  374. },
  375. {
  376. .keymap =
  377. "default xkb_keymap {\n"
  378. " xkb_compat { interpret A { action = XXX(xxx=0); }; };\n"
  379. "};",
  380. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-interpret-field.xkb"
  381. },
  382. {
  383. .keymap =
  384. "default xkb_keymap {\n"
  385. " xkb_compat { interpret A { action = SetMods(xxx=0); }; };\n"
  386. "};",
  387. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-action-field.xkb"
  388. },
  389. {
  390. .keymap =
  391. "default xkb_keymap {\n"
  392. " xkb_compat { interpret A { action = SetMods(mods=xxx); }; };\n"
  393. "};",
  394. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-action-value.xkb"
  395. },
  396. {
  397. .keymap =
  398. "default xkb_keymap {\n"
  399. " xkb_compat { interpret A { action = SetMods(mods=\"0\"); }; };\n"
  400. "};",
  401. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-action-value.xkb"
  402. },
  403. {
  404. .keymap =
  405. "default xkb_keymap {\n"
  406. " xkb_compat { interpret A { action = SetMods(mods[0]=0); }; };\n"
  407. "};",
  408. .expected = GOLDEN_TESTS_OUTPUTS "lax-compat-unknown-action-value.xkb"
  409. },
  410. /*
  411. * Symbols
  412. */
  413. {
  414. .keymap = "default xkb_keymap { xkb_symbols { SetMods.xxx = 0; }; };",
  415. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  416. },
  417. {
  418. .keymap = "default xkb_keymap { xkb_symbols { SetMods.mods = xxx; }; };",
  419. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  420. },
  421. {
  422. .keymap = "default xkb_keymap { xkb_symbols { SetMods.mods = \"0\"; }; };",
  423. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  424. },
  425. {
  426. .keymap = "default xkb_keymap { xkb_symbols { SetMods.mods[0] = 0; }; };",
  427. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  428. },
  429. {
  430. .keymap = "default xkb_keymap { xkb_symbols { XXX.xxx = 0; }; };",
  431. .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb"
  432. },
  433. {
  434. .keymap =
  435. "default xkb_keymap {\n"
  436. " xkb_keycodes { <> = 1; };\n"
  437. " xkb_symbols { key <> { [none], [XXX()] }; };\n"
  438. "};",
  439. .expected = GOLDEN_TESTS_OUTPUTS "lax-symbols-unknown-key-field.xkb"
  440. },
  441. {
  442. .keymap =
  443. "default xkb_keymap {\n"
  444. " xkb_keycodes { <> = 1; };\n"
  445. " xkb_symbols { key <> { [none], [XXX(xxx=0)] }; };\n"
  446. "};",
  447. .expected = GOLDEN_TESTS_OUTPUTS "lax-symbols-unknown-key-field.xkb"
  448. },
  449. {
  450. .keymap =
  451. "default xkb_keymap {\n"
  452. " xkb_keycodes { <> = 1; };\n"
  453. " xkb_symbols { key <> { [none], [SetMods(xxx=0)] }; };\n"
  454. "};",
  455. .expected = GOLDEN_TESTS_OUTPUTS "lax-symbols-unknown-action-field.xkb"
  456. },
  457. {
  458. .keymap =
  459. "default xkb_keymap {\n"
  460. " xkb_keycodes { <> = 1; };\n"
  461. " xkb_symbols { key <> { [none], [SetMods(mods=xxx)] }; };\n"
  462. "};",
  463. .expected = GOLDEN_TESTS_OUTPUTS "lax-symbols-unknown-action-value.xkb"
  464. },
  465. {
  466. .keymap =
  467. "default xkb_keymap {\n"
  468. " xkb_keycodes { <> = 1; };\n"
  469. " xkb_symbols { key <> { [none], [SetMods(mods=\"0\")] }; };\n"
  470. "};",
  471. .expected = GOLDEN_TESTS_OUTPUTS "lax-symbols-unknown-action-value.xkb"
  472. },
  473. {
  474. .keymap =
  475. "default xkb_keymap {\n"
  476. " xkb_keycodes { <> = 1; };\n"
  477. " xkb_symbols { key <> { [none], [SetMods(mods[0]=0)] }; };\n"
  478. "};",
  479. .expected = GOLDEN_TESTS_OUTPUTS "lax-symbols-unknown-action-value.xkb"
  480. },
  481. };
  482. for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) {
  483. fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k);
  484. for (size_t m = 0; m < ARRAY_SIZE(modes); m++) {
  485. assert(test_compile_output(
  486. ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT,
  487. compile_buffer, (void*)&modes[m].flags, modes[m].name,
  488. tests[k].keymap, strlen(tests[k].keymap),
  489. (modes[m].fail ? NULL : tests[k].expected), update_files
  490. ));
  491. }
  492. }
  493. }
  494. int
  495. main(int argc, char *argv[])
  496. {
  497. test_init();
  498. bool update_output_files = false;
  499. if (argc > 1) {
  500. if (streq(argv[1], "update")) {
  501. /* Update files with *obtained* results */
  502. update_output_files = true;
  503. } else {
  504. fprintf(stderr, "ERROR: unsupported argument: \"%s\".\n", argv[1]);
  505. exit(EXIT_FAILURE);
  506. }
  507. }
  508. struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG);
  509. test_unknown_declaration_statements(ctx, update_output_files);
  510. test_unknown_compound_statements(ctx, update_output_files);
  511. test_unknown_fields(ctx, update_output_files);
  512. test_unknown_values(ctx, update_output_files);
  513. test_actions(ctx, update_output_files);
  514. xkb_context_unref(ctx);
  515. return EXIT_SUCCESS;
  516. }