Commit 8978f1de by Vicent Marti

Merge branch 'clar2' into development

Conflicts:
	src/pqueue.c
	src/pqueue.h
	src/util.c
	tests-clar/merge/setup.c
parents 686a243a a7ffd936
/tests-clar/clar.h
/tests-clar/clar_main.c
/tests-clar/clar_main.c.rule
/tests-clar/clar.suite
/tests-clar/.clarcache
/apidocs
/trash-*.exe
/libgit2.pc
......@@ -28,4 +27,4 @@ CMake*
.DS_Store
*~
tags
mkmf.log
\ No newline at end of file
mkmf.log
......@@ -148,7 +148,7 @@ IF (MSVC)
# Precompiled headers
ELSE ()
SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra -Wno-missing-field-initializers -Wstrict-aliasing=2 -Wstrict-prototypes -Wmissing-prototypes ${CMAKE_C_FLAGS}")
SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra -Wno-missing-field-initializers -Wstrict-aliasing=2 -Wstrict-prototypes ${CMAKE_C_FLAGS}")
IF (MINGW) # MinGW always does PIC and complains if we tell it to
STRING(REGEX REPLACE "-fPIC" "" CMAKE_SHARED_LIBRARY_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
ELSE ()
......@@ -233,7 +233,6 @@ INSTALL(FILES include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} )
# Tests
IF (BUILD_CLAR)
FIND_PACKAGE(PythonInterp REQUIRED)
SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests-clar/resources/")
......@@ -243,26 +242,33 @@ IF (BUILD_CLAR)
ADD_DEFINITIONS(-DCLAR_RESOURCES=\"${TEST_RESOURCES}\")
INCLUDE_DIRECTORIES(${CLAR_PATH})
FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/clar_helpers.c ${CLAR_PATH}/testlib.c)
FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c)
SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar.c")
ADD_CUSTOM_COMMAND(
OUTPUT ${CLAR_PATH}/clar_main.c ${CLAR_PATH}/clar.h
COMMAND ${PYTHON_EXECUTABLE} clar .
DEPENDS ${CLAR_PATH}/clar ${SRC_TEST}
OUTPUT ${CLAR_PATH}/clar.suite
COMMAND ${PYTHON_EXECUTABLE} generate.py -xonline .
DEPENDS ${SRC_TEST}
WORKING_DIRECTORY ${CLAR_PATH}
)
ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1})
SET_SOURCE_FILES_PROPERTIES(
${CLAR_PATH}/clar.c
PROPERTIES OBJECT_DEPENDS ${CLAR_PATH}/clar.suite)
ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1})
TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES})
TARGET_OS_LIBRARIES(libgit2_clar)
MSVC_SPLIT_SOURCES(libgit2_clar)
IF (MSVC_IDE)
# Precompiled headers
SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
ENDIF ()
IF (MSVC_IDE)
# Precompiled headers
SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
ENDIF ()
ENABLE_TESTING()
ADD_TEST(libgit2_clar libgit2_clar -iall)
ADD_TEST(libgit2_clar libgit2_clar)
ENDIF ()
IF (TAGS)
......
#include <assert.h>
#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
/* required for sandboxing */
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _WIN32
# include <windows.h>
# include <io.h>
# include <shellapi.h>
# include <direct.h>
# define _MAIN_CC __cdecl
# define stat(path, st) _stat(path, st)
# define mkdir(path, mode) _mkdir(path)
# define chdir(path) _chdir(path)
# define access(path, mode) _access(path, mode)
# define strdup(str) _strdup(str)
# define strcasecmp(a,b) _stricmp(a,b)
# ifndef __MINGW32__
# pragma comment(lib, "shell32")
# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE)
# define W_OK 02
# define S_ISDIR(x) ((x & _S_IFDIR) != 0)
# define snprint_eq(buf,sz,fmt,a,b) _snprintf_s(buf,sz,_TRUNCATE,fmt,a,b)
# else
# define snprint_eq snprintf
# endif
typedef struct _stat STAT_T;
#else
# include <sys/wait.h> /* waitpid(2) */
# include <unistd.h>
# define _MAIN_CC
# define snprint_eq snprintf
typedef struct stat STAT_T;
#endif
#include "clar.h"
static void fs_rm(const char *_source);
static void fs_copy(const char *_source, const char *dest);
static const char *
fixture_path(const char *base, const char *fixture_name);
struct clar_error {
const char *test;
int test_number;
const char *suite;
const char *file;
int line_number;
const char *error_msg;
char *description;
struct clar_error *next;
};
static struct {
const char *active_test;
const char *active_suite;
int suite_errors;
int total_errors;
int tests_ran;
int suites_ran;
int report_errors_only;
int exit_on_error;
struct clar_error *errors;
struct clar_error *last_error;
void (*local_cleanup)(void *);
void *local_cleanup_payload;
jmp_buf trampoline;
int trampoline_enabled;
} _clar;
struct clar_func {
const char *name;
void (*ptr)(void);
};
struct clar_suite {
const char *name;
struct clar_func initialize;
struct clar_func cleanup;
const struct clar_func *tests;
size_t test_count;
int enabled;
};
/* From clar_print_*.c */
static void clar_print_init(int test_count, int suite_count, const char *suite_names);
static void clar_print_shutdown(int test_count, int suite_count, int error_count);
static void clar_print_error(int num, const struct clar_error *error);
static void clar_print_ontest(const char *test_name, int test_number, int failed);
static void clar_print_onsuite(const char *suite_name, int suite_index);
static void clar_print_onabort(const char *msg, ...);
/* From clar_sandbox.c */
static void clar_unsandbox(void);
static int clar_sandbox(void);
/* Load the declarations for the test suite */
#include "clar.suite"
/* Core test functions */
static void
clar_report_errors(void)
{
int i = 1;
struct clar_error *error, *next;
error = _clar.errors;
while (error != NULL) {
next = error->next;
clar_print_error(i++, error);
free(error->description);
free(error);
error = next;
}
_clar.errors = _clar.last_error = NULL;
}
static void
clar_run_test(
const struct clar_func *test,
const struct clar_func *initialize,
const struct clar_func *cleanup)
{
int error_st = _clar.suite_errors;
_clar.trampoline_enabled = 1;
if (setjmp(_clar.trampoline) == 0) {
if (initialize->ptr != NULL)
initialize->ptr();
test->ptr();
}
_clar.trampoline_enabled = 0;
if (_clar.local_cleanup != NULL)
_clar.local_cleanup(_clar.local_cleanup_payload);
if (cleanup->ptr != NULL)
cleanup->ptr();
_clar.tests_ran++;
/* remove any local-set cleanup methods */
_clar.local_cleanup = NULL;
_clar.local_cleanup_payload = NULL;
if (_clar.report_errors_only)
clar_report_errors();
else
clar_print_ontest(
test->name,
_clar.tests_ran,
(_clar.suite_errors > error_st)
);
}
static void
clar_run_suite(const struct clar_suite *suite)
{
const struct clar_func *test = suite->tests;
size_t i;
if (!suite->enabled)
return;
if (_clar.exit_on_error && _clar.total_errors)
return;
if (!_clar.report_errors_only)
clar_print_onsuite(suite->name, ++_clar.suites_ran);
_clar.active_suite = suite->name;
_clar.suite_errors = 0;
for (i = 0; i < suite->test_count; ++i) {
_clar.active_test = test[i].name;
clar_run_test(&test[i], &suite->initialize, &suite->cleanup);
if (_clar.exit_on_error && _clar.total_errors)
return;
}
}
static void
clar_usage(const char *arg)
{
printf("Usage: %s [options]\n\n", arg);
printf("Options:\n");
printf(" -sname\t\tRun only the suite with `name`\n");
printf(" -iname\t\tInclude the suite with `name`\n");
printf(" -xname\t\tExclude the suite with `name`\n");
printf(" -q \t\tOnly report tests that had an error\n");
printf(" -Q \t\tQuit as soon as a test fails\n");
printf(" -l \t\tPrint suite names\n");
exit(-1);
}
static void
clar_parse_args(int argc, char **argv)
{
int i;
for (i = 1; i < argc; ++i) {
char *argument = argv[i];
if (argument[0] != '-')
clar_usage(argv[0]);
switch (argument[1]) {
case 's':
case 'i':
case 'x': { /* given suite name */
int offset = (argument[2] == '=') ? 3 : 2;
char action = argument[1];
size_t j, len;
argument += offset;
len = strlen(argument);
if (len == 0)
clar_usage(argv[0]);
for (j = 0; j < _clar_suite_count; ++j) {
if (strncmp(argument, _clar_suites[j].name, len) == 0) {
switch (action) {
case 's': clar_run_suite(&_clar_suites[j]); break;
case 'i': _clar_suites[j].enabled = 1; break;
case 'x': _clar_suites[j].enabled = 0; break;
}
break;
}
}
if (j == _clar_suite_count) {
clar_print_onabort("No suite matching '%s' found.\n", argument);
exit(-1);
}
break;
}
case 'q':
_clar.report_errors_only = 1;
break;
case 'Q':
_clar.exit_on_error = 1;
break;
case 'l': {
size_t j;
printf("Test suites (use -s<name> to run just one):\n");
for (j = 0; j < _clar_suite_count; ++j)
printf(" %3d: %s\n", (int)j, _clar_suites[j].name);
exit(0);
}
default:
clar_usage(argv[0]);
}
}
}
int
clar_test(int argc, char **argv)
{
clar_print_init(
(int)_clar_callback_count,
(int)_clar_suite_count,
""
);
if (clar_sandbox() < 0) {
clar_print_onabort("Failed to sandbox the test runner.\n");
exit(-1);
}
if (argc > 1)
clar_parse_args(argc, argv);
if (!_clar.suites_ran) {
size_t i;
for (i = 0; i < _clar_suite_count; ++i)
clar_run_suite(&_clar_suites[i]);
}
clar_print_shutdown(
_clar.tests_ran,
(int)_clar_suite_count,
_clar.total_errors
);
clar_unsandbox();
return _clar.total_errors;
}
void
clar__assert(
int condition,
const char *file,
int line,
const char *error_msg,
const char *description,
int should_abort)
{
struct clar_error *error;
if (condition)
return;
error = calloc(1, sizeof(struct clar_error));
if (_clar.errors == NULL)
_clar.errors = error;
if (_clar.last_error != NULL)
_clar.last_error->next = error;
_clar.last_error = error;
error->test = _clar.active_test;
error->test_number = _clar.tests_ran;
error->suite = _clar.active_suite;
error->file = file;
error->line_number = line;
error->error_msg = error_msg;
if (description != NULL)
error->description = strdup(description);
_clar.suite_errors++;
_clar.total_errors++;
if (should_abort) {
if (!_clar.trampoline_enabled) {
clar_print_onabort(
"Fatal error: a cleanup method raised an exception.");
clar_report_errors();
exit(-1);
}
longjmp(_clar.trampoline, -1);
}
}
void clar__assert_equal_s(
const char *s1,
const char *s2,
const char *file,
int line,
const char *err,
int should_abort)
{
int match = (s1 == NULL || s2 == NULL) ? (s1 == s2) : (strcmp(s1, s2) == 0);
if (!match) {
char buf[4096];
snprint_eq(buf, 4096, "'%s' != '%s'", s1, s2);
clar__assert(0, file, line, err, buf, should_abort);
}
}
void clar__assert_equal_i(
int i1,
int i2,
const char *file,
int line,
const char *err,
int should_abort)
{
if (i1 != i2) {
char buf[128];
snprint_eq(buf, 128, "%d != %d", i1, i2);
clar__assert(0, file, line, err, buf, should_abort);
}
}
void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
{
_clar.local_cleanup = cleanup;
_clar.local_cleanup_payload = opaque;
}
#include "clar/sandbox.h"
#include "clar/fixtures.h"
#include "clar/fs.h"
#include "clar/print.h"
#ifndef __CLAR_TEST_H__
#define __CLAR_TEST_H__
#include <stdlib.h>
int clar_test(int argc, char *argv[]);
void cl_set_cleanup(void (*cleanup)(void *), void *opaque);
void cl_fs_cleanup(void);
#ifdef CLAR_FIXTURE_PATH
const char *cl_fixture(const char *fixture_name);
void cl_fixture_sandbox(const char *fixture_name);
void cl_fixture_cleanup(const char *fixture_name);
#endif
/**
* Assertion macros with explicit error message
*/
#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 1)
#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 1)
#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __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__, __LINE__, "Function call failed: " #expr, desc, 0)
#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 0)
#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 0)
/**
* Assertion macros with no error message
*/
#define cl_must_pass(expr) cl_must_pass_(expr, NULL)
#define cl_must_fail(expr) cl_must_fail_(expr, NULL)
#define cl_assert(expr) cl_assert_(expr, NULL)
/**
* Check macros with no error message
*/
#define cl_check_pass(expr) cl_check_pass_(expr, NULL)
#define cl_check_fail(expr) cl_check_fail_(expr, NULL)
#define cl_check(expr) cl_check_(expr, NULL)
/**
* Forced failure/warning
*/
#define cl_fail(desc) clar__assert(0, __FILE__, __LINE__, "Test failed.", desc, 1)
#define cl_warning(desc) clar__assert(0, __FILE__, __LINE__, "Warning during test execution:", desc, 0)
/**
* Typed assertion macros
*/
#define cl_assert_equal_s(s1,s2) clar__assert_equal_s((s1),(s2),__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1)
#define cl_assert_equal_i(i1,i2) clar__assert_equal_i((i1),(i2),__FILE__,__LINE__,#i1 " != " #i2, 1)
#define cl_assert_equal_b(b1,b2) clar__assert_equal_i(!!(b1),!!(b2),__FILE__,__LINE__,#b1 " != " #b2, 1)
#define cl_assert_equal_p(p1,p2) cl_assert((p1) == (p2))
void clar__assert(
int condition,
const char *file,
int line,
const char *error,
const char *description,
int should_abort);
void clar__assert_equal_s(const char *,const char *,const char *,int,const char *,int);
void clar__assert_equal_i(int,int,const char *,int,const char *,int);
#endif
static const char *
fixture_path(const char *base, const char *fixture_name)
{
static char _path[4096];
size_t root_len;
root_len = strlen(base);
strncpy(_path, base, sizeof(_path));
if (_path[root_len - 1] != '/')
_path[root_len++] = '/';
if (fixture_name[0] == '/')
fixture_name++;
strncpy(_path + root_len,
fixture_name,
sizeof(_path) - root_len);
return _path;
}
#ifdef CLAR_FIXTURE_PATH
const char *cl_fixture(const char *fixture_name)
{
return fixture_path(CLAR_FIXTURE_PATH, fixture_name);
}
void cl_fixture_sandbox(const char *fixture_name)
{
fs_copy(cl_fixture(fixture_name), _clar_path);
}
void cl_fixture_cleanup(const char *fixture_name)
{
fs_rm(fixture_path(_clar_path, fixture_name));
}
#endif
#ifdef _WIN32
#define RM_RETRY_COUNT 5
#define RM_RETRY_DELAY 10
#ifdef __MINGW32__
/* These security-enhanced functions are not available
* in MinGW, so just use the vanilla ones */
#define wcscpy_s(a, b, c) wcscpy((a), (c))
#define wcscat_s(a, b, c) wcscat((a), (c))
#endif /* __MINGW32__ */
static int
fs__dotordotdot(WCHAR *_tocheck)
{
return _tocheck[0] == '.' &&
(_tocheck[1] == '\0' ||
(_tocheck[1] == '.' && _tocheck[2] == '\0'));
}
static int
fs_rmdir_rmdir(WCHAR *_wpath)
{
unsigned retries = 1;
while (!RemoveDirectoryW(_wpath)) {
/* Only retry when we have retries remaining, and the
* error was ERROR_DIR_NOT_EMPTY. */
if (retries++ > RM_RETRY_COUNT ||
ERROR_DIR_NOT_EMPTY != GetLastError())
return -1;
/* Give whatever has a handle to a child item some time
* to release it before trying again */
Sleep(RM_RETRY_DELAY * retries * retries);
}
return 0;
}
static void
fs_rmdir_helper(WCHAR *_wsource)
{
WCHAR buffer[MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
int buffer_prefix_len;
/* Set up the buffer and capture the length */
wcscpy_s(buffer, MAX_PATH, _wsource);
wcscat_s(buffer, MAX_PATH, L"\\");
buffer_prefix_len = wcslen(buffer);
/* FindFirstFile needs a wildcard to match multiple items */
wcscat_s(buffer, MAX_PATH, L"*");
find_handle = FindFirstFileW(buffer, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);
do {
/* FindFirstFile/FindNextFile gives back . and ..
* entries at the beginning */
if (fs__dotordotdot(find_data.cFileName))
continue;
wcscpy_s(buffer + buffer_prefix_len, MAX_PATH - buffer_prefix_len, find_data.cFileName);
if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
fs_rmdir_helper(buffer);
else {
/* If set, the +R bit must be cleared before deleting */
if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes)
cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY));
cl_assert(DeleteFileW(buffer));
}
}
while (FindNextFileW(find_handle, &find_data));
/* Ensure that we successfully completed the enumeration */
cl_assert(ERROR_NO_MORE_FILES == GetLastError());
/* Close the find handle */
FindClose(find_handle);
/* Now that the directory is empty, remove it */
cl_assert(0 == fs_rmdir_rmdir(_wsource));
}
static int
fs_rm_wait(WCHAR *_wpath)
{
unsigned retries = 1;
DWORD last_error;
do {
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(_wpath))
last_error = GetLastError();
else
last_error = ERROR_SUCCESS;
/* Is the item gone? */
if (ERROR_FILE_NOT_FOUND == last_error ||
ERROR_PATH_NOT_FOUND == last_error)
return 0;
Sleep(RM_RETRY_DELAY * retries * retries);
}
while (retries++ <= RM_RETRY_COUNT);
return -1;
}
static void
fs_rm(const char *_source)
{
WCHAR wsource[MAX_PATH];
DWORD attrs;
/* The input path is UTF-8. Convert it to wide characters
* for use with the Windows API */
cl_assert(MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS,
_source,
-1, /* Indicates NULL termination */
wsource,
MAX_PATH));
/* Does the item exist? If not, we have no work to do */
attrs = GetFileAttributesW(wsource);
if (INVALID_FILE_ATTRIBUTES == attrs)
return;
if (FILE_ATTRIBUTE_DIRECTORY & attrs)
fs_rmdir_helper(wsource);
else {
/* The item is a file. Strip the +R bit */
if (FILE_ATTRIBUTE_READONLY & attrs)
cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY));
cl_assert(DeleteFileW(wsource));
}
/* Wait for the DeleteFile or RemoveDirectory call to complete */
cl_assert(0 == fs_rm_wait(wsource));
}
static void
fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
{
WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
int buf_source_prefix_len, buf_dest_prefix_len;
wcscpy_s(buf_source, MAX_PATH, _wsource);
wcscat_s(buf_source, MAX_PATH, L"\\");
buf_source_prefix_len = wcslen(buf_source);
wcscpy_s(buf_dest, MAX_PATH, _wdest);
wcscat_s(buf_dest, MAX_PATH, L"\\");
buf_dest_prefix_len = wcslen(buf_dest);
/* Get an enumerator for the items in the source. */
wcscat_s(buf_source, MAX_PATH, L"*");
find_handle = FindFirstFileW(buf_source, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);
/* Create the target directory. */
cl_assert(CreateDirectoryW(_wdest, NULL));
do {
/* FindFirstFile/FindNextFile gives back . and ..
* entries at the beginning */
if (fs__dotordotdot(find_data.cFileName))
continue;
wcscpy_s(buf_source + buf_source_prefix_len, MAX_PATH - buf_source_prefix_len, find_data.cFileName);
wcscpy_s(buf_dest + buf_dest_prefix_len, MAX_PATH - buf_dest_prefix_len, find_data.cFileName);
if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
fs_copydir_helper(buf_source, buf_dest);
else
cl_assert(CopyFileW(buf_source, buf_dest, TRUE));
}
while (FindNextFileW(find_handle, &find_data));
/* Ensure that we successfully completed the enumeration */
cl_assert(ERROR_NO_MORE_FILES == GetLastError());
/* Close the find handle */
FindClose(find_handle);
}
static void
fs_copy(const char *_source, const char *_dest)
{
WCHAR wsource[MAX_PATH], wdest[MAX_PATH];
DWORD source_attrs, dest_attrs;
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
/* The input paths are UTF-8. Convert them to wide characters
* for use with the Windows API. */
cl_assert(MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS,
_source,
-1,
wsource,
MAX_PATH));
cl_assert(MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS,
_dest,
-1,
wdest,
MAX_PATH));
/* Check the source for existence */
source_attrs = GetFileAttributesW(wsource);
cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs);
/* Check the target for existence */
dest_attrs = GetFileAttributesW(wdest);
if (INVALID_FILE_ATTRIBUTES != dest_attrs) {
/* Target exists; append last path part of source to target.
* Use FindFirstFile to parse the path */
find_handle = FindFirstFileW(wsource, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);
wcscat_s(wdest, MAX_PATH, L"\\");
wcscat_s(wdest, MAX_PATH, find_data.cFileName);
FindClose(find_handle);
/* Check the new target for existence */
cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest));
}
if (FILE_ATTRIBUTE_DIRECTORY & source_attrs)
fs_copydir_helper(wsource, wdest);
else
cl_assert(CopyFileW(wsource, wdest, TRUE));
}
void
cl_fs_cleanup(void)
{
fs_rm(fixture_path(_clar_path, "*"));
}
#else
static int
shell_out(char * const argv[])
{
int status;
pid_t pid;
pid = fork();
if (pid < 0) {
fprintf(stderr,
"System error: `fork()` call failed.\n");
exit(-1);
}
if (pid == 0) {
execv(argv[0], argv);
}
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
static void
fs_copy(const char *_source, const char *dest)
{
char *argv[5];
char *source;
size_t source_len;
source = strdup(_source);
source_len = strlen(source);
if (source[source_len - 1] == '/')
source[source_len - 1] = 0;
argv[0] = "/bin/cp";
argv[1] = "-R";
argv[2] = source;
argv[3] = (char *)dest;
argv[4] = NULL;
cl_must_pass_(
shell_out(argv),
"Failed to copy test fixtures to sandbox"
);
free(source);
}
static void
fs_rm(const char *source)
{
char *argv[4];
argv[0] = "/bin/rm";
argv[1] = "-Rf";
argv[2] = (char *)source;
argv[3] = NULL;
cl_must_pass_(
shell_out(argv),
"Failed to cleanup the sandbox"
);
}
void
cl_fs_cleanup(void)
{
clar_unsandbox();
clar_sandbox();
}
#endif
static void clar_print_init(int test_count, int suite_count, const char *suite_names)
{
(void)test_count;
printf("Loaded %d suites: %s\n", (int)suite_count, suite_names);
printf("Started\n");
}
static void clar_print_shutdown(int test_count, int suite_count, int error_count)
{
(void)test_count;
(void)suite_count;
(void)error_count;
printf("\n\n");
clar_report_errors();
}
static void clar_print_error(int num, const struct clar_error *error)
{
printf(" %d) Failure:\n", num);
printf("%s::%s [%s:%d]\n",
error->suite,
error->test,
error->file,
error->line_number);
printf(" %s\n", error->error_msg);
if (error->description != NULL)
printf(" %s\n", error->description);
printf("\n");
fflush(stdout);
}
static void clar_print_ontest(const char *test_name, int test_number, int failed)
{
(void)test_name;
(void)test_number;
printf("%c", failed ? 'F' : '.');
fflush(stdout);
}
static void clar_print_onsuite(const char *suite_name, int suite_index)
{
/* noop */
(void)suite_index;
(void)suite_name;
}
static void clar_print_onabort(const char *msg, ...)
{
va_list argp;
va_start(argp, msg);
vfprintf(stderr, msg, argp);
va_end(argp);
}
static char _clar_path[4096];
static int
is_valid_tmp_path(const char *path)
{
STAT_T st;
if (stat(path, &st) != 0)
return 0;
if (!S_ISDIR(st.st_mode))
return 0;
return (access(path, W_OK) == 0);
}
static int
find_tmp_path(char *buffer, size_t length)
{
#ifndef _WIN32
static const size_t var_count = 4;
static const char *env_vars[] = {
"TMPDIR", "TMP", "TEMP", "USERPROFILE"
};
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)) {
strncpy(buffer, env, length);
return 0;
}
}
/* If the environment doesn't say anything, try to use /tmp */
if (is_valid_tmp_path("/tmp")) {
strncpy(buffer, "/tmp", length);
return 0;
}
#else
if (GetTempPath((DWORD)length, buffer))
return 0;
#endif
/* This system doesn't like us, try to use the current directory */
if (is_valid_tmp_path(".")) {
strncpy(buffer, ".", length);
return 0;
}
return -1;
}
static void clar_unsandbox(void)
{
if (_clar_path[0] == '\0')
return;
#ifdef _WIN32
chdir("..");
#endif
fs_rm(_clar_path);
}
static int build_sandbox_path(void)
{
const char path_tail[] = "clar_tmp_XXXXXX";
size_t len;
if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0)
return -1;
len = strlen(_clar_path);
#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 (_clar_path[len - 1] != '/') {
_clar_path[len++] = '/';
}
strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len);
#if defined(__MINGW32__)
if (_mktemp(_clar_path) == NULL)
return -1;
if (mkdir(_clar_path, 0700) != 0)
return -1;
#elif defined(_WIN32)
if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0)
return -1;
if (mkdir(_clar_path, 0700) != 0)
return -1;
#else
if (mkdtemp(_clar_path) == NULL)
return -1;
#endif
return 0;
}
static int clar_sandbox(void)
{
if (_clar_path[0] == '\0' && build_sandbox_path() < 0)
return -1;
if (chdir(_clar_path) != 0)
return -1;
return 0;
}
......@@ -2,17 +2,6 @@
#include "posix.h"
#include "path.h"
void clar_on_init(void)
{
git_threads_init();
}
void clar_on_shutdown(void)
{
giterr_clear();
git_threads_shutdown();
}
void cl_git_mkfile(const char *filename, const char *content)
{
int fd;
......
......@@ -20,14 +20,14 @@ void test_clone_nonetwork__initialize(void)
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
}
static void cleanup_repository(void *path)
void test_clone_nonetwork__cleanup(void)
{
if (g_repo) {
git_repository_free(g_repo);
g_repo = NULL;
}
cl_fixture_cleanup((const char *)path);
cl_fixture_cleanup("./foo");
}
void test_clone_nonetwork__bad_url(void)
......@@ -42,39 +42,30 @@ void test_clone_nonetwork__bad_url(void)
void test_clone_nonetwork__local(void)
{
cl_set_cleanup(&cleanup_repository, "./foo");
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
}
void test_clone_nonetwork__local_absolute_path(void)
{
const char *local_src;
cl_set_cleanup(&cleanup_repository, "./foo");
local_src = cl_fixture("testrepo.git");
cl_git_pass(git_clone(&g_repo, local_src, "./foo", &g_options));
}
void test_clone_nonetwork__local_bare(void)
{
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.bare = true;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
}
void test_clone_nonetwork__fail_when_the_target_is_a_file(void)
{
cl_set_cleanup(&cleanup_repository, "./foo");
cl_git_mkfile("./foo", "Bar!");
cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
}
void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void)
{
cl_set_cleanup(&cleanup_repository, "./foo");
p_mkdir("./foo", GIT_DIR_MODE);
cl_git_mkfile("./foo/bar", "Baz!");
cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
......@@ -84,7 +75,6 @@ void test_clone_nonetwork__custom_origin_name(void)
{
git_remote *remote;
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.remote_name = "my_origin";
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
......@@ -98,7 +88,6 @@ void test_clone_nonetwork__custom_push_url(void)
git_remote *remote;
const char *url = "http://example.com";
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.pushurl = url;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
......@@ -115,7 +104,6 @@ void test_clone_nonetwork__custom_fetch_spec(void)
const git_refspec *actual_fs;
const char *spec = "+refs/heads/master:refs/heads/foo";
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.fetch_spec = spec;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
......@@ -136,7 +124,6 @@ void test_clone_nonetwork__custom_push_spec(void)
const git_refspec *actual_fs;
const char *spec = "+refs/heads/master:refs/heads/foo";
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.push_spec = spec;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
......@@ -152,7 +139,6 @@ void test_clone_nonetwork__custom_autotag(void)
{
git_strarray tags = {0};
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.remote_autotag = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
......@@ -162,8 +148,6 @@ void test_clone_nonetwork__custom_autotag(void)
void test_clone_nonetwork__cope_with_already_existing_directory(void)
{
cl_set_cleanup(&cleanup_repository, "./foo");
p_mkdir("./foo", GIT_DIR_MODE);
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
}
......@@ -171,7 +155,6 @@ void test_clone_nonetwork__cope_with_already_existing_directory(void)
void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void)
{
git_buf path = GIT_BUF_INIT;
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.checkout_opts.checkout_strategy = 0;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
......
......@@ -431,11 +431,18 @@ void test_config_read__simple_read_from_specific_level(void)
git_config_free(cfg);
}
static void clean_empty_config(void *unused)
{
GIT_UNUSED(unused);
cl_fixture_cleanup("./empty");
}
void test_config_read__can_load_and_parse_an_empty_config_file(void)
{
git_config *cfg;
int i;
cl_set_cleanup(&clean_empty_config, NULL);
cl_git_mkfile("./empty", "");
cl_git_pass(git_config_open_ondisk(&cfg, "./empty"));
cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither"));
......
......@@ -14,6 +14,18 @@ static const char *env_vars[NUM_VARS] = { "HOME" };
static char *env_save[NUM_VARS];
static char *home_values[] = {
"fake_home",
"fáke_hõme", /* all in latin-1 supplement */
"fĀke_Ĥome", /* latin extended */
"fακε_hοmέ", /* having fun with greek */
"faงe_นome", /* now I have no idea, but thai characters */
"f\xe1\x9cx80ke_\xe1\x9c\x91ome", /* tagalog characters */
"\xe1\xb8\x9fẢke_hoṁe", /* latin extended additional */
"\xf0\x9f\x98\x98\xf0\x9f\x98\x82", /* emoticons */
NULL
};
void test_core_env__initialize(void)
{
int i;
......@@ -24,6 +36,8 @@ void test_core_env__initialize(void)
void test_core_env__cleanup(void)
{
int i;
char **val;
for (i = 0; i < NUM_VARS; ++i) {
cl_setenv(env_vars[i], env_save[i]);
#ifdef GIT_WIN32
......@@ -31,11 +45,20 @@ void test_core_env__cleanup(void)
#endif
env_save[i] = NULL;
}
/* these will probably have already been cleaned up, but if a test
* fails, then it's probably good to try and clear out these dirs
*/
for (val = home_values; *val != NULL; val++) {
if (**val != '\0')
(void)p_rmdir(*val);
}
}
static void setenv_and_check(const char *name, const char *value)
{
char *check;
cl_git_pass(cl_setenv(name, value));
check = cl_getenv(name);
cl_assert_equal_s(value, check);
......@@ -46,17 +69,6 @@ static void setenv_and_check(const char *name, const char *value)
void test_core_env__0(void)
{
static char *home_values[] = {
"fake_home",
"fáke_hõme", /* all in latin-1 supplement */
"fĀke_Ĥome", /* latin extended */
"fακε_hοmέ", /* having fun with greek */
"faงe_นome", /* now I have no idea, but thai characters */
"f\xe1\x9cx80ke_\xe1\x9c\x91ome", /* tagalog characters */
"\xe1\xb8\x9fẢke_hoṁe", /* latin extended additional */
"\xf0\x9f\x98\x98\xf0\x9f\x98\x82", /* emoticons */
NULL
};
git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT;
char testfile[16], tidx = '0';
char **val;
......@@ -71,8 +83,10 @@ void test_core_env__0(void)
* we are on a filesystem that doesn't support the
* characters in question and skip this test...
*/
if (p_mkdir(*val, 0777) != 0)
if (p_mkdir(*val, 0777) != 0) {
*val = ""; /* mark as not created */
continue;
}
cl_git_pass(git_path_prettify(&path, *val, NULL));
......@@ -122,6 +136,8 @@ void test_core_env__0(void)
}
}
#endif
(void)p_rmdir(*val);
}
git_buf_free(&path);
......
#!/usr/bin/env python
from __future__ import with_statement
from string import Template
import re, fnmatch, os, codecs, pickle
class Module(object):
class Template(object):
def __init__(self, module):
self.module = module
def _render_callback(self, cb):
if not cb:
return '{ NULL, NULL }'
return '{ "%s", &%s }' % (cb['short_name'], cb['symbol'])
class DeclarationTemplate(Template):
def render(self):
out = "\n".join("extern %s;" % cb['declaration'] for cb in self.module.callbacks)
if self.module.initialize:
out += "extern %s;\n" % self.module.initialize['declaration']
if self.module.cleanup:
out += "extern %s;\n" % self.module.cleanup['declaration']
return out
class CallbacksTemplate(Template):
def render(self):
out = "static const struct clar_func _clar_cb_%s[] = {\n" % self.module.name
out += ",\n".join(self._render_callback(cb) for cb in self.module.callbacks)
out += "\n};\n"
return out
class InfoTemplate(Template):
def render(self):
return Template(
r"""{
"${clean_name}",
${initialize},
${cleanup},
${cb_ptr}, ${cb_count}, ${enabled}
}"""
).substitute(
clean_name = self.module.clean_name(),
initialize = self._render_callback(self.module.initialize),
cleanup = self._render_callback(self.module.cleanup),
cb_ptr = "_clar_cb_%s" % self.module.name,
cb_count = len(self.module.callbacks),
enabled = int(self.module.enabled)
)
def __init__(self, name):
self.name = name
self.mtime = 0
self.enabled = True
self.modified = False
def clean_name(self):
return self.name.replace("_", "::")
def _skip_comments(self, text):
SKIP_COMMENTS_REGEX = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE)
def _replacer(match):
s = match.group(0)
return "" if s.startswith('/') else s
return re.sub(SKIP_COMMENTS_REGEX, _replacer, text)
def parse(self, contents):
TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{"
contents = self._skip_comments(contents)
regex = re.compile(TEST_FUNC_REGEX % self.name, re.MULTILINE)
self.callbacks = []
self.initialize = None
self.cleanup = None
for (declaration, symbol, short_name) in regex.findall(contents):
data = {
"short_name" : short_name,
"declaration" : declaration,
"symbol" : symbol
}
if short_name == 'initialize':
self.initialize = data
elif short_name == 'cleanup':
self.cleanup = data
else:
self.callbacks.append(data)
return self.callbacks != []
def refresh(self, path):
self.modified = False
try:
st = os.stat(path)
# Not modified
if st.st_mtime == self.mtime:
return True
self.modified = True
self.mtime = st.st_mtime
with open(path) as fp:
raw_content = fp.read()
except IOError:
return False
return self.parse(raw_content)
class TestSuite(object):
def __init__(self, path):
self.path = path
def should_generate(self, path):
if not os.path.isfile(path):
return True
if any(module.modified for module in self.modules.values()):
return True
return False
def find_modules(self):
modules = []
for root, _, files in os.walk(self.path):
module_root = root[len(self.path):]
module_root = [c for c in module_root.split(os.sep) if c]
tests_in_module = fnmatch.filter(files, "*.c")
for test_file in tests_in_module:
full_path = os.path.join(root, test_file)
module_name = "_".join(module_root + [test_file[:-2]])
modules.append((full_path, module_name))
return modules
def load_cache(self):
path = os.path.join(self.path, '.clarcache')
cache = {}
try:
fp = open(path)
cache = pickle.load(fp)
fp.close()
except IOError:
pass
return cache
def save_cache(self):
path = os.path.join(self.path, '.clarcache')
with open(path, 'w') as cache:
pickle.dump(self.modules, cache)
def load(self, force = False):
module_data = self.find_modules()
self.modules = {} if force else self.load_cache()
for path, name in module_data:
if name not in self.modules:
self.modules[name] = Module(name)
if not self.modules[name].refresh(path):
del self.modules[name]
def disable(self, excluded):
for exclude in excluded:
for module in self.modules.values():
name = module.clean_name()
if name.startswith(exclude):
module.enabled = False
module.modified = True
def suite_count(self):
return len(self.modules)
def callback_count(self):
return sum(len(module.callbacks) for module in self.modules.values())
def write(self):
output = os.path.join(self.path, 'clar.suite')
if not self.should_generate(output):
return False
with open(output, 'w') as data:
for module in self.modules.values():
t = Module.DeclarationTemplate(module)
data.write(t.render())
for module in self.modules.values():
t = Module.CallbacksTemplate(module)
data.write(t.render())
suites = "static struct clar_suite _clar_suites[] = {" + ','.join(
Module.InfoTemplate(module).render() for module in self.modules.values()
) + "};"
data.write(suites)
data.write("static const size_t _clar_suite_count = %d;" % self.suite_count())
data.write("static const size_t _clar_callback_count = %d;" % self.callback_count())
suite.save_cache()
return True
if __name__ == '__main__':
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-f', '--force', dest='force', default=False)
parser.add_option('-x', '--exclude', dest='excluded', action='append', default=[])
options, args = parser.parse_args()
for path in args or ['.']:
suite = TestSuite(path)
suite.load(options.force)
suite.disable(options.excluded)
if suite.write():
print "Written `clar.suite` (%d suites)" % len(suite.modules)
......@@ -24,7 +24,6 @@ static struct test_entry test_entries[] = {
{48, "src/revobject.h", 1448, 0x4C3F7FE2}
};
// Helpers
static void copy_file(const char *src, const char *dst)
{
......@@ -72,11 +71,6 @@ void test_index_tests__initialize(void)
{
}
void test_index_tests__cleanup(void)
{
}
void test_index_tests__empty_index(void)
{
git_index *index;
......@@ -203,49 +197,57 @@ void test_index_tests__sort1(void)
git_index_free(index);
}
static void cleanup_myrepo(void *opaque)
{
GIT_UNUSED(opaque);
cl_fixture_cleanup("myrepo");
}
void test_index_tests__add(void)
{
git_index *index;
git_filebuf file = GIT_FILEBUF_INIT;
git_repository *repo;
const git_index_entry *entry;
git_oid id1;
git_index *index;
git_filebuf file = GIT_FILEBUF_INIT;
git_repository *repo;
const git_index_entry *entry;
git_oid id1;
/* Intialize a new repository */
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
cl_set_cleanup(&cleanup_myrepo, NULL);
/* Ensure we're the only guy in the room */
cl_git_pass(git_repository_index(&index, repo));
cl_assert(git_index_entrycount(index) == 0);
/* Intialize a new repository */
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
/* Create a new file in the working directory */
cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0));
cl_git_pass(git_filebuf_write(&file, "hey there\n", 10));
cl_git_pass(git_filebuf_commit(&file, 0666));
/* 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"));
/* Create a new file in the working directory */
cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0));
cl_git_pass(git_filebuf_write(&file, "hey there\n", 10));
cl_git_pass(git_filebuf_commit(&file, 0666));
/* Add the new file to the index */
cl_git_pass(git_index_add_from_workdir(index, "test.txt"));
/* 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"));
/* Wow... it worked! */
cl_assert(git_index_entrycount(index) == 1);
entry = git_index_get_byindex(index, 0);
/* Add the new file to the index */
cl_git_pass(git_index_add_from_workdir(index, "test.txt"));
/* And the built-in hashing mechanism worked as expected */
cl_assert(git_oid_cmp(&id1, &entry->oid) == 0);
/* Wow... it worked! */
cl_assert(git_index_entrycount(index) == 1);
entry = git_index_get_byindex(index, 0);
/* Test access by path instead of index */
cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
cl_assert(git_oid_cmp(&id1, &entry->oid) == 0);
/* And the built-in hashing mechanism worked as expected */
cl_assert(git_oid_cmp(&id1, &entry->oid) == 0);
git_index_free(index);
git_repository_free(repo);
/* Test access by path instead of index */
cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
cl_assert(git_oid_cmp(&id1, &entry->oid) == 0);
git_index_free(index);
git_repository_free(repo);
}
void test_index_tests__add_from_workdir_to_a_bare_repository_returns_EBAREPO(void)
......
#include "clar_libgit2.h"
int main(int argc, char *argv[])
{
int res;
git_threads_init();
/* Run the test suite */
res = clar_test(argc, argv);
giterr_clear();
git_threads_shutdown();
return res;
}
......@@ -44,22 +44,6 @@ void test_merge_setup__cleanup(void)
cl_git_sandbox_cleanup();
}
static bool test_file_contents(const char *filename, const char *expected)
{
git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT;
bool equals;
git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename);
cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr));
equals = (strcmp(file_buf.ptr, expected) == 0);
git_buf_free(&file_path_buf);
git_buf_free(&file_buf);
return equals;
}
static void write_file_contents(const char *filename, const char *output)
{
git_buf file_path_buf = GIT_BUF_INIT;
......@@ -77,18 +61,14 @@ struct merge_head_cb_data {
unsigned int i;
};
int merge_head_foreach_cb(git_oid *oid, void *payload)
static int merge_head_foreach_cb(const git_oid *oid, void *payload)
{
git_oid expected_oid;
struct merge_head_cb_data *cb_data = payload;
git_oid_fromstr(&expected_oid, cb_data->oid_str[cb_data->i]);
cl_assert(git_oid_cmp(&expected_oid, oid) == 0);
cb_data->i++;
return 0;
}
......
......@@ -11,6 +11,11 @@ static void transfer_cb(const git_transfer_progress *stats, void *payload)
(*callcount)++;
}
static void cleanup_local_repo(void *path)
{
cl_fixture_cleanup((char *)path);
}
void test_network_fetchlocal__complete(void)
{
git_repository *repo;
......@@ -19,6 +24,8 @@ void test_network_fetchlocal__complete(void)
git_strarray refnames = {0};
const char *url = cl_git_fixture_url("testrepo.git");
cl_set_cleanup(&cleanup_local_repo, "foo");
cl_git_pass(git_repository_init(&repo, "foo", true));
cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
......@@ -35,6 +42,12 @@ void test_network_fetchlocal__complete(void)
git_repository_free(repo);
}
static void cleanup_sandbox(void *unused)
{
GIT_UNUSED(unused);
cl_git_sandbox_cleanup();
}
void test_network_fetchlocal__partial(void)
{
git_repository *repo = cl_git_sandbox_init("partial-testrepo");
......@@ -43,6 +56,7 @@ void test_network_fetchlocal__partial(void)
git_strarray refnames = {0};
const char *url;
cl_set_cleanup(&cleanup_sandbox, NULL);
cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL));
cl_assert_equal_i(1, (int)refnames.count);
......@@ -60,6 +74,4 @@ void test_network_fetchlocal__partial(void)
git_strarray_free(&refnames);
git_remote_free(origin);
cl_git_sandbox_cleanup();
}
......@@ -6,13 +6,18 @@ static git_buf destpath, filepath;
static const char *paths[] = {
"A.git", "B.git", "C.git", "D.git", "E.git", "F.git", "G.git"
};
static git_filebuf file;
static git_filebuf file;
static git_repository *repo;
void test_odb_alternates__cleanup(void)
{
size_t i;
git_buf_free(&destpath);
git_buf_free(&filepath);
for (i = 0; i < ARRAY_SIZE(paths); i++)
cl_fixture_cleanup(paths[i]);
}
static void init_linked_repo(const char *path, const char *alternate)
......
......@@ -3,15 +3,13 @@
#include "git2/clone.h"
#include "repository.h"
CL_IN_CATEGORY("network")
#define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository"
#define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository"
static git_repository *g_repo;
static git_clone_options g_options;
void test_clone_network__initialize(void)
void test_online_clone__initialize(void)
{
git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT;
......@@ -23,22 +21,19 @@ void test_clone_network__initialize(void)
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
}
static void cleanup_repository(void *path)
void test_online_clone__cleanup(void)
{
if (g_repo) {
git_repository_free(g_repo);
g_repo = NULL;
}
cl_fixture_cleanup((const char *)path);
cl_fixture_cleanup("./foo");
}
void test_clone_network__network_full(void)
void test_online_clone__network_full(void)
{
git_remote *origin;
cl_set_cleanup(&cleanup_repository, "./foo");
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
cl_assert(!git_repository_is_bare(g_repo));
cl_git_pass(git_remote_load(&origin, g_repo, "origin"));
......@@ -46,12 +41,10 @@ void test_clone_network__network_full(void)
git_remote_free(origin);
}
void test_clone_network__network_bare(void)
void test_online_clone__network_bare(void)
{
git_remote *origin;
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.bare = true;
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
......@@ -61,12 +54,10 @@ void test_clone_network__network_bare(void)
git_remote_free(origin);
}
void test_clone_network__empty_repository(void)
void test_online_clone__empty_repository(void)
{
git_reference *head;
cl_set_cleanup(&cleanup_repository, "./foo");
cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./foo", &g_options));
cl_assert_equal_i(true, git_repository_is_empty(g_repo));
......@@ -93,7 +84,7 @@ static void fetch_progress(const git_transfer_progress *stats, void *payload)
(*was_called) = true;
}
void test_clone_network__can_checkout_a_cloned_repo(void)
void test_online_clone__can_checkout_a_cloned_repo(void)
{
git_buf path = GIT_BUF_INIT;
git_reference *head;
......@@ -106,8 +97,6 @@ void test_clone_network__can_checkout_a_cloned_repo(void)
g_options.fetch_progress_cb = &fetch_progress;
g_options.fetch_progress_payload = &fetch_progress_cb_was_called;
cl_set_cleanup(&cleanup_repository, "./foo");
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
......@@ -137,8 +126,6 @@ void test_clone_network__custom_remote_callbacks(void)
git_remote_callbacks remote_callbacks = GIT_REMOTE_CALLBACKS_INIT;
int callcount = 0;
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.remote_callbacks = &remote_callbacks;
remote_callbacks.update_tips = update_tips;
remote_callbacks.payload = &callcount;
......@@ -179,8 +166,6 @@ void test_clone_network__credentials(void)
if (!remote_url) return;
cl_set_cleanup(&cleanup_repository, "./foo");
g_options.cred_acquire_cb = cred_acquire;
g_options.cred_acquire_payload = &user_pass;
......
#include "clar_libgit2.h"
CL_IN_CATEGORY("network")
static git_repository *_repo;
static int counter;
void test_network_fetch__initialize(void)
void test_online_fetch__initialize(void)
{
cl_git_pass(git_repository_init(&_repo, "./fetch", 0));
}
void test_network_fetch__cleanup(void)
void test_online_fetch__cleanup(void)
{
git_repository_free(_repo);
_repo = NULL;
......@@ -55,22 +53,22 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n)
git_remote_free(remote);
}
void test_network_fetch__default_git(void)
void test_online_fetch__default_git(void)
{
do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6);
}
void test_network_fetch__default_http(void)
void test_online_fetch__default_http(void)
{
do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6);
}
void test_network_fetch__no_tags_git(void)
void test_online_fetch__no_tags_git(void)
{
do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3);
}
void test_network_fetch__no_tags_http(void)
void test_online_fetch__no_tags_http(void)
{
do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3);
}
......@@ -83,7 +81,7 @@ static void transferProgressCallback(const git_transfer_progress *stats, void *p
*invoked = true;
}
void test_network_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void)
void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void)
{
git_repository *_repository;
bool invoked = false;
......
......@@ -2,17 +2,15 @@
#include "repository.h"
#include "fetchhead.h"
#include "fetchhead_data.h"
#include "../fetchhead/fetchhead_data.h"
#include "git2/clone.h"
CL_IN_CATEGORY("network")
#define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository"
static git_repository *g_repo;
static git_clone_options g_options;
void test_fetchhead_network__initialize(void)
void test_online_fetchhead__initialize(void)
{
g_repo = NULL;
......@@ -20,21 +18,18 @@ void test_fetchhead_network__initialize(void)
g_options.version = GIT_CLONE_OPTIONS_VERSION;
}
static void cleanup_repository(void *path)
void test_online_fetchhead__cleanup(void)
{
if (g_repo) {
git_repository_free(g_repo);
g_repo = NULL;
}
cl_fixture_cleanup((const char *)path);
cl_fixture_cleanup("./foo");
}
static void fetchhead_test_clone(void)
{
cl_set_cleanup(&cleanup_repository, "./foo");
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
}
......@@ -65,19 +60,19 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet
cl_assert(equals);
}
void test_fetchhead_network__wildcard_spec(void)
void test_online_fetchhead__wildcard_spec(void)
{
fetchhead_test_clone();
fetchhead_test_fetch(NULL, FETCH_HEAD_WILDCARD_DATA);
}
void test_fetchhead_network__explicit_spec(void)
void test_online_fetchhead__explicit_spec(void)
{
fetchhead_test_clone();
fetchhead_test_fetch("refs/heads/first-merge:refs/remotes/origin/first-merge", FETCH_HEAD_EXPLICIT_DATA);
}
void test_fetchhead_network__no_merges(void)
void test_online_fetchhead__no_merges(void)
{
git_config *config;
......
......@@ -5,8 +5,6 @@
#include "../submodule/submodule_helpers.h"
#include "push_util.h"
CL_IN_CATEGORY("network")
static git_repository *_repo;
static char *_remote_url;
......@@ -112,7 +110,7 @@ static void do_verify_push_status(git_push *push, const push_status expected[],
/**
* Verifies that after git_push_finish(), refs on a remote have the expected
* names, oids, and order.
*
*
* @param remote remote to verify
* @param expected_refs expected remote refs after push
* @param expected_refs_len length of expected_refs
......@@ -127,7 +125,7 @@ static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t
git_vector_free(&actual_refs);
}
void test_network_push__initialize(void)
void test_online_push__initialize(void)
{
git_vector delete_specs = GIT_VECTOR_INIT;
size_t i;
......@@ -207,7 +205,7 @@ void test_network_push__initialize(void)
printf("GITTEST_REMOTE_URL unset; skipping push test\n");
}
void test_network_push__cleanup(void)
void test_online_push__cleanup(void)
{
if (_remote)
git_remote_free(_remote);
......@@ -224,7 +222,7 @@ void test_network_push__cleanup(void)
/**
* Calls push and relists refs on remote to verify success.
*
*
* @param refspecs refspecs to push
* @param refspecs_len length of refspecs
* @param expected_refs expected remote refs after push
......@@ -271,12 +269,12 @@ static void do_push(const char *refspecs[], size_t refspecs_len,
}
/* Call push_finish() without ever calling git_push_add_refspec() */
void test_network_push__noop(void)
void test_online_push__noop(void)
{
do_push(NULL, 0, NULL, 0, NULL, 0, 0);
}
void test_network_push__b1(void)
void test_online_push__b1(void)
{
const char *specs[] = { "refs/heads/b1:refs/heads/b1" };
push_status exp_stats[] = { { "refs/heads/b1", NULL } };
......@@ -286,7 +284,7 @@ void test_network_push__b1(void)
exp_refs, ARRAY_SIZE(exp_refs), 0);
}
void test_network_push__b2(void)
void test_online_push__b2(void)
{
const char *specs[] = { "refs/heads/b2:refs/heads/b2" };
push_status exp_stats[] = { { "refs/heads/b2", NULL } };
......@@ -296,7 +294,7 @@ void test_network_push__b2(void)
exp_refs, ARRAY_SIZE(exp_refs), 0);
}
void test_network_push__b3(void)
void test_online_push__b3(void)
{
const char *specs[] = { "refs/heads/b3:refs/heads/b3" };
push_status exp_stats[] = { { "refs/heads/b3", NULL } };
......@@ -306,7 +304,7 @@ void test_network_push__b3(void)
exp_refs, ARRAY_SIZE(exp_refs), 0);
}
void test_network_push__b4(void)
void test_online_push__b4(void)
{
const char *specs[] = { "refs/heads/b4:refs/heads/b4" };
push_status exp_stats[] = { { "refs/heads/b4", NULL } };
......@@ -316,7 +314,7 @@ void test_network_push__b4(void)
exp_refs, ARRAY_SIZE(exp_refs), 0);
}
void test_network_push__b5(void)
void test_online_push__b5(void)
{
const char *specs[] = { "refs/heads/b5:refs/heads/b5" };
push_status exp_stats[] = { { "refs/heads/b5", NULL } };
......@@ -326,7 +324,7 @@ void test_network_push__b5(void)
exp_refs, ARRAY_SIZE(exp_refs), 0);
}
void test_network_push__multi(void)
void test_online_push__multi(void)
{
const char *specs[] = {
"refs/heads/b1:refs/heads/b1",
......@@ -354,7 +352,7 @@ void test_network_push__multi(void)
exp_refs, ARRAY_SIZE(exp_refs), 0);
}
void test_network_push__implicit_tgt(void)
void test_online_push__implicit_tgt(void)
{
const char *specs1[] = { "refs/heads/b1:" };
push_status exp_stats1[] = { { "refs/heads/b1", NULL } };
......@@ -375,7 +373,7 @@ void test_network_push__implicit_tgt(void)
exp_refs2, ARRAY_SIZE(exp_refs2), 0);
}
void test_network_push__fast_fwd(void)
void test_online_push__fast_fwd(void)
{
/* Fast forward b1 in tgt from _oid_b1 to _oid_b6. */
......@@ -409,7 +407,7 @@ void test_network_push__fast_fwd(void)
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0);
}
void test_network_push__force(void)
void test_online_push__force(void)
{
const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"};
push_status exp_stats1[] = { { "refs/heads/tgt", NULL } };
......@@ -435,7 +433,7 @@ void test_network_push__force(void)
exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0);
}
void test_network_push__delete(void)
void test_online_push__delete(void)
{
const char *specs1[] = {
"refs/heads/b1:refs/heads/tgt1",
......@@ -492,7 +490,7 @@ void test_network_push__delete(void)
exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0);
}
void test_network_push__bad_refspecs(void)
void test_online_push__bad_refspecs(void)
{
/* All classes of refspecs that should be rejected by
* git_push_add_refspec() should go in this test.
......@@ -510,7 +508,7 @@ void test_network_push__bad_refspecs(void)
}
}
void test_network_push__expressions(void)
void test_online_push__expressions(void)
{
/* TODO: Expressions in refspecs doesn't actually work yet */
const char *specs_left_expr[] = { "refs/heads/b2~1:refs/heads/b2" };
......
#include "clar_libgit2.h"
#include "iterator.h"
#include "vector.h"
#include "posix.h"
static git_repository *_repo;
static git_revwalk *_revwalker;
......@@ -11,7 +12,7 @@ static int _commits_is_initialized;
void test_pack_packbuilder__initialize(void)
{
cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
_repo = cl_git_sandbox_init("testrepo.git");
cl_git_pass(git_revwalk_new(&_revwalker, _repo));
cl_git_pass(git_packbuilder_new(&_packbuilder, _repo));
cl_git_pass(git_vector_init(&_commits, 0, NULL));
......@@ -40,7 +41,7 @@ void test_pack_packbuilder__cleanup(void)
git_indexer_free(_indexer);
_indexer = NULL;
git_repository_free(_repo);
cl_git_sandbox_cleanup();
_repo = NULL;
}
......@@ -88,9 +89,7 @@ static git_transfer_progress stats;
static int foreach_cb(void *buf, size_t len, void *payload)
{
git_indexer_stream *idx = (git_indexer_stream *) payload;
cl_git_pass(git_indexer_stream_add(idx, buf, len, &stats));
return 0;
}
......
......@@ -32,6 +32,7 @@ void test_stash_save__cleanup(void)
repo = NULL;
cl_git_pass(git_futils_rmdir_r("stash", NULL, GIT_RMDIR_REMOVE_FILES));
cl_fixture_cleanup("sorry-it-is-a-non-bare-only-party");
}
static void assert_object_oid(const char* revision, const char* expected_oid, git_otype type)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment