xref: /aosp_15_r20/external/pigweed/pw_rpc/call_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2021 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/internal/call.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include <algorithm>
18*61c4878aSAndroid Build Coastguard Worker #include <array>
19*61c4878aSAndroid Build Coastguard Worker #include <cstdint>
20*61c4878aSAndroid Build Coastguard Worker #include <cstring>
21*61c4878aSAndroid Build Coastguard Worker #include <optional>
22*61c4878aSAndroid Build Coastguard Worker 
23*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/test_utils.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/service.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc_private/fake_server_reader_writer.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc_private/test_method.h"
27*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status_with_size.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 TestService : public Service {
33*61c4878aSAndroid Build Coastguard Worker  public:
TestService(uint32_t id)34*61c4878aSAndroid Build Coastguard Worker   constexpr TestService(uint32_t id) : Service(id, method) {}
35*61c4878aSAndroid Build Coastguard Worker 
36*61c4878aSAndroid Build Coastguard Worker   static constexpr internal::TestMethodUnion method = internal::TestMethod(8);
37*61c4878aSAndroid Build Coastguard Worker };
38*61c4878aSAndroid Build Coastguard Worker 
39*61c4878aSAndroid Build Coastguard Worker namespace internal {
40*61c4878aSAndroid Build Coastguard Worker namespace {
41*61c4878aSAndroid Build Coastguard Worker 
42*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kChannelId = 99;
43*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kServiceId = 16;
44*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kMethodId = 8;
45*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kCallId = 327;
46*61c4878aSAndroid Build Coastguard Worker constexpr Packet kPacket(
47*61c4878aSAndroid Build Coastguard Worker     pwpb::PacketType::REQUEST, kChannelId, kServiceId, kMethodId, kCallId);
48*61c4878aSAndroid Build Coastguard Worker 
49*61c4878aSAndroid Build Coastguard Worker using ::pw::rpc::internal::test::FakeServerReader;
50*61c4878aSAndroid Build Coastguard Worker using ::pw::rpc::internal::test::FakeServerReaderWriter;
51*61c4878aSAndroid Build Coastguard Worker using ::pw::rpc::internal::test::FakeServerWriter;
52*61c4878aSAndroid Build Coastguard Worker using ::std::byte;
53*61c4878aSAndroid Build Coastguard Worker using ::testing::Test;
54*61c4878aSAndroid Build Coastguard Worker 
55*61c4878aSAndroid Build Coastguard Worker static_assert(sizeof(Call) ==
56*61c4878aSAndroid Build Coastguard Worker                   // IntrusiveList::Item pointer
57*61c4878aSAndroid Build Coastguard Worker                   sizeof(IntrusiveList<Call>::Item) +
58*61c4878aSAndroid Build Coastguard Worker                       // Endpoint pointer
59*61c4878aSAndroid Build Coastguard Worker                       sizeof(Endpoint*) +
60*61c4878aSAndroid Build Coastguard Worker                       // call_id, channel_id, service_id, method_id
61*61c4878aSAndroid Build Coastguard Worker                       4 * sizeof(uint32_t) +
62*61c4878aSAndroid Build Coastguard Worker                       // Packed state and properties
63*61c4878aSAndroid Build Coastguard Worker                       sizeof(void*) +
64*61c4878aSAndroid Build Coastguard Worker                       // on_error and on_next callbacks
65*61c4878aSAndroid Build Coastguard Worker                       2 * sizeof(Function<void(Status)>),
66*61c4878aSAndroid Build Coastguard Worker               "Unexpected padding in Call!");
67*61c4878aSAndroid Build Coastguard Worker 
68*61c4878aSAndroid Build Coastguard Worker static_assert(sizeof(CallProperties) == sizeof(uint8_t));
69*61c4878aSAndroid Build Coastguard Worker 
TEST(CallProperties,ValuesMatch)70*61c4878aSAndroid Build Coastguard Worker TEST(CallProperties, ValuesMatch) {
71*61c4878aSAndroid Build Coastguard Worker   constexpr CallProperties props_1(
72*61c4878aSAndroid Build Coastguard Worker       MethodType::kBidirectionalStreaming, kClientCall, kRawProto);
73*61c4878aSAndroid Build Coastguard Worker   static_assert(props_1.method_type() == MethodType::kBidirectionalStreaming);
74*61c4878aSAndroid Build Coastguard Worker   static_assert(props_1.call_type() == kClientCall);
75*61c4878aSAndroid Build Coastguard Worker   static_assert(props_1.callback_proto_type() == kRawProto);
76*61c4878aSAndroid Build Coastguard Worker 
77*61c4878aSAndroid Build Coastguard Worker   constexpr CallProperties props_2(
78*61c4878aSAndroid Build Coastguard Worker       MethodType::kClientStreaming, kServerCall, kProtoStruct);
79*61c4878aSAndroid Build Coastguard Worker   static_assert(props_2.method_type() == MethodType::kClientStreaming);
80*61c4878aSAndroid Build Coastguard Worker   static_assert(props_2.call_type() == kServerCall);
81*61c4878aSAndroid Build Coastguard Worker   static_assert(props_2.callback_proto_type() == kProtoStruct);
82*61c4878aSAndroid Build Coastguard Worker 
83*61c4878aSAndroid Build Coastguard Worker   constexpr CallProperties props_3(
84*61c4878aSAndroid Build Coastguard Worker       MethodType::kUnary, kClientCall, kProtoStruct);
85*61c4878aSAndroid Build Coastguard Worker   static_assert(props_3.method_type() == MethodType::kUnary);
86*61c4878aSAndroid Build Coastguard Worker   static_assert(props_3.call_type() == kClientCall);
87*61c4878aSAndroid Build Coastguard Worker   static_assert(props_3.callback_proto_type() == kProtoStruct);
88*61c4878aSAndroid Build Coastguard Worker }
89*61c4878aSAndroid Build Coastguard Worker 
90*61c4878aSAndroid Build Coastguard Worker class ServerWriterTest : public Test {
91*61c4878aSAndroid Build Coastguard Worker  public:
ServerWriterTest()92*61c4878aSAndroid Build Coastguard Worker   ServerWriterTest() : context_(TestService::method.method()) {
93*61c4878aSAndroid Build Coastguard Worker     rpc_lock().lock();
94*61c4878aSAndroid Build Coastguard Worker     FakeServerWriter writer_temp(context_.get().ClaimLocked());
95*61c4878aSAndroid Build Coastguard Worker     rpc_lock().unlock();
96*61c4878aSAndroid Build Coastguard Worker     writer_ = std::move(writer_temp);
97*61c4878aSAndroid Build Coastguard Worker   }
98*61c4878aSAndroid Build Coastguard Worker 
99*61c4878aSAndroid Build Coastguard Worker   ServerContextForTest<TestService, kChannelId, kServiceId, kCallId> context_;
100*61c4878aSAndroid Build Coastguard Worker   FakeServerWriter writer_;
101*61c4878aSAndroid Build Coastguard Worker };
102*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,ConstructWithContext_StartsOpen)103*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, ConstructWithContext_StartsOpen) {
104*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(writer_.active());
105*61c4878aSAndroid Build Coastguard Worker }
106*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Move_ClosesOriginal)107*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Move_ClosesOriginal) {
108*61c4878aSAndroid Build Coastguard Worker   FakeServerWriter moved(std::move(writer_));
109*61c4878aSAndroid Build Coastguard Worker 
110*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
111*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(writer_.active());
112*61c4878aSAndroid Build Coastguard Worker #endif  // ignore use-after-move
113*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(moved.active());
114*61c4878aSAndroid Build Coastguard Worker }
115*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,DefaultConstruct_Closed)116*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, DefaultConstruct_Closed) {
117*61c4878aSAndroid Build Coastguard Worker   FakeServerWriter writer;
118*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(writer.active());
119*61c4878aSAndroid Build Coastguard Worker }
120*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Construct_RegistersWithServer)121*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Construct_RegistersWithServer) {
122*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
123*61c4878aSAndroid Build Coastguard Worker   IntrusiveList<Call>::iterator call = context_.server().FindCall(kPacket);
124*61c4878aSAndroid Build Coastguard Worker   ASSERT_NE(call, context_.server().calls_end());
125*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<void*>(&*call), static_cast<void*>(&writer_));
126*61c4878aSAndroid Build Coastguard Worker }
127*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Destruct_RemovesFromServer)128*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Destruct_RemovesFromServer) {
129*61c4878aSAndroid Build Coastguard Worker   {
130*61c4878aSAndroid Build Coastguard Worker     // Note `lock_guard` cannot be used here, because while the constructor
131*61c4878aSAndroid Build Coastguard Worker     // of `FakeServerWriter` requires the lock be held, the destructor acquires
132*61c4878aSAndroid Build Coastguard Worker     // it!
133*61c4878aSAndroid Build Coastguard Worker     rpc_lock().lock();
134*61c4878aSAndroid Build Coastguard Worker     FakeServerWriter writer(context_.get().ClaimLocked());
135*61c4878aSAndroid Build Coastguard Worker     rpc_lock().unlock();
136*61c4878aSAndroid Build Coastguard Worker   }
137*61c4878aSAndroid Build Coastguard Worker 
138*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
139*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(context_.server().FindCall(kPacket), context_.server().calls_end());
140*61c4878aSAndroid Build Coastguard Worker }
141*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Finish_RemovesFromServer)142*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Finish_RemovesFromServer) {
143*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), writer_.Finish());
144*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
145*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(context_.server().FindCall(kPacket), context_.server().calls_end());
146*61c4878aSAndroid Build Coastguard Worker }
147*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Finish_SendsResponse)148*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Finish_SendsResponse) {
149*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), writer_.Finish());
150*61c4878aSAndroid Build Coastguard Worker 
151*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(context_.output().total_packets(), 1u);
152*61c4878aSAndroid Build Coastguard Worker   const Packet& packet = context_.output().last_packet();
153*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.type(), pwpb::PacketType::RESPONSE);
154*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.channel_id(), context_.channel_id());
155*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.service_id(), context_.service_id());
156*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.method_id(), context_.get().method().id());
157*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(packet.payload().empty());
158*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(packet.status(), OkStatus());
159*61c4878aSAndroid Build Coastguard Worker }
160*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Finish_ReturnsStatusFromChannelSend)161*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Finish_ReturnsStatusFromChannelSend) {
162*61c4878aSAndroid Build Coastguard Worker   context_.output().set_send_status(Status::Unauthenticated());
163*61c4878aSAndroid Build Coastguard Worker 
164*61c4878aSAndroid Build Coastguard Worker   // All non-OK statuses are remapped to UNKNOWN.
165*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::Unknown(), writer_.Finish());
166*61c4878aSAndroid Build Coastguard Worker }
167*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Finish)168*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Finish) {
169*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(writer_.active());
170*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), writer_.Finish());
171*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(writer_.active());
172*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::FailedPrecondition(), writer_.Finish());
173*61c4878aSAndroid Build Coastguard Worker }
174*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Open_SendsPacketWithPayload)175*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Open_SendsPacketWithPayload) {
176*61c4878aSAndroid Build Coastguard Worker   constexpr byte data[] = {byte{0xf0}, byte{0x0d}};
177*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), writer_.Write(data));
178*61c4878aSAndroid Build Coastguard Worker 
179*61c4878aSAndroid Build Coastguard Worker   byte encoded[64];
180*61c4878aSAndroid Build Coastguard Worker   auto result = context_.server_stream(data).Encode(encoded);
181*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), result.status());
182*61c4878aSAndroid Build Coastguard Worker 
183*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan payload = context_.output().last_packet().payload();
184*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(sizeof(data), payload.size());
185*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0, std::memcmp(data, payload.data(), sizeof(data)));
186*61c4878aSAndroid Build Coastguard Worker }
187*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Open_WriteCallback_SendsPacketWithPayload)188*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Open_WriteCallback_SendsPacketWithPayload) {
189*61c4878aSAndroid Build Coastguard Worker   constexpr byte data[] = {byte{0xaa}, byte{0xbb}, byte{0xcc}, byte{0xdd}};
190*61c4878aSAndroid Build Coastguard Worker 
191*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), writer_.Write([&data](ByteSpan buffer) {
192*61c4878aSAndroid Build Coastguard Worker     std::memcpy(buffer.data(), data, sizeof(data));
193*61c4878aSAndroid Build Coastguard Worker     return StatusWithSize(sizeof(data));
194*61c4878aSAndroid Build Coastguard Worker   }));
195*61c4878aSAndroid Build Coastguard Worker 
196*61c4878aSAndroid Build Coastguard Worker   byte encoded[64];
197*61c4878aSAndroid Build Coastguard Worker   auto result = context_.server_stream(data).Encode(encoded);
198*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(OkStatus(), result.status());
199*61c4878aSAndroid Build Coastguard Worker 
200*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan payload = context_.output().last_packet().payload();
201*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(sizeof(data), payload.size());
202*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0, std::memcmp(data, payload.data(), sizeof(data)));
203*61c4878aSAndroid Build Coastguard Worker }
204*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Open_WriteCallback_ErrorPropagates)205*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Open_WriteCallback_ErrorPropagates) {
206*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(Status::DataLoss(),
207*61c4878aSAndroid Build Coastguard Worker             writer_.Write([](ByteSpan) { return StatusWithSize::DataLoss(); }));
208*61c4878aSAndroid Build Coastguard Worker }
209*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Open_WriteCallback_NullptrReturnsInvalidArgument)210*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Open_WriteCallback_NullptrReturnsInvalidArgument) {
211*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(Status::InvalidArgument(), writer_.Write(nullptr));
212*61c4878aSAndroid Build Coastguard Worker }
213*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Closed_IgnoresFinish)214*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Closed_IgnoresFinish) {
215*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), writer_.Finish());
216*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::FailedPrecondition(), writer_.Finish());
217*61c4878aSAndroid Build Coastguard Worker }
218*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,DefaultConstructor_NoClientStream)219*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, DefaultConstructor_NoClientStream) {
220*61c4878aSAndroid Build Coastguard Worker   FakeServerWriter writer;
221*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
222*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(writer.as_server_call().has_client_stream());
223*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(writer.as_server_call().client_requested_completion());
224*61c4878aSAndroid Build Coastguard Worker }
225*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerWriterTest,Open_NoClientStream)226*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerWriterTest, Open_NoClientStream) {
227*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
228*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(writer_.as_server_call().has_client_stream());
229*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(writer_.as_server_call().has_server_stream());
230*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(writer_.as_server_call().client_requested_completion());
231*61c4878aSAndroid Build Coastguard Worker }
232*61c4878aSAndroid Build Coastguard Worker 
233*61c4878aSAndroid Build Coastguard Worker class ServerReaderTest : public Test {
234*61c4878aSAndroid Build Coastguard Worker  public:
ServerReaderTest()235*61c4878aSAndroid Build Coastguard Worker   ServerReaderTest() : context_(TestService::method.method()) {
236*61c4878aSAndroid Build Coastguard Worker     rpc_lock().lock();
237*61c4878aSAndroid Build Coastguard Worker     FakeServerReader reader_temp(context_.get().ClaimLocked());
238*61c4878aSAndroid Build Coastguard Worker     rpc_lock().unlock();
239*61c4878aSAndroid Build Coastguard Worker     reader_ = std::move(reader_temp);
240*61c4878aSAndroid Build Coastguard Worker   }
241*61c4878aSAndroid Build Coastguard Worker 
242*61c4878aSAndroid Build Coastguard Worker   ServerContextForTest<TestService> context_;
243*61c4878aSAndroid Build Coastguard Worker   FakeServerReader reader_;
244*61c4878aSAndroid Build Coastguard Worker };
245*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderTest,DefaultConstructor_StreamClosed)246*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderTest, DefaultConstructor_StreamClosed) {
247*61c4878aSAndroid Build Coastguard Worker   FakeServerReader reader;
248*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(reader.as_server_call().active());
249*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
250*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(reader.as_server_call().client_requested_completion());
251*61c4878aSAndroid Build Coastguard Worker }
252*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderTest,Open_ClientStreamStartsOpen)253*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderTest, Open_ClientStreamStartsOpen) {
254*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
255*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(reader_.as_server_call().has_client_stream());
256*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(reader_.as_server_call().client_requested_completion());
257*61c4878aSAndroid Build Coastguard Worker }
258*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderTest,Close_ClosesStream)259*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderTest, Close_ClosesStream) {
260*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(reader_.as_server_call().active());
261*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
262*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(reader_.as_server_call().client_requested_completion());
263*61c4878aSAndroid Build Coastguard Worker   rpc_lock().unlock();
264*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(),
265*61c4878aSAndroid Build Coastguard Worker             reader_.as_server_call().CloseAndSendResponse(OkStatus()));
266*61c4878aSAndroid Build Coastguard Worker 
267*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(reader_.as_server_call().active());
268*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
269*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(reader_.as_server_call().client_requested_completion());
270*61c4878aSAndroid Build Coastguard Worker }
271*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderTest,RequestCompletion_OnlyMakesClientNotReady)272*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderTest, RequestCompletion_OnlyMakesClientNotReady) {
273*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(reader_.active());
274*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
275*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(reader_.as_server_call().client_requested_completion());
276*61c4878aSAndroid Build Coastguard Worker   reader_.as_server_call().HandleClientRequestedCompletion();
277*61c4878aSAndroid Build Coastguard Worker 
278*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(reader_.active());
279*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
280*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(reader_.as_server_call().client_requested_completion());
281*61c4878aSAndroid Build Coastguard Worker }
282*61c4878aSAndroid Build Coastguard Worker 
283*61c4878aSAndroid Build Coastguard Worker class ServerReaderWriterTest : public Test {
284*61c4878aSAndroid Build Coastguard Worker  public:
ServerReaderWriterTest()285*61c4878aSAndroid Build Coastguard Worker   ServerReaderWriterTest() : context_(TestService::method.method()) {
286*61c4878aSAndroid Build Coastguard Worker     rpc_lock().lock();
287*61c4878aSAndroid Build Coastguard Worker     FakeServerReaderWriter reader_writer_temp(context_.get().ClaimLocked());
288*61c4878aSAndroid Build Coastguard Worker     rpc_lock().unlock();
289*61c4878aSAndroid Build Coastguard Worker     reader_writer_ = std::move(reader_writer_temp);
290*61c4878aSAndroid Build Coastguard Worker   }
291*61c4878aSAndroid Build Coastguard Worker 
292*61c4878aSAndroid Build Coastguard Worker   ServerContextForTest<TestService> context_;
293*61c4878aSAndroid Build Coastguard Worker   FakeServerReaderWriter reader_writer_;
294*61c4878aSAndroid Build Coastguard Worker };
295*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderWriterTest,Move_MaintainsClientStream)296*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderWriterTest, Move_MaintainsClientStream) {
297*61c4878aSAndroid Build Coastguard Worker   FakeServerReaderWriter destination;
298*61c4878aSAndroid Build Coastguard Worker 
299*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
300*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(destination.as_server_call().client_requested_completion());
301*61c4878aSAndroid Build Coastguard Worker   rpc_lock().unlock();
302*61c4878aSAndroid Build Coastguard Worker 
303*61c4878aSAndroid Build Coastguard Worker   destination = std::move(reader_writer_);
304*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
305*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(destination.as_server_call().has_client_stream());
306*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(destination.as_server_call().client_requested_completion());
307*61c4878aSAndroid Build Coastguard Worker }
308*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderWriterTest,Move_MovesCallbacks)309*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderWriterTest, Move_MovesCallbacks) {
310*61c4878aSAndroid Build Coastguard Worker   int calls = 0;
311*61c4878aSAndroid Build Coastguard Worker   reader_writer_.set_on_error([&calls](Status) { calls += 1; });
312*61c4878aSAndroid Build Coastguard Worker   reader_writer_.set_on_next([&calls](ConstByteSpan) { calls += 1; });
313*61c4878aSAndroid Build Coastguard Worker   reader_writer_.set_on_completion_requested_if_enabled(
314*61c4878aSAndroid Build Coastguard Worker       [&calls]() { calls += 1; });
315*61c4878aSAndroid Build Coastguard Worker 
316*61c4878aSAndroid Build Coastguard Worker   FakeServerReaderWriter destination(std::move(reader_writer_));
317*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
318*61c4878aSAndroid Build Coastguard Worker   destination.as_server_call().HandlePayload({});
319*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
320*61c4878aSAndroid Build Coastguard Worker   destination.as_server_call().HandleClientRequestedCompletion();
321*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
322*61c4878aSAndroid Build Coastguard Worker   destination.as_server_call().HandleError(Status::Unknown());
323*61c4878aSAndroid Build Coastguard Worker 
324*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(calls, 2 + PW_RPC_COMPLETION_REQUEST_CALLBACK);
325*61c4878aSAndroid Build Coastguard Worker }
326*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderWriterTest,Move_ClearsCallAndChannelId)327*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderWriterTest, Move_ClearsCallAndChannelId) {
328*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
329*61c4878aSAndroid Build Coastguard Worker   reader_writer_.set_id(999);
330*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(reader_writer_.channel_id_locked(), 0u);
331*61c4878aSAndroid Build Coastguard Worker   rpc_lock().unlock();
332*61c4878aSAndroid Build Coastguard Worker 
333*61c4878aSAndroid Build Coastguard Worker   FakeServerReaderWriter destination(std::move(reader_writer_));
334*61c4878aSAndroid Build Coastguard Worker 
335*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
336*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(reader_writer_.id(), 0u);
337*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(reader_writer_.channel_id_locked(), 0u);
338*61c4878aSAndroid Build Coastguard Worker }
339*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderWriterTest,DefaultConstructorAssign_Reset)340*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderWriterTest, DefaultConstructorAssign_Reset) {
341*61c4878aSAndroid Build Coastguard Worker   reader_writer_ = {};
342*61c4878aSAndroid Build Coastguard Worker 
343*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
344*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(reader_writer_.service_id(), 0u);
345*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(reader_writer_.method_id(), 0u);
346*61c4878aSAndroid Build Coastguard Worker }
347*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderWriterTest,Move_SourceAwaitingCleanup_CleansUpCalls)348*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderWriterTest, Move_SourceAwaitingCleanup_CleansUpCalls) {
349*61c4878aSAndroid Build Coastguard Worker   std::optional<Status> on_error_cb;
350*61c4878aSAndroid Build Coastguard Worker   reader_writer_.set_on_error([&on_error_cb](Status error) {
351*61c4878aSAndroid Build Coastguard Worker     ASSERT_FALSE(on_error_cb.has_value());
352*61c4878aSAndroid Build Coastguard Worker     on_error_cb = error;
353*61c4878aSAndroid Build Coastguard Worker   });
354*61c4878aSAndroid Build Coastguard Worker 
355*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
356*61c4878aSAndroid Build Coastguard Worker   context_.server().CloseCallAndMarkForCleanup(reader_writer_.as_server_call(),
357*61c4878aSAndroid Build Coastguard Worker                                                Status::NotFound());
358*61c4878aSAndroid Build Coastguard Worker   rpc_lock().unlock();
359*61c4878aSAndroid Build Coastguard Worker 
360*61c4878aSAndroid Build Coastguard Worker   FakeServerReaderWriter destination(std::move(reader_writer_));
361*61c4878aSAndroid Build Coastguard Worker 
362*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::NotFound(), on_error_cb);
363*61c4878aSAndroid Build Coastguard Worker }
364*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderWriterTest,Move_BothAwaitingCleanup_CleansUpCalls)365*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderWriterTest, Move_BothAwaitingCleanup_CleansUpCalls) {
366*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
367*61c4878aSAndroid Build Coastguard Worker   // Use call ID 123 so this call is distinct from the other.
368*61c4878aSAndroid Build Coastguard Worker   FakeServerReaderWriter destination(context_.get(123).ClaimLocked());
369*61c4878aSAndroid Build Coastguard Worker   rpc_lock().unlock();
370*61c4878aSAndroid Build Coastguard Worker 
371*61c4878aSAndroid Build Coastguard Worker   std::optional<Status> destination_on_error_cb;
372*61c4878aSAndroid Build Coastguard Worker   destination.set_on_error([&destination_on_error_cb](Status error) {
373*61c4878aSAndroid Build Coastguard Worker     ASSERT_FALSE(destination_on_error_cb.has_value());
374*61c4878aSAndroid Build Coastguard Worker     destination_on_error_cb = error;
375*61c4878aSAndroid Build Coastguard Worker   });
376*61c4878aSAndroid Build Coastguard Worker 
377*61c4878aSAndroid Build Coastguard Worker   std::optional<Status> source_on_error_cb;
378*61c4878aSAndroid Build Coastguard Worker   reader_writer_.set_on_error([&source_on_error_cb](Status error) {
379*61c4878aSAndroid Build Coastguard Worker     ASSERT_FALSE(source_on_error_cb.has_value());
380*61c4878aSAndroid Build Coastguard Worker     source_on_error_cb = error;
381*61c4878aSAndroid Build Coastguard Worker   });
382*61c4878aSAndroid Build Coastguard Worker 
383*61c4878aSAndroid Build Coastguard Worker   // Simulate these two calls being closed by another thread.
384*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
385*61c4878aSAndroid Build Coastguard Worker   context_.server().CloseCallAndMarkForCleanup(destination.as_server_call(),
386*61c4878aSAndroid Build Coastguard Worker                                                Status::NotFound());
387*61c4878aSAndroid Build Coastguard Worker   context_.server().CloseCallAndMarkForCleanup(reader_writer_.as_server_call(),
388*61c4878aSAndroid Build Coastguard Worker                                                Status::Unauthenticated());
389*61c4878aSAndroid Build Coastguard Worker   rpc_lock().unlock();
390*61c4878aSAndroid Build Coastguard Worker 
391*61c4878aSAndroid Build Coastguard Worker   destination = std::move(reader_writer_);
392*61c4878aSAndroid Build Coastguard Worker 
393*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::NotFound(), destination_on_error_cb);
394*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Status::Unauthenticated(), source_on_error_cb);
395*61c4878aSAndroid Build Coastguard Worker }
396*61c4878aSAndroid Build Coastguard Worker 
TEST_F(ServerReaderWriterTest,Close_ClearsCallAndChannelId)397*61c4878aSAndroid Build Coastguard Worker TEST_F(ServerReaderWriterTest, Close_ClearsCallAndChannelId) {
398*61c4878aSAndroid Build Coastguard Worker   rpc_lock().lock();
399*61c4878aSAndroid Build Coastguard Worker   reader_writer_.set_id(999);
400*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(reader_writer_.channel_id_locked(), 0u);
401*61c4878aSAndroid Build Coastguard Worker   rpc_lock().unlock();
402*61c4878aSAndroid Build Coastguard Worker 
403*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(OkStatus(), reader_writer_.Finish());
404*61c4878aSAndroid Build Coastguard Worker 
405*61c4878aSAndroid Build Coastguard Worker   RpcLockGuard lock;
406*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(reader_writer_.id(), 0u);
407*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(reader_writer_.channel_id_locked(), 0u);
408*61c4878aSAndroid Build Coastguard Worker }
409*61c4878aSAndroid Build Coastguard Worker 
410*61c4878aSAndroid Build Coastguard Worker }  // namespace
411*61c4878aSAndroid Build Coastguard Worker }  // namespace internal
412*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::rpc
413