Project
Loading...
Searching...
No Matches
test_TMessageSerializer.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14#include <fairmq/TransportFactory.h>
15#include "TestClasses.h"
16#include <catch_amalgamated.hpp>
17#include <utility>
18
19using namespace o2::framework;
20
21class ExceptionMatcher : public Catch::Matchers::MatcherBase<RuntimeErrorRef>
22{
23 std::string m_expected;
24 mutable std::string m_actual;
25
26 public:
27 ExceptionMatcher(std::string exp) : m_expected(std::move(exp)) {}
28 bool match(RuntimeErrorRef const& ref) const override
29 {
30 auto& e = error_from_ref(ref);
31 m_actual = std::string(e.what);
32 return std::string(e.what) == m_expected;
33 }
34 std::string describe() const override
35 {
36 std::ostringstream ss;
37 ss << " special exception has value of " << m_expected << " but got " << m_actual;
38 return ss.str();
39 }
40};
41
42TEST_CASE("TestTMessageSerializer")
43{
45 const char* testname = "testname";
46 const char* testtitle = "testtitle";
47 using namespace o2::framework;
48
49 TObjArray array;
50 array.SetOwner();
51 array.Add(new TNamed(testname, testtitle));
52
53 auto transport = fair::mq::TransportFactory::CreateTransportFactory("zeromq");
54 auto msg = transport->CreateMessage(4096);
57
58 FairInputTBuffer msg2((char*)msg->GetData(), msg->GetSize());
59 // test deserialization with TObject as target class (default)
60 auto out = TMessageSerializer::deserialize(msg2);
61
62 auto* outarr = dynamic_cast<TObjArray*>(out.get());
63 REQUIRE(out.get() == outarr);
64 auto* named = dynamic_cast<TNamed*>(outarr->At(0));
65 REQUIRE(static_cast<void*>(named) == static_cast<void*>(outarr->At(0)));
66 REQUIRE(named->GetName() == std::string(testname));
67 REQUIRE(named->GetTitle() == std::string(testtitle));
68
69 // test deserialization with a wrong target class and check the exception
70 REQUIRE_THROWS_AS(TMessageSerializer::deserialize<TNamed>(msg2), o2::framework::RuntimeErrorRef);
71
72 REQUIRE_THROWS_MATCHES(TMessageSerializer::deserialize<TNamed>(msg2), o2::framework::RuntimeErrorRef,
73 ExceptionMatcher("can not convert serialized class TObjArray into target class TNamed"));
74}
75
77{
78 auto& e = error_from_ref(ref);
79 std::string expected("can not convert serialized class vector<o2::test::Polymorphic> into target class TObject");
80 return expected == e.what;
81};
82
83TEST_CASE("TestTMessageSerializer_NonTObject")
84{
85 using namespace o2::framework;
86 std::vector<o2::test::Polymorphic> data{{0xaffe}, {0xd00f}};
87
88 TClass* cl = TClass::GetClass("std::vector<o2::test::Polymorphic>");
89 REQUIRE(cl != nullptr);
90
91 auto transport = fair::mq::TransportFactory::CreateTransportFactory("zeromq");
92 auto msg = transport->CreateMessage(4096);
94 char* in = reinterpret_cast<char*>(&data);
96 FairInputTBuffer msg2((char*)msg->GetData(), msg->GetSize());
97
98 auto out = TMessageSerializer::deserialize<std::vector<o2::test::Polymorphic>>(msg2);
99 REQUIRE(out);
100 REQUIRE((*out.get()).size() == 2);
101 REQUIRE((*out.get())[0] == o2::test::Polymorphic(0xaffe));
102 REQUIRE((*out.get())[1] == o2::test::Polymorphic(0xd00f));
103
104 // test deserialization with a wrong target class and check the exception
105 REQUIRE_THROWS_AS(TMessageSerializer::deserialize(msg2), RuntimeErrorRef);
106}
107
108TEST_CASE("TestTMessageSerializer_InvalidBuffer")
109{
110 const char* buffer = "this is for sure not a serialized ROOT object";
111 auto transport = fair::mq::TransportFactory::CreateTransportFactory("zeromq");
112 auto msg = transport->CreateMessage(strlen(buffer) + 8);
113 memcpy((char*)msg->GetData() + 8, buffer, strlen(buffer));
114 // test deserialization of invalid buffer and check the exception
115 // FIXME: at the moment, TMessage fails directly with a segfault, which it shouldn't do
116 /*
117 try {
118 auto out = TMessageSerializer::deserialize((std::byte*)buffer, strlen(buffer));
119 BOOST_ERROR("here we should never get, the function call must fail with exception");
120 } catch (std::exception& e) {
121 std::string expected("");
122 BOOST_CHECK_MESSAGE(expected == e.what(), e.what());
123 }
124 */
125 // test deserialization of invalid target class and check the exception
126 struct Dummy {
127 };
128 auto matcher = ExceptionMatcher("class is not ROOT-serializable: ZL22CATCH2_INTERNAL_TEST_4vE5Dummy");
129 FairInputTBuffer msg2((char*)msg->GetData(), msg->GetSize());
130 REQUIRE_THROWS_MATCHES(TMessageSerializer::deserialize<Dummy>(msg2), o2::framework::RuntimeErrorRef, matcher);
131}
132
133TEST_CASE("TestTMessageSerializer_CheckExpansion")
134{
135 const char* buffer = "this is for sure not a serialized ROOT object";
136 auto transport = fair::mq::TransportFactory::CreateTransportFactory("zeromq");
137 auto msg = transport->CreateMessage(strlen(buffer) + 8);
138 FairOutputTBuffer msg2(*msg);
139 // The buffer starts after 8 bytes.
140 REQUIRE(msg2.Buffer() == (char*)msg->GetData() + 8);
141 // The first 8 bytes of the buffer store the pointer to the message itself.
142 REQUIRE(*(fair::mq::Message**)msg->GetData() == msg.get());
143 // Notice that TBuffer does the same trick with the reallocation function,
144 // so in the end the useful buffer size is the message size minus 16.
145 REQUIRE(msg2.BufferSize() == (msg->GetSize() - 16));
146 // This will not fit the original buffer size, so the buffer will be expanded.
147 msg2.Expand(100);
148}
uint64_t exp(uint64_t base, uint8_t exp) noexcept
ExceptionMatcher(std::string exp)
bool match(RuntimeErrorRef const &ref) const override
std::string describe() const override
GLuint buffer
Definition glcorearb.h:655
GLenum array
Definition glcorearb.h:4274
GLboolean * data
Definition glcorearb.h:298
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
TEST_CASE("test_prepareArguments")
void clean_all_runtime_errors()
RuntimeError & error_from_ref(RuntimeErrorRef)
Defining DataPointCompositeObject explicitly as copiable.
static void serialize(o2::framework::FairOutputTBuffer &msg, const TObject *input)
static std::unique_ptr< T > deserialize(FairInputTBuffer &buffer)
std::map< std::string, ID > expected
bool check_expected(RuntimeErrorRef const &ref)
uint64_t const void const *restrict const msg
Definition x9.h:153