• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gtest/gtest.h"
22 #include "pw_rpc/internal/channel.h"
23 #include "pw_rpc/internal/lock.h"
24 #include "pw_rpc/internal/packet.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 channel(kChannelId, &output);
53   const internal::Packet server_stream_packet(pwpb::PacketType::SERVER_STREAM,
54                                               kChannelId,
55                                               kServiceId,
56                                               kMethodId,
57                                               kCallId,
58                                               kPayload);
59   RpcLockGuard lock;
60   ASSERT_EQ(channel.Send(server_stream_packet), OkStatus());
61   ASSERT_EQ(output.last_response(type).size(), kPayload.size());
62   EXPECT_EQ(
63       std::memcmp(
64           output.last_response(type).data(), kPayload.data(), kPayload.size()),
65       0);
66   EXPECT_EQ(output.total_payloads(type), 1u);
67   EXPECT_EQ(output.total_packets(), 1u);
68   EXPECT_FALSE(output.done());
69 
70   output.clear();
71   EXPECT_EQ(output.total_payloads(type), 0u);
72   EXPECT_EQ(output.total_packets(), 0u);
73   EXPECT_FALSE(output.done());
74 }
75 
TEST(FakeChannelOutput,SendAndFakeFutureResults)76 TEST(FakeChannelOutput, SendAndFakeFutureResults) {
77   constexpr MethodType type = MethodType::kUnary;
78   TestFakeChannelOutput output;
79   Channel channel(kChannelId, &output);
80   const internal::Packet response_packet(pwpb::PacketType::RESPONSE,
81                                          kChannelId,
82                                          kServiceId,
83                                          kMethodId,
84                                          kCallId,
85                                          kPayload);
86   RpcLockGuard lock;
87   EXPECT_EQ(channel.Send(response_packet), OkStatus());
88   EXPECT_EQ(output.total_payloads(type), 1u);
89   EXPECT_EQ(output.total_packets(), 1u);
90   EXPECT_TRUE(output.done());
91 
92   // Multiple calls will return the same error status.
93   output.set_send_status(Status::Unknown());
94   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
95   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
96   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
97   EXPECT_EQ(output.total_payloads(type), 1u);
98   EXPECT_EQ(output.total_packets(), 1u);
99 
100   // Turn off error status behavior.
101   output.set_send_status(OkStatus());
102   EXPECT_EQ(channel.Send(response_packet), OkStatus());
103   EXPECT_EQ(output.total_payloads(type), 2u);
104   EXPECT_EQ(output.total_packets(), 2u);
105 
106   const internal::Packet server_stream_packet(pwpb::PacketType::SERVER_STREAM,
107                                               kChannelId,
108                                               kServiceId,
109                                               kMethodId,
110                                               kCallId,
111                                               kPayload);
112   EXPECT_EQ(channel.Send(server_stream_packet), OkStatus());
113   ASSERT_EQ(output.last_response(type).size(), kPayload.size());
114   EXPECT_EQ(
115       std::memcmp(
116           output.last_response(type).data(), kPayload.data(), kPayload.size()),
117       0);
118   EXPECT_EQ(output.total_payloads(type), 2u);
119   EXPECT_EQ(output.total_packets(), 3u);
120   EXPECT_TRUE(output.done());
121 }
122 
TEST(FakeChannelOutput,SendAndFakeSingleResult)123 TEST(FakeChannelOutput, SendAndFakeSingleResult) {
124   constexpr MethodType type = MethodType::kUnary;
125   TestFakeChannelOutput output;
126   Channel channel(kChannelId, &output);
127   const internal::Packet response_packet(pwpb::PacketType::RESPONSE,
128                                          kChannelId,
129                                          kServiceId,
130                                          kMethodId,
131                                          kCallId,
132                                          kPayload);
133   // Multiple calls will return the same error status.
134   const int packet_count_fail = 4;
135   output.set_send_status(Status::Unknown(), packet_count_fail);
136   RpcLockGuard lock;
137 
138   for (int i = 0; i < packet_count_fail; ++i) {
139     EXPECT_EQ(channel.Send(response_packet), OkStatus());
140   }
141   EXPECT_EQ(channel.Send(response_packet), Status::Unknown());
142   for (int i = 0; i < packet_count_fail; ++i) {
143     EXPECT_EQ(channel.Send(response_packet), OkStatus());
144   }
145 
146   const size_t total_response_packets =
147       static_cast<size_t>(2 * packet_count_fail);
148   EXPECT_EQ(output.total_payloads(type), total_response_packets);
149   EXPECT_EQ(output.total_packets(), total_response_packets);
150 
151   // Turn off error status behavior.
152   output.set_send_status(OkStatus());
153   EXPECT_EQ(channel.Send(response_packet), OkStatus());
154   EXPECT_EQ(output.total_payloads(type), total_response_packets + 1);
155   EXPECT_EQ(output.total_packets(), total_response_packets + 1);
156 }
157 
TEST(FakeChannelOutput,SendResponseUpdated)158 TEST(FakeChannelOutput, SendResponseUpdated) {
159   TestFakeChannelOutput output;
160   Channel channel(kChannelId, &output);
161   const internal::Packet response_packet(pwpb::PacketType::RESPONSE,
162                                          kChannelId,
163                                          kServiceId,
164                                          kMethodId,
165                                          kCallId,
166                                          kPayload);
167   RpcLockGuard lock;
168   ASSERT_EQ(channel.Send(response_packet), OkStatus());
169   ASSERT_EQ(output.last_response(MethodType::kUnary).size(), kPayload.size());
170   EXPECT_EQ(std::memcmp(output.last_response(MethodType::kUnary).data(),
171                         kPayload.data(),
172                         kPayload.size()),
173             0);
174   EXPECT_EQ(output.total_payloads(MethodType::kUnary), 1u);
175   EXPECT_EQ(output.total_packets(), 1u);
176   EXPECT_TRUE(output.done());
177 
178   output.clear();
179   const internal::Packet packet_empty_payload(pwpb::PacketType::RESPONSE,
180                                               kChannelId,
181                                               kServiceId,
182                                               kMethodId,
183                                               kCallId,
184                                               {});
185   EXPECT_EQ(channel.Send(packet_empty_payload), OkStatus());
186   EXPECT_EQ(output.last_response(MethodType::kUnary).size(), 0u);
187   EXPECT_EQ(output.total_payloads(MethodType::kUnary), 1u);
188   EXPECT_EQ(output.total_packets(), 1u);
189   EXPECT_TRUE(output.done());
190 
191   const internal::Packet server_stream_packet(pwpb::PacketType::SERVER_STREAM,
192                                               kChannelId,
193                                               kServiceId,
194                                               kMethodId,
195                                               kCallId,
196                                               kPayload);
197   ASSERT_EQ(channel.Send(server_stream_packet), OkStatus());
198   ASSERT_EQ(output.total_payloads(MethodType::kServerStreaming), 1u);
199   ASSERT_EQ(output.last_response(MethodType::kServerStreaming).size(),
200             kPayload.size());
201   EXPECT_EQ(
202       std::memcmp(output.last_response(MethodType::kServerStreaming).data(),
203                   kPayload.data(),
204                   kPayload.size()),
205       0);
206   EXPECT_EQ(output.total_payloads(MethodType::kServerStreaming), 1u);
207   EXPECT_EQ(output.total_packets(), 2u);
208   EXPECT_TRUE(output.done());
209 }
210 
211 }  // namespace
212 }  // namespace pw::rpc::internal::test
213