scanner: don't fail over unknown escape sequence
[platform/upstream/libxkbcommon.git] / test / rulescomp.c
1 /*
2  * Copyright © 2009 Dan Nicholson
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23
24 #include <linux/input.h>
25 #include <time.h>
26
27 #include "test.h"
28
29 #define BENCHMARK_ITERATIONS 1000
30
31 static int
32 test_rmlvo_va(struct xkb_context *context, const char *rules,
33               const char *model, const char *layout,
34               const char *variant, const char *options, va_list ap)
35 {
36     struct xkb_keymap *keymap;
37     int ret;
38
39     keymap = test_compile_rules(context, rules, model, layout, variant,
40                                 options);
41     if (!keymap)
42         return 0;
43
44     fprintf(stderr, "Compiled '%s' '%s' '%s' '%s' '%s'\n",
45             strnull(rules), strnull(model), strnull(layout),
46             strnull(variant), strnull(options));
47
48     ret = test_key_seq_va(keymap, ap);
49
50     xkb_keymap_unref(keymap);
51
52     return ret;
53 }
54
55 static int
56 test_rmlvo(struct xkb_context *context, const char *rules,
57            const char *model, const char *layout, const char *variant,
58            const char *options, ...)
59 {
60     va_list ap;
61     int ret;
62
63     va_start(ap, options);
64     ret = test_rmlvo_va(context, rules, model, layout, variant, options, ap);
65     va_end(ap);
66
67     return ret;
68 }
69
70 static int
71 test_rmlvo_silent(struct xkb_context *context, const char *rules,
72                   const char *model, const char *layout,
73                   const char *variant, const char *options)
74 {
75     struct xkb_keymap *keymap;
76
77     keymap = test_compile_rules(context, rules, model, layout, variant,
78                                 options);
79     if (keymap)
80         xkb_keymap_unref(keymap);
81
82     return keymap != NULL;
83 }
84
85 static int
86 test_rmlvo_env(struct xkb_context *ctx, const char *rules, const char *model,
87                const char *layout, const char *variant, const char *options,
88                ...)
89 {
90     va_list ap;
91     int ret;
92
93     va_start (ap, options);
94
95     if (!isempty(rules))
96         setenv("XKB_DEFAULT_RULES", rules, 1);
97     else
98         unsetenv("XKB_DEFAULT_RULES");
99
100     if (!isempty(model))
101         setenv("XKB_DEFAULT_MODEL", model, 1);
102     else
103         unsetenv("XKB_DEFAULT_MODEL");
104
105     if (!isempty(layout))
106         setenv("XKB_DEFAULT_LAYOUT", layout, 1);
107     else
108         unsetenv("XKB_DEFAULT_LAYOUT");
109
110     if (!isempty(variant))
111         setenv("XKB_DEFAULT_VARIANT", variant, 1);
112     else
113         unsetenv("XKB_DEFAULT_VARIANT");
114
115     if (!isempty(options))
116         setenv("XKB_DEFAULT_OPTIONS", options, 1);
117     else
118         unsetenv("XKB_DEFAULT_OPTIONS");
119
120     ret = test_rmlvo_va(ctx, NULL, NULL, NULL, NULL, NULL, ap);
121
122     va_end(ap);
123
124     return ret;
125 }
126
127 static void
128 benchmark(struct xkb_context *context)
129 {
130     struct timespec start, stop, elapsed;
131     enum xkb_log_level old_level = xkb_context_get_log_level(context);
132     int old_verb = xkb_context_get_log_verbosity(context);
133     int i;
134
135     xkb_context_set_log_level(context, XKB_LOG_LEVEL_CRITICAL);
136     xkb_context_set_log_verbosity(context, 0);
137
138     clock_gettime(CLOCK_MONOTONIC, &start);
139     for (i = 0; i < BENCHMARK_ITERATIONS; i++)
140         assert(test_rmlvo_silent(context, "evdev", "evdev", "us", "", ""));
141     clock_gettime(CLOCK_MONOTONIC, &stop);
142
143     xkb_context_set_log_level(context, old_level);
144     xkb_context_set_log_verbosity(context, old_verb);
145
146     elapsed.tv_sec = stop.tv_sec - start.tv_sec;
147     elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
148     if (elapsed.tv_nsec < 0) {
149         elapsed.tv_nsec += 1000000000;
150         elapsed.tv_sec--;
151     }
152
153     fprintf(stderr, "compiled %d keymaps in %ld.%09lds\n",
154             BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec);
155 }
156
157 int
158 main(int argc, char *argv[])
159 {
160     struct xkb_context *ctx = test_get_context(CONTEXT_ALLOW_ENVIRONMENT_NAMES);
161
162     assert(ctx);
163
164     if (argc > 1 && streq(argv[1], "bench")) {
165         benchmark(ctx);
166         return 0;
167     }
168
169 #define KS(name) xkb_keysym_from_name(name, 0)
170
171     assert(test_rmlvo(ctx, "evdev", "pc105", "us,il,ru,ca", ",,,multix", "grp:alts_toggle,ctrl:nocaps,compose:rwin",
172                       KEY_Q,          BOTH, XKB_KEY_q,                    NEXT,
173                       KEY_LEFTALT,    DOWN, XKB_KEY_Alt_L,                NEXT,
174                       KEY_RIGHTALT,   DOWN, XKB_KEY_ISO_Next_Group,       NEXT,
175                       KEY_RIGHTALT,   UP,   XKB_KEY_ISO_Level3_Shift,     NEXT,
176                       KEY_LEFTALT,    UP,   XKB_KEY_Alt_L,                NEXT,
177                       KEY_Q,          BOTH, XKB_KEY_slash,                NEXT,
178                       KEY_LEFTSHIFT,  DOWN, XKB_KEY_Shift_L,              NEXT,
179                       KEY_Q,          BOTH, XKB_KEY_Q,                    NEXT,
180                       KEY_RIGHTMETA,  BOTH, XKB_KEY_Multi_key,            FINISH));
181     assert(test_rmlvo(ctx, "evdev",  "pc105", "us,in", "", "grp:alts_toggle",
182                       KEY_A,          BOTH, XKB_KEY_a,                    NEXT,
183                       KEY_LEFTALT,    DOWN, XKB_KEY_Alt_L,                NEXT,
184                       KEY_RIGHTALT,   DOWN, XKB_KEY_ISO_Next_Group,       NEXT,
185                       KEY_RIGHTALT,   UP,   XKB_KEY_ISO_Level3_Shift,     NEXT,
186                       KEY_LEFTALT,    UP,   XKB_KEY_Alt_L,                NEXT,
187                       KEY_A,          BOTH, KS("U094b"),                  FINISH));
188     assert(test_rmlvo(ctx, "evdev", "pc105", "us", "intl", "",
189                       KEY_GRAVE,      BOTH,  XKB_KEY_dead_grave,          FINISH));
190     assert(test_rmlvo(ctx, "evdev", "evdev", "us", "intl", "grp:alts_toggle",
191                       KEY_GRAVE,      BOTH,  XKB_KEY_dead_grave,          FINISH));
192
193     /* 20 is not a legal group; make sure this is handled gracefully. */
194     assert(test_rmlvo(ctx, "evdev", "", "us:20", "", "",
195                       KEY_A,          BOTH, XKB_KEY_a,                    FINISH));
196
197     /* Don't choke on missing values in RMLVO. Should just skip them.
198        Currently generates us,us,ca. */
199     assert(test_rmlvo(ctx, "evdev", "", "us,,ca", "", "grp:alts_toggle",
200                       KEY_A,          BOTH, XKB_KEY_a,                    NEXT,
201                       KEY_LEFTALT,    DOWN, XKB_KEY_Alt_L,                NEXT,
202                       KEY_RIGHTALT,   DOWN, XKB_KEY_ISO_Next_Group,       NEXT,
203                       KEY_RIGHTALT,   UP,   XKB_KEY_ISO_Next_Group,       NEXT,
204                       KEY_LEFTALT,    UP,   XKB_KEY_Alt_L,                NEXT,
205                       KEY_LEFTALT,    DOWN, XKB_KEY_Alt_L,                NEXT,
206                       KEY_RIGHTALT,   DOWN, XKB_KEY_ISO_Next_Group,       NEXT,
207                       KEY_RIGHTALT,   UP,   XKB_KEY_ISO_Level3_Shift,     NEXT,
208                       KEY_LEFTALT,    UP,   XKB_KEY_Alt_L,                NEXT,
209                       KEY_APOSTROPHE, BOTH, XKB_KEY_dead_grave,           FINISH));
210
211     assert(test_rmlvo(ctx, "", "", "", "", "",
212                       KEY_A,          BOTH, XKB_KEY_a,                    FINISH));
213
214     assert(!test_rmlvo(ctx, "does-not-exist", "", "", "", "",
215                        KEY_A,          BOTH, XKB_KEY_a,                   FINISH));
216
217     assert(test_rmlvo_env(ctx, "evdev", "", "us", "", "",
218                           KEY_A,          BOTH, XKB_KEY_a,                FINISH));
219     assert(test_rmlvo_env(ctx, "evdev", "", "us", "", "ctrl:nocaps",
220                           KEY_CAPSLOCK,   BOTH, XKB_KEY_Control_L,        FINISH));
221
222     /* Ignores multix and generates us,ca. */
223     assert(test_rmlvo_env(ctx, "evdev", "", "us,ca", ",,,multix", "grp:alts_toggle",
224                           KEY_A,          BOTH, XKB_KEY_a,                NEXT,
225                           KEY_LEFTALT,    DOWN, XKB_KEY_Alt_L,            NEXT,
226                           KEY_RIGHTALT,   DOWN, XKB_KEY_ISO_Next_Group,   NEXT,
227                           KEY_RIGHTALT,   UP,   XKB_KEY_ISO_Level3_Shift, NEXT,
228                           KEY_LEFTALT,    UP,   XKB_KEY_Alt_L,            NEXT,
229                           KEY_GRAVE,      UP,   XKB_KEY_numbersign,       FINISH));
230
231     assert(!test_rmlvo_env(ctx, "broken", "what-on-earth", "invalid", "", "",
232                            KEY_A,          BOTH, XKB_KEY_a,               FINISH));
233
234     /* Ensure a keymap with an empty xkb_keycodes compiles fine. */
235     assert(test_rmlvo_env(ctx, "base", "empty", "empty", "", "",
236                           KEY_A,          BOTH, XKB_KEY_NoSymbol,         FINISH));
237
238     /* Has an illegal escape sequence, but shouldn't fail. */
239     assert(test_rmlvo_env(ctx, "evdev", "", "cz", "bksl", "",
240                           KEY_A,          BOTH, XKB_KEY_a,                FINISH));
241
242     xkb_context_unref(ctx);
243
244     ctx = test_get_context(0);
245     assert(test_rmlvo_env(ctx, "broken", "but", "ignored", "per", "ctx flags",
246                           KEY_A,          BOTH, XKB_KEY_a,                FINISH));
247
248     /* Test response to invalid flags. */
249     {
250         struct xkb_rule_names rmlvo = { NULL };
251         assert(!xkb_keymap_new_from_names(ctx, &rmlvo, -1));
252         assert(!xkb_keymap_new_from_names(ctx, &rmlvo, 5453));
253     }
254
255     xkb_context_unref(ctx);
256 }