assert: allow non-int returning functions to assert Include GIT_ASSERT_WITH_RETVAL and GIT_ASSERT_ARG_WITH_RETVAL so that functions that do not return int (or more precisely, where `-1` would not be an error code) can assert. This allows functions that return, eg, NULL on an error code to do that by passing the return value (in this example, `NULL`) as a second parameter to the GIT_ASSERT_WITH_RETVAL functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
diff --git a/src/assert_safe.h b/src/assert_safe.h
index 9f2e164..8c26110 100644
--- a/src/assert_safe.h
+++ b/src/assert_safe.h
@@ -21,28 +21,35 @@
# define GIT_ASSERT(expr) assert(expr)
# define GIT_ASSERT_ARG(expr) assert(expr)
+
+# define GIT_ASSERT_WITH_RETVAL(expr, fail) assert(expr)
+# define GIT_ASSERT_ARG_WITH_RETVAL(expr, fail) assert(expr)
#else
+/** Internal consistency check to stop the function. */
+# define GIT_ASSERT(expr) GIT_ASSERT_WITH_RETVAL(expr, -1)
+
/**
* Assert that a consumer-provided argument is valid, setting an
* actionable error message and returning -1 if it is not.
*/
-# define GIT_ASSERT_ARG(expr) do { \
- if (!(expr)) { \
- git_error_set(GIT_ERROR_INVALID, \
- "invalid argument: '%s'", \
- #expr); \
- return -1; \
- } \
- } while(0)
+# define GIT_ASSERT_ARG(expr) GIT_ASSERT_ARG_WITH_RETVAL(expr, -1)
+
+/** Internal consistency check to return the `fail` param on failure. */
+# define GIT_ASSERT_WITH_RETVAL(expr, fail) \
+ GIT_ASSERT__WITH_RETVAL(expr, GIT_ERROR_INTERNAL, "unrecoverable internal error", fail)
+
+/**
+ * Assert that a consumer-provided argument is valid, setting an
+ * actionable error message and returning the `fail` param if not.
+ */
+# define GIT_ASSERT_ARG_WITH_RETVAL(expr, fail) \
+ GIT_ASSERT__WITH_RETVAL(expr, GIT_ERROR_INVALID, "invalid argument", fail)
-/* Internal consistency check to stop the function. */
-# define GIT_ASSERT(expr) do { \
+# define GIT_ASSERT__WITH_RETVAL(expr, code, msg, fail) do { \
if (!(expr)) { \
- git_error_set(GIT_ERROR_INTERNAL, \
- "unrecoverable internal error: '%s'", \
- #expr); \
- return -1; \
+ git_error_set(code, "%s: '%s'", msg, #expr); \
+ return fail; \
} \
} while(0)
diff --git a/tests/core/assert.c b/tests/core/assert.c
index 5260b26..ef75624 100644
--- a/tests/core/assert.c
+++ b/tests/core/assert.c
@@ -1,8 +1,13 @@
+#ifdef GIT_ASSERT_HARD
+# undef GIT_ASSERT_HARD
+#endif
+
#define GIT_ASSERT_HARD 0
#include "clar_libgit2.h"
static const char *hello_world = "hello, world";
+static const char *fail = "FAIL";
static int dummy_fn(const char *myarg)
{
@@ -11,12 +16,26 @@ static int dummy_fn(const char *myarg)
return 0;
}
+static const char *fn_returns_string(const char *myarg)
+{
+ GIT_ASSERT_ARG_WITH_RETVAL(myarg, fail);
+ GIT_ASSERT_ARG_WITH_RETVAL(myarg != hello_world, fail);
+
+ return myarg;
+}
+
static int bad_math(void)
{
GIT_ASSERT(1 + 1 == 3);
return 42;
}
+static const char *bad_returns_string(void)
+{
+ GIT_ASSERT_WITH_RETVAL(1 + 1 == 3, NULL);
+ return hello_world;
+}
+
void test_core_assert__argument(void)
{
cl_git_fail(dummy_fn(NULL));
@@ -32,10 +51,44 @@ void test_core_assert__argument(void)
cl_git_pass(dummy_fn("foo"));
}
+void test_core_assert__argument_with_non_int_return_type(void)
+{
+ const char *foo = "foo";
+
+ cl_assert_equal_p(fail, fn_returns_string(NULL));
+ cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass);
+ cl_assert_equal_s("invalid argument: 'myarg'", git_error_last()->message);
+
+ cl_assert_equal_p(fail, fn_returns_string(hello_world));
+ cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass);
+ cl_assert_equal_s("invalid argument: 'myarg != hello_world'", git_error_last()->message);
+
+ cl_assert_equal_p(foo, fn_returns_string(foo));
+}
+
+void test_core_assert__argument_with_void_return_type(void)
+{
+ const char *foo = "foo";
+
+ git_error_clear();
+ fn_returns_string(hello_world);
+ cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass);
+ cl_assert_equal_s("invalid argument: 'myarg != hello_world'", git_error_last()->message);
+
+ git_error_clear();
+ cl_assert_equal_p(foo, fn_returns_string(foo));
+ cl_assert_equal_p(NULL, git_error_last());
+}
+
void test_core_assert__internal(void)
{
cl_git_fail(bad_math());
cl_assert(git_error_last());
cl_assert_equal_i(GIT_ERROR_INTERNAL, git_error_last()->klass);
cl_assert_equal_s("unrecoverable internal error: '1 + 1 == 3'", git_error_last()->message);
+
+ cl_assert_equal_p(NULL, bad_returns_string());
+ cl_assert(git_error_last());
+ cl_assert_equal_i(GIT_ERROR_INTERNAL, git_error_last()->klass);
+ cl_assert_equal_s("unrecoverable internal error: '1 + 1 == 3'", git_error_last()->message);
}