Commit 7da4c429ea3d21e0fca0755e927f19b93e81a5c6

Carlos Martín Nieto 2015-12-24T12:37:41

refdb: adjust the threading tests to what we promise We say it's going to work if you use a different repository in each thread. Let's do precisely that in our code instead of hoping re-using the refdb is going to work. This test does fail currently, surfacing existing bugs.

diff --git a/tests/threads/refdb.c b/tests/threads/refdb.c
index f869bcb..9b1b375 100644
--- a/tests/threads/refdb.c
+++ b/tests/threads/refdb.c
@@ -19,13 +19,21 @@ void test_threads_refdb__cleanup(void)
 #define REPEAT 20
 #define THREADS 20
 
+struct th_data {
+	int id;
+	const char *path;
+};
+
 static void *iterate_refs(void *arg)
 {
+	struct th_data *data = (struct th_data *) arg;
 	git_reference_iterator *i;
 	git_reference *ref;
 	int count = 0;
+	git_repository *repo;
 
-	cl_git_pass(git_reference_iterator_new(&i, g_repo));
+	cl_git_pass(git_repository_open(&repo, data->path));
+	cl_git_pass(git_reference_iterator_new(&i, repo));
 
 	for (count = 0; !git_reference_next(&ref, i); ++count) {
 		cl_assert(ref != NULL);
@@ -37,77 +45,31 @@ static void *iterate_refs(void *arg)
 
 	git_reference_iterator_free(i);
 
+	git_repository_free(repo);
 	giterr_clear();
 	return arg;
 }
 
-void test_threads_refdb__iterator(void)
-{
-	int r, t;
-	git_thread th[THREADS];
-	int id[THREADS];
-	git_oid head;
-	git_reference *ref;
-	char name[128];
-	git_refdb *refdb;
-
-	g_repo = cl_git_sandbox_init("testrepo2");
-
-	cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD"));
-
-	/* make a bunch of references */
-
-	for (r = 0; r < 200; ++r) {
-		p_snprintf(name, sizeof(name), "refs/heads/direct-%03d", r);
-		cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL));
-		git_reference_free(ref);
-	}
-
-	cl_git_pass(git_repository_refdb(&refdb, g_repo));
-	cl_git_pass(git_refdb_compress(refdb));
-	git_refdb_free(refdb);
-
-	g_expected = 206;
-
-	for (r = 0; r < REPEAT; ++r) {
-		g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */
-
-		for (t = 0; t < THREADS; ++t) {
-			id[t] = t;
-#ifdef GIT_THREADS
-			cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
-#else
-			th[t] = t;
-			iterate_refs(&id[t]);
-#endif
-		}
-
-#ifdef GIT_THREADS
-		for (t = 0; t < THREADS; ++t) {
-			cl_git_pass(git_thread_join(&th[t], NULL));
-		}
-#endif
-
-		memset(th, 0, sizeof(th));
-	}
-}
-
 static void *create_refs(void *arg)
 {
-	int *id = arg, i;
+	int i;
+	struct th_data *data = (struct th_data *) arg;
 	git_oid head;
 	char name[128];
 	git_reference *ref[10];
+	git_repository *repo;
 
-	cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD"));
+	cl_git_pass(git_repository_open(&repo, data->path));
+
+	cl_git_pass(git_reference_name_to_id(&head, repo, "HEAD"));
 
 	for (i = 0; i < 10; ++i) {
-		p_snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", *id, i);
-		cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0, NULL));
+		p_snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", data->id, i);
+		cl_git_pass(git_reference_create(&ref[i], repo, name, &head, 0, NULL));
 
 		if (i == 5) {
 			git_refdb *refdb;
-			cl_git_pass(git_repository_refdb(&refdb, g_repo));
+			cl_git_pass(git_repository_refdb(&refdb, repo));
 			cl_git_pass(git_refdb_compress(refdb));
 			git_refdb_free(refdb);
 		}
@@ -116,33 +78,40 @@ static void *create_refs(void *arg)
 	for (i = 0; i < 10; ++i)
 		git_reference_free(ref[i]);
 
+	git_repository_free(repo);
+
 	giterr_clear();
 	return arg;
 }
 
 static void *delete_refs(void *arg)
 {
-	int *id = arg, i;
+	int i;
+	struct th_data *data = (struct th_data *) arg;
 	git_reference *ref;
 	char name[128];
+	git_repository *repo;
+
+	cl_git_pass(git_repository_open(&repo, data->path));
 
 	for (i = 0; i < 10; ++i) {
 		p_snprintf(
-			name, sizeof(name), "refs/heads/thread-%03d-%02d", (*id) & ~0x3, i);
+			name, sizeof(name), "refs/heads/thread-%03d-%02d", (data->id) & ~0x3, i);
 
-		if (!git_reference_lookup(&ref, g_repo, name)) {
+		if (!git_reference_lookup(&ref, repo, name)) {
 			cl_git_pass(git_reference_delete(ref));
 			git_reference_free(ref);
 		}
 
 		if (i == 5) {
 			git_refdb *refdb;
-			cl_git_pass(git_repository_refdb(&refdb, g_repo));
+			cl_git_pass(git_repository_refdb(&refdb, repo));
 			cl_git_pass(git_refdb_compress(refdb));
 			git_refdb_free(refdb);
 		}
 	}
 
+	git_repository_free(repo);
 	giterr_clear();
 	return arg;
 }
@@ -150,7 +119,7 @@ static void *delete_refs(void *arg)
 void test_threads_refdb__edit_while_iterate(void)
 {
 	int r, t;
-	int id[THREADS];
+	struct th_data th_data[THREADS];
 	git_oid head;
 	git_reference *ref;
 	char name[128];
@@ -189,29 +158,26 @@ void test_threads_refdb__edit_while_iterate(void)
 		default: fn = iterate_refs; break;
 		}
 
-		id[t] = t;
-
-		/* It appears with all reflog writing changes, etc., that this
-		 * test has started to fail quite frequently, so let's disable it
-		 * for now by just running on a single thread...
-		 */
-/* #ifdef GIT_THREADS */
-/*		cl_git_pass(git_thread_create(&th[t], fn, &id[t])); */
-/* #else */
-		fn(&id[t]);
-/* #endif */
+		th_data[t].id = t;
+		th_data[t].path = git_repository_path(g_repo);
+
+#ifdef GIT_THREADS
+		cl_git_pass(git_thread_create(&th[t], fn, &th_data[t]));
+#else
+		fn(&th_data[t]);
+#endif
 	}
 
 #ifdef GIT_THREADS
-/*	for (t = 0; t < THREADS; ++t) { */
-/*		cl_git_pass(git_thread_join(th[t], NULL)); */
-/*	} */
+	for (t = 0; t < THREADS; ++t) {
+		cl_git_pass(git_thread_join(&th[t], NULL));
+	}
 
 	memset(th, 0, sizeof(th));
 
 	for (t = 0; t < THREADS; ++t) {
-		id[t] = t;
-		cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
+		th_data[t].id = t;
+		cl_git_pass(git_thread_create(&th[t], iterate_refs, &th_data[t]));
 	}
 
 	for (t = 0; t < THREADS; ++t) {