1 // Copyright 2020 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
15 #include "pw_rpc/server.h"
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"
33 using internal::Packet;
34 using internal::PacketType;
35 using internal::TestMethod;
36 using internal::TestMethodUnion;
38 class TestService : public Service {
40 TestService(uint32_t service_id)
41 : Service(service_id, methods_),
47 const TestMethod& method(uint32_t id) {
48 for (TestMethodUnion& method : methods_) {
49 if (method.method().id() == id) {
50 return method.test_method();
54 PW_CRASH("Invalid method ID %u", static_cast<unsigned>(id));
58 std::array<TestMethodUnion, 2> methods_;
61 class BasicServer : public ::testing::Test {
63 static constexpr byte kDefaultPayload[] = {
64 byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
68 Channel::Create<1>(&output_),
69 Channel::Create<2>(&output_),
70 Channel(), // available for assignment
74 server_.RegisterService(service_);
77 std::span<const byte> EncodeRequest(
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());
89 TestOutput<128> output_;
90 std::array<Channel, 3> channels_;
95 byte request_buffer_[64];
98 TEST_F(BasicServer, ProcessPacket_ValidMethod_InvokesMethod) {
100 server_.ProcessPacket(
101 EncodeRequest(PacketType::REQUEST, 1, 42, 100), output_));
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()),
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),
119 EXPECT_EQ(Status::DataLoss(),
120 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 0),
123 EXPECT_EQ(0u, service_.method(100).last_channel_id());
124 EXPECT_EQ(0u, service_.method(200).last_channel_id());
127 TEST_F(BasicServer, ProcessPacket_NoChannel_SendsNothing) {
128 EXPECT_EQ(Status::DataLoss(),
129 server_.ProcessPacket(
130 EncodeRequest(PacketType::REQUEST, 0, 42, 101), output_));
132 EXPECT_EQ(output_.packet_count(), 0u);
135 TEST_F(BasicServer, ProcessPacket_NoService_SendsDataLoss) {
136 EXPECT_EQ(Status::DataLoss(),
137 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 0, 101),
140 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
141 EXPECT_EQ(output_.sent_packet().status(), Status::DataLoss());
144 TEST_F(BasicServer, ProcessPacket_NoMethod_SendsDataLoss) {
145 EXPECT_EQ(Status::DataLoss(),
146 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 0),
149 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
150 EXPECT_EQ(output_.sent_packet().status(), Status::DataLoss());
153 TEST_F(BasicServer, ProcessPacket_InvalidMethod_NothingIsInvoked) {
154 EXPECT_EQ(OkStatus(),
155 server_.ProcessPacket(
156 EncodeRequest(PacketType::REQUEST, 1, 42, 101), output_));
158 EXPECT_EQ(0u, service_.method(100).last_channel_id());
159 EXPECT_EQ(0u, service_.method(200).last_channel_id());
162 TEST_F(BasicServer, ProcessPacket_InvalidMethod_SendsError) {
163 EXPECT_EQ(OkStatus(),
164 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 42, 27),
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());
175 TEST_F(BasicServer, ProcessPacket_InvalidService_SendsError) {
176 EXPECT_EQ(OkStatus(),
177 server_.ProcessPacket(EncodeRequest(PacketType::REQUEST, 1, 43, 27),
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());
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),
194 EXPECT_EQ(channels_[2].id(), 99u);
198 ProcessPacket_UnassignedChannel_SendsResourceExhaustedIfCannotAssign) {
199 channels_[2] = Channel::Create<3>(&output_); // Occupy only available channel
201 EXPECT_EQ(OkStatus(),
202 server_.ProcessPacket(
203 EncodeRequest(PacketType::REQUEST, /*channel_id=*/99, 42, 27),
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);
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),
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());
228 class MethodPending : public BasicServer {
231 : call_(static_cast<internal::Server&>(server_),
232 static_cast<internal::Channel&>(channels_[0]),
234 service_.method(100)),
236 ASSERT_TRUE(writer_.open());
239 internal::ServerCall call_;
240 internal::BaseServerWriter writer_;
243 TEST_F(MethodPending, ProcessPacket_Cancel_ClosesServerWriter) {
244 EXPECT_EQ(OkStatus(),
245 server_.ProcessPacket(
246 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 42, 100),
249 EXPECT_FALSE(writer_.open());
252 TEST_F(MethodPending, ProcessPacket_Cancel_SendsStreamEndPacket) {
253 EXPECT_EQ(OkStatus(),
254 server_.ProcessPacket(
255 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 42, 100),
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());
267 TEST_F(MethodPending,
268 ProcessPacket_ClientError_ClosesServerWriterWithoutStreamEnd) {
269 EXPECT_EQ(OkStatus(),
270 server_.ProcessPacket(
271 EncodeRequest(PacketType::CLIENT_ERROR, 1, 42, 100), output_));
273 EXPECT_FALSE(writer_.open());
274 EXPECT_EQ(output_.packet_count(), 0u);
277 TEST_F(MethodPending, ProcessPacket_Cancel_IncorrectChannel) {
278 EXPECT_EQ(OkStatus(),
279 server_.ProcessPacket(
280 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 2, 42, 100),
283 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
284 EXPECT_EQ(output_.sent_packet().status(), Status::FailedPrecondition());
285 EXPECT_TRUE(writer_.open());
288 TEST_F(MethodPending, ProcessPacket_Cancel_IncorrectService) {
289 EXPECT_EQ(OkStatus(),
290 server_.ProcessPacket(
291 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 43, 100),
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());
301 TEST_F(MethodPending, ProcessPacket_CancelIncorrectMethod) {
302 EXPECT_EQ(OkStatus(),
303 server_.ProcessPacket(
304 EncodeRequest(PacketType::CANCEL_SERVER_STREAM, 1, 42, 101),
306 EXPECT_EQ(output_.sent_packet().type(), PacketType::SERVER_ERROR);
307 EXPECT_EQ(output_.sent_packet().status(), Status::NotFound());
308 EXPECT_TRUE(writer_.open());
312 } // namespace pw::rpc