diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/checkout/icase.c | 2 | ||||
| -rw-r--r-- | tests/clar_libgit2_timer.c | 31 | ||||
| -rw-r--r-- | tests/clar_libgit2_timer.h | 35 | ||||
| -rw-r--r-- | tests/clar_libgit2_trace.c | 229 | ||||
| -rw-r--r-- | tests/clar_libgit2_trace.h | 7 | ||||
| -rw-r--r-- | tests/core/ftruncate.c | 48 | ||||
| -rw-r--r-- | tests/diff/rename.c | 100 | ||||
| -rw-r--r-- | tests/filter/file.c | 97 | ||||
| -rw-r--r-- | tests/index/tests.c | 122 | ||||
| -rw-r--r-- | tests/main.c | 4 | ||||
| -rw-r--r-- | tests/online/clone.c | 7 | ||||
| -rw-r--r-- | tests/online/fetch.c | 6 | ||||
| -rw-r--r-- | tests/refs/branches/create.c | 18 | ||||
| -rw-r--r-- | tests/refs/branches/move.c | 6 | ||||
| -rw-r--r-- | tests/repo/head.c | 8 | ||||
| -rw-r--r-- | tests/repo/new.c | 27 | ||||
| -rw-r--r-- | tests/repo/reservedname.c | 108 | ||||
| -rw-r--r-- | tests/reset/hard.c | 13 | ||||
| -rw-r--r-- | tests/reset/mixed.c | 12 | ||||
| -rw-r--r-- | tests/reset/reset_helpers.c | 2 | ||||
| -rw-r--r-- | tests/reset/soft.c | 33 | ||||
| -rw-r--r-- | tests/submodule/modify.c | 6 | ||||
| -rw-r--r-- | tests/trace/trace.c | 19 |
23 files changed, 913 insertions, 27 deletions
diff --git a/tests/checkout/icase.c b/tests/checkout/icase.c index 3a6ce2078..211738070 100644 --- a/tests/checkout/icase.c +++ b/tests/checkout/icase.c @@ -4,7 +4,7 @@ #include "path.h" #ifdef GIT_WIN32 -# include <Windows.h> +# include <windows.h> #endif static git_repository *repo; diff --git a/tests/clar_libgit2_timer.c b/tests/clar_libgit2_timer.c new file mode 100644 index 000000000..737506da2 --- /dev/null +++ b/tests/clar_libgit2_timer.c @@ -0,0 +1,31 @@ +#include "clar_libgit2.h" +#include "clar_libgit2_timer.h" +#include "buffer.h" + +void cl_perf_timer__init(cl_perf_timer *t) +{ + memset(t, 0, sizeof(cl_perf_timer)); +} + +void cl_perf_timer__start(cl_perf_timer *t) +{ + t->time_started = git__timer(); +} + +void cl_perf_timer__stop(cl_perf_timer *t) +{ + double time_now = git__timer(); + + t->last = time_now - t->time_started; + t->sum += t->last; +} + +double cl_perf_timer__last(const cl_perf_timer *t) +{ + return t->last; +} + +double cl_perf_timer__sum(const cl_perf_timer *t) +{ + return t->sum; +} diff --git a/tests/clar_libgit2_timer.h b/tests/clar_libgit2_timer.h new file mode 100644 index 000000000..0d150e018 --- /dev/null +++ b/tests/clar_libgit2_timer.h @@ -0,0 +1,35 @@ +#ifndef __CLAR_LIBGIT2_TIMER__ +#define __CLAR_LIBGIT2_TIMER__ + +struct cl_perf_timer +{ + /* cummulative running time across all start..stop intervals */ + double sum; + + /* value of last start..stop interval */ + double last; + + /* clock value at start */ + double time_started; +}; + +#define CL_PERF_TIMER_INIT {0} + +typedef struct cl_perf_timer cl_perf_timer; + +void cl_perf_timer__init(cl_perf_timer *t); +void cl_perf_timer__start(cl_perf_timer *t); +void cl_perf_timer__stop(cl_perf_timer *t); + +/** + * return value of last start..stop interval in seconds. + */ +double cl_perf_timer__last(const cl_perf_timer *t); + +/** + * return cummulative running time across all start..stop + * intervals in seconds. + */ +double cl_perf_timer__sum(const cl_perf_timer *t); + +#endif /* __CLAR_LIBGIT2_TIMER__ */ diff --git a/tests/clar_libgit2_trace.c b/tests/clar_libgit2_trace.c new file mode 100644 index 000000000..ae582d1cb --- /dev/null +++ b/tests/clar_libgit2_trace.c @@ -0,0 +1,229 @@ +#include "clar_libgit2.h" +#include "clar_libgit2_trace.h" +#include "clar_libgit2_timer.h" +#include "trace.h" + + +struct method { + const char *name; + void (*git_trace_cb)(git_trace_level_t level, const char *msg); + void (*close)(void); +}; + + +#if defined(GIT_TRACE) +static void _git_trace_cb__printf(git_trace_level_t level, const char *msg) +{ + /* TODO Use level to print a per-message prefix. */ + GIT_UNUSED(level); + + printf("%s\n", msg); +} + +#if defined(GIT_WIN32) +static void _git_trace_cb__debug(git_trace_level_t level, const char *msg) +{ + /* TODO Use level to print a per-message prefix. */ + GIT_UNUSED(level); + + OutputDebugString(msg); + OutputDebugString("\n"); + + printf("%s\n", msg); +} +#else +#define _git_trace_cb__debug _git_trace_cb__printf +#endif + + +static void _trace_printf_close(void) +{ + fflush(stdout); +} + +#define _trace_debug_close _trace_printf_close + + +static struct method s_methods[] = { + { "printf", _git_trace_cb__printf, _trace_printf_close }, + { "debug", _git_trace_cb__debug, _trace_debug_close }, + /* TODO add file method */ + {0}, +}; + + +static int s_trace_loaded = 0; +static int s_trace_level = GIT_TRACE_NONE; +static struct method *s_trace_method = NULL; + + +static int set_method(const char *name) +{ + int k; + + if (!name || !*name) + name = "printf"; + + for (k=0; (s_methods[k].name); k++) { + if (strcmp(name, s_methods[k].name) == 0) { + s_trace_method = &s_methods[k]; + return 0; + } + } + fprintf(stderr, "Unknown CLAR_TRACE_METHOD: '%s'\n", name); + return -1; +} + + +/** + * Lookup CLAR_TRACE_LEVEL and CLAR_TRACE_METHOD from + * the environment and set the above s_trace_* fields. + * + * If CLAR_TRACE_LEVEL is not set, we disable tracing. + * + * TODO If set, we assume GIT_TRACE_TRACE level, which + * logs everything. Later, we may want to parse the + * value of the environment variable and set a specific + * level. + * + * We assume the "printf" method. This can be changed + * with the CLAR_TRACE_METHOD environment variable. + * Currently, this is only needed on Windows for a "debug" + * version which also writes to the debug output window + * in Visual Studio. + * + * TODO add a "file" method that would open and write + * to a well-known file. This would help keep trace + * output and clar output separate. + * + */ +static void _load_trace_params(void) +{ + char *sz_level; + char *sz_method; + + s_trace_loaded = 1; + + sz_level = cl_getenv("CLAR_TRACE_LEVEL"); + if (!sz_level || !*sz_level) { + s_trace_level = GIT_TRACE_NONE; + s_trace_method = NULL; + return; + } + + /* TODO Parse sz_level and set s_trace_level. */ + s_trace_level = GIT_TRACE_TRACE; + + sz_method = cl_getenv("CLAR_TRACE_METHOD"); + if (set_method(sz_method) < 0) + set_method(NULL); +} + +#define HR "================================================================" + +/** + * Timer to report the take spend in a test's run() method. + */ +static cl_perf_timer s_timer_run = CL_PERF_TIMER_INIT; + +/** + * Timer to report total time in a test (init, run, cleanup). + */ +static cl_perf_timer s_timer_test = CL_PERF_TIMER_INIT; + +void _cl_trace_cb__event_handler( + cl_trace_event ev, + const char *suite_name, + const char *test_name, + void *payload) +{ + GIT_UNUSED(payload); + + switch (ev) { + case CL_TRACE__SUITE_BEGIN: + git_trace(GIT_TRACE_TRACE, "\n\n%s\n%s: Begin Suite", HR, suite_name); + break; + + case CL_TRACE__SUITE_END: + git_trace(GIT_TRACE_TRACE, "\n\n%s: End Suite\n%s", suite_name, HR); + break; + + case CL_TRACE__TEST__BEGIN: + git_trace(GIT_TRACE_TRACE, "\n%s::%s: Begin Test", suite_name, test_name); + cl_perf_timer__init(&s_timer_test); + cl_perf_timer__start(&s_timer_test); + break; + + case CL_TRACE__TEST__END: + cl_perf_timer__stop(&s_timer_test); + git_trace(GIT_TRACE_TRACE, "%s::%s: End Test (%.3f %.3f)", suite_name, test_name, + cl_perf_timer__last(&s_timer_run), + cl_perf_timer__last(&s_timer_test)); + break; + + case CL_TRACE__TEST__RUN_BEGIN: + git_trace(GIT_TRACE_TRACE, "%s::%s: Begin Run", suite_name, test_name); + cl_perf_timer__init(&s_timer_run); + cl_perf_timer__start(&s_timer_run); + break; + + case CL_TRACE__TEST__RUN_END: + cl_perf_timer__stop(&s_timer_run); + git_trace(GIT_TRACE_TRACE, "%s::%s: End Run", suite_name, test_name); + break; + + case CL_TRACE__TEST__LONGJMP: + cl_perf_timer__stop(&s_timer_run); + git_trace(GIT_TRACE_TRACE, "%s::%s: Aborted", suite_name, test_name); + break; + + default: + break; + } +} + +#endif /*GIT_TRACE*/ + +/** + * Setup/Enable git_trace() based upon settings user's environment. + * + */ +void cl_global_trace_register(void) +{ +#if defined(GIT_TRACE) + if (!s_trace_loaded) + _load_trace_params(); + + if (s_trace_level == GIT_TRACE_NONE) + return; + if (s_trace_method == NULL) + return; + if (s_trace_method->git_trace_cb == NULL) + return; + + git_trace_set(s_trace_level, s_trace_method->git_trace_cb); + cl_trace_register(_cl_trace_cb__event_handler, NULL); +#endif +} + +/** + * If we turned on git_trace() earlier, turn it off. + * + * This is intended to let us close/flush any buffered + * IO if necessary. + * + */ +void cl_global_trace_disable(void) +{ +#if defined(GIT_TRACE) + cl_trace_register(NULL, NULL); + git_trace_set(GIT_TRACE_NONE, NULL); + if (s_trace_method && s_trace_method->close) + s_trace_method->close(); + + /* Leave s_trace_ vars set so they can restart tracing + * since we only want to hit the environment variables + * once. + */ +#endif +} diff --git a/tests/clar_libgit2_trace.h b/tests/clar_libgit2_trace.h new file mode 100644 index 000000000..09d1e050f --- /dev/null +++ b/tests/clar_libgit2_trace.h @@ -0,0 +1,7 @@ +#ifndef __CLAR_LIBGIT2_TRACE__ +#define __CLAR_LIBGIT2_TRACE__ + +void cl_global_trace_register(void); +void cl_global_trace_disable(void); + +#endif diff --git a/tests/core/ftruncate.c b/tests/core/ftruncate.c new file mode 100644 index 000000000..21981d677 --- /dev/null +++ b/tests/core/ftruncate.c @@ -0,0 +1,48 @@ +/** + * Some tests for p_ftruncate() to ensure that + * properly handles large (2Gb+) files. + */ + +#include "clar_libgit2.h" + +static const char *filename = "core_ftruncate.txt"; +static int fd = -1; + +void test_core_ftruncate__initialize(void) +{ + if (!cl_getenv("GITTEST_INVASIVE_FS_SIZE")) + cl_skip(); + + cl_must_pass((fd = p_open(filename, O_CREAT | O_RDWR, 0644))); +} + +void test_core_ftruncate__cleanup(void) +{ + if (fd < 0) + return; + + p_close(fd); + fd = 0; + + p_unlink(filename); +} + +static void _extend(git_off_t i64len) +{ + struct stat st; + int error; + + cl_assert((error = p_ftruncate(fd, i64len)) == 0); + cl_assert((error = p_fstat(fd, &st)) == 0); + cl_assert(st.st_size == i64len); +} + +void test_core_ftruncate__2gb(void) +{ + _extend(0x80000001); +} + +void test_core_ftruncate__4gb(void) +{ + _extend(0x100000001); +} diff --git a/tests/diff/rename.c b/tests/diff/rename.c index fe31a4128..8a327f035 100644 --- a/tests/diff/rename.c +++ b/tests/diff/rename.c @@ -1602,3 +1602,103 @@ void test_diff_rename__by_config_doesnt_mess_with_whitespace_settings(void) git_tree_free(tree1); git_tree_free(tree2); } + +static void expect_files_renamed(const char *one, const char *two, uint32_t whitespace_flags) +{ + git_index *index; + git_diff *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + diffopts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + findopts.flags = GIT_DIFF_FIND_FOR_UNTRACKED | + GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES | + whitespace_flags; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_rewritefile("renames/ikeepsix.txt", one); + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + + cl_git_rmfile("renames/ikeepsix.txt"); + cl_git_rewritefile("renames/ikeepsix2.txt", two); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &diffopts)); + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + git_index_free(index); +} + +/* test some variations on empty and blank files */ +void test_diff_rename__empty_files_renamed(void) +{ + /* empty files are identical when ignoring whitespace or not */ + expect_files_renamed("", "", GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE); + expect_files_renamed("", "", GIT_DIFF_FIND_IGNORE_WHITESPACE); +} + +/* test that blank files are similar when ignoring whitespace */ +void test_diff_rename__blank_files_renamed_when_ignoring_whitespace(void) +{ + expect_files_renamed("", "\n\n", GIT_DIFF_FIND_IGNORE_WHITESPACE); + expect_files_renamed("", "\r\n\r\n", GIT_DIFF_FIND_IGNORE_WHITESPACE); + expect_files_renamed("\r\n\r\n", "\n\n\n", GIT_DIFF_FIND_IGNORE_WHITESPACE); + + expect_files_renamed(" ", "\n\n", GIT_DIFF_FIND_IGNORE_WHITESPACE); + expect_files_renamed(" \n \n", "\n\n", GIT_DIFF_FIND_IGNORE_WHITESPACE); +} + +/* blank files are not similar when whitespace is not ignored */ +static void expect_files_not_renamed(const char *one, const char *two, uint32_t whitespace_flags) +{ + git_index *index; + git_diff *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + diffopts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + + findopts.flags = GIT_DIFF_FIND_FOR_UNTRACKED | + whitespace_flags; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_rewritefile("renames/ikeepsix.txt", one); + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + + cl_git_rmfile("renames/ikeepsix.txt"); + cl_git_rewritefile("renames/ikeepsix2.txt", two); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &diffopts)); + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + git_index_free(index); +} + +/* test that blank files are similar when ignoring renames */ +void test_diff_rename__blank_files_not_renamed_when_not_ignoring_whitespace(void) +{ + expect_files_not_renamed("", "\r\n\r\n\r\n", GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE); + expect_files_not_renamed("", "\n\n\n\n", GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE); + expect_files_not_renamed("\n\n\n\n", "\r\n\r\n\r\n", GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE); +} diff --git a/tests/filter/file.c b/tests/filter/file.c new file mode 100644 index 000000000..865c416c5 --- /dev/null +++ b/tests/filter/file.c @@ -0,0 +1,97 @@ +#include "clar_libgit2.h" +#include "git2/sys/filter.h" +#include "crlf.h" +#include "buffer.h" + +static git_repository *g_repo = NULL; + +void test_filter_file__initialize(void) +{ + git_reference *head_ref; + git_commit *head; + + g_repo = cl_git_sandbox_init("crlf"); + + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + cl_git_pass(git_repository_head(&head_ref, g_repo)); + cl_git_pass(git_reference_peel((git_object **)&head, head_ref, GIT_OBJ_COMMIT)); + cl_git_pass(git_reset(g_repo, (git_object *)head, GIT_RESET_HARD, NULL)); + + git_commit_free(head); + git_reference_free(head_ref); +} + +void test_filter_file__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_filter_file__apply(void) +{ + git_filter_list *fl; + git_filter *crlf; + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_filter_list_new( + &fl, g_repo, GIT_FILTER_TO_ODB, 0)); + + crlf = git_filter_lookup(GIT_FILTER_CRLF); + cl_assert(crlf != NULL); + + cl_git_pass(git_filter_list_push(fl, crlf, NULL)); + + cl_git_pass(git_filter_list_apply_to_file(&buf, fl, g_repo, "all-crlf")); + cl_assert_equal_s("crlf\ncrlf\ncrlf\ncrlf\n", buf.ptr); + + git_buf_free(&buf); + git_filter_list_free(fl); +} + +struct buf_writestream { + git_writestream base; + git_buf buf; +}; + +int buf_writestream_write(git_writestream *s, const char *buf, size_t len) +{ + struct buf_writestream *stream = (struct buf_writestream *)s; + return git_buf_put(&stream->buf, buf, len); +} + +int buf_writestream_close(git_writestream *s) +{ + return 0; +} + +void buf_writestream_free(git_writestream *s) +{ + struct buf_writestream *stream = (struct buf_writestream *)s; + git_buf_free(&stream->buf); +} + +void test_filter_file__apply_stream(void) +{ + git_filter_list *fl; + git_filter *crlf; + struct buf_writestream write_target = { { + buf_writestream_write, + buf_writestream_close, + buf_writestream_free } }; + + cl_git_pass(git_filter_list_new( + &fl, g_repo, GIT_FILTER_TO_ODB, 0)); + + crlf = git_filter_lookup(GIT_FILTER_CRLF); + cl_assert(crlf != NULL); + + cl_git_pass(git_filter_list_push(fl, crlf, NULL)); + + cl_git_pass(git_filter_list_stream_file(fl, g_repo, "all-crlf", (git_writestream *)&write_target)); + cl_assert_equal_s("crlf\ncrlf\ncrlf\ncrlf\n", write_target.buf.ptr); + + git_filter_list_free(fl); +} diff --git a/tests/index/tests.c b/tests/index/tests.c index 4cf705127..3c8060a2e 100644 --- a/tests/index/tests.c +++ b/tests/index/tests.c @@ -253,6 +253,128 @@ void test_index_tests__add(void) git_repository_free(repo); } +void test_index_tests__add_frombuffer(void) +{ + git_index *index; + git_repository *repo; + git_index_entry entry; + const git_index_entry *returned_entry; + + git_oid id1; + git_blob *blob; + + const char *content = "hey there\n"; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + /* Intialize a new repository */ + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + + /* Ensure we're the only guy in the room */ + cl_git_pass(git_repository_index(&index, repo)); + cl_assert(git_index_entrycount(index) == 0); + + /* Store the expected hash of the file/blob + * This has been generated by executing the following + * $ echo "hey there" | git hash-object --stdin + */ + cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); + + /* Add the new file to the index */ + memset(&entry, 0x0, sizeof(git_index_entry)); + entry.mode = GIT_FILEMODE_BLOB; + entry.path = "test.txt"; + cl_git_pass(git_index_add_frombuffer(index, &entry, + content, strlen(content))); + + /* Wow... it worked! */ + cl_assert(git_index_entrycount(index) == 1); + returned_entry = git_index_get_byindex(index, 0); + + /* And the built-in hashing mechanism worked as expected */ + cl_assert_equal_oid(&id1, &returned_entry->id); + /* And mode is the one asked */ + cl_assert_equal_i(GIT_FILEMODE_BLOB, returned_entry->mode); + + /* Test access by path instead of index */ + cl_assert((returned_entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); + cl_assert_equal_oid(&id1, &returned_entry->id); + + /* Test the blob is in the repository */ + cl_git_pass(git_blob_lookup(&blob, repo, &id1)); + cl_assert_equal_s( + content, git_blob_rawcontent(blob)); + git_blob_free(blob); + + git_index_free(index); + git_repository_free(repo); +} + +void test_index_tests__add_frombuffer_reset_entry(void) +{ + git_index *index; + git_repository *repo; + git_index_entry entry; + const git_index_entry *returned_entry; + git_filebuf file = GIT_FILEBUF_INIT; + + git_oid id1; + git_blob *blob; + const char *old_content = "here\n"; + const char *content = "hey there\n"; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + /* Intialize a new repository */ + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); + cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666)); + cl_git_pass(git_filebuf_write(&file, old_content, strlen(old_content))); + cl_git_pass(git_filebuf_commit(&file)); + + /* Store the expected hash of the file/blob + * This has been generated by executing the following + * $ echo "hey there" | git hash-object --stdin + */ + cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); + + cl_git_pass(git_index_add_bypath(index, "test.txt")); + + /* Add the new file to the index */ + memset(&entry, 0x0, sizeof(git_index_entry)); + entry.mode = GIT_FILEMODE_BLOB; + entry.path = "test.txt"; + cl_git_pass(git_index_add_frombuffer(index, &entry, + content, strlen(content))); + + /* Wow... it worked! */ + cl_assert(git_index_entrycount(index) == 1); + returned_entry = git_index_get_byindex(index, 0); + + /* And the built-in hashing mechanism worked as expected */ + cl_assert_equal_oid(&id1, &returned_entry->id); + /* And mode is the one asked */ + cl_assert_equal_i(GIT_FILEMODE_BLOB, returned_entry->mode); + + /* Test access by path instead of index */ + cl_assert((returned_entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); + cl_assert_equal_oid(&id1, &returned_entry->id); + cl_assert_equal_i(0, returned_entry->dev); + cl_assert_equal_i(0, returned_entry->ino); + cl_assert_equal_i(0, returned_entry->uid); + cl_assert_equal_i(0, returned_entry->uid); + cl_assert_equal_i(10, returned_entry->file_size); + + /* Test the blob is in the repository */ + cl_git_pass(git_blob_lookup(&blob, repo, &id1)); + cl_assert_equal_s(content, git_blob_rawcontent(blob)); + git_blob_free(blob); + + git_index_free(index); + git_repository_free(repo); +} + static void cleanup_1397(void *opaque) { GIT_UNUSED(opaque); diff --git a/tests/main.c b/tests/main.c index a092b8ba4..f67c8ffbc 100644 --- a/tests/main.c +++ b/tests/main.c @@ -1,4 +1,5 @@ #include "clar_libgit2.h" +#include "clar_libgit2_trace.h" #ifdef _WIN32 int __cdecl main(int argc, char *argv[]) @@ -11,6 +12,7 @@ int main(int argc, char *argv[]) clar_test_init(argc, argv); git_libgit2_init(); + cl_global_trace_register(); cl_sandbox_set_search_path_defaults(); /* Run the test suite */ @@ -18,7 +20,7 @@ int main(int argc, char *argv[]) clar_test_shutdown(); - giterr_clear(); + cl_global_trace_disable(); git_libgit2_shutdown(); return res; diff --git a/tests/online/clone.c b/tests/online/clone.c index 3bb927955..4fdeee1d2 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -565,3 +565,10 @@ void test_online_clone__certificate_valid(void) cl_git_pass(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options)); } + +void test_online_clone__start_with_http(void) +{ + g_options.remote_callbacks.certificate_check = succeed_certificate_check; + + cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options)); +} diff --git a/tests/online/fetch.c b/tests/online/fetch.c index fcbe24d5f..22f32ba1a 100644 --- a/tests/online/fetch.c +++ b/tests/online/fetch.c @@ -58,17 +58,17 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) void test_online_fetch__default_git(void) { - do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 5); + do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } void test_online_fetch__default_http(void) { - do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 5); + do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } void test_online_fetch__default_https(void) { - do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 5); + do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } void test_online_fetch__no_tags_git(void) diff --git a/tests/refs/branches/create.c b/tests/refs/branches/create.c index dc805789f..31dec0678 100644 --- a/tests/refs/branches/create.c +++ b/tests/refs/branches/create.c @@ -97,6 +97,7 @@ void test_refs_branches_create__default_reflog_message(void) git_reflog *log; git_buf buf = GIT_BUF_INIT; const git_reflog_entry *entry; + git_annotated_commit *annotated; git_signature *sig; git_config *cfg; @@ -112,10 +113,25 @@ void test_refs_branches_create__default_reflog_message(void) cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME)); entry = git_reflog_entry_byindex(log, 0); - cl_git_pass(git_buf_printf(&buf, "Branch: created from %s", git_oid_tostr_s(git_commit_id(target)))); + cl_git_pass(git_buf_printf(&buf, "branch: Created from %s", git_oid_tostr_s(git_commit_id(target)))); cl_assert_equal_s(git_buf_cstr(&buf), git_reflog_entry_message(entry)); cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email); + cl_git_pass(git_reference_remove(repo, "refs/heads/" NEW_BRANCH_NAME)); + git_reference_free(branch); + git_reflog_free(log); + git_buf_clear(&buf); + + cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "e90810b8df3")); + cl_git_pass(git_branch_create_from_annotated(&branch, repo, NEW_BRANCH_NAME, annotated, true)); + cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME)); + + entry = git_reflog_entry_byindex(log, 0); + cl_git_pass(git_buf_printf(&buf, "branch: Created from e90810b8df3")); + cl_assert_equal_s(git_buf_cstr(&buf), git_reflog_entry_message(entry)); + cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email); + + git_annotated_commit_free(annotated); git_buf_free(&buf); git_reflog_free(log); git_signature_free(sig); diff --git a/tests/refs/branches/move.c b/tests/refs/branches/move.c index 6e335d1fa..bec39e18b 100644 --- a/tests/refs/branches/move.c +++ b/tests/refs/branches/move.c @@ -203,6 +203,7 @@ void test_refs_branches_move__default_reflog_message(void) const git_reflog_entry *entry; git_signature *sig; git_config *cfg; + git_oid id; cl_git_pass(git_repository_config(&cfg, repo)); cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar")); @@ -212,13 +213,16 @@ void test_refs_branches_move__default_reflog_message(void) cl_git_pass(git_signature_default(&sig, repo)); cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); + git_oid_cpy(&id, git_reference_target(branch)); cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0)); cl_git_pass(git_reflog_read(&log, repo, git_reference_name(new_branch))); entry = git_reflog_entry_byindex(log, 0); - cl_assert_equal_s("Branch: renamed refs/heads/master to refs/heads/master2", + cl_assert_equal_s("branch: renamed refs/heads/master to refs/heads/master2", git_reflog_entry_message(entry)); cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email); + cl_assert_equal_oid(&id, git_reflog_entry_id_old(entry)); + cl_assert_equal_oid(&id, git_reflog_entry_id_new(entry)); git_reference_free(branch); git_reference_free(new_branch); diff --git a/tests/repo/head.c b/tests/repo/head.c index b26d6acc7..31c228777 100644 --- a/tests/repo/head.c +++ b/tests/repo/head.c @@ -2,6 +2,7 @@ #include "refs.h" #include "repo_helpers.h" #include "posix.h" +#include "git2/annotated_commit.h" static const char *g_email = "foo@example.com"; static git_repository *repo; @@ -251,6 +252,7 @@ void test_repo_head__setting_head_updates_reflog(void) { git_object *tag; git_signature *sig; + git_annotated_commit *annotated; cl_git_pass(git_signature_now(&sig, "me", "foo@example.com")); @@ -264,6 +266,12 @@ void test_repo_head__setting_head_updates_reflog(void) test_reflog(repo, 1, NULL, "tags/test^{commit}", "foo@example.com", "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d"); test_reflog(repo, 0, "tags/test^{commit}", "refs/heads/haacked", "foo@example.com", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked"); + cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "haacked~0")); + cl_git_pass(git_repository_set_head_detached_from_annotated(repo, annotated)); + + test_reflog(repo, 0, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from haacked to haacked~0"); + + git_annotated_commit_free(annotated); git_object_free(tag); git_signature_free(sig); } diff --git a/tests/repo/new.c b/tests/repo/new.c new file mode 100644 index 000000000..d77e903f6 --- /dev/null +++ b/tests/repo/new.c @@ -0,0 +1,27 @@ +#include "clar_libgit2.h" +#include "git2/sys/repository.h" + +void test_repo_new__has_nothing(void) +{ + git_repository *repo; + + cl_git_pass(git_repository_new(&repo)); + cl_assert_equal_b(true, git_repository_is_bare(repo)); + cl_assert_equal_p(NULL, git_repository_path(repo)); + cl_assert_equal_p(NULL, git_repository_workdir(repo)); + git_repository_free(repo); +} + +void test_repo_new__is_bare_until_workdir_set(void) +{ + git_repository *repo; + + cl_git_pass(git_repository_new(&repo)); + cl_assert_equal_b(true, git_repository_is_bare(repo)); + + cl_git_pass(git_repository_set_workdir(repo, clar_sandbox_path(), 0)); + cl_assert_equal_b(false, git_repository_is_bare(repo)); + + git_repository_free(repo); +} + diff --git a/tests/repo/reservedname.c b/tests/repo/reservedname.c new file mode 100644 index 000000000..faea0cc2b --- /dev/null +++ b/tests/repo/reservedname.c @@ -0,0 +1,108 @@ +#include "clar_libgit2.h" +#include "../submodule/submodule_helpers.h" +#include "repository.h" + +void test_repo_reservedname__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_repo_reservedname__includes_shortname_on_win32(void) +{ + git_repository *repo; + git_buf *reserved; + size_t reserved_len; + + repo = cl_git_sandbox_init("nasty"); + cl_assert(git_repository__reserved_names(&reserved, &reserved_len, repo, false)); + +#ifdef GIT_WIN32 + cl_assert_equal_i(2, reserved_len); + cl_assert_equal_s(".git", reserved[0].ptr); + cl_assert_equal_s("GIT~1", reserved[1].ptr); +#else + cl_assert_equal_i(1, reserved_len); + cl_assert_equal_s(".git", reserved[0].ptr); +#endif +} + +void test_repo_reservedname__includes_shortname_when_requested(void) +{ + git_repository *repo; + git_buf *reserved; + size_t reserved_len; + + repo = cl_git_sandbox_init("nasty"); + cl_assert(git_repository__reserved_names(&reserved, &reserved_len, repo, true)); + + cl_assert_equal_i(2, reserved_len); + cl_assert_equal_s(".git", reserved[0].ptr); + cl_assert_equal_s("GIT~1", reserved[1].ptr); +} + +/* Ensures that custom shortnames are included: creates a GIT~1 so that the + * .git folder itself will have to be named GIT~2 + */ +void test_repo_reservedname__custom_shortname_recognized(void) +{ +#ifdef GIT_WIN32 + git_repository *repo; + git_buf *reserved; + size_t reserved_len; + + if (!cl_sandbox_supports_8dot3()) + clar__skip(); + + repo = cl_git_sandbox_init("nasty"); + + cl_must_pass(p_rename("nasty/.git", "nasty/_temp")); + cl_git_write2file("nasty/git~1", "", 0, O_RDWR|O_CREAT, 0666); + cl_must_pass(p_rename("nasty/_temp", "nasty/.git")); + + cl_assert(git_repository__reserved_names(&reserved, &reserved_len, repo, true)); + + cl_assert_equal_i(3, reserved_len); + cl_assert_equal_s(".git", reserved[0].ptr); + cl_assert_equal_s("GIT~1", reserved[1].ptr); + cl_assert_equal_s("GIT~2", reserved[2].ptr); +#endif +} + +/* When looking at the short name for a submodule, we need to prevent + * people from overwriting the `.git` file in the submodule working + * directory itself. We don't want to look at the actual repository + * path, since it will be in the super's repository above us, and + * typically named with the name of our subrepository. Consequently, + * preventing access to the short name of the actual repository path + * would prevent us from creating files with the same name as the + * subrepo. (Eg, a submodule named "libgit2" could not contain a file + * named "libgit2", which would be unfortunate.) + */ +void test_repo_reservedname__submodule_pointer(void) +{ +#ifdef GIT_WIN32 + git_repository *super_repo, *sub_repo; + git_submodule *sub; + git_buf *sub_reserved; + size_t sub_reserved_len; + + if (!cl_sandbox_supports_8dot3()) + clar__skip(); + + super_repo = setup_fixture_submod2(); + + assert_submodule_exists(super_repo, "sm_unchanged"); + + cl_git_pass(git_submodule_lookup(&sub, super_repo, "sm_unchanged")); + cl_git_pass(git_submodule_open(&sub_repo, sub)); + + cl_assert(git_repository__reserved_names(&sub_reserved, &sub_reserved_len, sub_repo, true)); + + cl_assert_equal_i(2, sub_reserved_len); + cl_assert_equal_s(".git", sub_reserved[0].ptr); + cl_assert_equal_s("GIT~1", sub_reserved[1].ptr); + + git_submodule_free(sub); + git_repository_free(sub_repo); +#endif +} diff --git a/tests/reset/hard.c b/tests/reset/hard.c index f6ca1037b..86d4be2ed 100644 --- a/tests/reset/hard.c +++ b/tests/reset/hard.c @@ -201,6 +201,7 @@ void test_reset_hard__cleans_up_merge(void) void test_reset_hard__reflog_is_correct(void) { git_buf buf = GIT_BUF_INIT; + git_annotated_commit *annotated; const char *exp_msg = "commit: Add a file which name should appear before the " "\"subdir/\" folder while being dealt with by the treewalker"; @@ -215,7 +216,7 @@ void test_reset_hard__reflog_is_correct(void) git_object_free(target); - /* Moved branch, expect default message */ + /* Moved branch, expect id in message */ cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}")); cl_git_pass(git_buf_printf(&buf, "reset: moving to %s", git_oid_tostr_s(git_object_id(target)))); cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL)); @@ -223,4 +224,14 @@ void test_reset_hard__reflog_is_correct(void) reflog_check(repo, "refs/heads/master", 4, NULL, git_buf_cstr(&buf)); git_buf_free(&buf); + + /* Moved branch, expect revspec in message */ + exp_msg = "reset: moving to HEAD~^{commit}"; + cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "HEAD~^{commit}")); + cl_git_pass(git_reset_from_annotated(repo, annotated, GIT_RESET_HARD, NULL)); + reflog_check(repo, "HEAD", 5, NULL, exp_msg); + reflog_check(repo, "refs/heads/master", 5, NULL, exp_msg); + + git_annotated_commit_free(annotated); + } diff --git a/tests/reset/mixed.c b/tests/reset/mixed.c index b374902aa..97eac74e8 100644 --- a/tests/reset/mixed.c +++ b/tests/reset/mixed.c @@ -51,6 +51,7 @@ void test_reset_mixed__resetting_refreshes_the_index_to_the_commit_tree(void) void test_reset_mixed__reflog_is_correct(void) { git_buf buf = GIT_BUF_INIT; + git_annotated_commit *annotated; const char *exp_msg = "commit: Updating test data so we can test inter-hunk-context"; reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg); @@ -65,13 +66,20 @@ void test_reset_mixed__reflog_is_correct(void) git_object_free(target); target = NULL; - /* Moved branch, expect default message */ + /* Moved branch, expect id in message */ cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}")); git_buf_clear(&buf); cl_git_pass(git_buf_printf(&buf, "reset: moving to %s", git_oid_tostr_s(git_object_id(target)))); cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL)); reflog_check(repo, "HEAD", 10, NULL, git_buf_cstr(&buf)); reflog_check(repo, "refs/heads/master", 10, NULL, git_buf_cstr(&buf)); - git_buf_free(&buf); + + /* Moved branch, expect revspec in message */ + exp_msg = "reset: moving to HEAD~^{commit}"; + cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "HEAD~^{commit}")); + cl_git_pass(git_reset_from_annotated(repo, annotated, GIT_RESET_MIXED, NULL)); + reflog_check(repo, "HEAD", 11, NULL, exp_msg); + reflog_check(repo, "refs/heads/master", 11, NULL, exp_msg); + git_annotated_commit_free(annotated); } diff --git a/tests/reset/reset_helpers.c b/tests/reset/reset_helpers.c index ec67b8634..e6acec9ef 100644 --- a/tests/reset/reset_helpers.c +++ b/tests/reset/reset_helpers.c @@ -7,7 +7,7 @@ void reflog_check(git_repository *repo, const char *refname, git_reflog *log; const git_reflog_entry *entry; - exp_email = exp_email; + GIT_UNUSED(exp_email); cl_git_pass(git_reflog_read(&log, repo, refname)); cl_assert_equal_i(exp_count, git_reflog_entrycount(log)); diff --git a/tests/reset/soft.c b/tests/reset/soft.c index a5bb13cc8..506decaed 100644 --- a/tests/reset/soft.c +++ b/tests/reset/soft.c @@ -155,28 +155,35 @@ void test_reset_soft__fails_when_index_contains_conflicts_independently_of_MERGE cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT, NULL)); } -void test_reset_soft_reflog_is_correct(void) +void test_reset_soft__reflog_is_correct(void) { - const char *exp_msg = "commit: Updating test data so we can test inter-hunk-context"; + git_annotated_commit *annotated; + const char *exp_msg = "checkout: moving from br2 to master"; + const char *master_msg = "commit: checking in"; - reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg); - reflog_check(repo, "refs/heads/master", 9, "yoram.harmelin@gmail.com", exp_msg); + reflog_check(repo, "HEAD", 7, "yoram.harmelin@gmail.com", exp_msg); + reflog_check(repo, "refs/heads/master", 2, "yoram.harmelin@gmail.com", master_msg); /* Branch not moving, no reflog entry */ cl_git_pass(git_revparse_single(&target, repo, "HEAD^{commit}")); cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL)); - reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg); - reflog_check(repo, "refs/heads/master", 9, "yoram.harmelin@gmail.com", exp_msg); + reflog_check(repo, "HEAD", 7, "yoram.harmelin@gmail.com", exp_msg); + reflog_check(repo, "refs/heads/master", 2, "yoram.harmelin@gmail.com", master_msg); + git_object_free(target); - /* Moved branch, expect default message */ + /* Moved branch, expect id in message */ + exp_msg = "reset: moving to be3563ae3f795b2b4353bcce3a527ad0a4f7f644"; cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}")); cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL)); - reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg); - reflog_check(repo, "refs/heads/master", 10, NULL, "reset: moving"); + reflog_check(repo, "HEAD", 8, "yoram.harmelin@gmail.com", exp_msg); + reflog_check(repo, "refs/heads/master", 3, NULL, exp_msg); - /* Moved branch, expect custom message */ - cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}")); - cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT, NULL)); + /* Moved branch, expect message with annotated string */ + exp_msg = "reset: moving to HEAD~^{commit}"; + cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "HEAD~^{commit}")); + cl_git_pass(git_reset_from_annotated(repo, annotated, GIT_RESET_SOFT, NULL)); reflog_check(repo, "HEAD", 9, "yoram.harmelin@gmail.com", exp_msg); - reflog_check(repo, "refs/heads/master", 11, NULL, "message1"); + reflog_check(repo, "refs/heads/master", 4, NULL, exp_msg); + + git_annotated_commit_free(annotated); } diff --git a/tests/submodule/modify.c b/tests/submodule/modify.c index 3d7269bff..fcb4c22a8 100644 --- a/tests/submodule/modify.c +++ b/tests/submodule/modify.c @@ -118,11 +118,11 @@ void test_submodule_modify__sync(void) /* check that submodule config is updated */ assert_submodule_url_is_synced( - sm1, "submodule."SM1".url", "branch.origin.remote"); + sm1, "submodule."SM1".url", "remote.origin.url"); assert_submodule_url_is_synced( - sm2, "submodule."SM2".url", "branch.origin.remote"); + sm2, "submodule."SM2".url", "remote.origin.url"); assert_submodule_url_is_synced( - sm3, "submodule."SM3".url", "branch.origin.remote"); + sm3, "submodule."SM3".url", "remote.origin.url"); git_submodule_free(sm1); git_submodule_free(sm2); diff --git a/tests/trace/trace.c b/tests/trace/trace.c index 87b325378..097208bff 100644 --- a/tests/trace/trace.c +++ b/tests/trace/trace.c @@ -1,4 +1,5 @@ #include "clar_libgit2.h" +#include "clar_libgit2_trace.h" #include "trace.h" static int written = 0; @@ -14,6 +15,9 @@ static void trace_callback(git_trace_level_t level, const char *message) void test_trace_trace__initialize(void) { + /* If global tracing is enabled, disable for the duration of this test. */ + cl_global_trace_disable(); + git_trace_set(GIT_TRACE_INFO, trace_callback); written = 0; } @@ -21,12 +25,17 @@ void test_trace_trace__initialize(void) void test_trace_trace__cleanup(void) { git_trace_set(GIT_TRACE_NONE, NULL); + + /* If global tracing was enabled, restart it. */ + cl_global_trace_register(); } void test_trace_trace__sets(void) { #ifdef GIT_TRACE cl_assert(git_trace_level() == GIT_TRACE_INFO); +#else + cl_skip(); #endif } @@ -42,6 +51,8 @@ void test_trace_trace__can_reset(void) git_trace(GIT_TRACE_ERROR, "Hello %s!", "world"); cl_assert(written == 1); +#else + cl_skip(); #endif } @@ -56,6 +67,8 @@ void test_trace_trace__can_unset(void) cl_assert(written == 0); git_trace(GIT_TRACE_FATAL, "Hello %s!", "world"); cl_assert(written == 0); +#else + cl_skip(); #endif } @@ -65,6 +78,8 @@ void test_trace_trace__skips_higher_level(void) cl_assert(written == 0); git_trace(GIT_TRACE_DEBUG, "Hello %s!", "world"); cl_assert(written == 0); +#else + cl_skip(); #endif } @@ -74,6 +89,8 @@ void test_trace_trace__writes(void) cl_assert(written == 0); git_trace(GIT_TRACE_INFO, "Hello %s!", "world"); cl_assert(written == 1); +#else + cl_skip(); #endif } @@ -83,5 +100,7 @@ void test_trace_trace__writes_lower_level(void) cl_assert(written == 0); git_trace(GIT_TRACE_ERROR, "Hello %s!", "world"); cl_assert(written == 1); +#else + cl_skip(); #endif } |
