diff --git a/libtransmission/libtransmission-test.c b/libtransmission/libtransmission-test.c index 302e37330..b1833e214 100644 --- a/libtransmission/libtransmission-test.c +++ b/libtransmission/libtransmission-test.c @@ -87,6 +87,47 @@ bool libtest_check_str(char const* file, int line, bool pass, char const* lhs, c return pass; } +static void print_mem(FILE* stream, void const* data, size_t size) +{ + if (data == NULL) + { + fprintf(stream, "NULL"); + return; + } + + if (size == 0) + { + fprintf(stream, "(no bytes)"); + return; + } + + uint8_t const* byte_data = data; + + fprintf(stream, "x'"); + + for (size_t i = 0; i < size; ++i) + { + fprintf(stream, "%02x", (unsigned int)byte_data[i]); + } + + fprintf(stream, "'"); +} + +bool libtest_check_mem(char const* file, int line, bool pass, void const* lhs, void const* rhs, size_t size, + char const* lhs_str, char const* op_str, char const* rhs_str) +{ + if (should_print(pass)) + { + fprintf(stderr, "%s %s:%d: %s %s %s (", pass ? "PASS" : "FAIL", file, line, lhs_str, op_str, rhs_str); + print_mem(stderr, lhs, size); + fprintf(stderr, " %s ", op_str); + print_mem(stderr, rhs, size); + fprintf(stderr, ")\n"); + } + + return pass; +} + bool libtest_check_int(char const* file, int line, bool pass, intmax_t lhs, intmax_t rhs, char const* lhs_str, char const* op_str, char const* rhs_str) { diff --git a/libtransmission/libtransmission-test.h b/libtransmission/libtransmission-test.h index c6c41197a..0943001b6 100644 --- a/libtransmission/libtransmission-test.h +++ b/libtransmission/libtransmission-test.h @@ -27,6 +27,8 @@ bool libtest_check_bool(char const* file, int line, bool pass, bool lhs, bool rh char const* rhs_str); bool libtest_check_str(char const* file, int line, bool pass, char const* lhs, char const* rhs, char const* lhs_str, char const* op_str, char const* rhs_str); +bool libtest_check_mem(char const* file, int line, bool pass, void const* lhs, void const* rhs, size_t size, + char const* lhs_str, char const* op_str, char const* rhs_str); bool libtest_check_int(char const* file, int line, bool pass, intmax_t lhs, intmax_t rhs, char const* lhs_str, char const* op_str, char const* rhs_str); bool libtest_check_uint(char const* file, int line, bool pass, uintmax_t lhs, uintmax_t rhs, char const* lhs_str, @@ -84,6 +86,23 @@ bool libtest_check_ptr(char const* file, int line, bool pass, void const* lhs, v } \ while (0) +#define check_mem(lhs, op, rhs, size) \ + do \ + { \ + ++current_test; \ + \ + void const* const check_mem_lhs = (lhs); \ + void const* const check_mem_rhs = (rhs); \ + size_t const check_mem_size = (size);\ + \ + if (!libtest_check_mem(__FILE__, __LINE__, tr_memcmp0(check_mem_lhs, check_mem_rhs, check_mem_size) op 0, \ + check_mem_lhs, check_mem_rhs, check_mem_size, #lhs, #op, #rhs)) \ + { \ + return current_test; \ + } \ + } \ + while (0) + #define check_int(lhs, op, rhs) \ do \ { \ diff --git a/libtransmission/utils.c b/libtransmission/utils.c index 5608068ba..ef5836626 100644 --- a/libtransmission/utils.c +++ b/libtransmission/utils.c @@ -493,6 +493,26 @@ int tr_strcmp0(char const* str1, char const* str2) return 0; } +int tr_memcmp0(void const* lhs, void const* rhs, size_t size) +{ + if (lhs != NULL && rhs != NULL) + { + return memcmp(lhs, rhs, size); + } + + if (lhs != NULL) + { + return 1; + } + + if (rhs != NULL) + { + return -1; + } + + return 0; +} + /**** ***** ****/ diff --git a/libtransmission/utils.h b/libtransmission/utils.h index d280cc338..93bcf7ae1 100644 --- a/libtransmission/utils.h +++ b/libtransmission/utils.h @@ -281,6 +281,11 @@ char* tr_strdup(void const* in); */ int tr_strcmp0(char const* str1, char const* str2); +/** + * @brief like memcmp() but gracefully handles NULL pointers + */ +int tr_memcmp0(void const* lhs, void const* rhs, size_t size); + char* evbuffer_free_to_str(struct evbuffer* buf, size_t* result_len); /** @brief similar to bsearch() but returns the index of the lower bound */