diff --git a/HeartTests/tst_testprotockol.cpp b/HeartTests/tst_testprotockol.cpp index ac8afb5..2a105d8 100644 --- a/HeartTests/tst_testprotockol.cpp +++ b/HeartTests/tst_testprotockol.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #define TestCase(name, testClass) \ void name() { \ @@ -39,6 +40,8 @@ private slots: #endif TestCase(upgradeDataBaseTest, UpgradeDataBaseTest) + TestCase(multiVersionTest, MultiVersionTest) + // END TEST CASES diff --git a/HeartTests/units/multiversiontest.cpp b/HeartTests/units/multiversiontest.cpp index dcc6a24..6454133 100644 --- a/HeartTests/units/multiversiontest.cpp +++ b/HeartTests/units/multiversiontest.cpp @@ -7,40 +7,27 @@ #include "multiversiontest.h" -class TestingClient: public QH::AbstractNode { - - // AbstractNode interface +class MultiVersionPkg { public: - const QH::PKG::Ping& getPing() const { - return _ping; - } - - NodeType nodeType() const override { - return NodeType::Node; - }; - -protected slots: - void receivePing(const QSharedPointer& ping) override { - _ping = *ping; - }; - -private: - QH::PKG::Ping _ping; + int v2; + int v1; + int lastSerializedFrom = 0; + int lastSerializedto = 0; }; -class MultiVersionPkg: public QH::PKG::MultiversionData { +class MultiVersionPkg1: public QH::PKG::MultiversionData, public MultiVersionPkg { QH_PACKAGE("MultiVersionPkg") public: - MultiVersionPkg(): QH::PKG::MultiversionData( + MultiVersionPkg1(): QH::PKG::MultiversionData( { {0, // version 0 { - [this](QDataStream& stream){ // from + [this](QDataStream& stream) -> QDataStream&{ // from stream >> v1; return stream; }, - [this](QDataStream& stream){ // to + [this](QDataStream& stream) -> QDataStream&{ // to stream << v1; return stream; @@ -49,13 +36,13 @@ public: }, {1, // version 1 { - [this](const QDataStream* stream){ // from + [this](QDataStream& stream) -> QDataStream&{ // from stream >> v1; stream >> v2; return stream; }, - [this](const QDataStream* stream){ // to + [this](QDataStream& stream) -> QDataStream&{ // to stream << v1; stream << v2; return stream; @@ -64,9 +51,126 @@ public: } } ) {}; - int v1; - int v2; +}; +class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg { + QH_PACKAGE("MultiVersionPkg") + +public: + MultiVersionPkg2(): QH::PKG::MultiversionData( + { + {0, // version 0 + { + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 0; + stream >> v1; + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 0; + + stream << v1; + + return stream; + } + } + }, + {1, // version 1 + { + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 1; + + stream >> v1; + stream >> v2; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 1; + + stream << v1; + stream << v2; + return stream; + } + } + }, + {2, // version 2 + { + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 2; + + stream >> v2; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 2; + + stream << v2; + return stream; + } + } + } + } + ) {}; +}; + +template +class TestAPI: public QH::iParser { +public: + TestAPI(QH::AbstractNode* parentNode): QH::iParser(parentNode) { + registerPackageType(); + } + + // iParser interface +public: + + QH::ParserResult parsePackage(const QSharedPointer &pkg, + const QH::Header &, + QH::AbstractNodeInfo *) override { + + if (pkg->cmd() == Base::command()) { + data = pkg; + return QH::ParserResult::Processed; + } + + return QH::ParserResult::NotProcessed; + }; + int version() const override {return 0;}; + QString parserId() const override {return "BigDataTestParser";}; + + QSharedPointer getData() const{ + return data; + }; + +private: + QSharedPointer data = nullptr; + +}; + +template +class TestingClient: public QH::AbstractNode { + + // AbstractNode interface +public: + TestingClient() { + _parser = addApiParser>(); + } + + bool sendRequest(const Base& data, int port) { + return sendData(&data, QH::HostAddress(TEST_LOCAL_HOST, port)); + } + + NodeType nodeType() const override { + return NodeType::Node; + }; + + const QSharedPointer& parser() const { + return _parser; + } + +private: + QSharedPointer _parser; }; MultiVersionTest::MultiVersionTest() { @@ -75,4 +179,59 @@ MultiVersionTest::MultiVersionTest() { void MultiVersionTest::test() { + TestingClient nodeWithV1; + TestingClient nodeWithV2; + + int nodev1Port = TEST_PORT + 5; + int nodev2Port = TEST_PORT + 6; + + QVERIFY(nodeWithV1.run(TEST_LOCAL_HOST, nodev1Port)); + QVERIFY(nodeWithV2.run(TEST_LOCAL_HOST, nodev2Port)); + + // from new to old + { + MultiVersionPkg2 pkg; + pkg.v1 = 10; + pkg.v2 = 20; + + QVERIFY(nodeWithV2.sendRequest(pkg, nodev1Port)); + + // should use the maximum available serialization. it is 1 + QVERIFY(pkg.lastSerializedto == 1); + + QVERIFY(wait([&nodeWithV1](){ + return nodeWithV1.parser().staticCast>()-> + getData().staticCast()->lastSerializedFrom == 1; + }, WAIT_RESPOCE_TIME)); + + auto data = nodeWithV1.parser().staticCast>()-> + getData().staticCast(); + + QVERIFY(data->v1 == pkg.v1); + QVERIFY(data->v2 == pkg.v2); + } + + // from old to new + + { + MultiVersionPkg1 pkg; + pkg.v1 = 10; + pkg.v2 = 20; + + QVERIFY(nodeWithV1.sendRequest(pkg, nodev1Port)); + + // should use the maximum available serialization. it is 1 + QVERIFY(pkg.lastSerializedto == 1); + + QVERIFY(wait([&nodeWithV2](){ + return nodeWithV2.parser().staticCast>()-> + getData().staticCast()->lastSerializedFrom == 1; + }, WAIT_RESPOCE_TIME)); + + auto data = nodeWithV2.parser().staticCast>()-> + getData().staticCast(); + + QVERIFY(data->v1 == pkg.v1); + QVERIFY(data->v2 == pkg.v2); + } } diff --git a/src/private/apiversion.cpp b/src/private/apiversion.cpp index ad3e75f..51ccfd1 100644 --- a/src/private/apiversion.cpp +++ b/src/private/apiversion.cpp @@ -16,7 +16,6 @@ APIVersion::APIVersion() { } QDataStream &APIVersion::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); stream >> _apisVersions; stream >> _packagesVersions; diff --git a/src/public/packages/multiversiondata.h b/src/public/packages/multiversiondata.h index 3785c5b..bde71a4 100644 --- a/src/public/packages/multiversiondata.h +++ b/src/public/packages/multiversiondata.h @@ -28,25 +28,38 @@ struct SerializationBox { * @code{cpp} * * class MyPackage: public MultiversionData { - * MyPackage(): MultiversionData( - * {0, {[](auto stream){ - * // some code from stream for version 0 ; - * return stream; - * },{[](auto stream){ - * // some code to stream for version 0 ; - * return stream; - * }}, - * - * 1, {[](auto stream){ - * // some code from stream for version 1 ; - * return stream; - * },{[](auto stream){ - * // some code to stream for version 1 ; - * return stream; - * }},} - * ) { - * } - * } + MyPackage(): QH::PKG::MultiversionData( + { + {0, // version 0 + { + [this](QDataStream& stream) -> QDataStream&{ // from + stream >> v1; + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + stream << v1; + + return stream; + } + } + }, + {1, // version 1 + { + [this](QDataStream& stream) -> QDataStream&{ // from + stream >> v1; + stream >> v2; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + stream << v1; + stream << v2; + return stream; + } + } + } + } + ) {}; * @endcode * * @note the default toBytes function of this class will be convert your class using latest version.