]> git.proxmox.com Git - libgit2.git/blob - tests/refs/iterator.c
18e9d1d5b7f423ae4db485ff2ebb6eea6ca12e40
[libgit2.git] / tests / refs / iterator.c
1 #include "clar_libgit2.h"
2 #include "refs.h"
3 #include "vector.h"
4
5 static git_repository *repo;
6
7 void test_refs_iterator__initialize(void)
8 {
9 repo = cl_git_sandbox_init("testrepo.git");
10 }
11
12 void test_refs_iterator__cleanup(void)
13 {
14 cl_git_sandbox_cleanup();
15 }
16
17 static const char *refnames[] = {
18 "refs/heads/br2",
19 "refs/heads/cannot-fetch",
20 "refs/heads/chomped",
21 "refs/heads/haacked",
22 "refs/heads/master",
23 "refs/heads/not-good",
24 "refs/heads/packed",
25 "refs/heads/packed-test",
26 "refs/heads/subtrees",
27 "refs/heads/test",
28 "refs/heads/track-local",
29 "refs/heads/trailing",
30 "refs/notes/fanout",
31 "refs/remotes/test/master",
32 "refs/tags/annotated_tag_to_blob",
33 "refs/tags/e90810b",
34 "refs/tags/hard_tag",
35 "refs/tags/point_to_blob",
36 "refs/tags/taggerless",
37 "refs/tags/test",
38 "refs/tags/wrapped_tag",
39 NULL
40 };
41
42 static const char *refnames_with_symlink[] = {
43 "refs/heads/br2",
44 "refs/heads/cannot-fetch",
45 "refs/heads/chomped",
46 "refs/heads/haacked",
47 "refs/heads/link/a",
48 "refs/heads/link/b",
49 "refs/heads/link/c",
50 "refs/heads/link/d",
51 "refs/heads/master",
52 "refs/heads/not-good",
53 "refs/heads/packed",
54 "refs/heads/packed-test",
55 "refs/heads/subtrees",
56 "refs/heads/test",
57 "refs/heads/track-local",
58 "refs/heads/trailing",
59 "refs/notes/fanout",
60 "refs/remotes/test/master",
61 "refs/tags/annotated_tag_to_blob",
62 "refs/tags/e90810b",
63 "refs/tags/hard_tag",
64 "refs/tags/point_to_blob",
65 "refs/tags/taggerless",
66 "refs/tags/test",
67 "refs/tags/wrapped_tag",
68 NULL
69 };
70
71 static int refcmp_cb(const void *a, const void *b)
72 {
73 const git_reference *refa = (const git_reference *)a;
74 const git_reference *refb = (const git_reference *)b;
75
76 return strcmp(refa->name, refb->name);
77 }
78
79 static void assert_all_refnames_match(const char **expected, git_vector *names)
80 {
81 size_t i;
82 git_reference *ref;
83
84 git_vector_sort(names);
85
86 git_vector_foreach(names, i, ref) {
87 cl_assert(expected[i] != NULL);
88 cl_assert_equal_s(expected[i], ref->name);
89 git_reference_free(ref);
90 }
91 cl_assert(expected[i] == NULL);
92
93 git_vector_free(names);
94 }
95
96 void test_refs_iterator__list(void)
97 {
98 git_reference_iterator *iter;
99 git_vector output;
100 git_reference *ref;
101
102 cl_git_pass(git_vector_init(&output, 32, &refcmp_cb));
103 cl_git_pass(git_reference_iterator_new(&iter, repo));
104
105 while (1) {
106 int error = git_reference_next(&ref, iter);
107 if (error == GIT_ITEROVER)
108 break;
109 cl_git_pass(error);
110 cl_git_pass(git_vector_insert(&output, ref));
111 }
112
113 git_reference_iterator_free(iter);
114
115 assert_all_refnames_match(refnames, &output);
116 }
117
118 void test_refs_iterator__empty(void)
119 {
120 git_reference_iterator *iter;
121 git_odb *odb;
122 git_reference *ref;
123 git_repository *empty;
124
125 cl_git_pass(git_odb_new(&odb));
126 cl_git_pass(git_repository_wrap_odb(&empty, odb));
127
128 cl_git_pass(git_reference_iterator_new(&iter, empty));
129 cl_assert_equal_i(GIT_ITEROVER, git_reference_next(&ref, iter));
130
131 git_reference_iterator_free(iter);
132 git_odb_free(odb);
133 git_repository_free(empty);
134 }
135
136 static int refs_foreach_cb(git_reference *reference, void *payload)
137 {
138 git_vector *output = payload;
139 cl_git_pass(git_vector_insert(output, reference));
140 return 0;
141 }
142
143 void test_refs_iterator__foreach(void)
144 {
145 git_vector output;
146 cl_git_pass(git_vector_init(&output, 32, &refcmp_cb));
147 cl_git_pass(git_reference_foreach(repo, refs_foreach_cb, &output));
148 assert_all_refnames_match(refnames, &output);
149 }
150
151 void test_refs_iterator__foreach_through_symlink(void)
152 {
153 git_vector output;
154
155 #ifdef GIT_WIN32
156 cl_skip();
157 #endif
158
159 cl_git_pass(git_vector_init(&output, 32, &refcmp_cb));
160
161 cl_git_pass(p_mkdir("refs", 0777));
162 cl_git_mkfile("refs/a", "1234567890123456789012345678901234567890");
163 cl_git_mkfile("refs/b", "1234567890123456789012345678901234567890");
164 cl_git_mkfile("refs/c", "1234567890123456789012345678901234567890");
165 cl_git_mkfile("refs/d", "1234567890123456789012345678901234567890");
166
167 cl_git_pass(p_symlink("../../../refs", "testrepo.git/refs/heads/link"));
168
169 cl_git_pass(git_reference_foreach(repo, refs_foreach_cb, &output));
170 assert_all_refnames_match(refnames_with_symlink, &output);
171 }
172
173 static int refs_foreach_cancel_cb(git_reference *reference, void *payload)
174 {
175 int *cancel_after = payload;
176
177 git_reference_free(reference);
178
179 if (!*cancel_after)
180 return -333;
181 (*cancel_after)--;
182 return 0;
183 }
184
185 void test_refs_iterator__foreach_can_cancel(void)
186 {
187 int cancel_after = 3;
188 cl_git_fail_with(
189 git_reference_foreach(repo, refs_foreach_cancel_cb, &cancel_after),
190 -333);
191 cl_assert_equal_i(0, cancel_after);
192 }
193
194 static int refs_foreach_name_cb(const char *name, void *payload)
195 {
196 git_vector *output = payload;
197 cl_git_pass(git_vector_insert(output, git__strdup(name)));
198 return 0;
199 }
200
201 void test_refs_iterator__foreach_name(void)
202 {
203 git_vector output;
204 size_t i;
205 char *name;
206
207 cl_git_pass(git_vector_init(&output, 32, &git__strcmp_cb));
208 cl_git_pass(
209 git_reference_foreach_name(repo, refs_foreach_name_cb, &output));
210
211 git_vector_sort(&output);
212
213 git_vector_foreach(&output, i, name) {
214 cl_assert(refnames[i] != NULL);
215 cl_assert_equal_s(refnames[i], name);
216 git__free(name);
217 }
218
219 git_vector_free(&output);
220 }
221
222 static int refs_foreach_name_cancel_cb(const char *name, void *payload)
223 {
224 int *cancel_after = payload;
225 if (!*cancel_after)
226 return -333;
227 GIT_UNUSED(name);
228 (*cancel_after)--;
229 return 0;
230 }
231
232 void test_refs_iterator__foreach_name_can_cancel(void)
233 {
234 int cancel_after = 5;
235 cl_git_fail_with(
236 git_reference_foreach_name(
237 repo, refs_foreach_name_cancel_cb, &cancel_after),
238 -333);
239 cl_assert_equal_i(0, cancel_after);
240 }
241
242 void test_refs_iterator__concurrent_delete(void)
243 {
244 git_reference_iterator *iter;
245 size_t full_count = 0, concurrent_count = 0;
246 const char *name;
247 int error;
248
249 cl_git_sandbox_cleanup();
250 repo = cl_git_sandbox_init("testrepo");
251
252 cl_git_pass(git_reference_iterator_new(&iter, repo));
253 while ((error = git_reference_next_name(&name, iter)) == 0) {
254 full_count++;
255 }
256
257 git_reference_iterator_free(iter);
258 cl_assert_equal_i(GIT_ITEROVER, error);
259
260 cl_git_pass(git_reference_iterator_new(&iter, repo));
261 while ((error = git_reference_next_name(&name, iter)) == 0) {
262 cl_git_pass(git_reference_remove(repo, name));
263 concurrent_count++;
264 }
265
266 git_reference_iterator_free(iter);
267 cl_assert_equal_i(GIT_ITEROVER, error);
268
269 cl_assert_equal_i(full_count, concurrent_count);
270 }