summaryrefslogtreecommitdiff
path: root/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'test.c')
-rw-r--r--test.c113
1 files changed, 89 insertions, 24 deletions
diff --git a/test.c b/test.c
index 1d38caa..48d36d0 100644
--- a/test.c
+++ b/test.c
@@ -180,43 +180,43 @@ static void test_format_commands(void) {
len = redisFormatCommand(&cmd,"SET foo bar");
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(3+2)+4+(3+2));
- free(cmd);
+ hi_free(cmd);
test("Format command with %%s string interpolation: ");
len = redisFormatCommand(&cmd,"SET %s %s","foo","bar");
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(3+2)+4+(3+2));
- free(cmd);
+ hi_free(cmd);
test("Format command with %%s and an empty string: ");
len = redisFormatCommand(&cmd,"SET %s %s","foo","");
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(3+2)+4+(0+2));
- free(cmd);
+ hi_free(cmd);
test("Format command with an empty string in between proper interpolations: ");
len = redisFormatCommand(&cmd,"SET %s %s","","foo");
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(0+2)+4+(3+2));
- free(cmd);
+ hi_free(cmd);
test("Format command with %%b string interpolation: ");
len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3);
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(3+2)+4+(3+2));
- free(cmd);
+ hi_free(cmd);
test("Format command with %%b and an empty string: ");
len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0);
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(3+2)+4+(0+2));
- free(cmd);
+ hi_free(cmd);
test("Format command with literal %%: ");
len = redisFormatCommand(&cmd,"SET %% %%");
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$1\r\n%\r\n$1\r\n%\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(1+2)+4+(1+2));
- free(cmd);
+ hi_free(cmd);
/* Vararg width depends on the type. These tests make sure that the
* width is correctly determined using the format and subsequent varargs
@@ -227,7 +227,7 @@ static void test_format_commands(void) {
len = redisFormatCommand(&cmd,"key:%08" fmt " str:%s", value, "hello"); \
test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:00000123\r\n$9\r\nstr:hello\r\n",len) == 0 && \
len == 4+5+(12+2)+4+(9+2)); \
- free(cmd); \
+ hi_free(cmd); \
} while(0)
#define FLOAT_WIDTH_TEST(type) do { \
@@ -236,7 +236,7 @@ static void test_format_commands(void) {
len = redisFormatCommand(&cmd,"key:%08.3f str:%s", value, "hello"); \
test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:0123.000\r\n$9\r\nstr:hello\r\n",len) == 0 && \
len == 4+5+(12+2)+4+(9+2)); \
- free(cmd); \
+ hi_free(cmd); \
} while(0)
INTEGER_WIDTH_TEST("d", int);
@@ -267,13 +267,13 @@ static void test_format_commands(void) {
len = redisFormatCommandArgv(&cmd,argc,argv,NULL);
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(3+2)+4+(3+2));
- free(cmd);
+ hi_free(cmd);
test("Format command by passing argc/argv with lengths: ");
len = redisFormatCommandArgv(&cmd,argc,argv,lens);
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(7+2)+4+(3+2));
- free(cmd);
+ hi_free(cmd);
sds sds_cmd;
@@ -308,7 +308,7 @@ static void test_append_formatted_commands(struct config config) {
assert(redisGetReply(c, (void*)&reply) == REDIS_OK);
- free(cmd);
+ hi_free(cmd);
freeReplyObject(reply);
disconnect(c, 0);
@@ -418,6 +418,16 @@ static void test_reply_reader(void) {
freeReplyObject(reply);
redisReaderFree(reader);
+ test("Can configure maximum multi-bulk elements: ");
+ reader = redisReaderCreate();
+ reader->maxelements = 1024;
+ redisReaderFeed(reader, "*1025\r\n", 7);
+ ret = redisReaderGetReply(reader,&reply);
+ test_cond(ret == REDIS_ERR &&
+ strcasecmp(reader->errstr, "Multi-bulk length out of range") == 0);
+ freeReplyObject(reply);
+ redisReaderFree(reader);
+
#if LLONG_MAX > SIZE_MAX
test("Set error when array > SIZE_MAX: ");
reader = redisReaderCreate();
@@ -518,6 +528,46 @@ static void test_free_null(void) {
test_cond(reply == NULL);
}
+static void *hi_malloc_fail(size_t size) {
+ (void)size;
+ return NULL;
+}
+
+static void *hi_calloc_fail(size_t nmemb, size_t size) {
+ (void)nmemb;
+ (void)size;
+ return NULL;
+}
+
+static void *hi_realloc_fail(void *ptr, size_t size) {
+ (void)ptr;
+ (void)size;
+ return NULL;
+}
+
+static void test_allocator_injection(void) {
+ hiredisAllocFuncs ha = {
+ .malloc = hi_malloc_fail,
+ .calloc = hi_calloc_fail,
+ .realloc = hi_realloc_fail,
+ .free = NULL,
+ };
+
+ // Override hiredis allocators
+ hiredisSetAllocators(&ha);
+
+ test("redisContext uses injected allocators: ");
+ redisContext *c = redisConnect("localhost", 6379);
+ test_cond(c == NULL);
+
+ test("redisReader uses injected allocators: ");
+ redisReader *reader = redisReaderCreate();
+ test_cond(reader == NULL);
+
+ // Return allocators to default
+ hiredisResetAllocators();
+}
+
#define HIREDIS_BAD_DOMAIN "idontexist-noreally.com"
static void test_blocking_connection_errors(void) {
redisContext *c;
@@ -799,6 +849,18 @@ static void test_invalid_timeout_errors(struct config config) {
redisFree(c);
}
+/* Wrap malloc to abort on failure so OOM checks don't make the test logic
+ * harder to follow. */
+void *hi_malloc_safe(size_t size) {
+ void *ptr = hi_malloc(size);
+ if (ptr == NULL) {
+ fprintf(stderr, "Error: Out of memory\n");
+ exit(-1);
+ }
+
+ return ptr;
+}
+
static void test_throughput(struct config config) {
redisContext *c = do_connect(config);
redisReply **replies;
@@ -810,7 +872,7 @@ static void test_throughput(struct config config) {
freeReplyObject(redisCommand(c,"LPUSH mylist foo"));
num = 1000;
- replies = malloc(sizeof(redisReply*)*num);
+ replies = hi_malloc_safe(sizeof(redisReply*)*num);
t1 = usec();
for (i = 0; i < num; i++) {
replies[i] = redisCommand(c,"PING");
@@ -818,10 +880,10 @@ static void test_throughput(struct config config) {
}
t2 = usec();
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
- free(replies);
+ hi_free(replies);
printf("\t(%dx PING: %.3fs)\n", num, (t2-t1)/1000000.0);
- replies = malloc(sizeof(redisReply*)*num);
+ replies = hi_malloc_safe(sizeof(redisReply*)*num);
t1 = usec();
for (i = 0; i < num; i++) {
replies[i] = redisCommand(c,"LRANGE mylist 0 499");
@@ -830,10 +892,10 @@ static void test_throughput(struct config config) {
}
t2 = usec();
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
- free(replies);
+ hi_free(replies);
printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0);
- replies = malloc(sizeof(redisReply*)*num);
+ replies = hi_malloc_safe(sizeof(redisReply*)*num);
t1 = usec();
for (i = 0; i < num; i++) {
replies[i] = redisCommand(c, "INCRBY incrkey %d", 1000000);
@@ -841,11 +903,11 @@ static void test_throughput(struct config config) {
}
t2 = usec();
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
- free(replies);
+ hi_free(replies);
printf("\t(%dx INCRBY: %.3fs)\n", num, (t2-t1)/1000000.0);
num = 10000;
- replies = malloc(sizeof(redisReply*)*num);
+ replies = hi_malloc_safe(sizeof(redisReply*)*num);
for (i = 0; i < num; i++)
redisAppendCommand(c,"PING");
t1 = usec();
@@ -855,10 +917,10 @@ static void test_throughput(struct config config) {
}
t2 = usec();
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
- free(replies);
+ hi_free(replies);
printf("\t(%dx PING (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
- replies = malloc(sizeof(redisReply*)*num);
+ replies = hi_malloc_safe(sizeof(redisReply*)*num);
for (i = 0; i < num; i++)
redisAppendCommand(c,"LRANGE mylist 0 499");
t1 = usec();
@@ -869,10 +931,10 @@ static void test_throughput(struct config config) {
}
t2 = usec();
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
- free(replies);
+ hi_free(replies);
printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
- replies = malloc(sizeof(redisReply*)*num);
+ replies = hi_malloc_safe(sizeof(redisReply*)*num);
for (i = 0; i < num; i++)
redisAppendCommand(c,"INCRBY incrkey %d", 1000000);
t1 = usec();
@@ -882,7 +944,7 @@ static void test_throughput(struct config config) {
}
t2 = usec();
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
- free(replies);
+ hi_free(replies);
printf("\t(%dx INCRBY (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
disconnect(c, 0);
@@ -1049,11 +1111,14 @@ int main(int argc, char **argv) {
signal(SIGPIPE, SIG_IGN);
test_unix_socket = access(cfg.unix_sock.path, F_OK) == 0;
+
#else
/* Unix sockets don't exist in Windows */
test_unix_socket = 0;
#endif
+ test_allocator_injection();
+
test_format_commands();
test_reply_reader();
test_blocking_connection_errors();