1 // Copyright 2024 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_async2/coro_or_else_task.h"
16
17 #include "pw_allocator/null_allocator.h"
18 #include "pw_allocator/testing.h"
19 #include "pw_async2/coro.h"
20 #include "pw_async2/dispatcher_base.h"
21 #include "pw_status/status.h"
22
23 namespace {
24
25 using ::pw::OkStatus;
26 using ::pw::Result;
27 using ::pw::Status;
28 using ::pw::allocator::Allocator;
29 using ::pw::allocator::GetNullAllocator;
30 using ::pw::allocator::test::AllocatorForTest;
31 using ::pw::async2::Context;
32 using ::pw::async2::Coro;
33 using ::pw::async2::CoroContext;
34 using ::pw::async2::CoroOrElseTask;
35 using ::pw::async2::Dispatcher;
36 using ::pw::async2::Pending;
37 using ::pw::async2::Poll;
38 using ::pw::async2::Ready;
39 using ::pw::async2::Task;
40 using ::pw::async2::Waker;
41
ImmediatelyReturnsFive(CoroContext &)42 Coro<Result<int>> ImmediatelyReturnsFive(CoroContext&) { co_return 5; }
43
StoresFiveThenReturns(CoroContext & coro_cx,int & out)44 Coro<Status> StoresFiveThenReturns(CoroContext& coro_cx, int& out) {
45 PW_CO_TRY_ASSIGN(out, co_await ImmediatelyReturnsFive(coro_cx));
46 co_return OkStatus();
47 }
48
TEST(CoroTest,BasicFunctionsWithoutYieldingRun)49 TEST(CoroTest, BasicFunctionsWithoutYieldingRun) {
50 AllocatorForTest<256> alloc;
51 CoroContext coro_cx(alloc);
52 int output = 0;
53 bool error_handler_did_run = false;
54 CoroOrElseTask task(
55 StoresFiveThenReturns(coro_cx, output),
56 [&error_handler_did_run](Status) { error_handler_did_run = true; });
57 Dispatcher dispatcher;
58 dispatcher.Post(task);
59 EXPECT_TRUE(dispatcher.RunUntilStalled().IsReady());
60 EXPECT_EQ(output, 5);
61 EXPECT_FALSE(error_handler_did_run);
62 }
63
TEST(CoroTest,AllocationFailureProducesInvalidCoro)64 TEST(CoroTest, AllocationFailureProducesInvalidCoro) {
65 CoroContext coro_cx(GetNullAllocator());
66 EXPECT_FALSE(ImmediatelyReturnsFive(coro_cx).IsValid());
67 Status status;
68 int output = 0;
69 CoroOrElseTask task(StoresFiveThenReturns(coro_cx, output),
70 [&status](Status actual) { status = actual; });
71 Dispatcher dispatcher;
72 dispatcher.Post(task);
73 EXPECT_TRUE(dispatcher.RunUntilStalled().IsReady());
74 EXPECT_EQ(status, Status::Internal());
75 }
76
77 } // namespace
78