Added URI support to redis-benchmark (cli and benchmark share the same uri-parsing methods) (#9314)

- Add `-u <uri>` command line option to support `redis://` URI scheme.
- included server connection information object (`struct cliConnInfo`),
  used to describe an ip:port pair, db num user input, and user:pass to
  avoid a large number of function arguments.
- Using sds on connection info strings for redis-benchmark/redis-cli

Co-authored-by: yoav-steinberg <yoav@monfort.co.il>
This commit is contained in:
filipe oliveira 2021-09-14 17:45:06 +01:00 committed by GitHub
parent ea36d4de17
commit b5a879e1c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 280 additions and 247 deletions

View File

@ -38,12 +38,15 @@
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */ #include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
#include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */ #include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <ctype.h>
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <hiredis_ssl.h> #include <hiredis_ssl.h>
#endif #endif
#define UNUSED(V) ((void) V)
/* Wrapper around redisSecureConnection to avoid hiredis_ssl dependencies if /* Wrapper around redisSecureConnection to avoid hiredis_ssl dependencies if
* not building with TLS support. * not building with TLS support.
@ -259,3 +262,111 @@ sds unquoteCString(char *str) {
return res; return res;
} }
/* URL-style percent decoding. */
#define isHexChar(c) (isdigit(c) || ((c) >= 'a' && (c) <= 'f'))
#define decodeHexChar(c) (isdigit(c) ? (c) - '0' : (c) - 'a' + 10)
#define decodeHex(h, l) ((decodeHexChar(h) << 4) + decodeHexChar(l))
static sds percentDecode(const char *pe, size_t len) {
const char *end = pe + len;
sds ret = sdsempty();
const char *curr = pe;
while (curr < end) {
if (*curr == '%') {
if ((end - curr) < 2) {
fprintf(stderr, "Incomplete URI encoding\n");
exit(1);
}
char h = tolower(*(++curr));
char l = tolower(*(++curr));
if (!isHexChar(h) || !isHexChar(l)) {
fprintf(stderr, "Illegal character in URI encoding\n");
exit(1);
}
char c = decodeHex(h, l);
ret = sdscatlen(ret, &c, 1);
curr++;
} else {
ret = sdscatlen(ret, curr++, 1);
}
}
return ret;
}
/* Parse a URI and extract the server connection information.
* URI scheme is based on the the provisional specification[1] excluding support
* for query parameters. Valid URIs are:
* scheme: "redis://"
* authority: [[<username> ":"] <password> "@"] [<hostname> [":" <port>]]
* path: ["/" [<db>]]
*
* [1]: https://www.iana.org/assignments/uri-schemes/prov/redis */
void parseRedisUri(const char *uri, const char* tool_name, cliConnInfo *connInfo, int *tls_flag) {
#ifdef USE_OPENSSL
UNUSED(tool_name);
#else
UNUSED(tls_flag);
#endif
const char *scheme = "redis://";
const char *tlsscheme = "rediss://";
const char *curr = uri;
const char *end = uri + strlen(uri);
const char *userinfo, *username, *port, *host, *path;
/* URI must start with a valid scheme. */
if (!strncasecmp(tlsscheme, curr, strlen(tlsscheme))) {
#ifdef USE_OPENSSL
*tls_flag = 1;
curr += strlen(tlsscheme);
#else
fprintf(stderr,"rediss:// is only supported when %s is compiled with OpenSSL\n", tool_name);
exit(1);
#endif
} else if (!strncasecmp(scheme, curr, strlen(scheme))) {
curr += strlen(scheme);
} else {
fprintf(stderr,"Invalid URI scheme\n");
exit(1);
}
if (curr == end) return;
/* Extract user info. */
if ((userinfo = strchr(curr,'@'))) {
if ((username = strchr(curr, ':')) && username < userinfo) {
connInfo->user = percentDecode(curr, username - curr);
curr = username + 1;
}
connInfo->auth = percentDecode(curr, userinfo - curr);
curr = userinfo + 1;
}
if (curr == end) return;
/* Extract host and port. */
path = strchr(curr, '/');
if (*curr != '/') {
host = path ? path - 1 : end;
if ((port = strchr(curr, ':'))) {
connInfo->hostport = atoi(port + 1);
host = port - 1;
}
connInfo->hostip = sdsnewlen(curr, host - curr + 1);
}
curr = path ? path + 1 : end;
if (curr == end) return;
/* Extract database number. */
connInfo->input_dbnum = atoi(curr);
}
void freeCliConnInfo(cliConnInfo connInfo){
if (connInfo.hostip) sdsfree(connInfo.hostip);
if (connInfo.auth) sdsfree(connInfo.auth);
if (connInfo.user) sdsfree(connInfo.user);
}

View File

@ -23,6 +23,16 @@ typedef struct cliSSLconfig {
char* ciphersuites; char* ciphersuites;
} cliSSLconfig; } cliSSLconfig;
/* server connection information object, used to describe an ip:port pair, db num user input, and user:pass. */
typedef struct cliConnInfo {
char *hostip;
int hostport;
int input_dbnum;
char *auth;
char *user;
} cliConnInfo;
int cliSecureConnection(redisContext *c, cliSSLconfig config, const char **err); int cliSecureConnection(redisContext *c, cliSSLconfig config, const char **err);
ssize_t cliWriteConn(redisContext *c, const char *buf, size_t buf_len); ssize_t cliWriteConn(redisContext *c, const char *buf, size_t buf_len);
@ -35,4 +45,7 @@ sds *getSdsArrayFromArgv(int argc,char **argv, int quoted);
sds unquoteCString(char *str); sds unquoteCString(char *str);
void parseRedisUri(const char *uri, const char* tool_name, cliConnInfo *connInfo, int *tls_flag);
void freeCliConnInfo(cliConnInfo connInfo);
#endif /* __CLICOMMON_H */ #endif /* __CLICOMMON_H */

View File

