]> git.proxmox.com Git - libgit2.git/blame - tests-clar/diff/diffiter.c
Merge pull request #959 from jamill/empty_file_hash
[libgit2.git] / tests-clar / diff / diffiter.c
CommitLineData
f335ecd6
RB
1#include "clar_libgit2.h"
2#include "diff_helpers.h"
3
4void test_diff_diffiter__initialize(void)
5{
6}
7
8void test_diff_diffiter__cleanup(void)
9{
10 cl_git_sandbox_cleanup();
11}
12
13void test_diff_diffiter__create(void)
14{
15 git_repository *repo = cl_git_sandbox_init("attr");
16 git_diff_list *diff;
5f69a31f 17 size_t d, num_d;
f335ecd6
RB
18
19 cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));
5f69a31f
RB
20
21 num_d = git_diff_num_deltas(diff);
22 for (d = 0; d < num_d; ++d) {
bae957b9 23 const git_diff_delta *delta;
5f69a31f
RB
24 cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d));
25 }
26
f335ecd6
RB
27 git_diff_list_free(diff);
28}
29
30void test_diff_diffiter__iterate_files(void)
31{
32 git_repository *repo = cl_git_sandbox_init("attr");
33 git_diff_list *diff;
5f69a31f
RB
34 size_t d, num_d;
35 int count = 0;
f335ecd6
RB
36
37 cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));
f335ecd6 38
5f69a31f
RB
39 num_d = git_diff_num_deltas(diff);
40 cl_assert_equal_i(6, num_d);
41
42 for (d = 0; d < num_d; ++d) {
bae957b9 43 const git_diff_delta *delta;
5f69a31f 44 cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d));
f335ecd6
RB
45 cl_assert(delta != NULL);
46 count++;
47 }
f335ecd6
RB
48 cl_assert_equal_i(6, count);
49
f335ecd6
RB
50 git_diff_list_free(diff);
51}
52
53void test_diff_diffiter__iterate_files_2(void)
54{
55 git_repository *repo = cl_git_sandbox_init("status");
56 git_diff_list *diff;
5f69a31f
RB
57 size_t d, num_d;
58 int count = 0;
f335ecd6
RB
59
60 cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));
f335ecd6 61
5f69a31f
RB
62 num_d = git_diff_num_deltas(diff);
63 cl_assert_equal_i(8, num_d);
64
65 for (d = 0; d < num_d; ++d) {
bae957b9 66 const git_diff_delta *delta;
5f69a31f 67 cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d));
f335ecd6
RB
68 cl_assert(delta != NULL);
69 count++;
70 }
f335ecd6
RB
71 cl_assert_equal_i(8, count);
72
f335ecd6
RB
73 git_diff_list_free(diff);
74}
75
76void test_diff_diffiter__iterate_files_and_hunks(void)
77{
78 git_repository *repo = cl_git_sandbox_init("status");
79 git_diff_options opts = {0};
80 git_diff_list *diff = NULL;
5f69a31f
RB
81 size_t d, num_d;
82 int file_count = 0, hunk_count = 0;
f335ecd6
RB
83
84 opts.context_lines = 3;
85 opts.interhunk_lines = 1;
86 opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
87
88 cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
89
5f69a31f
RB
90 num_d = git_diff_num_deltas(diff);
91
92 for (d = 0; d < num_d; ++d) {
93 git_diff_patch *patch;
bae957b9 94 const git_diff_delta *delta;
5f69a31f
RB
95 size_t h, num_h;
96
97 cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));
f335ecd6 98
f335ecd6 99 cl_assert(delta);
5f69a31f 100 cl_assert(patch);
f335ecd6
RB
101
102 file_count++;
103
5f69a31f
RB
104 num_h = git_diff_patch_num_hunks(patch);
105
106 for (h = 0; h < num_h; h++) {
bae957b9 107 const git_diff_range *range;
5f69a31f
RB
108 const char *header;
109 size_t header_len, num_l;
110
111 cl_git_pass(git_diff_patch_get_hunk(
112 &range, &header, &header_len, &num_l, patch, h));
113
f335ecd6 114 cl_assert(range);
5f69a31f
RB
115 cl_assert(header);
116
f335ecd6
RB
117 hunk_count++;
118 }
5f69a31f
RB
119
120 git_diff_patch_free(patch);
f335ecd6
RB
121 }
122
f335ecd6
RB
123 cl_assert_equal_i(13, file_count);
124 cl_assert_equal_i(8, hunk_count);
125
f335ecd6
RB
126 git_diff_list_free(diff);
127}
1f35e89d
RB
128
129void test_diff_diffiter__max_size_threshold(void)
130{
131 git_repository *repo = cl_git_sandbox_init("status");
132 git_diff_options opts = {0};
133 git_diff_list *diff = NULL;
5f69a31f
RB
134 int file_count = 0, binary_count = 0, hunk_count = 0;
135 size_t d, num_d;
1f35e89d
RB
136
137 opts.context_lines = 3;
138 opts.interhunk_lines = 1;
139 opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
140
141 cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
5f69a31f 142 num_d = git_diff_num_deltas(diff);
1f35e89d 143
5f69a31f
RB
144 for (d = 0; d < num_d; ++d) {
145 git_diff_patch *patch;
bae957b9 146 const git_diff_delta *delta;
5f69a31f
RB
147
148 cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));
1f35e89d 149 cl_assert(delta);
5f69a31f 150 cl_assert(patch);
1f35e89d
RB
151
152 file_count++;
5f69a31f 153 hunk_count += git_diff_patch_num_hunks(patch);
1f35e89d
RB
154
155 assert(delta->binary == 0 || delta->binary == 1);
1f35e89d 156 binary_count += delta->binary;
1f35e89d 157
5f69a31f
RB
158 git_diff_patch_free(patch);
159 }
1f35e89d
RB
160
161 cl_assert_equal_i(13, file_count);
162 cl_assert_equal_i(0, binary_count);
163 cl_assert_equal_i(8, hunk_count);
164
1f35e89d
RB
165 git_diff_list_free(diff);
166
167 /* try again with low file size threshold */
168
5f69a31f 169 file_count = binary_count = hunk_count = 0;
1f35e89d
RB
170
171 opts.context_lines = 3;
172 opts.interhunk_lines = 1;
173 opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
174 opts.max_size = 50; /* treat anything over 50 bytes as binary! */
175
176 cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
5f69a31f 177 num_d = git_diff_num_deltas(diff);
1f35e89d 178
5f69a31f
RB
179 for (d = 0; d < num_d; ++d) {
180 git_diff_patch *patch;
bae957b9 181 const git_diff_delta *delta;
1f35e89d 182
5f69a31f 183 cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));
1f35e89d 184
5f69a31f
RB
185 file_count++;
186 hunk_count += git_diff_patch_num_hunks(patch);
1f35e89d
RB
187
188 assert(delta->binary == 0 || delta->binary == 1);
1f35e89d 189 binary_count += delta->binary;
1f35e89d 190
5f69a31f
RB
191 git_diff_patch_free(patch);
192 }
1f35e89d
RB
193
194 cl_assert_equal_i(13, file_count);
1f35e89d
RB
195 /* Three files are over the 50 byte threshold:
196 * - staged_changes_file_deleted
197 * - staged_changes_modified_file
198 * - staged_new_file_modified_file
199 */
200 cl_assert_equal_i(3, binary_count);
1f35e89d
RB
201 cl_assert_equal_i(5, hunk_count);
202
1f35e89d 203 git_diff_list_free(diff);
5f69a31f
RB
204}
205
206
207void test_diff_diffiter__iterate_all(void)
208{
209 git_repository *repo = cl_git_sandbox_init("status");
210 git_diff_options opts = {0};
211 git_diff_list *diff = NULL;
212 diff_expects exp = {0};
213 size_t d, num_d;
214
215 opts.context_lines = 3;
216 opts.interhunk_lines = 1;
217 opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
218
219 cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
220
221 num_d = git_diff_num_deltas(diff);
222 for (d = 0; d < num_d; ++d) {
223 git_diff_patch *patch;
bae957b9 224 const git_diff_delta *delta;
5f69a31f
RB
225 size_t h, num_h;
226
227 cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));
228 cl_assert(patch && delta);
229 exp.files++;
230
231 num_h = git_diff_patch_num_hunks(patch);
232 for (h = 0; h < num_h; h++) {
bae957b9 233 const git_diff_range *range;
5f69a31f
RB
234 const char *header;
235 size_t header_len, l, num_l;
236
237 cl_git_pass(git_diff_patch_get_hunk(
238 &range, &header, &header_len, &num_l, patch, h));
239 cl_assert(range && header);
240 exp.hunks++;
241
242 for (l = 0; l < num_l; ++l) {
243 char origin;
244 const char *content;
245 size_t content_len;
246
247 cl_git_pass(git_diff_patch_get_line_in_hunk(
248 &origin, &content, &content_len, NULL, NULL, patch, h, l));
249 cl_assert(content);
250 exp.lines++;
251 }
252 }
253
254 git_diff_patch_free(patch);
255 }
256
257 cl_assert_equal_i(13, exp.files);
258 cl_assert_equal_i(8, exp.hunks);
64286308 259 cl_assert_equal_i(14, exp.lines);
5f69a31f
RB
260
261 git_diff_list_free(diff);
262}
263
264static void iterate_over_patch(git_diff_patch *patch, diff_expects *exp)
265{
64286308 266 size_t h, num_h = git_diff_patch_num_hunks(patch), num_l;
5f69a31f
RB
267
268 exp->files++;
269 exp->hunks += num_h;
270
271 /* let's iterate in reverse, just because we can! */
64286308
RB
272 for (h = 1, num_l = 0; h <= num_h; ++h)
273 num_l += git_diff_patch_num_lines_in_hunk(patch, num_h - h);
274
275 exp->lines += num_l;
5f69a31f
RB
276}
277
278#define PATCH_CACHE 5
279
280void test_diff_diffiter__iterate_randomly_while_saving_state(void)
281{
282 git_repository *repo = cl_git_sandbox_init("status");
283 git_diff_options opts = {0};
284 git_diff_list *diff = NULL;
285 diff_expects exp = {0};
286 git_diff_patch *patches[PATCH_CACHE];
287 size_t p, d, num_d;
288
289 memset(patches, 0, sizeof(patches));
290
291 opts.context_lines = 3;
292 opts.interhunk_lines = 1;
293 opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
294
295 cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
296
297 num_d = git_diff_num_deltas(diff);
298
299 /* To make sure that references counts work for diff and patch objects,
300 * this generates patches and randomly caches them. Only when the patch
301 * is removed from the cache are hunks and lines counted. At the end,
302 * there are still patches in the cache, so free the diff and try to
303 * process remaining patches after the diff is freed.
304 */
305
306 srand(121212);
307 p = rand() % PATCH_CACHE;
308
309 for (d = 0; d < num_d; ++d) {
310 /* take old patch */
311 git_diff_patch *patch = patches[p];
312 patches[p] = NULL;
313
314 /* cache new patch */
315 cl_git_pass(git_diff_get_patch(&patches[p], NULL, diff, d));
316 cl_assert(patches[p] != NULL);
317
318 /* process old patch if non-NULL */
319 if (patch != NULL) {
320 iterate_over_patch(patch, &exp);
321 git_diff_patch_free(patch);
322 }
323
324 p = rand() % PATCH_CACHE;
325 }
326
327 /* free diff list now - refcounts should keep things safe */
328 git_diff_list_free(diff);
329
330 /* process remaining unprocessed patches */
331 for (p = 0; p < PATCH_CACHE; p++) {
332 git_diff_patch *patch = patches[p];
333
334 if (patch != NULL) {
335 iterate_over_patch(patch, &exp);
336 git_diff_patch_free(patch);
337 }
338 }
1f35e89d 339
5f69a31f
RB
340 /* hopefully it all still added up right */
341 cl_assert_equal_i(13, exp.files);
342 cl_assert_equal_i(8, exp.hunks);
64286308 343 cl_assert_equal_i(14, exp.lines);
1f35e89d 344}