Commit f1558d9b by Vicent Marti

Come out and Clay

parent edb644dd
......@@ -43,9 +43,10 @@ SET(INSTALL_INC include CACHE PATH "Where to install headers to.")
# Build options
OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
OPTION (BUILD_TESTS "Build Tests" ON)
OPTION (THREADSAFE "Build libgit2 as threadsafe" OFF)
OPTION (STDCALL "Buildl libgit2 with the __stdcall convention (Windows)" ON)
OPTION (BUILD_TESTS "Build Tests" OFF)
OPTION (BUILD_CLAY "Build Tests using the Clay suite" ON)
# Platform specific compilation flags
IF (MSVC)
......@@ -113,11 +114,11 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc DESTINATION ${INSTALL_LIB}/
INSTALL(DIRECTORY include/git2 DESTINATION ${INSTALL_INC} )
INSTALL(FILES include/git2.h DESTINATION ${INSTALL_INC} )
SET(TEST_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources" CACHE PATH "Path to test resources.")
ADD_DEFINITIONS(-DTEST_RESOURCES=\"${TEST_RESOURCES}\")
# Tests
IF (BUILD_TESTS)
SET(TEST_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources" CACHE PATH "Path to test resources.")
ADD_DEFINITIONS(-DTEST_RESOURCES=\"${TEST_RESOURCES}\")
INCLUDE_DIRECTORIES(tests)
FILE(GLOB SRC_TEST tests/t??-*.c)
......@@ -132,3 +133,19 @@ IF (BUILD_TESTS)
ENABLE_TESTING()
ADD_TEST(libgit2_test libgit2_test)
ENDIF ()
IF (BUILD_CLAY)
INCLUDE_DIRECTORIES(tests-clay)
FILE(GLOB_RECURSE SRC_TEST tests-clay/*.c)
ADD_EXECUTABLE(libgit2_test ${SRC} ${SRC_TEST} ${SRC_ZLIB})
TARGET_LINK_LIBRARIES(libgit2_test ${CMAKE_THREAD_LIBS_INIT})
IF (WIN32)
TARGET_LINK_LIBRARIES(libgit2_test ws2_32)
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
TARGET_LINK_LIBRARIES(libgit2_test socket nsl)
ENDIF ()
ENABLE_TESTING()
ADD_TEST(libgit2_test libgit2_test)
ENDIF ()
This diff is collapsed. Click to expand it.
#ifndef __CLAY_TEST_H__
#define __CLAY_TEST_H__
#include <stdlib.h>
void clay__assert(
int condition,
const char *file,
int line,
const char *error,
const char *description,
int should_abort);
void cl_set_cleanup(void (*cleanup)(void *), void *opaque);
/**
* Assertion macros with explicit error message
*/
#define cl_must_pass_(expr, desc) clay__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 1)
#define cl_must_fail_(expr, desc) clay__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 1)
#define cl_assert_(expr, desc) clay__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 1)
/**
* Check macros with explicit error message
*/
#define cl_check_pass_(expr, desc) clay__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 0)
#define cl_check_fail_(expr, desc) clay__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 0)
#define cl_check_(expr, desc) clay__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) clay__assert(0, __FILE__, __LINE__, "Test failed.", desc, 1)
#define cl_warning(desc) clay__assert(0, __FILE__, __LINE__, "Warning during test execution:", desc, 0)
#endif
#ifndef __CLAY_LIBGIT2__
#define __CLAY_LIBGIT2__
#include "clay.h"
#include <git2.h>
#include "common.h"
/**
* Special wrapper for `clay_must_pass` that passes
* the last library error as the test failure message.
*
* Use this wrapper around all `git_` library calls that
* return error codes!
*/
#define cl_git_pass(expr) do { \
git_clearerror(); \
if ((expr) != GIT_SUCCESS) \
clay__assert(0, __FILE__, __LINE__, "Function call failed: " #expr, git_lasterror(), 1); \
} while(0);
/**
* Wrapper for `clay_must_fail` -- this one is
* just for consistency. Use with `git_` library
* calls that are supposed to fail!
*/
#define cl_git_fail(expr) cl_must_fail((expr))
#endif
#include "clay_libgit2.h"
#include "fileops.h"
typedef struct name_data {
int count; /* return count */
char *name; /* filename */
} name_data;
typedef struct walk_data {
char *sub; /* sub-directory name */
name_data *names; /* name state data */
} walk_data;
static char path_buffer[GIT_PATH_MAX];
static char *top_dir = "dir-walk";
static walk_data *state_loc;
static void setup(walk_data *d)
{
name_data *n;
cl_must_pass(p_mkdir(top_dir, 0755));
cl_must_pass(p_chdir(top_dir));
if (strcmp(d->sub, ".") != 0)
cl_must_pass(p_mkdir(d->sub, 0755));
strcpy(path_buffer, d->sub);
state_loc = d;
for (n = d->names; n->name; n++) {
git_file fd = p_creat(n->name, 0600);
cl_assert(fd >= 0);
p_close(fd);
n->count = 0;
}
}
static void dirent_cleanup__cb(void *_d)
{
walk_data *d = _d;
name_data *n;
for (n = d->names; n->name; n++) {
cl_must_pass(p_unlink(n->name));
}
if (strcmp(d->sub, ".") != 0)
cl_must_pass(p_rmdir(d->sub));
cl_must_pass(p_chdir(".."));
cl_must_pass(p_rmdir(top_dir));
}
static void check_counts(walk_data *d)
{
name_data *n;
for (n = d->names; n->name; n++) {
cl_assert(n->count == 1);
}
}
static int one_entry(void *state, char *path)
{
walk_data *d = (walk_data *) state;
name_data *n;
if (state != state_loc)
return GIT_ERROR;
if (path != path_buffer)
return GIT_ERROR;
for (n = d->names; n->name; n++) {
if (!strcmp(n->name, path)) {
n->count++;
return 0;
}
}
return GIT_ERROR;
}
static int dont_call_me(void *GIT_UNUSED(state), char *GIT_UNUSED(path))
{
GIT_UNUSED_ARG(state)
GIT_UNUSED_ARG(path)
return GIT_ERROR;
}
static name_data dot_names[] = {
{ 0, "./a" },
{ 0, "./asdf" },
{ 0, "./pack-foo.pack" },
{ 0, NULL }
};
static walk_data dot = {
".",
dot_names
};
/* make sure that the '.' folder is not traversed */
void test_core_dirent__dont_traverse_dot(void)
{
cl_set_cleanup(&dirent_cleanup__cb, &dot);
setup(&dot);
cl_git_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&dot));
check_counts(&dot);
}
static name_data sub_names[] = {
{ 0, "sub/a" },
{ 0, "sub/asdf" },
{ 0, "sub/pack-foo.pack" },
{ 0, NULL }
};
static walk_data sub = {
"sub",
sub_names
};
/* traverse a subfolder */
void test_core_dirent__traverse_subfolder(void)
{
cl_set_cleanup(&dirent_cleanup__cb, &sub);
setup(&sub);
cl_git_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&sub));
check_counts(&sub);
}
static walk_data sub_slash = {
"sub/",
sub_names
};
/* traverse a slash-terminated subfolder */
void test_core_dirent__traverse_slash_terminated_folder(void)
{
cl_set_cleanup(&dirent_cleanup__cb, &sub_slash);
setup(&sub_slash);
cl_git_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&sub_slash));
check_counts(&sub_slash);
}
static name_data empty_names[] = {
{ 0, NULL }
};
static walk_data empty = {
"empty",
empty_names
};
/* make sure that empty folders are not traversed */
void test_core_dirent__dont_traverse_empty_folders(void)
{
cl_set_cleanup(&dirent_cleanup__cb, &empty);
setup(&empty);
cl_git_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&empty));
check_counts(&empty);
/* make sure callback not called */
cl_git_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
dont_call_me,
&empty));
}
static name_data odd_names[] = {
{ 0, "odd/.a" },
{ 0, "odd/..c" },
/* the following don't work on cygwin/win32 */
/* { 0, "odd/.b." }, */
/* { 0, "odd/..d.." }, */
{ 0, NULL }
};
static walk_data odd = {
"odd",
odd_names
};
/* make sure that strange looking filenames ('..c') are traversed */
void test_core_dirent__traverse_weird_filenames(void)
{
cl_set_cleanup(&dirent_cleanup__cb, &odd);
setup(&odd);
cl_git_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&odd));
check_counts(&odd);
}
#include "clay_libgit2.h"
#include "filebuf.h"
/* make sure git_filebuf_open doesn't delete an existing lock */
void test_core_filebuf__0(void)
{
git_filebuf file;
int fd;
char test[] = "test", testlock[] = "test.lock";
fd = p_creat(testlock, 0744);
cl_must_pass(fd);
cl_must_pass(p_close(fd));
cl_git_fail(git_filebuf_open(&file, test, 0));
cl_git_pass(git_futils_exists(testlock));
cl_must_pass(p_unlink(testlock));
}
/* make sure GIT_FILEBUF_APPEND works as expected */
void test_core_filebuf__1(void)
{
git_filebuf file;
int fd;
char test[] = "test";
fd = p_creat(test, 0644);
cl_must_pass(fd);
cl_must_pass(p_write(fd, "libgit2 rocks\n", 14));
cl_must_pass(p_close(fd));
cl_git_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND));
cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
cl_git_pass(git_filebuf_commit(&file));
cl_must_pass(p_unlink(test));
}
/* make sure git_filebuf_write writes large buffer correctly */
void test_core_filebuf__2(void)
{
git_filebuf file;
char test[] = "test";
unsigned char buf[4096 * 4]; /* 2 * WRITE_BUFFER_SIZE */
memset(buf, 0xfe, sizeof(buf));
cl_git_pass(git_filebuf_open(&file, test, 0));
cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf)));
cl_git_pass(git_filebuf_commit(&file));
cl_must_pass(p_unlink(test));
}
#include "clay_libgit2.h"
#include <fileops.h>
static void
check_dirname(const char *A, const char *B)
{
char dir[64], *dir2;
cl_assert(git_path_dirname_r(dir, sizeof(dir), A) >= 0);
cl_assert(strcmp(dir, B) == 0);
cl_assert((dir2 = git_path_dirname(A)) != NULL);
cl_assert(strcmp(dir2, B) == 0);
free(dir2);
}
static void
check_basename(const char *A, const char *B)
{
char base[64], *base2;
cl_assert(git_path_basename_r(base, sizeof(base), A) >= 0);
cl_assert(strcmp(base, B) == 0);
cl_assert((base2 = git_path_basename(A)) != NULL);
cl_assert(strcmp(base2, B) == 0);
free(base2);
}
static void
check_topdir(const char *A, const char *B)
{
const char *dir;
cl_assert((dir = git_path_topdir(A)) != NULL);
cl_assert(strcmp(dir, B) == 0);
}
static void
check_joinpath(const char *path_a, const char *path_b, const char *expected_path)
{
char joined_path[GIT_PATH_MAX];
git_path_join(joined_path, path_a, path_b);
cl_assert(strcmp(joined_path, expected_path) == 0);
}
static void
check_joinpath_n(
const char *path_a,
const char *path_b,
const char *path_c,
const char *path_d,
const char *expected_path)
{
char joined_path[GIT_PATH_MAX];
git_path_join_n(joined_path, 4, path_a, path_b, path_c, path_d);
cl_assert(strcmp(joined_path, expected_path) == 0);
}
/* get the dirname of a path */
void test_core_path__0(void)
{
check_dirname(NULL, ".");
check_dirname("", ".");
check_dirname("a", ".");
check_dirname("/", "/");
check_dirname("/usr", "/");
check_dirname("/usr/", "/");
check_dirname("/usr/lib", "/usr");
check_dirname("/usr/lib/", "/usr");
check_dirname("/usr/lib//", "/usr");
check_dirname("usr/lib", "usr");
check_dirname("usr/lib/", "usr");
check_dirname("usr/lib//", "usr");
check_dirname(".git/", ".");
}
/* get the base name of a path */
void test_core_path__1(void)
{
check_basename(NULL, ".");
check_basename("", ".");
check_basename("a", "a");
check_basename("/", "/");
check_basename("/usr", "usr");
check_basename("/usr/", "usr");
check_basename("/usr/lib", "lib");
check_basename("/usr/lib//", "lib");
check_basename("usr/lib", "lib");
}
/* get the latest component in a path */
void test_core_path__2(void)
{
check_topdir(".git/", ".git/");
check_topdir("/.git/", ".git/");
check_topdir("usr/local/.git/", ".git/");
check_topdir("./.git/", ".git/");
check_topdir("/usr/.git/", ".git/");
check_topdir("/", "/");
check_topdir("a/", "a/");
cl_assert(git_path_topdir("/usr/.git") == NULL);
cl_assert(git_path_topdir(".") == NULL);
cl_assert(git_path_topdir("") == NULL);
cl_assert(git_path_topdir("a") == NULL);
}
/* properly join path components */
void test_core_path__5(void)
{
check_joinpath("", "", "");
check_joinpath("", "a", "a");
check_joinpath("", "/a", "/a");
check_joinpath("a", "", "a/");
check_joinpath("a", "/", "a/");
check_joinpath("a", "b", "a/b");
check_joinpath("/", "a", "/a");
check_joinpath("/", "", "/");
check_joinpath("/a", "/b", "/a/b");
check_joinpath("/a", "/b/", "/a/b/");
check_joinpath("/a/", "b/", "/a/b/");
check_joinpath("/a/", "/b/", "/a/b/");
}
/* properly join path components for more than one path */
void test_core_path__6(void)
{
check_joinpath_n("", "", "", "", "");
check_joinpath_n("", "a", "", "", "a/");
check_joinpath_n("a", "", "", "", "a/");
check_joinpath_n("", "", "", "a", "a");
check_joinpath_n("a", "b", "", "/c/d/", "a/b/c/d/");
check_joinpath_n("a", "b", "", "/c/d", "a/b/c/d");
}
#include "clay_libgit2.h"
#include "fileops.h"
static const char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test";
void test_core_rmdir__initialize()
{
char path[GIT_PATH_MAX];
cl_must_pass(p_mkdir(empty_tmp_dir, 0755));
git_path_join(path, empty_tmp_dir, "/one");
cl_must_pass(p_mkdir(path, 0755));
git_path_join(path, empty_tmp_dir, "/one/two_one");
cl_must_pass(p_mkdir(path, 0755));
git_path_join(path, empty_tmp_dir, "/one/two_two");
cl_must_pass(p_mkdir(path, 0755));
git_path_join(path, empty_tmp_dir, "/one/two_two/three");
cl_must_pass(p_mkdir(path, 0755));
git_path_join(path, empty_tmp_dir, "/two");
cl_must_pass(p_mkdir(path, 0755));
}
/* make sure empty dir can be deleted recusively */
void test_core_rmdir__delete_recursive(void)
{
cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, 0));
}
/* make sure non-empty dir cannot be deleted recusively */
void test_core_rmdir__fail_to_delete_non_empty_dir(void)
{
char file[GIT_PATH_MAX];
int fd;
git_path_join(file, empty_tmp_dir, "/two/file.txt");
fd = p_creat(file, 0755);
cl_assert(fd >= 0);
cl_must_pass(p_close(fd));
cl_git_fail(git_futils_rmdir_r(empty_tmp_dir, 0));
cl_must_pass(p_unlink(file));
cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, 0));
}
#include "clay_libgit2.h"
/* compare prefixes */
void test_core_string__0(void)
{
cl_assert(git__prefixcmp("", "") == 0);
cl_assert(git__prefixcmp("a", "") == 0);
cl_assert(git__prefixcmp("", "a") < 0);
cl_assert(git__prefixcmp("a", "b") < 0);
cl_assert(git__prefixcmp("b", "a") > 0);
cl_assert(git__prefixcmp("ab", "a") == 0);
cl_assert(git__prefixcmp("ab", "ac") < 0);
cl_assert(git__prefixcmp("ab", "aa") > 0);
}
/* compare suffixes */
void test_core_string__1(void)
{
cl_assert(git__suffixcmp("", "") == 0);
cl_assert(git__suffixcmp("a", "") == 0);
cl_assert(git__suffixcmp("", "a") < 0);
cl_assert(git__suffixcmp("a", "b") < 0);
cl_assert(git__suffixcmp("b", "a") > 0);
cl_assert(git__suffixcmp("ba", "a") == 0);
cl_assert(git__suffixcmp("zaa", "ac") < 0);
cl_assert(git__suffixcmp("zaz", "ac") > 0);
}
#include "clay_libgit2.h"
#include "vector.h"
/* initial size of 1 would cause writing past array bounds */
void test_core_vector__0(void)
{
git_vector x;
int i;
git_vector_init(&x, 1, NULL);
for (i = 0; i < 10; ++i) {
git_vector_insert(&x, (void*) 0xabc);
}
git_vector_free(&x);
}
/* don't read past array bounds on remove() */
void test_core_vector__1(void)
{
git_vector x;
// make initial capacity exact for our insertions.
git_vector_init(&x, 3, NULL);
git_vector_insert(&x, (void*) 0xabc);
git_vector_insert(&x, (void*) 0xdef);
git_vector_insert(&x, (void*) 0x123);
git_vector_remove(&x, 0); // used to read past array bounds.
git_vector_free(&x);
}
static int test_cmp(const void *a, const void *b)
{
return *(const int *)a - *(const int *)b;
}
/* remove duplicates */
void test_core_vector__2(void)
{
git_vector x;
int *ptrs[2];
ptrs[0] = git__malloc(sizeof(int));
ptrs[1] = git__malloc(sizeof(int));
*ptrs[0] = 2;
*ptrs[1] = 1;
cl_git_pass(git_vector_init(&x, 5, test_cmp));
cl_git_pass(git_vector_insert(&x, ptrs[0]));
cl_git_pass(git_vector_insert(&x, ptrs[1]));
cl_git_pass(git_vector_insert(&x, ptrs[1]));
cl_git_pass(git_vector_insert(&x, ptrs[0]));
cl_git_pass(git_vector_insert(&x, ptrs[1]));
cl_assert(x.length == 5);
git_vector_uniq(&x);
cl_assert(x.length == 2);
git_vector_free(&x);
free(ptrs[0]);
free(ptrs[1]);
}
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