@ -81,8 +81,7 @@ struct redisConfig;
static struct config { static struct config {
aeEventLoop *el; aeEventLoop *el;
const char *hostip; cliConnInfo conn_info;
int hostport;
const char *hostsocket; const char *hostsocket;
int tls; int tls;
struct cliSSLconfig sslconfig; struct cliSSLconfig sslconfig;
@ -108,12 +107,9 @@ static struct config {
int csv; int csv;
int loop; int loop;
int idlemode; int idlemode;
int dbnum; sds input_dbnumstr;
sds dbnumstr;
char *tests; char *tests;
int stdinarg; /* get last arg from stdin. (-x option) */ int stdinarg; /* get last arg from stdin. (-x option) */
char *auth;
const char *user;
int precision; int precision;
int num_threads; int num_threads;
struct benchmarkThread **threads; struct benchmarkThread **threads;
@ -287,12 +283,12 @@ static redisContext *getRedisContext(const char *ip, int port,
goto cleanup; goto cleanup;
} }
} }
if (config.auth == NULL) if (config.conn_info.auth == NULL)
return ctx; return ctx;
if (config.user == NULL) if (config.conn_info.user == NULL)
reply = redisCommand(ctx,"AUTH %s", config.auth); reply = redisCommand(ctx,"AUTH %s", config.conn_info.auth);
else else
reply = redisCommand(ctx,"AUTH %s %s", config.user, config.auth); reply = redisCommand(ctx,"AUTH %s %s", config.conn_info.user, config.conn_info.auth);
if (reply != NULL) { if (reply != NULL) {
if (reply->type == REDIS_REPLY_ERROR) { if (reply->type == REDIS_REPLY_ERROR) {
if (hostsocket == NULL) if (hostsocket == NULL)
@ -677,8 +673,8 @@ static client createClient(char *cmd, size_t len, client from, int thread_id) {
c->cluster_node = NULL; c->cluster_node = NULL;
if (config.hostsocket == NULL || is_cluster_client) { if (config.hostsocket == NULL || is_cluster_client) {
if (!is_cluster_client) { if (!is_cluster_client) {
ip = config.hostip; ip = config.conn_info.hostip;
port = config.hostport; port = config.conn_info.hostport;
} else { } else {
int node_idx = 0; int node_idx = 0;
if (config.num_threads < config.cluster_node_count) if (config.num_threads < config.cluster_node_count)
@ -722,14 +718,14 @@ static client createClient(char *cmd, size_t len, client from, int thread_id) {
* These commands are discarded after the first response, so if the client is * These commands are discarded after the first response, so if the client is
* reused the commands will not be used again. */ * reused the commands will not be used again. */
c->prefix_pending = 0; c->prefix_pending = 0;
if (config.auth) { if (config.conn_info.auth) {
char *buf = NULL; char *buf = NULL;
int len; int len;
if (config.user == NULL) if (config.conn_info.user == NULL)
len = redisFormatCommand(&buf, "AUTH %s", config.auth); len = redisFormatCommand(&buf, "AUTH %s", config.conn_info.auth);
else else
len = redisFormatCommand(&buf, "AUTH %s %s", len = redisFormatCommand(&buf, "AUTH %s %s",
config.user, config.auth); config.conn_info.user, config.conn_info.auth);
c->obuf = sdscatlen(c->obuf, buf, len); c->obuf = sdscatlen(c->obuf, buf, len);
free(buf); free(buf);
c->prefix_pending++; c->prefix_pending++;
@ -747,9 +743,9 @@ static client createClient(char *cmd, size_t len, client from, int thread_id) {
* buffer with the SELECT command, that will be discarded the first * buffer with the SELECT command, that will be discarded the first
* time the replies are received, so if the client is reused the * time the replies are received, so if the client is reused the
* SELECT command will not be used again. */ * SELECT command will not be used again. */
if (config.dbnum != 0 && !is_cluster_client) { if (config.conn_info.input_dbnum != 0 && !is_cluster_client) {
c->obuf = sdscatprintf(c->obuf,"*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n", c->obuf = sdscatprintf(c->obuf,"*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n",
(int)sdslen(config.dbnumstr),config.dbnumstr); (int)sdslen(config.input_dbnumstr),config.input_dbnumstr);
c->prefix_pending++; c->prefix_pending++;
} }
c->prefixlen = sdslen(c->obuf); c->prefixlen = sdslen(c->obuf);
@ -1082,9 +1078,9 @@ static void freeClusterNode(clusterNode *node) {
zfree(node->importing); zfree(node->importing);
} }
/* If the node is not the reference node, that uses the address from /* If the node is not the reference node, that uses the address from
* config.hostip and config.hostport, then the node ip has been * config.conn_info.hostip and config.conn_info.hostport, then the node ip has been
* allocated by fetchClusterConfiguration, so it must be freed. */ * allocated by fetchClusterConfiguration, so it must be freed. */
if (node->ip && strcmp(node->ip, config.hostip) != 0) sdsfree(node->ip); if (node->ip && strcmp(node->ip, config.conn_info.hostip) != 0) sdsfree(node->ip);
if (node->redis_config != NULL) freeRedisConfig(node->redis_config); if (node->redis_config != NULL) freeRedisConfig(node->redis_config);
zfree(node->slots); zfree(node->slots);
zfree(node); zfree(node);
@ -1113,12 +1109,12 @@ static int fetchClusterConfiguration() {
int success = 1; int success = 1;
redisContext *ctx = NULL; redisContext *ctx = NULL;
redisReply *reply = NULL; redisReply *reply = NULL;
ctx = getRedisContext(config.hostip, config.hostport, config.hostsocket); ctx = getRedisContext(config.conn_info.hostip, config.conn_info.hostport, config.hostsocket);
if (ctx == NULL) { if (ctx == NULL) {
exit(1); exit(1);
} }
clusterNode *firstNode = createClusterNode((char *) config.hostip, clusterNode *firstNode = createClusterNode((char *) config.conn_info.hostip,
config.hostport); config.conn_info.hostport);
if (!firstNode) {success = 0; goto cleanup;} if (!firstNode) {success = 0; goto cleanup;}
reply = redisCommand(ctx, "CLUSTER NODES"); reply = redisCommand(ctx, "CLUSTER NODES");
success = (reply != NULL); success = (reply != NULL);
@ -1127,7 +1123,7 @@ static int fetchClusterConfiguration() {
if (!success) { if (!success) {
if (config.hostsocket == NULL) { if (config.hostsocket == NULL) {
fprintf(stderr, "Cluster node %s:%d replied with error:\n%s\n", fprintf(stderr, "Cluster node %s:%d replied with error:\n%s\n",
config.hostip, config.hostport, reply->str); config.conn_info.hostip, config.conn_info.hostport, reply->str);
} else { } else {
fprintf(stderr, "Cluster node %s replied with error:\n%s\n", fprintf(stderr, "Cluster node %s replied with error:\n%s\n",
config.hostsocket, reply->str); config.hostsocket, reply->str);
@ -1425,10 +1421,10 @@ int parseOptions(int argc, char **argv) {
config.keepalive = atoi(argv[++i]); config.keepalive = atoi(argv[++i]);
} else if (!strcmp(argv[i],"-h")) { } else if (!strcmp(argv[i],"-h")) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.hostip = strdup(argv[++i]); config.conn_info.hostip = sdsnew(argv[++i]);
} else if (!strcmp(argv[i],"-p")) { } else if (!strcmp(argv[i],"-p")) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.hostport = atoi(argv[++i]); config.conn_info.hostport = atoi(argv[++i]);
} else if (!strcmp(argv[i],"-s")) { } else if (!strcmp(argv[i],"-s")) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.hostsocket = strdup(argv[++i]); config.hostsocket = strdup(argv[++i]);
@ -1436,10 +1432,13 @@ int parseOptions(int argc, char **argv) {
config.stdinarg = 1; config.stdinarg = 1;
} else if (!strcmp(argv[i],"-a") ) { } else if (!strcmp(argv[i],"-a") ) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.auth = strdup(argv[++i]); config.conn_info.auth = sdsnew(argv[++i]);
} else if (!strcmp(argv[i],"--user")) { } else if (!strcmp(argv[i],"--user")) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.user = argv[++i]; config.conn_info.user = sdsnew(argv[++i]);
} else if (!strcmp(argv[i],"-u") && !lastarg) {
parseRedisUri(argv[++i],"redis-benchmark",&config.conn_info,&config.tls);
config.input_dbnumstr = sdsfromlonglong(config.conn_info.input_dbnum);
} else if (!strcmp(argv[i],"-d")) { } else if (!strcmp(argv[i],"-d")) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.datasize = atoi(argv[++i]); config.datasize = atoi(argv[++i]);
@ -1485,8 +1484,8 @@ int parseOptions(int argc, char **argv) {
sdstolower(config.tests); sdstolower(config.tests);
} else if (!strcmp(argv[i],"--dbnum")) { } else if (!strcmp(argv[i],"--dbnum")) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.dbnum = atoi(argv[++i]); config.conn_info.input_dbnum = atoi(argv[++i]);
config.dbnumstr = sdsfromlonglong(config.dbnum); config.input_dbnumstr = sdsfromlonglong(config.conn_info.input_dbnum);
} else if (!strcmp(argv[i],"--precision")) { } else if (!strcmp(argv[i],"--precision")) {
if (lastarg) goto invalid; if (lastarg) goto invalid;
config.precision = atoi(argv[++i]); config.precision = atoi(argv[++i]);
@ -1561,6 +1560,7 @@ usage:
" -s <socket> Server socket (overrides host and port)\n" " -s <socket> Server socket (overrides host and port)\n"
" -a <password> Password for Redis Auth\n" " -a <password> Password for Redis Auth\n"
" --user <username> Used to send ACL style 'AUTH username pass'. Needs -a.\n" " --user <username> Used to send ACL style 'AUTH username pass'. Needs -a.\n"
" -u <uri> Server URI.\n"
" -c <clients> Number of parallel connections (default 50)\n" " -c <clients> Number of parallel connections (default 50)\n"
" -n <requests> Total number of requests (default 100000)\n" " -n <requests> Total number of requests (default 100000)\n"
" -d <size> Data size of SET/GET value in bytes (default 3)\n" " -d <size> Data size of SET/GET value in bytes (default 3)\n"
@ -1720,13 +1720,13 @@ int main(int argc, char **argv) {
config.loop = 0; config.loop = 0;
config.idlemode = 0; config.idlemode = 0;
config.clients = listCreate(); config.clients = listCreate();
config.hostip = "127.0.0.1"; config.conn_info.hostip = "127.0.0.1";
config.hostport = 6379; config.conn_info.hostport = 6379;
config.hostsocket = NULL; config.hostsocket = NULL;
config.tests = NULL; config.tests = NULL;
config.dbnum = 0; config.conn_info.input_dbnum = 0;
config.stdinarg = 0; config.stdinarg = 0;
config.auth = NULL; config.conn_info.auth = NULL;
config.precision = DEFAULT_LATENCY_PRECISION; config.precision = DEFAULT_LATENCY_PRECISION;
config.num_threads = 0; config.num_threads = 0;
config.threads = NULL; config.threads = NULL;
@ -1759,7 +1759,7 @@ int main(int argc, char **argv) {
if (!fetchClusterConfiguration() || !config.cluster_nodes) { if (!fetchClusterConfiguration() || !config.cluster_nodes) {
if (!config.hostsocket) { if (!config.hostsocket) {
fprintf(stderr, "Failed to fetch cluster configuration from " fprintf(stderr, "Failed to fetch cluster configuration from "
"%s:%d\n", config.hostip, config.hostport); "%s:%d\n", config.conn_info.hostip, config.conn_info.hostport);
} else { } else {
fprintf(stderr, "Failed to fetch cluster configuration from " fprintf(stderr, "Failed to fetch cluster configuration from "
"%s\n", config.hostsocket); "%s\n", config.hostsocket);
@ -1795,7 +1795,7 @@ int main(int argc, char **argv) {
config.num_threads = config.cluster_node_count; config.num_threads = config.cluster_node_count;
} else { } else {
config.redis_config = config.redis_config =
getRedisConfig(config.hostip, config.hostport, config.hostsocket); getRedisConfig(config.conn_info.hostip, config.conn_info.hostport, config.hostsocket);
if (config.redis_config == NULL) { if (config.redis_config == NULL) {
fprintf(stderr, "WARNING: Could not fetch server CONFIG\n"); fprintf(stderr, "WARNING: Could not fetch server CONFIG\n");
} }
@ -2007,6 +2007,7 @@ int main(int argc, char **argv) {
} while(config.loop); } while(config.loop);
zfree(data); zfree(data);
freeCliConnInfo(config.conn_info);
if (config.redis_config != NULL) freeRedisConfig(config.redis_config); if (config.redis_config != NULL) freeRedisConfig(config.redis_config);
return 0; return 0;

View File

@ -200,15 +200,13 @@ static void createClusterManagerCommand(char *cmdname, int argc, char **argv);
static redisContext *context; static redisContext *context;
static struct config { static struct config {
char *hostip; cliConnInfo conn_info;
int hostport;
char *hostsocket; char *hostsocket;
int tls; int tls;
cliSSLconfig sslconfig; cliSSLconfig sslconfig;
long repeat; long repeat;
long interval; long interval;
int dbnum; /* db num currently selected */ int dbnum; /* db num currently selected */
int input_dbnum; /* db num user input */
int interactive; int interactive;
int shutdown; int shutdown;
int monitor_mode; int monitor_mode;
@ -237,9 +235,7 @@ static struct config {
unsigned memkeys_samples; unsigned memkeys_samples;
int hotkeys; int hotkeys;
int stdinarg; /* get last arg from stdin. (-x option) */ int stdinarg; /* get last arg from stdin. (-x option) */
char *auth;
int askpass; int askpass;
char *user;
int quoted_input; /* Force input args to be treated as quoted strings */ int quoted_input; /* Force input args to be treated as quoted strings */
int output; /* output mode, see OUTPUT_* defines */ int output; /* output mode, see OUTPUT_* defines */
int push_output; /* Should we display spontaneous PUSH replies */ int push_output; /* Should we display spontaneous PUSH replies */
@ -306,7 +302,7 @@ static void cliRefreshPrompt(void) {
prompt = sdscatfmt(prompt,"redis %s",config.hostsocket); prompt = sdscatfmt(prompt,"redis %s",config.hostsocket);
} else { } else {
char addr[256]; char addr[256];
anetFormatAddr(addr, sizeof(addr), config.hostip, config.hostport); anetFormatAddr(addr, sizeof(addr), config.conn_info.hostip, config.conn_info.hostport);
prompt = sdscatlen(prompt,addr,strlen(addr)); prompt = sdscatlen(prompt,addr,strlen(addr));
} }
@ -355,102 +351,6 @@ static sds getDotfilePath(char *envoverride, char *dotfilename) {
return dotPath; return dotPath;
} }
/* URL-style percent decoding. */
#define isHexChar(c) (isdigit(c) || (c >= 'a' && c <= 'f'))
#define decodeHexChar(c) (isdigit(c) ? c - '0' : c - 'a' + 10)
#define decodeHex(h, l) ((decodeHexChar(h) << 4) + decodeHexChar(l))
static sds percentDecode(const char *pe, size_t len) {
const char *end = pe + len;
sds ret = sdsempty();
const char *curr = pe;
while (curr < end) {
if (*curr == '%') {
if ((end - curr) < 2) {
fprintf(stderr, "Incomplete URI encoding\n");
exit(1);
}
char h = tolower(*(++curr));
char l = tolower(*(++curr));
if (!isHexChar(h) || !isHexChar(l)) {
fprintf(stderr, "Illegal character in URI encoding\n");
exit(1);
}
char c = decodeHex(h, l);
ret = sdscatlen(ret, &c, 1);
curr++;
} else {
ret = sdscatlen(ret, curr++, 1);
}
}
return ret;
}
/* Parse a URI and extract the server connection information.
* URI scheme is based on the the provisional specification[1] excluding support
* for query parameters. Valid URIs are:
* scheme: "redis://"
* authority: [[<username> ":"] <password> "@"] [<hostname> [":" <port>]]
* path: ["/" [<db>]]
*
* [1]: https://www.iana.org/assignments/uri-schemes/prov/redis */
static void parseRedisUri(const char *uri) {
const char *scheme = "redis://";
const char *tlsscheme = "rediss://";
const char *curr = uri;
const char *end = uri + strlen(uri);
const char *userinfo, *username, *port, *host, *path;
/* URI must start with a valid scheme. */
if (!strncasecmp(tlsscheme, curr, strlen(tlsscheme))) {
#ifdef USE_OPENSSL
config.tls = 1;
curr += strlen(tlsscheme);
#else
fprintf(stderr,"rediss:// is only supported when redis-cli is compiled with OpenSSL\n");
exit(1);
#endif
} else if (!strncasecmp(scheme, curr, strlen(scheme))) {
curr += strlen(scheme);
} else {
fprintf(stderr,"Invalid URI scheme\n");
exit(1);
}
if (curr == end) return;
/* Extract user info. */
if ((userinfo = strchr(curr,'@'))) {
if ((username = strchr(curr, ':')) && username < userinfo) {
config.user = percentDecode(curr, username - curr);
curr = username + 1;
}
config.auth = percentDecode(curr, userinfo - curr);
curr = userinfo + 1;
}
if (curr == end) return;
/* Extract host and port. */
path = strchr(curr, '/');
if (*curr != '/') {
host = path ? path - 1 : end;
if ((port = strchr(curr, ':'))) {
config.hostport = atoi(port + 1);
host = port - 1;
}
config.hostip = sdsnewlen(curr, host - curr + 1);
}
curr = path ? path + 1 : end;
if (curr == end) return;
/* Extract database number. */
config.input_dbnum = atoi(curr);
}
static uint64_t dictSdsHash(const void *key) { static uint64_t dictSdsHash(const void *key) {
return dictGenHashFunction((unsigned char*)key, sdslen((char*)key)); return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));
} }
@ -802,9 +702,9 @@ static int cliAuth(redisContext *ctx, char *user, char *auth) {
/* Send SELECT input_dbnum to the server */ /* Send SELECT input_dbnum to the server */
static int cliSelect(void) { static int cliSelect(void) {
redisReply *reply; redisReply *reply;
if (config.input_dbnum == config.dbnum) return REDIS_OK; if (config.conn_info.input_dbnum == config.dbnum) return REDIS_OK;
reply = redisCommand(context,"SELECT %d",config.input_dbnum); reply = redisCommand(context,"SELECT %d",config.conn_info.input_dbnum);
if (reply == NULL) { if (reply == NULL) {
fprintf(stderr, "\nI/O error\n"); fprintf(stderr, "\nI/O error\n");
return REDIS_ERR; return REDIS_ERR;
@ -813,9 +713,9 @@ static int cliSelect(void) {
int result = REDIS_OK; int result = REDIS_OK;
if (reply->type == REDIS_REPLY_ERROR) { if (reply->type == REDIS_REPLY_ERROR) {
result = REDIS_ERR; result = REDIS_ERR;
fprintf(stderr,"SELECT %d failed: %s\n",config.input_dbnum,reply->str); fprintf(stderr,"SELECT %d failed: %s\n",config.conn_info.input_dbnum,reply->str);
} else { } else {
config.dbnum = config.input_dbnum; config.dbnum = config.conn_info.input_dbnum;
cliRefreshPrompt(); cliRefreshPrompt();
} }
freeReplyObject(reply); freeReplyObject(reply);
@ -858,7 +758,7 @@ static int cliConnect(int flags) {
/* Do not use hostsocket when we got redirected in cluster mode */ /* Do not use hostsocket when we got redirected in cluster mode */
if (config.hostsocket == NULL || if (config.hostsocket == NULL ||
(config.cluster_mode && config.cluster_reissue_command)) { (config.cluster_mode && config.cluster_reissue_command)) {
context = redisConnect(config.hostip,config.hostport); context = redisConnect(config.conn_info.hostip,config.conn_info.hostport);
} else { } else {
context = redisConnectUnix(config.hostsocket); context = redisConnectUnix(config.hostsocket);
} }
@ -880,7 +780,7 @@ static int cliConnect(int flags) {
(config.cluster_mode && config.cluster_reissue_command)) (config.cluster_mode && config.cluster_reissue_command))
{ {
fprintf(stderr, "%s:%d: %s\n", fprintf(stderr, "%s:%d: %s\n",
config.hostip,config.hostport,context->errstr); config.conn_info.hostip,config.conn_info.hostport,context->errstr);
} else { } else {
fprintf(stderr,"%s: %s\n", fprintf(stderr,"%s: %s\n",
config.hostsocket,context->errstr); config.hostsocket,context->errstr);
@ -899,7 +799,7 @@ static int cliConnect(int flags) {
anetKeepAlive(NULL, context->fd, REDIS_CLI_KEEPALIVE_INTERVAL); anetKeepAlive(NULL, context->fd, REDIS_CLI_KEEPALIVE_INTERVAL);
/* Do AUTH, select the right DB, switch to RESP3 if needed. */ /* Do AUTH, select the right DB, switch to RESP3 if needed. */
if (cliAuth(context, config.user, config.auth) != REDIS_OK) if (cliAuth(context, config.conn_info.user, config.conn_info.auth) != REDIS_OK)
return REDIS_ERR; return REDIS_ERR;
if (cliSelect() != REDIS_OK) if (cliSelect() != REDIS_OK)
return REDIS_ERR; return REDIS_ERR;
@ -1337,12 +1237,12 @@ static int cliReadReply(int output_raw_strings) {
slot = atoi(s+1); slot = atoi(s+1);
s = strrchr(p+1,':'); /* MOVED 3999[P]127.0.0.1[S]6381 */ s = strrchr(p+1,':'); /* MOVED 3999[P]127.0.0.1[S]6381 */
*s = '\0'; *s = '\0';
sdsfree(config.hostip); sdsfree(config.conn_info.hostip);
config.hostip = sdsnew(p+1); config.conn_info.hostip = sdsnew(p+1);
config.hostport = atoi(s+1); config.conn_info.hostport = atoi(s+1);
if (config.interactive) if (config.interactive)
printf("-> Redirected to slot [%d] located at %s:%d\n", printf("-> Redirected to slot [%d] located at %s:%d\n",
slot, config.hostip, config.hostport); slot, config.conn_info.hostip, config.conn_info.hostport);
config.cluster_reissue_command = 1; config.cluster_reissue_command = 1;
if (!strncmp(reply->str,"ASK ",4)) { if (!strncmp(reply->str,"ASK ",4)) {
config.cluster_send_asking = 1; config.cluster_send_asking = 1;
@ -1486,7 +1386,7 @@ static int cliSendCommand(int argc, char **argv, long repeat) {
if (!strcasecmp(command,"select") && argc == 2 && if (!strcasecmp(command,"select") && argc == 2 &&
config.last_cmd_type != REDIS_REPLY_ERROR) config.last_cmd_type != REDIS_REPLY_ERROR)
{ {
config.input_dbnum = config.dbnum = atoi(argv[1]); config.conn_info.input_dbnum = config.dbnum = atoi(argv[1]);
cliRefreshPrompt(); cliRefreshPrompt();
} else if (!strcasecmp(command,"auth") && (argc == 2 || argc == 3)) { } else if (!strcasecmp(command,"auth") && (argc == 2 || argc == 3)) {
cliSelect(); cliSelect();
@ -1501,20 +1401,20 @@ static int cliSendCommand(int argc, char **argv, long repeat) {
if (config.last_cmd_type == REDIS_REPLY_ERROR || if (config.last_cmd_type == REDIS_REPLY_ERROR ||
config.last_cmd_type == REDIS_REPLY_NIL) config.last_cmd_type == REDIS_REPLY_NIL)
{ {
config.input_dbnum = config.dbnum = config.pre_multi_dbnum; config.conn_info.input_dbnum = config.dbnum = config.pre_multi_dbnum;
} }
cliRefreshPrompt(); cliRefreshPrompt();
} else if (!strcasecmp(command,"discard") && argc == 1 && } else if (!strcasecmp(command,"discard") && argc == 1 &&
config.last_cmd_type != REDIS_REPLY_ERROR) config.last_cmd_type != REDIS_REPLY_ERROR)
{ {
config.in_multi = 0; config.in_multi = 0;
config.input_dbnum = config.dbnum = config.pre_multi_dbnum; config.conn_info.input_dbnum = config.dbnum = config.pre_multi_dbnum;
cliRefreshPrompt(); cliRefreshPrompt();
} else if (!strcasecmp(command,"reset") && argc == 1 && } else if (!strcasecmp(command,"reset") && argc == 1 &&
config.last_cmd_type != REDIS_REPLY_ERROR) { config.last_cmd_type != REDIS_REPLY_ERROR) {
config.in_multi = 0; config.in_multi = 0;
config.dbnum = 0; config.dbnum = 0;
config.input_dbnum = 0; config.conn_info.input_dbnum = 0;
config.resp3 = 0; config.resp3 = 0;
cliRefreshPrompt(); cliRefreshPrompt();
} }
@ -1546,7 +1446,7 @@ static redisReply *reconnectingRedisCommand(redisContext *c, const char *fmt, ..
fflush(stdout); fflush(stdout);
redisFree(c); redisFree(c);
c = redisConnect(config.hostip,config.hostport); c = redisConnect(config.conn_info.hostip,config.conn_info.hostport);
if (!c->err && config.tls) { if (!c->err && config.tls) {
const char *err = NULL; const char *err = NULL;
if (cliSecureConnection(c, config.sslconfig, &err) == REDIS_ERR && err) { if (cliSecureConnection(c, config.sslconfig, &err) == REDIS_ERR && err) {
@ -1584,8 +1484,8 @@ static int parseOptions(int argc, char **argv) {
int lastarg = i==argc-1; int lastarg = i==argc-1;
if (!strcmp(argv[i],"-h") && !lastarg) { if (!strcmp(argv[i],"-h") && !lastarg) {
sdsfree(config.hostip); sdsfree(config.conn_info.hostip);
config.hostip = sdsnew(argv[++i]); config.conn_info.hostip = sdsnew(argv[++i]);
} else if (!strcmp(argv[i],"-h") && lastarg) { } else if (!strcmp(argv[i],"-h") && lastarg) {
usage(0); usage(0);
} else if (!strcmp(argv[i],"--help")) { } else if (!strcmp(argv[i],"--help")) {
@ -1593,7 +1493,7 @@ static int parseOptions(int argc, char **argv) {
} else if (!strcmp(argv[i],"-x")) { } else if (!strcmp(argv[i],"-x")) {
config.stdinarg = 1; config.stdinarg = 1;
} else if (!strcmp(argv[i],"-p") && !lastarg) { } else if (!strcmp(argv[i],"-p") && !lastarg) {
config.hostport = atoi(argv[++i]); config.conn_info.hostport = atoi(argv[++i]);
} else if (!strcmp(argv[i],"-s") && !lastarg) { } else if (!strcmp(argv[i],"-s") && !lastarg) {
config.hostsocket = argv[++i]; config.hostsocket = argv[++i];
} else if (!strcmp(argv[i],"-r") && !lastarg) { } else if (!strcmp(argv[i],"-r") && !lastarg) {
@ -1602,7 +1502,7 @@ static int parseOptions(int argc, char **argv) {
double seconds = atof(argv[++i]); double seconds = atof(argv[++i]);
config.interval = seconds*1000000; config.interval = seconds*1000000;
} else if (!strcmp(argv[i],"-n") && !lastarg) { } else if (!strcmp(argv[i],"-n") && !lastarg) {
config.input_dbnum = atoi(argv[++i]); config.conn_info.input_dbnum = atoi(argv[++i]);
} else if (!strcmp(argv[i], "--no-auth-warning")) { } else if (!strcmp(argv[i], "--no-auth-warning")) {
config.no_auth_warning = 1; config.no_auth_warning = 1;
} else if (!strcmp(argv[i], "--askpass")) { } else if (!strcmp(argv[i], "--askpass")) {
@ -1610,11 +1510,11 @@ static int parseOptions(int argc, char **argv) {
} else if ((!strcmp(argv[i],"-a") || !strcmp(argv[i],"--pass")) } else if ((!strcmp(argv[i],"-a") || !strcmp(argv[i],"--pass"))
&& !lastarg) && !lastarg)
{ {
config.auth = argv[++i]; config.conn_info.auth = sdsnew(argv[++i]);
} else if (!strcmp(argv[i],"--user") && !lastarg) { } else if (!strcmp(argv[i],"--user") && !lastarg) {
config.user = argv[++i]; config.conn_info.user = sdsnew(argv[++i]);
} else if (!strcmp(argv[i],"-u") && !lastarg) { } else if (!strcmp(argv[i],"-u") && !lastarg) {
parseRedisUri(argv[++i]); parseRedisUri(argv[++i],"redis-cli",&config.conn_info,&config.tls);
} else if (!strcmp(argv[i],"--raw")) { } else if (!strcmp(argv[i],"--raw")) {
config.output = OUTPUT_RAW; config.output = OUTPUT_RAW;
} else if (!strcmp(argv[i],"--no-raw")) { } else if (!strcmp(argv[i],"--no-raw")) {
@ -1852,7 +1752,7 @@ static int parseOptions(int argc, char **argv) {
exit(1); exit(1);
} }
if (!config.no_auth_warning && config.auth != NULL) { if (!config.no_auth_warning && config.conn_info.auth != NULL) {
fputs("Warning: Using a password with '-a' or '-u' option on the command" fputs("Warning: Using a password with '-a' or '-u' option on the command"
" line interface may not be safe.\n", stderr); " line interface may not be safe.\n", stderr);
} }
@ -1863,8 +1763,8 @@ static int parseOptions(int argc, char **argv) {
static void parseEnv() { static void parseEnv() {
/* Set auth from env, but do not overwrite CLI arguments if passed */ /* Set auth from env, but do not overwrite CLI arguments if passed */
char *auth = getenv(REDIS_CLI_AUTH_ENV); char *auth = getenv(REDIS_CLI_AUTH_ENV);
if (auth != NULL && config.auth == NULL) { if (auth != NULL && config.conn_info.auth == NULL) {
config.auth = auth; config.conn_info.auth = auth;
} }
char *cluster_yes = getenv(REDIS_CLI_CLUSTER_YES_ENV); char *cluster_yes = getenv(REDIS_CLI_CLUSTER_YES_ENV);
@ -2261,9 +2161,9 @@ static void repl(void) {
printf("Use 'restart' only in Lua debugging mode."); printf("Use 'restart' only in Lua debugging mode.");
} }
} else if (argc == 3 && !strcasecmp(argv[0],"connect")) { } else if (argc == 3 && !strcasecmp(argv[0],"connect")) {
sdsfree(config.hostip); sdsfree(config.conn_info.hostip);
config.hostip = sdsnew(argv[1]); config.conn_info.hostip = sdsnew(argv[1]);
config.hostport = atoi(argv[2]); config.conn_info.hostport = atoi(argv[2]);
cliRefreshPrompt(); cliRefreshPrompt();
cliConnect(CC_FORCE); cliConnect(CC_FORCE);
} else if (argc == 1 && !strcasecmp(argv[0],"clear")) { } else if (argc == 1 && !strcasecmp(argv[0],"clear")) {
@ -2850,13 +2750,13 @@ static int clusterManagerNodeConnect(clusterManagerNode *node) {
* commands. At the same time this improves the detection of real * commands. At the same time this improves the detection of real
* errors. */ * errors. */
anetKeepAlive(NULL, node->context->fd, REDIS_CLI_KEEPALIVE_INTERVAL); anetKeepAlive(NULL, node->context->fd, REDIS_CLI_KEEPALIVE_INTERVAL);
if (config.auth) { if (config.conn_info.auth) {
redisReply *reply; redisReply *reply;
if (config.user == NULL) if (config.conn_info.user == NULL)
reply = redisCommand(node->context,"AUTH %s", config.auth); reply = redisCommand(node->context,"AUTH %s", config.conn_info.auth);
else else
reply = redisCommand(node->context,"AUTH %s %s", reply = redisCommand(node->context,"AUTH %s %s",
config.user,config.auth); config.conn_info.user,config.conn_info.auth);
int ok = clusterManagerCheckRedisReply(node, reply, NULL); int ok = clusterManagerCheckRedisReply(node, reply, NULL);
if (reply != NULL) freeReplyObject(reply); if (reply != NULL) freeReplyObject(reply);
if (!ok) return 0; if (!ok) return 0;
@ -3691,8 +3591,8 @@ static redisReply *clusterManagerMigrateKeysInReply(clusterManagerNode *source,
char **argv = NULL; char **argv = NULL;
size_t *argv_len = NULL; size_t *argv_len = NULL;
int c = (replace ? 8 : 7); int c = (replace ? 8 : 7);
if (config.auth) c += 2; if (config.conn_info.auth) c += 2;
if (config.user) c += 1; if (config.conn_info.user) c += 1;
size_t argc = c + reply->elements; size_t argc = c + reply->elements;
size_t i, offset = 6; // Keys Offset size_t i, offset = 6; // Keys Offset
argv = zcalloc(argc * sizeof(char *)); argv = zcalloc(argc * sizeof(char *));
@ -3718,23 +3618,23 @@ static redisReply *clusterManagerMigrateKeysInReply(clusterManagerNode *source,
argv_len[offset] = 7; argv_len[offset] = 7;
offset++; offset++;
} }
if (config.auth) { if (config.conn_info.auth) {
if (config.user) { if (config.conn_info.user) {
argv[offset] = "AUTH2"; argv[offset] = "AUTH2";
argv_len[offset] = 5; argv_len[offset] = 5;
offset++; offset++;
argv[offset] = config.user; argv[offset] = config.conn_info.user;
argv_len[offset] = strlen(config.user); argv_len[offset] = strlen(config.conn_info.user);
offset++; offset++;
argv[offset] = config.auth; argv[offset] = config.conn_info.auth;
argv_len[offset] = strlen(config.auth); argv_len[offset] = strlen(config.conn_info.auth);
offset++; offset++;
} else { } else {
argv[offset] = "AUTH"; argv[offset] = "AUTH";
argv_len[offset] = 4; argv_len[offset] = 4;
offset++; offset++;
argv[offset] = config.auth; argv[offset] = config.conn_info.auth;
argv_len[offset] = strlen(config.auth); argv_len[offset] = strlen(config.conn_info.auth);
offset++; offset++;
} }
} }
@ -6603,11 +6503,11 @@ static int clusterManagerCommandImport(int argc, char **argv) {
} }
} }
cmdfmt = sdsnew("MIGRATE %s %d %s %d %d"); cmdfmt = sdsnew("MIGRATE %s %d %s %d %d");
if (config.auth) { if (config.conn_info.auth) {
if (config.user) { if (config.conn_info.user) {
cmdfmt = sdscatfmt(cmdfmt," AUTH2 %s %s", config.user, config.auth); cmdfmt = sdscatfmt(cmdfmt," AUTH2 %s %s", config.conn_info.user, config.conn_info.auth);
} else { } else {
cmdfmt = sdscatfmt(cmdfmt," AUTH %s", config.auth); cmdfmt = sdscatfmt(cmdfmt," AUTH %s", config.conn_info.auth);
} }
} }
@ -8288,13 +8188,13 @@ int main(int argc, char **argv) {
struct timeval tv; struct timeval tv;
memset(&config.sslconfig, 0, sizeof(config.sslconfig)); memset(&config.sslconfig, 0, sizeof(config.sslconfig));
config.hostip = sdsnew("127.0.0.1"); config.conn_info.hostip = sdsnew("127.0.0.1");
config.hostport = 6379; config.conn_info.hostport = 6379;
config.hostsocket = NULL; config.hostsocket = NULL;
config.repeat = 1; config.repeat = 1;
config.interval = 0; config.interval = 0;
config.dbnum = 0; config.dbnum = 0;
config.input_dbnum = 0; config.conn_info.input_dbnum = 0;
config.interactive = 0; config.interactive = 0;
config.shutdown = 0; config.shutdown = 0;
config.monitor_mode = 0; config.monitor_mode = 0;
@ -8319,9 +8219,9 @@ int main(int argc, char **argv) {
config.bigkeys = 0; config.bigkeys = 0;
config.hotkeys = 0; config.hotkeys = 0;
config.stdinarg = 0; config.stdinarg = 0;
config.auth = NULL; config.conn_info.auth = NULL;
config.askpass = 0; config.askpass = 0;
config.user = NULL; config.conn_info.user = NULL;
config.eval = NULL; config.eval = NULL;
config.eval_ldb = 0; config.eval_ldb = 0;
config.eval_ldb_end = 0; config.eval_ldb_end = 0;
@ -8372,7 +8272,7 @@ int main(int argc, char **argv) {
parseEnv(); parseEnv();
if (config.askpass) { if (config.askpass) {
config.auth = askPassword("Please input password: "); config.conn_info.auth = askPassword("Please input password: ");
} }
if (config.cluster_manager_command.from_askpass) { if (config.cluster_manager_command.from_askpass) {

View File

@ -5,34 +5,54 @@ proc cmdstat {cmd} {
return [cmdrstat $cmd r] return [cmdrstat $cmd r]
} }
# common code to reset stats, flush the db and run redis-benchmark
proc common_bench_setup {cmd} {
r config resetstat
r flushall
if {[catch { exec {*}$cmd } error]} {
set first_line [lindex [split $error "\n"] 0]
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
}
}
# we use this extra asserts on a simple set,get test for features like uri parsing
# and other simple flag related tests
proc default_set_get_checks {} {
assert_match {*calls=10,*} [cmdstat set]
assert_match {*calls=10,*} [cmdstat get]
# assert one of the non benchmarked commands is not present
assert_match {} [cmdstat lrange]
}
start_server {tags {"benchmark network external:skip"}} { start_server {tags {"benchmark network external:skip"}} {
start_server {} { start_server {} {
set master_host [srv 0 host] set master_host [srv 0 host]
set master_port [srv 0 port] set master_port [srv 0 port]
test {benchmark: set,get} { test {benchmark: set,get} {
r config resetstat
r flushall
set cmd [redisbenchmark $master_host $master_port "-c 5 -n 10 -t set,get"] set cmd [redisbenchmark $master_host $master_port "-c 5 -n 10 -t set,get"]
if {[catch { exec {*}$cmd } error]} { common_bench_setup $cmd
set first_line [lindex [split $error "\n"] 0] default_set_get_checks
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
} }
assert_match {*calls=10,*} [cmdstat set]
assert_match {*calls=10,*} [cmdstat get] test {benchmark: connecting using URI set,get} {
# assert one of the non benchmarked commands is not present set cmd [redisbenchmarkuri $master_host $master_port "-c 5 -n 10 -t set,get"]
assert_match {} [cmdstat lrange] common_bench_setup $cmd
default_set_get_checks
}
test {benchmark: connecting using URI with authentication set,get} {
r config set masterauth pass
set cmd [redisbenchmarkuriuserpass $master_host $master_port "default" pass "-c 5 -n 10 -t set,get"]
common_bench_setup $cmd
default_set_get_checks
} }
test {benchmark: full test suite} { test {benchmark: full test suite} {
r config resetstat
set cmd [redisbenchmark $master_host $master_port "-c 10 -n 100"] set cmd [redisbenchmark $master_host $master_port "-c 10 -n 100"]
if {[catch { exec {*}$cmd } error]} { common_bench_setup $cmd
set first_line [lindex [split $error "\n"] 0]
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
}
# ping total calls are 2*issued commands per test due to PING_INLINE and PING_MBULK # ping total calls are 2*issued commands per test due to PING_INLINE and PING_MBULK
assert_match {*calls=200,*} [cmdstat ping] assert_match {*calls=200,*} [cmdstat ping]
assert_match {*calls=100,*} [cmdstat set] assert_match {*calls=100,*} [cmdstat set]
@ -55,32 +75,17 @@ start_server {tags {"benchmark network external:skip"}} {
} }
test {benchmark: multi-thread set,get} { test {benchmark: multi-thread set,get} {
r config resetstat
r flushall
set cmd [redisbenchmark $master_host $master_port "--threads 10 -c 5 -n 10 -t set,get"] set cmd [redisbenchmark $master_host $master_port "--threads 10 -c 5 -n 10 -t set,get"]
if {[catch { exec {*}$cmd } error]} { common_bench_setup $cmd
set first_line [lindex [split $error "\n"] 0] default_set_get_checks
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
}
assert_match {*calls=10,*} [cmdstat set]
assert_match {*calls=10,*} [cmdstat get]
# assert one of the non benchmarked commands is not present
assert_match {} [cmdstat lrange]
# ensure only one key was populated # ensure only one key was populated
assert_match {1} [scan [regexp -inline {keys\=([\d]*)} [r info keyspace]] keys=%d] assert_match {1} [scan [regexp -inline {keys\=([\d]*)} [r info keyspace]] keys=%d]
} }
test {benchmark: pipelined full set,get} { test {benchmark: pipelined full set,get} {
r config resetstat
r flushall
set cmd [redisbenchmark $master_host $master_port "-P 5 -c 10 -n 10010 -t set,get"] set cmd [redisbenchmark $master_host $master_port "-P 5 -c 10 -n 10010 -t set,get"]
if {[catch { exec {*}$cmd } error]} { common_bench_setup $cmd
set first_line [lindex [split $error "\n"] 0]
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
}
assert_match {*calls=10010,*} [cmdstat set] assert_match {*calls=10010,*} [cmdstat set]
assert_match {*calls=10010,*} [cmdstat get] assert_match {*calls=10010,*} [cmdstat get]
# assert one of the non benchmarked commands is not present # assert one of the non benchmarked commands is not present
@ -91,14 +96,8 @@ start_server {tags {"benchmark network external:skip"}} {
} }
test {benchmark: arbitrary command} { test {benchmark: arbitrary command} {
r config resetstat
r flushall
set cmd [redisbenchmark $master_host $master_port "-c 5 -n 150 INCRBYFLOAT mykey 10.0"] set cmd [redisbenchmark $master_host $master_port "-c 5 -n 150 INCRBYFLOAT mykey 10.0"]
if {[catch { exec {*}$cmd } error]} { common_bench_setup $cmd
set first_line [lindex [split $error "\n"] 0]
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
}
assert_match {*calls=150,*} [cmdstat incrbyfloat] assert_match {*calls=150,*} [cmdstat incrbyfloat]
# assert one of the non benchmarked commands is not present # assert one of the non benchmarked commands is not present
assert_match {} [cmdstat get] assert_match {} [cmdstat get]
@ -108,14 +107,8 @@ start_server {tags {"benchmark network external:skip"}} {
} }
test {benchmark: keyspace length} { test {benchmark: keyspace length} {
r flushall
r config resetstat
set cmd [redisbenchmark $master_host $master_port "-r 50 -t set -n 1000"] set cmd [redisbenchmark $master_host $master_port "-r 50 -t set -n 1000"]
if {[catch { exec {*}$cmd } error]} { common_bench_setup $cmd
set first_line [lindex [split $error "\n"] 0]
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
}
assert_match {*calls=1000,*} [cmdstat set] assert_match {*calls=1000,*} [cmdstat set]
# assert one of the non benchmarked commands is not present # assert one of the non benchmarked commands is not present
assert_match {} [cmdstat get] assert_match {} [cmdstat get]
@ -127,19 +120,20 @@ start_server {tags {"benchmark network external:skip"}} {
# tls specific tests # tls specific tests
if {$::tls} { if {$::tls} {
test {benchmark: specific tls-ciphers} { test {benchmark: specific tls-ciphers} {
r flushall
r config resetstat
set cmd [redisbenchmark $master_host $master_port "-r 50 -t set -n 1000 --tls-ciphers \"DEFAULT:-AES128-SHA256\""] set cmd [redisbenchmark $master_host $master_port "-r 50 -t set -n 1000 --tls-ciphers \"DEFAULT:-AES128-SHA256\""]
if {[catch { exec {*}$cmd } error]} { common_bench_setup $cmd
set first_line [lindex [split $error "\n"] 0]
puts [colorstr red "redis-benchmark non zero code. first line: $first_line"]
fail "redis-benchmark non zero code. first line: $first_line"
}
assert_match {*calls=1000,*} [cmdstat set] assert_match {*calls=1000,*} [cmdstat set]
# assert one of the non benchmarked commands is not present # assert one of the non benchmarked commands is not present
assert_match {} [cmdstat get] assert_match {} [cmdstat get]
} }
test {benchmark: tls connecting using URI with authentication set,get} {
r config set masterauth pass
set cmd [redisbenchmarkuriuserpass $master_host $master_port "default" pass "-c 5 -n 10 -t set,get"]
common_bench_setup $cmd
default_set_get_checks
}
test {benchmark: specific tls-ciphersuites} { test {benchmark: specific tls-ciphersuites} {
r flushall r flushall
r config resetstat r config resetstat

View File

@ -17,3 +17,17 @@ proc redisbenchmark {host port {opts {}}} {
lappend cmd {*}$opts lappend cmd {*}$opts
return $cmd return $cmd
} }
proc redisbenchmarkuri {host port {opts {}}} {
set cmd [list src/redis-benchmark -u redis://$host:$port]
lappend cmd {*}[redisbenchmark_tls_config "tests"]
lappend cmd {*}$opts
return $cmd
}
proc redisbenchmarkuriuserpass {host port user pass {opts {}}} {
set cmd [list src/redis-benchmark -u redis://$user:$pass@$host:$port]
lappend cmd {*}[redisbenchmark_tls_config "tests"]
lappend cmd {*}$opts
return $cmd
}