]> git.saurik.com Git - redis.git/blame - deps/hiredis/test.c
show initial querybuf bytes on querybuf overflow.
[redis.git] / deps / hiredis / test.c
CommitLineData
24f753a8
PN
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <strings.h>
5#include <sys/time.h>
6#include <assert.h>
7#include <unistd.h>
57c9babd 8#include <signal.h>
9703b1b3 9#include <errno.h>
24f753a8
PN
10
11#include "hiredis.h"
12
13/* The following lines make up our testing "framework" :) */
14static int tests = 0, fails = 0;
15#define test(_s) { printf("#%02d ", ++tests); printf(_s); }
16#define test_cond(_c) if(_c) printf("PASSED\n"); else {printf("FAILED\n"); fails++;}
17
18static long long usec(void) {
19 struct timeval tv;
20 gettimeofday(&tv,NULL);
21 return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
22}
23
24static int use_unix = 0;
25static redisContext *blocking_context = NULL;
26static void __connect(redisContext **target) {
27 *target = blocking_context = (use_unix ?
28 redisConnectUnix("/tmp/redis.sock") : redisConnect((char*)"127.0.0.1", 6379));
29 if (blocking_context->err) {
30 printf("Connection error: %s\n", blocking_context->errstr);
31 exit(1);
32 }
33}
34
9703b1b3 35static void test_format_commands(void) {
24f753a8
PN
36 char *cmd;
37 int len;
38
39 test("Format command without interpolation: ");
40 len = redisFormatCommand(&cmd,"SET foo bar");
41 test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
42 len == 4+4+(3+2)+4+(3+2)+4+(3+2));
43 free(cmd);
44
45 test("Format command with %%s string interpolation: ");
46 len = redisFormatCommand(&cmd,"SET %s %s","foo","bar");
47 test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
48 len == 4+4+(3+2)+4+(3+2)+4+(3+2));
49 free(cmd);
50
a1e97d69
PN
51 test("Format command with %%s and an empty string: ");
52 len = redisFormatCommand(&cmd,"SET %s %s","foo","");
53 test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
54 len == 4+4+(3+2)+4+(3+2)+4+(0+2));
55 free(cmd);
56
9703b1b3
PN
57 test("Format command with an empty string in between proper interpolations: ");
58 len = redisFormatCommand(&cmd,"SET %s %s","","foo");
59 test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 &&
60 len == 4+4+(3+2)+4+(0+2)+4+(3+2));
61 free(cmd);
62
24f753a8
PN
63 test("Format command with %%b string interpolation: ");
64 len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
65 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 &&
66 len == 4+4+(3+2)+4+(3+2)+4+(3+2));
67 free(cmd);
68
a1e97d69
PN
69 test("Format command with %%b and an empty string: ");
70 len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0);
71 test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
72 len == 4+4+(3+2)+4+(3+2)+4+(0+2));
73 free(cmd);
74
75 test("Format command with literal %%: ");
76 len = redisFormatCommand(&cmd,"SET %% %%");
77 test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$1\r\n%\r\n$1\r\n%\r\n",len) == 0 &&
78 len == 4+4+(3+2)+4+(1+2)+4+(1+2));
79 free(cmd);
80
81 test("Format command with printf-delegation (long long): ");
82 len = redisFormatCommand(&cmd,"key:%08lld",1234ll);
83 test_cond(strncmp(cmd,"*1\r\n$12\r\nkey:00001234\r\n",len) == 0 &&
84 len == 4+5+(12+2));
85 free(cmd);
86
87 test("Format command with printf-delegation (float): ");
88 len = redisFormatCommand(&cmd,"v:%06.1f",12.34f);
89 test_cond(strncmp(cmd,"*1\r\n$8\r\nv:0012.3\r\n",len) == 0 &&
90 len == 4+4+(8+2));
91 free(cmd);
92
93 test("Format command with printf-delegation and extra interpolation: ");
94 len = redisFormatCommand(&cmd,"key:%d %b",1234,"foo",3);
95 test_cond(strncmp(cmd,"*2\r\n$8\r\nkey:1234\r\n$3\r\nfoo\r\n",len) == 0 &&
96 len == 4+4+(8+2)+4+(3+2));
97 free(cmd);
98
99 test("Format command with wrong printf format and extra interpolation: ");
100 len = redisFormatCommand(&cmd,"key:%08p %b",1234,"foo",3);
101 test_cond(strncmp(cmd,"*2\r\n$6\r\nkey:8p\r\n$3\r\nfoo\r\n",len) == 0 &&
102 len == 4+4+(6+2)+4+(3+2));
103 free(cmd);
104
24f753a8
PN
105 const char *argv[3];
106 argv[0] = "SET";
a1e97d69 107 argv[1] = "foo\0xxx";
24f753a8 108 argv[2] = "bar";
a1e97d69 109 size_t lens[3] = { 3, 7, 3 };
24f753a8
PN
110 int argc = 3;
111
112 test("Format command by passing argc/argv without lengths: ");
113 len = redisFormatCommandArgv(&cmd,argc,argv,NULL);
114 test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 &&
115 len == 4+4+(3+2)+4+(3+2)+4+(3+2));
116 free(cmd);
117
118 test("Format command by passing argc/argv with lengths: ");
119 len = redisFormatCommandArgv(&cmd,argc,argv,lens);
a1e97d69
PN
120 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 &&
121 len == 4+4+(3+2)+4+(7+2)+4+(3+2));
24f753a8
PN
122 free(cmd);
123}
124
9703b1b3 125static void test_blocking_connection(void) {
24f753a8
PN
126 redisContext *c;
127 redisReply *reply;
a1e97d69 128 int major, minor;
24f753a8 129
a1e97d69
PN
130 test("Returns error when host cannot be resolved: ");
131 c = redisConnect((char*)"idontexist.local", 6379);
132 test_cond(c->err == REDIS_ERR_OTHER &&
133 strcmp(c->errstr,"Can't resolve: idontexist.local") == 0);
24f753a8
PN
134 redisFree(c);
135
a1e97d69
PN
136 test("Returns error when the port is not open: ");
137 c = redisConnect((char*)"localhost", 56380);
138 test_cond(c->err == REDIS_ERR_IO &&
139 strcmp(c->errstr,"Connection refused") == 0);
140 redisFree(c);
141
142 __connect(&c);
24f753a8
PN
143 test("Is able to deliver commands: ");
144 reply = redisCommand(c,"PING");
145 test_cond(reply->type == REDIS_REPLY_STATUS &&
146 strcasecmp(reply->str,"pong") == 0)
147 freeReplyObject(reply);
148
149 /* Switch to DB 9 for testing, now that we know we can chat. */
150 reply = redisCommand(c,"SELECT 9");
151 freeReplyObject(reply);
152
153 /* Make sure the DB is emtpy */
154 reply = redisCommand(c,"DBSIZE");
a1e97d69
PN
155 if (reply->type != REDIS_REPLY_INTEGER || reply->integer != 0) {
156 printf("Database #9 is not empty, test can not continue\n");
24f753a8 157 exit(1);
24f753a8
PN
158 }
159 freeReplyObject(reply);
160
161 test("Is a able to send commands verbatim: ");
162 reply = redisCommand(c,"SET foo bar");
163 test_cond (reply->type == REDIS_REPLY_STATUS &&
164 strcasecmp(reply->str,"ok") == 0)
165 freeReplyObject(reply);
166
167 test("%%s String interpolation works: ");
168 reply = redisCommand(c,"SET %s %s","foo","hello world");
169 freeReplyObject(reply);
170 reply = redisCommand(c,"GET foo");
171 test_cond(reply->type == REDIS_REPLY_STRING &&
172 strcmp(reply->str,"hello world") == 0);
173 freeReplyObject(reply);
174
175 test("%%b String interpolation works: ");
176 reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
177 freeReplyObject(reply);
178 reply = redisCommand(c,"GET foo");
179 test_cond(reply->type == REDIS_REPLY_STRING &&
180 memcmp(reply->str,"hello\x00world",11) == 0)
181
182 test("Binary reply length is correct: ");
183 test_cond(reply->len == 11)
184 freeReplyObject(reply);
185
186 test("Can parse nil replies: ");
187 reply = redisCommand(c,"GET nokey");
188 test_cond(reply->type == REDIS_REPLY_NIL)
189 freeReplyObject(reply);
190
191 /* test 7 */
192 test("Can parse integer replies: ");
193 reply = redisCommand(c,"INCR mycounter");
194 test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1)
195 freeReplyObject(reply);
196
197 test("Can parse multi bulk replies: ");
198 freeReplyObject(redisCommand(c,"LPUSH mylist foo"));
199 freeReplyObject(redisCommand(c,"LPUSH mylist bar"));
200 reply = redisCommand(c,"LRANGE mylist 0 -1");
201 test_cond(reply->type == REDIS_REPLY_ARRAY &&
202 reply->elements == 2 &&
203 !memcmp(reply->element[0]->str,"bar",3) &&
204 !memcmp(reply->element[1]->str,"foo",3))
205 freeReplyObject(reply);
206
207 /* m/e with multi bulk reply *before* other reply.
208 * specifically test ordering of reply items to parse. */
209 test("Can handle nested multi bulk replies: ");
210 freeReplyObject(redisCommand(c,"MULTI"));
211 freeReplyObject(redisCommand(c,"LRANGE mylist 0 -1"));
212 freeReplyObject(redisCommand(c,"PING"));
213 reply = (redisCommand(c,"EXEC"));
214 test_cond(reply->type == REDIS_REPLY_ARRAY &&
215 reply->elements == 2 &&
216 reply->element[0]->type == REDIS_REPLY_ARRAY &&
217 reply->element[0]->elements == 2 &&
218 !memcmp(reply->element[0]->element[0]->str,"bar",3) &&
219 !memcmp(reply->element[0]->element[1]->str,"foo",3) &&
220 reply->element[1]->type == REDIS_REPLY_STATUS &&
221 strcasecmp(reply->element[1]->str,"pong") == 0);
222 freeReplyObject(reply);
a1e97d69
PN
223
224 {
225 /* Find out Redis version to determine the path for the next test */
226 const char *field = "redis_version:";
227 char *p, *eptr;
228
229 reply = redisCommand(c,"INFO");
230 p = strstr(reply->str,field);
231 major = strtol(p+strlen(field),&eptr,10);
232 p = eptr+1; /* char next to the first "." */
233 minor = strtol(p,&eptr,10);
234 freeReplyObject(reply);
235 }
236
237 test("Returns I/O error when the connection is lost: ");
238 reply = redisCommand(c,"QUIT");
239 if (major >= 2 && minor > 0) {
240 /* > 2.0 returns OK on QUIT and read() should be issued once more
241 * to know the descriptor is at EOF. */
242 test_cond(strcasecmp(reply->str,"OK") == 0 &&
243 redisGetReply(c,(void**)&reply) == REDIS_ERR);
244 freeReplyObject(reply);
245 } else {
246 test_cond(reply == NULL);
247 }
248
249 /* On 2.0, QUIT will cause the connection to be closed immediately and
250 * the read(2) for the reply on QUIT will set the error to EOF.
251 * On >2.0, QUIT will return with OK and another read(2) needed to be
252 * issued to find out the socket was closed by the server. In both
253 * conditions, the error will be set to EOF. */
254 assert(c->err == REDIS_ERR_EOF &&
255 strcmp(c->errstr,"Server closed the connection") == 0);
9703b1b3 256 redisFree(c);
a1e97d69 257
9703b1b3
PN
258 __connect(&c);
259 test("Returns I/O error on socket timeout: ");
260 struct timeval tv = { 0, 1000 };
261 assert(redisSetTimeout(c,tv) == REDIS_OK);
262 test_cond(redisGetReply(c,(void**)&reply) == REDIS_ERR &&
263 c->err == REDIS_ERR_IO && errno == EAGAIN);
a1e97d69 264 redisFree(c);
9703b1b3
PN
265
266 /* Context should be connected */
a1e97d69 267 __connect(&c);
24f753a8
PN
268}
269
9703b1b3 270static void test_reply_reader(void) {
24f753a8 271 void *reader;
afc156c2 272 void *reply;
24f753a8
PN
273 char *err;
274 int ret;
275
276 test("Error handling in reply parser: ");
afc156c2 277 reader = redisReplyReaderCreate();
24f753a8
PN
278 redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
279 ret = redisReplyReaderGetReply(reader,NULL);
280 err = redisReplyReaderGetError(reader);
281 test_cond(ret == REDIS_ERR &&
a1e97d69 282 strcasecmp(err,"Protocol error, got \"@\" as reply type byte") == 0);
24f753a8
PN
283 redisReplyReaderFree(reader);
284
285 /* when the reply already contains multiple items, they must be free'd
286 * on an error. valgrind will bark when this doesn't happen. */
287 test("Memory cleanup in reply parser: ");
afc156c2 288 reader = redisReplyReaderCreate();
24f753a8
PN
289 redisReplyReaderFeed(reader,(char*)"*2\r\n",4);
290 redisReplyReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
291 redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
292 ret = redisReplyReaderGetReply(reader,NULL);
293 err = redisReplyReaderGetError(reader);
294 test_cond(ret == REDIS_ERR &&
a1e97d69
PN
295 strcasecmp(err,"Protocol error, got \"@\" as reply type byte") == 0);
296 redisReplyReaderFree(reader);
297
298 test("Set error on nested multi bulks with depth > 1: ");
299 reader = redisReplyReaderCreate();
300 redisReplyReaderFeed(reader,(char*)"*1\r\n",4);
301 redisReplyReaderFeed(reader,(char*)"*1\r\n",4);
302 redisReplyReaderFeed(reader,(char*)"*1\r\n",4);
303 ret = redisReplyReaderGetReply(reader,NULL);
304 err = redisReplyReaderGetError(reader);
305 test_cond(ret == REDIS_ERR &&
306 strncasecmp(err,"No support for",14) == 0);
24f753a8 307 redisReplyReaderFree(reader);
afc156c2
PN
308
309 test("Works with NULL functions for reply: ");
310 reader = redisReplyReaderCreate();
311 redisReplyReaderSetReplyObjectFunctions(reader,NULL);
312 redisReplyReaderFeed(reader,(char*)"+OK\r\n",5);
313 ret = redisReplyReaderGetReply(reader,&reply);
314 test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
315 redisReplyReaderFree(reader);
57c9babd
PN
316
317 test("Works when a single newline (\\r\\n) covers two calls to feed: ");
318 reader = redisReplyReaderCreate();
319 redisReplyReaderSetReplyObjectFunctions(reader,NULL);
320 redisReplyReaderFeed(reader,(char*)"+OK\r",4);
321 ret = redisReplyReaderGetReply(reader,&reply);
322 assert(ret == REDIS_OK && reply == NULL);
323 redisReplyReaderFeed(reader,(char*)"\n",1);
324 ret = redisReplyReaderGetReply(reader,&reply);
325 test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
326 redisReplyReaderFree(reader);
9703b1b3
PN
327
328 test("Properly reset state after protocol error: ");
329 reader = redisReplyReaderCreate();
330 redisReplyReaderSetReplyObjectFunctions(reader,NULL);
331 redisReplyReaderFeed(reader,(char*)"x",1);
332 ret = redisReplyReaderGetReply(reader,&reply);
333 assert(ret == REDIS_ERR);
334 ret = redisReplyReaderGetReply(reader,&reply);
335 test_cond(ret == REDIS_OK && reply == NULL)
24f753a8
PN
336}
337
9703b1b3
PN
338static void test_throughput(void) {
339 int i, num;
24f753a8
PN
340 long long t1, t2;
341 redisContext *c = blocking_context;
342 redisReply **replies;
343
344 test("Throughput:\n");
345 for (i = 0; i < 500; i++)
346 freeReplyObject(redisCommand(c,"LPUSH mylist foo"));
347
9703b1b3
PN
348 num = 1000;
349 replies = malloc(sizeof(redisReply*)*num);
24f753a8 350 t1 = usec();
9703b1b3 351 for (i = 0; i < num; i++) {
24f753a8
PN
352 replies[i] = redisCommand(c,"PING");
353 assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);
354 }
355 t2 = usec();
9703b1b3 356 for (i = 0; i < num; i++) freeReplyObject(replies[i]);
24f753a8 357 free(replies);
9703b1b3 358 printf("\t(%dx PING: %.3fs)\n", num, (t2-t1)/1000000.0);
24f753a8 359
9703b1b3 360 replies = malloc(sizeof(redisReply*)*num);
24f753a8 361 t1 = usec();
9703b1b3 362 for (i = 0; i < num; i++) {
24f753a8
PN
363 replies[i] = redisCommand(c,"LRANGE mylist 0 499");
364 assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);
365 assert(replies[i] != NULL && replies[i]->elements == 500);
366 }
367 t2 = usec();
9703b1b3
PN
368 for (i = 0; i < num; i++) freeReplyObject(replies[i]);
369 free(replies);
370 printf("\t(%dx LRANGE with 500 elements: %.3fs)\n", num, (t2-t1)/1000000.0);
371
372 num = 10000;
373 replies = malloc(sizeof(redisReply*)*num);
374 for (i = 0; i < num; i++)
375 redisAppendCommand(c,"PING");
376 t1 = usec();
377 for (i = 0; i < num; i++) {
378 assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);
379 assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);
380 }
381 t2 = usec();
382 for (i = 0; i < num; i++) freeReplyObject(replies[i]);
383 free(replies);
384 printf("\t(%dx PING (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
385
386 replies = malloc(sizeof(redisReply*)*num);
387 for (i = 0; i < num; i++)
388 redisAppendCommand(c,"LRANGE mylist 0 499");
389 t1 = usec();
390 for (i = 0; i < num; i++) {
391 assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);
392 assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);
393 assert(replies[i] != NULL && replies[i]->elements == 500);
394 }
395 t2 = usec();
396 for (i = 0; i < num; i++) freeReplyObject(replies[i]);
24f753a8 397 free(replies);
9703b1b3 398 printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
24f753a8
PN
399}
400
9703b1b3 401static void cleanup(void) {
24f753a8
PN
402 redisContext *c = blocking_context;
403 redisReply *reply;
404
405 /* Make sure we're on DB 9 */
406 reply = redisCommand(c,"SELECT 9");
407 assert(reply != NULL); freeReplyObject(reply);
408 reply = redisCommand(c,"FLUSHDB");
409 assert(reply != NULL); freeReplyObject(reply);
410 redisFree(c);
411}
412
413// static long __test_callback_flags = 0;
414// static void __test_callback(redisContext *c, void *privdata) {
415// ((void)c);
416// /* Shift to detect execution order */
417// __test_callback_flags <<= 8;
418// __test_callback_flags |= (long)privdata;
419// }
420//
421// static void __test_reply_callback(redisContext *c, redisReply *reply, void *privdata) {
422// ((void)c);
423// /* Shift to detect execution order */
424// __test_callback_flags <<= 8;
425// __test_callback_flags |= (long)privdata;
426// if (reply) freeReplyObject(reply);
427// }
428//
429// static redisContext *__connect_nonblock() {
430// /* Reset callback flags */
431// __test_callback_flags = 0;
432// return redisConnectNonBlock("127.0.0.1", 6379, NULL);
433// }
434//
435// static void test_nonblocking_connection() {
436// redisContext *c;
437// int wdone = 0;
438//
439// test("Calls command callback when command is issued: ");
440// c = __connect_nonblock();
441// redisSetCommandCallback(c,__test_callback,(void*)1);
442// redisCommand(c,"PING");
443// test_cond(__test_callback_flags == 1);
444// redisFree(c);
445//
446// test("Calls disconnect callback on redisDisconnect: ");
447// c = __connect_nonblock();
448// redisSetDisconnectCallback(c,__test_callback,(void*)2);
449// redisDisconnect(c);
450// test_cond(__test_callback_flags == 2);
451// redisFree(c);
452//
453// test("Calls disconnect callback and free callback on redisFree: ");
454// c = __connect_nonblock();
455// redisSetDisconnectCallback(c,__test_callback,(void*)2);
456// redisSetFreeCallback(c,__test_callback,(void*)4);
457// redisFree(c);
458// test_cond(__test_callback_flags == ((2 << 8) | 4));
459//
460// test("redisBufferWrite against empty write buffer: ");
461// c = __connect_nonblock();
462// test_cond(redisBufferWrite(c,&wdone) == REDIS_OK && wdone == 1);
463// redisFree(c);
464//
465// test("redisBufferWrite against not yet connected fd: ");
466// c = __connect_nonblock();
467// redisCommand(c,"PING");
468// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&
469// strncmp(c->error,"write:",6) == 0);
470// redisFree(c);
471//
472// test("redisBufferWrite against closed fd: ");
473// c = __connect_nonblock();
474// redisCommand(c,"PING");
475// redisDisconnect(c);
476// test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&
477// strncmp(c->error,"write:",6) == 0);
478// redisFree(c);
479//
480// test("Process callbacks in the right sequence: ");
481// c = __connect_nonblock();
482// redisCommandWithCallback(c,__test_reply_callback,(void*)1,"PING");
483// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING");
484// redisCommandWithCallback(c,__test_reply_callback,(void*)3,"PING");
485//
486// /* Write output buffer */
487// wdone = 0;
488// while(!wdone) {
489// usleep(500);
490// redisBufferWrite(c,&wdone);
491// }
492//
493// /* Read until at least one callback is executed (the 3 replies will
494// * arrive in a single packet, causing all callbacks to be executed in
495// * a single pass). */
496// while(__test_callback_flags == 0) {
497// assert(redisBufferRead(c) == REDIS_OK);
498// redisProcessCallbacks(c);
499// }
500// test_cond(__test_callback_flags == 0x010203);
501// redisFree(c);
502//
503// test("redisDisconnect executes pending callbacks with NULL reply: ");
504// c = __connect_nonblock();
505// redisSetDisconnectCallback(c,__test_callback,(void*)1);
506// redisCommandWithCallback(c,__test_reply_callback,(void*)2,"PING");
507// redisDisconnect(c);
508// test_cond(__test_callback_flags == 0x0201);
509// redisFree(c);
510// }
511
512int main(int argc, char **argv) {
513 if (argc > 1) {
514 if (strcmp(argv[1],"-s") == 0)
515 use_unix = 1;
516 }
517
518 signal(SIGPIPE, SIG_IGN);
519 test_format_commands();
520 test_blocking_connection();
521 test_reply_reader();
522 // test_nonblocking_connection();
523 test_throughput();
524 cleanup();
525
526 if (fails == 0) {
527 printf("ALL TESTS PASSED\n");
528 } else {
529 printf("*** %d TESTS FAILED ***\n", fails);
530 }
531 return 0;
532}