keymap: add xkb_keymap_new_from_buffer()
[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         fprintf(stderr, "]\n");
108
109         keysym = va_arg(ap, int);
110         if (keysym == NEXT)
111             continue;
112         if (keysym == FINISH)
113             break;
114
115         xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf));
116         fprintf(stderr, "Expected keysym: %s. Didn't get it.\n", ksbuf);
117         goto fail;
118     }
119
120     xkb_state_unref(state);
121     return 1;
122
123 fail:
124     xkb_state_unref(state);
125     return 0;
126 }
127
128 int
129 test_key_seq(struct xkb_keymap *keymap, ...)
130 {
131     va_list ap;
132     int ret;
133
134     va_start(ap, keymap);
135     ret = test_key_seq_va(keymap, ap);
136     va_end(ap);
137
138     return ret;
139 }
140
141 const char *
142 test_get_path(const char *path_rel)
143 {
144     static char path[PATH_MAX];
145     const char *srcdir = getenv("srcdir");
146
147     snprintf(path, PATH_MAX - 1,
148              "%s/test/data/%s", srcdir ? srcdir : ".",
149              path_rel ? path_rel : "");
150
151     return path;
152 }
153
154 char *
155 test_read_file(const char *path_rel)
156 {
157     struct stat info;
158     char *ret, *tmp;
159     int fd, count, remaining;
160
161     fd = open(test_get_path(path_rel), O_RDONLY);
162     if (fd < 0)
163         return NULL;
164
165     if (fstat(fd, &info) != 0) {
166         close(fd);
167         return NULL;
168     }
169
170     ret = malloc(info.st_size + 1);
171     if (!ret) {
172         close(fd);
173         return NULL;
174     }
175
176     remaining = info.st_size;
177     tmp = ret;
178     while ((count = read(fd, tmp, remaining))) {
179         remaining -= count;
180         tmp += count;
181     }
182     ret[info.st_size] = '\0';
183     close(fd);
184
185     if (remaining != 0) {
186         free(ret);
187         return NULL;
188     }
189
190     return ret;
191 }
192
193 struct xkb_context *
194 test_get_context(enum test_context_flags test_flags)
195 {
196     enum xkb_context_flags ctx_flags;
197     struct xkb_context *ctx;
198
199     ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES;
200     if (test_flags & CONTEXT_ALLOW_ENVIRONMENT_NAMES) {
201         unsetenv("XKB_DEFAULT_RULES");
202         unsetenv("XKB_DEFAULT_MODEL");
203         unsetenv("XKB_DEFAULT_LAYOUT");
204         unsetenv("XKB_DEFAULT_VARIANT");
205         unsetenv("XKB_DEFAULT_OPTIONS");
206     }
207     else {
208         ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES;
209     }
210
211     ctx = xkb_context_new(ctx_flags);
212     if (!ctx)
213         return NULL;
214
215     xkb_context_include_path_append(ctx, test_get_path(""));
216
217     return ctx;
218 }
219
220 struct xkb_keymap *
221 test_compile_file(struct xkb_context *context, const char *path_rel)
222 {
223     struct xkb_keymap *keymap;
224     FILE *file;
225     const char *path = test_get_path(path_rel);
226
227     file = fopen(path, "r");
228     if (!file) {
229         fprintf(stderr, "Failed to open path: %s\n", path);
230         return NULL;
231     }
232     assert(file != NULL);
233
234     keymap = xkb_keymap_new_from_file(context, file,
235                                       XKB_KEYMAP_FORMAT_TEXT_V1, 0);
236     fclose(file);
237
238     if (!keymap) {
239         fprintf(stderr, "Failed to compile path: %s\n", path);
240         return NULL;
241     }
242
243     fprintf(stderr, "Successfully compiled path: %s\n", path);
244
245     return keymap;
246 }
247
248 struct xkb_keymap *
249 test_compile_string(struct xkb_context *context, const char *string)
250 {
251     struct xkb_keymap *keymap;
252
253     keymap = xkb_keymap_new_from_string(context, string,
254                                         XKB_KEYMAP_FORMAT_TEXT_V1, 0);
255     if (!keymap) {
256         fprintf(stderr, "Failed to compile string\n");
257         return NULL;
258     }
259
260     return keymap;
261 }
262
263 struct xkb_keymap *
264 test_compile_buffer(struct xkb_context *context, const char *buf, size_t len)
265 {
266     struct xkb_keymap *keymap;
267
268     keymap = xkb_keymap_new_from_buffer(context, buf, len,
269                                         XKB_KEYMAP_FORMAT_TEXT_V1, 0);
270     if (!keymap) {
271         fprintf(stderr, "Failed to compile keymap from memory buffer\n");
272         return NULL;
273     }
274
275     return keymap;
276 }
277
278 struct xkb_keymap *
279 test_compile_rules(struct xkb_context *context, const char *rules,
280                    const char *model, const char *layout,
281                    const char *variant, const char *options)
282 {
283     struct xkb_keymap *keymap;
284     struct xkb_rule_names rmlvo = {
285         .rules = isempty(rules) ? NULL : rules,
286         .model = isempty(model) ? NULL : model,
287         .layout = isempty(layout) ? NULL : layout,
288         .variant = isempty(variant) ? NULL : variant,
289         .options = isempty(options) ? NULL : options
290     };
291
292     if (!rules && !model && !layout && !variant && !options)
293         keymap = xkb_keymap_new_from_names(context, NULL, 0);
294     else
295         keymap = xkb_keymap_new_from_names(context, &rmlvo, 0);
296
297     if (!keymap) {
298         fprintf(stderr,
299                 "Failed to compile RMLVO: '%s', '%s', '%s', '%s', '%s'\n",
300                 rules, model, layout, variant, options);
301         return NULL;
302     }
303
304     return keymap;
305 }