1 // Copyright 2022 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/pwpb/client_reader_writer.h"
16
17 #include <optional>
18
19 #include "gtest/gtest.h"
20 #include "pw_rpc/pwpb/client_testing.h"
21 #include "pw_rpc_test_protos/test.rpc.pwpb.h"
22
23 PW_MODIFY_DIAGNOSTICS_PUSH();
24 PW_MODIFY_DIAGNOSTIC(ignored, "-Wmissing-field-initializers");
25
26 namespace pw::rpc {
27 namespace {
28
29 using test::pw_rpc::pwpb::TestService;
30
31 namespace TestRequest = ::pw::rpc::test::pwpb::TestRequest;
32 namespace TestResponse = ::pw::rpc::test::pwpb::TestResponse;
33 namespace TestStreamResponse = ::pw::rpc::test::pwpb::TestStreamResponse;
34
FailIfCalled(Status)35 void FailIfCalled(Status) { FAIL(); }
36 template <typename T>
FailIfOnNextCalled(const T &)37 void FailIfOnNextCalled(const T&) {
38 FAIL();
39 }
40 template <typename T>
FailIfOnCompletedCalled(const T &,Status)41 void FailIfOnCompletedCalled(const T&, Status) {
42 FAIL();
43 }
44
TEST(PwpbUnaryReceiver,DefaultConstructed)45 TEST(PwpbUnaryReceiver, DefaultConstructed) {
46 PwpbUnaryReceiver<TestResponse::Message> call;
47
48 ASSERT_FALSE(call.active());
49 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
50
51 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
52
53 call.set_on_completed([](const TestResponse::Message&, Status) {});
54 call.set_on_error([](Status) {});
55 }
56
TEST(PwpbClientWriter,DefaultConstructed)57 TEST(PwpbClientWriter, DefaultConstructed) {
58 PwpbClientWriter<TestRequest::Message, TestStreamResponse::Message> call;
59
60 ASSERT_FALSE(call.active());
61 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
62
63 EXPECT_EQ(Status::FailedPrecondition(), call.Write({}));
64 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
65 EXPECT_EQ(Status::FailedPrecondition(), call.CloseClientStream());
66
67 call.set_on_completed([](const TestStreamResponse::Message&, Status) {});
68 call.set_on_error([](Status) {});
69 }
70
TEST(PwpbClientReader,DefaultConstructed)71 TEST(PwpbClientReader, DefaultConstructed) {
72 PwpbClientReader<TestStreamResponse::Message> call;
73
74 ASSERT_FALSE(call.active());
75 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
76
77 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
78
79 call.set_on_completed([](Status) {});
80 call.set_on_next([](const TestStreamResponse::Message&) {});
81 call.set_on_error([](Status) {});
82 }
83
TEST(PwpbClientReaderWriter,DefaultConstructed)84 TEST(PwpbClientReaderWriter, DefaultConstructed) {
85 PwpbClientReaderWriter<TestRequest::Message, TestStreamResponse::Message>
86 call;
87
88 ASSERT_FALSE(call.active());
89 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
90
91 EXPECT_EQ(Status::FailedPrecondition(), call.Write({}));
92 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
93 EXPECT_EQ(Status::FailedPrecondition(), call.CloseClientStream());
94
95 call.set_on_completed([](Status) {});
96 call.set_on_next([](const TestStreamResponse::Message&) {});
97 call.set_on_error([](Status) {});
98 }
99
TEST(PwpbUnaryReceiver,Closed)100 TEST(PwpbUnaryReceiver, Closed) {
101 PwpbClientTestContext ctx;
102 PwpbUnaryReceiver<TestResponse::Message> call =
103 TestService::TestUnaryRpc(ctx.client(),
104 ctx.channel().id(),
105 {},
106 FailIfOnCompletedCalled<TestResponse::Message>,
107 FailIfCalled);
108 ASSERT_EQ(OkStatus(), call.Cancel());
109
110 ASSERT_FALSE(call.active());
111 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
112
113 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
114
115 call.set_on_completed([](const TestResponse::Message&, Status) {});
116 call.set_on_error([](Status) {});
117 }
118
TEST(PwpbClientWriter,Closed)119 TEST(PwpbClientWriter, Closed) {
120 PwpbClientTestContext ctx;
121 PwpbClientWriter<TestRequest::Message, TestStreamResponse::Message> call =
122 TestService::TestClientStreamRpc(
123 ctx.client(),
124 ctx.channel().id(),
125 FailIfOnCompletedCalled<TestStreamResponse::Message>,
126 FailIfCalled);
127 ASSERT_EQ(OkStatus(), call.Cancel());
128
129 ASSERT_FALSE(call.active());
130 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
131
132 EXPECT_EQ(Status::FailedPrecondition(), call.Write({}));
133 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
134 EXPECT_EQ(Status::FailedPrecondition(), call.CloseClientStream());
135
136 call.set_on_completed([](const TestStreamResponse::Message&, Status) {});
137 call.set_on_error([](Status) {});
138 }
139
TEST(PwpbClientReader,Closed)140 TEST(PwpbClientReader, Closed) {
141 PwpbClientTestContext ctx;
142 PwpbClientReader<TestStreamResponse::Message> call =
143 TestService::TestServerStreamRpc(
144 ctx.client(),
145 ctx.channel().id(),
146 {},
147 FailIfOnNextCalled<TestStreamResponse::Message>,
148 FailIfCalled,
149 FailIfCalled);
150 ASSERT_EQ(OkStatus(), call.Cancel());
151
152 ASSERT_FALSE(call.active());
153 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
154
155 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
156
157 call.set_on_completed([](Status) {});
158 call.set_on_next([](const TestStreamResponse::Message&) {});
159 call.set_on_error([](Status) {});
160 }
161
TEST(PwpbClientReaderWriter,Closed)162 TEST(PwpbClientReaderWriter, Closed) {
163 PwpbClientTestContext ctx;
164 PwpbClientReaderWriter<TestRequest::Message, TestStreamResponse::Message>
165 call = TestService::TestBidirectionalStreamRpc(
166 ctx.client(),
167 ctx.channel().id(),
168 FailIfOnNextCalled<TestStreamResponse::Message>,
169 FailIfCalled,
170 FailIfCalled);
171 ASSERT_EQ(OkStatus(), call.Cancel());
172
173 ASSERT_FALSE(call.active());
174 EXPECT_EQ(call.channel_id(), Channel::kUnassignedChannelId);
175
176 EXPECT_EQ(Status::FailedPrecondition(), call.Write({}));
177 EXPECT_EQ(Status::FailedPrecondition(), call.Cancel());
178 EXPECT_EQ(Status::FailedPrecondition(), call.CloseClientStream());
179
180 call.set_on_completed([](Status) {});
181 call.set_on_next([](const TestStreamResponse::Message&) {});
182 call.set_on_error([](Status) {});
183 }
184
TEST(PwpbUnaryReceiver,CallbacksMoveCorrectly)185 TEST(PwpbUnaryReceiver, CallbacksMoveCorrectly) {
186 PwpbClientTestContext ctx;
187
188 struct {
189 TestResponse::Message payload = {.value = 12345678};
190 std::optional<Status> status;
191 } reply;
192
193 PwpbUnaryReceiver<TestResponse::Message> call_2;
194 {
195 PwpbUnaryReceiver call_1 = TestService::TestUnaryRpc(
196 ctx.client(),
197 ctx.channel().id(),
198 {},
199 [&reply](const TestResponse::Message& response, Status status) {
200 reply.payload = response;
201 reply.status = status;
202 });
203
204 call_2 = std::move(call_1);
205 }
206
207 ctx.server().SendResponse<TestService::TestUnaryRpc>({.value = 9000},
208 Status::NotFound());
209 EXPECT_EQ(reply.payload.value, 9000);
210 EXPECT_EQ(reply.status, Status::NotFound());
211 }
212
TEST(PwpbClientReaderWriter,CallbacksMoveCorrectly)213 TEST(PwpbClientReaderWriter, CallbacksMoveCorrectly) {
214 PwpbClientTestContext ctx;
215
216 TestStreamResponse::Message payload = {.chunk = {}, .number = 13579};
217
218 PwpbClientReaderWriter<TestRequest::Message, TestStreamResponse::Message>
219 call_2;
220 {
221 PwpbClientReaderWriter call_1 = TestService::TestBidirectionalStreamRpc(
222 ctx.client(),
223 ctx.channel().id(),
224 [&payload](const TestStreamResponse::Message& response) {
225 payload = response;
226 });
227
228 call_2 = std::move(call_1);
229 }
230
231 ctx.server().SendServerStream<TestService::TestBidirectionalStreamRpc>(
232 {.chunk = {}, .number = 5050});
233 EXPECT_EQ(payload.number, 5050u);
234 }
235
236 } // namespace
237 } // namespace pw::rpc
238
239 PW_MODIFY_DIAGNOSTICS_POP();
240