blob: 956c8d39346a553627bc0d1215136bd47d1cb828 [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.
Yi Jinb592e3b2018-02-01 15:17:04 -080014#include "Log.h"
Yi Jin0a3406f2017-06-22 19:23:11 -070015
16#include "FdBuffer.h"
Yi Jinb592e3b2018-02-01 15:17:04 -080017#include "incidentd_util.h"
Yi Jin0a3406f2017-06-22 19:23:11 -070018
19#include <android-base/file.h>
20#include <android-base/test_utils.h>
Yi Jin99c248f2017-08-25 18:11:58 -070021#include <fcntl.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070022#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;
Yi Jin0a3406f2017-06-22 19:23:11 -070033using ::testing::Test;
Yi Jin0a3406f2017-06-22 19:23:11 -070034
35class FdBufferTest : public Test {
36public:
37 virtual void SetUp() override {
38 ASSERT_NE(tf.fd, -1);
39 ASSERT_NE(p2cPipe.init(), -1);
40 ASSERT_NE(c2pPipe.init(), -1);
41 }
42
43 void AssertBufferReadSuccessful(size_t expected) {
44 EXPECT_EQ(buffer.size(), expected);
45 EXPECT_FALSE(buffer.timedOut());
46 EXPECT_FALSE(buffer.truncated());
47 }
48
49 void AssertBufferContent(const char* expected) {
Yi Jinb592e3b2018-02-01 15:17:04 -080050 int i = 0;
Yi Jinc23fad22017-09-15 17:24:59 -070051 EncodedBuffer::iterator it = buffer.data();
52 while (it.hasNext()) {
53 ASSERT_EQ(it.next(), expected[i++]);
Yi Jin99c248f2017-08-25 18:11:58 -070054 }
Yi Jinc23fad22017-09-15 17:24:59 -070055 EXPECT_EQ(expected[i], '\0');
Yi Jin0a3406f2017-06-22 19:23:11 -070056 }
57
58 bool DoDataStream(int rFd, int wFd) {
59 char buf[BUFFER_SIZE];
60 ssize_t nRead;
61 while ((nRead = read(rFd, buf, BUFFER_SIZE)) > 0) {
62 ssize_t nWritten = 0;
63 while (nWritten < nRead) {
64 ssize_t amt = write(wFd, buf + nWritten, nRead - nWritten);
65 if (amt < 0) {
66 return false;
67 }
68 nWritten += amt;
69 }
70 }
71 return nRead == 0;
72 }
73
74protected:
75 FdBuffer buffer;
76 TemporaryFile tf;
77 Fpipe p2cPipe;
78 Fpipe c2pPipe;
79
80 const std::string kTestPath = GetExecutableDirectory();
81 const std::string kTestDataPath = kTestPath + "/testdata/";
82};
83
84TEST_F(FdBufferTest, ReadAndWrite) {
85 std::string testdata = "FdBuffer test string";
Wei Wang254102d2017-11-09 21:45:29 -080086 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -070087 ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
88 AssertBufferReadSuccessful(testdata.size());
89 AssertBufferContent(testdata.c_str());
90}
91
Yi Jin0ed9b682017-08-18 14:51:20 -070092TEST_F(FdBufferTest, IterateEmpty) {
Yi Jinc23fad22017-09-15 17:24:59 -070093 EncodedBuffer::iterator it = buffer.data();
94 EXPECT_FALSE(it.hasNext());
Yi Jin99c248f2017-08-25 18:11:58 -070095}
96
Yi Jin0ed9b682017-08-18 14:51:20 -070097TEST_F(FdBufferTest, ReadAndIterate) {
98 std::string testdata = "FdBuffer test string";
Wei Wang254102d2017-11-09 21:45:29 -080099 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0ed9b682017-08-18 14:51:20 -0700100 ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
101
Yi Jinb592e3b2018-02-01 15:17:04 -0800102 int i = 0;
Yi Jinc23fad22017-09-15 17:24:59 -0700103 EncodedBuffer::iterator it = buffer.data();
104 while (it.hasNext()) {
105 EXPECT_EQ(it.next(), (uint8_t)testdata[i++]);
Yi Jin0ed9b682017-08-18 14:51:20 -0700106 }
107
Yi Jinc23fad22017-09-15 17:24:59 -0700108 it.rp()->rewind();
109 it.rp()->move(buffer.size());
Yi Jin0ed9b682017-08-18 14:51:20 -0700110 EXPECT_EQ(it.bytesRead(), testdata.size());
Yi Jinc23fad22017-09-15 17:24:59 -0700111 EXPECT_FALSE(it.hasNext());
Yi Jin0ed9b682017-08-18 14:51:20 -0700112}
113
Yi Jin0a3406f2017-06-22 19:23:11 -0700114TEST_F(FdBufferTest, ReadTimeout) {
115 int pid = fork();
116 ASSERT_TRUE(pid != -1);
117
118 if (pid == 0) {
119 close(c2pPipe.readFd());
Yi Jinb592e3b2018-02-01 15:17:04 -0800120 while (true) {
Yi Jin0a3406f2017-06-22 19:23:11 -0700121 write(c2pPipe.writeFd(), "poo", 3);
122 sleep(1);
123 }
Yi Jinb44f7d42017-07-21 12:12:59 -0700124 _exit(EXIT_FAILURE);
Yi Jin0a3406f2017-06-22 19:23:11 -0700125 } else {
126 close(c2pPipe.writeFd());
127
Yi Jinb44f7d42017-07-21 12:12:59 -0700128 status_t status = buffer.read(c2pPipe.readFd(), QUICK_TIMEOUT_MS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700129 ASSERT_EQ(NO_ERROR, status);
130 EXPECT_TRUE(buffer.timedOut());
131
Yi Jinb592e3b2018-02-01 15:17:04 -0800132 kill(pid, SIGKILL); // reap the child process
Yi Jin0a3406f2017-06-22 19:23:11 -0700133 }
134}
135
136TEST_F(FdBufferTest, ReadInStreamAndWrite) {
137 std::string testdata = "simply test read in stream";
138 std::string expected = HEAD + testdata;
Wei Wang254102d2017-11-09 21:45:29 -0800139 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700140
141 int pid = fork();
142 ASSERT_TRUE(pid != -1);
143
144 if (pid == 0) {
145 close(p2cPipe.writeFd());
146 close(c2pPipe.readFd());
147 ASSERT_TRUE(WriteStringToFd(HEAD, c2pPipe.writeFd()));
148 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
149 close(p2cPipe.readFd());
150 close(c2pPipe.writeFd());
151 // Must exit here otherwise the child process will continue executing the test binary.
Yi Jinb44f7d42017-07-21 12:12:59 -0700152 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700153 } else {
154 close(p2cPipe.readFd());
155 close(c2pPipe.writeFd());
156
Yi Jinb592e3b2018-02-01 15:17:04 -0800157 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
158 c2pPipe.readFd(), READ_TIMEOUT));
Yi Jin0a3406f2017-06-22 19:23:11 -0700159 AssertBufferReadSuccessful(HEAD.size() + testdata.size());
160 AssertBufferContent(expected.c_str());
161 wait(&pid);
162 }
163}
164
165TEST_F(FdBufferTest, ReadInStreamAndWriteAllAtOnce) {
166 std::string testdata = "child process flushes only after all data are read.";
167 std::string expected = HEAD + testdata;
Wei Wang254102d2017-11-09 21:45:29 -0800168 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700169
170 int pid = fork();
171 ASSERT_TRUE(pid != -1);
172
173 if (pid == 0) {
174 close(p2cPipe.writeFd());
175 close(c2pPipe.readFd());
176 std::string data;
177 // wait for read finishes then write.
178 ASSERT_TRUE(ReadFdToString(p2cPipe.readFd(), &data));
179 data = HEAD + data;
180 ASSERT_TRUE(WriteStringToFd(data, c2pPipe.writeFd()));
181 close(p2cPipe.readFd());
182 close(c2pPipe.writeFd());
183 // Must exit here otherwise the child process will continue executing the test binary.
Yi Jinb44f7d42017-07-21 12:12:59 -0700184 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700185 } else {
186 close(p2cPipe.readFd());
187 close(c2pPipe.writeFd());
188
Yi Jinb592e3b2018-02-01 15:17:04 -0800189 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
190 c2pPipe.readFd(), READ_TIMEOUT));
Yi Jin0a3406f2017-06-22 19:23:11 -0700191 AssertBufferReadSuccessful(HEAD.size() + testdata.size());
192 AssertBufferContent(expected.c_str());
193 wait(&pid);
194 }
195}
196
197TEST_F(FdBufferTest, ReadInStreamEmpty) {
Wei Wang254102d2017-11-09 21:45:29 -0800198 ASSERT_TRUE(WriteStringToFile("", tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700199
200 int pid = fork();
201 ASSERT_TRUE(pid != -1);
202
203 if (pid == 0) {
204 close(p2cPipe.writeFd());
205 close(c2pPipe.readFd());
206 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
207 close(p2cPipe.readFd());
208 close(c2pPipe.writeFd());
Yi Jinb44f7d42017-07-21 12:12:59 -0700209 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700210 } else {
211 close(p2cPipe.readFd());
212 close(c2pPipe.writeFd());
213
Yi Jinb592e3b2018-02-01 15:17:04 -0800214 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
215 c2pPipe.readFd(), READ_TIMEOUT));
Yi Jin0a3406f2017-06-22 19:23:11 -0700216 AssertBufferReadSuccessful(0);
217 AssertBufferContent("");
218 wait(&pid);
219 }
220}
221
222TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) {
223 const std::string testFile = kTestDataPath + "morethan4MB.txt";
Yi Jinb592e3b2018-02-01 15:17:04 -0800224 size_t fourMB = (size_t)4 * 1024 * 1024;
Yi Jin99c248f2017-08-25 18:11:58 -0700225 int fd = open(testFile.c_str(), O_RDONLY | O_CLOEXEC);
Yi Jin0a3406f2017-06-22 19:23:11 -0700226 ASSERT_NE(fd, -1);
227 int pid = fork();
228 ASSERT_TRUE(pid != -1);
229
230 if (pid == 0) {
231 close(p2cPipe.writeFd());
232 close(c2pPipe.readFd());
233 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
234 close(p2cPipe.readFd());
235 close(c2pPipe.writeFd());
Yi Jinb44f7d42017-07-21 12:12:59 -0700236 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700237 } else {
238 close(p2cPipe.readFd());
239 close(c2pPipe.writeFd());
240
Yi Jinb592e3b2018-02-01 15:17:04 -0800241 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(),
242 c2pPipe.readFd(), READ_TIMEOUT));
Yi Jin0ed9b682017-08-18 14:51:20 -0700243 EXPECT_EQ(buffer.size(), fourMB);
Yi Jin0a3406f2017-06-22 19:23:11 -0700244 EXPECT_FALSE(buffer.timedOut());
245 EXPECT_TRUE(buffer.truncated());
246 wait(&pid);
Yi Jinc23fad22017-09-15 17:24:59 -0700247 EncodedBuffer::iterator it = buffer.data();
248 it.rp()->move(fourMB);
Yi Jin0ed9b682017-08-18 14:51:20 -0700249 EXPECT_EQ(it.bytesRead(), fourMB);
Yi Jinc23fad22017-09-15 17:24:59 -0700250 EXPECT_FALSE(it.hasNext());
251
252 it.rp()->rewind();
253 while (it.hasNext()) {
Yi Jin0ed9b682017-08-18 14:51:20 -0700254 char c = 'A' + (it.bytesRead() % 64 / 8);
Yi Jinc23fad22017-09-15 17:24:59 -0700255 ASSERT_TRUE(it.next() == c);
Yi Jin0ed9b682017-08-18 14:51:20 -0700256 }
Yi Jin0a3406f2017-06-22 19:23:11 -0700257 }
258}
259
260TEST_F(FdBufferTest, ReadInStreamTimeOut) {
261 std::string testdata = "timeout test";
Wei Wang254102d2017-11-09 21:45:29 -0800262 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700263
264 int pid = fork();
265 ASSERT_TRUE(pid != -1);
266
267 if (pid == 0) {
268 close(p2cPipe.writeFd());
269 close(c2pPipe.readFd());
270 while (true) {
271 sleep(1);
272 }
Yi Jinb44f7d42017-07-21 12:12:59 -0700273 _exit(EXIT_FAILURE);
Yi Jin0a3406f2017-06-22 19:23:11 -0700274 } else {
275 close(p2cPipe.readFd());
276 close(c2pPipe.writeFd());
277
Yi Jinb592e3b2018-02-01 15:17:04 -0800278 ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
279 c2pPipe.readFd(), QUICK_TIMEOUT_MS));
Yi Jin0a3406f2017-06-22 19:23:11 -0700280 EXPECT_TRUE(buffer.timedOut());
Yi Jinb592e3b2018-02-01 15:17:04 -0800281 kill(pid, SIGKILL); // reap the child process
Yi Jin0a3406f2017-06-22 19:23:11 -0700282 }
283}