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