| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- /*
- * Copyright © 2012 Intel Corporation
- * SPDX-License-Identifier: MIT
- *
- * Author: Daniel Stone <daniel@fooishbar.org>
- */
- #include "config.h"
- #include "test-config.h"
- #include <stdlib.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include "test.h"
- #include "xkbcommon/xkbcommon.h"
- #include "context.h"
- /* keeps a cache of all makedir/maketmpdir directories so we can free and
- * rmdir them in one go, see unmakedirs() */
- static char *dirnames[64];
- static int ndirs;
- /* keeps a cache of all buffered env vars so we can restore
- * them in one go, see restore_env() */
- static struct env {
- char *key;
- char *value;
- } environment[64];
- static int nenviron;
- static void
- buffer_env(const char *key)
- {
- char *v = getenv(key);
- environment[nenviron].key = strdup(key);
- environment[nenviron].value = v ? strdup(v) : NULL;
- nenviron++;
- }
- static void
- restore_env(void)
- {
- for (int i = 0; i < nenviron; i++) {
- char *key = environment[i].key,
- *value = environment[i].value;
- if (value)
- setenv(key, value, 1);
- else
- unsetenv(key);
- free(key);
- free(value);
- }
- nenviron = 0;
- memset(environment, 0, sizeof(environment));
- }
- static const char *
- makedir(const char *parent, const char *path)
- {
- char *dirname = test_makedir(parent, path);
- dirnames[ndirs++] = dirname;
- return dirname;
- }
- static const char *maketmpdir(void)
- {
- char *tmpdir = test_maketempdir("xkbcommon-test.XXXXXX");
- dirnames[ndirs++] = tmpdir;
- return tmpdir;
- }
- static void
- unmakedirs(void)
- {
- /* backwards order for rmdir to work */
- for (int i = ndirs - 1; i >= 0; i--) {
- char *dir = dirnames[i];
- if (!dir)
- break;
- rmdir(dir);
- free(dir);
- }
- ndirs = 0;
- memset(dirnames, 0, sizeof(dirnames));
- }
- static void
- test_config_root_include_path(void)
- {
- struct xkb_context *ctx;
- const char *tmpdir;
- const char *context_path;
- buffer_env("XKB_CONFIG_ROOT");
- buffer_env("HOME");
- buffer_env("XDG_CONFIG_HOME");
- tmpdir = maketmpdir();
- setenv("XKB_CONFIG_ROOT", tmpdir, 1);
- unsetenv("HOME");
- unsetenv("XDG_CONFIG_HOME");
- /* Valid built-in path is last */
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- const unsigned int nincludes = xkb_context_num_include_paths(ctx);
- assert(nincludes >= 1);
- context_path = xkb_context_include_path_get(ctx, nincludes - 1);
- assert(strcmp(context_path, tmpdir) == 0);
- xkb_context_unref(ctx);
- unmakedirs();
- restore_env();
- }
- static void
- test_config_root_include_path_fallback(void)
- {
- struct xkb_context *ctx;
- const char *xkbdir = DFLT_XKB_CONFIG_ROOT;
- const char *context_path;
- /* quick and dirty check that the default directory exists.
- * It may not on a vanilla test box if we just run the test
- * suite, so where it's not there just skip this test. */
- struct stat stat_buf;
- int err = stat(xkbdir, &stat_buf);
- if (err != 0)
- return;
- if (!S_ISDIR(stat_buf.st_mode))
- return;
- buffer_env("XKB_CONFIG_ROOT");
- buffer_env("XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH");
- buffer_env("XKB_CONFIG_VERSIONED_EXTENSIONS_PATH");
- buffer_env("XKB_CONFIG_EXTRA_PATH");
- buffer_env("HOME");
- buffer_env("XDG_CONFIG_HOME");
- unsetenv("XKB_CONFIG_ROOT");
- unsetenv("HOME");
- unsetenv("XDG_CONFIG_HOME");
- /* Valid built-in path is last */
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- unsigned int nincludes = xkb_context_num_include_paths(ctx);
- assert(nincludes >= 1);
- context_path = xkb_context_include_path_get(ctx, nincludes - 1);
- assert(strcmp(context_path, xkbdir) == 0);
- xkb_context_unref(ctx);
- /* Invalid built-in path is replaced with legacy X11 path */
- setenv("XKB_CONFIG_ROOT", "¡NONSENSE!", 1);
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- nincludes = xkb_context_num_include_paths(ctx);
- assert(nincludes >= 1);
- context_path = xkb_context_include_path_get(ctx, nincludes - 1);
- assert(strcmp(context_path, DFLT_XKB_LEGACY_ROOT) == 0);
- xkb_context_unref(ctx);
- setenv("XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH", "", 1);
- setenv("XKB_CONFIG_VERSIONED_EXTENSIONS_PATH", "", 1);
- /* Ensure some path is available */
- const char *tmpdir = maketmpdir();
- setenv("XKB_CONFIG_EXTRA_PATH", tmpdir, 1);
- /* Invalid built-in path and deliberately skipped legacy X11 path */
- setenv("XKB_CONFIG_ROOT", "", 1);
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- nincludes = xkb_context_num_include_paths(ctx);
- assert(nincludes >= 1);
- context_path = xkb_context_include_path_get(ctx, nincludes - 1);
- assert(strcmp(context_path, tmpdir) == 0);
- xkb_context_unref(ctx);
- /* No valid path */
- setenv("XKB_CONFIG_EXTRA_PATH", "", 1);
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- nincludes = xkb_context_num_include_paths(ctx);
- assert(nincludes == 0);
- xkb_context_unref(ctx);
- unmakedirs();
- restore_env();
- }
- static void
- test_xkbdir_include_path(void)
- {
- struct xkb_context *ctx;
- const char *tmpdir;
- const char *xkb_path;
- const char *context_path;
- buffer_env("HOME");
- buffer_env("XDG_CONFIG_HOME");
- tmpdir = maketmpdir();
- xkb_path = makedir(tmpdir, ".xkb");
- setenv("HOME", tmpdir, 1);
- setenv("XDG_CONFIG_HOME", tmpdir, 1);
- /* No XDG directory in our tmpdir, so we expect
- * the $HOME/.xkb to be the first include path */
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- assert(xkb_context_num_include_paths(ctx) >= 1);
- context_path = xkb_context_include_path_get(ctx, 0);
- assert(strcmp(context_path, xkb_path) == 0);
- xkb_context_unref(ctx);
- unmakedirs();
- restore_env();
- }
- static void
- test_xdg_include_path(void)
- {
- struct xkb_context *ctx;
- const char *tmpdir;
- const char *xdg_path;
- const char *context_path;
- buffer_env("XDG_CONFIG_HOME");
- tmpdir = maketmpdir();
- xdg_path = makedir(tmpdir, "xkb");
- setenv("XDG_CONFIG_HOME", tmpdir, 1);
- /* XDG path is always first */
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- assert(xkb_context_num_include_paths(ctx) >= 1);
- context_path = xkb_context_include_path_get(ctx, 0);
- assert(strcmp(context_path, xdg_path) == 0);
- xkb_context_unref(ctx);
- unmakedirs();
- restore_env();
- }
- static void
- test_xdg_include_path_fallback(void)
- {
- struct xkb_context *ctx;
- const char *tmpdir;
- const char *xdg_root, *xdg_path;
- const char *context_path;
- buffer_env("XDG_CONFIG_HOME");
- buffer_env("HOME");
- tmpdir = maketmpdir();
- xdg_root = makedir(tmpdir, ".config");
- xdg_path = makedir(xdg_root, "xkb");
- setenv("HOME", tmpdir, 1);
- unsetenv("XDG_CONFIG_HOME");
- /* XDG path is always first, even if fallback */
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- assert(xkb_context_num_include_paths(ctx) >= 1);
- context_path = xkb_context_include_path_get(ctx, 0);
- assert(strcmp(context_path, xdg_path) == 0);
- xkb_context_unref(ctx);
- unmakedirs();
- restore_env();
- }
- static void
- test_include_order(void)
- {
- struct xkb_context *ctx;
- const char *tmpdir;
- const char *xdg_path;
- const char *xkb_home_path;
- const char *xkb_root_path;
- const char *context_path;
- buffer_env("XKB_CONFIG_ROOT");
- buffer_env("XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH");
- buffer_env("XKB_CONFIG_VERSIONED_EXTENSIONS_PATH");
- buffer_env("XDG_CONFIG_HOME");
- buffer_env("HOME");
- tmpdir = maketmpdir();
- xdg_path = makedir(tmpdir, "xkb");
- xkb_home_path = makedir(tmpdir, ".xkb");
- xkb_root_path = makedir(tmpdir, "xkbroot");
- setenv("HOME", tmpdir, 1);
- setenv("XDG_CONFIG_HOME", tmpdir, 1);
- setenv("XKB_CONFIG_ROOT", xkb_root_path, 1);
- setenv("XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH", "", 1);
- setenv("XKB_CONFIG_VERSIONED_EXTENSIONS_PATH", "", 1);
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- assert(xkb_context_num_include_paths(ctx) >= 3);
- /* XDG is first */
- context_path = xkb_context_include_path_get(ctx, 0);
- assert(strcmp(context_path, xdg_path) == 0);
- /* $HOME/.xkb is second */
- context_path = xkb_context_include_path_get(ctx, 1);
- assert(strcmp(context_path, xkb_home_path) == 0);
- /* CONFIG_ROOT is last */
- context_path = xkb_context_include_path_get(ctx, 2);
- assert(strcmp(context_path, xkb_root_path) == 0);
- xkb_context_unref(ctx);
- unmakedirs();
- restore_env();
- }
- static void
- test_delayed_includes(void)
- {
- buffer_env("XKB_CONFIG_ROOT");
- buffer_env("XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH");
- buffer_env("XKB_CONFIG_VERSIONED_EXTENSIONS_PATH");
- buffer_env("XKB_CONFIG_EXTRA_PATH");
- buffer_env("XDG_CONFIG_HOME");
- buffer_env("HOME");
- const char * const xkb_root_path = maketmpdir();
- /* Empty paths, so that currently a call to
- * xkb_context_include_path_append_default() would fail */
- setenv("XKB_CONFIG_ROOT", "", 1);
- setenv("XKB_CONFIG_UNVERSIONED_EXTENSIONS_PATH", "", 1);
- setenv("XKB_CONFIG_VERSIONED_EXTENSIONS_PATH", "", 1);
- setenv("XKB_CONFIG_EXTRA_PATH", "", 1);
- unsetenv("XDG_CONFIG_HOME");
- unsetenv("HOME");
- struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- /* Context should initialize correctly, despite no include path is
- * currently available */
- assert(ctx);
- assert(xkb_context_num_include_paths(ctx) == 0);
- /* Setting XKB_CONFIG_ROOT correctly is too late, because we used API that
- * requires to initialize the include paths */
- setenv("XKB_CONFIG_ROOT", xkb_root_path, 1);
- assert(xkb_context_num_include_paths(ctx) == 0);
- /* We cannot add further paths, since the default paths failed */
- assert(!xkb_context_include_path_append(ctx, xkb_root_path));
- xkb_context_unref(ctx);
- setenv("XKB_CONFIG_ROOT", "", 1);
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- /* Context should initialize correctly, despite no include path is
- * currently available */
- assert(ctx);
- /* Set XKB_CONFIG_ROOT correctly before using any API that requires the
- * to initialize the include paths */
- setenv("XKB_CONFIG_ROOT", xkb_root_path, 1);
- assert(xkb_context_num_include_paths(ctx) == 1);
- const char * const context_path = xkb_context_include_path_get(ctx, 0);
- assert(strcmp(context_path, xkb_root_path) == 0);
- assert(xkb_context_include_path_append(ctx, xkb_root_path) == 1);
- assert(xkb_context_num_include_paths(ctx) == 2);
- xkb_context_unref(ctx);
- unmakedirs();
- restore_env();
- }
- int
- main(void)
- {
- test_init();
- /* Reject invalid flags */
- assert(!xkb_context_new(-1));
- assert(!xkb_context_new(0xffff));
- struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
- assert(context);
- assert(xkb_context_num_include_paths(context) == 1);
- assert(!xkb_context_include_path_append(context, "¡NONSENSE!"));
- assert(xkb_context_num_include_paths(context) == 1);
- xkb_atom_t atom = xkb_atom_intern(context, "HELLOjunkjunkjunk", 5);
- assert(atom != XKB_ATOM_NONE);
- assert(streq(xkb_atom_text(context, atom), "HELLO"));
- atom = xkb_atom_intern_literal(context, "HELLOjunkjunkjunk");
- assert(atom != XKB_ATOM_NONE);
- assert(streq(xkb_atom_text(context, atom), "HELLOjunkjunkjunk"));
- xkb_context_unref(context);
- test_config_root_include_path();
- test_config_root_include_path_fallback();
- test_xkbdir_include_path();
- test_xdg_include_path();
- test_xdg_include_path_fallback();
- test_include_order();
- test_delayed_includes();
- return EXIT_SUCCESS;
- }
|