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