From: Martti Rannanjärvi Date: Tue, 29 Nov 2016 18:50:28 +0000 (+0200) Subject: lib: Add tests for path-util X-Git-Tag: 2.3.0.rc1~2212 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b28403dc4da6ee942ff18315596b43d4c4e9b7bd;p=thirdparty%2Fdovecot%2Fcore.git lib: Add tests for path-util --- diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 45d6c9674a..54308b28cf 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -357,6 +357,7 @@ test_lib_SOURCES = \ test-ostream-escaped.c \ test-ostream-failure-at.c \ test-ostream-file.c \ + test-path-util.c \ test-primes.c \ test-printf-format-fix.c \ test-priorityq.c \ diff --git a/src/lib/test-lib.inc b/src/lib/test-lib.inc index 77712f94ac..571a74a402 100644 --- a/src/lib/test-lib.inc +++ b/src/lib/test-lib.inc @@ -50,6 +50,7 @@ TEST(test_numpack) TEST(test_ostream_escaped) TEST(test_ostream_failure_at) TEST(test_ostream_file) +TEST(test_path_util) TEST(test_pkcs5_pbkdf2) TEST(test_primes) TEST(test_printf_format_fix) diff --git a/src/lib/test-path-util.c b/src/lib/test-path-util.c new file mode 100644 index 0000000000..2fada8f3cd --- /dev/null +++ b/src/lib/test-path-util.c @@ -0,0 +1,159 @@ +/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */ + +#include +#include +#include + +#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--;) { + 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(); +}