diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/attr/file.c | 16 | ||||
-rw-r--r-- | tests/attr/lookup.c | 16 | ||||
-rw-r--r-- | tests/attr/repo.c | 9 | ||||
-rw-r--r-- | tests/clar_libgit2.h | 2 | ||||
-rw-r--r-- | tests/core/strmap.c | 72 | ||||
-rw-r--r-- | tests/core/vector.c | 15 | ||||
-rw-r--r-- | tests/diff/diff_helpers.c | 29 | ||||
-rw-r--r-- | tests/diff/iterator.c | 59 | ||||
-rw-r--r-- | tests/index/tests.c | 20 | ||||
-rw-r--r-- | tests/status/ignore.c | 6 | ||||
-rw-r--r-- | tests/threads/diff.c | 182 | ||||
-rw-r--r-- | tests/threads/iterator.c | 49 | ||||
-rw-r--r-- | tests/threads/refdb.c | 3 | ||||
-rw-r--r-- | tests/threads/thread_helpers.c | 44 | ||||
-rw-r--r-- | tests/threads/thread_helpers.h | 8 |
15 files changed, 417 insertions, 113 deletions
diff --git a/tests/attr/file.c b/tests/attr/file.c index 4eb1d22fe..1f4108c3c 100644 --- a/tests/attr/file.c +++ b/tests/attr/file.c @@ -11,9 +11,9 @@ void test_attr_file__simple_read(void) git_attr_assignment *assign; git_attr_rule *rule; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr0"))); - cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); + cl_assert_equal_s(cl_fixture("attr/attr0"), file->entry->path); cl_assert(file->rules.length == 1); rule = get_rule(0); @@ -37,9 +37,9 @@ void test_attr_file__match_variants(void) git_attr_rule *rule; git_attr_assignment *assign; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr1"))); - cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); + cl_assert_equal_s(cl_fixture("attr/attr1"), file->entry->path); cl_assert(file->rules.length == 10); /* let's do a thorough check of this rule, then just verify @@ -121,9 +121,9 @@ void test_attr_file__assign_variants(void) git_attr_rule *rule; git_attr_assignment *assign; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr2"))); - cl_assert_equal_s(cl_fixture("attr/attr2"), file->key + 2); + cl_assert_equal_s(cl_fixture("attr/attr2"), file->entry->path); cl_assert(file->rules.length == 11); check_one_assign(file, 0, 0, "pat0", "simple", EXPECT_TRUE, NULL); @@ -187,8 +187,8 @@ void test_attr_file__check_attr_examples(void) git_attr_rule *rule; git_attr_assignment *assign; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); - cl_assert_equal_s(cl_fixture("attr/attr3"), file->key + 2); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr3"))); + cl_assert_equal_s(cl_fixture("attr/attr3"), file->entry->path); cl_assert(file->rules.length == 3); rule = get_rule(0); diff --git a/tests/attr/lookup.c b/tests/attr/lookup.c index 200bdd2c7..030ea075d 100644 --- a/tests/attr/lookup.c +++ b/tests/attr/lookup.c @@ -9,8 +9,8 @@ void test_attr_lookup__simple(void) git_attr_path path; const char *value = NULL; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); - cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr0"))); + cl_assert_equal_s(cl_fixture("attr/attr0"), file->entry->path); cl_assert(file->rules.length == 1); cl_git_pass(git_attr_path__init(&path, "test", NULL)); @@ -129,8 +129,8 @@ void test_attr_lookup__match_variants(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); - cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr1"))); + cl_assert_equal_s(cl_fixture("attr/attr1"), file->entry->path); cl_assert(file->rules.length == 10); cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0", NULL)); @@ -190,7 +190,7 @@ void test_attr_lookup__assign_variants(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr2"))); cl_assert(file->rules.length == 11); run_test_cases(file, cases, 0); @@ -225,7 +225,7 @@ void test_attr_lookup__check_attr_examples(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr3"))); cl_assert(file->rules.length == 3); run_test_cases(file, cases, 0); @@ -250,9 +250,9 @@ void test_attr_lookup__from_buffer(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new(&file, 0, NULL, NULL)); + cl_git_pass(git_attr_file__new(&file, NULL, 0)); - cl_git_pass(git_attr_file__parse_buffer(NULL, NULL, "a* foo\nabc bar\n* baz", file)); + cl_git_pass(git_attr_file__parse_buffer(NULL, file, "a* foo\nabc bar\n* baz")); cl_assert(file->rules.length == 3); diff --git a/tests/attr/repo.c b/tests/attr/repo.c index 49cccdc5a..71dc7a5b5 100644 --- a/tests/attr/repo.c +++ b/tests/attr/repo.c @@ -68,9 +68,12 @@ void test_attr_repo__get_one(void) attr_check_expected(scan->expected, scan->expected_str, scan->attr, value); } - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/attributes")); - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitattributes")); - cl_assert(git_attr_cache__is_cached(g_repo, 0, "sub/.gitattributes")); + cl_assert(git_attr_cache__is_cached( + g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/attributes")); + cl_assert(git_attr_cache__is_cached( + g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitattributes")); + cl_assert(git_attr_cache__is_cached( + g_repo, GIT_ATTR_FILE__FROM_FILE, "sub/.gitattributes")); } void test_attr_repo__get_many(void) diff --git a/tests/clar_libgit2.h b/tests/clar_libgit2.h index c2489db38..d395bd66f 100644 --- a/tests/clar_libgit2.h +++ b/tests/clar_libgit2.h @@ -11,7 +11,7 @@ * * Use this wrapper around all `git_` library calls that return error codes! */ -#define cl_git_pass(expr) cl_git_pass_(expr, __FILE__, __LINE__) +#define cl_git_pass(expr) cl_git_pass_((expr), __FILE__, __LINE__) #define cl_git_pass_(expr, file, line) do { \ int _lg2_error; \ diff --git a/tests/core/strmap.c b/tests/core/strmap.c index f34a4f89f..a120f1feb 100644 --- a/tests/core/strmap.c +++ b/tests/core/strmap.c @@ -3,12 +3,22 @@ GIT__USE_STRMAP; +git_strmap *g_table; + +void test_core_strmap__initialize(void) +{ + cl_git_pass(git_strmap_alloc(&g_table)); + cl_assert(g_table != NULL); +} + +void test_core_strmap__cleanup(void) +{ + git_strmap_free(g_table); +} + void test_core_strmap__0(void) { - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - cl_assert(git_strmap_num_entries(table) == 0); - git_strmap_free(table); + cl_assert(git_strmap_num_entries(g_table) == 0); } static void insert_strings(git_strmap *table, int count) @@ -37,21 +47,17 @@ void test_core_strmap__1(void) { int i; char *str; - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - insert_strings(table, 20); + insert_strings(g_table, 20); - cl_assert(git_strmap_exists(table, "aaaaaaaaa")); - cl_assert(git_strmap_exists(table, "ggggggggg")); - cl_assert(!git_strmap_exists(table, "aaaaaaaab")); - cl_assert(!git_strmap_exists(table, "abcdefghi")); + cl_assert(git_strmap_exists(g_table, "aaaaaaaaa")); + cl_assert(git_strmap_exists(g_table, "ggggggggg")); + cl_assert(!git_strmap_exists(g_table, "aaaaaaaab")); + cl_assert(!git_strmap_exists(g_table, "abcdefghi")); i = 0; - git_strmap_foreach_value(table, str, { i++; free(str); }); + git_strmap_foreach_value(g_table, str, { i++; free(str); }); cl_assert(i == 20); - - git_strmap_free(table); } void test_core_strmap__2(void) @@ -59,44 +65,36 @@ void test_core_strmap__2(void) khiter_t pos; int i; char *str; - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - insert_strings(table, 20); + insert_strings(g_table, 20); - cl_assert(git_strmap_exists(table, "aaaaaaaaa")); - cl_assert(git_strmap_exists(table, "ggggggggg")); - cl_assert(!git_strmap_exists(table, "aaaaaaaab")); - cl_assert(!git_strmap_exists(table, "abcdefghi")); + cl_assert(git_strmap_exists(g_table, "aaaaaaaaa")); + cl_assert(git_strmap_exists(g_table, "ggggggggg")); + cl_assert(!git_strmap_exists(g_table, "aaaaaaaab")); + cl_assert(!git_strmap_exists(g_table, "abcdefghi")); - cl_assert(git_strmap_exists(table, "bbbbbbbbb")); - pos = git_strmap_lookup_index(table, "bbbbbbbbb"); - cl_assert(git_strmap_valid_index(table, pos)); - cl_assert_equal_s(git_strmap_value_at(table, pos), "bbbbbbbbb"); - free(git_strmap_value_at(table, pos)); - git_strmap_delete_at(table, pos); + cl_assert(git_strmap_exists(g_table, "bbbbbbbbb")); + pos = git_strmap_lookup_index(g_table, "bbbbbbbbb"); + cl_assert(git_strmap_valid_index(g_table, pos)); + cl_assert_equal_s(git_strmap_value_at(g_table, pos), "bbbbbbbbb"); + free(git_strmap_value_at(g_table, pos)); + git_strmap_delete_at(g_table, pos); - cl_assert(!git_strmap_exists(table, "bbbbbbbbb")); + cl_assert(!git_strmap_exists(g_table, "bbbbbbbbb")); i = 0; - git_strmap_foreach_value(table, str, { i++; free(str); }); + git_strmap_foreach_value(g_table, str, { i++; free(str); }); cl_assert(i == 19); - - git_strmap_free(table); } void test_core_strmap__3(void) { int i; char *str; - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - insert_strings(table, 10000); + insert_strings(g_table, 10000); i = 0; - git_strmap_foreach_value(table, str, { i++; free(str); }); + git_strmap_foreach_value(g_table, str, { i++; free(str); }); cl_assert(i == 10000); - - git_strmap_free(table); } diff --git a/tests/core/vector.c b/tests/core/vector.c index db52c004f..66f90b82b 100644 --- a/tests/core/vector.c +++ b/tests/core/vector.c @@ -190,8 +190,9 @@ void test_core_vector__5(void) git_vector_free(&x); } -static int remove_ones(const git_vector *v, size_t idx) +static int remove_ones(const git_vector *v, size_t idx, void *p) { + GIT_UNUSED(p); return (git_vector_get(v, idx) == (void *)0x001); } @@ -206,7 +207,7 @@ void test_core_vector__remove_matching(void) git_vector_insert(&x, (void*) 0x001); cl_assert(x.length == 1); - git_vector_remove_matching(&x, remove_ones); + git_vector_remove_matching(&x, remove_ones, NULL); cl_assert(x.length == 0); git_vector_insert(&x, (void*) 0x001); @@ -214,7 +215,7 @@ void test_core_vector__remove_matching(void) git_vector_insert(&x, (void*) 0x001); cl_assert(x.length == 3); - git_vector_remove_matching(&x, remove_ones); + git_vector_remove_matching(&x, remove_ones, NULL); cl_assert(x.length == 0); git_vector_insert(&x, (void*) 0x002); @@ -223,7 +224,7 @@ void test_core_vector__remove_matching(void) git_vector_insert(&x, (void*) 0x001); cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); + git_vector_remove_matching(&x, remove_ones, NULL); cl_assert(x.length == 2); git_vector_foreach(&x, i, compare) { @@ -238,7 +239,7 @@ void test_core_vector__remove_matching(void) git_vector_insert(&x, (void*) 0x001); cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); + git_vector_remove_matching(&x, remove_ones, NULL); cl_assert(x.length == 2); git_vector_foreach(&x, i, compare) { @@ -253,7 +254,7 @@ void test_core_vector__remove_matching(void) git_vector_insert(&x, (void*) 0x001); cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); + git_vector_remove_matching(&x, remove_ones, NULL); cl_assert(x.length == 2); git_vector_foreach(&x, i, compare) { @@ -268,7 +269,7 @@ void test_core_vector__remove_matching(void) git_vector_insert(&x, (void*) 0x003); cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); + git_vector_remove_matching(&x, remove_ones, NULL); cl_assert(x.length == 4); git_vector_free(&x); diff --git a/tests/diff/diff_helpers.c b/tests/diff/diff_helpers.c index 33bb561f6..279cb20c5 100644 --- a/tests/diff/diff_helpers.c +++ b/tests/diff/diff_helpers.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "diff_helpers.h" +#include "git2/sys/diff.h" git_tree *resolve_commit_oid_to_tree( git_repository *repo, @@ -215,32 +216,16 @@ abort: return GIT_EUSER; } -static int diff_print_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *payload) -{ - FILE *fp = payload; - - GIT_UNUSED(delta); GIT_UNUSED(hunk); - - if (line->origin == GIT_DIFF_LINE_CONTEXT || - line->origin == GIT_DIFF_LINE_ADDITION || - line->origin == GIT_DIFF_LINE_DELETION) - fputc(line->origin, fp); - fwrite(line->content, 1, line->content_len, fp); - return 0; -} - void diff_print(FILE *fp, git_diff *diff) { - cl_git_pass(git_diff_print( - diff, GIT_DIFF_FORMAT_PATCH, diff_print_cb, fp ? fp : stderr)); + cl_git_pass( + git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, + git_diff_print_callback__to_file_handle, fp ? fp : stderr)); } void diff_print_raw(FILE *fp, git_diff *diff) { - cl_git_pass(git_diff_print( - diff, GIT_DIFF_FORMAT_RAW, diff_print_cb, fp ? fp : stderr)); + cl_git_pass( + git_diff_print(diff, GIT_DIFF_FORMAT_RAW, + git_diff_print_callback__to_file_handle, fp ? fp : stderr)); } diff --git a/tests/diff/iterator.c b/tests/diff/iterator.c index 891d8a6e5..cdc64eb1d 100644 --- a/tests/diff/iterator.c +++ b/tests/diff/iterator.c @@ -355,6 +355,7 @@ static void index_iterator_test( const char *sandbox, const char *start, const char *end, + git_iterator_flag_t flags, int expected_count, const char **expected_names, const char **expected_oids) @@ -362,11 +363,13 @@ static void index_iterator_test( git_index *index; git_iterator *i; const git_index_entry *entry; - int error, count = 0; + int error, count = 0, caps; git_repository *repo = cl_git_sandbox_init(sandbox); cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_iterator_for_index(&i, index, 0, start, end)); + caps = git_index_caps(index); + + cl_git_pass(git_iterator_for_index(&i, index, flags, start, end)); while (!(error = git_iterator_advance(&entry, i))) { cl_assert(entry); @@ -388,6 +391,8 @@ static void index_iterator_test( cl_assert_equal_i(expected_count, count); git_iterator_free(i); + + cl_assert(caps == git_index_caps(index)); git_index_free(index); } @@ -446,7 +451,8 @@ static const char *expected_index_oids_0[] = { void test_diff_iterator__index_0(void) { index_iterator_test( - "attr", NULL, NULL, 23, expected_index_0, expected_index_oids_0); + "attr", NULL, NULL, 0, ARRAY_SIZE(expected_index_0), + expected_index_0, expected_index_oids_0); } static const char *expected_index_range[] = { @@ -466,25 +472,26 @@ static const char *expected_index_oids_range[] = { void test_diff_iterator__index_range(void) { index_iterator_test( - "attr", "root", "root", 4, expected_index_range, expected_index_oids_range); + "attr", "root", "root", 0, ARRAY_SIZE(expected_index_range), + expected_index_range, expected_index_oids_range); } void test_diff_iterator__index_range_empty_0(void) { index_iterator_test( - "attr", "empty", "empty", 0, NULL, NULL); + "attr", "empty", "empty", 0, 0, NULL, NULL); } void test_diff_iterator__index_range_empty_1(void) { index_iterator_test( - "attr", "z_empty_after", NULL, 0, NULL, NULL); + "attr", "z_empty_after", NULL, 0, 0, NULL, NULL); } void test_diff_iterator__index_range_empty_2(void) { index_iterator_test( - "attr", NULL, ".aaa_empty_before", 0, NULL, NULL); + "attr", NULL, ".aaa_empty_before", 0, 0, NULL, NULL); } static const char *expected_index_1[] = { @@ -522,9 +529,45 @@ static const char* expected_index_oids_1[] = { void test_diff_iterator__index_1(void) { index_iterator_test( - "status", NULL, NULL, 13, expected_index_1, expected_index_oids_1); + "status", NULL, NULL, 0, ARRAY_SIZE(expected_index_1), + expected_index_1, expected_index_oids_1); } +static const char *expected_index_cs[] = { + "B", "D", "F", "H", "J", "L/1", "L/B", "L/D", "L/a", "L/c", + "a", "c", "e", "g", "i", "k/1", "k/B", "k/D", "k/a", "k/c", +}; + +static const char *expected_index_ci[] = { + "a", "B", "c", "D", "e", "F", "g", "H", "i", "J", + "k/1", "k/a", "k/B", "k/c", "k/D", "L/1", "L/a", "L/B", "L/c", "L/D", +}; + +void test_diff_iterator__index_case_folding(void) +{ + git_buf path = GIT_BUF_INIT; + int fs_is_ci = 0; + + cl_git_pass(git_buf_joinpath(&path, cl_fixture("icase"), ".gitted/CoNfIg")); + fs_is_ci = git_path_exists(path.ptr); + git_buf_free(&path); + + index_iterator_test( + "icase", NULL, NULL, 0, ARRAY_SIZE(expected_index_cs), + fs_is_ci ? expected_index_ci : expected_index_cs, NULL); + + cl_git_sandbox_cleanup(); + + index_iterator_test( + "icase", NULL, NULL, GIT_ITERATOR_IGNORE_CASE, + ARRAY_SIZE(expected_index_ci), expected_index_ci, NULL); + + cl_git_sandbox_cleanup(); + + index_iterator_test( + "icase", NULL, NULL, GIT_ITERATOR_DONT_IGNORE_CASE, + ARRAY_SIZE(expected_index_cs), expected_index_cs, NULL); +} /* -- WORKDIR ITERATOR TESTS -- */ diff --git a/tests/index/tests.c b/tests/index/tests.c index 6e28af1f7..fa5c0bb1a 100644 --- a/tests/index/tests.c +++ b/tests/index/tests.c @@ -544,36 +544,22 @@ void test_index_tests__corrupted_extension(void) cl_git_fail_with(git_index_open(&index, TEST_INDEXBAD_PATH), GIT_ERROR); } -static void assert_index_is_sorted(git_index *index) -{ - git_vector *entries = &index->entries; - size_t i; - - cl_assert(git_vector_is_sorted(entries)); - - for (i = 1; i < git_vector_length(entries); ++i) { - git_index_entry *prev = git_vector_get(entries, i - 1); - git_index_entry *curr = git_vector_get(entries, i); - cl_assert(index->entries._cmp(prev, curr) <= 0); - } -} - void test_index_tests__reload_while_ignoring_case(void) { git_index *index; unsigned int caps; cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); - assert_index_is_sorted(index); + cl_git_pass(git_vector_verify_sorted(&index->entries)); caps = git_index_caps(index); cl_git_pass(git_index_set_caps(index, caps &= ~GIT_INDEXCAP_IGNORE_CASE)); cl_git_pass(git_index_read(index, true)); - assert_index_is_sorted(index); + cl_git_pass(git_vector_verify_sorted(&index->entries)); cl_git_pass(git_index_set_caps(index, caps | GIT_INDEXCAP_IGNORE_CASE)); cl_git_pass(git_index_read(index, true)); - assert_index_is_sorted(index); + cl_git_pass(git_vector_verify_sorted(&index->entries)); git_index_free(index); } diff --git a/tests/status/ignore.c b/tests/status/ignore.c index d6c26a847..052a8eae8 100644 --- a/tests/status/ignore.c +++ b/tests/status/ignore.c @@ -54,8 +54,10 @@ void test_status_ignore__0(void) } /* confirm that ignore files were cached */ - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/exclude")); - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitignore")); + cl_assert(git_attr_cache__is_cached( + g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/exclude")); + cl_assert(git_attr_cache__is_cached( + g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitignore")); } diff --git a/tests/threads/diff.c b/tests/threads/diff.c new file mode 100644 index 000000000..79b85800b --- /dev/null +++ b/tests/threads/diff.c @@ -0,0 +1,182 @@ +#include "clar_libgit2.h" +#include "thread_helpers.h" + +static git_repository *_repo; +static git_tree *_a, *_b; +static git_atomic _counts[4]; +static int _check_counts; + +#define THREADS 20 + +void test_threads_diff__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void setup_trees(void) +{ + git_index *idx; + + _repo = cl_git_sandbox_reopen(); /* reopen sandbox to flush caches */ + + /* avoid competing to load initial index */ + cl_git_pass(git_repository_index(&idx, _repo)); + git_index_free(idx); + + cl_git_pass(git_revparse_single( + (git_object **)&_a, _repo, "0017bd4ab1^{tree}")); + cl_git_pass(git_revparse_single( + (git_object **)&_b, _repo, "26a125ee1b^{tree}")); + + memset(_counts, 0, sizeof(_counts)); +} + +static void free_trees(void) +{ + git_tree_free(_a); _a = NULL; + git_tree_free(_b); _b = NULL; + + if (_check_counts) { + cl_assert_equal_i(288, git_atomic_get(&_counts[0])); + cl_assert_equal_i(112, git_atomic_get(&_counts[1])); + cl_assert_equal_i( 80, git_atomic_get(&_counts[2])); + cl_assert_equal_i( 96, git_atomic_get(&_counts[3])); + } +} + +static void *run_index_diffs(void *arg) +{ + int thread = *(int *)arg; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + size_t i; + int exp[4] = { 0, 0, 0, 0 }; + + switch (thread & 0x03) { + case 0: /* diff index to workdir */; + cl_git_pass(git_diff_index_to_workdir(&diff, _repo, NULL, &opts)); + break; + case 1: /* diff tree 'a' to index */; + cl_git_pass(git_diff_tree_to_index(&diff, _repo, _a, NULL, &opts)); + break; + case 2: /* diff tree 'b' to index */; + cl_git_pass(git_diff_tree_to_index(&diff, _repo, _b, NULL, &opts)); + break; + case 3: /* diff index to workdir (explicit index) */; + { + git_index *idx; + cl_git_pass(git_repository_index(&idx, _repo)); + cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts)); + git_index_free(idx); + break; + } + } + + /* keep some diff stats to make sure results are as expected */ + + i = git_diff_num_deltas(diff); + git_atomic_add(&_counts[0], (int32_t)i); + exp[0] = (int)i; + + while (i > 0) { + switch (git_diff_get_delta(diff, --i)->status) { + case GIT_DELTA_MODIFIED: exp[1]++; git_atomic_inc(&_counts[1]); break; + case GIT_DELTA_ADDED: exp[2]++; git_atomic_inc(&_counts[2]); break; + case GIT_DELTA_DELETED: exp[3]++; git_atomic_inc(&_counts[3]); break; + default: break; + } + } + + switch (thread & 0x03) { + case 0: case 3: + cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(4, exp[1]); + cl_assert_equal_i(0, exp[2]); cl_assert_equal_i(4, exp[3]); + break; + case 1: + cl_assert_equal_i(12, exp[0]); cl_assert_equal_i(3, exp[1]); + cl_assert_equal_i(7, exp[2]); cl_assert_equal_i(2, exp[3]); + break; + case 2: + cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(3, exp[1]); + cl_assert_equal_i(3, exp[2]); cl_assert_equal_i(2, exp[3]); + break; + } + + git_diff_free(diff); + giterr_clear(); + + return arg; +} + +void test_threads_diff__concurrent_diffs(void) +{ + _repo = cl_git_sandbox_init("status"); + _check_counts = 1; + + run_in_parallel( + 5, 32, run_index_diffs, setup_trees, free_trees); +} + +static void *run_index_diffs_with_modifier(void *arg) +{ + int thread = *(int *)arg; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_index *idx = NULL; + + cl_git_pass(git_repository_index(&idx, _repo)); + + /* have first thread altering the index as we go */ + if (thread == 0) { + int i; + + for (i = 0; i < 300; ++i) { + switch (i & 0x03) { + case 0: (void)git_index_add_bypath(idx, "new_file"); break; + case 1: (void)git_index_remove_bypath(idx, "modified_file"); break; + case 2: (void)git_index_remove_bypath(idx, "new_file"); break; + case 3: (void)git_index_add_bypath(idx, "modified_file"); break; + } + git_thread_yield(); + } + + goto done; + } + + /* only use explicit index in this test to prevent reloading */ + + switch (thread & 0x03) { + case 0: /* diff index to workdir */; + cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts)); + break; + case 1: /* diff tree 'a' to index */; + cl_git_pass(git_diff_tree_to_index(&diff, _repo, _a, idx, &opts)); + break; + case 2: /* diff tree 'b' to index */; + cl_git_pass(git_diff_tree_to_index(&diff, _repo, _b, idx, &opts)); + break; + case 3: /* diff index to workdir reversed */; + opts.flags |= GIT_DIFF_REVERSE; + cl_git_pass(git_diff_index_to_workdir(&diff, _repo, idx, &opts)); + break; + } + + /* results will be unpredictable with index modifier thread running */ + + git_diff_free(diff); + +done: + git_index_free(idx); + giterr_clear(); + + return arg; +} + +void test_threads_diff__with_concurrent_index_modified(void) +{ + _repo = cl_git_sandbox_init("status"); + _check_counts = 0; + + run_in_parallel( + 5, 16, run_index_diffs_with_modifier, setup_trees, free_trees); +} diff --git a/tests/threads/iterator.c b/tests/threads/iterator.c new file mode 100644 index 000000000..8aeae1a6c --- /dev/null +++ b/tests/threads/iterator.c @@ -0,0 +1,49 @@ +#include "clar_libgit2.h" +#include "thread_helpers.h" +#include "iterator.h" + +static git_repository *_repo; + +void test_threads_iterator__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void *run_workdir_iterator(void *arg) +{ + int error = 0; + git_iterator *iter; + const git_index_entry *entry = NULL; + + cl_git_pass(git_iterator_for_workdir( + &iter, _repo, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); + + while (!error) { + if (entry && entry->mode == GIT_FILEMODE_TREE) { + error = git_iterator_advance_into(&entry, iter); + + if (error == GIT_ENOTFOUND) + error = git_iterator_advance(&entry, iter); + } else { + error = git_iterator_advance(&entry, iter); + } + + if (!error) + (void)git_iterator_current_is_ignored(iter); + } + + cl_assert_equal_i(GIT_ITEROVER, error); + + git_iterator_free(iter); + giterr_clear(); + return arg; +} + + +void test_threads_iterator__workdir(void) +{ + _repo = cl_git_sandbox_init("status"); + + run_in_parallel( + 1, 20, run_workdir_iterator, NULL, NULL); +} diff --git a/tests/threads/refdb.c b/tests/threads/refdb.c index fbf6ac09b..3b35b45e3 100644 --- a/tests/threads/refdb.c +++ b/tests/threads/refdb.c @@ -37,6 +37,7 @@ static void *iterate_refs(void *arg) git_reference_iterator_free(i); + giterr_clear(); return arg; } @@ -115,6 +116,7 @@ static void *create_refs(void *arg) for (i = 0; i < 10; ++i) git_reference_free(ref[i]); + giterr_clear(); return arg; } @@ -141,6 +143,7 @@ static void *delete_refs(void *arg) } } + giterr_clear(); return arg; } diff --git a/tests/threads/thread_helpers.c b/tests/threads/thread_helpers.c new file mode 100644 index 000000000..25370dddb --- /dev/null +++ b/tests/threads/thread_helpers.c @@ -0,0 +1,44 @@ +#include "clar_libgit2.h" +#include "thread_helpers.h" + +void run_in_parallel( + int repeats, + int threads, + void *(*func)(void *), + void (*before_test)(void), + void (*after_test)(void)) +{ + int r, t, *id = git__calloc(threads, sizeof(int)); +#ifdef GIT_THREADS + git_thread *th = git__calloc(threads, sizeof(git_thread)); + cl_assert(th != NULL); +#else + void *th = NULL; +#endif + + cl_assert(id != NULL); + + for (r = 0; r < repeats; ++r) { + if (before_test) before_test(); + + for (t = 0; t < threads; ++t) { + id[t] = t; +#ifdef GIT_THREADS + cl_git_pass(git_thread_create(&th[t], NULL, func, &id[t])); +#else + cl_assert(func(&id[t]) == &id[t]); +#endif + } + +#ifdef GIT_THREADS + for (t = 0; t < threads; ++t) + cl_git_pass(git_thread_join(th[t], NULL)); + memset(th, 0, threads * sizeof(git_thread)); +#endif + + if (after_test) after_test(); + } + + git__free(id); + git__free(th); +} diff --git a/tests/threads/thread_helpers.h b/tests/threads/thread_helpers.h new file mode 100644 index 000000000..3c13cfb6b --- /dev/null +++ b/tests/threads/thread_helpers.h @@ -0,0 +1,8 @@ +#include "thread-utils.h" + +void run_in_parallel( + int repeats, + int threads, + void *(*func)(void *), + void (*before_test)(void), + void (*after_test)(void)); |