From a56aacf4d36778daa446b0a6c075e4cbc0791f41 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Mar 2012 12:03:30 -0700 Subject: [PATCH] More status testing This "fixes" the broken t18 status tests to accurately reflect the new behavior for "created" untracked subdirectories. See discussion in the PR for more details. This also contains the submodules unit test that I forgot to git add, and ports most of the t18-status.c tests to clar (still missing a couple of the git_status_file() single file tests). --- tests-clar/status/status_data.h | 95 +++++++++++++++++++++++++++++ tests-clar/status/submodules.c | 104 ++++++++++++++++++++++++++++++++ tests-clar/status/worktree.c | 92 ++++++++++++++++++++++++++++ tests/t18-status.c | 8 +-- 4 files changed, 293 insertions(+), 6 deletions(-) create mode 100644 tests-clar/status/submodules.c diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h index 1a68648f4..395776845 100644 --- a/tests-clar/status/status_data.h +++ b/tests-clar/status/status_data.h @@ -8,6 +8,8 @@ struct status_entry_counts { int expected_entry_count; }; +/* entries for a plain copy of tests/resources/status */ + static const char *entry_paths0[] = { "file_deleted", "ignored_file", @@ -48,3 +50,96 @@ static const unsigned int entry_statuses0[] = { static const size_t entry_count0 = 15; +/* entries for a copy of tests/resources/status with all content + * deleted from the working directory + */ + +static const char *entry_paths2[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir.txt", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", +}; + +static const unsigned int entry_statuses2[] = { + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, +}; + +static const size_t entry_count2 = 15; + +/* entries for a copy of tests/resources/status with some mods */ + +static const char *entry_paths3[] = { + ".HEADER", + "42-is-not-prime.sigh", + "README.md", + "current_file", + "current_file/", + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", +}; + +static const unsigned int entry_statuses3[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, +}; + +static const size_t entry_count3 = 21; diff --git a/tests-clar/status/submodules.c b/tests-clar/status/submodules.c new file mode 100644 index 000000000..ca6c2ef30 --- /dev/null +++ b/tests-clar/status/submodules.c @@ -0,0 +1,104 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "path.h" +#include "posix.h" + +static git_repository *g_repo = NULL; + +void test_status_submodules__initialize(void) +{ + git_buf modpath = GIT_BUF_INIT; + + g_repo = cl_git_sandbox_init("submodules"); + + cl_fixture_sandbox("testrepo.git"); + + cl_git_pass(git_buf_sets(&modpath, git_repository_workdir(g_repo))); + cl_assert(git_path_dirname_r(&modpath, modpath.ptr) >= 0); + cl_git_pass(git_buf_joinpath(&modpath, modpath.ptr, "testrepo.git\n")); + + p_rename("submodules/gitmodules", "submodules/.gitmodules"); + cl_git_append2file("submodules/.gitmodules", modpath.ptr); + + p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git"); +} + +void test_status_submodules__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static int +cb_status__count(const char *p, unsigned int s, void *payload) +{ + volatile int *count = (int *)payload; + + GIT_UNUSED(p); + GIT_UNUSED(s); + + (*count)++; + + return 0; +} + +void test_status_submodules__0(void) +{ + int counts = 0; + + cl_assert(git_path_isdir("submodules/.git")); + cl_assert(git_path_isdir("submodules/testrepo/.git")); + cl_assert(git_path_isfile("submodules/.gitmodules")); + + cl_git_pass( + git_status_foreach(g_repo, cb_status__count, &counts) + ); + + cl_assert(counts == 7); +} + +static const char *expected_files[] = { + ".gitmodules", + "added", + "deleted", + "ignored", + "modified", + "testrepo", + "untracked" +}; + +static unsigned int expected_status[] = { + GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_MODIFIED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_INDEX_NEW, /* submodule added in index, but not committed */ + GIT_STATUS_WT_NEW +}; + +static int +cb_status__match(const char *p, unsigned int s, void *payload) +{ + volatile int *index = (int *)payload; + + cl_assert_strequal(expected_files[*index], p); + cl_assert(expected_status[*index] == s); + (*index)++; + + return 0; +} + +void test_status_submodules__1(void) +{ + int index = 0; + + cl_assert(git_path_isdir("submodules/.git")); + cl_assert(git_path_isdir("submodules/testrepo/.git")); + cl_assert(git_path_isfile("submodules/.gitmodules")); + + cl_git_pass( + git_status_foreach(g_repo, cb_status__match, &index) + ); + + cl_assert(index == 7); +} diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 98bb2b819..9ddb7d1bc 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -3,6 +3,8 @@ #include "ignore.h" #include "status_data.h" #include "posix.h" +#include "util.h" +#include "path.h" /** * Auxiliary methods @@ -67,6 +69,7 @@ void test_status_worktree__cleanup(void) /** * Tests - Status determination on a working tree */ +/* this test is equivalent to t18-status.c:statuscb0 */ void test_status_worktree__whole_repository(void) { struct status_entry_counts counts; @@ -86,6 +89,7 @@ void test_status_worktree__whole_repository(void) cl_assert(counts.wrong_sorted_path == 0); } +/* this test is equivalent to t18-status.c:statuscb1 */ void test_status_worktree__empty_repository(void) { int count = 0; @@ -96,6 +100,81 @@ void test_status_worktree__empty_repository(void) cl_assert(count == 0); } +static int remove_file_cb(void *data, git_buf *file) +{ + const char *filename = git_buf_cstr(file); + + GIT_UNUSED(data); + + if (git__suffixcmp(filename, ".git") == 0) + return 0; + + if (git_path_isdir(filename)) + cl_git_pass(git_futils_rmdir_r(filename, 1)); + else + cl_git_pass(p_unlink(git_buf_cstr(file))); + + return 0; +} + +/* this test is equivalent to t18-status.c:statuscb2 */ +void test_status_worktree__purged_worktree(void) +{ + struct status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + git_buf workdir = GIT_BUF_INIT; + + /* first purge the contents of the worktree */ + cl_git_pass(git_buf_sets(&workdir, git_repository_workdir(repo))); + cl_git_pass(git_path_direach(&workdir, remove_file_cb, NULL)); + + /* now get status */ + memset(&counts, 0x0, sizeof(struct status_entry_counts)); + counts.expected_entry_count = entry_count2; + counts.expected_paths = entry_paths2; + counts.expected_statuses = entry_statuses2; + + cl_git_pass( + git_status_foreach(repo, cb_status__normal, &counts) + ); + + cl_assert(counts.entry_count == counts.expected_entry_count); + cl_assert(counts.wrong_status_flags_count == 0); + cl_assert(counts.wrong_sorted_path == 0); +} + +/* this test is equivalent to t18-status.c:statuscb3 */ +void test_status_worktree__swap_subdir_and_file(void) +{ + struct status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + + /* first alter the contents of the worktree */ + cl_git_pass(p_rename("status/current_file", "status/swap")); + cl_git_pass(p_rename("status/subdir", "status/current_file")); + cl_git_pass(p_rename("status/swap", "status/subdir")); + + cl_git_mkfile("status/.HEADER", "dummy"); + cl_git_mkfile("status/42-is-not-prime.sigh", "dummy"); + cl_git_mkfile("status/README.md", "dummy"); + + /* now get status */ + memset(&counts, 0x0, sizeof(struct status_entry_counts)); + counts.expected_entry_count = entry_count3; + counts.expected_paths = entry_paths3; + counts.expected_statuses = entry_statuses3; + + cl_git_pass( + git_status_foreach(repo, cb_status__normal, &counts) + ); + + cl_assert(counts.entry_count == counts.expected_entry_count); + cl_assert(counts.wrong_status_flags_count == 0); + cl_assert(counts.wrong_sorted_path == 0); + +} + +/* this test is equivalent to t18-status.c:singlestatus0 */ void test_status_worktree__single_file(void) { int i; @@ -110,6 +189,19 @@ void test_status_worktree__single_file(void) } } +/* this test is equivalent to t18-status.c:singlestatus1 */ +void test_status_worktree__single_nonexistent_file(void) +{ + int error; + unsigned int status_flags; + git_repository *repo = cl_git_sandbox_init("status"); + + error = git_status_file(&status_flags, repo, "nonexistent"); + cl_git_fail(error); + cl_assert(error == GIT_ENOTFOUND); +} + + void test_status_worktree__ignores(void) { int i, ignored; diff --git a/tests/t18-status.c b/tests/t18-status.c index bfd6906c1..8abff9872 100644 --- a/tests/t18-status.c +++ b/tests/t18-status.c @@ -261,9 +261,7 @@ static const char *entry_paths3[] = { "42-is-not-prime.sigh", "README.md", "current_file", - "current_file/current_file", - "current_file/modified_file", - "current_file/new_file", + "current_file/", "file_deleted", "ignored_file", "modified_file", @@ -288,8 +286,6 @@ static const unsigned int entry_statuses3[] = { GIT_STATUS_WT_NEW, GIT_STATUS_WT_DELETED, GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, GIT_STATUS_WT_DELETED, GIT_STATUS_IGNORED, GIT_STATUS_WT_MODIFIED, @@ -308,7 +304,7 @@ static const unsigned int entry_statuses3[] = { GIT_STATUS_WT_DELETED, }; -#define ENTRY_COUNT3 23 +#define ENTRY_COUNT3 21 BEGIN_TEST(statuscb3, "test retrieving status for a worktree where a file and a subdir have been renamed and some files have been added") git_repository *repo;