// ---------------------------------------------------------------------- // File: formatting.cc // Author: Georgios Bitzes - CERN // ---------------------------------------------------------------------- /************************************************************************ * qclient - A simple redis C++ client with support for redirects * * Copyright (C) 2016 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ #include "gtest/gtest.h" #include "qclient/QClient.hh" #include "qclient/Formatting.hh" #include "qclient/ResponseBuilder.hh" #include "shared/SharedSerialization.hh" using namespace qclient; void setStr(redisReplyPtr reply, const std::string &str) { reply->str = (char*) str.c_str(); // evil const cast reply->len = str.size(); } TEST(DescribeRedisReply, BasicSanity1) { ASSERT_EQ(describeRedisReply(redisReplyPtr()), "nullptr"); redisReplyPtr reply = redisReplyPtr(new redisReply()); reply->type = REDIS_REPLY_NIL; ASSERT_EQ(describeRedisReply(reply), "(nil)"); reply->type = REDIS_REPLY_INTEGER; reply->integer = 13; ASSERT_EQ(describeRedisReply(reply), "(integer) 13"); std::string str = "OK"; reply->type = REDIS_REPLY_STATUS; setStr(reply, str); ASSERT_EQ(describeRedisReply(reply), "OK"); reply->type = REDIS_REPLY_STRING; ASSERT_EQ(describeRedisReply(reply), "\"OK\""); str = "abc111"; str.push_back('\0'); str.push_back('\0'); str += "\xAB" "aaaaaaa"; setStr(reply, str); ASSERT_EQ(describeRedisReply(reply), "\"abc111\\x00\\x00\\xABaaaaaaa\""); reply->str = nullptr; std::string description; description = qclient::describeRedisReply("*2\r\n$6\r\nnext:d\r\n*3\r\n$1\r\na\r\n$1\r\nb\r\n$1\r\nc\r\n"); std::cout << description << std::endl; ASSERT_EQ(description, "1) \"next:d\"\n2) 1) \"a\"\n 2) \"b\"\n 3) \"c\"\n"); description = qclient::describeRedisReply("*2\r\n$6\r\nnext:d\r\n*3\r\n*2\r\n:1337\r\n$2\r\nbb\r\n$1\r\nb\r\n$1\r\nc\r\n"); std::cout << description << std::endl; ASSERT_EQ(description, "1) \"next:d\"\n2) 1) 1) (integer) 1337\n 2) \"bb\"\n 2) \"b\"\n 3) \"c\"\n"); description = qclient::describeRedisReply("*2\r\n$6\r\nnext:d\r\n*0\r\n"); std::cout << description << std::endl; ASSERT_EQ(description, "1) \"next:d\"\n2) (empty list or set)\n"); reply->type = 999; ASSERT_EQ(describeRedisReply(reply), "!!! unknown reply type !!!"); } TEST(Formatting, SerializeString) { ASSERT_EQ(Formatting::serialize("asdf"), "$4\r\nasdf\r\n"); } TEST(Formatting, SerializeVector) { ASSERT_EQ(Formatting::serializeVector("asdf", "bbb", "aaaa"), "*3\r\n" "$4\r\nasdf\r\n" "$3\r\nbbb\r\n" "$4\r\naaaa\r\n" ); ASSERT_EQ(Formatting::serializeVector("asdf", 1234), "*2\r\n" "$4\r\nasdf\r\n" ":1234\r\n" ); } TEST(Formatting, SerializeIntVector) { std::vector vec = {4, 9, 8}; ASSERT_EQ(Formatting::serialize(vec), "*3\r\n" ":4\r\n" ":9\r\n" ":8\r\n" ); redisReplyPtr reply = ResponseBuilder::parseRedisEncodedString(Formatting::serialize(vec)); ASSERT_EQ(describeRedisReply(reply), "1) (integer) 4\n" "2) (integer) 9\n" "3) (integer) 8\n" ); } TEST(Formatting, SerializeStringMap) { std::map map; map["i like"] = "pickles"; map["asdf"] = "1234"; ASSERT_EQ(Formatting::serialize(map), "*4\r\n" "$4\r\nasdf\r\n" "$4\r\n1234\r\n" "$6\r\ni like\r\n" "$7\r\npickles\r\n" ); } TEST(Formatting, DescribeEncodedString) { ASSERT_EQ( "(integer) 5", qclient::ResponseBuilder::parseAndDescribeRedisEncodedString(":5\r\n") ); ASSERT_EQ( "nullptr", qclient::ResponseBuilder::parseAndDescribeRedisEncodedString("aaaaaaaaaa") ); } TEST(SharedSerialization, BatchUpdate) { std::map batch; batch["a"] = "bb"; batch["ccc"] = "dddd"; batch["eeeee"] = "ffffff"; std::map parsed; ASSERT_TRUE(qclient::parseBatch(qclient::serializeBatch(batch), parsed)); ASSERT_EQ(batch, parsed); }