Commit a56aacf4d36778daa446b0a6c075e4cbc0791f41

Russell Belfer 2012-03-22T12:03:30

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).

diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h
index 1a68648..3957768 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 0000000..ca6c2ef
--- /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 98bb2b8..9ddb7d1 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 bfd6906..8abff98 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;