blob: 541000b3b3b8f466e399c1d604091e0a05f9fc09 [file] [log] [blame]
Alexei Frolov26e3ae62020-05-04 17:06:17 -07001// 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
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070017#include <array>
18#include <cstdint>
19
Alexei Frolov26e3ae62020-05-04 17:06:17 -070020#include "gtest/gtest.h"
Wyatt Heplerf298de42021-03-19 15:06:36 -070021#include "pw_assert/check.h"
Wyatt Heplercbd09c22020-09-15 11:17:24 -070022#include "pw_rpc/internal/method.h"
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070023#include "pw_rpc/internal/packet.h"
Wyatt Heplercbd09c22020-09-15 11:17:24 -070024#include "pw_rpc/internal/test_method.h"
Alexei Frolov9a4d6bf2020-08-04 10:33:26 -070025#include "pw_rpc/service.h"
Wyatt Hepler8aa02922020-07-17 08:54:37 -070026#include "pw_rpc_private/internal_test_utils.h"
Alexei Frolov26e3ae62020-05-04 17:06:17 -070027
28namespace pw::rpc {
29namespace {
30
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070031using std::byte;
32
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070033using internal::Packet;
34using internal::PacketType;
Wyatt Heplercbd09c22020-09-15 11:17:24 -070035using internal::TestMethod;
Alexei Frolova4d71502020-10-14 12:43:14 -070036using internal::TestMethodUnion;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070037
Alexei Frolov9a4d6bf2020-08-04 10:33:26 -070038class TestService : public Service {
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070039 public:
40 TestService(uint32_t service_id)
Alexei Frolov9a4d6bf2020-08-04 10:33:26 -070041 : Service(service_id, methods_),
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070042 methods_{
Wyatt Heplercbd09c22020-09-15 11:17:24 -070043 TestMethod(100),
44 TestMethod(200),
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070045 } {}
46
Alexei Frolova4d71502020-10-14 12:43:14 -070047 const TestMethod& method(uint32_t id) {
48 for (TestMethodUnion& method : methods_) {
49 if (method.method().id() == id) {
50 return method.test_method();
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070051 }
52 }
53
54 PW_CRASH("Invalid method ID %u", static_cast<unsigned>(id));
55 }
56
57 private:
Alexei Frolova4d71502020-10-14 12:43:14 -070058 std::array<TestMethodUnion, 2> methods_;
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070059};
60
61class BasicServer : public ::testing::Test {
62 protected:
63 static constexpr byte kDefaultPayload[] = {
64 byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
65
66 BasicServer()
Wyatt Hepler51a2eb72020-06-04 14:47:00 -070067 : channels_{
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070068 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
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070077 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) {
Alexei Frolov3f2d0082020-10-04 22:30:39 -070083 auto result = Packet(type, channel_id, service_id, method_id, payload)
84 .Encode(request_buffer_);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080085 EXPECT_EQ(OkStatus(), result.status());
Alexei Frolov3f2d0082020-10-04 22:30:39 -070086 return result.value_or(ConstByteSpan());
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070087 }
88
Wyatt Hepleraf835682020-06-17 11:42:53 -070089 TestOutput<128> output_;
90 std::array<Channel, 3> channels_;
91 Server server_;
92 TestService service_;
93
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070094 private:
95 byte request_buffer_[64];
96};
97
98TEST_F(BasicServer, ProcessPacket_ValidMethod_InvokesMethod) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080099 EXPECT_EQ(OkStatus(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700100 server_.ProcessPacket(
101 EncodeRequest(PacketType::REQUEST, 1, 42, 100), output_));
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700102
Wyatt Heplercbd09c22020-09-15 11:17:24 -0700103 const TestMethod& method = service_.method(100);
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700104 EXPECT_EQ(1u, method.last_channel_id());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700105 ASSERT_EQ(sizeof(kDefaultPayload), method.last_request().payload().size());
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700106 EXPECT_EQ(std::memcmp(kDefaultPayload,
Wyatt Hepler712d3672020-07-13 15:52:11 -0700107 method.last_request().payload().data(),
108 method.last_request().payload().size()),
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700109 0);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700110}
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700111
Wyatt Hepleraf835682020-06-17 11:42:53 -0700112TEST_F(BasicServer, ProcessPacket_IncompletePacket_NothingIsInvoked) {
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700113 EXPECT_EQ(Status::DataLoss(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700114 server_.ProcessPacket(
115 EncodeRequest(PacketType::REQUEST, 0, 42, 101), output_));
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700116 EXPECT_EQ(Status::DataLoss(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700117 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 0, 101),
118 output_));
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700119 EXPECT_EQ(Status::DataLoss(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700120 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 0),
121 output_));
Wyatt Hepleraf835682020-06-17 11:42:53 -0700122
123 EXPECT_EQ(0u, service_.method(100).last_channel_id());
124 EXPECT_EQ(0u, service_.method(200).last_channel_id());
125}
126
Wyatt Hepler712d3672020-07-13 15:52:11 -0700127TEST_F(BasicServer, ProcessPacket_NoChannel_SendsNothing) {
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700128 EXPECT_EQ(Status::DataLoss(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700129 server_.ProcessPacket(
130 EncodeRequest(PacketType::REQUEST, 0, 42, 101), output_));
Wyatt Hepler712d3672020-07-13 15:52:11 -0700131
132 EXPECT_EQ(output_.packet_count(), 0u);
133}
134
135TEST_F(BasicServer, ProcessPacket_NoService_SendsDataLoss) {
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700136 EXPECT_EQ(Status::DataLoss(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700137 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 0, 101),
138 output_));
Wyatt Hepler712d3672020-07-13 15:52:11 -0700139
Wyatt Hepler0f262352020-07-29 09:51:27 -0700140 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700141 EXPECT_EQ(output_.sent_packet().status(), Status::DataLoss());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700142}
143
144TEST_F(BasicServer, ProcessPacket_NoMethod_SendsDataLoss) {
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700145 EXPECT_EQ(Status::DataLoss(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700146 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 0),
147 output_));
Wyatt Hepler712d3672020-07-13 15:52:11 -0700148
Wyatt Hepler0f262352020-07-29 09:51:27 -0700149 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700150 EXPECT_EQ(output_.sent_packet().status(), Status::DataLoss());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700151}
152
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700153TEST_F(BasicServer, ProcessPacket_InvalidMethod_NothingIsInvoked) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800154 EXPECT_EQ(OkStatus(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700155 server_.ProcessPacket(
156 EncodeRequest(PacketType::REQUEST, 1, 42, 101), output_));
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700157
158 EXPECT_EQ(0u, service_.method(100).last_channel_id());
159 EXPECT_EQ(0u, service_.method(200).last_channel_id());
160}
161
Wyatt Hepler712d3672020-07-13 15:52:11 -0700162TEST_F(BasicServer, ProcessPacket_InvalidMethod_SendsError) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800163 EXPECT_EQ(OkStatus(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700164 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 27),
165 output_));
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700166
Wyatt Hepler712d3672020-07-13 15:52:11 -0700167 const Packet& packet = output_.sent_packet();
Wyatt Hepler0f262352020-07-29 09:51:27 -0700168 EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700169 EXPECT_EQ(packet.channel_id(), 1u);
170 EXPECT_EQ(packet.service_id(), 42u);
Wyatt Hepler712d3672020-07-13 15:52:11 -0700171 EXPECT_EQ(packet.method_id(), 27u); // No method ID 27
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700172 EXPECT_EQ(packet.status(), Status::NotFound());
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700173}
174
Wyatt Hepler712d3672020-07-13 15:52:11 -0700175TEST_F(BasicServer, ProcessPacket_InvalidService_SendsError) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800176 EXPECT_EQ(OkStatus(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700177 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 43, 27),
178 output_));
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700179
Wyatt Hepler712d3672020-07-13 15:52:11 -0700180 const Packet& packet = output_.sent_packet();
Wyatt Hepler0f262352020-07-29 09:51:27 -0700181 EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700182 EXPECT_EQ(packet.channel_id(), 1u);
Wyatt Hepler60161aa2020-07-21 23:29:47 -0700183 EXPECT_EQ(packet.service_id(), 43u); // No service ID 43
184 EXPECT_EQ(packet.method_id(), 27u);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700185 EXPECT_EQ(packet.status(), Status::NotFound());
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700186}
187
Wyatt Hepler712d3672020-07-13 15:52:11 -0700188TEST_F(BasicServer, ProcessPacket_UnassignedChannel_AssignsToAvailableSlot) {
Wyatt Hepler51a2eb72020-06-04 14:47:00 -0700189 TestOutput<128> unassigned_output;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800190 EXPECT_EQ(OkStatus(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700191 server_.ProcessPacket(
192 EncodeRequest(PacketType::REQUEST, /*channel_id=*/99, 42, 100),
193 unassigned_output));
Wyatt Hepler712d3672020-07-13 15:52:11 -0700194 EXPECT_EQ(channels_[2].id(), 99u);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700195}
196
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700197TEST_F(BasicServer,
198 ProcessPacket_UnassignedChannel_SendsResourceExhaustedIfCannotAssign) {
199 channels_[2] = Channel::Create<3>(&output_); // Occupy only available channel
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700200
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800201 EXPECT_EQ(OkStatus(),
Wyatt Hepler0f262352020-07-29 09:51:27 -0700202 server_.ProcessPacket(
203 EncodeRequest(PacketType::REQUEST, /*channel_id=*/99, 42, 27),
204 output_));
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700205
Wyatt Hepler712d3672020-07-13 15:52:11 -0700206 const Packet& packet = output_.sent_packet();
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700207 EXPECT_EQ(packet.status(), Status::ResourceExhausted());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700208 EXPECT_EQ(packet.channel_id(), 99u);
209 EXPECT_EQ(packet.service_id(), 42u);
210 EXPECT_EQ(packet.method_id(), 27u);
Alexei Frolov26e3ae62020-05-04 17:06:17 -0700211}
212
Wyatt Hepler712d3672020-07-13 15:52:11 -0700213TEST_F(BasicServer, ProcessPacket_Cancel_MethodNotActive_SendsError) {
Wyatt Hepleraf835682020-06-17 11:42:53 -0700214 // Set up a fake ServerWriter representing an ongoing RPC.
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800215 EXPECT_EQ(OkStatus(),
Wyatt Heplera9211162021-06-12 15:40:11 -0700216 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 42, 100),
217 output_));
Wyatt Hepleraf835682020-06-17 11:42:53 -0700218
Wyatt Hepler712d3672020-07-13 15:52:11 -0700219 const Packet& packet = output_.sent_packet();
Wyatt Hepler0f262352020-07-29 09:51:27 -0700220 EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
Wyatt Hepler712d3672020-07-13 15:52:11 -0700221 EXPECT_EQ(packet.channel_id(), 1u);
222 EXPECT_EQ(packet.service_id(), 42u);
223 EXPECT_EQ(packet.method_id(), 100u);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700224 EXPECT_EQ(packet.status(), Status::FailedPrecondition());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700225}
Wyatt Hepleraf835682020-06-17 11:42:53 -0700226
Wyatt Hepler712d3672020-07-13 15:52:11 -0700227class MethodPending : public BasicServer {
228 protected:
229 MethodPending()
230 : call_(static_cast<internal::Server&>(server_),
231 static_cast<internal::Channel&>(channels_[0]),
232 service_,
233 service_.method(100)),
234 writer_(call_) {
235 ASSERT_TRUE(writer_.open());
236 }
237
238 internal::ServerCall call_;
239 internal::BaseServerWriter writer_;
240};
241
242TEST_F(MethodPending, ProcessPacket_Cancel_ClosesServerWriter) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800243 EXPECT_EQ(OkStatus(),
Wyatt Heplera9211162021-06-12 15:40:11 -0700244 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 42, 100),
245 output_));
Wyatt Hepler712d3672020-07-13 15:52:11 -0700246
247 EXPECT_FALSE(writer_.open());
248}
249
250TEST_F(MethodPending, ProcessPacket_Cancel_SendsStreamEndPacket) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800251 EXPECT_EQ(OkStatus(),
Wyatt Heplera9211162021-06-12 15:40:11 -0700252 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 42, 100),
253 output_));
Wyatt Hepler712d3672020-07-13 15:52:11 -0700254
255 const Packet& packet = output_.sent_packet();
Wyatt Hepler0f262352020-07-29 09:51:27 -0700256 EXPECT_EQ(packet.type(), PacketType::SERVER_STREAM_END);
Wyatt Hepleraf835682020-06-17 11:42:53 -0700257 EXPECT_EQ(packet.channel_id(), 1u);
258 EXPECT_EQ(packet.service_id(), 42u);
259 EXPECT_EQ(packet.method_id(), 100u);
260 EXPECT_TRUE(packet.payload().empty());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700261 EXPECT_EQ(packet.status(), Status::Cancelled());
Wyatt Hepleraf835682020-06-17 11:42:53 -0700262}
263
Alexei Frolov062ed182020-09-28 16:23:06 -0700264TEST_F(MethodPending,
265 ProcessPacket_ClientError_ClosesServerWriterWithoutStreamEnd) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800266 EXPECT_EQ(OkStatus(),
Alexei Frolov062ed182020-09-28 16:23:06 -0700267 server_.ProcessPacket(
268 EncodeRequest(PacketType::CLIENT_ERROR, 1, 42, 100), output_));
269
270 EXPECT_FALSE(writer_.open());
271 EXPECT_EQ(output_.packet_count(), 0u);
272}
273
Wyatt Hepler712d3672020-07-13 15:52:11 -0700274TEST_F(MethodPending, ProcessPacket_Cancel_IncorrectChannel) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800275 EXPECT_EQ(OkStatus(),
Wyatt Heplera9211162021-06-12 15:40:11 -0700276 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 2, 42, 100),
277 output_));
Wyatt Hepleraf835682020-06-17 11:42:53 -0700278
Wyatt Hepler0f262352020-07-29 09:51:27 -0700279 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700280 EXPECT_EQ(output_.sent_packet().status(), Status::FailedPrecondition());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700281 EXPECT_TRUE(writer_.open());
282}
283
284TEST_F(MethodPending, ProcessPacket_Cancel_IncorrectService) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800285 EXPECT_EQ(OkStatus(),
Wyatt Heplera9211162021-06-12 15:40:11 -0700286 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 43, 100),
287 output_));
Wyatt Hepler712d3672020-07-13 15:52:11 -0700288
Wyatt Hepler0f262352020-07-29 09:51:27 -0700289 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700290 EXPECT_EQ(output_.sent_packet().status(), Status::NotFound());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700291 EXPECT_EQ(output_.sent_packet().service_id(), 43u);
Wyatt Hepler60161aa2020-07-21 23:29:47 -0700292 EXPECT_EQ(output_.sent_packet().method_id(), 100u);
Wyatt Hepler712d3672020-07-13 15:52:11 -0700293 EXPECT_TRUE(writer_.open());
294}
295
296TEST_F(MethodPending, ProcessPacket_CancelIncorrectMethod) {
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800297 EXPECT_EQ(OkStatus(),
Wyatt Heplera9211162021-06-12 15:40:11 -0700298 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 42, 101),
299 output_));
Wyatt Hepler0f262352020-07-29 09:51:27 -0700300 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700301 EXPECT_EQ(output_.sent_packet().status(), Status::NotFound());
Wyatt Hepler712d3672020-07-13 15:52:11 -0700302 EXPECT_TRUE(writer_.open());
Wyatt Hepleraf835682020-06-17 11:42:53 -0700303}
304
Alexei Frolov26e3ae62020-05-04 17:06:17 -0700305} // namespace
306} // namespace pw::rpc