diff options
Diffstat (limited to 'searchlib/src/tests/common/packets/packets_test.cpp')
-rw-r--r-- | searchlib/src/tests/common/packets/packets_test.cpp | 705 |
1 files changed, 705 insertions, 0 deletions
diff --git a/searchlib/src/tests/common/packets/packets_test.cpp b/searchlib/src/tests/common/packets/packets_test.cpp new file mode 100644 index 00000000000..443436537e1 --- /dev/null +++ b/searchlib/src/tests/common/packets/packets_test.cpp @@ -0,0 +1,705 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/fastos/fastos.h> +#include <vespa/log/log.h> +LOG_SETUP("packets_test"); + +#include <vespa/searchlib/common/mapnames.h> +#include <vespa/searchlib/common/packets.h> +#include <vector> +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/util/stringfmt.h> + +using namespace search::fs4transport; + +// ---------------------------------------------------------------------------- +// +// Utilities +// +// ---------------------------------------------------------------------------- + +#define QRF_RANKTYPE QRF_RANKTYPE_DOUBLE + +#define PCODE_BEGIN PCODE_EOL +#define PCODE_END PCODE_LastCode + +class MyPersistentPacketStreamer : public FS4PersistentPacketStreamer { +public: + MyPersistentPacketStreamer() : + FS4PersistentPacketStreamer(FS4PacketFactory::CreateFS4Packet) { + // empty + } + + uint32_t getChannelId(uint32_t pcode, uint32_t chid) { + return HasChannelID(pcode) ? chid : -1u; + } +}; + +FNET_Packet * +testEncodeDecode(FS4PersistentPacketStreamer &streamer, FNET_Packet &packet) +{ + FNET_Context ctx; + FNET_DataBuffer buf; + buf.WriteInt32(0xdeadbeef); // buffers can have extra data at the front. + streamer.Encode(&packet, 1u, &buf); + buf.DataToDead(sizeof(uint32_t)); + + FNET_DataBuffer lhs; + lhs.WriteBytes(buf.GetData(), buf.GetDataLen()); + + buf.WriteInt32(0xdeadbeef); // buffers can have extra data at the end. + + bool broken; + uint32_t plen, pcode, chid; + MyPersistentPacketStreamer myStreamer; + EXPECT_TRUE(streamer.GetPacketInfo(&buf, &plen, &pcode, &chid, &broken)); + if ((pcode & ~PCODE_MASK) == 0) { + EXPECT_EQUAL(packet.GetLength(), plen); + } + EXPECT_EQUAL(packet.GetPCODE() & PCODE_MASK, pcode & PCODE_MASK); + EXPECT_EQUAL(myStreamer.getChannelId(pcode, 1u), chid); + + FNET_Packet *ret = streamer.Decode(&buf, plen, pcode, ctx); + ASSERT_TRUE(ret); + if (ret->GetPCODE() == (pcode & PCODE_MASK)) { + FNET_DataBuffer rhs; + streamer.Encode(ret, 1u, &rhs); + if (!EXPECT_TRUE(lhs.Equals(&rhs))) { + lhs.HexDump(); + rhs.HexDump(); + } + } else { + // Packet was transcoded. + } + return ret; +} + +FNET_Packet * +testEncodeDecode(FNET_Packet &packet) +{ + return testEncodeDecode(FS4PersistentPacketStreamer::Instance, packet); +} + +void fillProperties(FS4Properties &props, const std::string &name, + uint32_t len) { + props.setName(name); + props.allocEntries(len); + for (uint32_t i = 0; i < len; ++i) { + std::string key = vespalib::make_string("key%d", i); + props.setKey(i, key); + + std::string val = vespalib::make_string("val%d", i); + props.setValue(i, val); + } +} + +void testProperties(FS4Properties &props, const std::string &name, + uint32_t len) { + EXPECT_EQUAL(name, props.getName()); + EXPECT_EQUAL(name.size(), props.getNameLen()); + for (uint32_t i = 0; i < len; ++i) { + std::string key = vespalib::make_string("key%d", i); + EXPECT_EQUAL(key, std::string(props.getKey(i), props.getKeyLen(i))); + + std::string val = vespalib::make_string("val%d", i); + EXPECT_EQUAL(val, + std::string(props.getValue(i), props.getValueLen(i))); + } +} + + +// ---------------------------------------------------------------------------- +// +// Tests +// +// ---------------------------------------------------------------------------- + +document::GlobalId gid0("aaaaaaaaaaaa"); +document::GlobalId gid1("bbbbbbbbbbbb"); + +TEST("testPacketArray") { + PacketArray arr; + for (uint32_t i = 0; i < 32; ++i) { + EXPECT_EQUAL(i, arr.Length()); + arr.Add(new FNET_ControlPacket(i)); + EXPECT_EQUAL(i, static_cast<FNET_ControlPacket&>(*arr.Array()[i]).GetCommand()); + } + for (uint32_t i = 0; i < arr.Length(); ++i) { + delete static_cast<FNET_ControlPacket *>(arr.Array()[i]); + } +} + +TEST("testPacketFactory") { + ASSERT_TRUE(FS4PacketFactory::CreateFS4Packet(PCODE_BEGIN - 1) == NULL); + + ASSERT_TRUE(FS4PacketFactory::CreateFS4Packet(PCODE_END) == NULL); + + for (uint32_t pcode = PCODE_BEGIN; pcode < PCODE_END; ++pcode) { + if ((pcode != PCODE_MLD_QUERYRESULT2_NOTUSED) && + (pcode != PCODE_QUERY_NOTUSED) && + (pcode != PCODE_QUERY2_NOTUSED) && + (pcode != PCODE_MLD_GETDOCSUMS2_NOTUSED)) + { + std::unique_ptr<FNET_Packet> aptr(FS4PacketFactory::CreateFS4Packet(pcode)); + ASSERT_TRUE(aptr.get() != NULL); + EXPECT_EQUAL(pcode, aptr->GetPCODE()); + } + } +} + +TEST("testPersistentPacketStreamer") { + for (uint32_t pcode = PCODE_BEGIN; pcode < PCODE_END; ++pcode) { + if ((pcode == PCODE_QUERYX) || + (pcode != PCODE_MLD_QUERYRESULT2_NOTUSED) || + (pcode != PCODE_MLD_GETDOCSUMS2_NOTUSED)) + { + continue; + } + std::unique_ptr<FNET_Packet> arg(FS4PacketFactory::CreateFS4Packet(pcode)); + std::unique_ptr<FNET_Packet> ret(testEncodeDecode(FS4PersistentPacketStreamer::Instance, *arg)); + EXPECT_TRUE(ret.get() != NULL); + + FNET_Packet *raw = testEncodeDecode(FS4PersistentPacketStreamer::Instance, + *FS4PacketFactory::CreateFS4Packet(pcode)); + EXPECT_TRUE(raw != NULL); + } +} + +TEST("testProperties") { + FS4Properties src; + fillProperties(src, "foo", 32u); + testProperties(src, "foo", 32u); + + FNET_DataBuffer buf; + src.encode(buf); + FNET_DataBuffer lhs; + lhs.WriteBytes(buf.GetData(), buf.GetDataLen()); + + uint32_t len = buf.GetDataLen(); + FS4Properties dst; + dst.decode(buf, len); + EXPECT_EQUAL(src.getLength(), dst.getLength()); + + testProperties(dst, "foo", 32u); + + FNET_DataBuffer rhs; + dst.encode(rhs); + EXPECT_TRUE(lhs.Equals(&rhs)); +} + +TEST("testEol") { + FS4Packet_EOL *src = dynamic_cast<FS4Packet_EOL*>(FS4PacketFactory::CreateFS4Packet(PCODE_EOL)); + ASSERT_TRUE(src != NULL); + + std::vector<FNET_Packet*> lst { src, testEncodeDecode(*src) }; + + for (FNET_Packet * packet : lst) { + FS4Packet_EOL *ptr = dynamic_cast<FS4Packet_EOL*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_EOL, ptr->GetPCODE()); + EXPECT_EQUAL(0u, ptr->GetLength()); + + delete ptr; + } +} + +TEST("testError") { + FS4Packet_ERROR *src = dynamic_cast<FS4Packet_ERROR*>(FS4PacketFactory::CreateFS4Packet(PCODE_ERROR)); + ASSERT_TRUE(src != NULL); + src->_errorCode = 1u; + src->setErrorMessage("foo"); + + std::vector<FNET_Packet*> lst { src, testEncodeDecode(*src) }; + + for (FNET_Packet * packet : lst) { + FS4Packet_ERROR *ptr = dynamic_cast<FS4Packet_ERROR*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_ERROR, ptr->GetPCODE()); + EXPECT_EQUAL(11u, ptr->GetLength()); + EXPECT_EQUAL(1u, ptr->_errorCode); + EXPECT_EQUAL("foo", ptr->_message); + + delete ptr; + } +} + +TEST("testDocsum") { + FS4Packet_DOCSUM *src = dynamic_cast<FS4Packet_DOCSUM*>(FS4PacketFactory::CreateFS4Packet(PCODE_DOCSUM)); + ASSERT_TRUE(src != NULL); + src->setGid(gid0); + src->SetBuf("foo", 3u); + + std::vector<FNET_Packet*> lst { src, testEncodeDecode(*src) }; + + for (FNET_Packet * packet : lst) { + FS4Packet_DOCSUM *ptr = dynamic_cast<FS4Packet_DOCSUM*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_DOCSUM, ptr->GetPCODE()); + EXPECT_EQUAL(3u + 12u, ptr->GetLength()); + EXPECT_EQUAL(gid0, ptr->getGid()); + EXPECT_EQUAL("foo", std::string(ptr->getBuf().c_str(), ptr->getBuf().size())); + + delete ptr; + } +} + +TEST("testMonitorQueryX") { + FS4Packet_MONITORQUERYX *src = dynamic_cast<FS4Packet_MONITORQUERYX*>(FS4PacketFactory::CreateFS4Packet(PCODE_MONITORQUERYX)); + ASSERT_TRUE(src != NULL); + src->_qflags = 1u; + + std::vector<FNET_Packet*> lst; + for (uint32_t i = MQF_QFLAGS, len = (uint32_t)(MQF_QFLAGS << 1); i < len; ++i) { + if (i & ~FNET_MQF_SUPPORTED_MASK) { + continue; // not supported; + } + src->_features = i; + lst.push_back(testEncodeDecode(*src)); + } + src->_features = (uint32_t)-1; + lst.push_back(src); + + for (FNET_Packet * packet : lst) { + FS4Packet_MONITORQUERYX *ptr = dynamic_cast<FS4Packet_MONITORQUERYX*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_MONITORQUERYX, ptr->GetPCODE()); + EXPECT_EQUAL(ptr->_features & MQF_QFLAGS ? 1u : 0u, ptr->_qflags); + + delete ptr; + } +} + +TEST("testMonitorResultX") { + FS4Packet_MONITORRESULTX *src = dynamic_cast<FS4Packet_MONITORRESULTX*>(FS4PacketFactory::CreateFS4Packet(PCODE_MONITORRESULTX)); + ASSERT_TRUE(src != NULL); + src->_partid = 1u; + src->_timestamp = 2u; + src->_totalNodes = 3u; + src->_activeNodes = 4u; + src->_totalParts = 5u; + src->_activeParts = 6u; + src->_rflags = 7u; + + std::vector<FNET_Packet*> lst; + for (uint32_t i = MRF_MLD, len = (uint32_t)(MRF_RFLAGS << 1); i < len; ++i) { + if (i & ~FNET_MRF_SUPPORTED_MASK) { + continue; // not supported; + } + src->_features = i; + lst.push_back(testEncodeDecode(*src)); + } + src->_features = (uint32_t)-1; + lst.push_back(src); + + for (FNET_Packet * packet : lst) { + FS4Packet_MONITORRESULTX *ptr = dynamic_cast<FS4Packet_MONITORRESULTX*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_MONITORRESULTX, ptr->GetPCODE()); + EXPECT_EQUAL(1u, ptr->_partid); + EXPECT_EQUAL(2u, ptr->_timestamp); + EXPECT_EQUAL(ptr->_features & MRF_MLD ? 3u : 0u, ptr->_totalNodes); + EXPECT_EQUAL(ptr->_features & MRF_MLD ? 4u : 0u, ptr->_activeNodes); + EXPECT_EQUAL(ptr->_features & MRF_MLD ? 5u : 0u, ptr->_totalParts); + EXPECT_EQUAL(ptr->_features & MRF_MLD ? 6u : 0u, ptr->_activeParts); + EXPECT_EQUAL(ptr->_features & MRF_RFLAGS ? 7u : 0u, ptr->_rflags); + + delete ptr; + } +} + +TEST("testClearCaches") { + FS4Packet_CLEARCACHES *src = dynamic_cast<FS4Packet_CLEARCACHES*>(FS4PacketFactory::CreateFS4Packet(PCODE_CLEARCACHES)); + ASSERT_TRUE(src != NULL); + + std::vector<FNET_Packet*> lst { src, testEncodeDecode(*src) }; + + for (FNET_Packet * packet : lst) { + FS4Packet_CLEARCACHES *ptr = dynamic_cast<FS4Packet_CLEARCACHES*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_CLEARCACHES, ptr->GetPCODE()); + EXPECT_EQUAL(0u, ptr->GetLength()); + + delete ptr; + } +} + +TEST("testQueueLen") { + FS4Packet_QUEUELEN *src = dynamic_cast<FS4Packet_QUEUELEN*>(FS4PacketFactory::CreateFS4Packet(PCODE_QUEUELEN)); + ASSERT_TRUE(src != NULL); + src->_queueLen = 1u; + src->_dispatchers = 2u; + + std::vector<FNET_Packet*> lst { src, testEncodeDecode(*src) }; + + for (FNET_Packet * packet : lst) { + FS4Packet_QUEUELEN *ptr = dynamic_cast<FS4Packet_QUEUELEN*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_QUEUELEN, ptr->GetPCODE()); + EXPECT_EQUAL(8u, ptr->GetLength()); + EXPECT_EQUAL(1u, ptr->_queueLen); + EXPECT_EQUAL(2u, ptr->_dispatchers); + + delete ptr; + } +} + +TEST("testQueryResultX") { + FS4Packet_QUERYRESULTX *src = dynamic_cast<FS4Packet_QUERYRESULTX*>(FS4PacketFactory::CreateFS4Packet(PCODE_QUERYRESULTX)); + ASSERT_TRUE(src != NULL); + src->_offset = 1u; + src->_totNumDocs = 2u; + src->_maxRank = (search::HitRank)3; + src->setDistributionKey(4u); + src->_coverageDocs = 6u; + src->_activeDocs = 7u; + uint32_t sortIndex[3] = { 0u, 1u, 3u /* size of data */}; // numDocs + 1 + src->SetSortDataRef(2, sortIndex, "foo"); + src->SetAggrDataRef("bar", 3u); + src->SetGroupDataRef("baz", 3u); + src->AllocateHits(2); + src->_hits[0]._gid = gid0; + src->_hits[0]._metric = (search::HitRank)2; + src->_hits[0]._partid = 3u; + src->_hits[0].setDistributionKey(4u); + src->_hits[1]._gid = gid1; + src->_hits[1]._metric = (search::HitRank)3; + src->_hits[1]._partid = 4u; + src->_hits[1].setDistributionKey(5u); + + std::vector<FNET_Packet*> lst; + for (uint32_t i = QRF_MLD, len = (uint32_t)(QRF_GROUPDATA << 1); i < len; ++i) { + if (i & ~FNET_QRF_SUPPORTED_MASK) { + continue; // not supported; + } + src->_features = i; + lst.push_back(testEncodeDecode(*src)); + } + src->_features = (uint32_t)-1; + lst.push_back(src); + + for (FNET_Packet * packet : lst) { + FS4Packet_QUERYRESULTX *ptr = dynamic_cast<FS4Packet_QUERYRESULTX*>(packet); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_QUERYRESULTX, ptr->GetPCODE()); + + EXPECT_EQUAL(1u, ptr->_offset); + EXPECT_EQUAL(2u, ptr->_totNumDocs); + EXPECT_EQUAL((search::HitRank)3, ptr->_maxRank); + EXPECT_EQUAL(4u, ptr->getDistributionKey()); + EXPECT_EQUAL(ptr->_features & QRF_COVERAGE ? 6u : 0u, ptr->_coverageDocs); + EXPECT_EQUAL(ptr->_features & QRF_COVERAGE ? 7u : 0u, ptr->_activeDocs); + if (ptr->_features & QRF_SORTDATA) { + EXPECT_EQUAL(0u, ptr->_sortIndex[0]); + EXPECT_EQUAL(1u, ptr->_sortIndex[1]); + EXPECT_EQUAL(3u, ptr->_sortIndex[2]); + EXPECT_EQUAL("foo", std::string(ptr->_sortData, ptr->_sortIndex[2])); + } else { + EXPECT_EQUAL((void*)NULL, ptr->_sortIndex); + EXPECT_EQUAL((void*)NULL, ptr->_sortData); + } + if (ptr->_features & QRF_AGGRDATA) { + EXPECT_EQUAL("bar", std::string(ptr->_aggrData, ptr->_aggrDataLen)); + } else { + EXPECT_EQUAL(0u, ptr->_aggrDataLen); + EXPECT_EQUAL((void*)NULL, ptr->_aggrData); + } + if (ptr->_features & QRF_GROUPDATA) { + EXPECT_EQUAL("baz", std::string(ptr->_groupData, ptr->_groupDataLen)); + } else { + EXPECT_EQUAL(0u, ptr->_groupDataLen); + EXPECT_EQUAL((void*)NULL, ptr->_groupData); + } + EXPECT_EQUAL(2u, ptr->_numDocs); + for (uint32_t i = 0; i < ptr->_numDocs; ++i) { + EXPECT_EQUAL(i == 0 ? gid0 : gid1, ptr->_hits[i]._gid); + EXPECT_EQUAL((search::HitRank)2 + i, ptr->_hits[i]._metric); + EXPECT_EQUAL(ptr->_features & QRF_MLD ? 3u + i : 0u, ptr->_hits[i]._partid); + EXPECT_EQUAL(ptr->_features & QRF_MLD ? 4u + i : ptr->getDistributionKey(), ptr->_hits[i].getDistributionKey()); + } + + delete ptr; + } +} + +FS4Packet_QUERYX * +createAndFill_QUERYX() +{ + FS4Packet_QUERYX *src = dynamic_cast<FS4Packet_QUERYX*>(FS4PacketFactory::CreateFS4Packet(PCODE_QUERYX)); + ASSERT_TRUE(src != NULL); + src->_offset = 2u; + src->_maxhits = 3u; + src->setTimeout(fastos::TimeStamp(4*fastos::TimeStamp::MS)); + EXPECT_EQUAL(fastos::TimeStamp(4*fastos::TimeStamp::MS), src->getTimeout()); + src->setTimeout(fastos::TimeStamp(-4*fastos::TimeStamp::MS)); + EXPECT_EQUAL(0l, src->getTimeout()); + src->setTimeout(fastos::TimeStamp(4*fastos::TimeStamp::MS)); + EXPECT_EQUAL(fastos::TimeStamp(4*fastos::TimeStamp::MS), src->getTimeout()); + src->_qflags = 5u; + src->setRanking("seven"); + src->_numStackItems = 14u; + src->_propsVector.resize(2); + fillProperties(src->_propsVector[0], "foo", 8); + fillProperties(src->_propsVector[1], "bar", 16); + src->setSortSpec("sortspec"); + src->setAggrSpec("aggrspec"); + src->setGroupSpec("groupspec"); + src->setLocation("location"); + src->setStackDump("stackdump"); + return src; +} + +void +verifyQueryX(FS4Packet_QUERYX & queryX, uint32_t features) +{ + EXPECT_EQUAL((uint32_t)PCODE_QUERYX, queryX.GetPCODE()); + EXPECT_EQUAL(features, queryX._features); + EXPECT_EQUAL(2u, queryX._offset); + EXPECT_EQUAL(3u, queryX._maxhits); + EXPECT_EQUAL(fastos::TimeStamp(4*fastos::TimeStamp::MS), queryX.getTimeout()); + EXPECT_EQUAL(0x5u, queryX._qflags); + if (queryX._features & QF_RANKP) { + EXPECT_EQUAL("seven", queryX._ranking); + } else { + EXPECT_EQUAL("", queryX._ranking); + } + EXPECT_EQUAL(queryX._features & QF_PARSEDQUERY ? 14u : 0u, queryX._numStackItems); + if (queryX._features & QF_PROPERTIES) { + EXPECT_EQUAL(2u, queryX._propsVector.size()); + testProperties(queryX._propsVector[0], "foo", 8); + testProperties(queryX._propsVector[1], "bar", 16); + } else { + EXPECT_EQUAL(0u, queryX._propsVector.size()); + } + if (queryX._features & QF_SORTSPEC) { + EXPECT_EQUAL("sortspec", queryX._sortSpec); + } else { + EXPECT_EQUAL(0u, queryX._sortSpec.size()); + } + if (queryX._features & QF_AGGRSPEC) { + EXPECT_EQUAL("aggrspec", queryX._aggrSpec); + } else { + EXPECT_EQUAL(0u, queryX._aggrSpec.size()); + } + if (queryX._features & QF_GROUPSPEC) { + EXPECT_EQUAL("groupspec", queryX._groupSpec); + } else { + EXPECT_EQUAL(0u, queryX._groupSpec.size()); + } + if (queryX._features & QF_LOCATION) { + EXPECT_EQUAL("location", queryX._location); + } else { + EXPECT_EQUAL(0u, queryX._location.size()); + } + if (queryX._features & QF_PARSEDQUERY) { + EXPECT_EQUAL("stackdump", queryX._stackDump); + } else { + EXPECT_EQUAL(0u, queryX._stackDump.size()); + } +} + +TEST("testQueryX") { + FS4Packet_QUERYX *src = createAndFill_QUERYX(); + std::vector<std::pair<FNET_Packet*, uint32_t>> lst; + for (uint32_t i = QF_PARSEDQUERY, len = (uint32_t)(QF_GROUPSPEC << 1), skip = 0; i < len; ++i) { + if (!(i & QF_PARSEDQUERY)) { + continue; // skip most + } + if (i & ~FNET_QF_SUPPORTED_MASK) { + continue; // not supported + } + if (++skip % 10) { + continue; // skip most + } + src->_features = i; + lst.emplace_back(testEncodeDecode(*src), i); + } + src->_features = uint32_t(-1); + lst.emplace_back(src, -1); + + for (const auto & pfPair : lst) { + FS4Packet_QUERYX *ptr = dynamic_cast<FS4Packet_QUERYX*>(pfPair.first); + ASSERT_TRUE(ptr != NULL); + verifyQueryX(*ptr, pfPair.second); + + delete ptr; + } +} + +TEST("testSharedPacket") { + FNET_Packet::SP src(createAndFill_QUERYX()); + static_cast<FS4Packet_QUERYX *>(src.get())->_features=FNET_QF_SUPPORTED_MASK; + FNET_Packet::SP decoded(testEncodeDecode(*src)); + verifyQueryX(*static_cast<FS4Packet_QUERYX *>(decoded.get()), FNET_QF_SUPPORTED_MASK); + EXPECT_TRUE(decoded.get() != nullptr); + FS4Packet_Shared shared(decoded); + FNET_Packet::UP decoded2(testEncodeDecode(shared)); + EXPECT_TRUE(decoded2.get() != nullptr); + EXPECT_TRUE(nullptr == dynamic_cast<const FS4Packet_Shared *>(decoded2.get())); + EXPECT_TRUE(nullptr != dynamic_cast<const FS4Packet_QUERYX *>(decoded2.get())); + EXPECT_EQUAL(src->GetLength(), decoded2->GetLength()); + verifyQueryX(*static_cast<FS4Packet_QUERYX *>(decoded2.get()), FNET_QF_SUPPORTED_MASK); +} + +TEST("test pre serializing packets no compression") { + FNET_Packet::UP src(createAndFill_QUERYX()); + FS4Packet_QUERYX * queryX = static_cast<FS4Packet_QUERYX *>(src.get()); + queryX->_features=FNET_QF_SUPPORTED_MASK; + FNET_Packet::UP decoded(testEncodeDecode(*src)); + verifyQueryX(*static_cast<FS4Packet_QUERYX *>(decoded.get()), FNET_QF_SUPPORTED_MASK); + EXPECT_EQUAL(512u, src->GetLength()); + EXPECT_EQUAL(src->GetLength(), decoded->GetLength()); + FS4Packet_PreSerialized serialized(*src); + EXPECT_EQUAL(218u, serialized.GetPCODE()); + EXPECT_EQUAL(512u, serialized.GetLength()); + FNET_Packet::UP decoded2(testEncodeDecode(serialized)); + EXPECT_EQUAL(512u, decoded2->GetLength()); + verifyQueryX(*static_cast<FS4Packet_QUERYX *>(decoded2.get()), FNET_QF_SUPPORTED_MASK); +} + +TEST("test pre serializing packets with compression") { + FNET_Packet::UP src(createAndFill_QUERYX()); + FS4Packet_QUERYX * queryX = static_cast<FS4Packet_QUERYX *>(src.get()); + queryX->_features=FNET_QF_SUPPORTED_MASK; + FNET_Packet::UP decoded(testEncodeDecode(*src)); + verifyQueryX(*static_cast<FS4Packet_QUERYX *>(decoded.get()), FNET_QF_SUPPORTED_MASK); + EXPECT_EQUAL(512u, src->GetLength()); + EXPECT_EQUAL(src->GetLength(), decoded->GetLength()); + FS4PersistentPacketStreamer::Instance.SetCompressionLimit(100); + FS4Packet_PreSerialized serialized(*src); + EXPECT_EQUAL(218u | (document::CompressionConfig::LZ4 << 24), serialized.GetPCODE()); + EXPECT_GREATER_EQUAL(321u, serialized.GetLength()); + FNET_Packet::UP decoded2(testEncodeDecode(serialized)); + EXPECT_EQUAL(512u, decoded2->GetLength()); + verifyQueryX(*static_cast<FS4Packet_QUERYX *>(decoded2.get()), FNET_QF_SUPPORTED_MASK); +} + + +TEST("testGetDocsumsX") { + FS4Packet_GETDOCSUMSX *src = dynamic_cast<FS4Packet_GETDOCSUMSX*>(FS4PacketFactory::CreateFS4Packet(PCODE_GETDOCSUMSX)); + ASSERT_TRUE(src != NULL); + src->setTimeout(fastos::TimeStamp(2*fastos::TimeStamp::MS)); + src->setRanking("four"); + src->_qflags = 5u; + src->_stackItems = 7u; + src->_propsVector.resize(2); + fillProperties(src->_propsVector[0], "foo", 8); + fillProperties(src->_propsVector[1], "bar", 16); + src->setResultClassName("resultclassname"); + src->setStackDump("stackdump"); + src->setLocation("location"); + src->_flags = GDFLAG_IGNORE_ROW; + src->AllocateDocIDs(2); + src->_docid[0]._gid = gid0; + src->_docid[0]._partid = 2u; + src->_docid[1]._gid = gid1; + src->_docid[1]._partid = 3u; + + std::vector<std::pair<FNET_Packet*, uint32_t>> lst; + for (uint32_t i = GDF_MLD, len = (uint32_t)(GDF_FLAGS << 1); i < len; ++i) { + if (i & ~FNET_GDF_SUPPORTED_MASK) { + continue; // not supported + } + src->_features = i; + lst.emplace_back(testEncodeDecode(*src), i); + } + src->_features = uint32_t(-1); + lst.emplace_back(src, uint32_t(-1)); + + for (const auto & pfPair : lst) { + FS4Packet_GETDOCSUMSX *ptr = dynamic_cast<FS4Packet_GETDOCSUMSX*>(pfPair.first); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_GETDOCSUMSX, ptr->GetPCODE()); + EXPECT_EQUAL(pfPair.second, ptr->_features); + EXPECT_EQUAL(fastos::TimeStamp(2*fastos::TimeStamp::MS), ptr->getTimeout()); + if (ptr->_features & GDF_RANKP_QFLAGS) { + EXPECT_EQUAL("four", ptr->_ranking); + } else { + EXPECT_EQUAL("", ptr->_ranking); + } + EXPECT_EQUAL(ptr->_features & GDF_RANKP_QFLAGS ? 5u : 0u, ptr->_qflags); + EXPECT_EQUAL(ptr->_features & GDF_QUERYSTACK ? 7u : 0u, ptr->_stackItems); + if (ptr->_features & GDF_PROPERTIES) { + EXPECT_EQUAL(2u, ptr->_propsVector.size()); + testProperties(ptr->_propsVector[0], "foo", 8); + testProperties(ptr->_propsVector[1], "bar", 16); + } else { + EXPECT_EQUAL(0u, ptr->_propsVector.size()); + } + if (ptr->_features & GDF_RESCLASSNAME) { + EXPECT_EQUAL("resultclassname", ptr->_resultClassName); + } else { + EXPECT_EQUAL(0u, ptr->_resultClassName.size()); + } + if (ptr->_features & GDF_QUERYSTACK) { + EXPECT_EQUAL("stackdump", ptr->_stackDump); + } else { + EXPECT_EQUAL(0u, ptr->_stackDump.size()); + } + if (ptr->_features & GDF_LOCATION) { + EXPECT_EQUAL("location", ptr->_location); + } else { + EXPECT_EQUAL(0u, ptr->_location.size()); + } + if (ptr->_features & GDF_FLAGS) { + EXPECT_EQUAL(static_cast<uint32_t>(GDFLAG_IGNORE_ROW), + ptr->_flags); + } else { + EXPECT_EQUAL(0u, ptr->_flags); + } + EXPECT_EQUAL(2u, ptr->_docidCnt); + ASSERT_TRUE(ptr->_docid != NULL); + for (uint32_t i = 0; i < ptr->_docidCnt; ++i) { + EXPECT_EQUAL(i == 0u ? gid0 : gid1, ptr->_docid[i]._gid); + EXPECT_EQUAL(ptr->_features & GDF_MLD ? 2u + i : 0u, ptr->_docid[i]._partid); + } + + delete ptr; + } +} + +TEST("require that FS4PersistentPacketStreamer can compress packets") { + FS4Packet_ERROR *packet = static_cast<FS4Packet_ERROR*>(FS4PacketFactory::CreateFS4Packet(PCODE_ERROR)); + packet->_errorCode = 1u; + packet->setErrorMessage(string(1000, 'a')); + + FS4PersistentPacketStreamer streamer(FS4PacketFactory::CreateFS4Packet); + + FNET_DataBuffer buf1; + streamer.Encode(packet, 1u, &buf1); + EXPECT_EQUAL(1020u, buf1.GetDataLen()); + + streamer.SetCompressionLimit(100); + FNET_DataBuffer buf2; + streamer.Encode(packet, 1u, &buf2); + EXPECT_EQUAL(38u, buf2.GetDataLen()); + + std::vector<FNET_Packet*> lst{ packet, testEncodeDecode(streamer, *packet) }; + + for (FNET_Packet * fnetPacket : lst) { + FS4Packet_ERROR *ptr = dynamic_cast<FS4Packet_ERROR*>(fnetPacket); + ASSERT_TRUE(ptr != NULL); + EXPECT_EQUAL((uint32_t)PCODE_ERROR, ptr->GetPCODE()); + EXPECT_EQUAL(1008u, ptr->GetLength()); + delete ptr; + } +} + +TEST("require that FS4PersistentPacketStreamer can avoid compressing small packets") { + FS4Packet_ERROR *packet = static_cast<FS4Packet_ERROR*>(FS4PacketFactory::CreateFS4Packet(PCODE_ERROR)); + packet->_errorCode = 1u; + packet->setErrorMessage("a"); + + FS4PersistentPacketStreamer streamer(FS4PacketFactory::CreateFS4Packet); + + FNET_DataBuffer buf1; + streamer.Encode(packet, 1u, &buf1); + EXPECT_EQUAL(21u, buf1.GetDataLen()); + + streamer.SetCompressionLimit(10); + FNET_DataBuffer buf2; + streamer.Encode(packet, 1u, &buf2); + EXPECT_EQUAL(21u, buf2.GetDataLen()); + + delete packet; +} + +TEST_MAIN() { TEST_RUN_ALL(); } |