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 <string.h>
18
19 #include <memory>
20
21 #include <android-base/logging.h>
22 #include <android-base/unique_fd.h>
23 #include <gtest/gtest.h>
24 #include <utils/Errors.h>
25 #include <utils/StopWatch.h>
26
27 #include "wificond/looper_backed_event_loop.h"
28
29 namespace {
30
31 const int kTimingToleranceMs = 25;
32
33 // Adapt from libutils/tests/TestHelpers.h
34 class Pipe {
35 public:
36 android::base::unique_fd send_fd;
37 android::base::unique_fd receive_fd;
38
Pipe()39 Pipe() {
40 int fds[2];
41 ::pipe(fds);
42
43 receive_fd = android::base::unique_fd(fds[0]);
44 send_fd = android::base::unique_fd(fds[1]);
45 }
46
writeSignal()47 bool writeSignal() {
48 ssize_t n_written = ::write(send_fd, "*", 1);
49 if (n_written != 1) {
50 PLOG(ERROR) << "Failed to write signal to pipe";
51 return false;
52 }
53 return true;
54 }
55
readSignal()56 bool readSignal() {
57 char buf[1];
58 ssize_t n_read = ::read(receive_fd, buf, 1);
59 if (n_read != 1) {
60 if (n_read == 0) {
61 LOG(ERROR) << "No data from pipe";
62 } else {
63 PLOG(ERROR) << "Failed to read signal from pipe";
64 }
65 return false;
66 }
67 return true;
68 }
69 };
70
71 } // namespace
72
73 namespace android {
74 namespace wificond {
75
76 class WificondLooperBackedEventLoopTest : public ::testing::Test {
77 protected:
78 std::unique_ptr<LooperBackedEventLoop> event_loop_;
79
SetUp()80 virtual void SetUp() {
81 event_loop_.reset(new LooperBackedEventLoop());
82 }
83 };
84
TEST_F(WificondLooperBackedEventLoopTest,LooperBackedEventLoopPostTaskTest)85 TEST_F(WificondLooperBackedEventLoopTest, LooperBackedEventLoopPostTaskTest) {
86 bool task_executed = false;
87 event_loop_->PostTask([this, &task_executed]() mutable {
88 task_executed = true; event_loop_->TriggerExit();});
89 EXPECT_FALSE(task_executed);
90 event_loop_->Poll();
91 EXPECT_TRUE(task_executed);
92 }
93
TEST_F(WificondLooperBackedEventLoopTest,LooperBackedEventLoopPostDelayedTaskTest)94 TEST_F(WificondLooperBackedEventLoopTest,
95 LooperBackedEventLoopPostDelayedTaskTest) {
96 bool task_executed = false;
97 event_loop_->PostDelayedTask([this, &task_executed]() mutable {
98 task_executed = true; event_loop_->TriggerExit();}, 500);
99 EXPECT_FALSE(task_executed);
100 StopWatch stopWatch("DelayedTask");
101 event_loop_->Poll();
102 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
103 EXPECT_NEAR(500, elapsedMillis, kTimingToleranceMs);
104 EXPECT_TRUE(task_executed);
105 }
106
TEST_F(WificondLooperBackedEventLoopTest,LooperBackedEventLoopWatchFdInputReadyTest)107 TEST_F(WificondLooperBackedEventLoopTest, LooperBackedEventLoopWatchFdInputReadyTest) {
108 Pipe pipe;
109 bool read_result = false;
110 bool write_result = false;
111 event_loop_->PostTask([&write_result, &pipe]() {write_result = pipe.writeSignal();});
112 // Read data from pipe when fd is ready for input.
113 EXPECT_TRUE(event_loop_->WatchFileDescriptor(
114 pipe.receive_fd,
115 EventLoop::kModeInput,
116 [&read_result, &pipe, this](int fd) {
117 read_result = pipe.readSignal();
118 event_loop_->TriggerExit();}));
119 event_loop_->Poll();
120 EXPECT_EQ(true, read_result);
121 EXPECT_EQ(true, write_result);
122 }
123
TEST_F(WificondLooperBackedEventLoopTest,LooperBackedEventLoopWatchFdOutputReadyTest)124 TEST_F(WificondLooperBackedEventLoopTest, LooperBackedEventLoopWatchFdOutputReadyTest) {
125 Pipe pipe;
126 bool write_result = false;
127 // Write data to pipe when fd is ready for output.
128 EXPECT_TRUE(event_loop_->WatchFileDescriptor(
129 pipe.send_fd,
130 EventLoop::kModeOutput,
131 [&write_result, &pipe, this](int fd) {
132 write_result = pipe.writeSignal();
133 event_loop_->TriggerExit();}));
134 event_loop_->Poll();
135 EXPECT_EQ(true, write_result);
136 EXPECT_EQ(true, pipe.readSignal());
137 EXPECT_TRUE(event_loop_->StopWatchFileDescriptor(pipe.send_fd));
138 }
139
TEST_F(WificondLooperBackedEventLoopTest,LooperBackedEventLoopStopWatchFdTest)140 TEST_F(WificondLooperBackedEventLoopTest, LooperBackedEventLoopStopWatchFdTest) {
141 Pipe pipe;
142 bool read_result = false;
143 bool write_result = false;
144 event_loop_->PostTask([&write_result, &pipe]() {write_result = pipe.writeSignal();});
145 // Read data from pipe when fd is ready for input.
146 EXPECT_TRUE(event_loop_->WatchFileDescriptor(
147 pipe.receive_fd,
148 EventLoop::kModeInput,
149 [&read_result, &pipe, this](int fd) {
150 read_result = pipe.readSignal();
151 event_loop_->TriggerExit();}));
152 // Stop watching the file descriptor.
153 EXPECT_TRUE(event_loop_->StopWatchFileDescriptor(pipe.receive_fd));
154 // If the lambda for |WatchFileDescriptor| is not triggered, we need this to
155 // terminate the event loop.
156 event_loop_->PostDelayedTask([this]() { event_loop_->TriggerExit();}, 500);
157 event_loop_->Poll();
158 // We wrote to pipe successfully.
159 EXPECT_EQ(true, write_result);
160 // No data was read from the pipe because we stopped watching the file
161 // descriptor. |read_result| is not set to true;
162 EXPECT_EQ(false, read_result);
163 }
164
165 } // namespace wificond
166 } // namespace android
167