hiredis 0.5.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Rakefile +8 -6
- data/ext/hiredis_ext/connection.c +4 -3
- data/ext/hiredis_ext/extconf.rb +25 -10
- data/ext/hiredis_ext/reader.c +12 -6
- data/lib/hiredis/version.rb +1 -1
- data/vendor/hiredis/Makefile +119 -54
- data/vendor/hiredis/async.c +121 -27
- data/vendor/hiredis/async.h +5 -0
- data/vendor/hiredis/dict.c +2 -2
- data/vendor/hiredis/fmacros.h +5 -9
- data/vendor/hiredis/hiredis.c +275 -554
- data/vendor/hiredis/hiredis.h +64 -75
- data/vendor/hiredis/net.c +242 -56
- data/vendor/hiredis/net.h +12 -10
- data/vendor/hiredis/read.c +598 -0
- data/vendor/hiredis/read.h +111 -0
- data/vendor/hiredis/sds.c +847 -180
- data/vendor/hiredis/sds.h +203 -18
- data/vendor/hiredis/sdsalloc.h +42 -0
- data/vendor/hiredis/test.c +286 -19
- data/vendor/hiredis/win32.h +42 -0
- metadata +46 -28
- data/lib/hiredis/errors.rb +0 -5
data/vendor/hiredis/test.c
CHANGED
@@ -8,12 +8,15 @@
|
|
8
8
|
#include <unistd.h>
|
9
9
|
#include <signal.h>
|
10
10
|
#include <errno.h>
|
11
|
+
#include <limits.h>
|
11
12
|
|
12
13
|
#include "hiredis.h"
|
14
|
+
#include "net.h"
|
13
15
|
|
14
16
|
enum connection_type {
|
15
17
|
CONN_TCP,
|
16
|
-
CONN_UNIX
|
18
|
+
CONN_UNIX,
|
19
|
+
CONN_FD
|
17
20
|
};
|
18
21
|
|
19
22
|
struct config {
|
@@ -22,11 +25,12 @@ struct config {
|
|
22
25
|
struct {
|
23
26
|
const char *host;
|
24
27
|
int port;
|
28
|
+
struct timeval timeout;
|
25
29
|
} tcp;
|
26
30
|
|
27
31
|
struct {
|
28
32
|
const char *path;
|
29
|
-
}
|
33
|
+
} unix_sock;
|
30
34
|
};
|
31
35
|
|
32
36
|
/* The following lines make up our testing "framework" :) */
|
@@ -40,6 +44,13 @@ static long long usec(void) {
|
|
40
44
|
return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
|
41
45
|
}
|
42
46
|
|
47
|
+
/* The assert() calls below have side effects, so we need assert()
|
48
|
+
* even if we are compiling without asserts (-DNDEBUG). */
|
49
|
+
#ifdef NDEBUG
|
50
|
+
#undef assert
|
51
|
+
#define assert(e) (void)(e)
|
52
|
+
#endif
|
53
|
+
|
43
54
|
static redisContext *select_database(redisContext *c) {
|
44
55
|
redisReply *reply;
|
45
56
|
|
@@ -62,7 +73,7 @@ static redisContext *select_database(redisContext *c) {
|
|
62
73
|
return c;
|
63
74
|
}
|
64
75
|
|
65
|
-
static
|
76
|
+
static int disconnect(redisContext *c, int keep_fd) {
|
66
77
|
redisReply *reply;
|
67
78
|
|
68
79
|
/* Make sure we're on DB 9. */
|
@@ -73,8 +84,11 @@ static void disconnect(redisContext *c) {
|
|
73
84
|
assert(reply != NULL);
|
74
85
|
freeReplyObject(reply);
|
75
86
|
|
76
|
-
/* Free the context as well. */
|
87
|
+
/* Free the context as well, but keep the fd if requested. */
|
88
|
+
if (keep_fd)
|
89
|
+
return redisFreeKeepFd(c);
|
77
90
|
redisFree(c);
|
91
|
+
return -1;
|
78
92
|
}
|
79
93
|
|
80
94
|
static redisContext *connect(struct config config) {
|
@@ -83,13 +97,25 @@ static redisContext *connect(struct config config) {
|
|
83
97
|
if (config.type == CONN_TCP) {
|
84
98
|
c = redisConnect(config.tcp.host, config.tcp.port);
|
85
99
|
} else if (config.type == CONN_UNIX) {
|
86
|
-
c = redisConnectUnix(config.
|
100
|
+
c = redisConnectUnix(config.unix_sock.path);
|
101
|
+
} else if (config.type == CONN_FD) {
|
102
|
+
/* Create a dummy connection just to get an fd to inherit */
|
103
|
+
redisContext *dummy_ctx = redisConnectUnix(config.unix_sock.path);
|
104
|
+
if (dummy_ctx) {
|
105
|
+
int fd = disconnect(dummy_ctx, 1);
|
106
|
+
printf("Connecting to inherited fd %d\n", fd);
|
107
|
+
c = redisConnectFd(fd);
|
108
|
+
}
|
87
109
|
} else {
|
88
110
|
assert(NULL);
|
89
111
|
}
|
90
112
|
|
91
|
-
if (c
|
113
|
+
if (c == NULL) {
|
114
|
+
printf("Connection error: can't allocate redis context\n");
|
115
|
+
exit(1);
|
116
|
+
} else if (c->err) {
|
92
117
|
printf("Connection error: %s\n", c->errstr);
|
118
|
+
redisFree(c);
|
93
119
|
exit(1);
|
94
120
|
}
|
95
121
|
|
@@ -125,13 +151,13 @@ static void test_format_commands(void) {
|
|
125
151
|
free(cmd);
|
126
152
|
|
127
153
|
test("Format command with %%b string interpolation: ");
|
128
|
-
len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
|
154
|
+
len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3);
|
129
155
|
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 &&
|
130
156
|
len == 4+4+(3+2)+4+(3+2)+4+(3+2));
|
131
157
|
free(cmd);
|
132
158
|
|
133
159
|
test("Format command with %%b and an empty string: ");
|
134
|
-
len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0);
|
160
|
+
len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0);
|
135
161
|
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
|
136
162
|
len == 4+4+(3+2)+4+(3+2)+4+(0+2));
|
137
163
|
free(cmd);
|
@@ -177,7 +203,7 @@ static void test_format_commands(void) {
|
|
177
203
|
FLOAT_WIDTH_TEST(double);
|
178
204
|
|
179
205
|
test("Format command with invalid printf format: ");
|
180
|
-
len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
|
206
|
+
len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);
|
181
207
|
test_cond(len == -1);
|
182
208
|
|
183
209
|
const char *argv[3];
|
@@ -198,6 +224,44 @@ static void test_format_commands(void) {
|
|
198
224
|
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 &&
|
199
225
|
len == 4+4+(3+2)+4+(7+2)+4+(3+2));
|
200
226
|
free(cmd);
|
227
|
+
|
228
|
+
sds sds_cmd;
|
229
|
+
|
230
|
+
sds_cmd = sdsempty();
|
231
|
+
test("Format command into sds by passing argc/argv without lengths: ");
|
232
|
+
len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,NULL);
|
233
|
+
test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
|
234
|
+
len == 4+4+(3+2)+4+(3+2)+4+(3+2));
|
235
|
+
sdsfree(sds_cmd);
|
236
|
+
|
237
|
+
sds_cmd = sdsempty();
|
238
|
+
test("Format command into sds by passing argc/argv with lengths: ");
|
239
|
+
len = redisFormatSdsCommandArgv(&sds_cmd,argc,argv,lens);
|
240
|
+
test_cond(strncmp(sds_cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 &&
|
241
|
+
len == 4+4+(3+2)+4+(7+2)+4+(3+2));
|
242
|
+
sdsfree(sds_cmd);
|
243
|
+
}
|
244
|
+
|
245
|
+
static void test_append_formatted_commands(struct config config) {
|
246
|
+
redisContext *c;
|
247
|
+
redisReply *reply;
|
248
|
+
char *cmd;
|
249
|
+
int len;
|
250
|
+
|
251
|
+
c = connect(config);
|
252
|
+
|
253
|
+
test("Append format command: ");
|
254
|
+
|
255
|
+
len = redisFormatCommand(&cmd, "SET foo bar");
|
256
|
+
|
257
|
+
test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);
|
258
|
+
|
259
|
+
assert(redisGetReply(c, (void*)&reply) == REDIS_OK);
|
260
|
+
|
261
|
+
free(cmd);
|
262
|
+
freeReplyObject(reply);
|
263
|
+
|
264
|
+
disconnect(c, 0);
|
201
265
|
}
|
202
266
|
|
203
267
|
static void test_reply_reader(void) {
|
@@ -238,6 +302,82 @@ static void test_reply_reader(void) {
|
|
238
302
|
strncasecmp(reader->errstr,"No support for",14) == 0);
|
239
303
|
redisReaderFree(reader);
|
240
304
|
|
305
|
+
test("Correctly parses LLONG_MAX: ");
|
306
|
+
reader = redisReaderCreate();
|
307
|
+
redisReaderFeed(reader, ":9223372036854775807\r\n",22);
|
308
|
+
ret = redisReaderGetReply(reader,&reply);
|
309
|
+
test_cond(ret == REDIS_OK &&
|
310
|
+
((redisReply*)reply)->type == REDIS_REPLY_INTEGER &&
|
311
|
+
((redisReply*)reply)->integer == LLONG_MAX);
|
312
|
+
freeReplyObject(reply);
|
313
|
+
redisReaderFree(reader);
|
314
|
+
|
315
|
+
test("Set error when > LLONG_MAX: ");
|
316
|
+
reader = redisReaderCreate();
|
317
|
+
redisReaderFeed(reader, ":9223372036854775808\r\n",22);
|
318
|
+
ret = redisReaderGetReply(reader,&reply);
|
319
|
+
test_cond(ret == REDIS_ERR &&
|
320
|
+
strcasecmp(reader->errstr,"Bad integer value") == 0);
|
321
|
+
freeReplyObject(reply);
|
322
|
+
redisReaderFree(reader);
|
323
|
+
|
324
|
+
test("Correctly parses LLONG_MIN: ");
|
325
|
+
reader = redisReaderCreate();
|
326
|
+
redisReaderFeed(reader, ":-9223372036854775808\r\n",23);
|
327
|
+
ret = redisReaderGetReply(reader,&reply);
|
328
|
+
test_cond(ret == REDIS_OK &&
|
329
|
+
((redisReply*)reply)->type == REDIS_REPLY_INTEGER &&
|
330
|
+
((redisReply*)reply)->integer == LLONG_MIN);
|
331
|
+
freeReplyObject(reply);
|
332
|
+
redisReaderFree(reader);
|
333
|
+
|
334
|
+
test("Set error when < LLONG_MIN: ");
|
335
|
+
reader = redisReaderCreate();
|
336
|
+
redisReaderFeed(reader, ":-9223372036854775809\r\n",23);
|
337
|
+
ret = redisReaderGetReply(reader,&reply);
|
338
|
+
test_cond(ret == REDIS_ERR &&
|
339
|
+
strcasecmp(reader->errstr,"Bad integer value") == 0);
|
340
|
+
freeReplyObject(reply);
|
341
|
+
redisReaderFree(reader);
|
342
|
+
|
343
|
+
test("Set error when array < -1: ");
|
344
|
+
reader = redisReaderCreate();
|
345
|
+
redisReaderFeed(reader, "*-2\r\n+asdf\r\n",12);
|
346
|
+
ret = redisReaderGetReply(reader,&reply);
|
347
|
+
test_cond(ret == REDIS_ERR &&
|
348
|
+
strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0);
|
349
|
+
freeReplyObject(reply);
|
350
|
+
redisReaderFree(reader);
|
351
|
+
|
352
|
+
test("Set error when bulk < -1: ");
|
353
|
+
reader = redisReaderCreate();
|
354
|
+
redisReaderFeed(reader, "$-2\r\nasdf\r\n",11);
|
355
|
+
ret = redisReaderGetReply(reader,&reply);
|
356
|
+
test_cond(ret == REDIS_ERR &&
|
357
|
+
strcasecmp(reader->errstr,"Bulk string length out of range") == 0);
|
358
|
+
freeReplyObject(reply);
|
359
|
+
redisReaderFree(reader);
|
360
|
+
|
361
|
+
test("Set error when array > INT_MAX: ");
|
362
|
+
reader = redisReaderCreate();
|
363
|
+
redisReaderFeed(reader, "*9223372036854775807\r\n+asdf\r\n",29);
|
364
|
+
ret = redisReaderGetReply(reader,&reply);
|
365
|
+
test_cond(ret == REDIS_ERR &&
|
366
|
+
strcasecmp(reader->errstr,"Multi-bulk length out of range") == 0);
|
367
|
+
freeReplyObject(reply);
|
368
|
+
redisReaderFree(reader);
|
369
|
+
|
370
|
+
#if LLONG_MAX > SIZE_MAX
|
371
|
+
test("Set error when bulk > SIZE_MAX: ");
|
372
|
+
reader = redisReaderCreate();
|
373
|
+
redisReaderFeed(reader, "$9223372036854775807\r\nasdf\r\n",28);
|
374
|
+
ret = redisReaderGetReply(reader,&reply);
|
375
|
+
test_cond(ret == REDIS_ERR &&
|
376
|
+
strcasecmp(reader->errstr,"Bulk string length out of range") == 0);
|
377
|
+
freeReplyObject(reply);
|
378
|
+
redisReaderFree(reader);
|
379
|
+
#endif
|
380
|
+
|
241
381
|
test("Works with NULL functions for reply: ");
|
242
382
|
reader = redisReaderCreate();
|
243
383
|
reader->fn = NULL;
|
@@ -279,14 +419,32 @@ static void test_reply_reader(void) {
|
|
279
419
|
redisReaderFree(reader);
|
280
420
|
}
|
281
421
|
|
422
|
+
static void test_free_null(void) {
|
423
|
+
void *redisCtx = NULL;
|
424
|
+
void *reply = NULL;
|
425
|
+
|
426
|
+
test("Don't fail when redisFree is passed a NULL value: ");
|
427
|
+
redisFree(redisCtx);
|
428
|
+
test_cond(redisCtx == NULL);
|
429
|
+
|
430
|
+
test("Don't fail when freeReplyObject is passed a NULL value: ");
|
431
|
+
freeReplyObject(reply);
|
432
|
+
test_cond(reply == NULL);
|
433
|
+
}
|
434
|
+
|
282
435
|
static void test_blocking_connection_errors(void) {
|
283
436
|
redisContext *c;
|
284
437
|
|
285
438
|
test("Returns error when host cannot be resolved: ");
|
286
|
-
c = redisConnect((char*)"idontexist.
|
439
|
+
c = redisConnect((char*)"idontexist.test", 6379);
|
287
440
|
test_cond(c->err == REDIS_ERR_OTHER &&
|
288
441
|
(strcmp(c->errstr,"Name or service not known") == 0 ||
|
289
|
-
strcmp(c->errstr,"Can't resolve: idontexist.
|
442
|
+
strcmp(c->errstr,"Can't resolve: idontexist.test") == 0 ||
|
443
|
+
strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 ||
|
444
|
+
strcmp(c->errstr,"No address associated with hostname") == 0 ||
|
445
|
+
strcmp(c->errstr,"Temporary failure in name resolution") == 0 ||
|
446
|
+
strcmp(c->errstr,"hostname nor servname provided, or not known") == 0 ||
|
447
|
+
strcmp(c->errstr,"no address associated with name") == 0));
|
290
448
|
redisFree(c);
|
291
449
|
|
292
450
|
test("Returns error when the port is not open: ");
|
@@ -295,7 +453,7 @@ static void test_blocking_connection_errors(void) {
|
|
295
453
|
strcmp(c->errstr,"Connection refused") == 0);
|
296
454
|
redisFree(c);
|
297
455
|
|
298
|
-
test("Returns error when the
|
456
|
+
test("Returns error when the unix_sock socket path doesn't accept connections: ");
|
299
457
|
c = redisConnectUnix((char*)"/tmp/idontexist.sock");
|
300
458
|
test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */
|
301
459
|
redisFree(c);
|
@@ -328,7 +486,7 @@ static void test_blocking_connection(struct config config) {
|
|
328
486
|
freeReplyObject(reply);
|
329
487
|
|
330
488
|
test("%%b String interpolation works: ");
|
331
|
-
reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
|
489
|
+
reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11);
|
332
490
|
freeReplyObject(reply);
|
333
491
|
reply = redisCommand(c,"GET foo");
|
334
492
|
test_cond(reply->type == REDIS_REPLY_STRING &&
|
@@ -376,7 +534,53 @@ static void test_blocking_connection(struct config config) {
|
|
376
534
|
strcasecmp(reply->element[1]->str,"pong") == 0);
|
377
535
|
freeReplyObject(reply);
|
378
536
|
|
379
|
-
disconnect(c);
|
537
|
+
disconnect(c, 0);
|
538
|
+
}
|
539
|
+
|
540
|
+
static void test_blocking_connection_timeouts(struct config config) {
|
541
|
+
redisContext *c;
|
542
|
+
redisReply *reply;
|
543
|
+
ssize_t s;
|
544
|
+
const char *cmd = "DEBUG SLEEP 3\r\n";
|
545
|
+
struct timeval tv;
|
546
|
+
|
547
|
+
c = connect(config);
|
548
|
+
test("Successfully completes a command when the timeout is not exceeded: ");
|
549
|
+
reply = redisCommand(c,"SET foo fast");
|
550
|
+
freeReplyObject(reply);
|
551
|
+
tv.tv_sec = 0;
|
552
|
+
tv.tv_usec = 10000;
|
553
|
+
redisSetTimeout(c, tv);
|
554
|
+
reply = redisCommand(c, "GET foo");
|
555
|
+
test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0);
|
556
|
+
freeReplyObject(reply);
|
557
|
+
disconnect(c, 0);
|
558
|
+
|
559
|
+
c = connect(config);
|
560
|
+
test("Does not return a reply when the command times out: ");
|
561
|
+
s = write(c->fd, cmd, strlen(cmd));
|
562
|
+
tv.tv_sec = 0;
|
563
|
+
tv.tv_usec = 10000;
|
564
|
+
redisSetTimeout(c, tv);
|
565
|
+
reply = redisCommand(c, "GET foo");
|
566
|
+
test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_IO && strcmp(c->errstr, "Resource temporarily unavailable") == 0);
|
567
|
+
freeReplyObject(reply);
|
568
|
+
|
569
|
+
test("Reconnect properly reconnects after a timeout: ");
|
570
|
+
redisReconnect(c);
|
571
|
+
reply = redisCommand(c, "PING");
|
572
|
+
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
573
|
+
freeReplyObject(reply);
|
574
|
+
|
575
|
+
test("Reconnect properly uses owned parameters: ");
|
576
|
+
config.tcp.host = "foo";
|
577
|
+
config.unix_sock.path = "foo";
|
578
|
+
redisReconnect(c);
|
579
|
+
reply = redisCommand(c, "PING");
|
580
|
+
test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0);
|
581
|
+
freeReplyObject(reply);
|
582
|
+
|
583
|
+
disconnect(c, 0);
|
380
584
|
}
|
381
585
|
|
382
586
|
static void test_blocking_io_errors(struct config config) {
|
@@ -402,7 +606,7 @@ static void test_blocking_io_errors(struct config config) {
|
|
402
606
|
|
403
607
|
test("Returns I/O error when the connection is lost: ");
|
404
608
|
reply = redisCommand(c,"QUIT");
|
405
|
-
if (major
|
609
|
+
if (major > 2 || (major == 2 && minor > 0)) {
|
406
610
|
/* > 2.0 returns OK on QUIT and read() should be issued once more
|
407
611
|
* to know the descriptor is at EOF. */
|
408
612
|
test_cond(strcasecmp(reply->str,"OK") == 0 &&
|
@@ -430,6 +634,30 @@ static void test_blocking_io_errors(struct config config) {
|
|
430
634
|
redisFree(c);
|
431
635
|
}
|
432
636
|
|
637
|
+
static void test_invalid_timeout_errors(struct config config) {
|
638
|
+
redisContext *c;
|
639
|
+
|
640
|
+
test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: ");
|
641
|
+
|
642
|
+
config.tcp.timeout.tv_sec = 0;
|
643
|
+
config.tcp.timeout.tv_usec = 10000001;
|
644
|
+
|
645
|
+
c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
|
646
|
+
|
647
|
+
test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
|
648
|
+
redisFree(c);
|
649
|
+
|
650
|
+
test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: ");
|
651
|
+
|
652
|
+
config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;
|
653
|
+
config.tcp.timeout.tv_usec = 0;
|
654
|
+
|
655
|
+
c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
|
656
|
+
|
657
|
+
test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
|
658
|
+
redisFree(c);
|
659
|
+
}
|
660
|
+
|
433
661
|
static void test_throughput(struct config config) {
|
434
662
|
redisContext *c = connect(config);
|
435
663
|
redisReply **replies;
|
@@ -464,6 +692,17 @@ static void test_throughput(struct config config) {
|
|
464
692
|
free(replies);
|
465
693
|
printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0);
|
466
694
|
|
695
|
+
replies = malloc(sizeof(redisReply*)*num);
|
696
|
+
t1 = usec();
|
697
|
+
for (i = 0; i < num; i++) {
|
698
|
+
replies[i] = redisCommand(c, "INCRBY incrkey %d", 1000000);
|
699
|
+
assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER);
|
700
|
+
}
|
701
|
+
t2 = usec();
|
702
|
+
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
|
703
|
+
free(replies);
|
704
|
+
printf("\t(%dx INCRBY: %.3fs)\n", num, (t2-t1)/1000000.0);
|
705
|
+
|
467
706
|
num = 10000;
|
468
707
|
replies = malloc(sizeof(redisReply*)*num);
|
469
708
|
for (i = 0; i < num; i++)
|
@@ -492,7 +731,20 @@ static void test_throughput(struct config config) {
|
|
492
731
|
free(replies);
|
493
732
|
printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
|
494
733
|
|
495
|
-
|
734
|
+
replies = malloc(sizeof(redisReply*)*num);
|
735
|
+
for (i = 0; i < num; i++)
|
736
|
+
redisAppendCommand(c,"INCRBY incrkey %d", 1000000);
|
737
|
+
t1 = usec();
|
738
|
+
for (i = 0; i < num; i++) {
|
739
|
+
assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);
|
740
|
+
assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_INTEGER);
|
741
|
+
}
|
742
|
+
t2 = usec();
|
743
|
+
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
|
744
|
+
free(replies);
|
745
|
+
printf("\t(%dx INCRBY (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
|
746
|
+
|
747
|
+
disconnect(c, 0);
|
496
748
|
}
|
497
749
|
|
498
750
|
// static long __test_callback_flags = 0;
|
@@ -600,11 +852,12 @@ int main(int argc, char **argv) {
|
|
600
852
|
.host = "127.0.0.1",
|
601
853
|
.port = 6379
|
602
854
|
},
|
603
|
-
.
|
855
|
+
.unix_sock = {
|
604
856
|
.path = "/tmp/redis.sock"
|
605
857
|
}
|
606
858
|
};
|
607
859
|
int throughput = 1;
|
860
|
+
int test_inherit_fd = 1;
|
608
861
|
|
609
862
|
/* Ignore broken pipe signal (for I/O error tests). */
|
610
863
|
signal(SIGPIPE, SIG_IGN);
|
@@ -620,9 +873,11 @@ int main(int argc, char **argv) {
|
|
620
873
|
cfg.tcp.port = atoi(argv[0]);
|
621
874
|
} else if (argc >= 2 && !strcmp(argv[0],"-s")) {
|
622
875
|
argv++; argc--;
|
623
|
-
cfg.
|
876
|
+
cfg.unix_sock.path = argv[0];
|
624
877
|
} else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {
|
625
878
|
throughput = 0;
|
879
|
+
} else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
|
880
|
+
test_inherit_fd = 0;
|
626
881
|
} else {
|
627
882
|
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
628
883
|
exit(1);
|
@@ -633,19 +888,31 @@ int main(int argc, char **argv) {
|
|
633
888
|
test_format_commands();
|
634
889
|
test_reply_reader();
|
635
890
|
test_blocking_connection_errors();
|
891
|
+
test_free_null();
|
636
892
|
|
637
893
|
printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port);
|
638
894
|
cfg.type = CONN_TCP;
|
639
895
|
test_blocking_connection(cfg);
|
896
|
+
test_blocking_connection_timeouts(cfg);
|
640
897
|
test_blocking_io_errors(cfg);
|
898
|
+
test_invalid_timeout_errors(cfg);
|
899
|
+
test_append_formatted_commands(cfg);
|
641
900
|
if (throughput) test_throughput(cfg);
|
642
901
|
|
643
|
-
printf("\nTesting against Unix socket connection (%s):\n", cfg.
|
902
|
+
printf("\nTesting against Unix socket connection (%s):\n", cfg.unix_sock.path);
|
644
903
|
cfg.type = CONN_UNIX;
|
645
904
|
test_blocking_connection(cfg);
|
905
|
+
test_blocking_connection_timeouts(cfg);
|
646
906
|
test_blocking_io_errors(cfg);
|
647
907
|
if (throughput) test_throughput(cfg);
|
648
908
|
|
909
|
+
if (test_inherit_fd) {
|
910
|
+
printf("\nTesting against inherited fd (%s):\n", cfg.unix_sock.path);
|
911
|
+
cfg.type = CONN_FD;
|
912
|
+
test_blocking_connection(cfg);
|
913
|
+
}
|
914
|
+
|
915
|
+
|
649
916
|
if (fails) {
|
650
917
|
printf("*** %d TESTS FAILED ***\n", fails);
|
651
918
|
return 1;
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#ifndef _WIN32_HELPER_INCLUDE
|
2
|
+
#define _WIN32_HELPER_INCLUDE
|
3
|
+
#ifdef _MSC_VER
|
4
|
+
|
5
|
+
#ifndef inline
|
6
|
+
#define inline __inline
|
7
|
+
#endif
|
8
|
+
|
9
|
+
#ifndef va_copy
|
10
|
+
#define va_copy(d,s) ((d) = (s))
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#ifndef snprintf
|
14
|
+
#define snprintf c99_snprintf
|
15
|
+
|
16
|
+
__inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
|
17
|
+
{
|
18
|
+
int count = -1;
|
19
|
+
|
20
|
+
if (size != 0)
|
21
|
+
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
|
22
|
+
if (count == -1)
|
23
|
+
count = _vscprintf(format, ap);
|
24
|
+
|
25
|
+
return count;
|
26
|
+
}
|
27
|
+
|
28
|
+
__inline int c99_snprintf(char* str, size_t size, const char* format, ...)
|
29
|
+
{
|
30
|
+
int count;
|
31
|
+
va_list ap;
|
32
|
+
|
33
|
+
va_start(ap, format);
|
34
|
+
count = c99_vsnprintf(str, size, format, ap);
|
35
|
+
va_end(ap);
|
36
|
+
|
37
|
+
return count;
|
38
|
+
}
|
39
|
+
#endif
|
40
|
+
|
41
|
+
#endif
|
42
|
+
#endif
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hiredis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pieter Noordhuis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -28,16 +28,30 @@ dependencies:
|
|
28
28
|
name: rake-compiler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 0.7.1
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.7.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 5.5.1
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 5.5.1
|
41
55
|
description: Ruby wrapper for hiredis (protocol serialization/deserialization and
|
42
56
|
blocking I/O)
|
43
57
|
email:
|
@@ -47,38 +61,42 @@ extensions:
|
|
47
61
|
- ext/hiredis_ext/extconf.rb
|
48
62
|
extra_rdoc_files: []
|
49
63
|
files:
|
50
|
-
-
|
64
|
+
- COPYING
|
65
|
+
- Rakefile
|
51
66
|
- ext/hiredis_ext/connection.c
|
67
|
+
- ext/hiredis_ext/extconf.rb
|
52
68
|
- ext/hiredis_ext/hiredis_ext.c
|
53
|
-
- ext/hiredis_ext/reader.c
|
54
69
|
- ext/hiredis_ext/hiredis_ext.h
|
55
|
-
-
|
56
|
-
-
|
57
|
-
- vendor/hiredis/hiredis.c
|
58
|
-
- vendor/hiredis/net.c
|
59
|
-
- vendor/hiredis/sds.c
|
60
|
-
- vendor/hiredis/test.c
|
61
|
-
- vendor/hiredis/async.h
|
62
|
-
- vendor/hiredis/dict.h
|
63
|
-
- vendor/hiredis/fmacros.h
|
64
|
-
- vendor/hiredis/hiredis.h
|
65
|
-
- vendor/hiredis/net.h
|
66
|
-
- vendor/hiredis/sds.h
|
67
|
-
- vendor/hiredis/COPYING
|
68
|
-
- vendor/hiredis/Makefile
|
70
|
+
- ext/hiredis_ext/reader.c
|
71
|
+
- lib/hiredis.rb
|
69
72
|
- lib/hiredis/connection.rb
|
70
|
-
- lib/hiredis/errors.rb
|
71
73
|
- lib/hiredis/ext/connection.rb
|
72
74
|
- lib/hiredis/ext/reader.rb
|
73
75
|
- lib/hiredis/reader.rb
|
74
76
|
- lib/hiredis/ruby/connection.rb
|
75
77
|
- lib/hiredis/ruby/reader.rb
|
76
78
|
- lib/hiredis/version.rb
|
77
|
-
-
|
78
|
-
-
|
79
|
-
-
|
79
|
+
- vendor/hiredis/COPYING
|
80
|
+
- vendor/hiredis/Makefile
|
81
|
+
- vendor/hiredis/async.c
|
82
|
+
- vendor/hiredis/async.h
|
83
|
+
- vendor/hiredis/dict.c
|
84
|
+
- vendor/hiredis/dict.h
|
85
|
+
- vendor/hiredis/fmacros.h
|
86
|
+
- vendor/hiredis/hiredis.c
|
87
|
+
- vendor/hiredis/hiredis.h
|
88
|
+
- vendor/hiredis/net.c
|
89
|
+
- vendor/hiredis/net.h
|
90
|
+
- vendor/hiredis/read.c
|
91
|
+
- vendor/hiredis/read.h
|
92
|
+
- vendor/hiredis/sds.c
|
93
|
+
- vendor/hiredis/sds.h
|
94
|
+
- vendor/hiredis/sdsalloc.h
|
95
|
+
- vendor/hiredis/test.c
|
96
|
+
- vendor/hiredis/win32.h
|
80
97
|
homepage: http://github.com/redis/hiredis-rb
|
81
|
-
licenses:
|
98
|
+
licenses:
|
99
|
+
- BSD-3-Clause
|
82
100
|
metadata: {}
|
83
101
|
post_install_message:
|
84
102
|
rdoc_options: []
|
@@ -86,17 +104,17 @@ require_paths:
|
|
86
104
|
- lib
|
87
105
|
required_ruby_version: !ruby/object:Gem::Requirement
|
88
106
|
requirements:
|
89
|
-
- -
|
107
|
+
- - ">="
|
90
108
|
- !ruby/object:Gem::Version
|
91
109
|
version: '0'
|
92
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
111
|
requirements:
|
94
|
-
- -
|
112
|
+
- - ">="
|
95
113
|
- !ruby/object:Gem::Version
|
96
114
|
version: '0'
|
97
115
|
requirements: []
|
98
116
|
rubyforge_project:
|
99
|
-
rubygems_version: 2.
|
117
|
+
rubygems_version: 2.7.6
|
100
118
|
signing_key:
|
101
119
|
specification_version: 4
|
102
120
|
summary: Ruby wrapper for hiredis (protocol serialization/deserialization and blocking
|