summaryrefslogtreecommitdiff
path: root/tests/util/dirent.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/util/dirent.c')
-rw-r--r--tests/util/dirent.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/tests/util/dirent.c b/tests/util/dirent.c
new file mode 100644
index 000000000..5840c67e0
--- /dev/null
+++ b/tests/util/dirent.c
@@ -0,0 +1,306 @@
+#include "clar_libgit2.h"
+#include "futils.h"
+
+typedef struct name_data {
+ int count; /* return count */
+ char *name; /* filename */
+} name_data;
+
+typedef struct walk_data {
+ char *sub; /* sub-directory name */
+ name_data *names; /* name state data */
+ git_str path;
+} walk_data;
+
+
+static char *top_dir = "dir-walk";
+static walk_data *state_loc;
+
+static void setup(walk_data *d)
+{
+ name_data *n;
+
+ cl_must_pass(p_mkdir(top_dir, 0777));
+
+ cl_must_pass(p_chdir(top_dir));
+
+ if (strcmp(d->sub, ".") != 0)
+ cl_must_pass(p_mkdir(d->sub, 0777));
+
+ cl_git_pass(git_str_sets(&d->path, d->sub));
+
+ state_loc = d;
+
+ for (n = d->names; n->name; n++) {
+ git_file fd = p_creat(n->name, 0666);
+ cl_assert(fd >= 0);
+ p_close(fd);
+ n->count = 0;
+ }
+}
+
+static void dirent_cleanup__cb(void *_d)
+{
+ walk_data *d = _d;
+ name_data *n;
+
+ for (n = d->names; n->name; n++) {
+ cl_must_pass(p_unlink(n->name));
+ }
+
+ if (strcmp(d->sub, ".") != 0)
+ cl_must_pass(p_rmdir(d->sub));
+
+ cl_must_pass(p_chdir(".."));
+
+ cl_must_pass(p_rmdir(top_dir));
+
+ git_str_dispose(&d->path);
+}
+
+static void check_counts(walk_data *d)
+{
+ name_data *n;
+
+ for (n = d->names; n->name; n++) {
+ cl_assert(n->count == 1);
+ }
+}
+
+static int update_count(name_data *data, const char *name)
+{
+ name_data *n;
+
+ for (n = data; n->name; n++) {
+ if (!strcmp(n->name, name)) {
+ n->count++;
+ return 0;
+ }
+ }
+
+ return GIT_ERROR;
+}
+
+static int one_entry(void *state, git_str *path)
+{
+ walk_data *d = (walk_data *) state;
+
+ if (state != state_loc)
+ return GIT_ERROR;
+
+ if (path != &d->path)
+ return GIT_ERROR;
+
+ return update_count(d->names, path->ptr);
+}
+
+
+static name_data dot_names[] = {
+ { 0, "./a" },
+ { 0, "./asdf" },
+ { 0, "./pack-foo.pack" },
+ { 0, NULL }
+};
+static walk_data dot = {
+ ".",
+ dot_names,
+ GIT_STR_INIT
+};
+
+/* make sure that the '.' folder is not traversed */
+void test_dirent__dont_traverse_dot(void)
+{
+ cl_set_cleanup(&dirent_cleanup__cb, &dot);
+ setup(&dot);
+
+ cl_git_pass(git_fs_path_direach(&dot.path, 0, one_entry, &dot));
+
+ check_counts(&dot);
+}
+
+
+static name_data sub_names[] = {
+ { 0, "sub/a" },
+ { 0, "sub/asdf" },
+ { 0, "sub/pack-foo.pack" },
+ { 0, NULL }
+};
+static walk_data sub = {
+ "sub",
+ sub_names,
+ GIT_STR_INIT
+};
+
+/* traverse a subfolder */
+void test_dirent__traverse_subfolder(void)
+{
+ cl_set_cleanup(&dirent_cleanup__cb, &sub);
+ setup(&sub);
+
+ cl_git_pass(git_fs_path_direach(&sub.path, 0, one_entry, &sub));
+
+ check_counts(&sub);
+}
+
+
+static walk_data sub_slash = {
+ "sub/",
+ sub_names,
+ GIT_STR_INIT
+};
+
+/* traverse a slash-terminated subfolder */
+void test_dirent__traverse_slash_terminated_folder(void)
+{
+ cl_set_cleanup(&dirent_cleanup__cb, &sub_slash);
+ setup(&sub_slash);
+
+ cl_git_pass(git_fs_path_direach(&sub_slash.path, 0, one_entry, &sub_slash));
+
+ check_counts(&sub_slash);
+}
+
+
+static name_data empty_names[] = {
+ { 0, NULL }
+};
+static walk_data empty = {
+ "empty",
+ empty_names,
+ GIT_STR_INIT
+};
+
+/* make sure that empty folders are not traversed */
+void test_dirent__dont_traverse_empty_folders(void)
+{
+ cl_set_cleanup(&dirent_cleanup__cb, &empty);
+ setup(&empty);
+
+ cl_git_pass(git_fs_path_direach(&empty.path, 0, one_entry, &empty));
+
+ check_counts(&empty);
+
+ /* make sure callback not called */
+ cl_assert(git_fs_path_is_empty_dir(empty.path.ptr));
+}
+
+static name_data odd_names[] = {
+ { 0, "odd/.a" },
+ { 0, "odd/..c" },
+ /* the following don't work on cygwin/win32 */
+ /* { 0, "odd/.b." }, */
+ /* { 0, "odd/..d.." }, */
+ { 0, NULL }
+};
+static walk_data odd = {
+ "odd",
+ odd_names,
+ GIT_STR_INIT
+};
+
+/* make sure that strange looking filenames ('..c') are traversed */
+void test_dirent__traverse_weird_filenames(void)
+{
+ cl_set_cleanup(&dirent_cleanup__cb, &odd);
+ setup(&odd);
+
+ cl_git_pass(git_fs_path_direach(&odd.path, 0, one_entry, &odd));
+
+ check_counts(&odd);
+}
+
+/* test filename length limits */
+void test_dirent__length_limits(void)
+{
+ char *big_filename = (char *)git__malloc(FILENAME_MAX + 1);
+ memset(big_filename, 'a', FILENAME_MAX + 1);
+ big_filename[FILENAME_MAX] = 0;
+
+ cl_must_fail(p_creat(big_filename, 0666));
+
+ git__free(big_filename);
+}
+
+void test_dirent__empty_dir(void)
+{
+ cl_must_pass(p_mkdir("empty_dir", 0777));
+ cl_assert(git_fs_path_is_empty_dir("empty_dir"));
+
+ cl_git_mkfile("empty_dir/content", "whatever\n");
+ cl_assert(!git_fs_path_is_empty_dir("empty_dir"));
+ cl_assert(!git_fs_path_is_empty_dir("empty_dir/content"));
+
+ cl_must_pass(p_unlink("empty_dir/content"));
+
+ cl_must_pass(p_mkdir("empty_dir/content", 0777));
+ cl_assert(!git_fs_path_is_empty_dir("empty_dir"));
+ cl_assert(git_fs_path_is_empty_dir("empty_dir/content"));
+
+ cl_must_pass(p_rmdir("empty_dir/content"));
+
+ cl_must_pass(p_rmdir("empty_dir"));
+}
+
+static void handle_next(git_fs_path_diriter *diriter, walk_data *walk)
+{
+ const char *fullpath, *filename;
+ size_t fullpath_len, filename_len;
+
+ cl_git_pass(git_fs_path_diriter_fullpath(&fullpath, &fullpath_len, diriter));
+ cl_git_pass(git_fs_path_diriter_filename(&filename, &filename_len, diriter));
+
+ cl_assert_equal_strn(fullpath, "sub/", 4);
+ cl_assert_equal_s(fullpath+4, filename);
+
+ update_count(walk->names, fullpath);
+}
+
+/* test directory iterator */
+void test_dirent__diriter_with_fullname(void)
+{
+ git_fs_path_diriter diriter = GIT_FS_PATH_DIRITER_INIT;
+ int error;
+
+ cl_set_cleanup(&dirent_cleanup__cb, &sub);
+ setup(&sub);
+
+ cl_git_pass(git_fs_path_diriter_init(&diriter, sub.path.ptr, 0));
+
+ while ((error = git_fs_path_diriter_next(&diriter)) == 0)
+ handle_next(&diriter, &sub);
+
+ cl_assert_equal_i(error, GIT_ITEROVER);
+
+ git_fs_path_diriter_free(&diriter);
+
+ check_counts(&sub);
+}
+
+void test_dirent__diriter_at_directory_root(void)
+{
+ git_fs_path_diriter diriter = GIT_FS_PATH_DIRITER_INIT;
+ const char *sandbox_path, *path;
+ char *root_path;
+ size_t path_len;
+ int root_offset, error;
+
+ sandbox_path = clar_sandbox_path();
+ cl_assert((root_offset = git_fs_path_root(sandbox_path)) >= 0);
+
+ cl_assert(root_path = git__calloc(1, root_offset + 2));
+ strncpy(root_path, sandbox_path, root_offset + 1);
+
+ cl_git_pass(git_fs_path_diriter_init(&diriter, root_path, 0));
+
+ while ((error = git_fs_path_diriter_next(&diriter)) == 0) {
+ cl_git_pass(git_fs_path_diriter_fullpath(&path, &path_len, &diriter));
+
+ cl_assert(path_len > (size_t)(root_offset + 1));
+ cl_assert(path[root_offset+1] != '/');
+ }
+
+ cl_assert_equal_i(error, GIT_ITEROVER);
+
+ git_fs_path_diriter_free(&diriter);
+ git__free(root_path);
+}