1 //
2 // Copyright 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 "async_manager.h"
18 #include <gtest/gtest.h>
19 #include <cstdint>
20 #include <cstring>
21 #include <vector>
22
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 namespace test_vendor_lib {
30
31 class AsyncManagerSocketTest : public ::testing::Test {
32 public:
33 static const uint16_t kPort = 6111;
34 static const size_t kBufferSize = 16;
35
CheckBufferEquals()36 bool CheckBufferEquals() {
37 return strcmp(server_buffer_, client_buffer_) == 0;
38 }
39
40 protected:
StartServer()41 int StartServer() {
42 struct sockaddr_in serv_addr;
43 int fd = socket(AF_INET, SOCK_STREAM, 0);
44 EXPECT_FALSE(fd < 0);
45
46 memset(&serv_addr, 0, sizeof(serv_addr));
47 serv_addr.sin_family = AF_INET;
48 serv_addr.sin_addr.s_addr = INADDR_ANY;
49 serv_addr.sin_port = htons(kPort);
50 int reuse_flag = 1;
51 EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag,
52 sizeof(reuse_flag)) < 0);
53 EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0);
54
55 listen(fd, 1);
56 return fd;
57 }
58
AcceptConnection(int fd)59 int AcceptConnection(int fd) {
60 struct sockaddr_in cli_addr;
61 memset(&cli_addr, 0, sizeof(cli_addr));
62 socklen_t clilen = sizeof(cli_addr);
63
64 int connection_fd = accept(fd, (struct sockaddr*)&cli_addr, &clilen);
65 EXPECT_FALSE(connection_fd < 0);
66
67 return connection_fd;
68 }
69
ReadIncomingMessage(int fd)70 void ReadIncomingMessage(int fd) {
71 int n = TEMP_FAILURE_RETRY(read(fd, server_buffer_, kBufferSize - 1));
72 EXPECT_FALSE(n < 0);
73
74 if (n == 0) { // got EOF
75 async_manager_.StopWatchingFileDescriptor(fd);
76 close(fd);
77 } else {
78 n = write(fd, "1", 1);
79 }
80 }
81
SetUp()82 void SetUp() override {
83 memset(server_buffer_, 0, kBufferSize);
84
85 socket_fd_ = StartServer();
86
87 async_manager_.WatchFdForNonBlockingReads(socket_fd_, [this](int fd) {
88 int connection_fd = AcceptConnection(fd);
89
90 async_manager_.WatchFdForNonBlockingReads(
91 connection_fd, [this](int fd) { ReadIncomingMessage(fd); });
92 });
93 }
94
TearDown()95 void TearDown() override {
96 async_manager_.StopWatchingFileDescriptor(socket_fd_);
97 close(socket_fd_);
98 EXPECT_TRUE(CheckBufferEquals());
99 }
100
ConnectClient()101 int ConnectClient() {
102 int socket_cli_fd = socket(AF_INET, SOCK_STREAM, 0);
103 EXPECT_FALSE(socket_cli_fd < 0);
104
105 struct hostent* server;
106 server = gethostbyname("localhost");
107 EXPECT_FALSE(server == NULL);
108
109 struct sockaddr_in serv_addr;
110 memset((void*)&serv_addr, 0, sizeof(serv_addr));
111 serv_addr.sin_family = AF_INET;
112 serv_addr.sin_addr.s_addr = *(reinterpret_cast<in_addr_t*>(server->h_addr));
113 serv_addr.sin_port = htons(kPort);
114
115 int result =
116 connect(socket_cli_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
117 EXPECT_FALSE(result < 0);
118
119 return socket_cli_fd;
120 }
121
WriteFromClient(int socket_cli_fd)122 void WriteFromClient(int socket_cli_fd) {
123 strcpy(client_buffer_, "1");
124 int n = write(socket_cli_fd, client_buffer_, strlen(client_buffer_));
125 EXPECT_TRUE(n > 0);
126 }
127
AwaitServerResponse(int socket_cli_fd)128 void AwaitServerResponse(int socket_cli_fd) {
129 int n = read(socket_cli_fd, client_buffer_, 1);
130 EXPECT_TRUE(n > 0);
131 }
132
133 private:
134 AsyncManager async_manager_;
135 int socket_fd_;
136 char server_buffer_[kBufferSize];
137 char client_buffer_[kBufferSize];
138 };
139
TEST_F(AsyncManagerSocketTest,TestOneConnection)140 TEST_F(AsyncManagerSocketTest, TestOneConnection) {
141 int socket_cli_fd = ConnectClient();
142
143 WriteFromClient(socket_cli_fd);
144
145 AwaitServerResponse(socket_cli_fd);
146
147 close(socket_cli_fd);
148 }
149
TEST_F(AsyncManagerSocketTest,TestRepeatedConnections)150 TEST_F(AsyncManagerSocketTest, TestRepeatedConnections) {
151 static const int num_connections = 300;
152 for (int i = 0; i < num_connections; i++) {
153 int socket_cli_fd = ConnectClient();
154 WriteFromClient(socket_cli_fd);
155 AwaitServerResponse(socket_cli_fd);
156 close(socket_cli_fd);
157 }
158 }
159
TEST_F(AsyncManagerSocketTest,TestMultipleConnections)160 TEST_F(AsyncManagerSocketTest, TestMultipleConnections) {
161 static const int num_connections = 300;
162 int socket_cli_fd[num_connections];
163 for (int i = 0; i < num_connections; i++) {
164 socket_cli_fd[i] = ConnectClient();
165 EXPECT_TRUE(socket_cli_fd[i] > 0);
166 WriteFromClient(socket_cli_fd[i]);
167 }
168 for (int i = 0; i < num_connections; i++) {
169 AwaitServerResponse(socket_cli_fd[i]);
170 close(socket_cli_fd[i]);
171 }
172 }
173
174 } // namespace test_vendor_lib
175