1bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui/*
2bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * Copyright (C) 2015 The Android Open Source Project
3bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui *
4bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * Licensed under the Apache License, Version 2.0 (the "License");
5bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * you may not use this file except in compliance with the License.
6bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * You may obtain a copy of the License at
7bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui *
8bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui *      http://www.apache.org/licenses/LICENSE-2.0
9bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui *
10bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * Unless required by applicable law or agreed to in writing, software
11bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * distributed under the License is distributed on an "AS IS" BASIS,
12bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * See the License for the specific language governing permissions and
14bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui * limitations under the License.
15bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui */
16bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
17bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui#include "fdevent.h"
18bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
19bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui#include <gtest/gtest.h>
20bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
21a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui#include <limits>
22bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui#include <queue>
23bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui#include <string>
24bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui#include <vector>
25bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
26bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui#include "adb_io.h"
27022d447e9efcff59e22f0ab13764282116f235ddJosh Gao#include "fdevent_test.h"
28bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
29bec02fc43d917a4da817d4a02826f110ce340243Yabin Cuiclass FdHandler {
30bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui  public:
31bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    FdHandler(int read_fd, int write_fd) : read_fd_(read_fd), write_fd_(write_fd) {
32bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        fdevent_install(&read_fde_, read_fd_, FdEventCallback, this);
33a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui        fdevent_add(&read_fde_, FDE_READ);
34bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        fdevent_install(&write_fde_, write_fd_, FdEventCallback, this);
35a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    }
36a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui
37a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    ~FdHandler() {
38a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui        fdevent_remove(&read_fde_);
39a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui        fdevent_remove(&write_fde_);
40bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    }
41bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
42bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui  private:
43bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    static void FdEventCallback(int fd, unsigned events, void* userdata) {
44bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        FdHandler* handler = reinterpret_cast<FdHandler*>(userdata);
45bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        ASSERT_EQ(0u, (events & ~(FDE_READ | FDE_WRITE))) << "unexpected events: " << events;
46bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        if (events & FDE_READ) {
47bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            ASSERT_EQ(fd, handler->read_fd_);
48bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            char c;
49022d447e9efcff59e22f0ab13764282116f235ddJosh Gao            ASSERT_EQ(1, adb_read(fd, &c, 1));
50bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            handler->queue_.push(c);
51bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            fdevent_add(&handler->write_fde_, FDE_WRITE);
52bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        }
53bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        if (events & FDE_WRITE) {
54bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            ASSERT_EQ(fd, handler->write_fd_);
55bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            ASSERT_FALSE(handler->queue_.empty());
56bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            char c = handler->queue_.front();
57bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            handler->queue_.pop();
58022d447e9efcff59e22f0ab13764282116f235ddJosh Gao            ASSERT_EQ(1, adb_write(fd, &c, 1));
59bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            if (handler->queue_.empty()) {
60bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui              fdevent_del(&handler->write_fde_, FDE_WRITE);
61bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui            }
62bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        }
63bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    }
64bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
65bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui  private:
66bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    const int read_fd_;
67bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    const int write_fd_;
68bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    fdevent read_fde_;
69bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    fdevent write_fde_;
70bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    std::queue<char> queue_;
71bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui};
72bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
73bec02fc43d917a4da817d4a02826f110ce340243Yabin Cuistruct ThreadArg {
74bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    int first_read_fd;
75bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    int last_write_fd;
76bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    size_t middle_pipe_count;
77bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui};
78bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
79022d447e9efcff59e22f0ab13764282116f235ddJosh GaoTEST_F(FdeventTest, fdevent_terminate) {
80022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    adb_thread_t thread;
81022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    PrepareThread();
82022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_TRUE(adb_thread_create([](void*) { fdevent_loop(); }, nullptr, &thread));
83022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    TerminateThread(thread);
84022d447e9efcff59e22f0ab13764282116f235ddJosh Gao}
85022d447e9efcff59e22f0ab13764282116f235ddJosh Gao
86bec02fc43d917a4da817d4a02826f110ce340243Yabin Cuistatic void FdEventThreadFunc(ThreadArg* arg) {
87bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    std::vector<int> read_fds;
88bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    std::vector<int> write_fds;
89bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
90bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    read_fds.push_back(arg->first_read_fd);
91bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    for (size_t i = 0; i < arg->middle_pipe_count; ++i) {
92bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        int fds[2];
93022d447e9efcff59e22f0ab13764282116f235ddJosh Gao        ASSERT_EQ(0, adb_socketpair(fds));
94bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        read_fds.push_back(fds[0]);
95bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        write_fds.push_back(fds[1]);
96bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    }
97bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    write_fds.push_back(arg->last_write_fd);
98bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
99bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    std::vector<std::unique_ptr<FdHandler>> fd_handlers;
100bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    for (size_t i = 0; i < read_fds.size(); ++i) {
101bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        fd_handlers.push_back(std::unique_ptr<FdHandler>(new FdHandler(read_fds[i], write_fds[i])));
102bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    }
103bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
104bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    fdevent_loop();
105bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui}
106bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
107c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin CuiTEST_F(FdeventTest, smoke) {
108bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    const size_t PIPE_COUNT = 10;
109bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    const size_t MESSAGE_LOOP_COUNT = 100;
110bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    const std::string MESSAGE = "fdevent_test";
111bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    int fd_pair1[2];
112bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    int fd_pair2[2];
113022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_EQ(0, adb_socketpair(fd_pair1));
114022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_EQ(0, adb_socketpair(fd_pair2));
115022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    adb_thread_t thread;
116bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    ThreadArg thread_arg;
117bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    thread_arg.first_read_fd = fd_pair1[0];
118bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    thread_arg.last_write_fd = fd_pair2[1];
119bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    thread_arg.middle_pipe_count = PIPE_COUNT;
120bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    int writer = fd_pair1[1];
121bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    int reader = fd_pair2[0];
122bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
123022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    PrepareThread();
124022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(FdEventThreadFunc), &thread_arg,
125022d447e9efcff59e22f0ab13764282116f235ddJosh Gao                                  &thread));
126bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
127bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
128bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        std::string read_buffer = MESSAGE;
129bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        std::string write_buffer(MESSAGE.size(), 'a');
130bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        ASSERT_TRUE(WriteFdExactly(writer, read_buffer.c_str(), read_buffer.size()));
131bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        ASSERT_TRUE(ReadFdExactly(reader, &write_buffer[0], write_buffer.size()));
132bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui        ASSERT_EQ(read_buffer, write_buffer);
133bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui    }
134bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui
135022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    TerminateThread(thread);
136022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_EQ(0, adb_close(writer));
137022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_EQ(0, adb_close(reader));
138bec02fc43d917a4da817d4a02826f110ce340243Yabin Cui}
139a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui
140a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cuistruct InvalidFdArg {
141a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    fdevent fde;
142a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    unsigned expected_events;
143a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    size_t* happened_event_count;
144a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui};
145a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui
146a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cuistatic void InvalidFdEventCallback(int fd, unsigned events, void* userdata) {
147a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    InvalidFdArg* arg = reinterpret_cast<InvalidFdArg*>(userdata);
148a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    ASSERT_EQ(arg->expected_events, events);
149a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    fdevent_remove(&arg->fde);
150a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    if (++*(arg->happened_event_count) == 2) {
151022d447e9efcff59e22f0ab13764282116f235ddJosh Gao        fdevent_terminate_loop();
152a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    }
153a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui}
154a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui
155c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin Cuistatic void InvalidFdThreadFunc(void*) {
156a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    const int INVALID_READ_FD = std::numeric_limits<int>::max() - 1;
157a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    size_t happened_event_count = 0;
158a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    InvalidFdArg read_arg;
159a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    read_arg.expected_events = FDE_READ | FDE_ERROR;
160a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    read_arg.happened_event_count = &happened_event_count;
161a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    fdevent_install(&read_arg.fde, INVALID_READ_FD, InvalidFdEventCallback, &read_arg);
162a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    fdevent_add(&read_arg.fde, FDE_READ);
163a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui
164a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    const int INVALID_WRITE_FD = std::numeric_limits<int>::max();
165a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    InvalidFdArg write_arg;
166a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    write_arg.expected_events = FDE_READ | FDE_ERROR;
167a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    write_arg.happened_event_count = &happened_event_count;
168a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    fdevent_install(&write_arg.fde, INVALID_WRITE_FD, InvalidFdEventCallback, &write_arg);
169a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    fdevent_add(&write_arg.fde, FDE_WRITE);
170a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui    fdevent_loop();
171a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui}
172a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui
173c1b1f6ff5de82b457923eea3f0bbad1ac2e459d7Yabin CuiTEST_F(FdeventTest, invalid_fd) {
174022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    adb_thread_t thread;
175022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_TRUE(adb_thread_create(InvalidFdThreadFunc, nullptr, &thread));
176022d447e9efcff59e22f0ab13764282116f235ddJosh Gao    ASSERT_TRUE(adb_thread_join(thread));
177a10801674cb9e23ae549fb7f861cb33d8c629e80Yabin Cui}
178