- __connect(&c);
- test("Returns I/O error when the connection is lost: ");
- reply = redisCommand(c,"QUIT");
- test_cond(strcasecmp(reply->str,"OK") == 0 && redisCommand(c,"PING") == NULL);
-
- /* Two conditions may happen, depending on the type of connection.
- * When connected via TCP, the socket will not yet be aware of the closed
- * connection and the write(2) call will succeed, but the read(2) will
- * result in an EOF. When connected via Unix sockets, the socket will be
- * immediately aware that it was closed and fail on the write(2) call. */
- if (use_unix) {
- fprintf(stderr,"Error: %s\n", c->errstr);
- assert(c->err == REDIS_ERR_IO &&
- strcmp(c->errstr,"Broken pipe") == 0);
- } else {
- fprintf(stderr,"Error: %s\n", c->errstr);
- assert(c->err == REDIS_ERR_EOF &&
- strcmp(c->errstr,"Server closed the connection") == 0);
- }
+ test("Error handling in reply parser: ");
+ reader = redisReaderCreate();
+ redisReaderFeed(reader,(char*)"@foo\r\n",6);
+ ret = redisReaderGetReply(reader,NULL);
+ test_cond(ret == REDIS_ERR &&
+ strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
+ redisReaderFree(reader);
+
+ /* when the reply already contains multiple items, they must be free'd
+ * on an error. valgrind will bark when this doesn't happen. */
+ test("Memory cleanup in reply parser: ");
+ reader = redisReaderCreate();
+ redisReaderFeed(reader,(char*)"*2\r\n",4);
+ redisReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
+ redisReaderFeed(reader,(char*)"@foo\r\n",6);
+ ret = redisReaderGetReply(reader,NULL);
+ test_cond(ret == REDIS_ERR &&
+ strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
+ redisReaderFree(reader);
+
+ test("Set error on nested multi bulks with depth > 2: ");
+ reader = redisReaderCreate();
+ redisReaderFeed(reader,(char*)"*1\r\n",4);
+ redisReaderFeed(reader,(char*)"*1\r\n",4);
+ redisReaderFeed(reader,(char*)"*1\r\n",4);
+ redisReaderFeed(reader,(char*)"*1\r\n",4);
+ ret = redisReaderGetReply(reader,NULL);
+ test_cond(ret == REDIS_ERR &&
+ strncasecmp(reader->errstr,"No support for",14) == 0);
+ redisReaderFree(reader);
+
+ test("Works with NULL functions for reply: ");
+ reader = redisReaderCreate();
+ reader->fn = NULL;
+ redisReaderFeed(reader,(char*)"+OK\r\n",5);
+ ret = redisReaderGetReply(reader,&reply);
+ test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
+ redisReaderFree(reader);
+
+ test("Works when a single newline (\\r\\n) covers two calls to feed: ");
+ reader = redisReaderCreate();
+ reader->fn = NULL;
+ redisReaderFeed(reader,(char*)"+OK\r",4);
+ ret = redisReaderGetReply(reader,&reply);
+ assert(ret == REDIS_OK && reply == NULL);
+ redisReaderFeed(reader,(char*)"\n",1);
+ ret = redisReaderGetReply(reader,&reply);
+ test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
+ redisReaderFree(reader);
+
+ test("Don't reset state after protocol error: ");
+ reader = redisReaderCreate();
+ reader->fn = NULL;
+ redisReaderFeed(reader,(char*)"x",1);
+ ret = redisReaderGetReply(reader,&reply);
+ assert(ret == REDIS_ERR);
+ ret = redisReaderGetReply(reader,&reply);
+ test_cond(ret == REDIS_ERR && reply == NULL);
+ redisReaderFree(reader);
+
+ /* Regression test for issue #45 on GitHub. */
+ test("Don't do empty allocation for empty multi bulk: ");
+ reader = redisReaderCreate();
+ redisReaderFeed(reader,(char*)"*0\r\n",4);
+ ret = redisReaderGetReply(reader,&reply);
+ test_cond(ret == REDIS_OK &&
+ ((redisReply*)reply)->type == REDIS_REPLY_ARRAY &&
+ ((redisReply*)reply)->elements == 0);