features.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright © 2025 Pierre Le Marre <dev@wismill.eu>
  3. *
  4. * SPDX-License-Identifier: MIT
  5. */
  6. #include "config.h"
  7. #include "test-config.h"
  8. #include <limits.h>
  9. #include <stdint.h>
  10. #include "xkbcommon/xkbcommon-features.h"
  11. #include "test.h"
  12. #include "utils.h"
  13. #include "src/features/enums.h"
  14. #include "xkbcommon/xkbcommon.h"
  15. static void
  16. test_libxkbcommon_enums(void)
  17. {
  18. /*
  19. * All enums, all valid values
  20. */
  21. enum enum_property {
  22. ENUM_NONE = 0,
  23. ENUM_FLAG = (1u << 0),
  24. };
  25. static const struct {
  26. enum xkb_feature feature;
  27. enum enum_property properties;
  28. const char * name;
  29. const uint32_t * values;
  30. size_t count;
  31. } tests[] = {
  32. #define ENUM(feature, values, flag) { (feature), (flag), STRINGIFY(feature), (values), ARRAY_SIZE(values) }
  33. ENUM(XKB_FEATURE_ENUM_FEATURE, xkb_feature_values, ENUM_NONE),
  34. ENUM(XKB_FEATURE_ENUM_ERROR_CODE, xkb_error_code_values, ENUM_NONE),
  35. ENUM(XKB_FEATURE_ENUM_CONTEXT_FLAGS, xkb_context_flags_values, ENUM_FLAG),
  36. ENUM(XKB_FEATURE_ENUM_LOG_LEVEL, xkb_log_level_values, ENUM_NONE),
  37. ENUM(XKB_FEATURE_ENUM_KEYSYM_FLAGS, xkb_keysym_flags_values, ENUM_FLAG),
  38. ENUM(XKB_FEATURE_ENUM_RMLVO_BUILDER_FLAGS, xkb_rmlvo_builder_flags_values, ENUM_FLAG),
  39. ENUM(XKB_FEATURE_ENUM_KEYMAP_FORMAT, xkb_keymap_format_values, ENUM_NONE),
  40. ENUM(XKB_FEATURE_ENUM_KEYMAP_COMPILE_FLAGS, xkb_keymap_compile_flags_values, ENUM_FLAG),
  41. ENUM(XKB_FEATURE_ENUM_KEYMAP_SERIALIZE_FLAGS, xkb_keymap_serialize_flags_values, ENUM_FLAG),
  42. ENUM(XKB_FEATURE_ENUM_KEYMAP_KEY_ITERATOR_FLAGS, xkb_keymap_key_iterator_flags_values, ENUM_FLAG),
  43. ENUM(XKB_FEATURE_ENUM_STATE_COMPONENT, xkb_state_component_values, ENUM_FLAG),
  44. ENUM(XKB_FEATURE_ENUM_LAYOUT_OUT_OF_RANGE_POLICY, xkb_layout_out_of_range_policy_values, ENUM_NONE),
  45. ENUM(XKB_FEATURE_ENUM_A11Y_FLAGS, xkb_a11y_flags_values, ENUM_FLAG),
  46. ENUM(XKB_FEATURE_ENUM_KEYBOARD_CONTROL_FLAGS, xkb_keyboard_control_flags_values, ENUM_FLAG),
  47. ENUM(XKB_FEATURE_ENUM_STATE_MODE, xkb_state_mode_values, ENUM_NONE),
  48. ENUM(XKB_FEATURE_ENUM_STATE_MATCH, xkb_state_match_values, ENUM_FLAG),
  49. ENUM(XKB_FEATURE_ENUM_CONSUMED_MODE, xkb_consumed_mode_values, ENUM_NONE),
  50. ENUM(XKB_FEATURE_ENUM_MACHINE_BUILDER_FLAGS, xkb_machine_builder_flags_values, ENUM_FLAG),
  51. ENUM(XKB_FEATURE_ENUM_EVENT_TYPE, xkb_event_type_values, ENUM_NONE),
  52. ENUM(XKB_FEATURE_ENUM_KEY_DIRECTION, xkb_key_direction_values, ENUM_NONE),
  53. ENUM(XKB_FEATURE_ENUM_EVENTS_FLAGS, xkb_events_flags_values, ENUM_FLAG),
  54. ENUM(XKB_FEATURE_ENUM_COMPOSE_FORMAT, xkb_compose_format_values, ENUM_NONE),
  55. ENUM(XKB_FEATURE_ENUM_COMPOSE_COMPILE_FLAGS, xkb_compose_compile_flags_values, ENUM_FLAG),
  56. ENUM(XKB_FEATURE_ENUM_COMPOSE_STATUS, xkb_compose_status_values, ENUM_NONE),
  57. ENUM(XKB_FEATURE_ENUM_COMPOSE_STATE_FLAGS, xkb_compose_state_flags_values, ENUM_FLAG),
  58. ENUM(XKB_FEATURE_ENUM_COMPOSE_FEED_RESULT, xkb_compose_feed_result_values, ENUM_NONE),
  59. #undef ENUM
  60. };
  61. /* Test all enums values */
  62. for (size_t t = 0; t < ARRAY_SIZE(tests); t++) {
  63. fprintf(stderr, "------\n*** %s: #%zu %s ***\n", __func__, t, tests[t].name);
  64. /* Ensure to test all the enums */
  65. static_assert(ARRAY_SIZE(tests) == ARRAY_SIZE(xkb_feature_values),
  66. "Enum test count mismatch");
  67. assert(t == 0 || tests[t].feature > tests[t - 1].feature);
  68. /* Explicit values */
  69. bool has_zero = false;
  70. int32_t min = INT32_MAX;
  71. int32_t max = INT32_MIN;
  72. assert(tests[t].count > 0);
  73. for (size_t v = 0; v < tests[t].count; v++) {
  74. assert(xkb_feature_supported(tests[t].feature, tests[t].values[v]));
  75. if (tests[t].values[v] == 0)
  76. has_zero = true;
  77. min = MIN(min, (int32_t)tests[t].values[v]);
  78. max = MAX(max, (int32_t)tests[t].values[v]);
  79. }
  80. const enum xkb_feature feature = tests[t].feature;
  81. if (tests[t].properties & ENUM_FLAG) {
  82. /* Flag enum */
  83. /* Explicit zero */
  84. assert(has_zero ^ !xkb_feature_supported(feature, 0));
  85. /* No negative values */
  86. assert(min >= 0);
  87. assert(!xkb_feature_supported(feature, (uint32_t)-1));
  88. assert(!xkb_feature_supported(feature, (uint32_t)INT_MIN));
  89. assert(!xkb_feature_supported(feature, (uint32_t)INT32_MIN));
  90. /* No high positive values */
  91. #define ENUM_HIGHEST_VALUE XKB_STATE_MATCH_NON_EXCLUSIVE
  92. assert(max <= ENUM_HIGHEST_VALUE);
  93. /* Invalid mask */
  94. static_assert(ENUM_HIGHEST_VALUE < (INT32_MAX >> 1), "");
  95. assert(!xkb_feature_supported(feature, (ENUM_HIGHEST_VALUE << 1)));
  96. #undef ENUM_HIGHEST_VALUE
  97. if (max > 0) {
  98. assert(!xkb_feature_supported(feature, (max << 1)));
  99. assert(!xkb_feature_supported(feature, max | (max << 1)));
  100. }
  101. } else {
  102. /* Non-flag enum */
  103. /* Explicit zero */
  104. assert(has_zero ^ !xkb_feature_supported(feature, 0));
  105. /* No high values */
  106. assert(min > -2);
  107. assert(!xkb_feature_supported(feature, (uint32_t)-2));
  108. assert(!xkb_feature_supported(feature, min - 1));
  109. assert(max < 0xf000);
  110. assert(!xkb_feature_supported(feature, 0xf000));
  111. assert(!xkb_feature_supported(feature, max + 1));
  112. }
  113. }
  114. /*
  115. * Reference enum
  116. */
  117. /* Invalid feature */
  118. assert(!xkb_feature_supported(-1, 0));
  119. assert(!xkb_feature_supported(0xffff, 0));
  120. /* Invalid enum value */
  121. assert(!xkb_feature_supported(XKB_FEATURE_ENUM_FEATURE, (uint32_t)-1));
  122. assert(!xkb_feature_supported(XKB_FEATURE_ENUM_FEATURE, 0xffff));
  123. /*
  124. * Specific values
  125. */
  126. assert(!xkb_feature_supported(XKB_FEATURE_ENUM_KEYMAP_FORMAT,
  127. XKB_KEYMAP_USE_ORIGINAL_FORMAT));
  128. assert(!xkb_feature_supported(XKB_FEATURE_ENUM_KEYMAP_FORMAT, 0));
  129. assert(!xkb_feature_supported(XKB_FEATURE_ENUM_KEYMAP_FORMAT, 3));
  130. }
  131. int
  132. main(void)
  133. {
  134. test_init();
  135. test_libxkbcommon_enums();
  136. }