test/keyseq: add de(neo) Level{6,7,8} tests
[platform/upstream/libxkbcommon.git] / test / common.c
1 /*
2  * Copyright © 2009 Dan Nicholson <dbn.lists@gmail.com>
3  * Copyright © 2012 Intel Corporation
4  * Copyright © 2012 Ran Benita <ran234@gmail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Except as contained in this notice, the names of the authors or their
24  * institutions shall not be used in advertising or otherwise to promote the
25  * sale, use or other dealings in this Software without prior written
26  * authorization from the authors.
27  *
28  * Author: Dan Nicholson <dbn.lists@gmail.com>
29  *         Daniel Stone <daniel@fooishbar.org>
30  *         Ran Benita <ran234@gmail.com>
31  */
32
33 #include <limits.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38
39 #include "test.h"
40
41 /*
42  * Test a sequence of keysyms, resulting from a sequence of key presses,
43  * against the keysyms they're supposed to generate.
44  *
45  * - Each test runs with a clean state.
46  * - Each line in the test is made up of:
47  *   + A keycode, given as a KEY_* from linux/input.h.
48  *   + A direction - DOWN for press, UP for release, BOTH for
49  *     immediate press + release, REPEAT to just get the syms.
50  *   + A sequence of keysyms that should result from this keypress.
51  *
52  * The vararg format is:
53  * <KEY_*>  <DOWN | UP | BOTH>  <XKB_KEY_* (zero or more)>  <NEXT | FINISH>
54  *
55  * See below for examples.
56  */
57 int
58 test_key_seq_va(struct xkb_keymap *keymap, va_list ap)
59 {
60     struct xkb_state *state;
61
62     xkb_keycode_t kc;
63     int op;
64     xkb_keysym_t keysym;
65
66     const xkb_keysym_t *syms;
67     unsigned int nsyms, i;
68     char ksbuf[64];
69
70     fprintf(stderr, "----\n");
71
72     state = xkb_state_new(keymap);
73     assert(state);
74
75     for (;;) {
76         kc = va_arg(ap, int) + EVDEV_OFFSET;
77         op = va_arg(ap, int);
78
79         nsyms = xkb_state_key_get_syms(state, kc, &syms);
80         fprintf(stderr, "got %d syms for key 0x%x: [", nsyms, kc);
81
82         if (op == DOWN || op == BOTH)
83             xkb_state_update_key(state, kc, XKB_KEY_DOWN);
84         if (op == UP || op == BOTH)
85             xkb_state_update_key(state, kc, XKB_KEY_UP);
86
87         for (i = 0; i < nsyms; i++) {
88             keysym = va_arg(ap, int);
89             xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
90             fprintf(stderr, "%s%s", (i != 0) ? ", " : "", ksbuf);
91
92             if (keysym == FINISH || keysym == NEXT) {
93                 xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
94                 fprintf(stderr, "Did not expect keysym: %s.\n", ksbuf);
95                 goto fail;
96             }
97
98             if (keysym != syms[i]) {
99                 xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
100                 fprintf(stderr, "Expected keysym: %s. ", ksbuf);;
101                 xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
102                 fprintf(stderr, "Got keysym: %s.\n", ksbuf);;
103                 goto fail;
104             }
105         }
106
107         if (nsyms == 0) {
108             keysym = va_arg(ap, int);
109             if (keysym != XKB_KEY_NoSymbol) {
110                 xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
111                 fprintf(stderr, "Expected %s, but got no keysyms.\n", ksbuf);
112                 goto fail;
113             }
114         }
115
116         fprintf(stderr, "]\n");
117
118         keysym = va_arg(ap, int);
119         if (keysym == NEXT)
120             continue;
121         if (keysym == FINISH)
122             break;
123
124         xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
125         fprintf(stderr, "Expected keysym: %s. Didn't get it.\n", ksbuf);
126         goto fail;
127     }
128
129     xkb_state_unref(state);
130     return 1;
131
132 fail:
133     xkb_state_unref(state);
134     return 0;
135 }
136
137 int
138 test_key_seq(struct xkb_keymap *keymap, ...)
139 {
140     va_list ap;
141     int ret;
142
143     va_start(ap, keymap);
144     ret = test_key_seq_va(keymap, ap);
145     va_end(ap);
146
147     return ret;
148 }
149
150 char *
151 test_get_path(const char *path_rel)
152 {
153     char *path;
154     size_t path_len;
155     const char *srcdir = getenv("srcdir");
156
157     path_len = strlen(srcdir ? srcdir : ".") +
158                strlen(path_rel ? path_rel : "") + 12;
159     path = malloc(path_len);
160     if (!path) {
161         fprintf(stderr, "Failed to allocate path (%d chars) for %s\n",
162                 (int) path_len, path);
163         return NULL;
164     }
165     snprintf(path, path_len,
166              "%s/test/data/%s", srcdir ? srcdir : ".",
167              path_rel ? path_rel : "");
168
169     return path;
170 }
171
172 char *
173 test_read_file(const char *path_rel)
174 {
175     struct stat info;
176     char *ret, *tmp, *path;
177     int fd, count, remaining;
178
179     path = test_get_path(path_rel);
180     if (!path)
181         return NULL;
182
183     fd = open(path, O_RDONLY);
184     free(path);
185     if (fd < 0)
186         return NULL;
187
188     if (fstat(fd, &info) != 0) {
189         close(fd);
190         return NULL;
191     }
192
193     ret = malloc(info.st_size + 1);
194     if (!ret) {
195         close(fd);
196         return NULL;
197     }
198
199     remaining = info.st_size;
200     tmp = ret;
201     while ((count = read(fd, tmp, remaining))) {
202         remaining -= count;
203         tmp += count;
204     }
205     ret[info.st_size] = '\0';
206     close(fd);
207
208     if (remaining != 0) {
209         free(ret);
210         return NULL;
211     }
212
213     return ret;
214 }
215
216 struct xkb_context *
217 test_get_context(enum test_context_flags test_flags)
218 {
219     enum xkb_context_flags ctx_flags;
220     struct xkb_context *ctx;
221     char *path;
222
223     ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES;
224     if (test_flags & CONTEXT_ALLOW_ENVIRONMENT_NAMES) {
225         unsetenv("XKB_DEFAULT_RULES");
226         unsetenv("XKB_DEFAULT_MODEL");
227         unsetenv("XKB_DEFAULT_LAYOUT");
228         unsetenv("XKB_DEFAULT_VARIANT");
229         unsetenv("XKB_DEFAULT_OPTIONS");
230     }
231     else {
232         ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES;
233     }
234
235     ctx = xkb_context_new(ctx_flags);
236     if (!ctx)
237         return NULL;
238
239     path = test_get_path("");
240     if (!path)
241         return NULL;
242
243     xkb_context_include_path_append(ctx, path);
244     free(path);
245
246     return ctx;
247 }
248
249 struct xkb_keymap *
250 test_compile_file(struct xkb_context *context, const char *path_rel)
251 {
252     struct xkb_keymap *keymap;
253     FILE *file;
254     char *path;
255
256     path = test_get_path(path_rel);
257     if (!path)
258         return NULL;
259
260     file = fopen(path, "r");
261     if (!file) {
262         fprintf(stderr, "Failed to open path: %s\n", path);
263         free(path);
264         return NULL;
265     }
266     assert(file != NULL);
267
268     keymap = xkb_keymap_new_from_file(context, file,
269                                       XKB_KEYMAP_FORMAT_TEXT_V1, 0);
270     fclose(file);
271
272     if (!keymap) {
273         fprintf(stderr, "Failed to compile path: %s\n", path);
274         free(path);
275         return NULL;
276     }
277
278     fprintf(stderr, "Successfully compiled path: %s\n", path);
279     free(path);
280
281     return keymap;
282 }
283
284 struct xkb_keymap *
285 test_compile_string(struct xkb_context *context, const char *string)
286 {
287     struct xkb_keymap *keymap;
288
289     keymap = xkb_keymap_new_from_string(context, string,
290                                         XKB_KEYMAP_FORMAT_TEXT_V1, 0);
291     if (!keymap) {
292         fprintf(stderr, "Failed to compile string\n");
293         return NULL;
294     }
295
296     return keymap;
297 }
298
299 struct xkb_keymap *
300 test_compile_buffer(struct xkb_context *context, const char *buf, size_t len)
301 {
302     struct xkb_keymap *keymap;
303
304     keymap = xkb_keymap_new_from_buffer(context, buf, len,
305                                         XKB_KEYMAP_FORMAT_TEXT_V1, 0);
306     if (!keymap) {
307         fprintf(stderr, "Failed to compile keymap from memory buffer\n");
308         return NULL;
309     }
310
311     return keymap;
312 }
313
314 struct xkb_keymap *
315 test_compile_rules(struct xkb_context *context, const char *rules,
316                    const char *model, const char *layout,
317                    const char *variant, const char *options)
318 {
319     struct xkb_keymap *keymap;
320     struct xkb_rule_names rmlvo = {
321         .rules = isempty(rules) ? NULL : rules,
322         .model = isempty(model) ? NULL : model,
323         .layout = isempty(layout) ? NULL : layout,
324         .variant = isempty(variant) ? NULL : variant,
325         .options = isempty(options) ? NULL : options
326     };
327
328     if (!rules && !model && !layout && !variant && !options)
329         keymap = xkb_keymap_new_from_names(context, NULL, 0);
330     else
331         keymap = xkb_keymap_new_from_names(context, &rmlvo, 0);
332
333     if (!keymap) {
334         fprintf(stderr,
335                 "Failed to compile RMLVO: '%s', '%s', '%s', '%s', '%s'\n",
336                 rules, model, layout, variant, options);
337         return NULL;
338     }
339
340     return keymap;
341 }