2 * Copyright © 2012 Intel Corporation
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:
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
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.
23 * Author: Daniel Stone <daniel@fooishbar.org>
32 #include <sys/types.h>
35 /* keeps a cache of all makedir/maketmpdir directories so we can free and
36 * rmdir them in one go, see unmakedirs() */
40 /* keeps a cache of all buffered env vars so we can restore
41 * them in one go, see restore_env() */
48 static void buffer_env(const char *key)
50 char *v = getenv(key);
52 environment[nenviron].key = strdup(key);
53 environment[nenviron].value = v ? strdup(v) : NULL;
57 static void restore_env(void)
59 for (int i = 0; i < nenviron; i++) {
60 char *key = environment[i].key,
61 *value = environment[i].value;
64 setenv(key, value, 1);
72 memset(environment, 0, sizeof(environment));
75 static const char *makedir(const char *parent, const char *path)
80 err = asprintf(&dirname, "%s/%s", parent, path);
82 err = mkdir(dirname, 0777);
85 dirnames[ndirs++] = dirname;
90 static const char *maketmpdir(void)
92 const char *template = "/tmp/xkbcommon-test.XXXXXX";
93 char *tmpdir = strdup(template);
95 tmpdir = mkdtemp(tmpdir);
96 assert(tmpdir != NULL);
98 dirnames[ndirs++] = tmpdir;
103 static void unmakedirs(void)
105 /* backwards order for rmdir to work */
106 for (int i = ndirs - 1; i >= 0; i--) {
107 char *dir = dirnames[i];
114 memset(dirnames, 0, sizeof(dirnames));
118 test_config_root_include_path(void)
120 struct xkb_context *ctx;
122 const char *context_path;
125 buffer_env("XKB_CONFIG_ROOT");
127 buffer_env("XDG_CONFIG_HOME");
129 tmpdir = maketmpdir();
130 setenv("XKB_CONFIG_ROOT", tmpdir, 1);
132 unsetenv("XDG_CONFIG_HOME");
134 /* built-in path is last */
135 ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
136 nincludes = xkb_context_num_include_paths(ctx);
137 assert(nincludes >= 1);
138 context_path = xkb_context_include_path_get(ctx, nincludes - 1);
139 assert(strcmp(context_path, tmpdir) == 0);
140 xkb_context_unref(ctx);
147 test_config_root_include_path_fallback(void)
149 struct xkb_context *ctx;
150 const char *xkbdir = DFLT_XKB_CONFIG_ROOT;
151 const char *context_path;
154 /* quick and dirty check that the default directory exists.
155 * It may not on a vanilla test box if we just run the test
156 * suite, so where it's not there just skip this test. */
157 struct stat stat_buf;
158 int err = stat(xkbdir, &stat_buf);
161 if (!S_ISDIR(stat_buf.st_mode))
164 buffer_env("XKB_CONFIG_ROOT");
166 buffer_env("XDG_CONFIG_HOME");
168 unsetenv("XKB_CONFIG_ROOT");
170 unsetenv("XDG_CONFIG_HOME");
172 /* built-in path is last */
173 ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
174 nincludes = xkb_context_num_include_paths(ctx);
175 assert(nincludes >= 1);
176 context_path = xkb_context_include_path_get(ctx, nincludes - 1);
177 assert(strcmp(context_path, xkbdir) == 0);
178 xkb_context_unref(ctx);
185 test_xkbdir_include_path(void)
187 struct xkb_context *ctx;
189 const char *xkb_path;
190 const char *context_path;
193 buffer_env("XDG_CONFIG_HOME");
195 tmpdir = maketmpdir();
196 xkb_path = makedir(tmpdir, ".xkb");
197 setenv("HOME", tmpdir, 1);
198 setenv("XDG_CONFIG_HOME", tmpdir, 1);
200 /* No XDG directory in our tmpdir, so we expect
201 * the $HOME/.xkb to be the first include path */
202 ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
203 assert(xkb_context_num_include_paths(ctx) >= 1);
204 context_path = xkb_context_include_path_get(ctx, 0);
205 assert(strcmp(context_path, xkb_path) == 0);
206 xkb_context_unref(ctx);
213 test_xdg_include_path(void)
215 struct xkb_context *ctx;
217 const char *xdg_path;
218 const char *context_path;
220 buffer_env("XDG_CONFIG_HOME");
222 tmpdir = maketmpdir();
223 xdg_path = makedir(tmpdir, "xkb");
224 setenv("XDG_CONFIG_HOME", tmpdir, 1);
226 /* XDG path is always first */
227 ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
228 assert(xkb_context_num_include_paths(ctx) >= 1);
229 context_path = xkb_context_include_path_get(ctx, 0);
230 assert(strcmp(context_path, xdg_path) == 0);
231 xkb_context_unref(ctx);
238 test_xdg_include_path_fallback(void)
240 struct xkb_context *ctx;
242 const char *xdg_root, *xdg_path;
243 const char *context_path;
245 buffer_env("XDG_CONFIG_HOME");
248 tmpdir = maketmpdir();
249 xdg_root = makedir(tmpdir, ".config");
250 xdg_path = makedir(xdg_root, "xkb");
251 setenv("HOME", tmpdir, 1);
252 unsetenv("XDG_CONFIG_HOME");
254 /* XDG path is always first, even if fallback */
255 ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
256 assert(xkb_context_num_include_paths(ctx) >= 1);
257 context_path = xkb_context_include_path_get(ctx, 0);
258 assert(strcmp(context_path, xdg_path) == 0);
259 xkb_context_unref(ctx);
266 test_include_order(void)
268 struct xkb_context *ctx;
270 const char *xdg_path;
271 const char *xkb_home_path;
272 const char *xkb_root_path;
273 const char *context_path;
275 buffer_env("XKB_CONFIG_ROOT");
276 buffer_env("XDG_CONFIG_HOME");
279 tmpdir = maketmpdir();
280 xdg_path = makedir(tmpdir, "xkb");
281 xkb_home_path = makedir(tmpdir, ".xkb");
282 xkb_root_path = makedir(tmpdir, "xkbroot");
283 setenv("HOME", tmpdir, 1);
284 setenv("XDG_CONFIG_HOME", tmpdir, 1);
285 setenv("XKB_CONFIG_ROOT", xkb_root_path, 1);
287 ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
288 assert(xkb_context_num_include_paths(ctx) >= 3);
290 context_path = xkb_context_include_path_get(ctx, 0);
291 assert(strcmp(context_path, xdg_path) == 0);
292 /* $HOME/.xkb is second */
293 context_path = xkb_context_include_path_get(ctx, 1);
294 assert(strcmp(context_path, xkb_home_path) == 0);
295 /* CONFIG_ROOT is last */
296 context_path = xkb_context_include_path_get(ctx, 2);
297 assert(strcmp(context_path, xkb_root_path) == 0);
299 xkb_context_unref(ctx);
308 struct xkb_context *context = test_get_context(0);
313 assert(xkb_context_num_include_paths(context) == 1);
314 assert(!xkb_context_include_path_append(context, "¡NONSENSE!"));
315 assert(xkb_context_num_include_paths(context) == 1);
317 atom = xkb_atom_intern(context, "HELLOjunkjunkjunk", 5);
318 assert(atom != XKB_ATOM_NONE);
319 assert(streq(xkb_atom_text(context, atom), "HELLO"));
321 atom = xkb_atom_intern_literal(context, "HELLOjunkjunkjunk");
322 assert(atom != XKB_ATOM_NONE);
323 assert(streq(xkb_atom_text(context, atom), "HELLOjunkjunkjunk"));
325 xkb_context_unref(context);
327 test_config_root_include_path();
328 test_config_root_include_path_fallback();
329 test_xkbdir_include_path();
330 test_xdg_include_path();
331 test_xdg_include_path_fallback();
332 test_include_order();