xref: /aosp_15_r20/external/pigweed/pw_rpc/server_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/server.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include <array>
18*61c4878aSAndroid Build Coastguard Worker #include <cstdint>
19*61c4878aSAndroid Build Coastguard Worker 
20*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/call.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/method.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/packet.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/test_utils.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/service.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc_private/fake_server_reader_writer.h"
27*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc_private/test_method.h"
28*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
29*61c4878aSAndroid Build Coastguard Worker 
30*61c4878aSAndroid Build Coastguard Worker namespace pw::rpc {
31*61c4878aSAndroid Build Coastguard Worker 
32*61c4878aSAndroid Build Coastguard Worker class ServerTestHelper {
33*61c4878aSAndroid Build Coastguard Worker  public:
FindMethod(Server & server,uint32_t service_id,uint32_t method_id)34*61c4878aSAndroid Build Coastguard Worker   static std::tuple<Service*, const internal::Method*> FindMethod(
35*61c4878aSAndroid Build Coastguard Worker       Server& server, uint32_t service_id, uint32_t method_id) {
36*61c4878aSAndroid Build Coastguard Worker     return server.FindMethod(service_id, method_id);
37*61c4878aSAndroid Build Coastguard Worker   }
38*61c4878aSAndroid Build Coastguard Worker };
39*61c4878aSAndroid Build Coastguard Worker 
40*61c4878aSAndroid Build Coastguard Worker namespace {
41*61c4878aSAndroid Build Coastguard Worker 
42*61c4878aSAndroid Build Coastguard Worker using std::byte;
43*61c4878aSAndroid Build Coastguard Worker 
44*61c4878aSAndroid Build Coastguard Worker using internal::Packet;
45*61c4878aSAndroid Build Coastguard Worker using internal::TestMethod;
46*61c4878aSAndroid Build Coastguard Worker using internal::TestMethodUnion;
47*61c4878aSAndroid Build Coastguard Worker using internal::pwpb::PacketType;
48*61c4878aSAndroid Build Coastguard Worker 
49*61c4878aSAndroid Build Coastguard Worker class TestService : public Service {
50*61c4878aSAndroid Build Coastguard Worker  public:
TestService(uint32_t service_id)51*61c4878aSAndroid Build Coastguard Worker   TestService(uint32_t service_id)
52*61c4878aSAndroid Build Coastguard Worker       : Service(service_id, methods_),
53*61c4878aSAndroid Build Coastguard Worker         methods_{
54*61c4878aSAndroid Build Coastguard Worker             TestMethod(100, MethodType::kBidirectionalStreaming),
55*61c4878aSAndroid Build Coastguard Worker             TestMethod(200),
56*61c4878aSAndroid Build Coastguard Worker         } {}
57*61c4878aSAndroid Build Coastguard Worker 
method(uint32_t id)58*61c4878aSAndroid Build Coastguard Worker   const TestMethod& method(uint32_t id) {
59*61c4878aSAndroid Build Coastguard Worker     for (TestMethodUnion& method : methods_) {
60*61c4878aSAndroid Build Coastguard Worker       if (method.method().id() == id) {
61*61c4878aSAndroid Build Coastguard Worker         return method.test_method();
62*61c4878aSAndroid Build Coastguard Worker       }
63*61c4878aSAndroid Build Coastguard Worker     }
64*61c4878aSAndroid Build Coastguard Worker 
65*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("Invalid method ID %u", static_cast<unsigned>(id));
66*61c4878aSAndroid Build Coastguard Worker   }
67*61c4878aSAndroid Build Coastguard Worker 
68*61c4878aSAndroid Build Coastguard Worker  private:
69*61c4878aSAndroid Build Coastguard Worker   std::array<TestMethodUnion, 2> methods_;
70*61c4878aSAndroid Build Coastguard Worker };
71*61c4878aSAndroid Build Coastguard Worker 
72*61c4878aSAndroid Build Coastguard Worker class EmptyService : public Service {
73*61c4878aSAndroid Build Coastguard Worker  public:
EmptyService()74*61c4878aSAndroid Build Coastguard Worker   constexpr EmptyService() : Service(200, methods_) {}
75*61c4878aSAndroid Build Coastguard Worker 
76*61c4878aSAndroid Build Coastguard Worker  private:
77*61c4878aSAndroid Build Coastguard Worker   static constexpr std::array<TestMethodUnion, 0> methods_ = {};
78*61c4878aSAndroid Build Coastguard Worker };
79*61c4878aSAndroid Build Coastguard Worker 
80*61c4878aSAndroid Build Coastguard Worker uint32_t kDefaultCallId = 24601;
81*61c4878aSAndroid Build Coastguard Worker 
82*61c4878aSAndroid Build Coastguard Worker class BasicServer : public ::testing::Test {
83*61c4878aSAndroid Build Coastguard Worker  protected:
84*61c4878aSAndroid Build Coastguard Worker   static constexpr byte kDefaultPayload[] = {
85*61c4878aSAndroid Build Coastguard Worker       byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
86*61c4878aSAndroid Build Coastguard Worker 
BasicServer()87*61c4878aSAndroid Build Coastguard Worker   BasicServer()
88*61c4878aSAndroid Build Coastguard Worker       : channels_{
89*61c4878aSAndroid Build Coastguard Worker             Channel::Create<1>(&output_),
90*61c4878aSAndroid Build Coastguard Worker             Channel::Create<2>(&output_),
91*61c4878aSAndroid Build Coastguard Worker             Channel(),  // available for assignment
92*61c4878aSAndroid Build Coastguard Worker         },
93*61c4878aSAndroid Build Coastguard Worker         server_(channels_),
94*61c4878aSAndroid Build Coastguard Worker         service_1_(1),
95*61c4878aSAndroid Build Coastguard Worker         service_42_(42) {
96*61c4878aSAndroid Build Coastguard Worker     server_.RegisterService(service_1_, service_42_, empty_service_);
97*61c4878aSAndroid Build Coastguard Worker   }
98*61c4878aSAndroid Build Coastguard Worker 
EncodePacket(PacketType type,uint32_t channel_id,uint32_t service_id,uint32_t method_id,uint32_t call_id=kDefaultCallId)99*61c4878aSAndroid Build Coastguard Worker   span<const byte> EncodePacket(PacketType type,
100*61c4878aSAndroid Build Coastguard Worker                                 uint32_t channel_id,
101*61c4878aSAndroid Build Coastguard Worker                                 uint32_t service_id,
102*61c4878aSAndroid Build Coastguard Worker                                 uint32_t method_id,
103*61c4878aSAndroid Build Coastguard Worker                                 uint32_t call_id = kDefaultCallId) {
104*61c4878aSAndroid Build Coastguard Worker     return EncodePacketWithBody(type,
105*61c4878aSAndroid Build Coastguard Worker                                 channel_id,
106*61c4878aSAndroid Build Coastguard Worker                                 service_id,
107*61c4878aSAndroid Build Coastguard Worker                                 method_id,
108*61c4878aSAndroid Build Coastguard Worker                                 call_id,
109*61c4878aSAndroid Build Coastguard Worker                                 kDefaultPayload,
110*61c4878aSAndroid Build Coastguard Worker                                 OkStatus());
111*61c4878aSAndroid Build Coastguard Worker   }
112*61c4878aSAndroid Build Coastguard Worker 
EncodeCancel(uint32_t channel_id=1,uint32_t service_id=42,uint32_t method_id=100,uint32_t call_id=kDefaultCallId)113*61c4878aSAndroid Build Coastguard Worker   span<const byte> EncodeCancel(uint32_t channel_id = 1,
114*61c4878aSAndroid Build Coastguard Worker                                 uint32_t service_id = 42,
115*61c4878aSAndroid Build Coastguard Worker                                 uint32_t method_id = 100,
116*61c4878aSAndroid Build Coastguard Worker                                 uint32_t call_id = kDefaultCallId) {
117*61c4878aSAndroid Build Coastguard Worker     return EncodePacketWithBody(PacketType::CLIENT_ERROR,
118*61c4878aSAndroid Build Coastguard Worker                                 channel_id,
119*61c4878aSAndroid Build Coastguard Worker                                 service_id,
120*61c4878aSAndroid Build Coastguard Worker                                 method_id,
121*61c4878aSAndroid Build Coastguard Worker                                 call_id,
122*61c4878aSAndroid Build Coastguard Worker                                 {},
123*61c4878aSAndroid Build Coastguard Worker                                 Status::Cancelled());
124*61c4878aSAndroid Build Coastguard Worker   }
125*61c4878aSAndroid Build Coastguard Worker 
126*61c4878aSAndroid Build Coastguard Worker   template <typename T = ConstByteSpan>
PacketForRpc(PacketType type,Status status=OkStatus (),T && payload={},uint32_t call_id=kDefaultCallId)127*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan PacketForRpc(PacketType type,
128*61c4878aSAndroid Build Coastguard Worker                              Status status = OkStatus(),
129*61c4878aSAndroid Build Coastguard Worker                              T&& payload = {},
130*61c4878aSAndroid Build Coastguard Worker                              uint32_t call_id = kDefaultCallId) {
131*61c4878aSAndroid Build Coastguard Worker     return EncodePacketWithBody(
132*61c4878aSAndroid Build Coastguard Worker         type, 1, 42, 100, call_id, as_bytes(span(payload)), status);
133*61c4878aSAndroid Build Coastguard Worker   }
134*61c4878aSAndroid Build Coastguard Worker 
135*61c4878aSAndroid Build Coastguard Worker   RawFakeChannelOutput<2> output_;
136*61c4878aSAndroid Build Coastguard Worker   std::array<Channel, 3> channels_;
137*61c4878aSAndroid Build Coastguard Worker   Server server_;
138*61c4878aSAndroid Build Coastguard Worker   TestService service_1_;
139*61c4878aSAndroid Build Coastguard Worker   TestService service_42_;
140*61c4878aSAndroid Build Coastguard Worker   EmptyService empty_service_;
141*61c4878aSAndroid Build Coastguard Worker 
142*61c4878aSAndroid Build Coastguard Worker  private:
143*61c4878aSAndroid Build Coastguard Worker   byte request_buffer_[64];
144*61c4878aSAndroid Build Coastguard Worker 
EncodePacketWithBody(PacketType type,uint32_t channel_id,uint32_t service_id,uint32_t method_id,uint32_t call_id,span<const byte> payload,Status status)145*61c4878aSAndroid Build Coastguard Worker   span<const byte> EncodePacketWithBody(PacketType type,
146*61c4878aSAndroid Build Coastguard Worker                                         uint32_t channel_id,
147*61c4878aSAndroid Build Coastguard Worker                                         uint32_t service_id,
148*61c4878aSAndroid Build Coastguard Worker                                         uint32_t method_id,
149*61c4878aSAndroid Build Coastguard Worker                                         uint32_t call_id,
150*61c4878aSAndroid Build Coastguard Worker                                         span<const byte> payload,
151*61c4878aSAndroid Build Coastguard Worker                                         Status status) {
152*61c4878aSAndroid Build Coastguard Worker     auto result =
153*61c4878aSAndroid Build Coastguard Worker         Packet(
154*61c4878aSAndroid Build Coastguard Worker             type, channel_id, service_id, method_id, call_id, payload, status)
155*61c4878aSAndroid Build Coastguard Worker             .Encode(request_buffer_);
156*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(OkStatus(), result.status());
157*61c4878aSAndroid Build Coastguard Worker     return result.value_or(ConstByteSpan());
158*61c4878aSAndroid Build Coastguard Worker   }
159*61c4878aSAndroid Build Coastguard Worker };
160*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,IsServiceRegistered)161*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, IsServiceRegistered) {
162*61c4878aSAndroid Build Coastguard Worker   TestService unregisteredService(0);
163*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(server_.IsServiceRegistered(unregisteredService));
164*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(server_.IsServiceRegistered(service_1_));
165*61c4878aSAndroid Build Coastguard Worker }
166*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_ValidMethodInService1_InvokesMethod)167*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_ValidMethodInService1_InvokesMethod) {
168*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
169*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
170*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 1, 100)));
171*61c4878aSAndroid Build Coastguard Worker 
172*61c4878aSAndroid Build Coastguard Worker   const TestMethod& method = service_1_.method(100);
173*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, method.last_channel_id());
174*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(sizeof(kDefaultPayload), method.last_request().payload().size());
175*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(kDefaultPayload,
176*61c4878aSAndroid Build Coastguard Worker                         method.last_request().payload().data(),
177*61c4878aSAndroid Build Coastguard Worker                         method.last_request().payload().size()),
178*61c4878aSAndroid Build Coastguard Worker             0);
179*61c4878aSAndroid Build Coastguard Worker }
180*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_ValidMethodInService42_InvokesMethod)181*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_ValidMethodInService42_InvokesMethod) {
182*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
183*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
184*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 42, 200)));
185*61c4878aSAndroid Build Coastguard Worker 
186*61c4878aSAndroid Build Coastguard Worker   const TestMethod& method = service_42_.method(200);
187*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, method.last_channel_id());
188*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(sizeof(kDefaultPayload), method.last_request().payload().size());
189*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(kDefaultPayload,
190*61c4878aSAndroid Build Coastguard Worker                         method.last_request().payload().data(),
191*61c4878aSAndroid Build Coastguard Worker                         method.last_request().payload().size()),
192*61c4878aSAndroid Build Coastguard Worker             0);
193*61c4878aSAndroid Build Coastguard Worker }
194*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,UnregisterService_CannotCallMethod)195*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, UnregisterService_CannotCallMethod) {
196*61c4878aSAndroid Build Coastguard Worker   const uint32_t kCallId = 8675309;
197*61c4878aSAndroid Build Coastguard Worker   server_.UnregisterService(service_1_, service_42_);
198*61c4878aSAndroid Build Coastguard Worker 
199*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(),
200*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
201*61c4878aSAndroid Build Coastguard Worker                 EncodePacket(PacketType::REQUEST, 1, 1, 100, kCallId)));
202*61c4878aSAndroid Build Coastguard Worker 
203*61c4878aSAndroid Build Coastguard Worker   const Packet& packet =
204*61c4878aSAndroid Build Coastguard Worker       static_cast<internal::test::FakeChannelOutput&>(output_).last_packet();
205*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
206*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.channel_id(), 1u);
207*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.service_id(), 1u);
208*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.method_id(), 100u);
209*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.call_id(), kCallId);
210*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.status(), Status::NotFound());
211*61c4878aSAndroid Build Coastguard Worker }
212*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,UnregisterService_AlreadyUnregistered_DoesNothing)213*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, UnregisterService_AlreadyUnregistered_DoesNothing) {
214*61c4878aSAndroid Build Coastguard Worker   server_.UnregisterService(service_42_, service_42_, service_42_);
215*61c4878aSAndroid Build Coastguard Worker   server_.UnregisterService(service_42_);
216*61c4878aSAndroid Build Coastguard Worker 
217*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
218*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
219*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 1, 100)));
220*61c4878aSAndroid Build Coastguard Worker 
221*61c4878aSAndroid Build Coastguard Worker   const TestMethod& method = service_1_.method(100);
222*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, method.last_channel_id());
223*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(sizeof(kDefaultPayload), method.last_request().payload().size());
224*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(kDefaultPayload,
225*61c4878aSAndroid Build Coastguard Worker                         method.last_request().payload().data(),
226*61c4878aSAndroid Build Coastguard Worker                         method.last_request().payload().size()),
227*61c4878aSAndroid Build Coastguard Worker             0);
228*61c4878aSAndroid Build Coastguard Worker }
229*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_IncompletePacket_NothingIsInvoked)230*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_IncompletePacket_NothingIsInvoked) {
231*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
232*61c4878aSAndroid Build Coastguard Worker       Status::DataLoss(),
233*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 0, 42, 101)));
234*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
235*61c4878aSAndroid Build Coastguard Worker       Status::DataLoss(),
236*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 0, 101)));
237*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::DataLoss(),
238*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 42, 0)));
239*61c4878aSAndroid Build Coastguard Worker 
240*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, service_42_.method(100).last_channel_id());
241*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, service_42_.method(200).last_channel_id());
242*61c4878aSAndroid Build Coastguard Worker }
243*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_NoChannel_SendsNothing)244*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_NoChannel_SendsNothing) {
245*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
246*61c4878aSAndroid Build Coastguard Worker       Status::DataLoss(),
247*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 0, 42, 101)));
248*61c4878aSAndroid Build Coastguard Worker 
249*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
250*61c4878aSAndroid Build Coastguard Worker }
251*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_NoService_SendsNothing)252*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_NoService_SendsNothing) {
253*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
254*61c4878aSAndroid Build Coastguard Worker       Status::DataLoss(),
255*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 0, 101)));
256*61c4878aSAndroid Build Coastguard Worker 
257*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
258*61c4878aSAndroid Build Coastguard Worker }
259*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_NoMethod_SendsNothing)260*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_NoMethod_SendsNothing) {
261*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::DataLoss(),
262*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 42, 0)));
263*61c4878aSAndroid Build Coastguard Worker 
264*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
265*61c4878aSAndroid Build Coastguard Worker }
266*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_InvalidMethod_NothingIsInvoked)267*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_InvalidMethod_NothingIsInvoked) {
268*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
269*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
270*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 42, 101)));
271*61c4878aSAndroid Build Coastguard Worker 
272*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, service_42_.method(100).last_channel_id());
273*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, service_42_.method(200).last_channel_id());
274*61c4878aSAndroid Build Coastguard Worker }
275*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_ClientErrorWithInvalidMethod_NoResponse)276*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_ClientErrorWithInvalidMethod_NoResponse) {
277*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(),
278*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
279*61c4878aSAndroid Build Coastguard Worker                 EncodePacket(PacketType::CLIENT_ERROR, 1, 42, 101)));
280*61c4878aSAndroid Build Coastguard Worker 
281*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, output_.total_packets());
282*61c4878aSAndroid Build Coastguard Worker }
283*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_InvalidMethod_SendsError)284*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_InvalidMethod_SendsError) {
285*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
286*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
287*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 42, 27)));
288*61c4878aSAndroid Build Coastguard Worker 
289*61c4878aSAndroid Build Coastguard Worker   const Packet& packet =
290*61c4878aSAndroid Build Coastguard Worker       static_cast<internal::test::FakeChannelOutput&>(output_).last_packet();
291*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
292*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.channel_id(), 1u);
293*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.service_id(), 42u);
294*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.method_id(), 27u);  // No method ID 27
295*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.status(), Status::NotFound());
296*61c4878aSAndroid Build Coastguard Worker }
297*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_InvalidService_SendsError)298*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_InvalidService_SendsError) {
299*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
300*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
301*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 43, 27)));
302*61c4878aSAndroid Build Coastguard Worker 
303*61c4878aSAndroid Build Coastguard Worker   const Packet& packet =
304*61c4878aSAndroid Build Coastguard Worker       static_cast<internal::test::FakeChannelOutput&>(output_).last_packet();
305*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
306*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.channel_id(), 1u);
307*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.service_id(), 43u);  // No service ID 43
308*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.method_id(), 27u);
309*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.status(), Status::NotFound());
310*61c4878aSAndroid Build Coastguard Worker }
311*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_UnassignedChannel)312*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_UnassignedChannel) {
313*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::Unavailable(),
314*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
315*61c4878aSAndroid Build Coastguard Worker                 EncodePacket(PacketType::REQUEST, /*channel_id=*/99, 42, 27)));
316*61c4878aSAndroid Build Coastguard Worker }
317*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_ClientErrorOnUnassignedChannel_NoResponse)318*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_ClientErrorOnUnassignedChannel_NoResponse) {
319*61c4878aSAndroid Build Coastguard Worker   channels_[2] = Channel::Create<3>(&output_);  // Occupy only available channel
320*61c4878aSAndroid Build Coastguard Worker 
321*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::Unavailable(),
322*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(EncodePacket(
323*61c4878aSAndroid Build Coastguard Worker                 PacketType::CLIENT_ERROR, /*channel_id=*/99, 42, 27)));
324*61c4878aSAndroid Build Coastguard Worker 
325*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, output_.total_packets());
326*61c4878aSAndroid Build Coastguard Worker }
327*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,ProcessPacket_Cancel_MethodNotActive_SendsNothing)328*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, ProcessPacket_Cancel_MethodNotActive_SendsNothing) {
329*61c4878aSAndroid Build Coastguard Worker   // Set up a fake ServerWriter representing an ongoing RPC.
330*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel(1, 42, 100)));
331*61c4878aSAndroid Build Coastguard Worker 
332*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
333*61c4878aSAndroid Build Coastguard Worker }
334*61c4878aSAndroid Build Coastguard Worker 
GetChannel(internal::Endpoint & endpoint,uint32_t id)335*61c4878aSAndroid Build Coastguard Worker const internal::ChannelBase* GetChannel(internal::Endpoint& endpoint,
336*61c4878aSAndroid Build Coastguard Worker                                         uint32_t id) {
337*61c4878aSAndroid Build Coastguard Worker   internal::RpcLockGuard lock;
338*61c4878aSAndroid Build Coastguard Worker   return endpoint.GetInternalChannel(id);
339*61c4878aSAndroid Build Coastguard Worker }
340*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,CloseChannel_NoCalls)341*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, CloseChannel_NoCalls) {
342*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(nullptr, GetChannel(server_, 2));
343*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.CloseChannel(2));
344*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, GetChannel(server_, 2));
345*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(output_.total_packets(), 0u);
346*61c4878aSAndroid Build Coastguard Worker }
347*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,CloseChannel_UnknownChannel)348*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, CloseChannel_UnknownChannel) {
349*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(nullptr, GetChannel(server_, 13579));
350*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::NotFound(), server_.CloseChannel(13579));
351*61c4878aSAndroid Build Coastguard Worker }
352*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,CloseChannel_PendingCall)353*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, CloseChannel_PendingCall) {
354*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(nullptr, GetChannel(server_, 1));
355*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<internal::Endpoint&>(server_).active_call_count(), 0u);
356*61c4878aSAndroid Build Coastguard Worker 
357*61c4878aSAndroid Build Coastguard Worker   internal::test::FakeServerReaderWriter call;
358*61c4878aSAndroid Build Coastguard Worker   service_42_.method(100).keep_call_active(call);
359*61c4878aSAndroid Build Coastguard Worker 
360*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
361*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
362*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(EncodePacket(PacketType::REQUEST, 1, 42, 100)));
363*61c4878aSAndroid Build Coastguard Worker 
364*61c4878aSAndroid Build Coastguard Worker   Status on_error_status;
365*61c4878aSAndroid Build Coastguard Worker   call.set_on_error(
366*61c4878aSAndroid Build Coastguard Worker       [&on_error_status](Status error) { on_error_status = error; });
367*61c4878aSAndroid Build Coastguard Worker 
368*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(call.active());
369*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<internal::Endpoint&>(server_).active_call_count(), 1u);
370*61c4878aSAndroid Build Coastguard Worker 
371*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.CloseChannel(1));
372*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, GetChannel(server_, 1));
373*61c4878aSAndroid Build Coastguard Worker 
374*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<internal::Endpoint&>(server_).active_call_count(), 0u);
375*61c4878aSAndroid Build Coastguard Worker 
376*61c4878aSAndroid Build Coastguard Worker   // Should call on_error, but not send a packet since the channel is closed.
377*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::Aborted(), on_error_status);
378*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(output_.total_packets(), 0u);
379*61c4878aSAndroid Build Coastguard Worker }
380*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,OpenChannel_UnusedSlot)381*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, OpenChannel_UnusedSlot) {
382*61c4878aSAndroid Build Coastguard Worker   const span request = EncodePacket(PacketType::REQUEST, 9, 42, 100);
383*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::Unavailable(), server_.ProcessPacket(request));
384*61c4878aSAndroid Build Coastguard Worker 
385*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.OpenChannel(9, output_));
386*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.ProcessPacket(request));
387*61c4878aSAndroid Build Coastguard Worker 
388*61c4878aSAndroid Build Coastguard Worker   const Packet& packet =
389*61c4878aSAndroid Build Coastguard Worker       static_cast<internal::test::FakeChannelOutput&>(output_).last_packet();
390*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), PacketType::RESPONSE);
391*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.channel_id(), 9u);
392*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.service_id(), 42u);
393*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.method_id(), 100u);
394*61c4878aSAndroid Build Coastguard Worker }
395*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,OpenChannel_AlreadyExists)396*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, OpenChannel_AlreadyExists) {
397*61c4878aSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, GetChannel(server_, 1));
398*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::AlreadyExists(), server_.OpenChannel(1, output_));
399*61c4878aSAndroid Build Coastguard Worker }
400*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,OpenChannel_AdditionalSlot)401*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, OpenChannel_AdditionalSlot) {
402*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.OpenChannel(3, output_));
403*61c4878aSAndroid Build Coastguard Worker 
404*61c4878aSAndroid Build Coastguard Worker   constexpr Status kExpected =
405*61c4878aSAndroid Build Coastguard Worker       PW_RPC_DYNAMIC_ALLOCATION == 0 ? Status::ResourceExhausted() : OkStatus();
406*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(kExpected, server_.OpenChannel(19823, output_));
407*61c4878aSAndroid Build Coastguard Worker }
408*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,FindMethod_FoundOkOptionallyCheckType)409*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, FindMethod_FoundOkOptionallyCheckType) {
410*61c4878aSAndroid Build Coastguard Worker   const auto [service, method] = ServerTestHelper::FindMethod(server_, 1, 100);
411*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(service != nullptr);
412*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(method != nullptr);
413*61c4878aSAndroid Build Coastguard Worker #if PW_RPC_METHOD_STORES_TYPE
414*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(MethodType::kBidirectionalStreaming, method->type());
415*61c4878aSAndroid Build Coastguard Worker #endif
416*61c4878aSAndroid Build Coastguard Worker }
417*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BasicServer,FindMethod_NotFound)418*61c4878aSAndroid Build Coastguard Worker TEST_F(BasicServer, FindMethod_NotFound) {
419*61c4878aSAndroid Build Coastguard Worker   {
420*61c4878aSAndroid Build Coastguard Worker     const auto [service, method] =
421*61c4878aSAndroid Build Coastguard Worker         ServerTestHelper::FindMethod(server_, 2, 100);
422*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(service == nullptr);
423*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(method == nullptr);
424*61c4878aSAndroid Build Coastguard Worker   }
425*61c4878aSAndroid Build Coastguard Worker 
426*61c4878aSAndroid Build Coastguard Worker   {
427*61c4878aSAndroid Build Coastguard Worker     const auto [service, method] =
428*61c4878aSAndroid Build Coastguard Worker         ServerTestHelper::FindMethod(server_, 1, 101);
429*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(service != nullptr);
430*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(method == nullptr);
431*61c4878aSAndroid Build Coastguard Worker   }
432*61c4878aSAndroid Build Coastguard Worker }
433*61c4878aSAndroid Build Coastguard Worker 
434*61c4878aSAndroid Build Coastguard Worker class BidiMethod : public BasicServer {
435*61c4878aSAndroid Build Coastguard Worker  protected:
BidiMethod()436*61c4878aSAndroid Build Coastguard Worker   BidiMethod() {
437*61c4878aSAndroid Build Coastguard Worker     internal::rpc_lock().lock();
438*61c4878aSAndroid Build Coastguard Worker     internal::CallContext context(server_,
439*61c4878aSAndroid Build Coastguard Worker                                   channels_[0].id(),
440*61c4878aSAndroid Build Coastguard Worker                                   service_42_,
441*61c4878aSAndroid Build Coastguard Worker                                   service_42_.method(100),
442*61c4878aSAndroid Build Coastguard Worker                                   kDefaultCallId);
443*61c4878aSAndroid Build Coastguard Worker     // A local temporary is required since the constructor requires a lock,
444*61c4878aSAndroid Build Coastguard Worker     // but the *move* constructor takes out the lock.
445*61c4878aSAndroid Build Coastguard Worker     internal::test::FakeServerReaderWriter responder_temp(
446*61c4878aSAndroid Build Coastguard Worker         context.ClaimLocked());
447*61c4878aSAndroid Build Coastguard Worker     internal::rpc_lock().unlock();
448*61c4878aSAndroid Build Coastguard Worker     responder_ = std::move(responder_temp);
449*61c4878aSAndroid Build Coastguard Worker     PW_CHECK(responder_.active());
450*61c4878aSAndroid Build Coastguard Worker   }
451*61c4878aSAndroid Build Coastguard Worker 
452*61c4878aSAndroid Build Coastguard Worker   internal::test::FakeServerReaderWriter responder_;
453*61c4878aSAndroid Build Coastguard Worker };
454*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,DuplicateCallId_CancelsExistingThenCallsAgain)455*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, DuplicateCallId_CancelsExistingThenCallsAgain) {
456*61c4878aSAndroid Build Coastguard Worker   int cancelled = 0;
457*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_error([&cancelled](Status error) {
458*61c4878aSAndroid Build Coastguard Worker     if (error.IsCancelled()) {
459*61c4878aSAndroid Build Coastguard Worker       cancelled += 1;
460*61c4878aSAndroid Build Coastguard Worker     }
461*61c4878aSAndroid Build Coastguard Worker   });
462*61c4878aSAndroid Build Coastguard Worker 
463*61c4878aSAndroid Build Coastguard Worker   const TestMethod& method = service_42_.method(100);
464*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(method.invocations(), 0u);
465*61c4878aSAndroid Build Coastguard Worker 
466*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(),
467*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(PacketType::REQUEST)));
468*61c4878aSAndroid Build Coastguard Worker 
469*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(cancelled, 1);
470*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(method.invocations(), 1u);
471*61c4878aSAndroid Build Coastguard Worker }
472*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,DuplicateMethodDifferentCallId_NotCancelled)473*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, DuplicateMethodDifferentCallId_NotCancelled) {
474*61c4878aSAndroid Build Coastguard Worker   int cancelled = 0;
475*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_error([&cancelled](Status error) {
476*61c4878aSAndroid Build Coastguard Worker     if (error.IsCancelled()) {
477*61c4878aSAndroid Build Coastguard Worker       cancelled += 1;
478*61c4878aSAndroid Build Coastguard Worker     }
479*61c4878aSAndroid Build Coastguard Worker   });
480*61c4878aSAndroid Build Coastguard Worker 
481*61c4878aSAndroid Build Coastguard Worker   const uint32_t kSecondCallId = 1625;
482*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(),
483*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(
484*61c4878aSAndroid Build Coastguard Worker                 PacketType::REQUEST, OkStatus(), {}, kSecondCallId)));
485*61c4878aSAndroid Build Coastguard Worker 
486*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(cancelled, 0);
487*61c4878aSAndroid Build Coastguard Worker }
488*61c4878aSAndroid Build Coastguard Worker 
span_as_cstr(ConstByteSpan span)489*61c4878aSAndroid Build Coastguard Worker const char* span_as_cstr(ConstByteSpan span) {
490*61c4878aSAndroid Build Coastguard Worker   return reinterpret_cast<const char*>(span.data());
491*61c4878aSAndroid Build Coastguard Worker }
492*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,DuplicateMethodDifferentCallIdEachCallGetsSeparateResponse)493*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, DuplicateMethodDifferentCallIdEachCallGetsSeparateResponse) {
494*61c4878aSAndroid Build Coastguard Worker   const uint32_t kSecondCallId = 1625;
495*61c4878aSAndroid Build Coastguard Worker 
496*61c4878aSAndroid Build Coastguard Worker   internal::rpc_lock().lock();
497*61c4878aSAndroid Build Coastguard Worker   internal::test::FakeServerReaderWriter responder_2(
498*61c4878aSAndroid Build Coastguard Worker       internal::CallContext(server_,
499*61c4878aSAndroid Build Coastguard Worker                             channels_[0].id(),
500*61c4878aSAndroid Build Coastguard Worker                             service_42_,
501*61c4878aSAndroid Build Coastguard Worker                             service_42_.method(100),
502*61c4878aSAndroid Build Coastguard Worker                             kSecondCallId)
503*61c4878aSAndroid Build Coastguard Worker           .ClaimLocked());
504*61c4878aSAndroid Build Coastguard Worker   internal::rpc_lock().unlock();
505*61c4878aSAndroid Build Coastguard Worker 
506*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan data_1 = as_bytes(span("data_1_unset"));
507*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_next(
508*61c4878aSAndroid Build Coastguard Worker       [&data_1](ConstByteSpan payload) { data_1 = payload; });
509*61c4878aSAndroid Build Coastguard Worker 
510*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan data_2 = as_bytes(span("data_2_unset"));
511*61c4878aSAndroid Build Coastguard Worker   responder_2.set_on_next(
512*61c4878aSAndroid Build Coastguard Worker       [&data_2](ConstByteSpan payload) { data_2 = payload; });
513*61c4878aSAndroid Build Coastguard Worker 
514*61c4878aSAndroid Build Coastguard Worker   const char* kMessage1 = "hello_1";
515*61c4878aSAndroid Build Coastguard Worker   const char* kMessage2 = "hello_2";
516*61c4878aSAndroid Build Coastguard Worker 
517*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
518*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
519*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(PacketForRpc(
520*61c4878aSAndroid Build Coastguard Worker           PacketType::CLIENT_STREAM, OkStatus(), "hello_2", kSecondCallId)));
521*61c4878aSAndroid Build Coastguard Worker 
522*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(span_as_cstr(data_2), kMessage2);
523*61c4878aSAndroid Build Coastguard Worker 
524*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
525*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
526*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(PacketForRpc(
527*61c4878aSAndroid Build Coastguard Worker           PacketType::CLIENT_STREAM, OkStatus(), "hello_1", kDefaultCallId)));
528*61c4878aSAndroid Build Coastguard Worker 
529*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(span_as_cstr(data_1), kMessage1);
530*61c4878aSAndroid Build Coastguard Worker }
531*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,Cancel_ClosesServerWriter)532*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, Cancel_ClosesServerWriter) {
533*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel()));
534*61c4878aSAndroid Build Coastguard Worker 
535*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(responder_.active());
536*61c4878aSAndroid Build Coastguard Worker }
537*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,Cancel_SendsNoResponse)538*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, Cancel_SendsNoResponse) {
539*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel()));
540*61c4878aSAndroid Build Coastguard Worker 
541*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
542*61c4878aSAndroid Build Coastguard Worker }
543*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientError_ClosesServerWriterWithoutResponse)544*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientError_ClosesServerWriterWithoutResponse) {
545*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
546*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(PacketType::CLIENT_ERROR)));
547*61c4878aSAndroid Build Coastguard Worker 
548*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(responder_.active());
549*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
550*61c4878aSAndroid Build Coastguard Worker }
551*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientError_CallsOnErrorCallback)552*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientError_CallsOnErrorCallback) {
553*61c4878aSAndroid Build Coastguard Worker   Status status = Status::Unknown();
554*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_error([&status](Status error) { status = error; });
555*61c4878aSAndroid Build Coastguard Worker 
556*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
557*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(PacketType::CLIENT_ERROR,
558*61c4878aSAndroid Build Coastguard Worker                                                Status::Unauthenticated())));
559*61c4878aSAndroid Build Coastguard Worker 
560*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(status, Status::Unauthenticated());
561*61c4878aSAndroid Build Coastguard Worker }
562*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,Cancel_CallsOnErrorCallback)563*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, Cancel_CallsOnErrorCallback) {
564*61c4878aSAndroid Build Coastguard Worker   Status status = Status::Unknown();
565*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_error([&status](Status error) { status = error; });
566*61c4878aSAndroid Build Coastguard Worker 
567*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel()));
568*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(status, Status::Cancelled());
569*61c4878aSAndroid Build Coastguard Worker }
570*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,Cancel_IncorrectChannel_SendsNothing)571*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, Cancel_IncorrectChannel_SendsNothing) {
572*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel(2, 42, 100)));
573*61c4878aSAndroid Build Coastguard Worker 
574*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
575*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(responder_.active());
576*61c4878aSAndroid Build Coastguard Worker }
577*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,Cancel_IncorrectService_SendsNothing)578*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, Cancel_IncorrectService_SendsNothing) {
579*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel(1, 43, 100)));
580*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
581*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(responder_.active());
582*61c4878aSAndroid Build Coastguard Worker }
583*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,Cancel_IncorrectMethod_SendsNothing)584*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, Cancel_IncorrectMethod_SendsNothing) {
585*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel(1, 42, 101)));
586*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
587*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(responder_.active());
588*61c4878aSAndroid Build Coastguard Worker }
589*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientStream_CallsCallback)590*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientStream_CallsCallback) {
591*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan data = as_bytes(span("?"));
592*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_next([&data](ConstByteSpan payload) { data = payload; });
593*61c4878aSAndroid Build Coastguard Worker 
594*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
595*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
596*61c4878aSAndroid Build Coastguard Worker                 PacketForRpc(PacketType::CLIENT_STREAM, {}, "hello")));
597*61c4878aSAndroid Build Coastguard Worker 
598*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
599*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(span_as_cstr(data), "hello");
600*61c4878aSAndroid Build Coastguard Worker }
601*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientStream_CallsCallbackOnCallWithOpenId)602*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientStream_CallsCallbackOnCallWithOpenId) {
603*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan data = as_bytes(span("?"));
604*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_next([&data](ConstByteSpan payload) { data = payload; });
605*61c4878aSAndroid Build Coastguard Worker 
606*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(
607*61c4878aSAndroid Build Coastguard Worker       OkStatus(),
608*61c4878aSAndroid Build Coastguard Worker       server_.ProcessPacket(PacketForRpc(
609*61c4878aSAndroid Build Coastguard Worker           PacketType::CLIENT_STREAM, {}, "hello", internal::kOpenCallId)));
610*61c4878aSAndroid Build Coastguard Worker 
611*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
612*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(span_as_cstr(data), "hello");
613*61c4878aSAndroid Build Coastguard Worker }
614*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientStream_CallsCallbackOnCallWithLegacyOpenId)615*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientStream_CallsCallbackOnCallWithLegacyOpenId) {
616*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan data = as_bytes(span("?"));
617*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_next([&data](ConstByteSpan payload) { data = payload; });
618*61c4878aSAndroid Build Coastguard Worker 
619*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
620*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(PacketType::CLIENT_STREAM,
621*61c4878aSAndroid Build Coastguard Worker                                                {},
622*61c4878aSAndroid Build Coastguard Worker                                                "hello",
623*61c4878aSAndroid Build Coastguard Worker                                                internal::kLegacyOpenCallId)));
624*61c4878aSAndroid Build Coastguard Worker 
625*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
626*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(span_as_cstr(data), "hello");
627*61c4878aSAndroid Build Coastguard Worker }
628*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientStream_CallsOpenIdOnCallWithDifferentId)629*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientStream_CallsOpenIdOnCallWithDifferentId) {
630*61c4878aSAndroid Build Coastguard Worker   const uint32_t kSecondCallId = 1625;
631*61c4878aSAndroid Build Coastguard Worker   internal::CallContext context(server_,
632*61c4878aSAndroid Build Coastguard Worker                                 channels_[0].id(),
633*61c4878aSAndroid Build Coastguard Worker                                 service_42_,
634*61c4878aSAndroid Build Coastguard Worker                                 service_42_.method(100),
635*61c4878aSAndroid Build Coastguard Worker                                 internal::kOpenCallId);
636*61c4878aSAndroid Build Coastguard Worker   internal::rpc_lock().lock();
637*61c4878aSAndroid Build Coastguard Worker   auto temp_responder =
638*61c4878aSAndroid Build Coastguard Worker       internal::test::FakeServerReaderWriter(context.ClaimLocked());
639*61c4878aSAndroid Build Coastguard Worker   internal::rpc_lock().unlock();
640*61c4878aSAndroid Build Coastguard Worker   responder_ = std::move(temp_responder);
641*61c4878aSAndroid Build Coastguard Worker 
642*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan data = as_bytes(span("?"));
643*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_next([&data](ConstByteSpan payload) { data = payload; });
644*61c4878aSAndroid Build Coastguard Worker 
645*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
646*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(
647*61c4878aSAndroid Build Coastguard Worker                 PacketType::CLIENT_STREAM, {}, "hello", kSecondCallId)));
648*61c4878aSAndroid Build Coastguard Worker 
649*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
650*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(span_as_cstr(data), "hello");
651*61c4878aSAndroid Build Coastguard Worker 
652*61c4878aSAndroid Build Coastguard Worker   internal::RpcLockGuard lock;
653*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(responder_.as_server_call().id(), kSecondCallId);
654*61c4878aSAndroid Build Coastguard Worker }
655*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientStream_CallsLegacyOpenIdOnCallWithDifferentId)656*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientStream_CallsLegacyOpenIdOnCallWithDifferentId) {
657*61c4878aSAndroid Build Coastguard Worker   const uint32_t kSecondCallId = 1625;
658*61c4878aSAndroid Build Coastguard Worker   internal::CallContext context(server_,
659*61c4878aSAndroid Build Coastguard Worker                                 channels_[0].id(),
660*61c4878aSAndroid Build Coastguard Worker                                 service_42_,
661*61c4878aSAndroid Build Coastguard Worker                                 service_42_.method(100),
662*61c4878aSAndroid Build Coastguard Worker                                 internal::kLegacyOpenCallId);
663*61c4878aSAndroid Build Coastguard Worker   internal::rpc_lock().lock();
664*61c4878aSAndroid Build Coastguard Worker   auto temp_responder =
665*61c4878aSAndroid Build Coastguard Worker       internal::test::FakeServerReaderWriter(context.ClaimLocked());
666*61c4878aSAndroid Build Coastguard Worker   internal::rpc_lock().unlock();
667*61c4878aSAndroid Build Coastguard Worker   responder_ = std::move(temp_responder);
668*61c4878aSAndroid Build Coastguard Worker 
669*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan data = as_bytes(span("?"));
670*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_next([&data](ConstByteSpan payload) { data = payload; });
671*61c4878aSAndroid Build Coastguard Worker 
672*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
673*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(
674*61c4878aSAndroid Build Coastguard Worker                 PacketType::CLIENT_STREAM, {}, "hello", kSecondCallId)));
675*61c4878aSAndroid Build Coastguard Worker 
676*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
677*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(span_as_cstr(data), "hello");
678*61c4878aSAndroid Build Coastguard Worker 
679*61c4878aSAndroid Build Coastguard Worker   internal::RpcLockGuard lock;
680*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(responder_.as_server_call().id(), kSecondCallId);
681*61c4878aSAndroid Build Coastguard Worker }
682*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,UnregsiterService_AbortsActiveCalls)683*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, UnregsiterService_AbortsActiveCalls) {
684*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(responder_.active());
685*61c4878aSAndroid Build Coastguard Worker 
686*61c4878aSAndroid Build Coastguard Worker   Status on_error_status = OkStatus();
687*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_error(
688*61c4878aSAndroid Build Coastguard Worker       [&on_error_status](Status status) { on_error_status = status; });
689*61c4878aSAndroid Build Coastguard Worker 
690*61c4878aSAndroid Build Coastguard Worker   server_.UnregisterService(service_42_);
691*61c4878aSAndroid Build Coastguard Worker 
692*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(responder_.active());
693*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::Aborted(), on_error_status);
694*61c4878aSAndroid Build Coastguard Worker }
695*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientRequestedCompletion_CallsCallback)696*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientRequestedCompletion_CallsCallback) {
697*61c4878aSAndroid Build Coastguard Worker   bool called = false;
698*61c4878aSAndroid Build Coastguard Worker #if PW_RPC_COMPLETION_REQUEST_CALLBACK
699*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_completion_requested([&called]() { called = true; });
700*61c4878aSAndroid Build Coastguard Worker #endif
701*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
702*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
703*61c4878aSAndroid Build Coastguard Worker                 PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION)));
704*61c4878aSAndroid Build Coastguard Worker 
705*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
706*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(called, PW_RPC_COMPLETION_REQUEST_CALLBACK);
707*61c4878aSAndroid Build Coastguard Worker }
708*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientRequestedCompletion_CallsCallbackIfEnabled)709*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientRequestedCompletion_CallsCallbackIfEnabled) {
710*61c4878aSAndroid Build Coastguard Worker   bool called = false;
711*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_completion_requested_if_enabled(
712*61c4878aSAndroid Build Coastguard Worker       [&called]() { called = true; });
713*61c4878aSAndroid Build Coastguard Worker 
714*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
715*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
716*61c4878aSAndroid Build Coastguard Worker                 PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION)));
717*61c4878aSAndroid Build Coastguard Worker 
718*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
719*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(called, PW_RPC_COMPLETION_REQUEST_CALLBACK);
720*61c4878aSAndroid Build Coastguard Worker }
721*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientRequestedCompletion_ErrorWhenClosed)722*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientRequestedCompletion_ErrorWhenClosed) {
723*61c4878aSAndroid Build Coastguard Worker   const auto end = PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION);
724*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(end));
725*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(end));
726*61c4878aSAndroid Build Coastguard Worker 
727*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(output_.total_packets(), 0u);
728*61c4878aSAndroid Build Coastguard Worker }
729*61c4878aSAndroid Build Coastguard Worker 
TEST_F(BidiMethod,ClientRequestedCompletion_ErrorWhenAlreadyClosed)730*61c4878aSAndroid Build Coastguard Worker TEST_F(BidiMethod, ClientRequestedCompletion_ErrorWhenAlreadyClosed) {
731*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel()));
732*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(responder_.active());
733*61c4878aSAndroid Build Coastguard Worker 
734*61c4878aSAndroid Build Coastguard Worker   const auto end = PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION);
735*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(end));
736*61c4878aSAndroid Build Coastguard Worker 
737*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(output_.total_packets(), 1u);
738*61c4878aSAndroid Build Coastguard Worker   const Packet& packet =
739*61c4878aSAndroid Build Coastguard Worker       static_cast<internal::test::FakeChannelOutput&>(output_).last_packet();
740*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
741*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.status(), Status::FailedPrecondition());
742*61c4878aSAndroid Build Coastguard Worker }
743*61c4878aSAndroid Build Coastguard Worker 
744*61c4878aSAndroid Build Coastguard Worker class ServerStreamingMethod : public BasicServer {
745*61c4878aSAndroid Build Coastguard Worker  protected:
ServerStreamingMethod()746*61c4878aSAndroid Build Coastguard Worker   ServerStreamingMethod() {
747*61c4878aSAndroid Build Coastguard Worker     internal::CallContext context(server_,
748*61c4878aSAndroid Build Coastguard Worker                                   channels_[0].id(),
749*61c4878aSAndroid Build Coastguard Worker                                   service_42_,
750*61c4878aSAndroid Build Coastguard Worker                                   service_42_.method(100),
751*61c4878aSAndroid Build Coastguard Worker                                   kDefaultCallId);
752*61c4878aSAndroid Build Coastguard Worker     internal::rpc_lock().lock();
753*61c4878aSAndroid Build Coastguard Worker     internal::test::FakeServerWriter responder_temp(context.ClaimLocked());
754*61c4878aSAndroid Build Coastguard Worker     internal::rpc_lock().unlock();
755*61c4878aSAndroid Build Coastguard Worker     responder_ = std::move(responder_temp);
756*61c4878aSAndroid Build Coastguard Worker     PW_CHECK(responder_.active());
757*61c4878aSAndroid Build Coastguard Worker   }
758*61c4878aSAndroid Build Coastguard Worker 
759*61c4878aSAndroid Build Coastguard Worker   internal::test::FakeServerWriter responder_;
760*61c4878aSAndroid Build Coastguard Worker };
761*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerStreamingMethod,ClientStream_InvalidArgumentError)762*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerStreamingMethod, ClientStream_InvalidArgumentError) {
763*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
764*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(PacketForRpc(PacketType::CLIENT_STREAM)));
765*61c4878aSAndroid Build Coastguard Worker 
766*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(output_.total_packets(), 1u);
767*61c4878aSAndroid Build Coastguard Worker   const Packet& packet =
768*61c4878aSAndroid Build Coastguard Worker       static_cast<internal::test::FakeChannelOutput&>(output_).last_packet();
769*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
770*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.status(), Status::InvalidArgument());
771*61c4878aSAndroid Build Coastguard Worker }
772*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerStreamingMethod,ClientRequestedCompletion_CallsCallback)773*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerStreamingMethod, ClientRequestedCompletion_CallsCallback) {
774*61c4878aSAndroid Build Coastguard Worker   bool called = false;
775*61c4878aSAndroid Build Coastguard Worker #if PW_RPC_COMPLETION_REQUEST_CALLBACK
776*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_completion_requested([&called]() { called = true; });
777*61c4878aSAndroid Build Coastguard Worker #endif
778*61c4878aSAndroid Build Coastguard Worker 
779*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
780*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
781*61c4878aSAndroid Build Coastguard Worker                 PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION)));
782*61c4878aSAndroid Build Coastguard Worker 
783*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
784*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(called, PW_RPC_COMPLETION_REQUEST_CALLBACK);
785*61c4878aSAndroid Build Coastguard Worker }
786*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerStreamingMethod,ClientRequestedCompletion_CallsCallbackIfEnabled)787*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerStreamingMethod,
788*61c4878aSAndroid Build Coastguard Worker        ClientRequestedCompletion_CallsCallbackIfEnabled) {
789*61c4878aSAndroid Build Coastguard Worker   bool called = false;
790*61c4878aSAndroid Build Coastguard Worker   responder_.set_on_completion_requested_if_enabled(
791*61c4878aSAndroid Build Coastguard Worker       [&called]() { called = true; });
792*61c4878aSAndroid Build Coastguard Worker 
793*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(),
794*61c4878aSAndroid Build Coastguard Worker             server_.ProcessPacket(
795*61c4878aSAndroid Build Coastguard Worker                 PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION)));
796*61c4878aSAndroid Build Coastguard Worker 
797*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(output_.total_packets(), 0u);
798*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(called, PW_RPC_COMPLETION_REQUEST_CALLBACK);
799*61c4878aSAndroid Build Coastguard Worker }
800*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerStreamingMethod,ClientRequestedCompletion_ErrorWhenClosed)801*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerStreamingMethod, ClientRequestedCompletion_ErrorWhenClosed) {
802*61c4878aSAndroid Build Coastguard Worker   const auto end = PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION);
803*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(end));
804*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(end));
805*61c4878aSAndroid Build Coastguard Worker 
806*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(output_.total_packets(), 0u);
807*61c4878aSAndroid Build Coastguard Worker }
808*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerStreamingMethod,ClientRequestedCompletion_ErrorWhenAlreadyClosed)809*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerStreamingMethod,
810*61c4878aSAndroid Build Coastguard Worker        ClientRequestedCompletion_ErrorWhenAlreadyClosed) {
811*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(EncodeCancel()));
812*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(responder_.active());
813*61c4878aSAndroid Build Coastguard Worker 
814*61c4878aSAndroid Build Coastguard Worker   const auto end = PacketForRpc(PacketType::CLIENT_REQUEST_COMPLETION);
815*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), server_.ProcessPacket(end));
816*61c4878aSAndroid Build Coastguard Worker 
817*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(output_.total_packets(), 1u);
818*61c4878aSAndroid Build Coastguard Worker   const Packet& packet =
819*61c4878aSAndroid Build Coastguard Worker       static_cast<internal::test::FakeChannelOutput&>(output_).last_packet();
820*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), PacketType::SERVER_ERROR);
821*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.status(), Status::FailedPrecondition());
822*61c4878aSAndroid Build Coastguard Worker }
823*61c4878aSAndroid Build Coastguard Worker 
824*61c4878aSAndroid Build Coastguard Worker }  // namespace
825*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::rpc
826