]> git.proxmox.com Git - libgit2.git/blame - tests/threads/diff.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / tests / threads / diff.c
CommitLineData
40ed4990 1#include "clar_libgit2.h"
7d490872 2#include "thread_helpers.h"
40ed4990 3
905fb592
CMN
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
8a2834d3
RB
18static git_repository *_repo;
19static git_tree *_a, *_b;
c25aa7cd 20static git_atomic32 _counts[4];
8a2834d3 21static int _check_counts;
13c275ab 22#ifdef GIT_WIN32
7ece9065 23static int _retries;
13c275ab 24#endif
40ed4990 25
7d490872
RB
26#define THREADS 20
27
7ece9065
ET
28void test_threads_diff__initialize(void)
29{
48f09c6c 30#ifdef GIT_WIN32
7ece9065
ET
31 _retries = git_win32__retries;
32 git_win32__retries = 1;
48f09c6c 33#endif
7ece9065
ET
34}
35
40ed4990
RB
36void test_threads_diff__cleanup(void)
37{
38 cl_git_sandbox_cleanup();
48f09c6c
ET
39
40#ifdef GIT_WIN32
7ece9065 41 git_win32__retries = _retries;
48f09c6c 42#endif
40ed4990
RB
43}
44
40ed4990
RB
45static void setup_trees(void)
46{
ea642d61
RB
47 git_index *idx;
48
7d490872
RB
49 _repo = cl_git_sandbox_reopen(); /* reopen sandbox to flush caches */
50
ea642d61
RB
51 /* avoid competing to load initial index */
52 cl_git_pass(git_repository_index(&idx, _repo));
53 git_index_free(idx);
54
40ed4990 55 cl_git_pass(git_revparse_single(
8a2834d3 56 (git_object **)&_a, _repo, "0017bd4ab1^{tree}"));
40ed4990 57 cl_git_pass(git_revparse_single(
8a2834d3 58 (git_object **)&_b, _repo, "26a125ee1b^{tree}"));
40ed4990 59
8a2834d3 60 memset(_counts, 0, sizeof(_counts));
40ed4990
RB
61}
62
40ed4990
RB
63static void free_trees(void)
64{
8a2834d3
RB
65 git_tree_free(_a); _a = NULL;
66 git_tree_free(_b); _b = NULL;
67
68 if (_check_counts) {
c25aa7cd
PP
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]));
8a2834d3 73 }
40ed4990
RB
74}
75
76static void *run_index_diffs(void *arg)
77{
78 int thread = *(int *)arg;
ac3d33df 79 git_repository *repo;
40ed4990
RB
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
ac3d33df
JK
85 cl_git_pass(git_repository_open(&repo, git_repository_path(_repo)));
86
40ed4990
RB
87 switch (thread & 0x03) {
88 case 0: /* diff index to workdir */;
ac3d33df 89 cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts));
40ed4990
RB
90 break;
91 case 1: /* diff tree 'a' to index */;
ac3d33df 92 cl_git_pass(git_diff_tree_to_index(&diff, repo, _a, NULL, &opts));
40ed4990
RB
93 break;
94 case 2: /* diff tree 'b' to index */;
ac3d33df 95 cl_git_pass(git_diff_tree_to_index(&diff, repo, _b, NULL, &opts));
40ed4990
RB
96 break;
97 case 3: /* diff index to workdir (explicit index) */;
98 {
99 git_index *idx;
ac3d33df
JK
100 cl_git_pass(git_repository_index(&idx, repo));
101 cl_git_pass(git_diff_index_to_workdir(&diff, repo, idx, &opts));
40ed4990
RB
102 git_index_free(idx);
103 break;
104 }
105 }
106
40ed4990
RB
107 /* keep some diff stats to make sure results are as expected */
108
109 i = git_diff_num_deltas(diff);
c25aa7cd 110 git_atomic32_add(&_counts[0], (int32_t)i);
40ed4990
RB
111 exp[0] = (int)i;
112
113 while (i > 0) {
114 switch (git_diff_get_delta(diff, --i)->status) {
c25aa7cd
PP
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;
40ed4990
RB
118 default: break;
119 }
120 }
121
40ed4990
RB
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);
ac3d33df
JK
138 git_repository_free(repo);
139 git_error_clear();
40ed4990
RB
140
141 return arg;
142}
143
144void test_threads_diff__concurrent_diffs(void)
145{
8a2834d3
RB
146 _repo = cl_git_sandbox_init("status");
147 _check_counts = 1;
40ed4990
RB
148
149 run_in_parallel(
ea642d61 150 5, 32, run_index_diffs, setup_trees, free_trees);
40ed4990 151}
8a2834d3
RB
152
153static 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;
ac3d33df 159 git_repository *repo;
8a2834d3 160
ac3d33df
JK
161 cl_git_pass(git_repository_open(&repo, git_repository_path(_repo)));
162 cl_git_pass(git_repository_index(&idx, repo));
8a2834d3
RB
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
83038272 178 goto done;
8a2834d3
RB
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 */;
ac3d33df 185 cl_git_pass(git_diff_index_to_workdir(&diff, repo, idx, &opts));
8a2834d3
RB
186 break;
187 case 1: /* diff tree 'a' to index */;
ac3d33df 188 cl_git_pass(git_diff_tree_to_index(&diff, repo, _a, idx, &opts));
8a2834d3
RB
189 break;
190 case 2: /* diff tree 'b' to index */;
ac3d33df 191 cl_git_pass(git_diff_tree_to_index(&diff, repo, _b, idx, &opts));
8a2834d3
RB
192 break;
193 case 3: /* diff index to workdir reversed */;
194 opts.flags |= GIT_DIFF_REVERSE;
ac3d33df 195 cl_git_pass(git_diff_index_to_workdir(&diff, repo, idx, &opts));
8a2834d3
RB
196 break;
197 }
198
199 /* results will be unpredictable with index modifier thread running */
200
201 git_diff_free(diff);
83038272
RB
202
203done:
8a2834d3 204 git_index_free(idx);
ac3d33df
JK
205 git_repository_free(repo);
206 git_error_clear();
8a2834d3
RB
207
208 return arg;
209}
210
211void 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(
ea642d61 217 5, 16, run_index_diffs_with_modifier, setup_trees, free_trees);
8a2834d3 218}