scripts: update makeheader script for the _EVDEVK keysym defines
[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 "config.h"
34
35 #include <limits.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #ifdef _MSC_VER
40 #include <io.h>
41 #include <windows.h>
42 #else
43 #include <unistd.h>
44 #include <termios.h>
45 #endif
46
47 #include "test.h"
48 #include "utils.h"
49
50 /*
51  * Test a sequence of keysyms, resulting from a sequence of key presses,
52  * against the keysyms they're supposed to generate.
53  *
54  * - Each test runs with a clean state.
55  * - Each line in the test is made up of:
56  *   + A keycode, given as a KEY_* from linux/input.h.
57  *   + A direction - DOWN for press, UP for release, BOTH for
58  *     immediate press + release, REPEAT to just get the syms.
59  *   + A sequence of keysyms that should result from this keypress.
60  *
61  * The vararg format is:
62  * <KEY_*>  <DOWN | UP | BOTH>  <XKB_KEY_* (zero or more)>  <NEXT | FINISH>
63  *
64  * See below for examples.
65  */
66 int
67 test_key_seq_va(struct xkb_keymap *keymap, va_list ap)
68 {
69     struct xkb_state *state;
70
71     xkb_keycode_t kc;
72     int op;
73     xkb_keysym_t keysym;
74
75     const xkb_keysym_t *syms;
76     xkb_keysym_t sym;
77     unsigned int nsyms, i;
78     char ksbuf[64];
79
80     fprintf(stderr, "----\n");
81
82     state = xkb_state_new(keymap);
83     assert(state);
84
85     for (;;) {
86         kc = va_arg(ap, int) + EVDEV_OFFSET;
87         op = va_arg(ap, int);
88
89         nsyms = xkb_state_key_get_syms(state, kc, &syms);
90         if (nsyms == 1) {
91             sym = xkb_state_key_get_one_sym(state, kc);
92             syms = &sym;
93         }
94
95         fprintf(stderr, "got %u syms for keycode %u: [", nsyms, kc);
96
97         if (op == DOWN || op == BOTH)
98             xkb_state_update_key(state, kc, XKB_KEY_DOWN);
99         if (op == UP || op == BOTH)
100             xkb_state_update_key(state, kc, XKB_KEY_UP);
101
102         for (i = 0; i < nsyms; i++) {
103             keysym = va_arg(ap, int);
104             xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
105             fprintf(stderr, "%s%s", (i != 0) ? ", " : "", ksbuf);
106
107             if (keysym == FINISH || keysym == NEXT) {
108                 xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
109                 fprintf(stderr, "Did not expect keysym: %s.\n", ksbuf);
110                 goto fail;
111             }
112
113             if (keysym != syms[i]) {
114                 xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
115                 fprintf(stderr, "Expected keysym: %s. ", ksbuf);;
116                 xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf));
117                 fprintf(stderr, "Got keysym: %s.\n", ksbuf);;
118                 goto fail;
119             }
120         }
121
122         if (nsyms == 0) {
123             keysym = va_arg(ap, int);
124             if (keysym != XKB_KEY_NoSymbol) {
125                 xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
126                 fprintf(stderr, "Expected %s, but got no keysyms.\n", ksbuf);
127                 goto fail;
128             }
129         }
130
131         fprintf(stderr, "]\n");
132
133         keysym = va_arg(ap, int);
134         if (keysym == NEXT)
135             continue;
136         if (keysym == FINISH)
137             break;
138
139         xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
140         fprintf(stderr, "Expected keysym: %s. Didn't get it.\n", ksbuf);
141         goto fail;
142     }
143
144     xkb_state_unref(state);
145     return 1;
146
147 fail:
148     xkb_state_unref(state);
149     return 0;
150 }
151
152 int
153 test_key_seq(struct xkb_keymap *keymap, ...)
154 {
155     va_list ap;
156     int ret;
157
158     va_start(ap, keymap);
159     ret = test_key_seq_va(keymap, ap);
160     va_end(ap);
161
162     return ret;
163 }
164
165 char *
166 test_get_path(const char *path_rel)
167 {
168     char *path;
169     const char *srcdir;
170
171     srcdir = getenv("top_srcdir");
172     if (!srcdir)
173         srcdir = ".";
174
175     if (path_rel[0] == '/')
176         return strdup(path_rel);
177
178     path = asprintf_safe("%s/test/data%s%s", srcdir,
179                          path_rel[0] ? "/" : "", path_rel);
180     if (!path) {
181         fprintf(stderr, "Failed to allocate path for %s\n", path_rel);
182         return NULL;
183     }
184     return path;
185 }
186
187 char *
188 test_read_file(const char *path_rel)
189 {
190     struct stat info;
191     char *ret, *tmp, *path;
192     int fd, count, remaining;
193
194     path = test_get_path(path_rel);
195     if (!path)
196         return NULL;
197
198     fd = open(path, O_RDONLY);
199     free(path);
200     if (fd < 0)
201         return NULL;
202
203     if (fstat(fd, &info) != 0) {
204         close(fd);
205         return NULL;
206     }
207
208     ret = malloc(info.st_size + 1);
209     if (!ret) {
210         close(fd);
211         return NULL;
212     }
213
214     remaining = info.st_size;
215     tmp = ret;
216     while ((count = read(fd, tmp, remaining))) {
217         remaining -= count;
218         tmp += count;
219     }
220     ret[info.st_size] = '\0';
221     close(fd);
222
223     if (remaining != 0) {
224         free(ret);
225         return NULL;
226     }
227
228     return ret;
229 }
230
231 struct xkb_context *
232 test_get_context(enum test_context_flags test_flags)
233 {
234     enum xkb_context_flags ctx_flags;
235     struct xkb_context *ctx;
236     char *path;
237
238     ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES;
239     if (test_flags & CONTEXT_ALLOW_ENVIRONMENT_NAMES) {
240         unsetenv("XKB_DEFAULT_RULES");
241         unsetenv("XKB_DEFAULT_MODEL");
242         unsetenv("XKB_DEFAULT_LAYOUT");
243         unsetenv("XKB_DEFAULT_VARIANT");
244         unsetenv("XKB_DEFAULT_OPTIONS");
245     }
246     else {
247         ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES;
248     }
249
250     ctx = xkb_context_new(ctx_flags);
251     if (!ctx)
252         return NULL;
253
254     path = test_get_path("");
255     if (!path) {
256         xkb_context_unref(ctx);
257         return NULL;
258     }
259
260     xkb_context_include_path_append(ctx, path);
261     free(path);
262
263     return ctx;
264 }
265
266 struct xkb_keymap *
267 test_compile_file(struct xkb_context *context, const char *path_rel)
268 {
269     struct xkb_keymap *keymap;
270     FILE *file;
271     char *path;
272
273     path = test_get_path(path_rel);
274     if (!path)
275         return NULL;
276
277     file = fopen(path, "rb");
278     if (!file) {
279         fprintf(stderr, "Failed to open path: %s\n", path);
280         free(path);
281         return NULL;
282     }
283     assert(file != NULL);
284
285     keymap = xkb_keymap_new_from_file(context, file,
286                                       XKB_KEYMAP_FORMAT_TEXT_V1, 0);
287     fclose(file);
288
289     if (!keymap) {
290         fprintf(stderr, "Failed to compile path: %s\n", path);
291         free(path);
292         return NULL;
293     }
294
295     fprintf(stderr, "Successfully compiled path: %s\n", path);
296     free(path);
297
298     return keymap;
299 }
300
301 struct xkb_keymap *
302 test_compile_string(struct xkb_context *context, const char *string)
303 {
304     struct xkb_keymap *keymap;
305
306     keymap = xkb_keymap_new_from_string(context, string,
307                                         XKB_KEYMAP_FORMAT_TEXT_V1, 0);
308     if (!keymap) {
309         fprintf(stderr, "Failed to compile string\n");
310         return NULL;
311     }
312
313     return keymap;
314 }
315
316 struct xkb_keymap *
317 test_compile_buffer(struct xkb_context *context, const char *buf, size_t len)
318 {
319     struct xkb_keymap *keymap;
320
321     keymap = xkb_keymap_new_from_buffer(context, buf, len,
322                                         XKB_KEYMAP_FORMAT_TEXT_V1, 0);
323     if (!keymap) {
324         fprintf(stderr, "Failed to compile keymap from memory buffer\n");
325         return NULL;
326     }
327
328     return keymap;
329 }
330
331 struct xkb_keymap *
332 test_compile_rules(struct xkb_context *context, const char *rules,
333                    const char *model, const char *layout,
334                    const char *variant, const char *options)
335 {
336     struct xkb_keymap *keymap;
337     struct xkb_rule_names rmlvo = {
338         .rules = isempty(rules) ? NULL : rules,
339         .model = isempty(model) ? NULL : model,
340         .layout = isempty(layout) ? NULL : layout,
341         .variant = isempty(variant) ? NULL : variant,
342         .options = isempty(options) ? NULL : options
343     };
344
345     if (!rules && !model && !layout && !variant && !options)
346         keymap = xkb_keymap_new_from_names(context, NULL, 0);
347     else
348         keymap = xkb_keymap_new_from_names(context, &rmlvo, 0);
349
350     if (!keymap) {
351         fprintf(stderr,
352                 "Failed to compile RMLVO: '%s', '%s', '%s', '%s', '%s'\n",
353                 rules, model, layout, variant, options);
354         return NULL;
355     }
356
357     return keymap;
358 }