blob: ba8b77a8bfacc03ef4d8210958459b9d07d4a399 [file] [log] [blame]
Yi Jin0a3406f2017-06-22 19:23:11 -07001// Copyright (C) 2017 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#define LOG_TAG "incidentd"
16
17#include "FdBuffer.h"
18
19#include <android-base/file.h>
20#include <android-base/test_utils.h>
21#include <gmock/gmock.h>
22#include <gtest/gtest.h>
23#include <signal.h>
24#include <string.h>
25
26const int READ_TIMEOUT = 5 * 1000;
27const int BUFFER_SIZE = 16 * 1024;
Yi Jinb44f7d42017-07-21 12:12:59 -070028const int QUICK_TIMEOUT_MS = 100;
Yi Jin0a3406f2017-06-22 19:23:11 -070029const std::string HEAD = "[OK]";
30
31using namespace android;
32using namespace android::base;
33using ::testing::StrEq;
34using ::testing::Test;
35using ::testing::internal::CaptureStdout;
36using ::testing::internal::GetCapturedStdout;
37
38class FdBufferTest : public Test {
39public:
40 virtual void SetUp() override {
41 ASSERT_NE(tf.fd, -1);
42 ASSERT_NE(p2cPipe.init(), -1);
43 ASSERT_NE(c2pPipe.init(), -1);
44 }
45
46 void AssertBufferReadSuccessful(size_t expected) {
47 EXPECT_EQ(buffer.size(), expected);
48 EXPECT_FALSE(buffer.timedOut());
49 EXPECT_FALSE(buffer.truncated());
50 }
51
52 void AssertBufferContent(const char* expected) {
53 ReportRequestSet requests;
54 requests.setMainFd(STDOUT_FILENO);
55
56 CaptureStdout();
57 ASSERT_EQ(NO_ERROR, buffer.write(&requests));
58 EXPECT_THAT(GetCapturedStdout(), StrEq(expected));
59 }
60
61 bool DoDataStream(int rFd, int wFd) {
62 char buf[BUFFER_SIZE];
63 ssize_t nRead;
64 while ((nRead = read(rFd, buf, BUFFER_SIZE)) > 0) {
65 ssize_t nWritten = 0;
66 while (nWritten < nRead) {
67 ssize_t amt = write(wFd, buf + nWritten, nRead - nWritten);
68 if (amt < 0) {
69 return false;
70 }
71 nWritten += amt;
72 }
73 }
74 return nRead == 0;
75 }
76
77protected:
78 FdBuffer buffer;
79 TemporaryFile tf;
80 Fpipe p2cPipe;
81 Fpipe c2pPipe;
82
83 const std::string kTestPath = GetExecutableDirectory();
84 const std::string kTestDataPath = kTestPath + "/testdata/";
85};
86
87TEST_F(FdBufferTest, ReadAndWrite) {
88 std::string testdata = "FdBuffer test string";
89 ASSERT_TRUE(WriteStringToFile(testdata, tf.path, false));
90 ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
91 AssertBufferReadSuccessful(testdata.size());
92 AssertBufferContent(testdata.c_str());
93}
94
95TEST_F(FdBufferTest, ReadTimeout) {
96 int pid = fork();
97 ASSERT_TRUE(pid != -1);
98
99 if (pid == 0) {
100 close(c2pPipe.readFd());
101 while(true) {
102 write(c2pPipe.writeFd(), "poo", 3);
103 sleep(1);
104 }
Yi Jinb44f7d42017-07-21 12:12:59 -0700105 _exit(EXIT_FAILURE);
Yi Jin0a3406f2017-06-22 19:23:11 -0700106 } else {
107 close(c2pPipe.writeFd());
108
Yi Jinb44f7d42017-07-21 12:12:59 -0700109 status_t status = buffer.read(c2pPipe.readFd(), QUICK_TIMEOUT_MS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700110 ASSERT_EQ(NO_ERROR, status);
111 EXPECT_TRUE(buffer.timedOut());
112
113 kill(pid, SIGKILL); // reap the child process
114 }
115}
116
117TEST_F(FdBufferTest, ReadInStreamAndWrite) {
118 std::string testdata = "simply test read in stream";
119 std::string expected = HEAD + testdata;
120 ASSERT_TRUE(WriteStringToFile(testdata, tf.path, false));
121
122 int pid = fork();
123 ASSERT_TRUE(pid != -1);
124
125 if (pid == 0) {
126 close(p2cPipe.writeFd());
127 close(c2pPipe.readFd());
128 ASSERT_TRUE(WriteStringToFd(HEAD, c2pPipe.writeFd()));
129 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
130 close(p2cPipe.readFd());
131 close(c2pPipe.writeFd());
132 // Must exit here otherwise the child process will continue executing the test binary.
Yi Jinb44f7d42017-07-21 12:12:59 -0700133 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700134 } else {
135 close(p2cPipe.readFd());
136 close(c2pPipe.writeFd());
137
138 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
139 p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
140 AssertBufferReadSuccessful(HEAD.size() + testdata.size());
141 AssertBufferContent(expected.c_str());
142 wait(&pid);
143 }
144}
145
146TEST_F(FdBufferTest, ReadInStreamAndWriteAllAtOnce) {
147 std::string testdata = "child process flushes only after all data are read.";
148 std::string expected = HEAD + testdata;
149 ASSERT_TRUE(WriteStringToFile(testdata, tf.path, false));
150
151 int pid = fork();
152 ASSERT_TRUE(pid != -1);
153
154 if (pid == 0) {
155 close(p2cPipe.writeFd());
156 close(c2pPipe.readFd());
157 std::string data;
158 // wait for read finishes then write.
159 ASSERT_TRUE(ReadFdToString(p2cPipe.readFd(), &data));
160 data = HEAD + data;
161 ASSERT_TRUE(WriteStringToFd(data, c2pPipe.writeFd()));
162 close(p2cPipe.readFd());
163 close(c2pPipe.writeFd());
164 // Must exit here otherwise the child process will continue executing the test binary.
Yi Jinb44f7d42017-07-21 12:12:59 -0700165 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700166 } else {
167 close(p2cPipe.readFd());
168 close(c2pPipe.writeFd());
169
170 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
171 p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
172 AssertBufferReadSuccessful(HEAD.size() + testdata.size());
173 AssertBufferContent(expected.c_str());
174 wait(&pid);
175 }
176}
177
178TEST_F(FdBufferTest, ReadInStreamEmpty) {
179 ASSERT_TRUE(WriteStringToFile("", tf.path, false));
180
181 int pid = fork();
182 ASSERT_TRUE(pid != -1);
183
184 if (pid == 0) {
185 close(p2cPipe.writeFd());
186 close(c2pPipe.readFd());
187 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
188 close(p2cPipe.readFd());
189 close(c2pPipe.writeFd());
Yi Jinb44f7d42017-07-21 12:12:59 -0700190 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700191 } else {
192 close(p2cPipe.readFd());
193 close(c2pPipe.writeFd());
194
195 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
196 p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
197 AssertBufferReadSuccessful(0);
198 AssertBufferContent("");
199 wait(&pid);
200 }
201}
202
203TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) {
204 const std::string testFile = kTestDataPath + "morethan4MB.txt";
George Burgess IV4e4a34b2017-07-31 11:09:10 -0700205 int fd = open(testFile.c_str(), O_RDONLY);
Yi Jin0a3406f2017-06-22 19:23:11 -0700206 ASSERT_NE(fd, -1);
207 int pid = fork();
208 ASSERT_TRUE(pid != -1);
209
210 if (pid == 0) {
211 close(p2cPipe.writeFd());
212 close(c2pPipe.readFd());
213 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
214 close(p2cPipe.readFd());
215 close(c2pPipe.writeFd());
Yi Jinb44f7d42017-07-21 12:12:59 -0700216 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700217 } else {
218 close(p2cPipe.readFd());
219 close(c2pPipe.writeFd());
220
221 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd,
222 p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
223 EXPECT_EQ(buffer.size(), (size_t) (4 * 1024 * 1024));
224 EXPECT_FALSE(buffer.timedOut());
225 EXPECT_TRUE(buffer.truncated());
226 wait(&pid);
227 }
228}
229
230TEST_F(FdBufferTest, ReadInStreamTimeOut) {
231 std::string testdata = "timeout test";
232 ASSERT_TRUE(WriteStringToFile(testdata, tf.path, false));
233
234 int pid = fork();
235 ASSERT_TRUE(pid != -1);
236
237 if (pid == 0) {
238 close(p2cPipe.writeFd());
239 close(c2pPipe.readFd());
240 while (true) {
241 sleep(1);
242 }
Yi Jinb44f7d42017-07-21 12:12:59 -0700243 _exit(EXIT_FAILURE);
Yi Jin0a3406f2017-06-22 19:23:11 -0700244 } else {
245 close(p2cPipe.readFd());
246 close(c2pPipe.writeFd());
247
248 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
Yi Jinb44f7d42017-07-21 12:12:59 -0700249 p2cPipe.writeFd(), c2pPipe.readFd(), QUICK_TIMEOUT_MS));
Yi Jin0a3406f2017-06-22 19:23:11 -0700250 EXPECT_TRUE(buffer.timedOut());
251 kill(pid, SIGKILL); // reap the child process
252 }
253}