1*61c4878aSAndroid Build Coastguard Worker // Copyright 2022 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/pwpb/internal/method.h"
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Worker #include <array>
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker #include "pw_containers/algorithm.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/lock.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/method_impl_tester.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/test_utils.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/pwpb/internal/method_union.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/service.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc_pwpb_private/internal_test_utils.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc_test_protos/test.pwpb.h"
27*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
28*61c4878aSAndroid Build Coastguard Worker
29*61c4878aSAndroid Build Coastguard Worker PW_MODIFY_DIAGNOSTICS_PUSH();
30*61c4878aSAndroid Build Coastguard Worker PW_MODIFY_DIAGNOSTIC(ignored, "-Wmissing-field-initializers");
31*61c4878aSAndroid Build Coastguard Worker
32*61c4878aSAndroid Build Coastguard Worker namespace pw::rpc::internal {
33*61c4878aSAndroid Build Coastguard Worker namespace {
34*61c4878aSAndroid Build Coastguard Worker
35*61c4878aSAndroid Build Coastguard Worker using std::byte;
36*61c4878aSAndroid Build Coastguard Worker
37*61c4878aSAndroid Build Coastguard Worker struct FakePb {};
38*61c4878aSAndroid Build Coastguard Worker
39*61c4878aSAndroid Build Coastguard Worker // Create a fake service for use with the MethodImplTester.
40*61c4878aSAndroid Build Coastguard Worker class TestPwpbService final : public Service {
41*61c4878aSAndroid Build Coastguard Worker public:
42*61c4878aSAndroid Build Coastguard Worker // Unary signatures
43*61c4878aSAndroid Build Coastguard Worker
Unary(const FakePb &,FakePb &)44*61c4878aSAndroid Build Coastguard Worker Status Unary(const FakePb&, FakePb&) { return Status(); }
45*61c4878aSAndroid Build Coastguard Worker
StaticUnary(const FakePb &,FakePb &)46*61c4878aSAndroid Build Coastguard Worker static Status StaticUnary(const FakePb&, FakePb&) { return Status(); }
47*61c4878aSAndroid Build Coastguard Worker
AsyncUnary(const FakePb &,PwpbUnaryResponder<FakePb> &)48*61c4878aSAndroid Build Coastguard Worker void AsyncUnary(const FakePb&, PwpbUnaryResponder<FakePb>&) {}
49*61c4878aSAndroid Build Coastguard Worker
StaticAsyncUnary(const FakePb &,PwpbUnaryResponder<FakePb> &)50*61c4878aSAndroid Build Coastguard Worker static void StaticAsyncUnary(const FakePb&, PwpbUnaryResponder<FakePb>&) {}
51*61c4878aSAndroid Build Coastguard Worker
UnaryWrongArg(FakePb &,FakePb &)52*61c4878aSAndroid Build Coastguard Worker Status UnaryWrongArg(FakePb&, FakePb&) { return Status(); }
53*61c4878aSAndroid Build Coastguard Worker
StaticUnaryVoidReturn(const FakePb &,FakePb &)54*61c4878aSAndroid Build Coastguard Worker static void StaticUnaryVoidReturn(const FakePb&, FakePb&) {}
55*61c4878aSAndroid Build Coastguard Worker
56*61c4878aSAndroid Build Coastguard Worker // Server streaming signatures
57*61c4878aSAndroid Build Coastguard Worker
ServerStreaming(const FakePb &,PwpbServerWriter<FakePb> &)58*61c4878aSAndroid Build Coastguard Worker void ServerStreaming(const FakePb&, PwpbServerWriter<FakePb>&) {}
59*61c4878aSAndroid Build Coastguard Worker
StaticServerStreaming(const FakePb &,PwpbServerWriter<FakePb> &)60*61c4878aSAndroid Build Coastguard Worker static void StaticServerStreaming(const FakePb&, PwpbServerWriter<FakePb>&) {}
61*61c4878aSAndroid Build Coastguard Worker
ServerStreamingBadReturn(const FakePb &,PwpbServerWriter<FakePb> &)62*61c4878aSAndroid Build Coastguard Worker int ServerStreamingBadReturn(const FakePb&, PwpbServerWriter<FakePb>&) {
63*61c4878aSAndroid Build Coastguard Worker return 5;
64*61c4878aSAndroid Build Coastguard Worker }
65*61c4878aSAndroid Build Coastguard Worker
StaticServerStreamingMissingArg(PwpbServerWriter<FakePb> &)66*61c4878aSAndroid Build Coastguard Worker static void StaticServerStreamingMissingArg(PwpbServerWriter<FakePb>&) {}
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker // Client streaming signatures
69*61c4878aSAndroid Build Coastguard Worker
ClientStreaming(PwpbServerReader<FakePb,FakePb> &)70*61c4878aSAndroid Build Coastguard Worker void ClientStreaming(PwpbServerReader<FakePb, FakePb>&) {}
71*61c4878aSAndroid Build Coastguard Worker
StaticClientStreaming(PwpbServerReader<FakePb,FakePb> &)72*61c4878aSAndroid Build Coastguard Worker static void StaticClientStreaming(PwpbServerReader<FakePb, FakePb>&) {}
73*61c4878aSAndroid Build Coastguard Worker
ClientStreamingBadReturn(PwpbServerReader<FakePb,FakePb> &)74*61c4878aSAndroid Build Coastguard Worker int ClientStreamingBadReturn(PwpbServerReader<FakePb, FakePb>&) { return 0; }
75*61c4878aSAndroid Build Coastguard Worker
StaticClientStreamingMissingArg()76*61c4878aSAndroid Build Coastguard Worker static void StaticClientStreamingMissingArg() {}
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard Worker // Bidirectional streaming signatures
79*61c4878aSAndroid Build Coastguard Worker
BidirectionalStreaming(PwpbServerReaderWriter<FakePb,FakePb> &)80*61c4878aSAndroid Build Coastguard Worker void BidirectionalStreaming(PwpbServerReaderWriter<FakePb, FakePb>&) {}
81*61c4878aSAndroid Build Coastguard Worker
StaticBidirectionalStreaming(PwpbServerReaderWriter<FakePb,FakePb> &)82*61c4878aSAndroid Build Coastguard Worker static void StaticBidirectionalStreaming(
83*61c4878aSAndroid Build Coastguard Worker PwpbServerReaderWriter<FakePb, FakePb>&) {}
84*61c4878aSAndroid Build Coastguard Worker
BidirectionalStreamingBadReturn(PwpbServerReaderWriter<FakePb,FakePb> &)85*61c4878aSAndroid Build Coastguard Worker int BidirectionalStreamingBadReturn(PwpbServerReaderWriter<FakePb, FakePb>&) {
86*61c4878aSAndroid Build Coastguard Worker return 0;
87*61c4878aSAndroid Build Coastguard Worker }
88*61c4878aSAndroid Build Coastguard Worker
StaticBidirectionalStreamingMissingArg()89*61c4878aSAndroid Build Coastguard Worker static void StaticBidirectionalStreamingMissingArg() {}
90*61c4878aSAndroid Build Coastguard Worker };
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker struct WrongPb;
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker // Test matches() rejects incorrect request/response types.
95*61c4878aSAndroid Build Coastguard Worker // clang-format off
96*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::Unary, WrongPb, FakePb>());
97*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::Unary, FakePb, WrongPb>());
98*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::Unary, WrongPb, WrongPb>());
99*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::StaticUnary, FakePb, WrongPb>());
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::ServerStreaming, WrongPb, FakePb>());
102*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::StaticServerStreaming, FakePb, WrongPb>());
103*61c4878aSAndroid Build Coastguard Worker
104*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::ClientStreaming, WrongPb, FakePb>());
105*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::StaticClientStreaming, FakePb, WrongPb>());
106*61c4878aSAndroid Build Coastguard Worker
107*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::BidirectionalStreaming, WrongPb, FakePb>());
108*61c4878aSAndroid Build Coastguard Worker static_assert(!PwpbMethod::template matches<&TestPwpbService::StaticBidirectionalStreaming, FakePb, WrongPb>());
109*61c4878aSAndroid Build Coastguard Worker // clang-format on
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard Worker static_assert(MethodImplTests<PwpbMethod, TestPwpbService>().Pass(
112*61c4878aSAndroid Build Coastguard Worker MatchesTypes<FakePb, FakePb>(),
113*61c4878aSAndroid Build Coastguard Worker std::tuple<const PwpbMethodSerde&>(kPwpbMethodSerde<nullptr, nullptr>)));
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard Worker template <typename Impl>
116*61c4878aSAndroid Build Coastguard Worker class FakeServiceBase : public Service {
117*61c4878aSAndroid Build Coastguard Worker public:
FakeServiceBase(uint32_t id)118*61c4878aSAndroid Build Coastguard Worker FakeServiceBase(uint32_t id) : Service(id, kMethods) {}
119*61c4878aSAndroid Build Coastguard Worker
120*61c4878aSAndroid Build Coastguard Worker static constexpr std::array<PwpbMethodUnion, 5> kMethods = {
121*61c4878aSAndroid Build Coastguard Worker PwpbMethod::SynchronousUnary<&Impl::DoNothing>(
122*61c4878aSAndroid Build Coastguard Worker 10u,
123*61c4878aSAndroid Build Coastguard Worker kPwpbMethodSerde<&pw::rpc::test::pwpb::Empty::kMessageFields,
124*61c4878aSAndroid Build Coastguard Worker &pw::rpc::test::pwpb::Empty::kMessageFields>),
125*61c4878aSAndroid Build Coastguard Worker PwpbMethod::AsynchronousUnary<&Impl::AddFive>(
126*61c4878aSAndroid Build Coastguard Worker 11u,
127*61c4878aSAndroid Build Coastguard Worker kPwpbMethodSerde<&pw::rpc::test::pwpb::TestRequest::kMessageFields,
128*61c4878aSAndroid Build Coastguard Worker &pw::rpc::test::pwpb::TestResponse::kMessageFields>),
129*61c4878aSAndroid Build Coastguard Worker PwpbMethod::ServerStreaming<&Impl::StartStream>(
130*61c4878aSAndroid Build Coastguard Worker 12u,
131*61c4878aSAndroid Build Coastguard Worker kPwpbMethodSerde<&pw::rpc::test::pwpb::TestRequest::kMessageFields,
132*61c4878aSAndroid Build Coastguard Worker &pw::rpc::test::pwpb::TestResponse::kMessageFields>),
133*61c4878aSAndroid Build Coastguard Worker PwpbMethod::ClientStreaming<&Impl::ClientStream>(
134*61c4878aSAndroid Build Coastguard Worker 13u,
135*61c4878aSAndroid Build Coastguard Worker kPwpbMethodSerde<&pw::rpc::test::pwpb::TestRequest::kMessageFields,
136*61c4878aSAndroid Build Coastguard Worker &pw::rpc::test::pwpb::TestResponse::kMessageFields>),
137*61c4878aSAndroid Build Coastguard Worker PwpbMethod::BidirectionalStreaming<&Impl::BidirectionalStream>(
138*61c4878aSAndroid Build Coastguard Worker 14u,
139*61c4878aSAndroid Build Coastguard Worker kPwpbMethodSerde<&pw::rpc::test::pwpb::TestRequest::kMessageFields,
140*61c4878aSAndroid Build Coastguard Worker &pw::rpc::test::pwpb::TestResponse::kMessageFields>),
141*61c4878aSAndroid Build Coastguard Worker };
142*61c4878aSAndroid Build Coastguard Worker };
143*61c4878aSAndroid Build Coastguard Worker
144*61c4878aSAndroid Build Coastguard Worker class FakeService : public FakeServiceBase<FakeService> {
145*61c4878aSAndroid Build Coastguard Worker public:
FakeService(uint32_t id)146*61c4878aSAndroid Build Coastguard Worker FakeService(uint32_t id) : FakeServiceBase(id) {}
147*61c4878aSAndroid Build Coastguard Worker
DoNothing(const pw::rpc::test::pwpb::Empty::Message &,pw::rpc::test::pwpb::Empty::Message &)148*61c4878aSAndroid Build Coastguard Worker Status DoNothing(const pw::rpc::test::pwpb::Empty::Message&,
149*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::Empty::Message&) {
150*61c4878aSAndroid Build Coastguard Worker return Status::Unknown();
151*61c4878aSAndroid Build Coastguard Worker }
152*61c4878aSAndroid Build Coastguard Worker
AddFive(const pw::rpc::test::pwpb::TestRequest::Message & request,PwpbUnaryResponder<pw::rpc::test::pwpb::TestResponse::Message> & responder)153*61c4878aSAndroid Build Coastguard Worker void AddFive(const pw::rpc::test::pwpb::TestRequest::Message& request,
154*61c4878aSAndroid Build Coastguard Worker PwpbUnaryResponder<pw::rpc::test::pwpb::TestResponse::Message>&
155*61c4878aSAndroid Build Coastguard Worker responder) {
156*61c4878aSAndroid Build Coastguard Worker last_request = request;
157*61c4878aSAndroid Build Coastguard Worker
158*61c4878aSAndroid Build Coastguard Worker if (fail_to_encode_async_unary_response) {
159*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestResponse::Message response = {};
160*61c4878aSAndroid Build Coastguard Worker response.repeated_field.SetEncoder(
161*61c4878aSAndroid Build Coastguard Worker [](const pw::rpc::test::pwpb::TestResponse::StreamEncoder&) {
162*61c4878aSAndroid Build Coastguard Worker return Status::Internal();
163*61c4878aSAndroid Build Coastguard Worker });
164*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), responder.Finish(response, Status::NotFound()));
165*61c4878aSAndroid Build Coastguard Worker } else {
166*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(
167*61c4878aSAndroid Build Coastguard Worker OkStatus(),
168*61c4878aSAndroid Build Coastguard Worker responder.Finish({.value = static_cast<int32_t>(request.integer + 5)},
169*61c4878aSAndroid Build Coastguard Worker Status::Unauthenticated()));
170*61c4878aSAndroid Build Coastguard Worker }
171*61c4878aSAndroid Build Coastguard Worker }
172*61c4878aSAndroid Build Coastguard Worker
StartStream(const pw::rpc::test::pwpb::TestRequest::Message & request,PwpbServerWriter<pw::rpc::test::pwpb::TestResponse::Message> & writer)173*61c4878aSAndroid Build Coastguard Worker void StartStream(
174*61c4878aSAndroid Build Coastguard Worker const pw::rpc::test::pwpb::TestRequest::Message& request,
175*61c4878aSAndroid Build Coastguard Worker PwpbServerWriter<pw::rpc::test::pwpb::TestResponse::Message>& writer) {
176*61c4878aSAndroid Build Coastguard Worker last_request = request;
177*61c4878aSAndroid Build Coastguard Worker last_writer = std::move(writer);
178*61c4878aSAndroid Build Coastguard Worker }
179*61c4878aSAndroid Build Coastguard Worker
ClientStream(PwpbServerReader<pw::rpc::test::pwpb::TestRequest::Message,pw::rpc::test::pwpb::TestResponse::Message> & reader)180*61c4878aSAndroid Build Coastguard Worker void ClientStream(
181*61c4878aSAndroid Build Coastguard Worker PwpbServerReader<pw::rpc::test::pwpb::TestRequest::Message,
182*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestResponse::Message>& reader) {
183*61c4878aSAndroid Build Coastguard Worker last_reader = std::move(reader);
184*61c4878aSAndroid Build Coastguard Worker }
185*61c4878aSAndroid Build Coastguard Worker
BidirectionalStream(PwpbServerReaderWriter<pw::rpc::test::pwpb::TestRequest::Message,pw::rpc::test::pwpb::TestResponse::Message> & reader_writer)186*61c4878aSAndroid Build Coastguard Worker void BidirectionalStream(
187*61c4878aSAndroid Build Coastguard Worker PwpbServerReaderWriter<pw::rpc::test::pwpb::TestRequest::Message,
188*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestResponse::Message>&
189*61c4878aSAndroid Build Coastguard Worker reader_writer) {
190*61c4878aSAndroid Build Coastguard Worker last_reader_writer = std::move(reader_writer);
191*61c4878aSAndroid Build Coastguard Worker }
192*61c4878aSAndroid Build Coastguard Worker
193*61c4878aSAndroid Build Coastguard Worker bool fail_to_encode_async_unary_response = false;
194*61c4878aSAndroid Build Coastguard Worker
195*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestRequest::Message last_request;
196*61c4878aSAndroid Build Coastguard Worker PwpbServerWriter<pw::rpc::test::pwpb::TestResponse::Message> last_writer;
197*61c4878aSAndroid Build Coastguard Worker PwpbServerReader<pw::rpc::test::pwpb::TestRequest::Message,
198*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestResponse::Message>
199*61c4878aSAndroid Build Coastguard Worker last_reader;
200*61c4878aSAndroid Build Coastguard Worker PwpbServerReaderWriter<pw::rpc::test::pwpb::TestRequest::Message,
201*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestResponse::Message>
202*61c4878aSAndroid Build Coastguard Worker last_reader_writer;
203*61c4878aSAndroid Build Coastguard Worker };
204*61c4878aSAndroid Build Coastguard Worker
205*61c4878aSAndroid Build Coastguard Worker constexpr const PwpbMethod& kSyncUnary =
206*61c4878aSAndroid Build Coastguard Worker std::get<0>(FakeServiceBase<FakeService>::kMethods).pwpb_method();
207*61c4878aSAndroid Build Coastguard Worker constexpr const PwpbMethod& kAsyncUnary =
208*61c4878aSAndroid Build Coastguard Worker std::get<1>(FakeServiceBase<FakeService>::kMethods).pwpb_method();
209*61c4878aSAndroid Build Coastguard Worker constexpr const PwpbMethod& kServerStream =
210*61c4878aSAndroid Build Coastguard Worker std::get<2>(FakeServiceBase<FakeService>::kMethods).pwpb_method();
211*61c4878aSAndroid Build Coastguard Worker constexpr const PwpbMethod& kClientStream =
212*61c4878aSAndroid Build Coastguard Worker std::get<3>(FakeServiceBase<FakeService>::kMethods).pwpb_method();
213*61c4878aSAndroid Build Coastguard Worker constexpr const PwpbMethod& kBidirectionalStream =
214*61c4878aSAndroid Build Coastguard Worker std::get<4>(FakeServiceBase<FakeService>::kMethods).pwpb_method();
215*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,AsyncUnaryRpc_SendsResponse)216*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, AsyncUnaryRpc_SendsResponse) {
217*61c4878aSAndroid Build Coastguard Worker PW_ENCODE_PB(pw::rpc::test::pwpb::TestRequest,
218*61c4878aSAndroid Build Coastguard Worker request,
219*61c4878aSAndroid Build Coastguard Worker .integer = 123,
220*61c4878aSAndroid Build Coastguard Worker .status_code = 0);
221*61c4878aSAndroid Build Coastguard Worker
222*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kAsyncUnary);
223*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
224*61c4878aSAndroid Build Coastguard Worker kAsyncUnary.Invoke(context.get(), context.request(request));
225*61c4878aSAndroid Build Coastguard Worker
226*61c4878aSAndroid Build Coastguard Worker const Packet& response = context.output().last_packet();
227*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(response.status(), Status::Unauthenticated());
228*61c4878aSAndroid Build Coastguard Worker
229*61c4878aSAndroid Build Coastguard Worker // Field 1 (encoded as 1 << 3) with 128 as the value.
230*61c4878aSAndroid Build Coastguard Worker constexpr std::byte expected[]{
231*61c4878aSAndroid Build Coastguard Worker std::byte{0x08}, std::byte{0x80}, std::byte{0x01}};
232*61c4878aSAndroid Build Coastguard Worker
233*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(sizeof(expected), response.payload().size());
234*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(0,
235*61c4878aSAndroid Build Coastguard Worker std::memcmp(expected, response.payload().data(), sizeof(expected)));
236*61c4878aSAndroid Build Coastguard Worker
237*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(123, context.service().last_request.integer);
238*61c4878aSAndroid Build Coastguard Worker }
239*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,SyncUnaryRpc_InvalidPayload_SendsError)240*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, SyncUnaryRpc_InvalidPayload_SendsError) {
241*61c4878aSAndroid Build Coastguard Worker std::array<byte, 8> bad_payload{byte{0xFF}, byte{0xAA}, byte{0xDD}};
242*61c4878aSAndroid Build Coastguard Worker
243*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kSyncUnary);
244*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
245*61c4878aSAndroid Build Coastguard Worker kSyncUnary.Invoke(context.get(), context.request(bad_payload));
246*61c4878aSAndroid Build Coastguard Worker
247*61c4878aSAndroid Build Coastguard Worker const Packet& packet = context.output().last_packet();
248*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(pwpb::PacketType::SERVER_ERROR, packet.type());
249*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Status::DataLoss(), packet.status());
250*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(context.service_id(), packet.service_id());
251*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(kSyncUnary.id(), packet.method_id());
252*61c4878aSAndroid Build Coastguard Worker }
253*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,AsyncUnaryRpc_ResponseEncodingFails_SendsInternalError)254*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, AsyncUnaryRpc_ResponseEncodingFails_SendsInternalError) {
255*61c4878aSAndroid Build Coastguard Worker constexpr int64_t value = 0x7FFFFFFF'FFFFFF00ll;
256*61c4878aSAndroid Build Coastguard Worker PW_ENCODE_PB(pw::rpc::test::pwpb::TestRequest,
257*61c4878aSAndroid Build Coastguard Worker request,
258*61c4878aSAndroid Build Coastguard Worker .integer = value,
259*61c4878aSAndroid Build Coastguard Worker .status_code = 0);
260*61c4878aSAndroid Build Coastguard Worker
261*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kAsyncUnary);
262*61c4878aSAndroid Build Coastguard Worker context.service().fail_to_encode_async_unary_response = true;
263*61c4878aSAndroid Build Coastguard Worker
264*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
265*61c4878aSAndroid Build Coastguard Worker kAsyncUnary.Invoke(context.get(), context.request(request));
266*61c4878aSAndroid Build Coastguard Worker
267*61c4878aSAndroid Build Coastguard Worker const Packet& packet = context.output().last_packet();
268*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(pwpb::PacketType::SERVER_ERROR, packet.type());
269*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Status::Internal(), packet.status());
270*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(context.service_id(), packet.service_id());
271*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(kAsyncUnary.id(), packet.method_id());
272*61c4878aSAndroid Build Coastguard Worker
273*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(value, context.service().last_request.integer);
274*61c4878aSAndroid Build Coastguard Worker }
275*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerStreamingRpc_SendsNothingWhenInitiallyCalled)276*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerStreamingRpc_SendsNothingWhenInitiallyCalled) {
277*61c4878aSAndroid Build Coastguard Worker PW_ENCODE_PB(pw::rpc::test::pwpb::TestRequest,
278*61c4878aSAndroid Build Coastguard Worker request,
279*61c4878aSAndroid Build Coastguard Worker .integer = 555,
280*61c4878aSAndroid Build Coastguard Worker .status_code = 0);
281*61c4878aSAndroid Build Coastguard Worker
282*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kServerStream);
283*61c4878aSAndroid Build Coastguard Worker
284*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
285*61c4878aSAndroid Build Coastguard Worker kServerStream.Invoke(context.get(), context.request(request));
286*61c4878aSAndroid Build Coastguard Worker
287*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(0u, context.output().total_packets());
288*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(555, context.service().last_request.integer);
289*61c4878aSAndroid Build Coastguard Worker }
290*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerWriter_SendsResponse)291*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerWriter_SendsResponse) {
292*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kServerStream);
293*61c4878aSAndroid Build Coastguard Worker
294*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
295*61c4878aSAndroid Build Coastguard Worker kServerStream.Invoke(context.get(), context.request({}));
296*61c4878aSAndroid Build Coastguard Worker
297*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(OkStatus(), context.service().last_writer.Write({.value = 100}));
298*61c4878aSAndroid Build Coastguard Worker
299*61c4878aSAndroid Build Coastguard Worker PW_ENCODE_PB(pw::rpc::test::pwpb::TestResponse, payload, .value = 100);
300*61c4878aSAndroid Build Coastguard Worker std::array<byte, 128> encoded_response = {};
301*61c4878aSAndroid Build Coastguard Worker auto encoded = context.server_stream(payload).Encode(encoded_response);
302*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), encoded.status());
303*61c4878aSAndroid Build Coastguard Worker
304*61c4878aSAndroid Build Coastguard Worker ConstByteSpan sent_payload = context.output().last_packet().payload();
305*61c4878aSAndroid Build Coastguard Worker EXPECT_TRUE(pw::containers::Equal(payload, sent_payload));
306*61c4878aSAndroid Build Coastguard Worker }
307*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerWriter_WriteWhenClosed_ReturnsFailedPrecondition)308*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerWriter_WriteWhenClosed_ReturnsFailedPrecondition) {
309*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kServerStream);
310*61c4878aSAndroid Build Coastguard Worker
311*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
312*61c4878aSAndroid Build Coastguard Worker kServerStream.Invoke(context.get(), context.request({}));
313*61c4878aSAndroid Build Coastguard Worker
314*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(OkStatus(), context.service().last_writer.Finish());
315*61c4878aSAndroid Build Coastguard Worker EXPECT_TRUE(context.service()
316*61c4878aSAndroid Build Coastguard Worker .last_writer.Write({.value = 100})
317*61c4878aSAndroid Build Coastguard Worker .IsFailedPrecondition());
318*61c4878aSAndroid Build Coastguard Worker }
319*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerWriter_WriteAfterMoved_ReturnsFailedPrecondition)320*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerWriter_WriteAfterMoved_ReturnsFailedPrecondition) {
321*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kServerStream);
322*61c4878aSAndroid Build Coastguard Worker
323*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
324*61c4878aSAndroid Build Coastguard Worker kServerStream.Invoke(context.get(), context.request({}));
325*61c4878aSAndroid Build Coastguard Worker PwpbServerWriter<pw::rpc::test::pwpb::TestResponse::Message> new_writer =
326*61c4878aSAndroid Build Coastguard Worker std::move(context.service().last_writer);
327*61c4878aSAndroid Build Coastguard Worker
328*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(OkStatus(), new_writer.Write({.value = 100}));
329*61c4878aSAndroid Build Coastguard Worker
330*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Status::FailedPrecondition(),
331*61c4878aSAndroid Build Coastguard Worker context.service().last_writer.Write({.value = 100}));
332*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Status::FailedPrecondition(),
333*61c4878aSAndroid Build Coastguard Worker context.service().last_writer.Finish());
334*61c4878aSAndroid Build Coastguard Worker
335*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(OkStatus(), new_writer.Finish());
336*61c4878aSAndroid Build Coastguard Worker }
337*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerStreamingRpc_ResponseEncodingFails_InternalError)338*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerStreamingRpc_ResponseEncodingFails_InternalError) {
339*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kServerStream);
340*61c4878aSAndroid Build Coastguard Worker
341*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
342*61c4878aSAndroid Build Coastguard Worker kServerStream.Invoke(context.get(), context.request({}));
343*61c4878aSAndroid Build Coastguard Worker
344*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(OkStatus(), context.service().last_writer.Write({}));
345*61c4878aSAndroid Build Coastguard Worker
346*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestResponse::Message response = {};
347*61c4878aSAndroid Build Coastguard Worker response.repeated_field.SetEncoder(
348*61c4878aSAndroid Build Coastguard Worker [](const pw::rpc::test::pwpb::TestResponse::StreamEncoder&) {
349*61c4878aSAndroid Build Coastguard Worker return Status::Internal();
350*61c4878aSAndroid Build Coastguard Worker });
351*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Status::Internal(), context.service().last_writer.Write(response));
352*61c4878aSAndroid Build Coastguard Worker }
353*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerReader_HandlesRequests)354*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerReader_HandlesRequests) {
355*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kClientStream);
356*61c4878aSAndroid Build Coastguard Worker
357*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
358*61c4878aSAndroid Build Coastguard Worker kClientStream.Invoke(context.get(), context.request({}));
359*61c4878aSAndroid Build Coastguard Worker
360*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestRequest::Message request_struct{};
361*61c4878aSAndroid Build Coastguard Worker context.service().last_reader.set_on_next(
362*61c4878aSAndroid Build Coastguard Worker [&request_struct](const pw::rpc::test::pwpb::TestRequest::Message& req) {
363*61c4878aSAndroid Build Coastguard Worker request_struct = req;
364*61c4878aSAndroid Build Coastguard Worker });
365*61c4878aSAndroid Build Coastguard Worker
366*61c4878aSAndroid Build Coastguard Worker PW_ENCODE_PB(pw::rpc::test::pwpb::TestRequest,
367*61c4878aSAndroid Build Coastguard Worker request,
368*61c4878aSAndroid Build Coastguard Worker .integer = 1 << 30,
369*61c4878aSAndroid Build Coastguard Worker .status_code = 9);
370*61c4878aSAndroid Build Coastguard Worker std::array<byte, 128> encoded_request = {};
371*61c4878aSAndroid Build Coastguard Worker auto encoded = context.client_stream(request).Encode(encoded_request);
372*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), encoded.status());
373*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), context.server().ProcessPacket(*encoded));
374*61c4878aSAndroid Build Coastguard Worker
375*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(request_struct.integer, 1 << 30);
376*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(request_struct.status_code, 9u);
377*61c4878aSAndroid Build Coastguard Worker }
378*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerReaderWriter_WritesResponses)379*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerReaderWriter_WritesResponses) {
380*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kBidirectionalStream);
381*61c4878aSAndroid Build Coastguard Worker
382*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
383*61c4878aSAndroid Build Coastguard Worker kBidirectionalStream.Invoke(context.get(), context.request({}));
384*61c4878aSAndroid Build Coastguard Worker
385*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(OkStatus(),
386*61c4878aSAndroid Build Coastguard Worker context.service().last_reader_writer.Write({.value = 100}));
387*61c4878aSAndroid Build Coastguard Worker
388*61c4878aSAndroid Build Coastguard Worker PW_ENCODE_PB(pw::rpc::test::pwpb::TestResponse, payload, .value = 100);
389*61c4878aSAndroid Build Coastguard Worker std::array<byte, 128> encoded_response = {};
390*61c4878aSAndroid Build Coastguard Worker auto encoded = context.server_stream(payload).Encode(encoded_response);
391*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), encoded.status());
392*61c4878aSAndroid Build Coastguard Worker
393*61c4878aSAndroid Build Coastguard Worker ConstByteSpan sent_payload = context.output().last_packet().payload();
394*61c4878aSAndroid Build Coastguard Worker EXPECT_TRUE(pw::containers::Equal(payload, sent_payload));
395*61c4878aSAndroid Build Coastguard Worker }
396*61c4878aSAndroid Build Coastguard Worker
TEST(PwpbMethod,ServerReaderWriter_HandlesRequests)397*61c4878aSAndroid Build Coastguard Worker TEST(PwpbMethod, ServerReaderWriter_HandlesRequests) {
398*61c4878aSAndroid Build Coastguard Worker ServerContextForTest<FakeService> context(kBidirectionalStream);
399*61c4878aSAndroid Build Coastguard Worker
400*61c4878aSAndroid Build Coastguard Worker rpc_lock().lock();
401*61c4878aSAndroid Build Coastguard Worker kBidirectionalStream.Invoke(context.get(), context.request({}));
402*61c4878aSAndroid Build Coastguard Worker
403*61c4878aSAndroid Build Coastguard Worker pw::rpc::test::pwpb::TestRequest::Message request_struct{};
404*61c4878aSAndroid Build Coastguard Worker context.service().last_reader_writer.set_on_next(
405*61c4878aSAndroid Build Coastguard Worker [&request_struct](const pw::rpc::test::pwpb::TestRequest::Message& req) {
406*61c4878aSAndroid Build Coastguard Worker request_struct = req;
407*61c4878aSAndroid Build Coastguard Worker });
408*61c4878aSAndroid Build Coastguard Worker
409*61c4878aSAndroid Build Coastguard Worker PW_ENCODE_PB(pw::rpc::test::pwpb::TestRequest,
410*61c4878aSAndroid Build Coastguard Worker request,
411*61c4878aSAndroid Build Coastguard Worker .integer = 1 << 29,
412*61c4878aSAndroid Build Coastguard Worker .status_code = 8);
413*61c4878aSAndroid Build Coastguard Worker std::array<byte, 128> encoded_request = {};
414*61c4878aSAndroid Build Coastguard Worker auto encoded = context.client_stream(request).Encode(encoded_request);
415*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), encoded.status());
416*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(OkStatus(), context.server().ProcessPacket(*encoded));
417*61c4878aSAndroid Build Coastguard Worker
418*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(request_struct.integer, 1 << 29);
419*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(request_struct.status_code, 8u);
420*61c4878aSAndroid Build Coastguard Worker }
421*61c4878aSAndroid Build Coastguard Worker
422*61c4878aSAndroid Build Coastguard Worker } // namespace
423*61c4878aSAndroid Build Coastguard Worker } // namespace pw::rpc::internal
424*61c4878aSAndroid Build Coastguard Worker
425*61c4878aSAndroid Build Coastguard Worker PW_MODIFY_DIAGNOSTICS_POP();
426