Skip to content

Commit abe2efe

Browse files
committed
Introduce GIT_ASSERT macros
Provide macros to replace usages of `assert`. A true `assert` is punishing as a library. Instead we should do our best to not crash. GIT_ASSERT_ARG(x) will now assert that the given argument complies to some format and sets an error message and returns `-1` if it does not. GIT_ASSERT(x) is for internal usage, and available as an internal consistency check. It will set an error message and return `-1` in the event of failure.
1 parent b83bc6d commit abe2efe

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

include/git2/errors.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ typedef enum {
107107
GIT_ERROR_PATCH,
108108
GIT_ERROR_WORKTREE,
109109
GIT_ERROR_SHA1,
110-
GIT_ERROR_HTTP
110+
GIT_ERROR_HTTP,
111+
GIT_ERROR_INTERNAL
111112
} git_error_t;
112113

113114
/**

src/common.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,33 @@
9494
#define FILTERIO_BUFSIZE DEFAULT_BUFSIZE
9595
#define NETIO_BUFSIZE DEFAULT_BUFSIZE
9696

97+
/**
98+
* Assert that a consumer-provided argument is valid, setting an
99+
* actionable error message and returning -1 if it is not.
100+
*
101+
* Note that memory leaks can occur in a release-mode assertion
102+
* failure -- it is impractical to provide safe clean up routines in these very
103+
* extreme failures, but care should be taken to not leak very large objects.
104+
*/
105+
#define GIT_ASSERT_ARG(expr) do { \
106+
if (!(expr)) { \
107+
git_error_set(GIT_ERROR_INVALID, \
108+
"invalid argument: '%s'", \
109+
#expr); \
110+
return -1; \
111+
} \
112+
} while(0)
113+
114+
/** Internal consistency check to stop the function. */
115+
#define GIT_ASSERT(expr) do { \
116+
if (!(expr)) { \
117+
git_error_set(GIT_ERROR_INTERNAL, \
118+
"unrecoverable internal error: '%s'", \
119+
#expr); \
120+
return -1; \
121+
} \
122+
} while(0)
123+
97124
/**
98125
* Check a pointer allocation result, returning -1 if it failed.
99126
*/

tests/core/assert.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include "clar_libgit2.h"
2+
3+
static const char *hello_world = "hello, world";
4+
5+
static int dummy_fn(const char *myarg)
6+
{
7+
GIT_ASSERT_ARG(myarg);
8+
GIT_ASSERT_ARG(myarg != hello_world);
9+
return 0;
10+
}
11+
12+
static int bad_math(void)
13+
{
14+
GIT_ASSERT(1 + 1 == 3);
15+
return 42;
16+
}
17+
18+
void test_core_assert__argument(void)
19+
{
20+
cl_git_fail(dummy_fn(NULL));
21+
cl_assert(git_error_last());
22+
cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass);
23+
cl_assert_equal_s("invalid argument: 'myarg'", git_error_last()->message);
24+
25+
cl_git_fail(dummy_fn(hello_world));
26+
cl_assert(git_error_last());
27+
cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass);
28+
cl_assert_equal_s("invalid argument: 'myarg != hello_world'", git_error_last()->message);
29+
30+
cl_git_pass(dummy_fn("foo"));
31+
}
32+
33+
void test_core_assert__internal(void)
34+
{
35+
cl_git_fail(bad_math());
36+
cl_assert(git_error_last());
37+
cl_assert_equal_i(GIT_ERROR_INTERNAL, git_error_last()->klass);
38+
cl_assert_equal_s("unrecoverable internal error: '1 + 1 == 3'", git_error_last()->message);
39+
}

0 commit comments

Comments
 (0)