refdb.c 4.47 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#include "clar_libgit2.h"
#include "git2/refdb.h"
#include "refdb.h"

static git_repository *g_repo;
static int g_expected = 0;

void test_threads_refdb__initialize(void)
{
	g_repo = NULL;
}

void test_threads_refdb__cleanup(void)
{
	cl_git_sandbox_cleanup();
	g_repo = NULL;
}

#define REPEAT 20
#define THREADS 20

static void *iterate_refs(void *arg)
{
	git_reference_iterator *i;
	git_reference *ref;
26
	int count = 0;
27 28 29 30 31 32 33 34 35 36 37 38 39

	cl_git_pass(git_reference_iterator_new(&i, g_repo));

	for (count = 0; !git_reference_next(&ref, i); ++count) {
		cl_assert(ref != NULL);
		git_reference_free(ref);
	}

	if (g_expected > 0)
		cl_assert_equal_i(g_expected, count);

	git_reference_iterator_free(i);

Russell Belfer committed
40
	giterr_clear();
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
	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) {
61
		p_snprintf(name, sizeof(name), "refs/heads/direct-%03d", r);
62
		cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL));
63 64 65 66 67 68 69 70 71 72 73 74 75 76
		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;
77
#ifdef GIT_THREADS
78
			cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
79 80 81 82
#else
			th[t] = t;
			iterate_refs(&id[t]);
#endif
83 84
		}

85
#ifdef GIT_THREADS
86
		for (t = 0; t < THREADS; ++t) {
87
			cl_git_pass(git_thread_join(&th[t], NULL));
88
		}
89
#endif
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

		memset(th, 0, sizeof(th));
	}
}

static void *create_refs(void *arg)
{
	int *id = arg, i;
	git_oid head;
	char name[128];
	git_reference *ref[10];

	cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD"));

	for (i = 0; i < 10; ++i) {
105
		p_snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", *id, i);
106
		cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0, NULL));
107 108 109 110 111 112 113 114 115 116 117 118

		if (i == 5) {
			git_refdb *refdb;
			cl_git_pass(git_repository_refdb(&refdb, g_repo));
			cl_git_pass(git_refdb_compress(refdb));
			git_refdb_free(refdb);
		}
	}

	for (i = 0; i < 10; ++i)
		git_reference_free(ref[i]);

Russell Belfer committed
119
	giterr_clear();
120 121 122 123 124 125 126 127 128 129
	return arg;
}

static void *delete_refs(void *arg)
{
	int *id = arg, i;
	git_reference *ref;
	char name[128];

	for (i = 0; i < 10; ++i) {
130
		p_snprintf(
131 132 133 134
			name, sizeof(name), "refs/heads/thread-%03d-%02d", (*id) & ~0x3, i);

		if (!git_reference_lookup(&ref, g_repo, name)) {
			cl_git_pass(git_reference_delete(ref));
135
			git_reference_free(ref);
136 137 138 139 140 141 142 143 144 145
		}

		if (i == 5) {
			git_refdb *refdb;
			cl_git_pass(git_repository_refdb(&refdb, g_repo));
			cl_git_pass(git_refdb_compress(refdb));
			git_refdb_free(refdb);
		}
	}

Russell Belfer committed
146
	giterr_clear();
147 148 149 150 151 152 153 154 155 156 157 158
	return arg;
}

void test_threads_refdb__edit_while_iterate(void)
{
	int r, t;
	int id[THREADS];
	git_oid head;
	git_reference *ref;
	char name[128];
	git_refdb *refdb;

159 160 161 162
#ifdef GIT_THREADS
	git_thread th[THREADS];
#endif

163 164 165 166 167 168 169
	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 < 50; ++r) {
170
		p_snprintf(name, sizeof(name), "refs/heads/starter-%03d", r);
171
		cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL));
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
		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 = -1;

	g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */

	for (t = 0; t < THREADS; ++t) {
		void *(*fn)(void *arg);

		switch (t & 0x3) {
		case 0:  fn = create_refs;  break;
		case 1:  fn = delete_refs;  break;
		default: fn = iterate_refs; break;
		}

		id[t] = t;
193 194 195 196 197 198

		/* 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 */
199
/*		cl_git_pass(git_thread_create(&th[t], fn, &id[t])); */
200
/* #else */
201
		fn(&id[t]);
202
/* #endif */
203 204
	}

205
#ifdef GIT_THREADS
206 207 208
/*	for (t = 0; t < THREADS; ++t) { */
/*		cl_git_pass(git_thread_join(th[t], NULL)); */
/*	} */
209 210 211 212 213

	memset(th, 0, sizeof(th));

	for (t = 0; t < THREADS; ++t) {
		id[t] = t;
214
		cl_git_pass(git_thread_create(&th[t], iterate_refs, &id[t]));
215 216 217
	}

	for (t = 0; t < THREADS; ++t) {
218
		cl_git_pass(git_thread_join(&th[t], NULL));
219
	}
220
#endif
221
}