• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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