xref: /aosp_15_r20/external/pigweed/pw_rpc/fake_channel_output_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 "pw_rpc/internal/fake_channel_output.h"
16 
17 #include <array>
18 #include <cstddef>
19 #include <memory>
20 
21 #include "pw_rpc/channel.h"
22 #include "pw_rpc/internal/lock.h"
23 #include "pw_rpc/internal/packet.h"
24 #include "pw_unit_test/framework.h"
25 
26 namespace pw::rpc::internal::test {
27 namespace {
28 
29 constexpr uint32_t kChannelId = 1;
30 constexpr uint32_t kServiceId = 1;
31 constexpr uint32_t kMethodId = 1;
32 constexpr uint32_t kCallId = 0;
33 constexpr std::array<std::byte, 3> kPayload = {
34     std::byte(1), std::byte(2), std::byte(3)};
35 
36 class TestFakeChannelOutput final : public FakeChannelOutputBuffer<9, 128> {
37  public:
38   TestFakeChannelOutput() = default;
39 
last_response(MethodType type)40   const ConstByteSpan& last_response(MethodType type) {
41     return payloads(type, kChannelId, kServiceId, kMethodId).back();
42   }
43 
total_payloads(MethodType type)44   size_t total_payloads(MethodType type) {
45     return payloads(type, kChannelId, kServiceId, kMethodId).size();
46   }
47 };
48 
TEST(FakeChannelOutput,SendAndClear)49 TEST(FakeChannelOutput, SendAndClear) {
50   constexpr MethodType type = MethodType::kServerStreaming;
51   TestFakeChannelOutput output;
52   Channel public_channel = Channel::Create<kChannelId>(&output);
53   internal::ChannelBase& channel = public_channel;
54 
55   const internal::Packet server_stream_packet(pwpb::PacketType::SERVER_STREAM,
56                                               kChannelId,
57                                               kServiceId,
58                                               kMethodId,
59                                               kCallId,
60                                               kPayload);
61   RpcLockGuard lock;
62   ASSERT_EQ(channel.Send(server_stream_packet), OkStatus());
63   ASSERT_EQ(output.last_response(type).size(), kPayload.size());
64   EXPECT_EQ(
65       std::memcmp(
66           output.last_response(type).data(), kPayload.data(), kPayload.size()),
67       0);
68   EXPECT_EQ(output.total_payloads(type), 1u);
69   EXPECT_EQ(output.total_packets(), 1u);
70   EXPECT_FALSE(output.done());
71 
72   output.clear();
73   EXPECT_EQ(output.total_payloads(type), 0u);
74   EXPECT_EQ(output.total_packets(), 0u);
75   EXPECT_FALSE(output.done());
76 }
77 
TEST(FakeChannelOutput,SendAndFakeFutureResults)78 TEST(FakeChannelOutput, SendAndFakeFutureResults) {
79   constexpr MethodType type = MethodType::kUnary;
80   TestFakeChannelOutput output;
81   Channel public_channel = Channel::Create<kChannelId>(&output);
82   internal::ChannelBase& channel = public_channel;
83 
84   const internal::Packet response_packet(pwpb::PacketType::RESPONSE,
85                                          kChannelId,
86                                          kServiceId,
87                                          kMethodId,
88                                          kCallId,
89                                          kPayload);
90   RpcLockGuard lock;
91   EXPECT_EQ(channel.Send(response_packet), OkStatus());
92   EXPECT_EQ(output.total_payloads(type), 1u);
93   EXPECT_EQ(output.total_packets(), 1u);
94   EXPECT_TRUE(output.done());
95 
96   // Multiple calls will return the same error status.
97   output.set_send_status(Status::Unknown());
98   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
99   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
100   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
101   EXPECT_EQ(output.total_payloads(type), 1u);
102   EXPECT_EQ(output.total_packets(), 1u);
103 
104   // Turn off error status behavior.
105   output.set_send_status(OkStatus());
106   EXPECT_EQ(channel.Send(response_packet), OkStatus());
107   EXPECT_EQ(output.total_payloads(type), 2u);
108   EXPECT_EQ(output.total_packets(), 2u);
109 
110   const internal::Packet server_stream_packet(pwpb::PacketType::SERVER_STREAM,
111                                               kChannelId,
112                                               kServiceId,
113                                               kMethodId,
114                                               kCallId,
115                                               kPayload);
116   EXPECT_EQ(channel.Send(server_stream_packet), OkStatus());
117   ASSERT_EQ(output.last_response(type).size(), kPayload.size());
118   EXPECT_EQ(
119       std::memcmp(
120           output.last_response(type).data(), kPayload.data(), kPayload.size()),
121       0);
122   EXPECT_EQ(output.total_payloads(type), 2u);
123   EXPECT_EQ(output.total_packets(), 3u);
124   EXPECT_TRUE(output.done());
125 }
126 
TEST(FakeChannelOutput,SendAndFakeSingleResult)127 TEST(FakeChannelOutput, SendAndFakeSingleResult) {
128   constexpr MethodType type = MethodType::kUnary;
129   TestFakeChannelOutput output;
130   Channel public_channel = Channel::Create<kChannelId>(&output);
131   internal::ChannelBase& channel = public_channel;
132 
133   const internal::Packet response_packet(pwpb::PacketType::RESPONSE,
134                                          kChannelId,
135                                          kServiceId,
136                                          kMethodId,
137                                          kCallId,
138                                          kPayload);
139   // Multiple calls will return the same error status.
140   const int packet_count_fail = 4;
141   output.set_send_status(Status::Unknown(), packet_count_fail);
142   RpcLockGuard lock;
143 
144   for (int i = 0; i < packet_count_fail; ++i) {
145     EXPECT_EQ(channel.Send(response_packet), OkStatus());
146   }
147   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
148   for (int i = 0; i < packet_count_fail; ++i) {
149     EXPECT_EQ(channel.Send(response_packet), OkStatus());
150   }
151 
152   const size_t total_response_packets =
153       static_cast<size_t>(2 * packet_count_fail);
154   EXPECT_EQ(output.total_payloads(type), total_response_packets);
155   EXPECT_EQ(output.total_packets(), total_response_packets);
156 
157   // Turn off error status behavior.
158   output.set_send_status(OkStatus());
159   EXPECT_EQ(channel.Send(response_packet), OkStatus());
160   EXPECT_EQ(output.total_payloads(type), total_response_packets + 1);
161   EXPECT_EQ(output.total_packets(), total_response_packets + 1);
162 }
163 
TEST(FakeChannelOutput,SendResponseUpdated)164 TEST(FakeChannelOutput, SendResponseUpdated) {
165   TestFakeChannelOutput output;
166   Channel public_channel = Channel::Create<kChannelId>(&output);
167   internal::ChannelBase& channel = public_channel;
168 
169   const internal::Packet response_packet(pwpb::PacketType::RESPONSE,
170                                          kChannelId,
171                                          kServiceId,
172                                          kMethodId,
173                                          kCallId,
174                                          kPayload);
175   RpcLockGuard lock;
176   ASSERT_EQ(channel.Send(response_packet), OkStatus());
177   ASSERT_EQ(output.last_response(MethodType::kUnary).size(), kPayload.size());
178   EXPECT_EQ(std::memcmp(output.last_response(MethodType::kUnary).data(),
179                         kPayload.data(),
180                         kPayload.size()),
181             0);
182   EXPECT_EQ(output.total_payloads(MethodType::kUnary), 1u);
183   EXPECT_EQ(output.total_packets(), 1u);
184   EXPECT_TRUE(output.done());
185 
186   output.clear();
187   const internal::Packet packet_empty_payload(pwpb::PacketType::RESPONSE,
188                                               kChannelId,
189                                               kServiceId,
190                                               kMethodId,
191                                               kCallId,
192                                               {});
193   EXPECT_EQ(channel.Send(packet_empty_payload), OkStatus());
194   EXPECT_EQ(output.last_response(MethodType::kUnary).size(), 0u);
195   EXPECT_EQ(output.total_payloads(MethodType::kUnary), 1u);
196   EXPECT_EQ(output.total_packets(), 1u);
197   EXPECT_TRUE(output.done());
198 
199   const internal::Packet server_stream_packet(pwpb::PacketType::SERVER_STREAM,
200                                               kChannelId,
201                                               kServiceId,
202                                               kMethodId,
203                                               kCallId,
204                                               kPayload);
205   ASSERT_EQ(channel.Send(server_stream_packet), OkStatus());
206   ASSERT_EQ(output.total_payloads(MethodType::kServerStreaming), 1u);
207   ASSERT_EQ(output.last_response(MethodType::kServerStreaming).size(),
208             kPayload.size());
209   EXPECT_EQ(
210       std::memcmp(output.last_response(MethodType::kServerStreaming).data(),
211                   kPayload.data(),
212                   kPayload.size()),
213       0);
214   EXPECT_EQ(output.total_payloads(MethodType::kServerStreaming), 1u);
215   EXPECT_EQ(output.total_packets(), 2u);
216   EXPECT_TRUE(output.done());
217 }
218 
219 }  // namespace
220 }  // namespace pw::rpc::internal::test
221