1 /*
2  * Copyright (C) 2016 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 "IOEventLoop.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include <atomic>
22 #include <chrono>
23 #include <thread>
24 
TEST(IOEventLoop,read)25 TEST(IOEventLoop, read) {
26   int fd[2];
27   ASSERT_EQ(0, pipe(fd));
28   IOEventLoop loop;
29   int count = 0;
30   int retry_count = 0;
31   ASSERT_NE(nullptr, loop.AddReadEvent(fd[0], [&]() {
32     while (true) {
33       char c;
34       int ret = read(fd[0], &c, 1);
35       if (ret == 1) {
36         if (++count == 100) {
37           return loop.ExitLoop();
38         }
39       } else if (ret == -1 && errno == EAGAIN) {
40         retry_count++;
41         break;
42       } else {
43         return false;
44       }
45     }
46     return true;
47   }));
48   std::thread thread([&]() {
49     for (int i = 0; i < 100; ++i) {
50       usleep(1000);
51       char c;
52       write(fd[1], &c, 1);
53     }
54   });
55   ASSERT_TRUE(loop.RunLoop());
56   thread.join();
57   ASSERT_EQ(100, count);
58   // Test retry_count to make sure we are not doing blocking read.
59   ASSERT_GT(retry_count, 0);
60   close(fd[0]);
61   close(fd[1]);
62 }
63 
TEST(IOEventLoop,write)64 TEST(IOEventLoop, write) {
65   int fd[2];
66   ASSERT_EQ(0, pipe(fd));
67   IOEventLoop loop;
68   int count = 0;
69   ASSERT_NE(nullptr, loop.AddWriteEvent(fd[1], [&]() {
70     int ret = 0;
71     char buf[4096];
72     while ((ret = write(fd[1], buf, sizeof(buf))) > 0) {
73     }
74     if (ret == -1 && errno == EAGAIN) {
75       if (++count == 100) {
76         loop.ExitLoop();
77       }
78       return true;
79     }
80     return false;
81   }));
82   std::thread thread([&]() {
83     usleep(500000);
84     while (true) {
85       usleep(1000);
86       char buf[4096];
87       if (read(fd[0], buf, sizeof(buf)) <= 0) {
88         break;
89       }
90     }
91   });
92   ASSERT_TRUE(loop.RunLoop());
93   // close fd[1] to make read thread stop.
94   close(fd[1]);
95   thread.join();
96   close(fd[0]);
97   ASSERT_EQ(100, count);
98 }
99 
TEST(IOEventLoop,signal)100 TEST(IOEventLoop, signal) {
101   IOEventLoop loop;
102   int count = 0;
103   ASSERT_TRUE(loop.AddSignalEvent(SIGINT, [&]() {
104     if (++count == 100) {
105       loop.ExitLoop();
106     }
107     return true;
108   }));
109   std::atomic<bool> stop_thread(false);
110   std::thread thread([&]() {
111     while (!stop_thread) {
112       usleep(1000);
113       kill(getpid(), SIGINT);
114     }
115   });
116   ASSERT_TRUE(loop.RunLoop());
117   stop_thread = true;
118   thread.join();
119   ASSERT_EQ(100, count);
120 }
121 
TestPeriodicEvents(int period_in_us,int iterations,bool precise)122 void TestPeriodicEvents(int period_in_us, int iterations, bool precise) {
123   timeval tv;
124   tv.tv_sec = period_in_us / 1000000;
125   tv.tv_usec = period_in_us % 1000000;
126   int count = 0;
127   IOEventLoop loop;
128   if (precise) {
129     ASSERT_TRUE(loop.UsePreciseTimer());
130   }
131   ASSERT_TRUE(loop.AddPeriodicEvent(tv, [&]() {
132     if (++count == iterations) {
133       loop.ExitLoop();
134     }
135     return true;
136   }));
137   auto start_time = std::chrono::steady_clock::now();
138   ASSERT_TRUE(loop.RunLoop());
139   auto end_time = std::chrono::steady_clock::now();
140   ASSERT_EQ(iterations, count);
141   double time_used = std::chrono::duration_cast<std::chrono::duration<double>>(
142                          end_time - start_time).count();
143   double min_time_in_sec = period_in_us / 1e6 * iterations;
144   double max_time_in_sec = min_time_in_sec + (precise ? 0.1 : 1);
145   ASSERT_GE(time_used, min_time_in_sec);
146   ASSERT_LT(time_used, max_time_in_sec);
147 }
148 
TEST(IOEventLoop,periodic)149 TEST(IOEventLoop, periodic) {
150   TestPeriodicEvents(1000000, 1, false);
151 }
152 
TEST(IOEventLoop,periodic_precise)153 TEST(IOEventLoop, periodic_precise) {
154   TestPeriodicEvents(1000, 100, true);
155 }
156 
TEST(IOEventLoop,read_and_del_event)157 TEST(IOEventLoop, read_and_del_event) {
158   int fd[2];
159   ASSERT_EQ(0, pipe(fd));
160   IOEventLoop loop;
161   int count = 0;
162   IOEventRef ref = loop.AddReadEvent(fd[0], [&]() {
163     count++;
164     return IOEventLoop::DelEvent(ref);
165   });
166   ASSERT_NE(nullptr, ref);
167 
168   std::thread thread([&]() {
169     for (int i = 0; i < 100; ++i) {
170       usleep(1000);
171       char c;
172       write(fd[1], &c, 1);
173     }
174   });
175   ASSERT_TRUE(loop.RunLoop());
176   thread.join();
177   ASSERT_EQ(1, count);
178   close(fd[0]);
179   close(fd[1]);
180 }
181 
TEST(IOEventLoop,disable_enable_event)182 TEST(IOEventLoop, disable_enable_event) {
183   int fd[2];
184   ASSERT_EQ(0, pipe(fd));
185   IOEventLoop loop;
186   int count = 0;
187   IOEventRef ref = loop.AddWriteEvent(fd[1], [&]() {
188     count++;
189     return IOEventLoop::DisableEvent(ref);
190   });
191   ASSERT_NE(nullptr, ref);
192 
193   timeval tv;
194   tv.tv_sec = 0;
195   tv.tv_usec = 500000;
196   int periodic_count = 0;
197   ASSERT_TRUE(loop.AddPeriodicEvent(tv, [&]() {
198     periodic_count++;
199     if (periodic_count == 1) {
200       if (count != 1) {
201         return false;
202       }
203       return IOEventLoop::EnableEvent(ref);
204     } else {
205       if (count != 2) {
206         return false;
207       }
208       return loop.ExitLoop();
209     }
210   }));
211 
212   ASSERT_TRUE(loop.RunLoop());
213   ASSERT_EQ(2, count);
214   ASSERT_EQ(2, periodic_count);
215   close(fd[0]);
216   close(fd[1]);
217 }
218