blob: 47b62e56d719b9050e18533aef4351c9b1861829 [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 Hepler80f26ff2020-06-01 09:30:17 -070021#include "pw_assert/assert.h"
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070022#include "pw_rpc/internal/packet.h"
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070023#include "pw_rpc/internal/service.h"
Wyatt Heplercb9d9572020-06-01 11:25:58 -070024#include "pw_rpc_private/test_utils.h"
Alexei Frolov26e3ae62020-05-04 17:06:17 -070025
26namespace pw::rpc {
27namespace {
28
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070029using std::byte;
30
31using internal::Method;
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070032using internal::Packet;
33using internal::PacketType;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070034
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070035class TestService : public internal::Service {
36 public:
37 TestService(uint32_t service_id)
38 : internal::Service(service_id, methods_),
39 methods_{
40 Method(100),
41 Method(200),
42 } {}
43
44 Method& method(uint32_t id) {
45 for (Method& method : methods_) {
46 if (method.id() == id) {
47 return method;
48 }
49 }
50
51 PW_CRASH("Invalid method ID %u", static_cast<unsigned>(id));
52 }
53
54 private:
55 std::array<Method, 2> methods_;
56};
57
58class BasicServer : public ::testing::Test {
59 protected:
60 static constexpr byte kDefaultPayload[] = {
61 byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
62
63 BasicServer()
Wyatt Hepler51a2eb72020-06-04 14:47:00 -070064 : channels_{
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070065 Channel::Create<1>(&output_),
66 Channel::Create<2>(&output_),
67 Channel(), // available for assignment
68 },
69 server_(channels_),
70 service_(42) {
71 server_.RegisterService(service_);
72 }
73
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070074 std::span<const byte> EncodeRequest(
75 PacketType type,
76 uint32_t channel_id,
77 uint32_t service_id,
78 uint32_t method_id,
79 std::span<const byte> payload = kDefaultPayload) {
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070080 auto sws = Packet(type, channel_id, service_id, method_id, payload)
81 .Encode(request_buffer_);
82 EXPECT_EQ(Status::OK, sws.status());
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070083 return std::span(request_buffer_, sws.size());
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070084 }
85
Wyatt Hepleraf835682020-06-17 11:42:53 -070086 TestOutput<128> output_;
87 std::array<Channel, 3> channels_;
88 Server server_;
89 TestService service_;
90
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070091 private:
92 byte request_buffer_[64];
93};
94
95TEST_F(BasicServer, ProcessPacket_ValidMethod_InvokesMethod) {
96 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 100), output_);
97
98 const Method& method = service_.method(100);
99 EXPECT_EQ(1u, method.last_channel_id());
100 EXPECT_EQ(sizeof(kDefaultPayload), method.last_request().size());
101 EXPECT_EQ(std::memcmp(kDefaultPayload,
102 method.last_request().data(),
103 method.last_request().size()),
104 0);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700105}
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700106
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700107TEST_F(BasicServer, ProcessPacket_ValidMethod_SendsOkResponse) {
108 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 100), output_);
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700109
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700110 Packet packet = Packet::FromBuffer(output_.sent_packet());
Wyatt Hepleraf835682020-06-17 11:42:53 -0700111 EXPECT_EQ(packet.type(), PacketType::RPC);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700112 EXPECT_EQ(packet.channel_id(), 1u);
113 EXPECT_EQ(packet.service_id(), 42u);
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700114 EXPECT_EQ(packet.method_id(), 100u);
115 EXPECT_TRUE(packet.payload().empty());
116 EXPECT_EQ(packet.status(), Status::OK);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700117}
118
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700119TEST_F(BasicServer, ProcessPacket_ValidMethod_SendsErrorResponse) {
120 constexpr byte resp[] = {byte{0xf0}, byte{0x0d}};
121 service_.method(200).set_response(resp);
122 service_.method(200).set_status(Status::FAILED_PRECONDITION);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700123
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700124 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 2, 42, 200), output_);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700125
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700126 Packet packet = Packet::FromBuffer(output_.sent_packet());
127 EXPECT_EQ(packet.channel_id(), 2u);
128 EXPECT_EQ(packet.service_id(), 42u);
129 EXPECT_EQ(packet.method_id(), 200u);
130 EXPECT_EQ(packet.status(), Status::FAILED_PRECONDITION);
131 ASSERT_EQ(sizeof(resp), packet.payload().size());
132 EXPECT_EQ(std::memcmp(packet.payload().data(), resp, sizeof(resp)), 0);
133}
134
Wyatt Hepleraf835682020-06-17 11:42:53 -0700135TEST_F(BasicServer, ProcessPacket_IncompletePacket_NothingIsInvoked) {
136 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 0, 42, 101), output_);
137 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 0, 101), output_);
138 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 0), output_);
139
140 EXPECT_EQ(0u, service_.method(100).last_channel_id());
141 EXPECT_EQ(0u, service_.method(200).last_channel_id());
142}
143
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700144TEST_F(BasicServer, ProcessPacket_InvalidMethod_NothingIsInvoked) {
145 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 101), output_);
146
147 EXPECT_EQ(0u, service_.method(100).last_channel_id());
148 EXPECT_EQ(0u, service_.method(200).last_channel_id());
149}
150
151TEST_F(BasicServer, ProcessPacket_InvalidMethod_SendsNotFound) {
152 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 27), output_);
153
154 Packet packet = Packet::FromBuffer(output_.sent_packet());
Wyatt Hepleraf835682020-06-17 11:42:53 -0700155 EXPECT_EQ(packet.type(), PacketType::RPC);
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700156 EXPECT_EQ(packet.channel_id(), 1u);
157 EXPECT_EQ(packet.service_id(), 42u);
158 EXPECT_EQ(packet.method_id(), 0u); // No method ID 27
159 EXPECT_EQ(packet.status(), Status::NOT_FOUND);
160}
161
162TEST_F(BasicServer, ProcessPacket_InvalidService_SendsNotFound) {
163 server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 43, 27), output_);
164
165 Packet packet = Packet::FromBuffer(output_.sent_packet());
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700166 EXPECT_EQ(packet.status(), Status::NOT_FOUND);
167 EXPECT_EQ(packet.channel_id(), 1u);
168 EXPECT_EQ(packet.service_id(), 0u);
169}
170
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700171TEST_F(BasicServer, ProcessPacket_UnassignedChannel_AssignsToAvalableSlot) {
Wyatt Hepler51a2eb72020-06-04 14:47:00 -0700172 TestOutput<128> unassigned_output;
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700173 server_.ProcessPacket(
174 EncodeRequest(PacketType::RPC, /*channel_id=*/99, 42, 27),
175 unassigned_output);
176 ASSERT_EQ(channels_[2].id(), 99u);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700177
178 Packet packet = Packet::FromBuffer(unassigned_output.sent_packet());
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700179 EXPECT_EQ(packet.channel_id(), 99u);
180 EXPECT_EQ(packet.service_id(), 42u);
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700181 EXPECT_EQ(packet.method_id(), 0u); // No method ID 27
182 EXPECT_EQ(packet.status(), Status::NOT_FOUND);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700183}
184
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700185TEST_F(BasicServer,
186 ProcessPacket_UnassignedChannel_SendsResourceExhaustedIfCannotAssign) {
187 channels_[2] = Channel::Create<3>(&output_); // Occupy only available channel
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700188
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700189 server_.ProcessPacket(
190 EncodeRequest(PacketType::RPC, /*channel_id=*/99, 42, 27), output_);
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700191
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700192 Packet packet = Packet::FromBuffer(output_.sent_packet());
Alexei Frolov33a1e8f2020-05-26 08:39:32 -0700193 EXPECT_EQ(packet.status(), Status::RESOURCE_EXHAUSTED);
194 EXPECT_EQ(packet.channel_id(), 0u);
195 EXPECT_EQ(packet.service_id(), 0u);
196 EXPECT_EQ(packet.method_id(), 0u);
Alexei Frolov26e3ae62020-05-04 17:06:17 -0700197}
198
Wyatt Hepleraf835682020-06-17 11:42:53 -0700199TEST_F(BasicServer, ProcessPacket_Cancel_ClosesServerWriter) {
200 // Set up a fake ServerWriter representing an ongoing RPC.
201 internal::ServerCall call(static_cast<internal::Server&>(server_),
202 static_cast<internal::Channel&>(channels_[0]),
203 service_,
204 service_.method(100));
205 internal::BaseServerWriter writer(call);
206 ASSERT_TRUE(writer.open());
207
208 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 42, 100), output_);
209
210 EXPECT_FALSE(writer.open());
211
212 Packet packet = Packet::FromBuffer(output_.sent_packet());
213 EXPECT_EQ(packet.type(), PacketType::CANCEL);
214 EXPECT_EQ(packet.channel_id(), 1u);
215 EXPECT_EQ(packet.service_id(), 42u);
216 EXPECT_EQ(packet.method_id(), 100u);
217 EXPECT_TRUE(packet.payload().empty());
218 EXPECT_EQ(packet.status(), Status::OK);
219}
220
221TEST_F(BasicServer, ProcessPacket_Cancel_UnknownIdIsIgnored) {
222 internal::ServerCall call(static_cast<internal::Server&>(server_),
223 static_cast<internal::Channel&>(channels_[0]),
224 service_,
225 service_.method(100));
226 internal::BaseServerWriter writer(call);
227 ASSERT_TRUE(writer.open());
228
229 // Send packets with incorrect channel, service, and method ID.
230 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 2, 42, 100), output_);
231 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 43, 100), output_);
232 server_.ProcessPacket(EncodeRequest(PacketType::CANCEL, 1, 42, 101), output_);
233
234 EXPECT_TRUE(writer.open());
235 EXPECT_TRUE(output_.sent_packet().empty());
236}
237
Alexei Frolov26e3ae62020-05-04 17:06:17 -0700238} // namespace
239} // namespace pw::rpc