|
Packit Service |
20376f |
#include "clar_libgit2.h"
|
|
Packit Service |
20376f |
#include "thread_helpers.h"
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
#ifdef GIT_THREADS
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
# if defined(GIT_WIN32)
|
|
Packit Service |
20376f |
# define git_thread_yield() Sleep(0)
|
|
Packit Service |
20376f |
# elif defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__DragonFly__)
|
|
Packit Service |
20376f |
# define git_thread_yield() pthread_yield()
|
|
Packit Service |
20376f |
# else
|
|
Packit Service |
20376f |
# define git_thread_yield() sched_yield()
|
|
Packit Service |
20376f |
# endif
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
#else
|
|
Packit Service |
20376f |
# define git_thread_yield() (void)0
|
|
Packit Service |
20376f |
#endif
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static git_repository *_repo;
|
|
Packit Service |
20376f |
static git_tree *_a, *_b;
|
|
Packit Service |
20376f |
static git_atomic _counts[4];
|
|
Packit Service |
20376f |
static int _check_counts;
|
|
Packit Service |
20376f |
#ifdef GIT_WIN32
|
|
Packit Service |
20376f |
static int _retries;
|
|
Packit Service |
20376f |
#endif
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
#define THREADS 20
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void test_threads_diff__initialize(void)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
#ifdef GIT_WIN32
|
|
Packit Service |
20376f |
_retries = git_win32__retries;
|
|
Packit Service |
20376f |
git_win32__retries = 1;
|
|
Packit Service |
20376f |
#endif
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void test_threads_diff__cleanup(void)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
cl_git_sandbox_cleanup();
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
#ifdef GIT_WIN32
|
|
Packit Service |
20376f |
git_win32__retries = _retries;
|
|
Packit Service |
20376f |
#endif
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void setup_trees(void)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_index *idx;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
_repo = cl_git_sandbox_reopen(); /* reopen sandbox to flush caches */
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* avoid competing to load initial index */
|
|
Packit Service |
20376f |
cl_git_pass(git_repository_index(&idx, _repo));
|
|
Packit Service |
20376f |
git_index_free(idx);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
cl_git_pass(git_revparse_single(
|
|
Packit Service |
20376f |
(git_object **)&_a, _repo, "0017bd4ab1^{tree}"));
|
|
Packit Service |
20376f |
cl_git_pass(git_revparse_single(
|
|
Packit Service |
20376f |
(git_object **)&_b, _repo, "26a125ee1b^{tree}"));
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
memset(_counts, 0, sizeof(_counts));
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void free_trees(void)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_tree_free(_a); _a = NULL;
|
|
Packit Service |
20376f |
git_tree_free(_b); _b = NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (_check_counts) {
|
|
Packit Service |
20376f |
cl_assert_equal_i(288, git_atomic_get(&_counts[0]));
|
|
Packit Service |
20376f |
cl_assert_equal_i(112, git_atomic_get(&_counts[1]));
|
|
Packit Service |
20376f |
cl_assert_equal_i( 80, git_atomic_get(&_counts[2]));
|
|
Packit Service |
20376f |
cl_assert_equal_i( 96, git_atomic_get(&_counts[3]));
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void *run_index_diffs(void *arg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int thread = *(int *)arg;
|
|
Packit Service |
20376f |
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
|
Packit Service |
20376f |
git_diff *diff = NULL;
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
int exp[4] = { 0, 0, 0, 0 };
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
switch (thread & 0x03) {
|
|
Packit Service |
20376f |
case 0: /* diff index to workdir */;
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_index_to_workdir(&diff, _repo, NULL, &opts));
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 1: /* diff tree 'a' to index */;
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_tree_to_index(&diff, _repo, _a, NULL, &opts));
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 2: /* diff tree 'b' to index */;
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_tree_to_index(&diff, _repo, _b, NULL, &opts));
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 3: /* diff index to workdir (explicit index) */;
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_index *idx;
|
|
Packit Service |
20376f |
cl_git_pass(git_repository_index(&idx, _repo));
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts));
|
|
Packit Service |
20376f |
git_index_free(idx);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* keep some diff stats to make sure results are as expected */
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
i = git_diff_num_deltas(diff);
|
|
Packit Service |
20376f |
git_atomic_add(&_counts[0], (int32_t)i);
|
|
Packit Service |
20376f |
exp[0] = (int)i;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
while (i > 0) {
|
|
Packit Service |
20376f |
switch (git_diff_get_delta(diff, --i)->status) {
|
|
Packit Service |
20376f |
case GIT_DELTA_MODIFIED: exp[1]++; git_atomic_inc(&_counts[1]); break;
|
|
Packit Service |
20376f |
case GIT_DELTA_ADDED: exp[2]++; git_atomic_inc(&_counts[2]); break;
|
|
Packit Service |
20376f |
case GIT_DELTA_DELETED: exp[3]++; git_atomic_inc(&_counts[3]); break;
|
|
Packit Service |
20376f |
default: break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
switch (thread & 0x03) {
|
|
Packit Service |
20376f |
case 0: case 3:
|
|
Packit Service |
20376f |
cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(4, exp[1]);
|
|
Packit Service |
20376f |
cl_assert_equal_i(0, exp[2]); cl_assert_equal_i(4, exp[3]);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 1:
|
|
Packit Service |
20376f |
cl_assert_equal_i(12, exp[0]); cl_assert_equal_i(3, exp[1]);
|
|
Packit Service |
20376f |
cl_assert_equal_i(7, exp[2]); cl_assert_equal_i(2, exp[3]);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 2:
|
|
Packit Service |
20376f |
cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(3, exp[1]);
|
|
Packit Service |
20376f |
cl_assert_equal_i(3, exp[2]); cl_assert_equal_i(2, exp[3]);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_diff_free(diff);
|
|
Packit Service |
20376f |
giterr_clear();
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return arg;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void test_threads_diff__concurrent_diffs(void)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
_repo = cl_git_sandbox_init("status");
|
|
Packit Service |
20376f |
_check_counts = 1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
run_in_parallel(
|
|
Packit Service |
20376f |
5, 32, run_index_diffs, setup_trees, free_trees);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void *run_index_diffs_with_modifier(void *arg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int thread = *(int *)arg;
|
|
Packit Service |
20376f |
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
|
Packit Service |
20376f |
git_diff *diff = NULL;
|
|
Packit Service |
20376f |
git_index *idx = NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
cl_git_pass(git_repository_index(&idx, _repo));
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* have first thread altering the index as we go */
|
|
Packit Service |
20376f |
if (thread == 0) {
|
|
Packit Service |
20376f |
int i;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
for (i = 0; i < 300; ++i) {
|
|
Packit Service |
20376f |
switch (i & 0x03) {
|
|
Packit Service |
20376f |
case 0: (void)git_index_add_bypath(idx, "new_file"); break;
|
|
Packit Service |
20376f |
case 1: (void)git_index_remove_bypath(idx, "modified_file"); break;
|
|
Packit Service |
20376f |
case 2: (void)git_index_remove_bypath(idx, "new_file"); break;
|
|
Packit Service |
20376f |
case 3: (void)git_index_add_bypath(idx, "modified_file"); break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
git_thread_yield();
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
goto done;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* only use explicit index in this test to prevent reloading */
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
switch (thread & 0x03) {
|
|
Packit Service |
20376f |
case 0: /* diff index to workdir */;
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts));
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 1: /* diff tree 'a' to index */;
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_tree_to_index(&diff, _repo, _a, idx, &opts));
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 2: /* diff tree 'b' to index */;
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_tree_to_index(&diff, _repo, _b, idx, &opts));
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
case 3: /* diff index to workdir reversed */;
|
|
Packit Service |
20376f |
opts.flags |= GIT_DIFF_REVERSE;
|
|
Packit Service |
20376f |
cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts));
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* results will be unpredictable with index modifier thread running */
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_diff_free(diff);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
done:
|
|
Packit Service |
20376f |
git_index_free(idx);
|
|
Packit Service |
20376f |
giterr_clear();
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return arg;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void test_threads_diff__with_concurrent_index_modified(void)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
_repo = cl_git_sandbox_init("status");
|
|
Packit Service |
20376f |
_check_counts = 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
run_in_parallel(
|
|
Packit Service |
20376f |
5, 16, run_index_diffs_with_modifier, setup_trees, free_trees);
|
|
Packit Service |
20376f |
}
|