xref: /aosp_15_r20/external/pigweed/pw_rpc/client_integration_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include <algorithm>
16 #include <array>
17 #include <cstring>
18 
19 #include "pw_assert/check.h"
20 #include "pw_log/log.h"
21 #include "pw_rpc/benchmark.raw_rpc.pb.h"
22 #include "pw_rpc/integration_testing.h"
23 #include "pw_sync/binary_semaphore.h"
24 #include "pw_unit_test/framework.h"
25 
26 namespace rpc_test {
27 namespace {
28 
29 constexpr int kIterations = 3;
30 
31 using namespace std::chrono_literals;
32 using pw::ByteSpan;
33 using pw::ConstByteSpan;
34 using pw::Function;
35 using pw::OkStatus;
36 using pw::Status;
37 
38 using pw::rpc::pw_rpc::raw::Benchmark;
39 
40 Benchmark::Client kServiceClient(pw::rpc::integration_test::client(),
41                                  pw::rpc::integration_test::kChannelId);
42 
43 class StringReceiver {
44  public:
Wait()45   const char* Wait() {
46     PW_CHECK(sem_.try_acquire_for(10s));
47     return reinterpret_cast<const char*>(buffer_.data());
48   }
49 
UnaryOnCompleted()50   Function<void(ConstByteSpan, Status)> UnaryOnCompleted() {
51     return [this](ConstByteSpan data, Status) { CopyStringPayload(data); };
52   }
53 
OnNext()54   Function<void(ConstByteSpan)> OnNext() {
55     return [this](ConstByteSpan data) { CopyStringPayload(data); };
56   }
57 
CopyStringPayload(ConstByteSpan data)58   void CopyStringPayload(ConstByteSpan data) {
59     std::memset(buffer_.data(), 0, buffer_.size());
60     PW_CHECK_UINT_LE(data.size(), buffer_.size());
61     std::copy(data.begin(), data.end(), buffer_.begin());
62     sem_.release();
63   }
64 
ReverseCopyStringPayload(ConstByteSpan data)65   void ReverseCopyStringPayload(ConstByteSpan data) {
66     std::memset(buffer_.data(), 0, buffer_.size());
67     PW_CHECK_UINT_LE(data.size(), buffer_.size());
68     std::reverse_copy(data.begin(), data.end() - 1, buffer_.begin());
69     sem_.release();
70   }
71 
72  private:
73   pw::sync::BinarySemaphore sem_;
74   std::array<std::byte, 64> buffer_;
75 };
76 
TEST(RawRpcIntegrationTest,Unary)77 TEST(RawRpcIntegrationTest, Unary) {
78   for (int i = 0; i < kIterations; ++i) {
79     StringReceiver receiver;
80     pw::rpc::RawUnaryReceiver call = kServiceClient.UnaryEcho(
81         pw::as_bytes(pw::span("hello")), receiver.UnaryOnCompleted());
82     EXPECT_STREQ(receiver.Wait(), "hello");
83   }
84 }
85 
TEST(RawRpcIntegrationTest,BidirectionalStreaming)86 TEST(RawRpcIntegrationTest, BidirectionalStreaming) {
87   for (int i = 0; i < kIterations; ++i) {
88     StringReceiver receiver;
89     pw::rpc::RawClientReaderWriter call =
90         kServiceClient.BidirectionalEcho(receiver.OnNext());
91 
92     ASSERT_EQ(OkStatus(), call.Write(pw::as_bytes(pw::span("Yello"))));
93     EXPECT_STREQ(receiver.Wait(), "Yello");
94 
95     ASSERT_EQ(OkStatus(), call.Write(pw::as_bytes(pw::span("Dello"))));
96     EXPECT_STREQ(receiver.Wait(), "Dello");
97 
98     ASSERT_EQ(OkStatus(), call.Cancel());
99   }
100 }
101 
102 // This test sometimes fails due to a server stream packet being dropped.
103 // TODO: b/290048137 - Enable this test after the flakiness is fixed.
TEST(RawRpcIntegrationTest,DISABLED_OnNextOverwritesItsOwnCall)104 TEST(RawRpcIntegrationTest, DISABLED_OnNextOverwritesItsOwnCall) {
105   for (int i = 0; i < kIterations; ++i) {
106     struct {
107       StringReceiver receiver;
108       pw::rpc::RawClientReaderWriter call;
109     } ctx;
110 
111     // Chain together three calls. The first and third copy the string in normal
112     // order, while the second copies the string in reverse order.
113     ctx.call = kServiceClient.BidirectionalEcho([&ctx](ConstByteSpan data_1) {
114       ctx.call = kServiceClient.BidirectionalEcho([&ctx](ConstByteSpan data_2) {
115         ctx.receiver.ReverseCopyStringPayload(data_2);
116         ctx.call = kServiceClient.BidirectionalEcho(ctx.receiver.OnNext());
117       });
118       ctx.receiver.CopyStringPayload(data_1);
119     });
120 
121     ASSERT_EQ(OkStatus(), ctx.call.Write(pw::as_bytes(pw::span("Window"))));
122     EXPECT_STREQ(ctx.receiver.Wait(), "Window");
123 
124     ASSERT_EQ(OkStatus(), ctx.call.Write(pw::as_bytes(pw::span("Door"))));
125     EXPECT_STREQ(ctx.receiver.Wait(), "rooD");
126 
127     ASSERT_EQ(OkStatus(), ctx.call.Write(pw::as_bytes(pw::span("Roof"))));
128     EXPECT_STREQ(ctx.receiver.Wait(), "Roof");
129 
130     ASSERT_EQ(OkStatus(), ctx.call.Cancel());
131   }
132 }
133 
134 }  // namespace
135 }  // namespace rpc_test
136 
main(int argc,char * argv[])137 int main(int argc, char* argv[]) {
138   if (!pw::rpc::integration_test::InitializeClient(argc, argv).ok()) {
139     return 1;
140   }
141 
142   int test_retval = RUN_ALL_TESTS();
143 
144   pw::rpc::integration_test::TerminateClient();
145 
146   return test_retval;
147 }
148