summaryrefslogtreecommitdiff
path: root/deps/hiredis/test.c
diff options
context:
space:
mode:
authorMatt Stancliff <matt@genges.com>2014-04-24 15:14:54 -0400
committerantirez <antirez@gmail.com>2014-06-23 11:44:34 +0200
commit28f32c99d0118eb60b236a0c8a96ea4bd9b7fa5b (patch)
tree393b4873a2dc0a28e9f7110605f4eae672d20b75 /deps/hiredis/test.c
parentef897a41e80eb03a18d131d6a3c4d1d868f38ea0 (diff)
downloadredis-28f32c99d0118eb60b236a0c8a96ea4bd9b7fa5b.tar.gz
hiredis: Update to latest version
This is hiredis f225c276be7fd0646019b51023e3f41566633dfe This update includes all changes that diverged inside of Redis since the last update. This version also allows optional source address binding for connections which we need for some Sentinel deployments.
Diffstat (limited to 'deps/hiredis/test.c')
-rw-r--r--deps/hiredis/test.c111
1 files changed, 95 insertions, 16 deletions
diff --git a/deps/hiredis/test.c b/deps/hiredis/test.c
index 5945b6552..713cc06c5 100644
--- a/deps/hiredis/test.c
+++ b/deps/hiredis/test.c
@@ -8,12 +8,14 @@
#include <unistd.h>
#include <signal.h>
#include <errno.h>
+#include <limits.h>
#include "hiredis.h"
enum connection_type {
CONN_TCP,
- CONN_UNIX
+ CONN_UNIX,
+ CONN_FD
};
struct config {
@@ -22,6 +24,7 @@ struct config {
struct {
const char *host;
int port;
+ struct timeval timeout;
} tcp;
struct {
@@ -62,7 +65,7 @@ static redisContext *select_database(redisContext *c) {
return c;
}
-static void disconnect(redisContext *c) {
+static int disconnect(redisContext *c, int keep_fd) {
redisReply *reply;
/* Make sure we're on DB 9. */
@@ -73,8 +76,11 @@ static void disconnect(redisContext *c) {
assert(reply != NULL);
freeReplyObject(reply);
- /* Free the context as well. */
+ /* Free the context as well, but keep the fd if requested. */
+ if (keep_fd)
+ return redisFreeKeepFd(c);
redisFree(c);
+ return -1;
}
static redisContext *connect(struct config config) {
@@ -84,11 +90,22 @@ static redisContext *connect(struct config config) {
c = redisConnect(config.tcp.host, config.tcp.port);
} else if (config.type == CONN_UNIX) {
c = redisConnectUnix(config.unix.path);
+ } else if (config.type == CONN_FD) {
+ /* Create a dummy connection just to get an fd to inherit */
+ redisContext *dummy_ctx = redisConnectUnix(config.unix.path);
+ if (dummy_ctx) {
+ int fd = disconnect(dummy_ctx, 1);
+ printf("Connecting to inherited fd %d\n", fd);
+ c = redisConnectFd(fd);
+ }
} else {
assert(NULL);
}
- if (c->err) {
+ if (c == NULL) {
+ printf("Connection error: can't allocate redis context\n");
+ exit(1);
+ } else if (c->err) {
printf("Connection error: %s\n", c->errstr);
exit(1);
}
@@ -125,13 +142,13 @@ static void test_format_commands(void) {
free(cmd);
test("Format command with %%b string interpolation: ");
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
+ 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);
test("Format command with %%b and an empty string: ");
- len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0);
+ 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);
@@ -177,7 +194,7 @@ static void test_format_commands(void) {
FLOAT_WIDTH_TEST(double);
test("Format command with invalid printf format: ");
- len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
+ len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);
test_cond(len == -1);
const char *argv[3];
@@ -200,10 +217,33 @@ static void test_format_commands(void) {
free(cmd);
}
+static void test_append_formatted_commands(struct config config) {
+ redisContext *c;
+ redisReply *reply;
+ char *cmd;
+ int len;
+
+ c = connect(config);
+
+ test("Append format command: ");
+
+ len = redisFormatCommand(&cmd, "SET foo bar");
+
+ test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);
+
+ assert(redisGetReply(c, (void*)&reply) == REDIS_OK);
+
+ free(cmd);
+ freeReplyObject(reply);
+
+ disconnect(c, 0);
+}
+
static void test_reply_reader(void) {
redisReader *reader;
void *reply;
int ret;
+ int i;
test("Error handling in reply parser: ");
reader = redisReaderCreate();
@@ -225,12 +265,13 @@ static void test_reply_reader(void) {
strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
redisReaderFree(reader);
- test("Set error on nested multi bulks with depth > 2: ");
+ test("Set error on nested multi bulks with depth > 7: ");
reader = redisReaderCreate();
- redisReaderFeed(reader,(char*)"*1\r\n",4);
- redisReaderFeed(reader,(char*)"*1\r\n",4);
- redisReaderFeed(reader,(char*)"*1\r\n",4);
- redisReaderFeed(reader,(char*)"*1\r\n",4);
+
+ for (i = 0; i < 9; i++) {
+ redisReaderFeed(reader,(char*)"*1\r\n",4);
+ }
+
ret = redisReaderGetReply(reader,NULL);
test_cond(ret == REDIS_ERR &&
strncasecmp(reader->errstr,"No support for",14) == 0);
@@ -284,7 +325,10 @@ static void test_blocking_connection_errors(void) {
c = redisConnect((char*)"idontexist.local", 6379);
test_cond(c->err == REDIS_ERR_OTHER &&
(strcmp(c->errstr,"Name or service not known") == 0 ||
- strcmp(c->errstr,"Can't resolve: idontexist.local") == 0));
+ strcmp(c->errstr,"Can't resolve: idontexist.local") == 0 ||
+ strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 ||
+ strcmp(c->errstr,"No address associated with hostname") == 0 ||
+ strcmp(c->errstr,"no address associated with name") == 0));
redisFree(c);
test("Returns error when the port is not open: ");
@@ -326,7 +370,7 @@ static void test_blocking_connection(struct config config) {
freeReplyObject(reply);
test("%%b String interpolation works: ");
- reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
+ reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11);
freeReplyObject(reply);
reply = redisCommand(c,"GET foo");
test_cond(reply->type == REDIS_REPLY_STRING &&
@@ -374,7 +418,7 @@ static void test_blocking_connection(struct config config) {
strcasecmp(reply->element[1]->str,"pong") == 0);
freeReplyObject(reply);
- disconnect(c);
+ disconnect(c, 0);
}
static void test_blocking_io_errors(struct config config) {
@@ -428,6 +472,30 @@ static void test_blocking_io_errors(struct config config) {
redisFree(c);
}
+static void test_invalid_timeout_errors(struct config config) {
+ redisContext *c;
+
+ test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: ");
+
+ config.tcp.timeout.tv_sec = 0;
+ config.tcp.timeout.tv_usec = 10000001;
+
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
+
+ test_cond(c->err == REDIS_ERR_IO);
+
+ test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: ");
+
+ config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;
+ config.tcp.timeout.tv_usec = 0;
+
+ c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
+
+ test_cond(c->err == REDIS_ERR_IO);
+
+ redisFree(c);
+}
+
static void test_throughput(struct config config) {
redisContext *c = connect(config);
redisReply **replies;
@@ -490,7 +558,7 @@ static void test_throughput(struct config config) {
free(replies);
printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
- disconnect(c);
+ disconnect(c, 0);
}
// static long __test_callback_flags = 0;
@@ -603,6 +671,7 @@ int main(int argc, char **argv) {
}
};
int throughput = 1;
+ int test_inherit_fd = 1;
/* Ignore broken pipe signal (for I/O error tests). */
signal(SIGPIPE, SIG_IGN);
@@ -621,6 +690,8 @@ int main(int argc, char **argv) {
cfg.unix.path = argv[0];
} else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {
throughput = 0;
+ } else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
+ test_inherit_fd = 0;
} else {
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
exit(1);
@@ -636,6 +707,8 @@ int main(int argc, char **argv) {
cfg.type = CONN_TCP;
test_blocking_connection(cfg);
test_blocking_io_errors(cfg);
+ test_invalid_timeout_errors(cfg);
+ test_append_formatted_commands(cfg);
if (throughput) test_throughput(cfg);
printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path);
@@ -644,6 +717,12 @@ int main(int argc, char **argv) {
test_blocking_io_errors(cfg);
if (throughput) test_throughput(cfg);
+ if (test_inherit_fd) {
+ printf("\nTesting against inherited fd (%s):\n", cfg.unix.path);
+ cfg.type = CONN_FD;
+ test_blocking_connection(cfg);
+ }
+
if (fails) {
printf("*** %d TESTS FAILED ***\n", fails);
return 1;