test-path-util.c revision 9b5576a265cbadb1f0b3c3d5e40e928e1fed1ec9
/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
#include <unistd.h>
#include <stdlib.h>
#include <libgen.h>
#include "test-lib.h"
#include "path-util.h"
static char tmpdir[64];
static const char *cwd;
static const char *link1;
static const char *link2;
static const char *link3;
static void test_local_path() {
const char *expected = t_strconcat(cwd, "/README.md", NULL);
const char *npath = NULL, *error = NULL;
test_assert(t_normpath_to("README.md", cwd, &npath, &error) == 0);
test_assert_strcmp(npath, expected);
}
static void test_absolute_path_no_change(void) {
const char *npath = NULL, *error = NULL;
test_assert(t_normpath_to("/", "/", &npath, &error) == 0);
test_assert_strcmp(npath, "/");
test_assert(t_normpath_to(cwd, cwd, &npath, &error) == 0);
test_assert_strcmp(npath, cwd);
}
static int path_height(const char* p) {
int n;
for (n = 0; *p != '\0'; ++p)
n += *p == '/';
return n;
}
static void test_travel_to_root(void) {
int l = path_height(cwd);
const char *npath = cwd;
for (npath = cwd; l != 0; l--) {
const char *error;
test_assert_idx(t_normpath_to("../", npath, &npath, &error) == 0, l);
}
test_assert_strcmp(npath, "/");
}
static void test_extra_slashes(void) {
const char *npath = NULL, *error = NULL;
test_assert(t_normpath_to(".", cwd, &npath, &error) == 0);
test_assert_strcmp(npath, cwd);
test_assert(t_normpath_to("./", cwd, &npath, &error) == 0);
test_assert_strcmp(npath, cwd);
test_assert(t_normpath_to(".////", cwd, &npath, &error) == 0);
test_assert_strcmp(npath, cwd);
}
static void test_nonexistent_path(void) {
const char *npath = NULL, *error = NULL;
const char *expected = t_strconcat(cwd, "/nonexistent", NULL);
test_assert(t_normpath_to("nonexistent", cwd, &npath, &error) == 0);
test_assert_strcmp(npath, expected);
test_assert(t_realpath_to("nonexistent", cwd, &npath, &error) == -1);
test_assert(error != NULL);
}
static void test_relative_dotdot() {
const char *rel_path = t_strconcat("../", basename(tmpdir), NULL);
const char *npath = NULL, *error = NULL;
test_assert(t_normpath_to(rel_path, tmpdir, &npath, &error) == 0);
test_assert_strcmp(npath, tmpdir);
test_assert(t_normpath_to("..", tmpdir, &npath, &error) == 0);
test_assert_strcmp(npath, "/tmp");
test_assert(t_normpath_to("../", tmpdir, &npath, &error) == 0);
test_assert_strcmp(npath, "/tmp");
test_assert(t_normpath_to("../.", tmpdir, &npath, &error) == 0);
test_assert_strcmp(npath, "/tmp");
}
static void test_link1() {
const char *npath = NULL, *error = NULL;
test_assert(t_realpath_to(link1, "/", &npath, &error) == 0);
test_assert_strcmp(npath, tmpdir);
}
static void test_link_loop() {
const char *npath = NULL, *error = NULL;
errno = 0;
test_assert(t_realpath_to(link2, "/", &npath, &error) == -1);
test_assert(errno == ELOOP);
test_assert(error != NULL);
}
static void test_abspath_vs_normpath() {
const char *abs = t_abspath_to("../../bin", "/usr/lib/");
test_assert_strcmp(abs, "/usr/lib//../../bin");
const char *norm = NULL, *error = NULL;
test_assert(t_normpath_to("../../bin", "/usr///lib/", &norm, &error) == 0);
test_assert_strcmp(norm, "/bin");
}
static void test_init(void) {
const char *error;
test_assert(t_get_working_dir(&cwd, &error) == 0);
strcpy(tmpdir, "/tmp/tmpdir.XXXXXX");
if (mkdtemp(tmpdir) == NULL) {
i_fatal("mkdtemp: %m");
}
link1 = t_strconcat(tmpdir, "/link1", NULL);
if (symlink(tmpdir, link1) < 0) {
i_fatal("symlink: %m");
}
/* link2 and link3 point to each other to create a loop */
link2 = t_strconcat(tmpdir, "/link2", NULL);
link3 = t_strconcat(tmpdir, "/link3", NULL);
if (symlink(link3, link2) < 0) {
i_fatal("symlink: %m");
}
if (symlink(link2, link3) < 0) {
i_fatal("symlink: %m");
}
}
static void test_deinit(void) {
if (unlink(link1) < 0) {
i_fatal("unlink: %m");
} if (unlink(link2) < 0) {
i_fatal("unlink: %m");
} if (unlink(link3) < 0) {
i_fatal("unlink: %m");
} if (rmdir(tmpdir) < 0) {
i_fatal("rmdir: %m");
}
}
void test_path_util(void) {
test_begin("test_path_util");
test_init();
test_local_path();
test_absolute_path_no_change();
test_travel_to_root();
test_extra_slashes();
test_nonexistent_path();
test_relative_dotdot();
test_link1();
test_link_loop();
test_abspath_vs_normpath();
test_deinit();
test_end();
}