]> git.proxmox.com Git - libgit2.git/blame - tests/threads/diff.c
libgit2 v0.21.0
[libgit2.git] / tests / threads / diff.c
CommitLineData
40ed4990 1#include "clar_libgit2.h"
7d490872 2#include "thread_helpers.h"
40ed4990 3
8a2834d3
RB
4static git_repository *_repo;
5static git_tree *_a, *_b;
6static git_atomic _counts[4];
7static int _check_counts;
40ed4990 8
7d490872
RB
9#define THREADS 20
10
40ed4990
RB
11void test_threads_diff__cleanup(void)
12{
13 cl_git_sandbox_cleanup();
14}
15
40ed4990
RB
16static void setup_trees(void)
17{
ea642d61
RB
18 git_index *idx;
19
7d490872
RB
20 _repo = cl_git_sandbox_reopen(); /* reopen sandbox to flush caches */
21
ea642d61
RB
22 /* avoid competing to load initial index */
23 cl_git_pass(git_repository_index(&idx, _repo));
24 git_index_free(idx);
25
40ed4990 26 cl_git_pass(git_revparse_single(
8a2834d3 27 (git_object **)&_a, _repo, "0017bd4ab1^{tree}"));
40ed4990 28 cl_git_pass(git_revparse_single(
8a2834d3 29 (git_object **)&_b, _repo, "26a125ee1b^{tree}"));
40ed4990 30
8a2834d3 31 memset(_counts, 0, sizeof(_counts));
40ed4990
RB
32}
33
40ed4990
RB
34static void free_trees(void)
35{
8a2834d3
RB
36 git_tree_free(_a); _a = NULL;
37 git_tree_free(_b); _b = NULL;
38
39 if (_check_counts) {
40 cl_assert_equal_i(288, git_atomic_get(&_counts[0]));
41 cl_assert_equal_i(112, git_atomic_get(&_counts[1]));
42 cl_assert_equal_i( 80, git_atomic_get(&_counts[2]));
43 cl_assert_equal_i( 96, git_atomic_get(&_counts[3]));
44 }
40ed4990
RB
45}
46
47static void *run_index_diffs(void *arg)
48{
49 int thread = *(int *)arg;
50 git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
51 git_diff *diff = NULL;
52 size_t i;
53 int exp[4] = { 0, 0, 0, 0 };
54
40ed4990
RB
55 switch (thread & 0x03) {
56 case 0: /* diff index to workdir */;
8a2834d3 57 cl_git_pass(git_diff_index_to_workdir(&diff, _repo, NULL, &opts));
40ed4990
RB
58 break;
59 case 1: /* diff tree 'a' to index */;
8a2834d3 60 cl_git_pass(git_diff_tree_to_index(&diff, _repo, _a, NULL, &opts));
40ed4990
RB
61 break;
62 case 2: /* diff tree 'b' to index */;
8a2834d3 63 cl_git_pass(git_diff_tree_to_index(&diff, _repo, _b, NULL, &opts));
40ed4990
RB
64 break;
65 case 3: /* diff index to workdir (explicit index) */;
66 {
67 git_index *idx;
8a2834d3
RB
68 cl_git_pass(git_repository_index(&idx, _repo));
69 cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts));
40ed4990
RB
70 git_index_free(idx);
71 break;
72 }
73 }
74
40ed4990
RB
75 /* keep some diff stats to make sure results are as expected */
76
77 i = git_diff_num_deltas(diff);
8a2834d3 78 git_atomic_add(&_counts[0], (int32_t)i);
40ed4990
RB
79 exp[0] = (int)i;
80
81 while (i > 0) {
82 switch (git_diff_get_delta(diff, --i)->status) {
8a2834d3
RB
83 case GIT_DELTA_MODIFIED: exp[1]++; git_atomic_inc(&_counts[1]); break;
84 case GIT_DELTA_ADDED: exp[2]++; git_atomic_inc(&_counts[2]); break;
85 case GIT_DELTA_DELETED: exp[3]++; git_atomic_inc(&_counts[3]); break;
40ed4990
RB
86 default: break;
87 }
88 }
89
40ed4990
RB
90 switch (thread & 0x03) {
91 case 0: case 3:
92 cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(4, exp[1]);
93 cl_assert_equal_i(0, exp[2]); cl_assert_equal_i(4, exp[3]);
94 break;
95 case 1:
96 cl_assert_equal_i(12, exp[0]); cl_assert_equal_i(3, exp[1]);
97 cl_assert_equal_i(7, exp[2]); cl_assert_equal_i(2, exp[3]);
98 break;
99 case 2:
100 cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(3, exp[1]);
101 cl_assert_equal_i(3, exp[2]); cl_assert_equal_i(2, exp[3]);
102 break;
103 }
104
105 git_diff_free(diff);
83038272 106 giterr_clear();
40ed4990
RB
107
108 return arg;
109}
110
111void test_threads_diff__concurrent_diffs(void)
112{
8a2834d3
RB
113 _repo = cl_git_sandbox_init("status");
114 _check_counts = 1;
40ed4990
RB
115
116 run_in_parallel(
ea642d61 117 5, 32, run_index_diffs, setup_trees, free_trees);
40ed4990 118}
8a2834d3
RB
119
120static void *run_index_diffs_with_modifier(void *arg)
121{
122 int thread = *(int *)arg;
123 git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
124 git_diff *diff = NULL;
125 git_index *idx = NULL;
126
127 cl_git_pass(git_repository_index(&idx, _repo));
128
129 /* have first thread altering the index as we go */
130 if (thread == 0) {
131 int i;
132
133 for (i = 0; i < 300; ++i) {
134 switch (i & 0x03) {
135 case 0: (void)git_index_add_bypath(idx, "new_file"); break;
136 case 1: (void)git_index_remove_bypath(idx, "modified_file"); break;
137 case 2: (void)git_index_remove_bypath(idx, "new_file"); break;
138 case 3: (void)git_index_add_bypath(idx, "modified_file"); break;
139 }
140 git_thread_yield();
141 }
142
83038272 143 goto done;
8a2834d3
RB
144 }
145
146 /* only use explicit index in this test to prevent reloading */
147
148 switch (thread & 0x03) {
149 case 0: /* diff index to workdir */;
150 cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts));
151 break;
152 case 1: /* diff tree 'a' to index */;
153 cl_git_pass(git_diff_tree_to_index(&diff, _repo, _a, idx, &opts));
154 break;
155 case 2: /* diff tree 'b' to index */;
156 cl_git_pass(git_diff_tree_to_index(&diff, _repo, _b, idx, &opts));
157 break;
158 case 3: /* diff index to workdir reversed */;
159 opts.flags |= GIT_DIFF_REVERSE;
160 cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts));
161 break;
162 }
163
164 /* results will be unpredictable with index modifier thread running */
165
166 git_diff_free(diff);
83038272
RB
167
168done:
8a2834d3 169 git_index_free(idx);
83038272 170 giterr_clear();
8a2834d3
RB
171
172 return arg;
173}
174
175void test_threads_diff__with_concurrent_index_modified(void)
176{
177 _repo = cl_git_sandbox_init("status");
178 _check_counts = 0;
179
180 run_in_parallel(
ea642d61 181 5, 16, run_index_diffs_with_modifier, setup_trees, free_trees);
8a2834d3 182}