xref: /aosp_15_r20/external/pigweed/pw_channel/channel_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2024 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 #include "pw_channel/channel.h"
15*61c4878aSAndroid Build Coastguard Worker 
16*61c4878aSAndroid Build Coastguard Worker #include <optional>
17*61c4878aSAndroid Build Coastguard Worker 
18*61c4878aSAndroid Build Coastguard Worker #include "pw_allocator/testing.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_compilation_testing/negative_compilation.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_multibuf/allocator.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_multibuf/simple_allocator.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_preprocessor/compiler.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
25*61c4878aSAndroid Build Coastguard Worker 
26*61c4878aSAndroid Build Coastguard Worker namespace {
27*61c4878aSAndroid Build Coastguard Worker 
28*61c4878aSAndroid Build Coastguard Worker using ::pw::allocator::test::AllocatorForTest;
29*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Context;
30*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Dispatcher;
31*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Pending;
32*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Poll;
33*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Ready;
34*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Task;
35*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Waker;
36*61c4878aSAndroid Build Coastguard Worker using ::pw::channel::ByteChannel;
37*61c4878aSAndroid Build Coastguard Worker using ::pw::channel::DatagramWriter;
38*61c4878aSAndroid Build Coastguard Worker using ::pw::channel::kReadable;
39*61c4878aSAndroid Build Coastguard Worker using ::pw::channel::kReliable;
40*61c4878aSAndroid Build Coastguard Worker using ::pw::channel::kSeekable;
41*61c4878aSAndroid Build Coastguard Worker using ::pw::channel::kWritable;
42*61c4878aSAndroid Build Coastguard Worker using ::pw::multibuf::MultiBuf;
43*61c4878aSAndroid Build Coastguard Worker using ::pw::multibuf::MultiBufAllocationFuture;
44*61c4878aSAndroid Build Coastguard Worker using ::pw::multibuf::MultiBufAllocator;
45*61c4878aSAndroid Build Coastguard Worker using ::pw::multibuf::SimpleAllocator;
46*61c4878aSAndroid Build Coastguard Worker 
47*61c4878aSAndroid Build Coastguard Worker static_assert(sizeof(::pw::channel::AnyChannel) == 2 * sizeof(void*));
48*61c4878aSAndroid Build Coastguard Worker 
49*61c4878aSAndroid Build Coastguard Worker static_assert((kReliable < kReadable) && (kReadable < kWritable) &&
50*61c4878aSAndroid Build Coastguard Worker               (kWritable < kSeekable));
51*61c4878aSAndroid Build Coastguard Worker 
52*61c4878aSAndroid Build Coastguard Worker class ReliableByteReaderWriterStub
53*61c4878aSAndroid Build Coastguard Worker     : public pw::channel::ByteChannelImpl<kReliable, kReadable, kWritable> {
54*61c4878aSAndroid Build Coastguard Worker  private:
55*61c4878aSAndroid Build Coastguard Worker   // Read functions
56*61c4878aSAndroid Build Coastguard Worker 
DoPendRead(Context &)57*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Result<pw::multibuf::MultiBuf>> DoPendRead(Context&) override {
58*61c4878aSAndroid Build Coastguard Worker     return Pending();
59*61c4878aSAndroid Build Coastguard Worker   }
60*61c4878aSAndroid Build Coastguard Worker 
61*61c4878aSAndroid Build Coastguard Worker   // Write functions
62*61c4878aSAndroid Build Coastguard Worker 
63*61c4878aSAndroid Build Coastguard Worker   // Disable maybe-uninitialized: this check fails erroniously on Windows GCC.
64*61c4878aSAndroid Build Coastguard Worker   PW_MODIFY_DIAGNOSTICS_PUSH();
65*61c4878aSAndroid Build Coastguard Worker   PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wmaybe-uninitialized");
DoPendReadyToWrite(Context &)66*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendReadyToWrite(Context&) override { return Pending(); }
67*61c4878aSAndroid Build Coastguard Worker   PW_MODIFY_DIAGNOSTICS_POP();
68*61c4878aSAndroid Build Coastguard Worker 
DoPendAllocateWriteBuffer(Context &,size_t)69*61c4878aSAndroid Build Coastguard Worker   Poll<std::optional<MultiBuf>> DoPendAllocateWriteBuffer(Context&,
70*61c4878aSAndroid Build Coastguard Worker                                                           size_t) override {
71*61c4878aSAndroid Build Coastguard Worker     return std::nullopt;
72*61c4878aSAndroid Build Coastguard Worker   }
73*61c4878aSAndroid Build Coastguard Worker 
DoStageWrite(pw::multibuf::MultiBuf &&)74*61c4878aSAndroid Build Coastguard Worker   pw::Status DoStageWrite(pw::multibuf::MultiBuf&&) override {
75*61c4878aSAndroid Build Coastguard Worker     return pw::Status::Unimplemented();
76*61c4878aSAndroid Build Coastguard Worker   }
77*61c4878aSAndroid Build Coastguard Worker 
DoPendWrite(Context &)78*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendWrite(Context&) override {
79*61c4878aSAndroid Build Coastguard Worker     return Ready(pw::Status::Unimplemented());
80*61c4878aSAndroid Build Coastguard Worker   }
81*61c4878aSAndroid Build Coastguard Worker 
82*61c4878aSAndroid Build Coastguard Worker   // Common functions
DoPendClose(Context &)83*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendClose(Context&) override { return pw::OkStatus(); }
84*61c4878aSAndroid Build Coastguard Worker };
85*61c4878aSAndroid Build Coastguard Worker 
86*61c4878aSAndroid Build Coastguard Worker class ReadOnlyStub : public pw::channel::Implement<pw::channel::ByteReader> {
87*61c4878aSAndroid Build Coastguard Worker  public:
88*61c4878aSAndroid Build Coastguard Worker   constexpr ReadOnlyStub() = default;
89*61c4878aSAndroid Build Coastguard Worker 
90*61c4878aSAndroid Build Coastguard Worker  private:
91*61c4878aSAndroid Build Coastguard Worker   // Read functions
DoPendRead(Context &)92*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Result<pw::multibuf::MultiBuf>> DoPendRead(Context&) override {
93*61c4878aSAndroid Build Coastguard Worker     return Pending();
94*61c4878aSAndroid Build Coastguard Worker   }
95*61c4878aSAndroid Build Coastguard Worker 
DoPendClose(Context &)96*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendClose(Context&) override { return pw::OkStatus(); }
97*61c4878aSAndroid Build Coastguard Worker };
98*61c4878aSAndroid Build Coastguard Worker 
99*61c4878aSAndroid Build Coastguard Worker class WriteOnlyStub : public pw::channel::Implement<pw::channel::ByteWriter> {
100*61c4878aSAndroid Build Coastguard Worker  private:
101*61c4878aSAndroid Build Coastguard Worker   // Write functions
102*61c4878aSAndroid Build Coastguard Worker 
DoPendReadyToWrite(Context &)103*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendReadyToWrite(Context&) override { return Pending(); }
104*61c4878aSAndroid Build Coastguard Worker 
DoPendAllocateWriteBuffer(Context &,size_t)105*61c4878aSAndroid Build Coastguard Worker   Poll<std::optional<MultiBuf>> DoPendAllocateWriteBuffer(Context&,
106*61c4878aSAndroid Build Coastguard Worker                                                           size_t) override {
107*61c4878aSAndroid Build Coastguard Worker     return std::nullopt;
108*61c4878aSAndroid Build Coastguard Worker   }
109*61c4878aSAndroid Build Coastguard Worker 
DoStageWrite(pw::multibuf::MultiBuf &&)110*61c4878aSAndroid Build Coastguard Worker   pw::Status DoStageWrite(pw::multibuf::MultiBuf&&) override {
111*61c4878aSAndroid Build Coastguard Worker     return pw::Status::Unimplemented();
112*61c4878aSAndroid Build Coastguard Worker   }
113*61c4878aSAndroid Build Coastguard Worker 
DoPendWrite(Context &)114*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendWrite(Context&) override {
115*61c4878aSAndroid Build Coastguard Worker     return Ready(pw::Status::Unimplemented());
116*61c4878aSAndroid Build Coastguard Worker   }
117*61c4878aSAndroid Build Coastguard Worker 
118*61c4878aSAndroid Build Coastguard Worker   // Common functions
DoPendClose(Context &)119*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendClose(Context&) override { return pw::OkStatus(); }
120*61c4878aSAndroid Build Coastguard Worker };
121*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,MethodsShortCircuitAfterCloseReturnsReady)122*61c4878aSAndroid Build Coastguard Worker TEST(Channel, MethodsShortCircuitAfterCloseReturnsReady) {
123*61c4878aSAndroid Build Coastguard Worker   Dispatcher dispatcher;
124*61c4878aSAndroid Build Coastguard Worker 
125*61c4878aSAndroid Build Coastguard Worker   class : public Task {
126*61c4878aSAndroid Build Coastguard Worker    public:
127*61c4878aSAndroid Build Coastguard Worker     ReliableByteReaderWriterStub channel;
128*61c4878aSAndroid Build Coastguard Worker 
129*61c4878aSAndroid Build Coastguard Worker    private:
130*61c4878aSAndroid Build Coastguard Worker     Poll<> DoPend(Context& cx) override {
131*61c4878aSAndroid Build Coastguard Worker       EXPECT_TRUE(channel.is_read_open());
132*61c4878aSAndroid Build Coastguard Worker       EXPECT_TRUE(channel.is_write_open());
133*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(Ready(pw::OkStatus()), channel.PendClose(cx));
134*61c4878aSAndroid Build Coastguard Worker       EXPECT_FALSE(channel.is_read_open());
135*61c4878aSAndroid Build Coastguard Worker       EXPECT_FALSE(channel.is_write_open());
136*61c4878aSAndroid Build Coastguard Worker 
137*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(pw::Status::FailedPrecondition(),
138*61c4878aSAndroid Build Coastguard Worker                 channel.PendRead(cx)->status());
139*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(Ready(pw::Status::FailedPrecondition()),
140*61c4878aSAndroid Build Coastguard Worker                 channel.PendReadyToWrite(cx));
141*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(Ready(pw::Status::FailedPrecondition()), channel.PendWrite(cx));
142*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(Ready(pw::Status::FailedPrecondition()), channel.PendClose(cx));
143*61c4878aSAndroid Build Coastguard Worker 
144*61c4878aSAndroid Build Coastguard Worker       return Ready();
145*61c4878aSAndroid Build Coastguard Worker     }
146*61c4878aSAndroid Build Coastguard Worker   } test_task;
147*61c4878aSAndroid Build Coastguard Worker   dispatcher.Post(test_task);
148*61c4878aSAndroid Build Coastguard Worker 
149*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(dispatcher.RunUntilStalled().IsReady());
150*61c4878aSAndroid Build Coastguard Worker }
151*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,ReadOnlyChannelOnlyOpenForReads)152*61c4878aSAndroid Build Coastguard Worker TEST(Channel, ReadOnlyChannelOnlyOpenForReads) {
153*61c4878aSAndroid Build Coastguard Worker   ReadOnlyStub read_only;
154*61c4878aSAndroid Build Coastguard Worker 
155*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(read_only.readable());
156*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(read_only.is_read_open());
157*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(read_only.is_write_open());
158*61c4878aSAndroid Build Coastguard Worker }
159*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,WriteOnlyChannelOnlyOpenForWrites)160*61c4878aSAndroid Build Coastguard Worker TEST(Channel, WriteOnlyChannelOnlyOpenForWrites) {
161*61c4878aSAndroid Build Coastguard Worker   WriteOnlyStub write_only;
162*61c4878aSAndroid Build Coastguard Worker 
163*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(write_only.readable());
164*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(write_only.is_read_open());
165*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(write_only.is_write_open());
166*61c4878aSAndroid Build Coastguard Worker }
167*61c4878aSAndroid Build Coastguard Worker 
168*61c4878aSAndroid Build Coastguard Worker #if PW_NC_TEST(ChannelInvalidOrdering)
169*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("Properties must be specified in the following order");
Illegal(pw::channel::ByteChannel<kReadable,pw::channel::kReliable> & foo)170*61c4878aSAndroid Build Coastguard Worker bool Illegal(pw::channel::ByteChannel<kReadable, pw::channel::kReliable>& foo) {
171*61c4878aSAndroid Build Coastguard Worker   return foo.is_read_open();
172*61c4878aSAndroid Build Coastguard Worker }
173*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(ChannelImplInvalidOrdering)
174*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("Properties must be specified in the following order");
175*61c4878aSAndroid Build Coastguard Worker class BadChannel
176*61c4878aSAndroid Build Coastguard Worker     : public pw::channel::ByteChannelImpl<kReadable, pw::channel::kReliable> {};
177*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(ChannelNoProperties)
178*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("At least one of kReadable or kWritable must be provided");
Illegal(pw::channel::ByteChannel<> & foo)179*61c4878aSAndroid Build Coastguard Worker bool Illegal(pw::channel::ByteChannel<>& foo) { return foo.is_read_open(); }
180*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(ChannelImplNoProperties)
181*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("At least one of kReadable or kWritable must be provided");
182*61c4878aSAndroid Build Coastguard Worker class NoChannel : public pw::channel::ByteChannelImpl<> {};
183*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(ChannelNoReadOrWrite)
184*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("At least one of kReadable or kWritable must be provided");
Illegal(pw::channel::ByteChannel<pw::channel::kReliable> & foo)185*61c4878aSAndroid Build Coastguard Worker bool Illegal(pw::channel::ByteChannel<pw::channel::kReliable>& foo) {
186*61c4878aSAndroid Build Coastguard Worker   return foo.is_read_open();
187*61c4878aSAndroid Build Coastguard Worker }
188*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(ChannelImplNoReadOrWrite)
189*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("At least one of kReadable or kWritable must be provided");
190*61c4878aSAndroid Build Coastguard Worker class BadChannel : public pw::channel::ByteChannelImpl<pw::channel::kReliable> {
191*61c4878aSAndroid Build Coastguard Worker };
192*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(TooMany)
193*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("Too many properties given");
Illegal(pw::channel::ByteChannel<kReliable,kReliable,kReliable,kReadable,kWritable> & foo)194*61c4878aSAndroid Build Coastguard Worker bool Illegal(
195*61c4878aSAndroid Build Coastguard Worker     pw::channel::
196*61c4878aSAndroid Build Coastguard Worker         ByteChannel<kReliable, kReliable, kReliable, kReadable, kWritable>&
197*61c4878aSAndroid Build Coastguard Worker             foo) {
198*61c4878aSAndroid Build Coastguard Worker   return foo.is_read_open();
199*61c4878aSAndroid Build Coastguard Worker }
200*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(Duplicates)
201*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("duplicates");
Illegal(pw::channel::ByteChannel<kReadable,kReadable> & foo)202*61c4878aSAndroid Build Coastguard Worker bool Illegal(pw::channel::ByteChannel<kReadable, kReadable>& foo) {
203*61c4878aSAndroid Build Coastguard Worker   return foo.is_read_open();
204*61c4878aSAndroid Build Coastguard Worker }
205*61c4878aSAndroid Build Coastguard Worker #endif  // PW_NC_TEST
206*61c4878aSAndroid Build Coastguard Worker 
207*61c4878aSAndroid Build Coastguard Worker class TestByteReader
208*61c4878aSAndroid Build Coastguard Worker     : public pw::channel::ByteChannelImpl<kReliable, kReadable> {
209*61c4878aSAndroid Build Coastguard Worker  public:
TestByteReader()210*61c4878aSAndroid Build Coastguard Worker   TestByteReader() {}
211*61c4878aSAndroid Build Coastguard Worker 
PushData(MultiBuf data)212*61c4878aSAndroid Build Coastguard Worker   void PushData(MultiBuf data) {
213*61c4878aSAndroid Build Coastguard Worker     bool was_empty = data_.empty();
214*61c4878aSAndroid Build Coastguard Worker     data_.PushSuffix(std::move(data));
215*61c4878aSAndroid Build Coastguard Worker     if (was_empty) {
216*61c4878aSAndroid Build Coastguard Worker       std::move(read_waker_).Wake();
217*61c4878aSAndroid Build Coastguard Worker     }
218*61c4878aSAndroid Build Coastguard Worker   }
219*61c4878aSAndroid Build Coastguard Worker 
220*61c4878aSAndroid Build Coastguard Worker  private:
DoPendRead(Context & cx)221*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Result<MultiBuf>> DoPendRead(Context& cx) override {
222*61c4878aSAndroid Build Coastguard Worker     if (data_.empty()) {
223*61c4878aSAndroid Build Coastguard Worker       PW_ASYNC_STORE_WAKER(
224*61c4878aSAndroid Build Coastguard Worker           cx, read_waker_, "TestByteReader is waiting for a call to PushData");
225*61c4878aSAndroid Build Coastguard Worker       return Pending();
226*61c4878aSAndroid Build Coastguard Worker     }
227*61c4878aSAndroid Build Coastguard Worker     return std::move(data_);
228*61c4878aSAndroid Build Coastguard Worker   }
229*61c4878aSAndroid Build Coastguard Worker 
DoPendClose(Context &)230*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendClose(Context&) override {
231*61c4878aSAndroid Build Coastguard Worker     return Ready(pw::OkStatus());
232*61c4878aSAndroid Build Coastguard Worker   }
233*61c4878aSAndroid Build Coastguard Worker 
234*61c4878aSAndroid Build Coastguard Worker   Waker read_waker_;
235*61c4878aSAndroid Build Coastguard Worker   MultiBuf data_;
236*61c4878aSAndroid Build Coastguard Worker };
237*61c4878aSAndroid Build Coastguard Worker 
238*61c4878aSAndroid Build Coastguard Worker class TestDatagramWriter : public pw::channel::Implement<DatagramWriter> {
239*61c4878aSAndroid Build Coastguard Worker  public:
TestDatagramWriter(MultiBufAllocator & alloc)240*61c4878aSAndroid Build Coastguard Worker   TestDatagramWriter(MultiBufAllocator& alloc) : alloc_fut_(alloc) {}
241*61c4878aSAndroid Build Coastguard Worker 
last_datagram() const242*61c4878aSAndroid Build Coastguard Worker   const pw::multibuf::MultiBuf& last_datagram() const { return last_dgram_; }
243*61c4878aSAndroid Build Coastguard Worker 
MakeReadyToWrite()244*61c4878aSAndroid Build Coastguard Worker   void MakeReadyToWrite() {
245*61c4878aSAndroid Build Coastguard Worker     PW_CHECK_INT_EQ(
246*61c4878aSAndroid Build Coastguard Worker         state_,
247*61c4878aSAndroid Build Coastguard Worker         kUnavailable,
248*61c4878aSAndroid Build Coastguard Worker         "Can't make writable when write is pending or already writable");
249*61c4878aSAndroid Build Coastguard Worker 
250*61c4878aSAndroid Build Coastguard Worker     state_ = kReadyToWrite;
251*61c4878aSAndroid Build Coastguard Worker     std::move(waker_).Wake();
252*61c4878aSAndroid Build Coastguard Worker   }
253*61c4878aSAndroid Build Coastguard Worker 
MakeReadyToFlush()254*61c4878aSAndroid Build Coastguard Worker   void MakeReadyToFlush() {
255*61c4878aSAndroid Build Coastguard Worker     PW_CHECK_INT_EQ(state_,
256*61c4878aSAndroid Build Coastguard Worker                     kWritePending,
257*61c4878aSAndroid Build Coastguard Worker                     "Can't make flushable unless a write is pending");
258*61c4878aSAndroid Build Coastguard Worker 
259*61c4878aSAndroid Build Coastguard Worker     state_ = kReadyToFlush;
260*61c4878aSAndroid Build Coastguard Worker     std::move(waker_).Wake();
261*61c4878aSAndroid Build Coastguard Worker   }
262*61c4878aSAndroid Build Coastguard Worker 
263*61c4878aSAndroid Build Coastguard Worker  private:
DoPendReadyToWrite(Context & cx)264*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendReadyToWrite(Context& cx) override {
265*61c4878aSAndroid Build Coastguard Worker     if (state_ == kReadyToWrite) {
266*61c4878aSAndroid Build Coastguard Worker       return Ready(pw::OkStatus());
267*61c4878aSAndroid Build Coastguard Worker     }
268*61c4878aSAndroid Build Coastguard Worker 
269*61c4878aSAndroid Build Coastguard Worker     PW_ASYNC_STORE_WAKER(
270*61c4878aSAndroid Build Coastguard Worker         cx,
271*61c4878aSAndroid Build Coastguard Worker         waker_,
272*61c4878aSAndroid Build Coastguard Worker         "TestDatagramWriter waiting for a call to MakeReadyToWrite");
273*61c4878aSAndroid Build Coastguard Worker     return Pending();
274*61c4878aSAndroid Build Coastguard Worker   }
275*61c4878aSAndroid Build Coastguard Worker 
DoStageWrite(MultiBuf && buffer)276*61c4878aSAndroid Build Coastguard Worker   pw::Status DoStageWrite(MultiBuf&& buffer) override {
277*61c4878aSAndroid Build Coastguard Worker     if (state_ != kReadyToWrite) {
278*61c4878aSAndroid Build Coastguard Worker       return pw::Status::Unavailable();
279*61c4878aSAndroid Build Coastguard Worker     }
280*61c4878aSAndroid Build Coastguard Worker 
281*61c4878aSAndroid Build Coastguard Worker     state_ = kWritePending;
282*61c4878aSAndroid Build Coastguard Worker     last_dgram_ = std::move(buffer);
283*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
284*61c4878aSAndroid Build Coastguard Worker   }
285*61c4878aSAndroid Build Coastguard Worker 
DoPendAllocateWriteBuffer(Context & cx,size_t min_bytes)286*61c4878aSAndroid Build Coastguard Worker   Poll<std::optional<MultiBuf>> DoPendAllocateWriteBuffer(
287*61c4878aSAndroid Build Coastguard Worker       Context& cx, size_t min_bytes) override {
288*61c4878aSAndroid Build Coastguard Worker     alloc_fut_.SetDesiredSize(min_bytes);
289*61c4878aSAndroid Build Coastguard Worker     return alloc_fut_.Pend(cx);
290*61c4878aSAndroid Build Coastguard Worker   }
291*61c4878aSAndroid Build Coastguard Worker 
DoPendWrite(Context & cx)292*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendWrite(Context& cx) override {
293*61c4878aSAndroid Build Coastguard Worker     if (state_ != kReadyToFlush) {
294*61c4878aSAndroid Build Coastguard Worker       PW_ASYNC_STORE_WAKER(
295*61c4878aSAndroid Build Coastguard Worker           cx, waker_, "TestDatagramWriter is waiting for its Channel to flush");
296*61c4878aSAndroid Build Coastguard Worker       return Pending();
297*61c4878aSAndroid Build Coastguard Worker     }
298*61c4878aSAndroid Build Coastguard Worker     last_flush_ = last_write_;
299*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
300*61c4878aSAndroid Build Coastguard Worker   }
301*61c4878aSAndroid Build Coastguard Worker 
DoPendClose(Context &)302*61c4878aSAndroid Build Coastguard Worker   Poll<pw::Status> DoPendClose(Context&) override {
303*61c4878aSAndroid Build Coastguard Worker     return Ready(pw::OkStatus());
304*61c4878aSAndroid Build Coastguard Worker   }
305*61c4878aSAndroid Build Coastguard Worker 
306*61c4878aSAndroid Build Coastguard Worker   enum {
307*61c4878aSAndroid Build Coastguard Worker     kUnavailable,
308*61c4878aSAndroid Build Coastguard Worker     kReadyToWrite,
309*61c4878aSAndroid Build Coastguard Worker     kWritePending,
310*61c4878aSAndroid Build Coastguard Worker     kReadyToFlush,
311*61c4878aSAndroid Build Coastguard Worker   } state_ = kUnavailable;
312*61c4878aSAndroid Build Coastguard Worker   Waker waker_;
313*61c4878aSAndroid Build Coastguard Worker   uint32_t last_write_ = 0;
314*61c4878aSAndroid Build Coastguard Worker   uint32_t last_flush_ = 0;
315*61c4878aSAndroid Build Coastguard Worker   MultiBuf last_dgram_;
316*61c4878aSAndroid Build Coastguard Worker   MultiBufAllocationFuture alloc_fut_;
317*61c4878aSAndroid Build Coastguard Worker };
318*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,TestByteReader)319*61c4878aSAndroid Build Coastguard Worker TEST(Channel, TestByteReader) {
320*61c4878aSAndroid Build Coastguard Worker   static constexpr char kReadData[] = "hello, world";
321*61c4878aSAndroid Build Coastguard Worker   static constexpr size_t kReadDataSize = sizeof(kReadData);
322*61c4878aSAndroid Build Coastguard Worker   static constexpr size_t kArbitraryMetaSize = 512;
323*61c4878aSAndroid Build Coastguard Worker 
324*61c4878aSAndroid Build Coastguard Worker   Dispatcher dispatcher;
325*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kReadDataSize> data_area;
326*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryMetaSize> meta_alloc;
327*61c4878aSAndroid Build Coastguard Worker   SimpleAllocator simple_allocator(data_area, meta_alloc);
328*61c4878aSAndroid Build Coastguard Worker   std::optional<MultiBuf> read_buf_opt =
329*61c4878aSAndroid Build Coastguard Worker       simple_allocator.Allocate(kReadDataSize);
330*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(read_buf_opt.has_value());
331*61c4878aSAndroid Build Coastguard Worker   MultiBuf& read_buf = *read_buf_opt;
332*61c4878aSAndroid Build Coastguard Worker 
333*61c4878aSAndroid Build Coastguard Worker   class : public Task {
334*61c4878aSAndroid Build Coastguard Worker    public:
335*61c4878aSAndroid Build Coastguard Worker     TestByteReader channel;
336*61c4878aSAndroid Build Coastguard Worker     int test_executed = 0;
337*61c4878aSAndroid Build Coastguard Worker 
338*61c4878aSAndroid Build Coastguard Worker    private:
339*61c4878aSAndroid Build Coastguard Worker     Poll<> DoPend(Context& cx) override {
340*61c4878aSAndroid Build Coastguard Worker       auto result = channel.PendRead(cx);
341*61c4878aSAndroid Build Coastguard Worker       if (!result.IsReady()) {
342*61c4878aSAndroid Build Coastguard Worker         return Pending();
343*61c4878aSAndroid Build Coastguard Worker       }
344*61c4878aSAndroid Build Coastguard Worker 
345*61c4878aSAndroid Build Coastguard Worker       auto actual_result = std::move(*result);
346*61c4878aSAndroid Build Coastguard Worker       EXPECT_TRUE(actual_result.ok());
347*61c4878aSAndroid Build Coastguard Worker 
348*61c4878aSAndroid Build Coastguard Worker       std::byte contents[kReadDataSize] = {};
349*61c4878aSAndroid Build Coastguard Worker 
350*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(actual_result->size(), sizeof(kReadData));
351*61c4878aSAndroid Build Coastguard Worker       std::copy(actual_result->begin(), actual_result->end(), contents);
352*61c4878aSAndroid Build Coastguard Worker       EXPECT_STREQ(reinterpret_cast<const char*>(contents), kReadData);
353*61c4878aSAndroid Build Coastguard Worker 
354*61c4878aSAndroid Build Coastguard Worker       test_executed += 1;
355*61c4878aSAndroid Build Coastguard Worker       return Ready();
356*61c4878aSAndroid Build Coastguard Worker     }
357*61c4878aSAndroid Build Coastguard Worker   } test_task;
358*61c4878aSAndroid Build Coastguard Worker 
359*61c4878aSAndroid Build Coastguard Worker   dispatcher.Post(test_task);
360*61c4878aSAndroid Build Coastguard Worker 
361*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(dispatcher.RunUntilStalled().IsReady());
362*61c4878aSAndroid Build Coastguard Worker 
363*61c4878aSAndroid Build Coastguard Worker   auto kReadDataBytes = reinterpret_cast<const std::byte*>(kReadData);
364*61c4878aSAndroid Build Coastguard Worker   std::copy(kReadDataBytes, kReadDataBytes + kReadDataSize, read_buf.begin());
365*61c4878aSAndroid Build Coastguard Worker   test_task.channel.PushData(std::move(read_buf));
366*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(dispatcher.RunUntilStalled().IsReady());
367*61c4878aSAndroid Build Coastguard Worker 
368*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(test_task.test_executed, 1);
369*61c4878aSAndroid Build Coastguard Worker }
370*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,TestDatagramWriter)371*61c4878aSAndroid Build Coastguard Worker TEST(Channel, TestDatagramWriter) {
372*61c4878aSAndroid Build Coastguard Worker   Dispatcher dispatcher;
373*61c4878aSAndroid Build Coastguard Worker   static constexpr size_t kArbitraryDataSize = 128;
374*61c4878aSAndroid Build Coastguard Worker   static constexpr size_t kArbitraryMetaSize = 512;
375*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kArbitraryDataSize> data_area;
376*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryMetaSize> meta_alloc;
377*61c4878aSAndroid Build Coastguard Worker   SimpleAllocator simple_allocator(data_area, meta_alloc);
378*61c4878aSAndroid Build Coastguard Worker   TestDatagramWriter write_channel(simple_allocator);
379*61c4878aSAndroid Build Coastguard Worker 
380*61c4878aSAndroid Build Coastguard Worker   static constexpr char kWriteData[] = "Hello there";
381*61c4878aSAndroid Build Coastguard Worker 
382*61c4878aSAndroid Build Coastguard Worker   class SendWriteDataAndFlush : public Task {
383*61c4878aSAndroid Build Coastguard Worker    public:
384*61c4878aSAndroid Build Coastguard Worker     explicit SendWriteDataAndFlush(DatagramWriter& channel, size_t)
385*61c4878aSAndroid Build Coastguard Worker         : channel_(channel) {}
386*61c4878aSAndroid Build Coastguard Worker     int test_executed = 0;
387*61c4878aSAndroid Build Coastguard Worker 
388*61c4878aSAndroid Build Coastguard Worker    private:
389*61c4878aSAndroid Build Coastguard Worker     Poll<> DoPend(Context& cx) override {
390*61c4878aSAndroid Build Coastguard Worker       switch (state_) {
391*61c4878aSAndroid Build Coastguard Worker         case kWaitUntilReady: {
392*61c4878aSAndroid Build Coastguard Worker           if (channel_.PendReadyToWrite(cx).IsPending()) {
393*61c4878aSAndroid Build Coastguard Worker             return Pending();
394*61c4878aSAndroid Build Coastguard Worker           }
395*61c4878aSAndroid Build Coastguard Worker           Poll<std::optional<MultiBuf>> buffer =
396*61c4878aSAndroid Build Coastguard Worker               channel_.PendAllocateWriteBuffer(cx, sizeof(kWriteData));
397*61c4878aSAndroid Build Coastguard Worker           if (buffer.IsPending()) {
398*61c4878aSAndroid Build Coastguard Worker             return Pending();
399*61c4878aSAndroid Build Coastguard Worker           }
400*61c4878aSAndroid Build Coastguard Worker           if (!buffer->has_value()) {
401*61c4878aSAndroid Build Coastguard Worker             // Allocator should have enough space for `kWriteData`.
402*61c4878aSAndroid Build Coastguard Worker             ADD_FAILURE();
403*61c4878aSAndroid Build Coastguard Worker             return Ready();
404*61c4878aSAndroid Build Coastguard Worker           }
405*61c4878aSAndroid Build Coastguard Worker           pw::ConstByteSpan str(pw::as_bytes(pw::span(kWriteData)));
406*61c4878aSAndroid Build Coastguard Worker           std::copy(str.begin(), str.end(), (**buffer).begin());
407*61c4878aSAndroid Build Coastguard Worker           pw::Status write_status = channel_.StageWrite(std::move(**buffer));
408*61c4878aSAndroid Build Coastguard Worker           PW_CHECK_OK(write_status);
409*61c4878aSAndroid Build Coastguard Worker           state_ = kFlushPacket;
410*61c4878aSAndroid Build Coastguard Worker           [[fallthrough]];
411*61c4878aSAndroid Build Coastguard Worker         }
412*61c4878aSAndroid Build Coastguard Worker         case kFlushPacket: {
413*61c4878aSAndroid Build Coastguard Worker           auto result = channel_.PendWrite(cx);
414*61c4878aSAndroid Build Coastguard Worker           if (result.IsPending()) {
415*61c4878aSAndroid Build Coastguard Worker             return Pending();
416*61c4878aSAndroid Build Coastguard Worker           }
417*61c4878aSAndroid Build Coastguard Worker           test_executed += 1;
418*61c4878aSAndroid Build Coastguard Worker           state_ = kWaitUntilReady;
419*61c4878aSAndroid Build Coastguard Worker           return Ready();
420*61c4878aSAndroid Build Coastguard Worker         }
421*61c4878aSAndroid Build Coastguard Worker         default:
422*61c4878aSAndroid Build Coastguard Worker           PW_CRASH("Illegal value");
423*61c4878aSAndroid Build Coastguard Worker       }
424*61c4878aSAndroid Build Coastguard Worker 
425*61c4878aSAndroid Build Coastguard Worker       // This test is INCOMPLETE.
426*61c4878aSAndroid Build Coastguard Worker 
427*61c4878aSAndroid Build Coastguard Worker       test_executed += 1;
428*61c4878aSAndroid Build Coastguard Worker       return Ready();
429*61c4878aSAndroid Build Coastguard Worker     }
430*61c4878aSAndroid Build Coastguard Worker 
431*61c4878aSAndroid Build Coastguard Worker     enum { kWaitUntilReady, kFlushPacket } state_ = kWaitUntilReady;
432*61c4878aSAndroid Build Coastguard Worker     DatagramWriter& channel_;
433*61c4878aSAndroid Build Coastguard Worker   };
434*61c4878aSAndroid Build Coastguard Worker 
435*61c4878aSAndroid Build Coastguard Worker   SendWriteDataAndFlush test_task(write_channel.channel(), 24601);
436*61c4878aSAndroid Build Coastguard Worker   dispatcher.Post(test_task);
437*61c4878aSAndroid Build Coastguard Worker 
438*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(dispatcher.RunUntilStalled(), Pending());
439*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(dispatcher.RunUntilStalled(), Pending());
440*61c4878aSAndroid Build Coastguard Worker 
441*61c4878aSAndroid Build Coastguard Worker   write_channel.MakeReadyToWrite();
442*61c4878aSAndroid Build Coastguard Worker 
443*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(dispatcher.RunUntilStalled(), Pending());
444*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(dispatcher.RunUntilStalled(), Pending());
445*61c4878aSAndroid Build Coastguard Worker 
446*61c4878aSAndroid Build Coastguard Worker   write_channel.MakeReadyToFlush();
447*61c4878aSAndroid Build Coastguard Worker 
448*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(dispatcher.RunUntilStalled(), Ready());
449*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(test_task.test_executed, 1);
450*61c4878aSAndroid Build Coastguard Worker 
451*61c4878aSAndroid Build Coastguard Worker   std::byte contents[64] = {};
452*61c4878aSAndroid Build Coastguard Worker   const MultiBuf& dgram = write_channel.last_datagram();
453*61c4878aSAndroid Build Coastguard Worker   std::copy(dgram.begin(), dgram.end(), contents);
454*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(reinterpret_cast<const char*>(contents), kWriteData);
455*61c4878aSAndroid Build Coastguard Worker }
456*61c4878aSAndroid Build Coastguard Worker 
TakesAChannel(const pw::channel::AnyChannel &)457*61c4878aSAndroid Build Coastguard Worker void TakesAChannel(const pw::channel::AnyChannel&) {}
458*61c4878aSAndroid Build Coastguard Worker 
TakesAReadableByteChannel(const pw::channel::ByteChannel<kReadable> & channel)459*61c4878aSAndroid Build Coastguard Worker const pw::channel::ByteChannel<kReadable>& TakesAReadableByteChannel(
460*61c4878aSAndroid Build Coastguard Worker     const pw::channel::ByteChannel<kReadable>& channel) {
461*61c4878aSAndroid Build Coastguard Worker   return channel;
462*61c4878aSAndroid Build Coastguard Worker }
463*61c4878aSAndroid Build Coastguard Worker 
TakesAWritableByteChannel(const pw::channel::ByteChannel<kWritable> &)464*61c4878aSAndroid Build Coastguard Worker void TakesAWritableByteChannel(const pw::channel::ByteChannel<kWritable>&) {}
465*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,Conversions)466*61c4878aSAndroid Build Coastguard Worker TEST(Channel, Conversions) {
467*61c4878aSAndroid Build Coastguard Worker   static constexpr size_t kArbitraryDataSize = 128;
468*61c4878aSAndroid Build Coastguard Worker   static constexpr size_t kArbitraryMetaSize = 128;
469*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, kArbitraryDataSize> data_area;
470*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryMetaSize> meta_alloc;
471*61c4878aSAndroid Build Coastguard Worker   SimpleAllocator simple_allocator(data_area, meta_alloc);
472*61c4878aSAndroid Build Coastguard Worker 
473*61c4878aSAndroid Build Coastguard Worker   const TestByteReader byte_channel;
474*61c4878aSAndroid Build Coastguard Worker   const TestDatagramWriter datagram_channel(simple_allocator);
475*61c4878aSAndroid Build Coastguard Worker 
476*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(byte_channel.channel());
477*61c4878aSAndroid Build Coastguard Worker 
478*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(byte_channel.as<kReadable>());
479*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(byte_channel.channel().as<kReadable>());
480*61c4878aSAndroid Build Coastguard Worker 
481*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(byte_channel.as<pw::channel::ByteReader>());
482*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(
483*61c4878aSAndroid Build Coastguard Worker       byte_channel.channel().as<pw::channel::ByteReader>());
484*61c4878aSAndroid Build Coastguard Worker 
485*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(
486*61c4878aSAndroid Build Coastguard Worker       byte_channel.as<pw::channel::ByteChannel<kReliable, kReadable>>());
487*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(
488*61c4878aSAndroid Build Coastguard Worker       byte_channel.channel()
489*61c4878aSAndroid Build Coastguard Worker           .as<pw::channel::ByteChannel<kReliable, kReadable>>());
490*61c4878aSAndroid Build Coastguard Worker 
491*61c4878aSAndroid Build Coastguard Worker   TakesAChannel(byte_channel);
492*61c4878aSAndroid Build Coastguard Worker   TakesAChannel(byte_channel.as<pw::channel::AnyChannel>());
493*61c4878aSAndroid Build Coastguard Worker 
494*61c4878aSAndroid Build Coastguard Worker   TakesAWritableByteChannel(datagram_channel.IgnoreDatagramBoundaries());
495*61c4878aSAndroid Build Coastguard Worker   TakesAWritableByteChannel(
496*61c4878aSAndroid Build Coastguard Worker       datagram_channel.channel().IgnoreDatagramBoundaries());
497*61c4878aSAndroid Build Coastguard Worker 
498*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] const pw::channel::AnyChannel& plain = byte_channel;
499*61c4878aSAndroid Build Coastguard Worker 
500*61c4878aSAndroid Build Coastguard Worker #if PW_NC_TEST(CannotImplicitlyLoseWritability)
501*61c4878aSAndroid Build Coastguard Worker   PW_NC_EXPECT("no matching function for call");
502*61c4878aSAndroid Build Coastguard Worker   TakesAWritableByteChannel(byte_channel.channel());
503*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotExplicitlyLoseWritability)
504*61c4878aSAndroid Build Coastguard Worker   PW_NC_EXPECT("Cannot use a non-writable channel as a writable channel");
505*61c4878aSAndroid Build Coastguard Worker   TakesAWritableByteChannel(byte_channel.as<kWritable>());
506*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotIgnoreDatagramBoundariesOnByteChannel)
507*61c4878aSAndroid Build Coastguard Worker   PW_NC_EXPECT("only be called to use a datagram channel to a byte channel");
508*61c4878aSAndroid Build Coastguard Worker   std::ignore = byte_channel.IgnoreDatagramBoundaries();
509*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotIgnoreDatagramBoundariesOnByteChannelImpl)
510*61c4878aSAndroid Build Coastguard Worker   PW_NC_EXPECT("only be called to use a datagram channel to a byte channel");
511*61c4878aSAndroid Build Coastguard Worker   std::ignore = byte_channel.channel().IgnoreDatagramBoundaries();
512*61c4878aSAndroid Build Coastguard Worker #endif  // PW_NC_TEST
513*61c4878aSAndroid Build Coastguard Worker }
514*61c4878aSAndroid Build Coastguard Worker 
515*61c4878aSAndroid Build Coastguard Worker #if PW_NC_TEST(CannotImplicitlyUseDatagramChannelAsByteChannel)
516*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("no matching function for call");
DatagramChannelNcTest(pw::channel::DatagramChannel<kReliable,kReadable> & dgram)517*61c4878aSAndroid Build Coastguard Worker void DatagramChannelNcTest(
518*61c4878aSAndroid Build Coastguard Worker     pw::channel::DatagramChannel<kReliable, kReadable>& dgram) {
519*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(dgram);
520*61c4878aSAndroid Build Coastguard Worker }
521*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotExplicitlyUseDatagramChannelAsByteChannel)
522*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("Datagram and byte channels are not interchangeable");
DatagramChannelNcTest(pw::channel::DatagramChannel<kReliable,kReadable> & dgram)523*61c4878aSAndroid Build Coastguard Worker void DatagramChannelNcTest(
524*61c4878aSAndroid Build Coastguard Worker     pw::channel::DatagramChannel<kReliable, kReadable>& dgram) {
525*61c4878aSAndroid Build Coastguard Worker   TakesAReadableByteChannel(dgram.as<pw::channel::ByteChannel<kReadable>>());
526*61c4878aSAndroid Build Coastguard Worker }
527*61c4878aSAndroid Build Coastguard Worker #endif  // PW_NC_TEST
528*61c4878aSAndroid Build Coastguard Worker 
529*61c4878aSAndroid Build Coastguard Worker class Foo {
530*61c4878aSAndroid Build Coastguard Worker  public:
Foo(pw::channel::ByteChannel<kReadable> &)531*61c4878aSAndroid Build Coastguard Worker   Foo(pw::channel::ByteChannel<kReadable>&) {}
532*61c4878aSAndroid Build Coastguard Worker   Foo(const Foo&) = default;
533*61c4878aSAndroid Build Coastguard Worker };
534*61c4878aSAndroid Build Coastguard Worker 
535*61c4878aSAndroid Build Coastguard Worker // Define additional overloads to ensure the right overload is selected with the
536*61c4878aSAndroid Build Coastguard Worker // implicit conversion.
TakesAReadableByteChannel(const Foo &)537*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void TakesAReadableByteChannel(const Foo&) {}
TakesAReadableByteChannel(int)538*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void TakesAReadableByteChannel(int) {}
TakesAReadableByteChannel(const pw::channel::DatagramReaderWriter &)539*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void TakesAReadableByteChannel(
540*61c4878aSAndroid Build Coastguard Worker     const pw::channel::DatagramReaderWriter&) {}
541*61c4878aSAndroid Build Coastguard Worker 
TEST(Channel,SelectsCorrectOverloadWhenRelyingOnImplicitConversion)542*61c4878aSAndroid Build Coastguard Worker TEST(Channel, SelectsCorrectOverloadWhenRelyingOnImplicitConversion) {
543*61c4878aSAndroid Build Coastguard Worker   TestByteReader byte_channel;
544*61c4878aSAndroid Build Coastguard Worker 
545*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] Foo selects_channel_ctor_not_copy_ctor(
546*61c4878aSAndroid Build Coastguard Worker       byte_channel.channel());
547*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(&byte_channel.as<pw::channel::ByteChannel<kReadable>>(),
548*61c4878aSAndroid Build Coastguard Worker             &TakesAReadableByteChannel(byte_channel.channel()));
549*61c4878aSAndroid Build Coastguard Worker }
550*61c4878aSAndroid Build Coastguard Worker 
551*61c4878aSAndroid Build Coastguard Worker #if PW_NC_TEST(CannotCallUnsupportedWriteMethodsOnChannel)
552*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("PendReadyToWrite may only be called on writable channels");
Bad(Context & cx,pw::channel::DatagramReader & c)553*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void Bad(Context& cx, pw::channel::DatagramReader& c) {
554*61c4878aSAndroid Build Coastguard Worker   std::ignore = c.PendReadyToWrite(cx);
555*61c4878aSAndroid Build Coastguard Worker }
556*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotCallUnsupportedWriteMethodsOnChannelImpl)
557*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("PendReadyToWrite may only be called on writable channels");
Bad(Context & cx,pw::channel::ByteReaderImpl & c)558*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void Bad(Context& cx, pw::channel::ByteReaderImpl& c) {
559*61c4878aSAndroid Build Coastguard Worker   std::ignore = c.PendReadyToWrite(cx);
560*61c4878aSAndroid Build Coastguard Worker }
561*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotCallUnsupportedReadMethodsOnChannel)
562*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("PendRead may only be called on readable channels");
Bad(Context & cx,pw::channel::ByteWriter & c)563*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void Bad(Context& cx, pw::channel::ByteWriter& c) {
564*61c4878aSAndroid Build Coastguard Worker   std::ignore = c.PendRead(cx);
565*61c4878aSAndroid Build Coastguard Worker }
566*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotCallUnsupportedReadMethodsOnChannelImpl)
567*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("PendRead may only be called on readable channels");
Bad(Context & cx,pw::channel::DatagramWriterImpl & c)568*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void Bad(Context& cx, pw::channel::DatagramWriterImpl& c) {
569*61c4878aSAndroid Build Coastguard Worker   std::ignore = c.PendRead(cx);
570*61c4878aSAndroid Build Coastguard Worker }
571*61c4878aSAndroid Build Coastguard Worker #endif  // PW_NC_TEST
572*61c4878aSAndroid Build Coastguard Worker 
573*61c4878aSAndroid Build Coastguard Worker }  // namespace
574