]>
Commit | Line | Data |
---|---|---|
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 |
18 | static git_repository *_repo; |
19 | static git_tree *_a, *_b; | |
c25aa7cd | 20 | static git_atomic32 _counts[4]; |
8a2834d3 | 21 | static int _check_counts; |
13c275ab | 22 | #ifdef GIT_WIN32 |
7ece9065 | 23 | static int _retries; |
13c275ab | 24 | #endif |
40ed4990 | 25 | |
7d490872 RB |
26 | #define THREADS 20 |
27 | ||
7ece9065 ET |
28 | void 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 |
36 | void 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 |
45 | static 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 |
63 | static 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 | ||
76 | static 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 | ||
144 | void 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 | |
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; | |
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 | |
203 | done: | |
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 | ||
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( | |
ea642d61 | 217 | 5, 16, run_index_diffs_with_modifier, setup_trees, free_trees); |
8a2834d3 | 218 | } |