Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_rpc / server_test.cc
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_rpc/server.h"
16
17 #include <array>
18 #include <cstdint>
19
20 #include "gtest/gtest.h"
21 #include "pw_assert/assert.h"
22 #include "pw_rpc/internal/method.h"
23 #include "pw_rpc/internal/packet.h"
24 #include "pw_rpc/internal/test_method.h"
25 #include "pw_rpc/service.h"
26 #include "pw_rpc_private/internal_test_utils.h"
27
28 namespace pw::rpc {
29 namespace {
30
31 using std::byte;
32
33 using internal::Packet;
34 using internal::PacketType;
35 using internal::TestMethod;
36 using internal::TestMethodUnion;
37
38 class TestService : public Service {
39  public:
40   TestService(uint32_t service_id)
41       : Service(service_id, methods_),
42         methods_{
43             TestMethod(100),
44             TestMethod(200),
45         } {}
46
47   const TestMethod& method(uint32_t id) {
48     for (TestMethodUnion& method : methods_) {
49       if (method.method().id() == id) {
50         return method.test_method();
51       }
52     }
53
54     PW_CRASH("Invalid method ID %u", static_cast<unsigned>(id));
55   }
56
57  private:
58   std::array<TestMethodUnion, 2> methods_;
59 };
60
61 class BasicServer : public ::testing::Test {
62  protected:
63   static constexpr byte kDefaultPayload[] = {
64       byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
65
66   BasicServer()
67       : channels_{
68             Channel::Create<1>(&output_),
69             Channel::Create<2>(&output_),
70             Channel(),  // available for assignment
71         },
72         server_(channels_),
73         service_(42) {
74     server_.RegisterService(service_);
75   }
76
77   std::span<const byte> EncodeRequest(
78       PacketType type,
79       uint32_t channel_id,
80       uint32_t service_id,
81       uint32_t method_id,
82       std::span<const byte> payload = kDefaultPayload) {
83     auto result = Packet(type, channel_id, service_id, method_id, payload)
84                       .Encode(request_buffer_);
85     EXPECT_EQ(OkStatus(), result.status());
86     return result.value_or(ConstByteSpan());
87   }
88
89   TestOutput<128> output_;
90   std::array<Channel, 3> channels_;
91   Server server_;
92   TestService service_;
93
94  private:
95   byte request_buffer_[64];
96 };
97
98 TEST_F(BasicServer, ProcessPacket_ValidMethod_InvokesMethod) {
99   EXPECT_EQ(OkStatus(),
100             server_.ProcessPacket(
101                 EncodeRequest(PacketType::REQUEST, 1, 42, 100), output_));
102
103   const TestMethod& method = service_.method(100);
104   EXPECT_EQ(1u, method.last_channel_id());
105   ASSERT_EQ(sizeof(kDefaultPayload), method.last_request().payload().size());
106   EXPECT_EQ(std::memcmp(kDefaultPayload,
107                         method.last_request().payload().data(),
108                         method.last_request().payload().size()),
109             0);
110 }
111
112 TEST_F(BasicServer, ProcessPacket_IncompletePacket_NothingIsInvoked) {
113   EXPECT_EQ(Status::DataLoss(),
114             server_.ProcessPacket(
115                 EncodeRequest(PacketType::REQUEST, 0, 42, 101), output_));
116   EXPECT_EQ(Status::DataLoss(),
117             server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 0, 101),
118                                   output_));
119   EXPECT_EQ(Status::DataLoss(),
120             server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 0),
121                                   output_));
122
123   EXPECT_EQ(0u, service_.method(100).last_channel_id());
124   EXPECT_EQ(0u, service_.method(200).last_channel_id());
125 }
126
127 TEST_F(BasicServer, ProcessPacket_NoChannel_SendsNothing) {
128   EXPECT_EQ(Status::DataLoss(),
129             server_.ProcessPacket(
130                 EncodeRequest(PacketType::REQUEST, 0, 42, 101), output_));
131
132   EXPECT_EQ(output_.packet_count(), 0u);
133 }
134
135 TEST_F(BasicServer, ProcessPacket_NoService_SendsDataLoss) {
136   EXPECT_EQ(Status::DataLoss(),
137             server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 0, 101),
138                                   output_));
139
140   EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
141   EXPECT_EQ(output_.sent_packet().status(), Status::DataLoss());
142 }
143
144 TEST_F(BasicServer, ProcessPacket_NoMethod_SendsDataLoss) {
145   EXPECT_EQ(Status::DataLoss(),
146             server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 0),
147                                   output_));
148
149   EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
150   EXPECT_EQ(output_.sent_packet().status(), Status::DataLoss());
151 }
152
153 TEST_F(BasicServer, ProcessPacket_InvalidMethod_NothingIsInvoked) {
154   EXPECT_EQ(OkStatus(),
155             server_.ProcessPacket(
156                 EncodeRequest(PacketType::REQUEST, 1, 42, 101), output_));
157
158   EXPECT_EQ(0u, service_.method(100).last_channel_id());
159   EXPECT_EQ(0u, service_.method(200).last_channel_id());
160 }
161
162 TEST_F(BasicServer, ProcessPacket_InvalidMethod_SendsError) {
163   EXPECT_EQ(OkStatus(),
164             server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 27),
165                                   output_));
166
167   const Packet& packet = output_.sent_packet();
168   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
169   EXPECT_EQ(packet.channel_id(), 1u);
170   EXPECT_EQ(packet.service_id(), 42u);
171   EXPECT_EQ(packet.method_id(), 27u);  // No method ID 27
172   EXPECT_EQ(packet.status(), Status::NotFound());
173 }
174
175 TEST_F(BasicServer, ProcessPacket_InvalidService_SendsError) {
176   EXPECT_EQ(OkStatus(),
177             server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 43, 27),
178                                   output_));
179
180   const Packet& packet = output_.sent_packet();
181   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
182   EXPECT_EQ(packet.channel_id(), 1u);
183   EXPECT_EQ(packet.service_id(), 43u);  // No service ID 43
184   EXPECT_EQ(packet.method_id(), 27u);
185   EXPECT_EQ(packet.status(), Status::NotFound());
186 }
187
188 TEST_F(BasicServer, ProcessPacket_UnassignedChannel_AssignsToAvailableSlot) {
189   TestOutput<128> unassigned_output;
190   EXPECT_EQ(OkStatus(),
191             server_.ProcessPacket(
192                 EncodeRequest(PacketType::REQUEST, /*channel_id=*/99, 42, 100),
193                 unassigned_output));
194   EXPECT_EQ(channels_[2].id(), 99u);
195 }
196
197 TEST_F(BasicServer,
198        ProcessPacket_UnassignedChannel_SendsResourceExhaustedIfCannotAssign) {
199   channels_[2] = Channel::Create<3>(&output_);  // Occupy only available channel
200
201   EXPECT_EQ(OkStatus(),
202             server_.ProcessPacket(
203                 EncodeRequest(PacketType::REQUEST, /*channel_id=*/99, 42, 27),
204                 output_));
205
206   const Packet& packet = output_.sent_packet();
207   EXPECT_EQ(packet.status(), Status::ResourceExhausted());
208   EXPECT_EQ(packet.channel_id(), 99u);
209   EXPECT_EQ(packet.service_id(), 42u);
210   EXPECT_EQ(packet.method_id(), 27u);
211 }
212
213 TEST_F(BasicServer, ProcessPacket_Cancel_MethodNotActive_SendsError) {
214   // Set up a fake ServerWriter representing an ongoing RPC.
215   EXPECT_EQ(OkStatus(),
216             server_.ProcessPacket(
217                 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 42, 100),
218                 output_));
219
220   const Packet& packet = output_.sent_packet();
221   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
222   EXPECT_EQ(packet.channel_id(), 1u);
223   EXPECT_EQ(packet.service_id(), 42u);
224   EXPECT_EQ(packet.method_id(), 100u);
225   EXPECT_EQ(packet.status(), Status::FailedPrecondition());
226 }
227
228 class MethodPending : public BasicServer {
229  protected:
230   MethodPending()
231       : call_(static_cast<internal::Server&>(server_),
232               static_cast<internal::Channel&>(channels_[0]),
233               service_,
234               service_.method(100)),
235         writer_(call_) {
236     ASSERT_TRUE(writer_.open());
237   }
238
239   internal::ServerCall call_;
240   internal::BaseServerWriter writer_;
241 };
242
243 TEST_F(MethodPending, ProcessPacket_Cancel_ClosesServerWriter) {
244   EXPECT_EQ(OkStatus(),
245             server_.ProcessPacket(
246                 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 42, 100),
247                 output_));
248
249   EXPECT_FALSE(writer_.open());
250 }
251
252 TEST_F(MethodPending, ProcessPacket_Cancel_SendsStreamEndPacket) {
253   EXPECT_EQ(OkStatus(),
254             server_.ProcessPacket(
255                 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 42, 100),
256                 output_));
257
258   const Packet& packet = output_.sent_packet();
259   EXPECT_EQ(packet.type(), PacketType::SERVER_STREAM_END);
260   EXPECT_EQ(packet.channel_id(), 1u);
261   EXPECT_EQ(packet.service_id(), 42u);
262   EXPECT_EQ(packet.method_id(), 100u);
263   EXPECT_TRUE(packet.payload().empty());
264   EXPECT_EQ(packet.status(), Status::Cancelled());
265 }
266
267 TEST_F(MethodPending,
268        ProcessPacket_ClientError_ClosesServerWriterWithoutStreamEnd) {
269   EXPECT_EQ(OkStatus(),
270             server_.ProcessPacket(
271                 EncodeRequest(PacketType::CLIENT_ERROR, 1, 42, 100), output_));
272
273   EXPECT_FALSE(writer_.open());
274   EXPECT_EQ(output_.packet_count(), 0u);
275 }
276
277 TEST_F(MethodPending, ProcessPacket_Cancel_IncorrectChannel) {
278   EXPECT_EQ(OkStatus(),
279             server_.ProcessPacket(
280                 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 2, 42, 100),
281                 output_));
282
283   EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
284   EXPECT_EQ(output_.sent_packet().status(), Status::FailedPrecondition());
285   EXPECT_TRUE(writer_.open());
286 }
287
288 TEST_F(MethodPending, ProcessPacket_Cancel_IncorrectService) {
289   EXPECT_EQ(OkStatus(),
290             server_.ProcessPacket(
291                 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 43, 100),
292                 output_));
293
294   EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
295   EXPECT_EQ(output_.sent_packet().status(), Status::NotFound());
296   EXPECT_EQ(output_.sent_packet().service_id(), 43u);
297   EXPECT_EQ(output_.sent_packet().method_id(), 100u);
298   EXPECT_TRUE(writer_.open());
299 }
300
301 TEST_F(MethodPending, ProcessPacket_CancelIncorrectMethod) {
302   EXPECT_EQ(OkStatus(),
303             server_.ProcessPacket(
304                 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 42, 101),
305                 output_));
306   EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
307   EXPECT_EQ(output_.sent_packet().status(), Status::NotFound());
308   EXPECT_TRUE(writer_.open());
309 }
310
311 }  // namespace
312 }  // namespace pw::rpc