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
29namespace {
30
31const int kTimingToleranceMs = 25;
32
33// Adapt from libutils/tests/TestHelpers.h
34class Pipe {
35public:
36  android::base::unique_fd send_fd;
37  android::base::unique_fd receive_fd;
38
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
47  bool writeSignal() {
48    ssize_t n_written = ::write(send_fd, "*", 1);
49    if (n_written != 1) {
50      LOG(ERROR) << "Failed to write signal to pipe: " << strerror(errno);
51      return false;
52    }
53    return true;
54  }
55
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        LOG(ERROR) << "Failed to read signal from pipe: " << strerror(errno);
64      }
65      return false;
66    }
67    return true;
68  }
69};
70
71}  // namespace
72
73namespace android {
74namespace wificond {
75
76class WificondLooperBackedEventLoopTest : public ::testing::Test {
77 protected:
78  std::unique_ptr<LooperBackedEventLoop> event_loop_;
79
80  virtual void SetUp() {
81    event_loop_.reset(new LooperBackedEventLoop());
82  }
83};
84
85TEST_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
94TEST_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
107TEST_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
124TEST_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}
138
139TEST_F(WificondLooperBackedEventLoopTest, LooperBackedEventLoopStopWatchFdTest) {
140  Pipe pipe;
141  bool read_result = false;
142  bool write_result = false;
143  event_loop_->PostTask([&write_result, &pipe]() {write_result = pipe.writeSignal();});
144  // Read data from pipe when fd is ready for input.
145  EXPECT_TRUE(event_loop_->WatchFileDescriptor(
146      pipe.receive_fd,
147      EventLoop::kModeInput,
148      [&read_result, &pipe, this](int fd) {
149          read_result = pipe.readSignal();
150          event_loop_->TriggerExit();}));
151  // Stop watching the file descriptor.
152  EXPECT_TRUE(event_loop_->StopWatchFileDescriptor(pipe.receive_fd));
153  event_loop_->Poll();
154  // We wrote to pipe successfully.
155  EXPECT_EQ(true, write_result);
156  // No data was read from the pipe because we stopped watching the file
157  // descriptor. |read_result| is not set to true;
158  EXPECT_EQ(false, read_result);
159}
160
161}  // namespace wificond
162}  // namespace android
163