packaging: Bump up to 1.6.0
[platform/upstream/libxkbcommon.git] / test / context.c
index dc60888..bb619b0 100644 (file)
  * Author: Daniel Stone <daniel@fooishbar.org>
  */
 
+#include "config.h"
+
 #include "test.h"
 #include "context.h"
 
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* keeps a cache of all makedir/maketmpdir directories so we can free and
+ * rmdir them in one go, see unmakedirs() */
+char *dirnames[64];
+int ndirs;
+
+/* keeps a cache of all buffered env vars so we can restore
+ * them in one go, see restore_env() */
+struct env {
+    char *key;
+    char *value;
+} environment[64];
+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;
+    int nincludes;
+
+    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");
+
+    /* built-in path is last */
+    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);
+
+    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;
+    int nincludes;
+
+    /* 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("HOME");
+    buffer_env("XDG_CONFIG_HOME");
+
+    unsetenv("XKB_CONFIG_ROOT");
+    unsetenv("HOME");
+    unsetenv("XDG_CONFIG_HOME");
+
+    /* built-in path is last */
+    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, xkbdir) == 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("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);
+
+    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();
+}
+
 int
 main(void)
 {
@@ -48,5 +309,12 @@ main(void)
 
     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();
+
     return 0;
 }