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
15*61c4878aSAndroid Build Coastguard Worker #include "pw_channel/stream_channel.h"
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Worker #include <algorithm>
18*61c4878aSAndroid Build Coastguard Worker #include <array>
19*61c4878aSAndroid Build Coastguard Worker
20*61c4878aSAndroid Build Coastguard Worker #include "pw_async2/pend_func_task.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/suffix.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_multibuf/simple_allocator_for_test.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_stream/mpsc_stream.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/test_thread_context.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
27*61c4878aSAndroid Build Coastguard Worker
28*61c4878aSAndroid Build Coastguard Worker namespace {
29*61c4878aSAndroid Build Coastguard Worker
30*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Context;
31*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::PendFuncTask;
32*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Pending;
33*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Poll;
34*61c4878aSAndroid Build Coastguard Worker using ::pw::async2::Ready;
35*61c4878aSAndroid Build Coastguard Worker using ::pw::multibuf::MultiBuf;
36*61c4878aSAndroid Build Coastguard Worker using ::pw::multibuf::test::SimpleAllocatorForTest;
37*61c4878aSAndroid Build Coastguard Worker using ::pw::operator""_b;
38*61c4878aSAndroid Build Coastguard Worker
39*61c4878aSAndroid Build Coastguard Worker template <typename ActualIterable, typename ExpectedIterable>
ExpectElementsEqual(const ActualIterable & actual,const ExpectedIterable & expected)40*61c4878aSAndroid Build Coastguard Worker void ExpectElementsEqual(const ActualIterable& actual,
41*61c4878aSAndroid Build Coastguard Worker const ExpectedIterable& expected) {
42*61c4878aSAndroid Build Coastguard Worker auto actual_iter = actual.begin();
43*61c4878aSAndroid Build Coastguard Worker auto expected_iter = expected.begin();
44*61c4878aSAndroid Build Coastguard Worker for (; expected_iter != expected.end(); ++actual_iter, ++expected_iter) {
45*61c4878aSAndroid Build Coastguard Worker ASSERT_NE(actual_iter, actual.end());
46*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(*actual_iter, *expected_iter);
47*61c4878aSAndroid Build Coastguard Worker }
48*61c4878aSAndroid Build Coastguard Worker }
49*61c4878aSAndroid Build Coastguard Worker
50*61c4878aSAndroid Build Coastguard Worker template <typename ActualIterable, typename T>
ExpectElementsEqual(const ActualIterable & actual,std::initializer_list<T> expected)51*61c4878aSAndroid Build Coastguard Worker void ExpectElementsEqual(const ActualIterable& actual,
52*61c4878aSAndroid Build Coastguard Worker std::initializer_list<T> expected) {
53*61c4878aSAndroid Build Coastguard Worker ExpectElementsEqual<ActualIterable, std::initializer_list<T>>(actual,
54*61c4878aSAndroid Build Coastguard Worker expected);
55*61c4878aSAndroid Build Coastguard Worker }
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker struct LiveForeverTestData {
LiveForeverTestData__anon9af3b3a00111::LiveForeverTestData58*61c4878aSAndroid Build Coastguard Worker LiveForeverTestData() {
59*61c4878aSAndroid Build Coastguard Worker pw::stream::CreateMpscStream(channel_input_reader, channel_input_writer);
60*61c4878aSAndroid Build Coastguard Worker pw::stream::CreateMpscStream(channel_output_reader, channel_output_writer);
61*61c4878aSAndroid Build Coastguard Worker }
62*61c4878aSAndroid Build Coastguard Worker pw::stream::BufferedMpscReader<512> channel_input_reader;
63*61c4878aSAndroid Build Coastguard Worker pw::stream::MpscWriter channel_input_writer;
64*61c4878aSAndroid Build Coastguard Worker pw::stream::BufferedMpscReader<512> channel_output_reader;
65*61c4878aSAndroid Build Coastguard Worker pw::stream::MpscWriter channel_output_writer;
66*61c4878aSAndroid Build Coastguard Worker SimpleAllocatorForTest<> allocator;
67*61c4878aSAndroid Build Coastguard Worker pw::thread::test::TestThreadContext read_thread_cx;
68*61c4878aSAndroid Build Coastguard Worker pw::thread::test::TestThreadContext write_thread_cx;
69*61c4878aSAndroid Build Coastguard Worker };
70*61c4878aSAndroid Build Coastguard Worker
TEST(StreamChannel,ReadsAndWritesData)71*61c4878aSAndroid Build Coastguard Worker TEST(StreamChannel, ReadsAndWritesData) {
72*61c4878aSAndroid Build Coastguard Worker static pw::NoDestructor<LiveForeverTestData> test_data;
73*61c4878aSAndroid Build Coastguard Worker static pw::NoDestructor<pw::channel::StreamChannel> stream_channel(
74*61c4878aSAndroid Build Coastguard Worker test_data->allocator,
75*61c4878aSAndroid Build Coastguard Worker test_data->channel_input_reader,
76*61c4878aSAndroid Build Coastguard Worker test_data->read_thread_cx.options(),
77*61c4878aSAndroid Build Coastguard Worker test_data->channel_output_writer,
78*61c4878aSAndroid Build Coastguard Worker test_data->write_thread_cx.options());
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker PendFuncTask read_task([&](Context& cx) -> Poll<> {
81*61c4878aSAndroid Build Coastguard Worker auto read = stream_channel->PendRead(cx);
82*61c4878aSAndroid Build Coastguard Worker if (read.IsPending()) {
83*61c4878aSAndroid Build Coastguard Worker return Pending();
84*61c4878aSAndroid Build Coastguard Worker }
85*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(read->status(), pw::OkStatus());
86*61c4878aSAndroid Build Coastguard Worker if (read->ok()) {
87*61c4878aSAndroid Build Coastguard Worker ExpectElementsEqual(**read, {1_b, 2_b, 3_b});
88*61c4878aSAndroid Build Coastguard Worker }
89*61c4878aSAndroid Build Coastguard Worker return Ready();
90*61c4878aSAndroid Build Coastguard Worker });
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker MultiBuf to_send = test_data->allocator.BufWith({4_b, 5_b, 6_b});
93*61c4878aSAndroid Build Coastguard Worker PendFuncTask write_task([&](Context& cx) -> Poll<> {
94*61c4878aSAndroid Build Coastguard Worker if (stream_channel->PendReadyToWrite(cx).IsPending()) {
95*61c4878aSAndroid Build Coastguard Worker return Pending();
96*61c4878aSAndroid Build Coastguard Worker }
97*61c4878aSAndroid Build Coastguard Worker PW_TEST_EXPECT_OK(stream_channel->StageWrite(std::move(to_send)));
98*61c4878aSAndroid Build Coastguard Worker return Ready();
99*61c4878aSAndroid Build Coastguard Worker });
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker pw::async2::Dispatcher dispatcher;
102*61c4878aSAndroid Build Coastguard Worker dispatcher.Post(write_task);
103*61c4878aSAndroid Build Coastguard Worker dispatcher.Post(read_task);
104*61c4878aSAndroid Build Coastguard Worker
105*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Pending(), dispatcher.RunUntilStalled());
106*61c4878aSAndroid Build Coastguard Worker std::array<const std::byte, 3> data_to_send({1_b, 2_b, 3_b});
107*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(pw::OkStatus(),
108*61c4878aSAndroid Build Coastguard Worker test_data->channel_input_writer.Write(data_to_send));
109*61c4878aSAndroid Build Coastguard Worker dispatcher.RunToCompletion();
110*61c4878aSAndroid Build Coastguard Worker }
111*61c4878aSAndroid Build Coastguard Worker
112*61c4878aSAndroid Build Coastguard Worker } // namespace
113