1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "perfetto/ext/base/threading/spawn.h"
18
19 #include <optional>
20
21 #include "perfetto/ext/base/event_fd.h"
22 #include "perfetto/ext/base/thread_task_runner.h"
23 #include "perfetto/ext/base/threading/future.h"
24 #include "perfetto/ext/base/threading/poll.h"
25 #include "perfetto/ext/base/threading/util.h"
26 #include "perfetto/ext/base/unix_task_runner.h"
27 #include "src/base/test/test_task_runner.h"
28 #include "test/gtest_and_gmock.h"
29
30 namespace perfetto {
31 namespace base {
32 namespace {
33
34 using ::testing::_;
35 using ::testing::Return;
36
37 template <typename T>
38 class MockFuturePollable : public FuturePollable<T> {
39 public:
40 MOCK_METHOD(FuturePollResult<T>, Poll, (PollContext*), (override));
41 };
42
43 template <typename T>
44 class MockStreamPollable : public StreamPollable<T> {
45 public:
46 MOCK_METHOD(StreamPollResult<T>, PollNext, (PollContext*), (override));
47 };
48
TEST(SpawnUnittest,SpawnFuture)49 TEST(SpawnUnittest, SpawnFuture) {
50 base::TestTaskRunner task_runner;
51
52 base::EventFd fd;
53 auto pollable = std::make_unique<MockFuturePollable<int>>();
54 EXPECT_CALL(*pollable, Poll(_))
55 .WillOnce([&fd](PollContext* ctx) {
56 fd.Clear();
57 ctx->RegisterInterested(fd.fd());
58 return PendingPollResult();
59 })
60 .WillOnce(Return(FuturePollResult<int>(1024)));
61 auto res = SpawnResultFuture<int>(
62 &task_runner,
63 [pollable = std::make_shared<std::unique_ptr<MockFuturePollable<int>>>(
64 std::move(pollable))]() mutable {
65 return base::Future<int>(std::move(*pollable));
66 });
67
68 task_runner.RunUntilIdle();
69 ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);
70
71 task_runner.RunUntilIdle();
72 ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);
73
74 fd.Notify();
75 task_runner.RunUntilIdle();
76
77 auto read = res.channel()->ReadNonBlocking();
78 ASSERT_EQ(read.item, 1024);
79 ASSERT_TRUE(read.is_closed);
80
81 read = res.channel()->ReadNonBlocking();
82 ASSERT_TRUE(read.is_closed);
83 }
84
TEST(SpawnUnittest,SpawnStream)85 TEST(SpawnUnittest, SpawnStream) {
86 base::TestTaskRunner task_runner;
87
88 base::EventFd fd;
89 auto pollable = std::make_unique<MockStreamPollable<int>>();
90 EXPECT_CALL(*pollable, PollNext(_))
91 .WillOnce([&fd](PollContext* ctx) {
92 fd.Clear();
93 ctx->RegisterInterested(fd.fd());
94 return PendingPollResult();
95 })
96 .WillOnce(Return(StreamPollResult<int>(1024)))
97 .WillOnce([&fd](PollContext* ctx) {
98 fd.Clear();
99 ctx->RegisterInterested(fd.fd());
100 return PendingPollResult();
101 })
102 .WillOnce(Return(StreamPollResult<int>(2048)))
103 .WillOnce(Return(DonePollResult()));
104 auto res = SpawnResultStream<int>(
105 &task_runner,
106 [pollable = std::make_shared<std::unique_ptr<MockStreamPollable<int>>>(
107 std::move(pollable))]() mutable {
108 return base::Stream<int>(std::move(*pollable));
109 });
110
111 task_runner.RunUntilIdle();
112 ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);
113
114 fd.Notify();
115 task_runner.RunUntilIdle();
116
117 auto read = res.channel()->ReadNonBlocking();
118 ASSERT_EQ(read.item, 1024);
119 ASSERT_FALSE(read.is_closed);
120
121 task_runner.RunUntilIdle();
122 ASSERT_EQ(res.channel()->ReadNonBlocking().item, std::nullopt);
123
124 fd.Notify();
125 task_runner.RunUntilIdle();
126
127 read = res.channel()->ReadNonBlocking();
128 ASSERT_EQ(read.item, 2048);
129 ASSERT_TRUE(read.is_closed);
130 }
131
132 } // namespace
133 } // namespace base
134 } // namespace perfetto
135