test: add test for the various default include paths
[platform/upstream/libxkbcommon.git] / test / context.c
1 /*
2  * Copyright © 2012 Intel Corporation
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  * Author: Daniel Stone <daniel@fooishbar.org>
24  */
25
26 #include "test.h"
27 #include "context.h"
28
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <dirent.h>
32
33 /* keeps a cache of all makedir/maketmpdir directories so we can free and
34  * rmdir them in one go, see unmakedirs() */
35 char *dirnames[64];
36 int ndirs;
37
38 /* keeps a cache of all buffered env vars so we can restore
39  * them in one go, see restore_env() */
40 struct env {
41     char *key;
42     char *value;
43 } environment[64];
44 int nenviron;
45
46 static void buffer_env(const char *key)
47 {
48     char *v = getenv(key);
49
50     environment[nenviron].key = strdup(key);
51     environment[nenviron].value = v ? strdup(v) : NULL;
52     nenviron++;
53 }
54
55 static void restore_env(void)
56 {
57     for (int i = 0; i < nenviron; i++) {
58         char *key = environment[i].key,
59              *value = environment[i].value;
60
61         if (value)
62             setenv(key, value, 1);
63         else
64             unsetenv(key);
65
66         free(key);
67         free(value);
68     }
69     nenviron = 0;
70     memset(environment, 0, sizeof(environment));
71 }
72
73 static const char *makedir(const char *parent, const char *path)
74 {
75     char *dirname;
76     int err;
77
78     err = asprintf(&dirname, "%s/%s", parent, path);
79     assert(err >= 0);
80     err = mkdir(dirname, 0777);
81     assert(err == 0);
82
83     dirnames[ndirs++] = dirname;
84
85     return dirname;
86 }
87
88 static const char *maketmpdir(void)
89 {
90     const char *template = "/tmp/xkbcommon-test.XXXXXX";
91     char *tmpdir = strdup(template);
92
93     tmpdir = mkdtemp(tmpdir);
94     assert(tmpdir != NULL);
95
96     dirnames[ndirs++] = tmpdir;
97
98     return tmpdir;
99 }
100
101 static void unmakedirs(void)
102 {
103     /* backwards order for rmdir to work */
104     for (int i = ndirs - 1; i >= 0; i--) {
105         char *dir = dirnames[i];
106         if (!dir)
107             break;
108         rmdir(dir);
109         free(dir);
110     }
111     ndirs = 0;
112     memset(dirnames, 0, sizeof(dirnames));
113 }
114
115 static void
116 test_config_root_include_path(void)
117 {
118     struct xkb_context *ctx;
119     const char *tmpdir;
120     const char *context_path;
121     int nincludes;
122
123     buffer_env("XKB_CONFIG_ROOT");
124     buffer_env("HOME");
125     buffer_env("XDG_CONFIG_HOME");
126
127     tmpdir = maketmpdir();
128     setenv("XKB_CONFIG_ROOT", tmpdir, 1);
129     unsetenv("HOME");
130     unsetenv("XDG_CONFIG_HOME");
131
132     /* built-in path is last */
133     ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
134     nincludes = xkb_context_num_include_paths(ctx);
135     assert(nincludes >= 1);
136     context_path = xkb_context_include_path_get(ctx, nincludes - 1);
137     assert(strcmp(context_path, tmpdir) == 0);
138     xkb_context_unref(ctx);
139
140     unmakedirs();
141     restore_env();
142 }
143
144 static void
145 test_config_root_include_path_fallback(void)
146 {
147     struct xkb_context *ctx;
148     const char *xkbdir = DFLT_XKB_CONFIG_ROOT;
149     const char *context_path;
150     int nincludes;
151     DIR *dir;
152
153     /* quick and dirty check that the default directory exists.
154      * It may not on a vanilla test box if we just run the test
155      * suite, so where it's not there just skip this test. */
156     dir = opendir(xkbdir);
157     if (!dir)
158         return;
159     closedir(dir);
160
161     buffer_env("XKB_CONFIG_ROOT");
162     buffer_env("HOME");
163     buffer_env("XDG_CONFIG_HOME");
164
165     unsetenv("XKB_CONFIG_ROOT");
166     unsetenv("HOME");
167     unsetenv("XDG_CONFIG_HOME");
168
169     /* built-in path is last */
170     ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
171     nincludes = xkb_context_num_include_paths(ctx);
172     assert(nincludes >= 1);
173     context_path = xkb_context_include_path_get(ctx, nincludes - 1);
174     assert(strcmp(context_path, xkbdir) == 0);
175     xkb_context_unref(ctx);
176
177     unmakedirs();
178     restore_env();
179 }
180
181 static void
182 test_xkbdir_include_path(void)
183 {
184     struct xkb_context *ctx;
185     const char *tmpdir;
186     const char *xkb_path;
187     const char *context_path;
188
189     buffer_env("HOME");
190     buffer_env("XDG_CONFIG_HOME");
191
192     tmpdir = maketmpdir();
193     xkb_path = makedir(tmpdir, ".xkb");
194     setenv("HOME", tmpdir, 1);
195     setenv("XDG_CONFIG_HOME", tmpdir, 1);
196
197     /* No XDG directory in our tmpdir, so we expect
198      * the $HOME/.xkb to be the first include path */
199     ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
200     assert(xkb_context_num_include_paths(ctx) >= 1);
201     context_path = xkb_context_include_path_get(ctx, 0);
202     assert(strcmp(context_path, xkb_path) == 0);
203     xkb_context_unref(ctx);
204
205     unmakedirs();
206     restore_env();
207 }
208
209 static void
210 test_xdg_include_path(void)
211 {
212     struct xkb_context *ctx;
213     const char *tmpdir;
214     const char *xdg_path;
215     const char *context_path;
216
217     buffer_env("XDG_CONFIG_HOME");
218
219     tmpdir = maketmpdir();
220     xdg_path = makedir(tmpdir, "xkb");
221     setenv("XDG_CONFIG_HOME", tmpdir, 1);
222
223     /* XDG path is always first */
224     ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
225     assert(xkb_context_num_include_paths(ctx) >= 1);
226     context_path = xkb_context_include_path_get(ctx, 0);
227     assert(strcmp(context_path, xdg_path) == 0);
228     xkb_context_unref(ctx);
229
230     unmakedirs();
231     restore_env();
232 }
233
234 static void
235 test_xdg_include_path_fallback(void)
236 {
237     struct xkb_context *ctx;
238     const char *tmpdir;
239     const char *xdg_root, *xdg_path;
240     const char *context_path;
241
242     buffer_env("XDG_CONFIG_HOME");
243     buffer_env("HOME");
244
245     tmpdir = maketmpdir();
246     xdg_root = makedir(tmpdir, ".config");
247     xdg_path = makedir(xdg_root, "xkb");
248     setenv("HOME", tmpdir, 1);
249     unsetenv("XDG_CONFIG_HOME");
250
251     /* XDG path is always first, even if fallback */
252     ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
253     assert(xkb_context_num_include_paths(ctx) >= 1);
254     context_path = xkb_context_include_path_get(ctx, 0);
255     assert(strcmp(context_path, xdg_path) == 0);
256     xkb_context_unref(ctx);
257
258     unmakedirs();
259     restore_env();
260 }
261
262 static void
263 test_include_order(void)
264 {
265     struct xkb_context *ctx;
266     const char *tmpdir;
267     const char *xdg_path;
268     const char *xkb_home_path;
269     const char *xkb_root_path;
270     const char *context_path;
271
272     buffer_env("XKB_CONFIG_ROOT");
273     buffer_env("XDG_CONFIG_HOME");
274     buffer_env("HOME");
275
276     tmpdir = maketmpdir();
277     xdg_path = makedir(tmpdir, "xkb");
278     xkb_home_path = makedir(tmpdir, ".xkb");
279     xkb_root_path = makedir(tmpdir, "xkbroot");
280     setenv("HOME", tmpdir, 1);
281     setenv("XDG_CONFIG_HOME", tmpdir, 1);
282     setenv("XKB_CONFIG_ROOT", xkb_root_path, 1);
283
284     ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
285     assert(xkb_context_num_include_paths(ctx) >= 3);
286     /* XDG is first */
287     context_path = xkb_context_include_path_get(ctx, 0);
288     assert(strcmp(context_path, xdg_path) == 0);
289     /* $HOME/.xkb is second */
290     context_path = xkb_context_include_path_get(ctx, 1);
291     assert(strcmp(context_path, xkb_home_path) == 0);
292     /* CONFIG_ROOT is last */
293     context_path = xkb_context_include_path_get(ctx, 2);
294     assert(strcmp(context_path, xkb_root_path) == 0);
295
296     xkb_context_unref(ctx);
297
298     unmakedirs();
299     restore_env();
300 }
301
302 int
303 main(void)
304 {
305     struct xkb_context *context = test_get_context(0);
306     xkb_atom_t atom;
307
308     assert(context);
309
310     assert(xkb_context_num_include_paths(context) == 1);
311     assert(!xkb_context_include_path_append(context, "¡NONSENSE!"));
312     assert(xkb_context_num_include_paths(context) == 1);
313
314     atom = xkb_atom_intern(context, "HELLOjunkjunkjunk", 5);
315     assert(atom != XKB_ATOM_NONE);
316     assert(streq(xkb_atom_text(context, atom), "HELLO"));
317
318     atom = xkb_atom_intern_literal(context, "HELLOjunkjunkjunk");
319     assert(atom != XKB_ATOM_NONE);
320     assert(streq(xkb_atom_text(context, atom), "HELLOjunkjunkjunk"));
321
322     xkb_context_unref(context);
323
324     test_config_root_include_path();
325     test_config_root_include_path_fallback();
326     test_xkbdir_include_path();
327     test_xdg_include_path();
328     test_xdg_include_path_fallback();
329     test_include_order();
330
331     return 0;
332 }