commit
0153527444
19
Makefile
19
Makefile
@ -65,6 +65,12 @@ STLIB_MAKE_CMD=$(AR) rcs
|
|||||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||||
|
|
||||||
USE_SSL?=0
|
USE_SSL?=0
|
||||||
|
|
||||||
|
# This is required for test.c only
|
||||||
|
ifeq ($(USE_SSL),1)
|
||||||
|
CFLAGS+=-DHIREDIS_TEST_SSL
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(uname_S),Linux)
|
ifeq ($(uname_S),Linux)
|
||||||
SSL_LDFLAGS=-lssl -lcrypto
|
SSL_LDFLAGS=-lssl -lcrypto
|
||||||
else
|
else
|
||||||
@ -176,19 +182,20 @@ hiredis-example: examples/example.c $(STLIBNAME)
|
|||||||
|
|
||||||
examples: $(EXAMPLES)
|
examples: $(EXAMPLES)
|
||||||
|
|
||||||
hiredis-test: test.o $(STLIBNAME)
|
TEST_LIBS = $(STLIBNAME)
|
||||||
|
ifeq ($(USE_SSL),1)
|
||||||
|
TEST_LIBS += $(SSL_STLIBNAME) -lssl -lcrypto -lpthread
|
||||||
|
endif
|
||||||
|
hiredis-test: test.o $(TEST_LIBS)
|
||||||
|
|
||||||
hiredis-%: %.o $(STLIBNAME)
|
hiredis-%: %.o $(STLIBNAME)
|
||||||
$(CC) $(REAL_CFLAGS) -o $@ $< $(STLIBNAME) $(REAL_LDFLAGS)
|
$(CC) $(REAL_CFLAGS) -o $@ $< $(TEST_LIBS) $(REAL_LDFLAGS)
|
||||||
|
|
||||||
test: hiredis-test
|
test: hiredis-test
|
||||||
./hiredis-test
|
./hiredis-test
|
||||||
|
|
||||||
check: hiredis-test
|
check: hiredis-test
|
||||||
@echo "$$REDIS_TEST_CONFIG" | $(REDIS_SERVER) -
|
TEST_SSL=$(USE_SSL) ./test.sh
|
||||||
$(PRE) ./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \
|
|
||||||
( kill `cat /tmp/hiredis-test-redis.pid` && false )
|
|
||||||
kill `cat /tmp/hiredis-test-redis.pid`
|
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
|
$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
|
||||||
|
@ -708,6 +708,11 @@ int redisReconnect(redisContext *c) {
|
|||||||
c->err = 0;
|
c->err = 0;
|
||||||
memset(c->errstr, '\0', strlen(c->errstr));
|
memset(c->errstr, '\0', strlen(c->errstr));
|
||||||
|
|
||||||
|
if (c->privdata && c->funcs->free_privdata) {
|
||||||
|
c->funcs->free_privdata(c->privdata);
|
||||||
|
c->privdata = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
redisNetClose(c);
|
redisNetClose(c);
|
||||||
|
|
||||||
sdsfree(c->obuf);
|
sdsfree(c->obuf);
|
||||||
|
2
ssl.c
2
ssl.c
@ -337,7 +337,7 @@ static int redisSSLRead(redisContext *c, char *buf, size_t bufcap) {
|
|||||||
} else {
|
} else {
|
||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
msg = "Timed out";
|
msg = "Resource temporarily unavailable";
|
||||||
}
|
}
|
||||||
__redisSetError(c, REDIS_ERR_IO, msg);
|
__redisSetError(c, REDIS_ERR_IO, msg);
|
||||||
return -1;
|
return -1;
|
||||||
|
80
test.c
80
test.c
@ -13,12 +13,16 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include "hiredis.h"
|
#include "hiredis.h"
|
||||||
|
#ifdef HIREDIS_TEST_SSL
|
||||||
|
#include "hiredis_ssl.h"
|
||||||
|
#endif
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
enum connection_type {
|
enum connection_type {
|
||||||
CONN_TCP,
|
CONN_TCP,
|
||||||
CONN_UNIX,
|
CONN_UNIX,
|
||||||
CONN_FD
|
CONN_FD,
|
||||||
|
CONN_SSL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config {
|
struct config {
|
||||||
@ -33,6 +37,14 @@ struct config {
|
|||||||
struct {
|
struct {
|
||||||
const char *path;
|
const char *path;
|
||||||
} unix_sock;
|
} unix_sock;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const char *host;
|
||||||
|
int port;
|
||||||
|
const char *ca_cert;
|
||||||
|
const char *cert;
|
||||||
|
const char *key;
|
||||||
|
} ssl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The following lines make up our testing "framework" :) */
|
/* The following lines make up our testing "framework" :) */
|
||||||
@ -93,11 +105,27 @@ static int disconnect(redisContext *c, int keep_fd) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_ssl_handshake(redisContext *c, struct config config) {
|
||||||
|
#ifdef HIREDIS_TEST_SSL
|
||||||
|
redisSecureConnection(c, config.ssl.ca_cert, config.ssl.cert, config.ssl.key, NULL);
|
||||||
|
if (c->err) {
|
||||||
|
printf("SSL error: %s\n", c->errstr);
|
||||||
|
redisFree(c);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void) c;
|
||||||
|
(void) config;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static redisContext *do_connect(struct config config) {
|
static redisContext *do_connect(struct config config) {
|
||||||
redisContext *c = NULL;
|
redisContext *c = NULL;
|
||||||
|
|
||||||
if (config.type == CONN_TCP) {
|
if (config.type == CONN_TCP) {
|
||||||
c = redisConnect(config.tcp.host, config.tcp.port);
|
c = redisConnect(config.tcp.host, config.tcp.port);
|
||||||
|
} else if (config.type == CONN_SSL) {
|
||||||
|
c = redisConnect(config.ssl.host, config.ssl.port);
|
||||||
} else if (config.type == CONN_UNIX) {
|
} else if (config.type == CONN_UNIX) {
|
||||||
c = redisConnectUnix(config.unix_sock.path);
|
c = redisConnectUnix(config.unix_sock.path);
|
||||||
} else if (config.type == CONN_FD) {
|
} else if (config.type == CONN_FD) {
|
||||||
@ -121,9 +149,21 @@ static redisContext *do_connect(struct config config) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.type == CONN_SSL) {
|
||||||
|
do_ssl_handshake(c, config);
|
||||||
|
}
|
||||||
|
|
||||||
return select_database(c);
|
return select_database(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_reconnect(redisContext *c, struct config config) {
|
||||||
|
redisReconnect(c);
|
||||||
|
|
||||||
|
if (config.type == CONN_SSL) {
|
||||||
|
do_ssl_handshake(c, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void test_format_commands(void) {
|
static void test_format_commands(void) {
|
||||||
char *cmd;
|
char *cmd;
|
||||||
int len;
|
int len;
|
||||||
@ -575,7 +615,8 @@ static void test_blocking_connection_timeouts(struct config config) {
|
|||||||
|
|
||||||
c = do_connect(config);
|
c = do_connect(config);
|
||||||
test("Does not return a reply when the command times out: ");
|
test("Does not return a reply when the command times out: ");
|
||||||
s = write(c->fd, cmd, strlen(cmd));
|
redisAppendFormattedCommand(c, cmd, strlen(cmd));
|
||||||
|
s = c->funcs->write(c);
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = 10000;
|
tv.tv_usec = 10000;
|
||||||
redisSetTimeout(c, tv);
|
redisSetTimeout(c, tv);
|
||||||
@ -584,7 +625,7 @@ static void test_blocking_connection_timeouts(struct config config) {
|
|||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
|
|
||||||
test("Reconnect properly reconnects after a timeout: ");
|
test("Reconnect properly reconnects after a timeout: ");
|
||||||
redisReconnect(c);
|
do_reconnect(c, config);
|
||||||
reply = redisCommand(c, "PING");
|
reply = redisCommand(c, "PING");
|
||||||
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
@ -592,7 +633,7 @@ static void test_blocking_connection_timeouts(struct config config) {
|
|||||||
test("Reconnect properly uses owned parameters: ");
|
test("Reconnect properly uses owned parameters: ");
|
||||||
config.tcp.host = "foo";
|
config.tcp.host = "foo";
|
||||||
config.unix_sock.path = "foo";
|
config.unix_sock.path = "foo";
|
||||||
redisReconnect(c);
|
do_reconnect(c, config);
|
||||||
reply = redisCommand(c, "PING");
|
reply = redisCommand(c, "PING");
|
||||||
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
@ -895,6 +936,23 @@ int main(int argc, char **argv) {
|
|||||||
throughput = 0;
|
throughput = 0;
|
||||||
} else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
|
} else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
|
||||||
test_inherit_fd = 0;
|
test_inherit_fd = 0;
|
||||||
|
#ifdef HIREDIS_TEST_SSL
|
||||||
|
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-port")) {
|
||||||
|
argv++; argc--;
|
||||||
|
cfg.ssl.port = atoi(argv[0]);
|
||||||
|
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-host")) {
|
||||||
|
argv++; argc--;
|
||||||
|
cfg.ssl.host = argv[0];
|
||||||
|
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-ca-cert")) {
|
||||||
|
argv++; argc--;
|
||||||
|
cfg.ssl.ca_cert = argv[0];
|
||||||
|
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-cert")) {
|
||||||
|
argv++; argc--;
|
||||||
|
cfg.ssl.cert = argv[0];
|
||||||
|
} else if (argc >= 2 && !strcmp(argv[0],"--ssl-key")) {
|
||||||
|
argv++; argc--;
|
||||||
|
cfg.ssl.key = argv[0];
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -923,6 +981,20 @@ int main(int argc, char **argv) {
|
|||||||
test_blocking_io_errors(cfg);
|
test_blocking_io_errors(cfg);
|
||||||
if (throughput) test_throughput(cfg);
|
if (throughput) test_throughput(cfg);
|
||||||
|
|
||||||
|
#ifdef HIREDIS_TEST_SSL
|
||||||
|
if (cfg.ssl.port && cfg.ssl.host) {
|
||||||
|
printf("\nTesting against SSL connection (%s:%d):\n", cfg.ssl.host, cfg.ssl.port);
|
||||||
|
cfg.type = CONN_SSL;
|
||||||
|
|
||||||
|
test_blocking_connection(cfg);
|
||||||
|
test_blocking_connection_timeouts(cfg);
|
||||||
|
test_blocking_io_errors(cfg);
|
||||||
|
test_invalid_timeout_errors(cfg);
|
||||||
|
test_append_formatted_commands(cfg);
|
||||||
|
if (throughput) test_throughput(cfg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (test_inherit_fd) {
|
if (test_inherit_fd) {
|
||||||
printf("\nTesting against inherited fd (%s):\n", cfg.unix_sock.path);
|
printf("\nTesting against inherited fd (%s):\n", cfg.unix_sock.path);
|
||||||
cfg.type = CONN_FD;
|
cfg.type = CONN_FD;
|
||||||
|
49
test.sh
49
test.sh
@ -2,11 +2,44 @@
|
|||||||
|
|
||||||
REDIS_SERVER=${REDIS_SERVER:-redis-server}
|
REDIS_SERVER=${REDIS_SERVER:-redis-server}
|
||||||
REDIS_PORT=${REDIS_PORT:-56379}
|
REDIS_PORT=${REDIS_PORT:-56379}
|
||||||
|
REDIS_SSL_PORT=${REDIS_SSL_PORT:-56443}
|
||||||
|
TEST_SSL=${TEST_SSL:-0}
|
||||||
|
SSL_TEST_ARGS=
|
||||||
|
|
||||||
tmpdir=$(mktemp -d)
|
tmpdir=$(mktemp -d)
|
||||||
PID_FILE=${tmpdir}/hiredis-test-redis.pid
|
PID_FILE=${tmpdir}/hiredis-test-redis.pid
|
||||||
SOCK_FILE=${tmpdir}/hiredis-test-redis.sock
|
SOCK_FILE=${tmpdir}/hiredis-test-redis.sock
|
||||||
|
|
||||||
|
if [ "$TEST_SSL" = "1" ]; then
|
||||||
|
SSL_CA_CERT=${tmpdir}/ca.crt
|
||||||
|
SSL_CA_KEY=${tmpdir}/ca.key
|
||||||
|
SSL_CERT=${tmpdir}/redis.crt
|
||||||
|
SSL_KEY=${tmpdir}/redis.key
|
||||||
|
|
||||||
|
openssl genrsa -out ${tmpdir}/ca.key 4096
|
||||||
|
openssl req \
|
||||||
|
-x509 -new -nodes -sha256 \
|
||||||
|
-key ${SSL_CA_KEY} \
|
||||||
|
-days 3650 \
|
||||||
|
-subj '/CN=Hiredis Test CA' \
|
||||||
|
-out ${SSL_CA_CERT}
|
||||||
|
openssl genrsa -out ${SSL_KEY} 2048
|
||||||
|
openssl req \
|
||||||
|
-new -sha256 \
|
||||||
|
-key ${SSL_KEY} \
|
||||||
|
-subj '/CN=Hiredis Test Cert' | \
|
||||||
|
openssl x509 \
|
||||||
|
-req -sha256 \
|
||||||
|
-CA ${SSL_CA_CERT} \
|
||||||
|
-CAkey ${SSL_CA_KEY} \
|
||||||
|
-CAserial ${tmpdir}/ca.txt \
|
||||||
|
-CAcreateserial \
|
||||||
|
-days 365 \
|
||||||
|
-out ${SSL_CERT}
|
||||||
|
|
||||||
|
SSL_TEST_ARGS="--ssl-host 127.0.0.1 --ssl-port ${REDIS_SSL_PORT} --ssl-ca-cert ${SSL_CA_CERT} --ssl-cert ${SSL_CERT} --ssl-key ${SSL_KEY}"
|
||||||
|
fi
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
set +e
|
set +e
|
||||||
kill $(cat ${PID_FILE})
|
kill $(cat ${PID_FILE})
|
||||||
@ -14,7 +47,7 @@ cleanup() {
|
|||||||
}
|
}
|
||||||
trap cleanup INT TERM EXIT
|
trap cleanup INT TERM EXIT
|
||||||
|
|
||||||
${REDIS_SERVER} - <<EOF
|
cat > ${tmpdir}/redis.conf <<EOF
|
||||||
daemonize yes
|
daemonize yes
|
||||||
pidfile ${PID_FILE}
|
pidfile ${PID_FILE}
|
||||||
port ${REDIS_PORT}
|
port ${REDIS_PORT}
|
||||||
@ -22,4 +55,16 @@ bind 127.0.0.1
|
|||||||
unixsocket ${SOCK_FILE}
|
unixsocket ${SOCK_FILE}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
${TEST_PREFIX:-} ./hiredis-test -h 127.0.0.1 -p ${REDIS_PORT} -s ${SOCK_FILE}
|
if [ "$TEST_SSL" = "1" ]; then
|
||||||
|
cat >> ${tmpdir}/redis.conf <<EOF
|
||||||
|
tls-port ${REDIS_SSL_PORT}
|
||||||
|
tls-ca-cert-file ${SSL_CA_CERT}
|
||||||
|
tls-cert-file ${SSL_CERT}
|
||||||
|
tls-key-file ${SSL_KEY}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat ${tmpdir}/redis.conf
|
||||||
|
${REDIS_SERVER} ${tmpdir}/redis.conf
|
||||||
|
|
||||||
|
${TEST_PREFIX:-} ./hiredis-test -h 127.0.0.1 -p ${REDIS_PORT} -s ${SOCK_FILE} ${SSL_TEST_ARGS}
|
||||||
|
Loading…
Reference in New Issue
Block a user