1 /*
2 * Copyright (C) 2021 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 <gtest/gtest.h>
18 #include <unistd.h>
19 #include <chrono>
20 #include <thread>
21
22 #include "MultiPoll.h"
23
24 using android::hardware::sensors::V2_0::subhal::implementation::MultiPoll;
25
26 // using namespace here is the sanctioned C++ way
27 // NOLINTNEXTLINE(build/namespaces)
28 using namespace std::chrono_literals;
29
30 class PipeHelper {
31 public:
PipeHelper()32 PipeHelper() {
33 int pipefd[2] = {0, 0};
34 int err = ::pipe(pipefd);
35 if (err == 0) {
36 mReadFd = pipefd[0];
37 mWriteFd = pipefd[1];
38 } else {
39 mReadFd = mWriteFd = -1;
40 }
41 }
42
~PipeHelper()43 ~PipeHelper() {
44 close(mReadFd);
45 close(mWriteFd);
46 }
47
readFd() const48 int readFd() const { return mReadFd; }
writeFd() const49 int writeFd() const { return mWriteFd; }
50
operator bool() const51 explicit operator bool() const { return (mReadFd >= 0) && (mWriteFd >= 0); }
52
read(char * buf,size_t n)53 size_t read(char* buf, size_t n) { return ::read(mReadFd, reinterpret_cast<void*>(buf), n); }
write(const char * buf,size_t n)54 size_t write(const char* buf, size_t n) {
55 return ::write(mWriteFd, reinterpret_cast<const void*>(buf), n);
56 }
57
58 private:
59 int mReadFd;
60 int mWriteFd;
61 };
62
TEST(MultiPollTest,EmptyList)63 TEST(MultiPollTest, EmptyList) {
64 MultiPoll mp(100);
65 bool called = false;
66 MultiPoll::OnPollIn f = [&called](int) -> void { called = true; };
67 mp.poll(f);
68 EXPECT_FALSE(called);
69 }
70
TEST(MultiPollTest,DataAvailable)71 TEST(MultiPollTest, DataAvailable) {
72 MultiPoll mp(100);
73 PipeHelper pe;
74 ASSERT_TRUE(pe);
75
76 mp.addDescriptor(pe.readFd());
77 pe.write("hello", 5);
78 bool called = false;
79 int poll_fd;
80 MultiPoll::OnPollIn f = [&called, &poll_fd](int fd) -> void {
81 called = true;
82 poll_fd = fd;
83 };
84 mp.poll(f);
85 EXPECT_TRUE(called);
86 EXPECT_EQ(poll_fd, pe.readFd());
87 }
88
TEST(MultiPollTest,DataComesUpLater)89 TEST(MultiPollTest, DataComesUpLater) {
90 MultiPoll mp(120000 /* 2 minutes */);
91 PipeHelper pe;
92 ASSERT_TRUE(pe);
93 mp.addDescriptor(pe.readFd());
94
95 bool called = false;
96 int poll_fd;
97 MultiPoll::OnPollIn f = [&called, &poll_fd](int fd) -> void {
98 called = true;
99 poll_fd = fd;
100 };
101 std::thread pollerThread([&mp, &f]() -> void { mp.poll(f); });
102
103 std::this_thread::sleep_for(100ms);
104 pe.write("hello", 5);
105
106 pollerThread.join();
107 EXPECT_TRUE(called);
108 EXPECT_EQ(poll_fd, pe.readFd());
109 }
110
TEST(MultiPollTest,OneFdHasData)111 TEST(MultiPollTest, OneFdHasData) {
112 MultiPoll mp(100);
113 PipeHelper p1;
114 PipeHelper p2;
115
116 mp.addDescriptor(p1.readFd());
117 mp.addDescriptor(p2.readFd());
118
119 int called = 0;
120 MultiPoll::OnPollIn f = [&called](int) -> void { ++called; };
121
122 p1.write("hello", 5);
123 mp.poll(f);
124 EXPECT_EQ(1, called);
125 }
126
TEST(MultiPollTest,TwoFdHaveData)127 TEST(MultiPollTest, TwoFdHaveData) {
128 MultiPoll mp(100);
129 PipeHelper p1;
130 PipeHelper p2;
131
132 mp.addDescriptor(p1.readFd());
133 mp.addDescriptor(p2.readFd());
134
135 int called = 0;
136 int prev_fd = -1;
137 bool repeat_fd = false;
138 MultiPoll::OnPollIn f = [&called, &prev_fd, &repeat_fd](int fd) -> void {
139 ++called;
140 if (prev_fd == fd) repeat_fd = true;
141 prev_fd = fd;
142 };
143
144 p1.write("hello", 5);
145 p2.write("hi", 2);
146 mp.poll(f);
147 EXPECT_EQ(2, called);
148 EXPECT_FALSE(repeat_fd);
149 EXPECT_TRUE(prev_fd == p1.readFd() || prev_fd == p2.readFd());
150 }
151
TEST(MultiPollTest,ZeroWait)152 TEST(MultiPollTest, ZeroWait) {
153 MultiPoll mp(0);
154 PipeHelper pe;
155 ASSERT_TRUE(pe);
156 mp.addDescriptor(pe.readFd());
157
158 bool called = false;
159 int poll_fd;
160 MultiPoll::OnPollIn f = [&called, &poll_fd](int fd) -> void {
161 called = true;
162 poll_fd = fd;
163 };
164 std::thread pollerThread([&mp, &f, &called]() -> void {
165 while (!called) mp.poll(f);
166 });
167
168 std::this_thread::sleep_for(100ms);
169 pe.write("hello", 5);
170
171 pollerThread.join();
172 EXPECT_TRUE(called);
173 EXPECT_EQ(poll_fd, pe.readFd());
174 }
175
TEST(MultiPollTest,AddOneLater)176 TEST(MultiPollTest, AddOneLater) {
177 MultiPoll mp(100);
178 PipeHelper p1;
179 PipeHelper p2;
180
181 mp.addDescriptor(p1.readFd());
182
183 bool called = false;
184 int poll_fd;
185 MultiPoll::OnPollIn f = [&called, &poll_fd](int fd) -> void {
186 called = true;
187 poll_fd = fd;
188 };
189
190 std::thread pollerThread([&mp, &f, &called]() -> void {
191 while (!called) mp.poll(f);
192 });
193
194 std::this_thread::sleep_for(250ms);
195 mp.addDescriptor(p2.readFd());
196 std::this_thread::sleep_for(100ms);
197 p2.write("hello", 5);
198
199 pollerThread.join();
200 EXPECT_TRUE(called);
201 EXPECT_EQ(p2.readFd(), poll_fd);
202 }
203