Skip to content

Commit 7f51127

Browse files
committed
added various gtest matcher and printers
1 parent d63bb58 commit 7f51127

File tree

6 files changed

+233
-14
lines changed

6 files changed

+233
-14
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
uint64 service_id
21
uint64 tag
32
uint64 sequence
3+
uint64 service_id
44

55
# reserve twice as much as we need.
66
@extent _offset_.max * 2

src/common/ipc/client_router.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ class ClientRouterImpl final : public ClientRouter
156156
Route_1_0 route{&router_.memory_};
157157

158158
auto& channel_msg = route.set_channel_msg();
159-
channel_msg.service_id = service_id;
160159
channel_msg.tag = endpoint_.getTag();
161160
channel_msg.sequence = sequence_++;
161+
channel_msg.service_id = service_id;
162162

163163
return tryPerformOnSerialized(route, [this, payload](const auto prefix) {
164164
//

src/common/ipc/server_router.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ class ServerRouterImpl final : public ServerRouter
163163
Route_1_0 route{&router_.memory_};
164164

165165
auto& channel_msg = route.set_channel_msg();
166-
channel_msg.service_id = service_id;
167166
channel_msg.tag = endpoint_.getTag();
168167
channel_msg.sequence = sequence_++;
168+
channel_msg.service_id = service_id;
169169

170170
return tryPerformOnSerialized(route, [this, payload](const auto prefix) {
171171
//
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
//
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: MIT
4+
//
5+
6+
#ifndef OCVSMD_COMMON_IPC_GTEST_HELPERS_HPP_INCLUDED
7+
#define OCVSMD_COMMON_IPC_GTEST_HELPERS_HPP_INCLUDED
8+
9+
#include "dsdl_helpers.hpp"
10+
#include "ipc/pipe/pipe_types.hpp"
11+
12+
#include "ocvsmd/common/ipc/RouteChannelEnd_1_0.hpp"
13+
#include "ocvsmd/common/ipc/RouteChannelMsg_1_0.hpp"
14+
#include "ocvsmd/common/ipc/RouteConnect_1_0.hpp"
15+
#include "ocvsmd/common/ipc/Route_1_0.hpp"
16+
17+
#include <uavcan/node/Version_1_0.hpp>
18+
#include <uavcan/primitive/Empty_1_0.hpp>
19+
20+
#include <cetl/pf17/cetlpf.hpp>
21+
22+
#include <gmock/gmock.h>
23+
#include <gtest/gtest-matchers.h>
24+
#include <gtest/gtest-printers.h>
25+
26+
#include <cstdint>
27+
#include <ios>
28+
#include <ostream>
29+
#include <vector>
30+
31+
// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
32+
33+
namespace ocvsmd
34+
{
35+
namespace common
36+
{
37+
namespace ipc
38+
{
39+
40+
// MARK: - GTest Printers:
41+
42+
inline void PrintTo(const uavcan::primitive::Empty_1_0&, std::ostream* os)
43+
{
44+
*os << "Empty_1_0";
45+
}
46+
47+
inline void PrintTo(const uavcan::node::Version_1_0& ver, std::ostream* os)
48+
{
49+
*os << "Version_1_0{'" << static_cast<int>(ver.major) << "." << static_cast<int>(ver.minor) << "'}";
50+
}
51+
52+
inline void PrintTo(const RouteConnect_1_0& conn, std::ostream* os)
53+
{
54+
*os << "RouteConnect_1_0{ver=";
55+
PrintTo(conn.version, os);
56+
*os << "}";
57+
}
58+
59+
inline void PrintTo(const RouteChannelMsg_1_0& msg, std::ostream* os)
60+
{
61+
*os << "RouteChannelMsg_1_0{tag=" << msg.tag << ", seq=" << msg.sequence << ", srv=0x" << std::hex << msg.service_id
62+
<< "}";
63+
}
64+
65+
inline void PrintTo(const RouteChannelEnd_1_0& msg, std::ostream* os)
66+
{
67+
*os << "RouteChannelEnd_1_0{tag=" << msg.tag << ", err=" << msg.error_code << "}";
68+
}
69+
70+
inline void PrintTo(const Route_1_0& route, std::ostream* os)
71+
{
72+
*os << "Route_1_0{";
73+
cetl::visit([os](const auto& v) { PrintTo(v, os); }, route.union_value);
74+
*os << "}";
75+
}
76+
77+
// MARK: - Equitable-s for matching:
78+
79+
inline bool operator==(const RouteConnect_1_0& lhs, const RouteConnect_1_0& rhs)
80+
{
81+
return lhs.version.major == rhs.version.major && lhs.version.minor == rhs.version.minor;
82+
}
83+
84+
inline bool operator==(const RouteChannelMsg_1_0& lhs, const RouteChannelMsg_1_0& rhs)
85+
{
86+
return lhs.tag == rhs.tag && lhs.sequence == rhs.sequence && lhs.service_id == rhs.service_id;
87+
}
88+
89+
inline bool operator==(const RouteChannelEnd_1_0& lhs, const RouteChannelEnd_1_0& rhs)
90+
{
91+
return lhs.tag == rhs.tag && lhs.error_code == rhs.error_code;
92+
}
93+
94+
// MARK: - GTest Matchers:
95+
96+
template <typename T>
97+
class PayloadMatcher
98+
{
99+
public:
100+
explicit PayloadMatcher(testing::Matcher<const typename T::VariantType&> matcher,
101+
cetl::pmr::memory_resource& memory)
102+
: matcher_(std::move(matcher))
103+
, memory_{memory}
104+
105+
{
106+
}
107+
108+
bool MatchAndExplain(const pipe::Payload& payload, testing::MatchResultListener* listener) const
109+
{
110+
T msg{&memory_};
111+
const auto result = tryDeserializePayload<T>(payload, msg);
112+
if (!result)
113+
{
114+
if (listener->IsInterested())
115+
{
116+
*listener << "Failed to deserialize the payload.";
117+
}
118+
return false;
119+
}
120+
121+
const bool match = matcher_.MatchAndExplain(msg.union_value, listener);
122+
if (!match && listener->IsInterested())
123+
{
124+
*listener << ".\n Payload: ";
125+
*listener << testing::PrintToString(msg);
126+
}
127+
return match;
128+
}
129+
130+
bool MatchAndExplain(const pipe::Payloads& payloads, testing::MatchResultListener* listener) const
131+
{
132+
std::vector<std::uint8_t> flatten;
133+
for (const auto& payload : payloads)
134+
{
135+
flatten.insert(flatten.end(), payload.begin(), payload.end());
136+
}
137+
return MatchAndExplain({flatten.data(), flatten.size()}, listener);
138+
}
139+
140+
void DescribeTo(std::ostream* os) const
141+
{
142+
*os << "is a variant<> with value of type '" << "GetTypeName()"
143+
<< "' and the value ";
144+
matcher_.DescribeTo(os);
145+
}
146+
147+
void DescribeNegationTo(std::ostream* os) const
148+
{
149+
*os << "is a variant<> with value of type other than '" << "GetTypeName()"
150+
<< "' or the value ";
151+
matcher_.DescribeNegationTo(os);
152+
}
153+
154+
private:
155+
const testing::Matcher<const typename T::VariantType&> matcher_;
156+
cetl::pmr::memory_resource& memory_;
157+
158+
}; // PayloadMatcher
159+
160+
template <typename T>
161+
testing::PolymorphicMatcher<PayloadMatcher<T>> PayloadWith(
162+
163+
const testing::Matcher<const typename T::VariantType&>& matcher,
164+
cetl::pmr::memory_resource& memory)
165+
{
166+
return testing::MakePolymorphicMatcher(PayloadMatcher<T>(matcher, memory));
167+
}
168+
169+
inline auto PayloadRouteConnectEq(cetl::pmr::memory_resource& mr,
170+
const std::uint8_t ver_major = VERSION_MAJOR,
171+
const std::uint8_t ver_minor = VERSION_MINOR)
172+
{
173+
const RouteConnect_1_0 connect{{ver_major, ver_minor, &mr}, &mr};
174+
return PayloadWith<Route_1_0>(testing::VariantWith<RouteConnect_1_0>(connect), mr);
175+
}
176+
177+
template <typename Msg>
178+
auto PayloadOfRouteChannel(cetl::pmr::memory_resource& mr,
179+
const std::uint64_t tag,
180+
const std::uint64_t seq,
181+
const cetl::string_view srv_name = "")
182+
{
183+
const RouteChannelMsg_1_0 msg{tag, seq, AnyChannel::getServiceId<Msg>(srv_name), &mr};
184+
return PayloadWith<Route_1_0>(testing::VariantWith<RouteChannelMsg_1_0>(msg), mr);
185+
}
186+
187+
} // namespace ipc
188+
} // namespace common
189+
} // namespace ocvsmd
190+
191+
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
192+
193+
#endif // OCVSMD_COMMON_IPC_GTEST_HELPERS_HPP_INCLUDED

test/common/ipc/test_client_router.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
#include "ipc/channel.hpp"
1010
#include "ipc/pipe/client_pipe.hpp"
1111
#include "ipc/pipe/pipe_types.hpp"
12+
#include "ipc_gtest_helpers.hpp"
1213
#include "pipe/client_pipe_mock.hpp"
1314
#include "tracking_memory_resource.hpp"
1415

16+
#include "ocvsmd/common/ipc/RouteChannelEnd_1_0.hpp"
17+
#include "ocvsmd/common/ipc/RouteChannelMsg_1_0.hpp"
1518
#include "ocvsmd/common/ipc/RouteConnect_1_0.hpp"
1619
#include "ocvsmd/common/ipc/Route_1_0.hpp"
1720
#include "ocvsmd/common/node_command/ExecCmd_1_0.hpp"
1821

1922
#include <cetl/pf17/cetlpf.hpp>
20-
#include <cetl/pf20/cetlpf.hpp>
2123

2224
#include <gmock/gmock.h>
2325
#include <gtest/gtest.h>
@@ -26,7 +28,6 @@
2628
#include <cstdint>
2729
#include <iterator>
2830
#include <memory>
29-
#include <utility>
3031
#include <vector>
3132

3233
namespace
@@ -81,7 +82,7 @@ class TestClientRouter : public testing::Test
8182
void emulateRouteConnect(pipe::ClientPipeMock& client_pipe_mock)
8283
{
8384
// client RouteConnect -> server
84-
EXPECT_CALL(client_pipe_mock, send(_)).WillOnce(Return(0));
85+
EXPECT_CALL(client_pipe_mock, send(PayloadRouteConnectEq(mr_))).WillOnce(Return(0));
8586
client_pipe_mock.event_handler_(pipe::ClientPipe::Event::Connected{});
8687

8788
// Server -> client RouteConnect
@@ -102,9 +103,9 @@ class TestClientRouter : public testing::Test
102103

103104
Route_1_0 route{&mr_};
104105
auto& channel_msg = route.set_channel_msg();
105-
channel_msg.service_id = AnyChannel::getServiceId<Msg>(service_name);
106106
channel_msg.tag = tag;
107107
channel_msg.sequence = seq;
108+
channel_msg.service_id = AnyChannel::getServiceId<Msg>(service_name);
108109

109110
const int result = tryPerformOnSerialized(route, [&](const auto prefix) {
110111
//
@@ -202,8 +203,14 @@ TEST_F(TestClientRouter, makeChannel_send)
202203

203204
emulateRouteConnect(client_pipe_mock);
204205

205-
EXPECT_CALL(client_pipe_mock, send(SizeIs(2))).WillOnce(Return(0));
206+
EXPECT_CALL(client_pipe_mock, send(PayloadOfRouteChannel<Msg>(mr_, 1, 0))).WillOnce(Return(0));
206207
EXPECT_THAT(channel.send(msg), 0);
208+
209+
EXPECT_CALL(client_pipe_mock, send(PayloadOfRouteChannel<Msg>(mr_, 1, 1))).WillOnce(Return(0));
210+
EXPECT_THAT(channel.send(msg), 0);
211+
212+
EXPECT_CALL(client_pipe_mock, send(PayloadWith<Route_1_0>(VariantWith<RouteChannelEnd_1_0>(_), mr_)))
213+
.WillOnce(Return(0));
207214
}
208215

209216
TEST_F(TestClientRouter, makeChannel_receive_events)

test/common/ipc/test_server_router.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
#include "ipc/channel.hpp"
99
#include "ipc/pipe/pipe_types.hpp"
1010
#include "ipc/pipe/server_pipe.hpp"
11+
#include "ipc_gtest_helpers.hpp"
1112
#include "pipe/server_pipe_mock.hpp"
1213
#include "tracking_memory_resource.hpp"
1314

15+
#include "ocvsmd/common/ipc/RouteConnect_1_0.hpp"
1416
#include "ocvsmd/common/ipc/Route_1_0.hpp"
1517
#include "ocvsmd/common/node_command/ExecCmd_1_0.hpp"
1618

@@ -32,6 +34,7 @@ using namespace ocvsmd::common::ipc; // NOLINT This our main concern here in th
3234

3335
using testing::_;
3436
using testing::IsTrue;
37+
using testing::Return;
3538
using testing::IsEmpty;
3639
using testing::IsFalse;
3740
using testing::NotNull;
@@ -55,9 +58,14 @@ class TestServerRouter : public testing::Test
5558
EXPECT_THAT(mr_.total_allocated_bytes, mr_.total_deallocated_bytes);
5659
}
5760

61+
static void emulatePipeConnect(const pipe::ServerPipe::ClientId client_id, pipe::ServerPipeMock& server_pipe_mock)
62+
{
63+
server_pipe_mock.event_handler_(pipe::ServerPipe::Event::Connected{client_id});
64+
}
65+
5866
template <typename Msg>
59-
void emulateRouteChannelMsg(pipe::ServerPipeMock& server_pipe_mock,
60-
const pipe::ServerPipe::ClientId client_id,
67+
void emulateRouteChannelMsg(const pipe::ServerPipe::ClientId client_id,
68+
pipe::ServerPipeMock& server_pipe_mock,
6169
const std::uint64_t tag,
6270
const Msg& msg,
6371
const std::uint64_t seq,
@@ -67,9 +75,9 @@ class TestServerRouter : public testing::Test
6775

6876
Route_1_0 route{&mr_};
6977
auto& channel_msg = route.set_channel_msg();
70-
channel_msg.service_id = AnyChannel::getServiceId<Msg>(service_name);
7178
channel_msg.tag = tag;
7279
channel_msg.sequence = seq;
80+
channel_msg.service_id = AnyChannel::getServiceId<Msg>(service_name);
7381

7482
const int result = tryPerformOnSerialized(route, [&](const auto prefix) {
7583
//
@@ -172,16 +180,27 @@ TEST_F(TestServerRouter, channel_send)
172180
});
173181
EXPECT_THAT(maybe_channel.has_value(), IsFalse());
174182

183+
// Emulate that client #42 is connected.
184+
//
185+
EXPECT_CALL(ch1_event_mock, Call(VariantWith<Channel::Connected>(_))).Times(1);
186+
emulatePipeConnect(42, server_pipe_mock);
187+
175188
// Emulate that client posted initial `RouteChannelMsg` on 42/1 client/tag pair.
176189
//
177190
EXPECT_CALL(ch1_event_mock, Call(VariantWith<Channel::Input>(_))).Times(1);
178-
emulateRouteChannelMsg(server_pipe_mock, 42, 1, Channel::Input{&mr_}, 0);
179-
EXPECT_THAT(maybe_channel.has_value(), IsTrue());
191+
emulateRouteChannelMsg(42, server_pipe_mock, 1, Channel::Input{&mr_}, 0);
192+
ASSERT_THAT(maybe_channel.has_value(), IsTrue());
180193

181194
// Emulate that client posted one more `RouteChannelMsg` on the same 42/1 client/tag pair.
182195
//
183196
EXPECT_CALL(ch1_event_mock, Call(VariantWith<Channel::Input>(_))).Times(1);
184-
emulateRouteChannelMsg(server_pipe_mock, 42, 1, Channel::Input{&mr_}, 1);
197+
emulateRouteChannelMsg(42, server_pipe_mock, 1, Channel::Input{&mr_}, 1);
198+
199+
EXPECT_CALL(server_pipe_mock, send(42, PayloadOfRouteChannel<Msg>(mr_, 1, 0))).WillOnce(Return(0));
200+
EXPECT_THAT(maybe_channel->send(Channel::Output{&mr_}), 0);
201+
202+
EXPECT_CALL(server_pipe_mock, send(42, PayloadOfRouteChannel<Msg>(mr_, 1, 1))).WillOnce(Return(0));
203+
EXPECT_THAT(maybe_channel->send(Channel::Output{&mr_}), 0);
185204
}
186205

187206
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)

0 commit comments

Comments
 (0)