diff --git a/.github/workflows/experimental.yml b/.github/workflows/experimental.yml index 07442bddecb..15fa0880adc 100644 --- a/.github/workflows/experimental.yml +++ b/.github/workflows/experimental.yml @@ -113,7 +113,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download test results - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: Generate test summary uses: test-summary/action@v2 with: diff --git a/AUTHORS b/AUTHORS index f4e852357e5..ee55e6ad5b7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -70,6 +70,7 @@ Shawn O. Pearce Shuhei Tanuma Steve Frécinaux Sven Strickroth +Talya "kivikakk" Connor Tim Branyen Tim Clem Tim Harder diff --git a/CMakeLists.txt b/CMakeLists.txt index 31da49a8856..5be7bef9fc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.5.1) -project(libgit2 VERSION "1.9.0" LANGUAGES C) +project(libgit2 VERSION "1.9.1" LANGUAGES C) # Add find modules to the path set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") diff --git a/cmake/DefaultCFlags.cmake b/cmake/DefaultCFlags.cmake index a9c9ab9729c..5ba3466fc9e 100644 --- a/cmake/DefaultCFlags.cmake +++ b/cmake/DefaultCFlags.cmake @@ -56,7 +56,7 @@ if(MSVC) set(CMAKE_C_FLAGS_MINSIZEREL "/DNDEBUG /O1 /Oy /GL /Gy ${CRT_FLAG_RELEASE}") # /IGNORE:4221 - Ignore empty compilation units - set(CMAKE_STATIC_LINKER_FLAGS "/IGNORE:4221") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221") # /DYNAMICBASE - Address space load randomization (ASLR) # /NXCOMPAT - Data execution prevention (DEP) diff --git a/cmake/SelectSSH.cmake b/cmake/SelectSSH.cmake index b0d747114da..1a4032b8ac4 100644 --- a/cmake/SelectSSH.cmake +++ b/cmake/SelectSSH.cmake @@ -42,5 +42,5 @@ elseif(USE_SSH STREQUAL ON OR USE_SSH STREQUAL "libssh2") elseif(USE_SSH STREQUAL OFF OR USE_SSH STREQUAL "") add_feature_info(SSH OFF "SSH transport support") else() - message(FATAL_ERROR "unknown SSH option: ${USE_HTTP_PARSER}") + message(FATAL_ERROR "unknown SSH option: ${USE_SSH}") endif() diff --git a/docs/changelog.md b/docs/changelog.md index 9824d994bc7..96d3a9fe170 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,3 +1,93 @@ +v1.9.1 +------ + +This release includes a number of bugfixes and compatibility +improvements. + +## What's Changed + +### Bug fixes + +* hash: allow `unsigned int` != `size_t` in sha256 by @ethomson in + https://github.com/libgit2/libgit2/pull/6996 +* include: Fix code comment termination by @florianpircher in + https://github.com/libgit2/libgit2/pull/6997 +* alternates: allow relative paths in all repositories by @vapier + in https://github.com/libgit2/libgit2/pull/7019 +* Fix potential null dereference by @peter15914 in + https://github.com/libgit2/libgit2/pull/6998 +* cli: fix undefined alloca() on CYGWIN by @carlo-bramini in + https://github.com/libgit2/libgit2/pull/7022 +* attr: honor ignorecase in attribute matching by @ethomson in + https://github.com/libgit2/libgit2/pull/7018 +* tag: Refuse to use HEAD as a tagname by @csware in + https://github.com/libgit2/libgit2/pull/7061 +* Fix memory leak in openssl fips modes by @wklatka in + https://github.com/libgit2/libgit2/pull/7064 +* Fix circular includes between types.h and oid.h by @georgthegreat + in https://github.com/libgit2/libgit2/pull/7059 +* diff: correct diff stat alignment in presence of renames w/ common + prefix. by @kivikakk in https://github.com/libgit2/libgit2/pull/7057 +* Revert include path regression by @ytnuf in + https://github.com/libgit2/libgit2/pull/7039 + +### Build and CI improvements + +* benchmarks: update path to baseline cli by @ethomson in + https://github.com/libgit2/libgit2/pull/7006 +* Update SelectSSH.cmake by @lrm29 in + https://github.com/libgit2/libgit2/pull/7012 +* ci: update download-artifact version by @ethomson in + https://github.com/libgit2/libgit2/pull/7038 +* install cmake files into configured libdir by @kanavin in + https://github.com/libgit2/libgit2/pull/7004 +* Test updates by @ethomson in + https://github.com/libgit2/libgit2/pull/7025 +* conflict tests: check `core.ignorecase` by @emilazy in + https://github.com/libgit2/libgit2/pull/7026 +* Include common.h in version.h by @ethomson in + https://github.com/libgit2/libgit2/pull/7030 +* clar: update to latest version by @ethomson in + https://github.com/libgit2/libgit2/pull/7029 +* Fix MSVC cross compilation by @Faless in + https://github.com/libgit2/libgit2/pull/7079 +* fuzzers: Fix CFLAGS by @nelhage in + https://github.com/libgit2/libgit2/pull/7044 +* Avoid duplicate definition of `git_http_auth_dummy`. by + @JohannesWilde in https://github.com/libgit2/libgit2/pull/7077 + +### Documentation improvements + +* docs: add `update_refs` as ABI breaking change by @ethomson + in https://github.com/libgit2/libgit2/pull/7005 +* docs: correct wrong docstring info for `git_remote_url` by + @DominiqueFuchs in https://github.com/libgit2/libgit2/pull/7076 + +## New Contributors + +* @peter15914 made their first contribution in + https://github.com/libgit2/libgit2/pull/6998 +* @kanavin made their first contribution in + https://github.com/libgit2/libgit2/pull/7004 +* @carlo-bramini made their first contribution in + https://github.com/libgit2/libgit2/pull/7022 +* @vapier made their first contribution in + https://github.com/libgit2/libgit2/pull/7019 +* @emilazy made their first contribution in + https://github.com/libgit2/libgit2/pull/7026 +* @ytnuf made their first contribution in + https://github.com/libgit2/libgit2/pull/7039 +* @DominiqueFuchs made their first contribution in + https://github.com/libgit2/libgit2/pull/7076 +* @wklatka made their first contribution in + https://github.com/libgit2/libgit2/pull/7064 +* @kivikakk made their first contribution in + https://github.com/libgit2/libgit2/pull/7057 +* @JohannesWilde made their first contribution in + https://github.com/libgit2/libgit2/pull/7077 + +**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.9.0...v1.9.1 + v1.9.0 ------ @@ -71,6 +161,13 @@ maintainers of bindings or FFI users, may want to be aware of. to provide a mechanism to nicely free the configuration entries that they provide. +* **`update_refs` callback for remotes** (ABI breaking change) + The `update_refs` callback was added to the `git_remote_callbacks` + structure to provide additional information about updated refs; + in particular, the `git_refspec` is included for more information + about the remote ref. The `update_refs` callback will be + preferred over the now deprecated `update_tips` callback. + ## What's Changed ### New features diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt index 4063def331a..38d705f74c8 100644 --- a/fuzzers/CMakeLists.txt +++ b/fuzzers/CMakeLists.txt @@ -2,7 +2,6 @@ if(BUILD_FUZZERS AND NOT USE_STANDALONE_FUZZERS) set(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer-no-link") - add_c_flag(-fsanitize=fuzzer) add_c_flag(-fsanitize=fuzzer-no-link) unset(CMAKE_REQUIRED_FLAGS) endif() @@ -24,6 +23,9 @@ foreach(fuzz_target_src ${SRC_FUZZERS}) target_include_directories(${fuzz_target_name} SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES}) target_link_libraries(${fuzz_target_name} ${LIBGIT2_SYSTEM_LIBS}) + if(NOT USE_STANDALONE_FUZZERS) + target_link_options(${fuzz_target_name} PRIVATE "-fsanitize=fuzzer") + endif() add_test(${fuzz_target_name} "${CMAKE_CURRENT_BINARY_DIR}/${fuzz_target_name}" "${CMAKE_CURRENT_SOURCE_DIR}/corpora/${fuzz_name}") endforeach() diff --git a/include/git2/oid.h b/include/git2/oid.h index 0af9737a04d..8539b4e6963 100644 --- a/include/git2/oid.h +++ b/include/git2/oid.h @@ -8,7 +8,6 @@ #define INCLUDE_git_oid_h__ #include "common.h" -#include "types.h" #include "experimental.h" /** diff --git a/include/git2/remote.h b/include/git2/remote.h index ecb7b537eb7..2472dedccf8 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -249,9 +249,9 @@ GIT_EXTERN(const char *) git_remote_name(const git_remote *remote); /** * Get the remote's url * - * If url.*.insteadOf has been configured for this URL, it will - * return the modified URL. If `git_remote_set_instance_pushurl` - * has been called for this remote, then that URL will be returned. + * If url.*.insteadOf has been configured for this URL, it will return + * the modified URL. This function does not consider if a push url has + * been configured for this remote (use `git_remote_pushurl` if needed). * * @param remote the remote * @return a pointer to the url diff --git a/include/git2/stdint.h b/include/git2/stdint.h index 4b235c73f87..4f532e13c85 100644 --- a/include/git2/stdint.h +++ b/include/git2/stdint.h @@ -221,7 +221,7 @@ typedef uint64_t uintmax_t; #endif /* __STDC_LIMIT_MACROS ] */ -/* 7.18.4 Limits of other integer types +/* 7.18.4 Limits of other integer types */ #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* [ See footnote 224 at page 260 */ diff --git a/include/git2/version.h b/include/git2/version.h index 6a352e1a53a..587a101f978 100644 --- a/include/git2/version.h +++ b/include/git2/version.h @@ -7,6 +7,8 @@ #ifndef INCLUDE_git_version_h__ #define INCLUDE_git_version_h__ +#include "common.h" + /** * @file git2/version.h * @brief The version of libgit2 @@ -19,7 +21,7 @@ GIT_BEGIN_DECL * The version string for libgit2. This string follows semantic * versioning (v2) guidelines. */ -#define LIBGIT2_VERSION "1.9.0" +#define LIBGIT2_VERSION "1.9.1" /** The major version number for this version of libgit2. */ #define LIBGIT2_VERSION_MAJOR 1 @@ -28,7 +30,7 @@ GIT_BEGIN_DECL #define LIBGIT2_VERSION_MINOR 9 /** The revision ("teeny") version number for this version of libgit2. */ -#define LIBGIT2_VERSION_REVISION 0 +#define LIBGIT2_VERSION_REVISION 1 /** The Windows DLL patch number for this version of libgit2. */ #define LIBGIT2_VERSION_PATCH 0 diff --git a/package.json b/package.json index 2bea37ef30b..3d62e016c2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "libgit2", - "version": "1.9.0", + "version": "1.9.1", "repo": "https://github.com/libgit2/libgit2", "description": " A cross-platform, linkable library implementation of Git that you can use in your application.", "install": "mkdir build && cd build && cmake .. && cmake --build ." diff --git a/src/cli/opt.c b/src/cli/opt.c index 9242e2203b4..204de10c271 100644 --- a/src/cli/opt.c +++ b/src/cli/opt.c @@ -19,7 +19,7 @@ #include #include -#if defined(__sun) || defined(__illumos__) +#if defined(__sun) || defined(__illumos__) || defined(__CYGWIN__) # include #endif diff --git a/src/libgit2/CMakeLists.txt b/src/libgit2/CMakeLists.txt index a7d3c7ca400..0dddb025e14 100644 --- a/src/libgit2/CMakeLists.txt +++ b/src/libgit2/CMakeLists.txt @@ -58,7 +58,7 @@ set(LIBGIT2_SYSTEM_LIBS ${LIBGIT2_SYSTEM_LIBS} PARENT_SCOPE) add_library(libgit2package ${SRC_RC} ${LIBGIT2_OBJECTS}) target_link_libraries(libgit2package ${LIBGIT2_SYSTEM_LIBS}) target_include_directories(libgit2package SYSTEM PRIVATE ${LIBGIT2_INCLUDES}) -target_include_directories(libgit2package INTERFACE $) +target_include_directories(libgit2package INTERFACE $) set_target_properties(libgit2package PROPERTIES C_STANDARD 90) set_target_properties(libgit2package PROPERTIES C_EXTENSIONS OFF) @@ -119,11 +119,11 @@ configure_file(config.cmake.in install(FILES "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION "lib/cmake/${PROJECT_NAME}") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") install( EXPORT ${LIBGIT2_TARGETS_EXPORT_NAME} NAMESPACE "${PROJECT_NAME}::" - DESTINATION "lib/cmake/${PROJECT_NAME}") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") # Install diff --git a/src/libgit2/attr_file.c b/src/libgit2/attr_file.c index c19921e2491..56647042064 100644 --- a/src/libgit2/attr_file.c +++ b/src/libgit2/attr_file.c @@ -347,7 +347,7 @@ int git_attr_file__parse_buffer( { const char *scan = data, *context = NULL; git_attr_rule *rule = NULL; - int error = 0; + int ignorecase = 0, error = 0; /* If subdir file path, convert context for file paths */ if (attrs->entry && git_fs_path_root(attrs->entry->path) < 0 && @@ -379,6 +379,13 @@ int git_attr_file__parse_buffer( continue; } + if (repo && + (error = git_repository__configmap_lookup(&ignorecase, repo, GIT_CONFIGMAP_IGNORECASE)) < 0) + goto out; + + if (ignorecase) + rule->match.flags |= GIT_ATTR_FNMATCH_ICASE; + if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) { /* TODO: warning if macro found in file below repo root */ if (!allow_macros) @@ -482,7 +489,7 @@ bool git_attr_fnmatch__match( */ if (match->containing_dir) { if (match->flags & GIT_ATTR_FNMATCH_ICASE) { - if (git__strncasecmp(path->path, match->containing_dir, match->containing_dir_length)) + if (git__prefixcmp_icase(path->path, match->containing_dir)) return 0; } else { if (git__prefixcmp(path->path, match->containing_dir)) diff --git a/src/libgit2/diff_stats.c b/src/libgit2/diff_stats.c index 259939844a5..b67aa48dd6b 100644 --- a/src/libgit2/diff_stats.c +++ b/src/libgit2/diff_stats.c @@ -28,7 +28,6 @@ struct git_diff_stats { size_t files_changed; size_t insertions; size_t deletions; - size_t renames; size_t max_name; size_t max_filestat; @@ -68,17 +67,19 @@ static int diff_file_stats_full_to_buf( size_t common_dirlen; int error; - padding = stats->max_name - strlen(old_path) - strlen(new_path); - if ((common_dirlen = git_fs_path_common_dirlen(old_path, new_path)) && common_dirlen <= INT_MAX) { error = git_str_printf(out, " %.*s{%s"DIFF_RENAME_FILE_SEPARATOR"%s}", (int) common_dirlen, old_path, old_path + common_dirlen, new_path + common_dirlen); + padding = stats->max_name + common_dirlen - strlen(old_path) + - strlen(new_path) - 2 - strlen(DIFF_RENAME_FILE_SEPARATOR); } else { error = git_str_printf(out, " %s" DIFF_RENAME_FILE_SEPARATOR "%s", old_path, new_path); + padding = stats->max_name - strlen(old_path) + - strlen(new_path) - strlen(DIFF_RENAME_FILE_SEPARATOR); } if (error < 0) @@ -89,9 +90,6 @@ static int diff_file_stats_full_to_buf( goto on_error; padding = stats->max_name - strlen(adddel_path); - - if (stats->renames > 0) - padding += strlen(DIFF_RENAME_FILE_SEPARATOR); } if (git_str_putcn(out, ' ', padding) < 0 || @@ -210,14 +208,23 @@ int git_diff_get_stats( if ((error = git_patch_from_diff(&patch, diff, i)) < 0) break; - /* keep a count of renames because it will affect formatting */ + /* Length calculation for renames mirrors the actual presentation format + * generated in diff_file_stats_full_to_buf; namelen is the full length of + * what will be printed, taking into account renames and common prefixes. + */ delta = patch->delta; - - /* TODO ugh */ namelen = strlen(delta->new_file.path); - if (delta->old_file.path && strcmp(delta->old_file.path, delta->new_file.path) != 0) { - namelen += strlen(delta->old_file.path); - stats->renames++; + if (delta->old_file.path && + strcmp(delta->old_file.path, delta->new_file.path) != 0) { + size_t common_dirlen; + if ((common_dirlen = git_fs_path_common_dirlen(delta->old_file.path, delta->new_file.path)) && + common_dirlen <= INT_MAX) { + namelen += strlen(delta->old_file.path) + 2 + + strlen(DIFF_RENAME_FILE_SEPARATOR) - common_dirlen; + } else { + namelen += strlen(delta->old_file.path) + + strlen(DIFF_RENAME_FILE_SEPARATOR); + } } /* and, of course, count the line stats */ diff --git a/src/libgit2/odb.c b/src/libgit2/odb.c index 2c308c97772..653c7c03940 100644 --- a/src/libgit2/odb.c +++ b/src/libgit2/odb.c @@ -790,12 +790,8 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_ if (*alternate == '\0' || *alternate == '#') continue; - /* - * Relative path: build based on the current `objects` - * folder. However, relative paths are only allowed in - * the current repository. - */ - if (*alternate == '.' && !alternate_depth) { + /* Relative path: build based on the current `objects` folder. */ + if (*alternate == '.') { if ((result = git_str_joinpath(&alternates_path, objects_dir, alternate)) < 0) break; alternate = git_str_cstr(&alternates_path); diff --git a/src/libgit2/tag.c b/src/libgit2/tag.c index cad9e416e5c..d12efdb63b5 100644 --- a/src/libgit2/tag.c +++ b/src/libgit2/tag.c @@ -263,8 +263,10 @@ static bool tag_name_is_valid(const char *tag_name) /* * Discourage tag name starting with dash, * https://github.com/git/git/commit/4f0accd638b8d2 + * and refuse to use HEAD as a tagname, + * https://github.com/git/git/commit/bbd445d5efd415 */ - return tag_name[0] != '-'; + return tag_name[0] != '-' && git__strcmp(tag_name, "HEAD"); } static int git_tag_create__internal( diff --git a/src/util/hash/builtin.c b/src/util/hash/builtin.c index cc4aa58fe8d..b4736efbc66 100644 --- a/src/util/hash/builtin.c +++ b/src/util/hash/builtin.c @@ -32,13 +32,23 @@ int git_hash_sha256_init(git_hash_sha256_ctx *ctx) return 0; } -int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *data, size_t len) +int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *_data, size_t len) { + const unsigned char *data = _data; GIT_ASSERT_ARG(ctx); - if (SHA256Input(&ctx->c, data, len)) { - git_error_set(GIT_ERROR_SHA, "SHA256 error"); - return -1; + + while (len > 0) { + unsigned int chunk = (len > UINT_MAX) ? UINT_MAX : (unsigned int)len; + + if (SHA256Input(&ctx->c, data, chunk)) { + git_error_set(GIT_ERROR_SHA, "SHA256 error"); + return -1; + } + + data += chunk; + len -= chunk; } + return 0; } diff --git a/src/util/hash/openssl.c b/src/util/hash/openssl.c index 1ed1b4409f9..891107310f0 100644 --- a/src/util/hash/openssl.c +++ b/src/util/hash/openssl.c @@ -189,8 +189,6 @@ int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx) return -1; } - ctx->c = NULL; - return 0; } @@ -339,8 +337,6 @@ int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx) return -1; } - ctx->c = NULL; - return 0; } diff --git a/tests/benchmarks/benchmark.sh b/tests/benchmarks/benchmark.sh index 6830064e776..944f26bc52a 100755 --- a/tests/benchmarks/benchmark.sh +++ b/tests/benchmarks/benchmark.sh @@ -100,11 +100,11 @@ SYSTEM_KERNEL=$(uname -v) fullpath() { if [[ "$(uname -s)" == "MINGW"* && $(cygpath -u "${TEST_CLI}") == "/"* ]]; then - echo "${TEST_CLI}" + echo "$1" elif [[ "${TEST_CLI}" == "/"* ]]; then - echo "${TEST_CLI}" + echo "$1" else - which "${TEST_CLI}" + which "$1" fi } diff --git a/tests/clar/clar.c b/tests/clar/clar.c index 9695dc946e4..f28d6af08b9 100644 --- a/tests/clar/clar.c +++ b/tests/clar/clar.c @@ -4,7 +4,12 @@ * This file is part of clar, distributed under the ISC license. * For full terms see the included COPYING file. */ -#include + +#define _BSD_SOURCE +#define _DARWIN_C_SOURCE +#define _DEFAULT_SOURCE + +#include #include #include #include @@ -13,21 +18,35 @@ #include #include #include +#include /* required for sandboxing */ #include #include +#if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_WCHAR__) + /* + * uClibc can optionally be built without wchar support, in which case + * the installed is a stub that only defines the `whar_t` + * type but none of the functions typically declared by it. + */ +#else +# define CLAR_HAVE_WCHAR +#endif + #ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN # include # include -# include # include # define _MAIN_CC __cdecl # ifndef stat # define stat(path, st) _stat(path, st) + typedef struct _stat STAT_T; +# else + typedef struct stat STAT_T; # endif # ifndef mkdir # define mkdir(path, mode) _mkdir(path) @@ -41,6 +60,9 @@ # ifndef strdup # define strdup(str) _strdup(str) # endif +# ifndef strcasecmp +# define strcasecmp(a,b) _stricmp(a,b) +# endif # ifndef __MINGW32__ # pragma comment(lib, "shell32") @@ -57,30 +79,11 @@ # else # define p_snprintf snprintf # endif - -# ifndef PRIuZ -# define PRIuZ "Iu" -# endif -# ifndef PRIxZ -# define PRIxZ "Ix" -# endif - -# if defined(_MSC_VER) || defined(__MINGW32__) - typedef struct stat STAT_T; -# else - typedef struct _stat STAT_T; -# endif #else # include /* waitpid(2) */ # include # define _MAIN_CC # define p_snprintf snprintf -# ifndef PRIuZ -# define PRIuZ "zu" -# endif -# ifndef PRIxZ -# define PRIxZ "zx" -# endif typedef struct stat STAT_T; #endif @@ -99,7 +102,7 @@ fixture_path(const char *base, const char *fixture_name); struct clar_error { const char *file; const char *function; - size_t line_number; + uintmax_t line_number; const char *error_msg; char *description; @@ -161,6 +164,10 @@ static struct { struct clar_report *reports; struct clar_report *last_report; + const char *invoke_file; + const char *invoke_func; + size_t invoke_line; + void (*local_cleanup)(void *); void *local_cleanup_payload; @@ -192,11 +199,14 @@ static void clar_print_shutdown(int test_count, int suite_count, int error_count static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error); static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status failed); static void clar_print_onsuite(const char *suite_name, int suite_index); +static void clar_print_onabortv(const char *msg, va_list argp); static void clar_print_onabort(const char *msg, ...); /* From clar_sandbox.c */ -static void clar_unsandbox(void); -static int clar_sandbox(void); +static void clar_tempdir_init(void); +static void clar_tempdir_shutdown(void); +static int clar_sandbox_create(const char *suite_name, const char *test_name); +static int clar_sandbox_cleanup(void); /* From summary.h */ static struct clar_summary *clar_summary_init(const char *filename); @@ -215,6 +225,15 @@ static int clar_summary_shutdown(struct clar_summary *fp); _clar.trace_payload); \ } while (0) +static void clar_abort(const char *msg, ...) +{ + va_list argp; + va_start(argp, msg); + clar_print_onabortv(msg, argp); + va_end(argp); + exit(-1); +} + void cl_trace_register(cl_trace_cb *cb, void *payload) { _clar.pfn_trace_cb = cb; @@ -268,9 +287,7 @@ static double clar_time_diff(clar_time *start, clar_time *end) static void clar_time_now(clar_time *out) { - struct timezone tz; - - gettimeofday(out, &tz); + gettimeofday(out, NULL); } static double clar_time_diff(clar_time *start, clar_time *end) @@ -293,6 +310,8 @@ clar_run_test( CL_TRACE(CL_TRACE__TEST__BEGIN); + clar_sandbox_create(suite->name, test->name); + _clar.last_report->start = time(NULL); clar_time_now(&start); @@ -317,9 +336,13 @@ clar_run_test( if (_clar.local_cleanup != NULL) _clar.local_cleanup(_clar.local_cleanup_payload); + clar__clear_invokepoint(); + if (cleanup->ptr != NULL) cleanup->ptr(); + clar_sandbox_cleanup(); + CL_TRACE(CL_TRACE__TEST__END); _clar.tests_ran++; @@ -383,7 +406,8 @@ clar_run_suite(const struct clar_suite *suite, const char *filter) _clar.active_test = test[i].name; - report = calloc(1, sizeof(struct clar_report)); + if ((report = calloc(1, sizeof(*report))) == NULL) + clar_abort("Failed to allocate report.\n"); report->suite = _clar.active_suite; report->test = _clar.active_test; report->test_number = _clar.tests_ran; @@ -421,7 +445,7 @@ clar_usage(const char *arg) printf(" -t Display results in tap format\n"); printf(" -l Print suite names\n"); printf(" -r[filename] Write summary file (to the optional filename)\n"); - exit(-1); + exit(1); } static void @@ -429,18 +453,11 @@ clar_parse_args(int argc, char **argv) { int i; - /* Verify options before execute */ for (i = 1; i < argc; ++i) { char *argument = argv[i]; - if (argument[0] != '-' || argument[1] == '\0' - || strchr("sixvqQtlr", argument[1]) == NULL) { + if (argument[0] != '-' || argument[1] == '\0') clar_usage(argv[0]); - } - } - - for (i = 1; i < argc; ++i) { - char *argument = argv[i]; switch (argument[1]) { case 's': @@ -453,8 +470,13 @@ clar_parse_args(int argc, char **argv) argument += offset; arglen = strlen(argument); - if (arglen == 0) - clar_usage(argv[0]); + if (arglen == 0) { + if (i + 1 == argc) + clar_usage(argv[0]); + + argument = argv[++i]; + arglen = strlen(argument); + } for (j = 0; j < _clar_suite_count; ++j) { suitelen = strlen(_clar_suites[j].name); @@ -471,14 +493,12 @@ clar_parse_args(int argc, char **argv) ++found; - if (!exact) - _clar.verbosity = MAX(_clar.verbosity, 1); - switch (action) { case 's': { - struct clar_explicit *explicit = - calloc(1, sizeof(struct clar_explicit)); - assert(explicit); + struct clar_explicit *explicit; + + if ((explicit = calloc(1, sizeof(*explicit))) == NULL) + clar_abort("Failed to allocate explicit test.\n"); explicit->suite_idx = j; explicit->filter = argument; @@ -502,27 +522,39 @@ clar_parse_args(int argc, char **argv) } } - if (!found) { - clar_print_onabort("No suite matching '%s' found.\n", argument); - exit(-1); - } + if (!found) + clar_abort("No suite matching '%s' found.\n", argument); + break; } case 'q': + if (argument[2] != '\0') + clar_usage(argv[0]); + _clar.report_errors_only = 1; break; case 'Q': + if (argument[2] != '\0') + clar_usage(argv[0]); + _clar.exit_on_error = 1; break; case 't': + if (argument[2] != '\0') + clar_usage(argv[0]); + _clar.output_format = CL_OUTPUT_TAP; break; case 'l': { size_t j; + + if (argument[2] != '\0') + clar_usage(argv[0]); + printf("Test suites (use -s to run just one):\n"); for (j = 0; j < _clar_suite_count; ++j) printf(" %3d: %s\n", (int)j, _clar_suites[j].name); @@ -531,17 +563,27 @@ clar_parse_args(int argc, char **argv) } case 'v': + if (argument[2] != '\0') + clar_usage(argv[0]); + _clar.verbosity++; break; case 'r': _clar.write_summary = 1; free(_clar.summary_filename); - _clar.summary_filename = *(argument + 2) ? strdup(argument + 2) : NULL; + + if (*(argument + 2)) { + if ((_clar.summary_filename = strdup(argument + 2)) == NULL) + clar_abort("Failed to allocate summary filename.\n"); + } else { + _clar.summary_filename = NULL; + } + break; default: - assert(!"Unexpected commandline argument!"); + clar_usage(argv[0]); } } } @@ -563,22 +605,18 @@ clar_test_init(int argc, char **argv) if (!_clar.summary_filename && (summary_env = getenv("CLAR_SUMMARY")) != NULL) { _clar.write_summary = 1; - _clar.summary_filename = strdup(summary_env); + if ((_clar.summary_filename = strdup(summary_env)) == NULL) + clar_abort("Failed to allocate summary filename.\n"); } if (_clar.write_summary && !_clar.summary_filename) - _clar.summary_filename = strdup("summary.xml"); + if ((_clar.summary_filename = strdup("summary.xml")) == NULL) + clar_abort("Failed to allocate summary filename.\n"); - if (_clar.write_summary && - !(_clar.summary = clar_summary_init(_clar.summary_filename))) { - clar_print_onabort("Failed to open the summary file\n"); - exit(-1); - } + if (_clar.write_summary) + _clar.summary = clar_summary_init(_clar.summary_filename); - if (clar_sandbox() < 0) { - clar_print_onabort("Failed to sandbox the test runner.\n"); - exit(-1); - } + clar_tempdir_init(); } int @@ -610,12 +648,11 @@ clar_test_shutdown(void) _clar.total_errors ); - clar_unsandbox(); + clar_tempdir_shutdown(); - if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) { - clar_print_onabort("Failed to write the summary file\n"); - exit(-1); - } + if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) + clar_abort("Failed to write the summary file '%s: %s.\n", + _clar.summary_filename, strerror(errno)); for (explicit = _clar.explicit; explicit; explicit = explicit_next) { explicit_next = explicit->next; @@ -623,6 +660,14 @@ clar_test_shutdown(void) } for (report = _clar.reports; report; report = report_next) { + struct clar_error *error, *error_next; + + for (error = report->errors; error; error = error_next) { + free(error->description); + error_next = error->next; + free(error); + } + report_next = report->next; free(report); } @@ -646,9 +691,9 @@ static void abort_test(void) { if (!_clar.trampoline_enabled) { clar_print_onabort( - "Fatal error: a cleanup method raised an exception."); + "Fatal error: a cleanup method raised an exception.\n"); clar_report_errors(_clar.last_report); - exit(-1); + exit(1); } CL_TRACE(CL_TRACE__TEST__LONGJMP); @@ -670,7 +715,10 @@ void clar__fail( const char *description, int should_abort) { - struct clar_error *error = calloc(1, sizeof(struct clar_error)); + struct clar_error *error; + + if ((error = calloc(1, sizeof(*error))) == NULL) + clar_abort("Failed to allocate error.\n"); if (_clar.last_report->errors == NULL) _clar.last_report->errors = error; @@ -680,13 +728,14 @@ void clar__fail( _clar.last_report->last_error = error; - error->file = file; - error->function = function; - error->line_number = line; + error->file = _clar.invoke_file ? _clar.invoke_file : file; + error->function = _clar.invoke_func ? _clar.invoke_func : function; + error->line_number = _clar.invoke_line ? _clar.invoke_line : line; error->error_msg = error_msg; - if (description != NULL) - error->description = strdup(description); + if (description != NULL && + (error->description = strdup(description)) == NULL) + clar_abort("Failed to allocate description.\n"); _clar.total_errors++; _clar.last_report->status = CL_TEST_FAILURE; @@ -760,6 +809,7 @@ void clar__assert_equal( } } } +#ifdef CLAR_HAVE_WCHAR else if (!strcmp("%ls", fmt)) { const wchar_t *wcs1 = va_arg(args, const wchar_t *); const wchar_t *wcs2 = va_arg(args, const wchar_t *); @@ -795,8 +845,9 @@ void clar__assert_equal( } } } - else if (!strcmp("%"PRIuZ, fmt) || !strcmp("%"PRIxZ, fmt)) { - size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t); +#endif /* CLAR_HAVE_WCHAR */ + else if (!strcmp("%"PRIuMAX, fmt) || !strcmp("%"PRIxMAX, fmt)) { + uintmax_t sz1 = va_arg(args, uintmax_t), sz2 = va_arg(args, uintmax_t); is_equal = (sz1 == sz2); if (!is_equal) { int offset = p_snprintf(buf, sizeof(buf), fmt, sz1); @@ -808,7 +859,8 @@ void clar__assert_equal( void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *); is_equal = (p1 == p2); if (!is_equal) - p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2); + p_snprintf(buf, sizeof(buf), "0x%"PRIxPTR" != 0x%"PRIxPTR, + (uintptr_t)p1, (uintptr_t)p2); } else { int i1 = va_arg(args, int), i2 = va_arg(args, int); @@ -832,6 +884,23 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque) _clar.local_cleanup_payload = opaque; } +void clar__set_invokepoint( + const char *file, + const char *func, + size_t line) +{ + _clar.invoke_file = file; + _clar.invoke_func = func; + _clar.invoke_line = line; +} + +void clar__clear_invokepoint(void) +{ + _clar.invoke_file = NULL; + _clar.invoke_func = NULL; + _clar.invoke_line = 0; +} + #include "clar/sandbox.h" #include "clar/fixtures.h" #include "clar/fs.h" diff --git a/tests/clar/clar.h b/tests/clar/clar.h index 8c22382bd56..ca72292ae91 100644 --- a/tests/clar/clar.h +++ b/tests/clar/clar.h @@ -8,6 +8,25 @@ #define __CLAR_TEST_H__ #include +#include + +#if defined(_WIN32) && defined(CLAR_WIN32_LONGPATHS) +# define CLAR_MAX_PATH 4096 +#elif defined(_WIN32) +# define CLAR_MAX_PATH MAX_PATH +#else +# define CLAR_MAX_PATH PATH_MAX +#endif + +#ifndef CLAR_SELFTEST +# define CLAR_CURRENT_FILE __FILE__ +# define CLAR_CURRENT_LINE __LINE__ +# define CLAR_CURRENT_FUNC __func__ +#else +# define CLAR_CURRENT_FILE "file" +# define CLAR_CURRENT_LINE 42 +# define CLAR_CURRENT_FUNC "func" +#endif enum cl_test_status { CL_TEST_OK, @@ -30,6 +49,7 @@ void clar_test_shutdown(void); int clar_test(int argc, char *argv[]); const char *clar_sandbox_path(void); +const char *clar_tempdir_path(void); void cl_set_cleanup(void (*cleanup)(void *), void *opaque); void cl_fs_cleanup(void); @@ -83,19 +103,33 @@ void cl_fixture_cleanup(const char *fixture_name); const char *cl_fixture_basename(const char *fixture_name); #endif +/** + * Invoke a helper function, which itself will use `cl_assert` + * constructs. This will preserve the stack information of the + * current call point, so that function name and line number + * information is shown from the line of the test, instead of + * the helper function. + */ +#define cl_invoke(expr) \ + do { \ + clar__set_invokepoint(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE); \ + expr; \ + clar__clear_invokepoint(); \ + } while(0) + /** * Assertion macros with explicit error message */ -#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 1) -#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 1) -#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 1) +#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 1) +#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 1) +#define cl_assert_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 1) /** * Check macros with explicit error message */ -#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 0) -#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 0) -#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 0) +#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 0) +#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 0) +#define cl_check_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 0) /** * Assertion macros with no error message @@ -114,33 +148,33 @@ const char *cl_fixture_basename(const char *fixture_name); /** * Forced failure/warning */ -#define cl_fail(desc) clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1) -#define cl_warning(desc) clar__fail(__FILE__, __func__, __LINE__, "Warning during test execution:", desc, 0) +#define cl_fail(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Test failed.", desc, 1) +#define cl_warning(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Warning during test execution:", desc, 0) #define cl_skip() clar__skip() /** * Typed assertion macros */ -#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) -#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) +#define cl_assert_equal_s(s1,s2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) +#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) -#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2)) -#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2)) +#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2)) +#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2)) -#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len)) -#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len)) +#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len)) +#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len)) -#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len)) -#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len)) +#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len)) +#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len)) -#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) -#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) -#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) +#define cl_assert_equal_i(i1,i2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) +#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) +#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) -#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__func__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) +#define cl_assert_equal_b(b1,b2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) -#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__func__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) +#define cl_assert_equal_p(p1,p2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) void clar__skip(void); @@ -170,4 +204,11 @@ void clar__assert_equal( const char *fmt, ...); +void clar__set_invokepoint( + const char *file, + const char *func, + size_t line); + +void clar__clear_invokepoint(void); + #endif diff --git a/tests/clar/clar/fixtures.h b/tests/clar/clar/fixtures.h index 6ec6423484d..9f1023df594 100644 --- a/tests/clar/clar/fixtures.h +++ b/tests/clar/clar/fixtures.h @@ -2,7 +2,7 @@ static const char * fixture_path(const char *base, const char *fixture_name) { - static char _path[4096]; + static char _path[CLAR_MAX_PATH]; size_t root_len; root_len = strlen(base); @@ -28,7 +28,7 @@ const char *cl_fixture(const char *fixture_name) void cl_fixture_sandbox(const char *fixture_name) { - fs_copy(cl_fixture(fixture_name), _clar_path); + fs_copy(cl_fixture(fixture_name), clar_sandbox_path()); } const char *cl_fixture_basename(const char *fixture_name) @@ -45,6 +45,6 @@ const char *cl_fixture_basename(const char *fixture_name) void cl_fixture_cleanup(const char *fixture_name) { - fs_rm(fixture_path(_clar_path, cl_fixture_basename(fixture_name))); + fs_rm(fixture_path(clar_sandbox_path(), cl_fixture_basename(fixture_name))); } #endif diff --git a/tests/clar/clar/fs.h b/tests/clar/clar/fs.h index a6eda5e5dc2..42fa4719468 100644 --- a/tests/clar/clar/fs.h +++ b/tests/clar/clar/fs.h @@ -8,12 +8,6 @@ #ifdef _WIN32 -#ifdef CLAR_WIN32_LONGPATHS -# define CLAR_MAX_PATH 4096 -#else -# define CLAR_MAX_PATH MAX_PATH -#endif - #define RM_RETRY_COUNT 5 #define RM_RETRY_DELAY 10 @@ -146,7 +140,7 @@ fs_rm_wait(WCHAR *_wpath) ERROR_PATH_NOT_FOUND == last_error) return 0; - Sleep(RM_RETRY_DELAY * retries * retries); + Sleep(RM_RETRY_DELAY * retries * retries); } while (retries++ <= RM_RETRY_COUNT); @@ -296,7 +290,9 @@ void cl_fs_cleanup(void) { #ifdef CLAR_FIXTURE_PATH - fs_rm(fixture_path(_clar_path, "*")); + fs_rm(fixture_path(clar_tempdir_path(), "*")); +#else + ((void)fs_copy); /* unused */ #endif } @@ -516,7 +512,7 @@ fs_rm(const char *path) void cl_fs_cleanup(void) { - clar_unsandbox(); - clar_sandbox(); + clar_tempdir_shutdown(); + clar_tempdir_init(); } #endif diff --git a/tests/clar/clar/print.h b/tests/clar/clar/print.h index c17e2f693bd..f577c01c40a 100644 --- a/tests/clar/clar/print.h +++ b/tests/clar/clar/print.h @@ -21,7 +21,7 @@ static void clar_print_clap_error(int num, const struct clar_report *report, con { printf(" %d) Failure:\n", num); - printf("%s::%s [%s:%"PRIuZ"]\n", + printf("%s::%s [%s:%"PRIuMAX"]\n", report->suite, report->test, error->file, @@ -47,8 +47,8 @@ static void clar_print_clap_ontest(const char *suite_name, const char *test_name switch (status) { case CL_TEST_OK: printf("ok\n"); break; case CL_TEST_FAILURE: printf("fail\n"); break; - case CL_TEST_SKIP: printf("skipped"); break; - case CL_TEST_NOTRUN: printf("notrun"); break; + case CL_TEST_SKIP: printf("skipped\n"); break; + case CL_TEST_NOTRUN: printf("notrun\n"); break; } } else { switch (status) { @@ -136,7 +136,7 @@ static void clar_print_tap_ontest(const char *suite_name, const char *test_name, printf(" at:\n"); printf(" file: '"); print_escaped(error->file); printf("'\n"); - printf(" line: %" PRIuZ "\n", error->line_number); + printf(" line: %" PRIuMAX "\n", error->line_number); printf(" function: '%s'\n", error->function); printf(" ---\n"); @@ -202,10 +202,15 @@ static void clar_print_onsuite(const char *suite_name, int suite_index) PRINT(onsuite, suite_name, suite_index); } +static void clar_print_onabortv(const char *msg, va_list argp) +{ + PRINT(onabort, msg, argp); +} + static void clar_print_onabort(const char *msg, ...) { va_list argp; va_start(argp, msg); - PRINT(onabort, msg, argp); + clar_print_onabortv(msg, argp); va_end(argp); } diff --git a/tests/clar/clar/sandbox.h b/tests/clar/clar/sandbox.h index 0688374f8d6..ff431599d52 100644 --- a/tests/clar/clar/sandbox.h +++ b/tests/clar/clar/sandbox.h @@ -2,8 +2,17 @@ #include #endif -#define CLAR_PATH_MAX 4096 -static char _clar_path[CLAR_PATH_MAX]; +/* + * The tempdir is the temporary directory for the entirety of the clar + * process execution. The sandbox is an individual temporary directory + * for the execution of an individual test. Sandboxes are deleted + * entirely after test execution to avoid pollution across tests. + */ + +static char _clar_tempdir[CLAR_MAX_PATH]; +static size_t _clar_tempdir_len; + +static char _clar_sandbox[CLAR_MAX_PATH]; static int is_valid_tmp_path(const char *path) @@ -16,7 +25,10 @@ is_valid_tmp_path(const char *path) if (!S_ISDIR(st.st_mode)) return 0; - return (access(path, W_OK) == 0); + if (access(path, W_OK) != 0) + return 0; + + return (strlen(path) < CLAR_MAX_PATH); } static int @@ -26,19 +38,17 @@ find_tmp_path(char *buffer, size_t length) static const size_t var_count = 5; static const char *env_vars[] = { "CLAR_TMP", "TMPDIR", "TMP", "TEMP", "USERPROFILE" - }; + }; - size_t i; + size_t i; for (i = 0; i < var_count; ++i) { const char *env = getenv(env_vars[i]); + if (!env) continue; if (is_valid_tmp_path(env)) { - if (strlen(env) + 1 > CLAR_PATH_MAX) - return -1; - strncpy(buffer, env, length - 1); buffer[length - 1] = '\0'; return 0; @@ -53,11 +63,12 @@ find_tmp_path(char *buffer, size_t length) } #else - DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length); - if (env_len > 0 && env_len < (DWORD)length) + DWORD len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length); + if (len > 0 && len < (DWORD)length) return 0; - if (GetTempPath((DWORD)length, buffer)) + len = GetTempPath((DWORD)length, buffer); + if (len > 0 && len < (DWORD)length) return 0; #endif @@ -74,42 +85,50 @@ find_tmp_path(char *buffer, size_t length) static int canonicalize_tmp_path(char *buffer) { #ifdef _WIN32 - char tmp[CLAR_PATH_MAX]; + char tmp[CLAR_MAX_PATH], *p; DWORD ret; - ret = GetFullPathName(buffer, CLAR_PATH_MAX, tmp, NULL); + ret = GetFullPathName(buffer, CLAR_MAX_PATH, tmp, NULL); - if (ret == 0 || ret > CLAR_PATH_MAX) + if (ret == 0 || ret > CLAR_MAX_PATH) return -1; - ret = GetLongPathName(tmp, buffer, CLAR_PATH_MAX); + ret = GetLongPathName(tmp, buffer, CLAR_MAX_PATH); - if (ret == 0 || ret > CLAR_PATH_MAX) + if (ret == 0 || ret > CLAR_MAX_PATH) return -1; + /* normalize path to POSIX forward slashes */ + for (p = buffer; *p; p++) + if (*p == '\\') + *p = '/'; + return 0; -#else - char tmp[CLAR_PATH_MAX]; +#elif defined(CLAR_HAS_REALPATH) + char tmp[CLAR_MAX_PATH]; if (realpath(buffer, tmp) == NULL) return -1; strcpy(buffer, tmp); return 0; +#else + (void)buffer; + return 0; #endif } -static void clar_unsandbox(void) +static void clar_tempdir_shutdown(void) { - if (_clar_path[0] == '\0') + if (_clar_tempdir[0] == '\0') return; cl_must_pass(chdir("..")); - fs_rm(_clar_path); + fs_rm(_clar_tempdir); } -static int build_sandbox_path(void) +static int build_tempdir_path(void) { #ifdef CLAR_TMPDIR const char path_tail[] = CLAR_TMPDIR "_XXXXXX"; @@ -119,61 +138,153 @@ static int build_sandbox_path(void) size_t len; - if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0 || - canonicalize_tmp_path(_clar_path) < 0) + if (find_tmp_path(_clar_tempdir, sizeof(_clar_tempdir)) < 0 || + canonicalize_tmp_path(_clar_tempdir) < 0) return -1; - len = strlen(_clar_path); + len = strlen(_clar_tempdir); -#ifdef _WIN32 - { /* normalize path to POSIX forward slashes */ - size_t i; - for (i = 0; i < len; ++i) { - if (_clar_path[i] == '\\') - _clar_path[i] = '/'; - } - } -#endif + if (len + strlen(path_tail) + 2 > CLAR_MAX_PATH) + return -1; - if (_clar_path[len - 1] != '/') { - _clar_path[len++] = '/'; - } + if (_clar_tempdir[len - 1] != '/') + _clar_tempdir[len++] = '/'; - strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len); + strncpy(_clar_tempdir + len, path_tail, sizeof(_clar_tempdir) - len); #if defined(__MINGW32__) - if (_mktemp(_clar_path) == NULL) + if (_mktemp(_clar_tempdir) == NULL) return -1; - if (mkdir(_clar_path, 0700) != 0) + if (mkdir(_clar_tempdir, 0700) != 0) return -1; #elif defined(_WIN32) - if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0) + if (_mktemp_s(_clar_tempdir, sizeof(_clar_tempdir)) != 0) return -1; - if (mkdir(_clar_path, 0700) != 0) + if (mkdir(_clar_tempdir, 0700) != 0) + return -1; +#elif defined(__sun) || defined(__TANDEM) + if (mktemp(_clar_tempdir) == NULL) + return -1; + + if (mkdir(_clar_tempdir, 0700) != 0) return -1; #else - if (mkdtemp(_clar_path) == NULL) + if (mkdtemp(_clar_tempdir) == NULL) return -1; #endif + _clar_tempdir_len = strlen(_clar_tempdir); return 0; } -static int clar_sandbox(void) +static void clar_tempdir_init(void) { - if (_clar_path[0] == '\0' && build_sandbox_path() < 0) + if (_clar_tempdir[0] == '\0' && build_tempdir_path() < 0) + clar_abort("Failed to build tempdir path.\n"); + + if (chdir(_clar_tempdir) != 0) + clar_abort("Failed to change into tempdir '%s': %s.\n", + _clar_tempdir, strerror(errno)); + +#if !defined(CLAR_SANDBOX_TEST_NAMES) && defined(_WIN32) + srand(clock() ^ (unsigned int)time(NULL) ^ GetCurrentProcessId() ^ GetCurrentThreadId()); +#elif !defined(CLAR_SANDBOX_TEST_NAMES) + srand(clock() ^ time(NULL) ^ (getpid() << 16)); +#endif +} + +static void append(char *dst, const char *src) +{ + char *d; + const char *s; + + for (d = dst; *d; d++) + ; + + for (s = src; *s; d++, s++) + if (*s == ':') + *d = '_'; + else + *d = *s; + + *d = '\0'; +} + +static int clar_sandbox_create(const char *suite_name, const char *test_name) +{ +#ifndef CLAR_SANDBOX_TEST_NAMES + char alpha[] = "0123456789abcdef"; + int num = rand(); +#endif + + cl_assert(_clar_sandbox[0] == '\0'); + + /* + * We may want to use test names as sandbox directory names for + * readability, _however_ on platforms with restrictions for short + * file / folder names (eg, Windows), this may be too long. + */ +#ifdef CLAR_SANDBOX_TEST_NAMES + cl_assert(strlen(_clar_tempdir) + strlen(suite_name) + strlen(test_name) + 3 < CLAR_MAX_PATH); + + strcpy(_clar_sandbox, _clar_tempdir); + _clar_sandbox[_clar_tempdir_len] = '/'; + _clar_sandbox[_clar_tempdir_len + 1] = '\0'; + + append(_clar_sandbox, suite_name); + append(_clar_sandbox, "__"); + append(_clar_sandbox, test_name); +#else + ((void)suite_name); + ((void)test_name); + ((void)append); + + cl_assert(strlen(_clar_tempdir) + 9 < CLAR_MAX_PATH); + + strcpy(_clar_sandbox, _clar_tempdir); + _clar_sandbox[_clar_tempdir_len] = '/'; + + _clar_sandbox[_clar_tempdir_len + 1] = alpha[(num & 0xf0000000) >> 28]; + _clar_sandbox[_clar_tempdir_len + 2] = alpha[(num & 0x0f000000) >> 24]; + _clar_sandbox[_clar_tempdir_len + 3] = alpha[(num & 0x00f00000) >> 20]; + _clar_sandbox[_clar_tempdir_len + 4] = alpha[(num & 0x000f0000) >> 16]; + _clar_sandbox[_clar_tempdir_len + 5] = alpha[(num & 0x0000f000) >> 12]; + _clar_sandbox[_clar_tempdir_len + 6] = alpha[(num & 0x00000f00) >> 8]; + _clar_sandbox[_clar_tempdir_len + 7] = alpha[(num & 0x000000f0) >> 4]; + _clar_sandbox[_clar_tempdir_len + 8] = alpha[(num & 0x0000000f) >> 0]; + _clar_sandbox[_clar_tempdir_len + 9] = '\0'; +#endif + + if (mkdir(_clar_sandbox, 0700) != 0) return -1; - if (chdir(_clar_path) != 0) + if (chdir(_clar_sandbox) != 0) return -1; return 0; } -const char *clar_sandbox_path(void) +static int clar_sandbox_cleanup(void) +{ + cl_assert(_clar_sandbox[0] != '\0'); + + if (chdir(_clar_tempdir) != 0) + return -1; + + fs_rm(_clar_sandbox); + _clar_sandbox[0] = '\0'; + + return 0; +} + +const char *clar_tempdir_path(void) { - return _clar_path; + return _clar_tempdir; } +const char *clar_sandbox_path(void) +{ + return _clar_sandbox; +} diff --git a/tests/clar/clar/summary.h b/tests/clar/clar/summary.h index 4dd352e28b8..0d0b646fe75 100644 --- a/tests/clar/clar/summary.h +++ b/tests/clar/clar/summary.h @@ -66,16 +66,12 @@ struct clar_summary *clar_summary_init(const char *filename) struct clar_summary *summary; FILE *fp; - if ((fp = fopen(filename, "w")) == NULL) { - perror("fopen"); - return NULL; - } + if ((fp = fopen(filename, "w")) == NULL) + clar_abort("Failed to open the summary file '%s': %s.\n", + filename, strerror(errno)); - if ((summary = malloc(sizeof(struct clar_summary))) == NULL) { - perror("malloc"); - fclose(fp); - return NULL; - } + if ((summary = malloc(sizeof(struct clar_summary))) == NULL) + clar_abort("Failed to allocate summary.\n"); summary->filename = filename; summary->fp = fp; diff --git a/tests/clar/clar_libgit2.c b/tests/clar/clar_libgit2.c index a1b92fc336e..c4a2dfc7e48 100644 --- a/tests/clar/clar_libgit2.c +++ b/tests/clar/clar_libgit2.c @@ -649,7 +649,7 @@ void cl_sandbox_set_homedir(const char *home) if (home) { git_libgit2_opts(GIT_OPT_SET_HOMEDIR, home); } else { - git_str_joinpath(&path, clar_sandbox_path(), "__home"); + git_str_joinpath(&path, clar_tempdir_path(), "__home"); if (!git_fs_path_exists(path.ptr)) cl_must_pass(p_mkdir(path.ptr, 0777)); @@ -664,7 +664,7 @@ void cl_sandbox_set_search_path_defaults(void) { git_str path = GIT_STR_INIT; - git_str_joinpath(&path, clar_sandbox_path(), "__config"); + git_str_joinpath(&path, clar_tempdir_path(), "__config"); if (!git_fs_path_exists(path.ptr)) cl_must_pass(p_mkdir(path.ptr, 0777)); diff --git a/tests/libgit2/CMakeLists.txt b/tests/libgit2/CMakeLists.txt index f058b6e97ce..7a4bb476ca5 100644 --- a/tests/libgit2/CMakeLists.txt +++ b/tests/libgit2/CMakeLists.txt @@ -18,6 +18,7 @@ set(TEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}") add_definitions(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\") add_definitions(-DCLAR_TMPDIR=\"libgit2_tests\") add_definitions(-DCLAR_WIN32_LONGPATHS) +add_definitions(-DCLAR_HAS_REALPATH) add_definitions(-D_FILE_OFFSET_BITS=64) # Ensure that we do not use deprecated functions internally diff --git a/tests/libgit2/checkout/conflict.c b/tests/libgit2/checkout/conflict.c index ab4d0aba4d4..a40c3fc2fca 100644 --- a/tests/libgit2/checkout/conflict.c +++ b/tests/libgit2/checkout/conflict.c @@ -965,17 +965,17 @@ void test_checkout_conflict__name_mangled_file_exists_in_workdir(void) 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); /* Name is mangled on case insensitive only */ -#if defined(GIT_WIN32) || defined(__APPLE__) - ensure_workdir("test-three.txt~ours_0", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); - ensure_workdir("test-three.txt~theirs_0", - 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); -#else - ensure_workdir("test-three.txt~ours", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); - ensure_workdir("test-three.txt~theirs", - 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); -#endif + if (cl_repo_get_bool(g_repo, "core.ignorecase")) { + ensure_workdir("test-three.txt~ours_0", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-three.txt~theirs_0", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); + } else { + ensure_workdir("test-three.txt~ours", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-three.txt~theirs", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); + } ensure_workdir("directory_file-one~ours_0", 0100644, CONFLICTING_OURS_OID); ensure_workdir("directory_file-two~theirs_0", 0100644, CONFLICTING_THEIRS_OID); diff --git a/tests/libgit2/config/global.c b/tests/libgit2/config/global.c index 5aba4eec69e..d382f970eee 100644 --- a/tests/libgit2/config/global.c +++ b/tests/libgit2/config/global.c @@ -20,6 +20,11 @@ void test_config_global__initialize(void) cl_git_pass(git_libgit2_opts( GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + cl_git_pass(git_futils_mkdir_r("programdata", 0777)); + cl_git_pass(git_fs_path_prettify(&path, "programdata", NULL)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_PROGRAMDATA, path.ptr)); + git_str_dispose(&path); } diff --git a/tests/libgit2/diff/stats.c b/tests/libgit2/diff/stats.c index 7af89155084..71ea7ea0ee7 100644 --- a/tests/libgit2/diff/stats.c +++ b/tests/libgit2/diff/stats.c @@ -229,6 +229,26 @@ void test_diff_stats__rename_in_subdirectory(void) git_buf_dispose(&buf); } +void test_diff_stats__rename_in_subdirectory_aligns(void) +{ + git_buf buf = GIT_BUF_INIT; + const char *stat = + " dir/{renamed.txt => rerenamed.txt} | 0\n" + " file3.txt | 2 +-\n" + " 2 files changed, 1 insertion(+), 1 deletion(-)\n"; + + diff_stats_from_commit_oid( + &_stats, "7f4c6d9d6ba363e3352f7c21807ca3a7835072b2", true); + + cl_assert_equal_sz(2, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(1, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(1, git_diff_stats_deletions(_stats)); + + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, buf.ptr); + git_buf_dispose(&buf); +} + void test_diff_stats__rename_no_find(void) { git_buf buf = GIT_BUF_INIT; diff --git a/tests/libgit2/filter/query.c b/tests/libgit2/filter/query.c index 429c1044324..d57b808cd9b 100644 --- a/tests/libgit2/filter/query.c +++ b/tests/libgit2/filter/query.c @@ -53,6 +53,18 @@ void test_filter_query__filters(void) cl_assert_equal_i(1, filter_for("id.binident", "ident")); } +void test_filter_query__filters_ignorecase(void) +{ + if (!cl_repo_get_bool(g_repo, "core.ignorecase")) + cl_skip(); + + cl_assert_equal_i(1, filter_for("TEXT.TXT", "crlf")); + cl_assert_equal_i(0, filter_for("Binary.bin", "crlf")); + + cl_assert_equal_i(1, filter_for("id.Ident", "crlf")); + cl_assert_equal_i(1, filter_for("ID.IdEnT", "ident")); +} + void test_filter_query__autocrlf_true_implies_crlf(void) { cl_repo_set_bool(g_repo, "core.autocrlf", true); diff --git a/tests/libgit2/filter/systemattrs.c b/tests/libgit2/filter/systemattrs.c index b687b4b44cd..5f669e35124 100644 --- a/tests/libgit2/filter/systemattrs.c +++ b/tests/libgit2/filter/systemattrs.c @@ -1,21 +1,30 @@ #include "clar_libgit2.h" #include "crlf.h" #include "path.h" +#include "futils.h" static git_repository *g_repo = NULL; +static git_str orig_system_path = GIT_STR_INIT; static git_str system_attr_path = GIT_STR_INIT; void test_filter_systemattrs__initialize(void) { - git_buf system_path = GIT_BUF_INIT; + git_str new_system_path = GIT_BUF_INIT; g_repo = cl_git_sandbox_init("crlf"); cl_must_pass(p_unlink("crlf/.gitattributes")); cl_git_pass(git_libgit2_opts( - GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, &system_path)); + GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, &orig_system_path)); + + cl_git_pass(git_str_joinpath(&new_system_path, + clar_sandbox_path(), "_system_path")); + cl_git_pass(git_futils_mkdir_r(new_system_path.ptr, 0777)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, new_system_path.ptr)); + cl_git_pass(git_str_joinpath(&system_attr_path, - system_path.ptr, "gitattributes")); + new_system_path.ptr, "gitattributes")); cl_git_mkfile(system_attr_path.ptr, "*.txt text\n" @@ -23,13 +32,17 @@ void test_filter_systemattrs__initialize(void) "*.crlf text eol=crlf\n" "*.lf text eol=lf\n"); - git_buf_dispose(&system_path); + git_str_dispose(&new_system_path); } void test_filter_systemattrs__cleanup(void) { + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, orig_system_path.ptr)); + cl_must_pass(p_unlink(system_attr_path.ptr)); git_str_dispose(&system_attr_path); + git_str_dispose(&orig_system_path); cl_git_sandbox_cleanup(); } diff --git a/tests/libgit2/odb/alternates.c b/tests/libgit2/odb/alternates.c index 4d2da6b1f39..0278f4497f1 100644 --- a/tests/libgit2/odb/alternates.c +++ b/tests/libgit2/odb/alternates.c @@ -78,3 +78,39 @@ void test_odb_alternates__long_chain(void) cl_git_fail(git_commit_lookup(&commit, repo, &oid)); git_repository_free(repo); } + +void test_odb_alternates__relative(void) +{ + git_commit *commit; + git_oid oid; + + /* Set the alternate A -> testrepo.git */ + init_linked_repo(paths[0], cl_fixture("testrepo.git")); + + /* Set the alternate B -> A */ + init_linked_repo(paths[1], paths[0]); + /* Set the alternate C -> B */ + init_linked_repo(paths[2], paths[1]); + + /* Use a relative alternates path for B -> A */ + cl_git_pass(git_fs_path_prettify(&filepath, paths[1], NULL)); + cl_git_pass(git_str_joinpath(&filepath, filepath.ptr, "objects/info/alternates")); + + cl_git_pass(git_filebuf_open(&file, git_str_cstr(&filepath), 0, 0666)); + git_filebuf_printf(&file, "../../%s/objects\n", paths[0]); + cl_git_pass(git_filebuf_commit(&file)); + + /* Now load B and see if we can find an object from testrepo.git */ + cl_git_pass(git_repository_open(&repo, paths[1])); + git_oid__fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OID_SHA1); + cl_git_pass(git_commit_lookup(&commit, repo, &oid)); + git_commit_free(commit); + git_repository_free(repo); + + /* Now load C and see if we can find an object from testrepo.git */ + cl_git_pass(git_repository_open(&repo, paths[2])); + git_oid__fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OID_SHA1); + cl_git_pass(git_commit_lookup(&commit, repo, &oid)); + git_commit_free(commit); + git_repository_free(repo); +} diff --git a/tests/libgit2/refs/tags/name.c b/tests/libgit2/refs/tags/name.c index 1dd1760b9ed..bc6cbaef56b 100644 --- a/tests/libgit2/refs/tags/name.c +++ b/tests/libgit2/refs/tags/name.c @@ -11,7 +11,9 @@ void test_refs_tags_name__is_name_valid(void) { cl_assert_equal_i(true, name_is_valid("sometag")); cl_assert_equal_i(true, name_is_valid("test/sometag")); + cl_assert_equal_i(true, name_is_valid("test/HEAD")); cl_assert_equal_i(false, name_is_valid("")); cl_assert_equal_i(false, name_is_valid("-dash")); + cl_assert_equal_i(false, name_is_valid("HEAD")); } diff --git a/tests/libgit2/transport/register.c b/tests/libgit2/transport/register.c index 4d3c09726da..1554afc23c2 100644 --- a/tests/libgit2/transport/register.c +++ b/tests/libgit2/transport/register.c @@ -144,6 +144,7 @@ static int custom_subtransport__action( git_remote_connect_options_dispose(&opts); *out = git__calloc(1, sizeof(git_smart_subtransport_stream)); + GIT_ERROR_CHECK_ALLOC(*out); (*out)->subtransport = transport; (*out)->read = custom_subtransport_stream__read; (*out)->write = custom_subtransport_stream__write; @@ -169,6 +170,7 @@ static void custom_subtransport__free(git_smart_subtransport *transport) static int custom_transport_callback(git_smart_subtransport **out, git_transport *owner, void *param) { struct custom_subtransport *subtransport = git__calloc(1, sizeof(struct custom_subtransport)); + GIT_ERROR_CHECK_ALLOC(subtransport); subtransport->called = (int *)param; subtransport->owner = owner; subtransport->subtransport.action = custom_subtransport__action; diff --git a/tests/resources/diff_format_email/.gitted/index b/tests/resources/diff_format_email/.gitted/index index 4514a6b9c76..7053c2159d6 100644 Binary files a/tests/resources/diff_format_email/.gitted/index and b/tests/resources/diff_format_email/.gitted/index differ diff --git a/tests/resources/diff_format_email/.gitted/objects/7f/4c6d9d6ba363e3352f7c21807ca3a7835072b2 b/tests/resources/diff_format_email/.gitted/objects/7f/4c6d9d6ba363e3352f7c21807ca3a7835072b2 new file mode 100644 index 00000000000..1be0e79273a --- /dev/null +++ b/tests/resources/diff_format_email/.gitted/objects/7f/4c6d9d6ba363e3352f7c21807ca3a7835072b2 @@ -0,0 +1 @@ +xKj1EьLZ[JǢR@v