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