blob: 7a05d7e071d0ef992311ed582a9d62d9dbcf815a [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 Jin4e843102018-02-14 15:36:18 -080014#define DEBUG false
Yi Jinb592e3b2018-02-01 15:17:04 -080015#include "Log.h"
Yi Jin0a3406f2017-06-22 19:23:11 -070016
17#include "FdBuffer.h"
Yi Jinb592e3b2018-02-01 15:17:04 -080018#include "incidentd_util.h"
Yi Jin0a3406f2017-06-22 19:23:11 -070019
20#include <android-base/file.h>
21#include <android-base/test_utils.h>
Yi Jin99c248f2017-08-25 18:11:58 -070022#include <fcntl.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070023#include <gtest/gtest.h>
24#include <signal.h>
25#include <string.h>
26
27const int READ_TIMEOUT = 5 * 1000;
28const int BUFFER_SIZE = 16 * 1024;
Yi Jinb44f7d42017-07-21 12:12:59 -070029const int QUICK_TIMEOUT_MS = 100;
Yi Jin0a3406f2017-06-22 19:23:11 -070030const std::string HEAD = "[OK]";
31
32using namespace android;
33using namespace android::base;
Yi Jin0a3406f2017-06-22 19:23:11 -070034using ::testing::Test;
Yi Jin0a3406f2017-06-22 19:23:11 -070035
36class FdBufferTest : public Test {
37public:
38 virtual void SetUp() override {
39 ASSERT_NE(tf.fd, -1);
40 ASSERT_NE(p2cPipe.init(), -1);
41 ASSERT_NE(c2pPipe.init(), -1);
42 }
43
44 void AssertBufferReadSuccessful(size_t expected) {
45 EXPECT_EQ(buffer.size(), expected);
46 EXPECT_FALSE(buffer.timedOut());
47 EXPECT_FALSE(buffer.truncated());
48 }
49
50 void AssertBufferContent(const char* expected) {
Yi Jinb592e3b2018-02-01 15:17:04 -080051 int i = 0;
Yi Jinc23fad22017-09-15 17:24:59 -070052 EncodedBuffer::iterator it = buffer.data();
53 while (it.hasNext()) {
54 ASSERT_EQ(it.next(), expected[i++]);
Yi Jin99c248f2017-08-25 18:11:58 -070055 }
Yi Jinc23fad22017-09-15 17:24:59 -070056 EXPECT_EQ(expected[i], '\0');
Yi Jin0a3406f2017-06-22 19:23:11 -070057 }
58
Yi Jine3dab2d2018-03-22 16:56:39 -070059 bool DoDataStream(const unique_fd& rFd, const unique_fd& wFd) {
Yi Jin0a3406f2017-06-22 19:23:11 -070060 char buf[BUFFER_SIZE];
61 ssize_t nRead;
Yi Jine3dab2d2018-03-22 16:56:39 -070062 while ((nRead = read(rFd.get(), buf, BUFFER_SIZE)) > 0) {
Yi Jin0a3406f2017-06-22 19:23:11 -070063 ssize_t nWritten = 0;
64 while (nWritten < nRead) {
Yi Jine3dab2d2018-03-22 16:56:39 -070065 ssize_t amt = write(wFd.get(), buf + nWritten, nRead - nWritten);
Yi Jin0a3406f2017-06-22 19:23:11 -070066 if (amt < 0) {
67 return false;
68 }
69 nWritten += amt;
70 }
71 }
72 return nRead == 0;
73 }
74
75protected:
76 FdBuffer buffer;
77 TemporaryFile tf;
78 Fpipe p2cPipe;
79 Fpipe c2pPipe;
80
81 const std::string kTestPath = GetExecutableDirectory();
82 const std::string kTestDataPath = kTestPath + "/testdata/";
83};
84
85TEST_F(FdBufferTest, ReadAndWrite) {
86 std::string testdata = "FdBuffer test string";
Wei Wang254102d2017-11-09 21:45:29 -080087 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jine3dab2d2018-03-22 16:56:39 -070088 ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
Yi Jin0a3406f2017-06-22 19:23:11 -070089 AssertBufferReadSuccessful(testdata.size());
90 AssertBufferContent(testdata.c_str());
91}
92
Yi Jin0ed9b682017-08-18 14:51:20 -070093TEST_F(FdBufferTest, IterateEmpty) {
Yi Jinc23fad22017-09-15 17:24:59 -070094 EncodedBuffer::iterator it = buffer.data();
95 EXPECT_FALSE(it.hasNext());
Yi Jin99c248f2017-08-25 18:11:58 -070096}
97
Yi Jin0ed9b682017-08-18 14:51:20 -070098TEST_F(FdBufferTest, ReadAndIterate) {
99 std::string testdata = "FdBuffer test string";
Wei Wang254102d2017-11-09 21:45:29 -0800100 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jine3dab2d2018-03-22 16:56:39 -0700101 ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
Yi Jin0ed9b682017-08-18 14:51:20 -0700102
Yi Jinb592e3b2018-02-01 15:17:04 -0800103 int i = 0;
Yi Jinc23fad22017-09-15 17:24:59 -0700104 EncodedBuffer::iterator it = buffer.data();
105 while (it.hasNext()) {
106 EXPECT_EQ(it.next(), (uint8_t)testdata[i++]);
Yi Jin0ed9b682017-08-18 14:51:20 -0700107 }
108
Yi Jinc23fad22017-09-15 17:24:59 -0700109 it.rp()->rewind();
110 it.rp()->move(buffer.size());
Yi Jin0ed9b682017-08-18 14:51:20 -0700111 EXPECT_EQ(it.bytesRead(), testdata.size());
Yi Jinc23fad22017-09-15 17:24:59 -0700112 EXPECT_FALSE(it.hasNext());
Yi Jin0ed9b682017-08-18 14:51:20 -0700113}
114
Yi Jin0a3406f2017-06-22 19:23:11 -0700115TEST_F(FdBufferTest, ReadTimeout) {
116 int pid = fork();
117 ASSERT_TRUE(pid != -1);
118
119 if (pid == 0) {
Yi Jin6355d2f2018-03-14 15:18:02 -0700120 c2pPipe.readFd().reset();
Yi Jinb592e3b2018-02-01 15:17:04 -0800121 while (true) {
Yi Jin0a3406f2017-06-22 19:23:11 -0700122 write(c2pPipe.writeFd(), "poo", 3);
123 sleep(1);
124 }
Yi Jinb44f7d42017-07-21 12:12:59 -0700125 _exit(EXIT_FAILURE);
Yi Jin0a3406f2017-06-22 19:23:11 -0700126 } else {
Yi Jin6355d2f2018-03-14 15:18:02 -0700127 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700128
Yi Jine3dab2d2018-03-22 16:56:39 -0700129 status_t status = buffer.read(c2pPipe.readFd().get(), QUICK_TIMEOUT_MS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700130 ASSERT_EQ(NO_ERROR, status);
131 EXPECT_TRUE(buffer.timedOut());
132
Yi Jinb592e3b2018-02-01 15:17:04 -0800133 kill(pid, SIGKILL); // reap the child process
Yi Jin0a3406f2017-06-22 19:23:11 -0700134 }
135}
136
137TEST_F(FdBufferTest, ReadInStreamAndWrite) {
138 std::string testdata = "simply test read in stream";
139 std::string expected = HEAD + testdata;
Wei Wang254102d2017-11-09 21:45:29 -0800140 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700141
142 int pid = fork();
143 ASSERT_TRUE(pid != -1);
144
145 if (pid == 0) {
Yi Jin6355d2f2018-03-14 15:18:02 -0700146 p2cPipe.writeFd().reset();
147 c2pPipe.readFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700148 ASSERT_TRUE(WriteStringToFd(HEAD, c2pPipe.writeFd()));
Yi Jine3dab2d2018-03-22 16:56:39 -0700149 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
Yi Jin6355d2f2018-03-14 15:18:02 -0700150 p2cPipe.readFd().reset();
151 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700152 // Must exit here otherwise the child process will continue executing the test binary.
Yi Jinb44f7d42017-07-21 12:12:59 -0700153 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700154 } else {
Yi Jin6355d2f2018-03-14 15:18:02 -0700155 p2cPipe.readFd().reset();
156 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700157
Yi Jine3dab2d2018-03-22 16:56:39 -0700158 ASSERT_EQ(NO_ERROR,
159 buffer.readProcessedDataInStream(tf.fd, std::move(p2cPipe.writeFd()),
160 std::move(c2pPipe.readFd()), READ_TIMEOUT));
Yi Jin0a3406f2017-06-22 19:23:11 -0700161 AssertBufferReadSuccessful(HEAD.size() + testdata.size());
162 AssertBufferContent(expected.c_str());
163 wait(&pid);
164 }
165}
166
167TEST_F(FdBufferTest, ReadInStreamAndWriteAllAtOnce) {
168 std::string testdata = "child process flushes only after all data are read.";
169 std::string expected = HEAD + testdata;
Wei Wang254102d2017-11-09 21:45:29 -0800170 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700171
172 int pid = fork();
173 ASSERT_TRUE(pid != -1);
174
175 if (pid == 0) {
Yi Jin6355d2f2018-03-14 15:18:02 -0700176 p2cPipe.writeFd().reset();
177 c2pPipe.readFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700178 std::string data;
179 // wait for read finishes then write.
180 ASSERT_TRUE(ReadFdToString(p2cPipe.readFd(), &data));
181 data = HEAD + data;
182 ASSERT_TRUE(WriteStringToFd(data, c2pPipe.writeFd()));
Yi Jin6355d2f2018-03-14 15:18:02 -0700183 p2cPipe.readFd().reset();
184 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700185 // Must exit here otherwise the child process will continue executing the test binary.
Yi Jinb44f7d42017-07-21 12:12:59 -0700186 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700187 } else {
Yi Jin6355d2f2018-03-14 15:18:02 -0700188 p2cPipe.readFd().reset();
189 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700190
Yi Jine3dab2d2018-03-22 16:56:39 -0700191 ASSERT_EQ(NO_ERROR,
192 buffer.readProcessedDataInStream(tf.fd, std::move(p2cPipe.writeFd()),
193 std::move(c2pPipe.readFd()), READ_TIMEOUT));
Yi Jin0a3406f2017-06-22 19:23:11 -0700194 AssertBufferReadSuccessful(HEAD.size() + testdata.size());
195 AssertBufferContent(expected.c_str());
196 wait(&pid);
197 }
198}
199
200TEST_F(FdBufferTest, ReadInStreamEmpty) {
Wei Wang254102d2017-11-09 21:45:29 -0800201 ASSERT_TRUE(WriteStringToFile("", tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700202
203 int pid = fork();
204 ASSERT_TRUE(pid != -1);
205
206 if (pid == 0) {
Yi Jin6355d2f2018-03-14 15:18:02 -0700207 p2cPipe.writeFd().reset();
208 c2pPipe.readFd().reset();
Yi Jine3dab2d2018-03-22 16:56:39 -0700209 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
Yi Jin6355d2f2018-03-14 15:18:02 -0700210 p2cPipe.readFd().reset();
211 c2pPipe.writeFd().reset();
Yi Jinb44f7d42017-07-21 12:12:59 -0700212 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700213 } else {
Yi Jin6355d2f2018-03-14 15:18:02 -0700214 p2cPipe.readFd().reset();
215 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700216
Yi Jine3dab2d2018-03-22 16:56:39 -0700217 ASSERT_EQ(NO_ERROR,
218 buffer.readProcessedDataInStream(tf.fd, std::move(p2cPipe.writeFd()),
219 std::move(c2pPipe.readFd()), READ_TIMEOUT));
Yi Jin0a3406f2017-06-22 19:23:11 -0700220 AssertBufferReadSuccessful(0);
221 AssertBufferContent("");
222 wait(&pid);
223 }
224}
225
226TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) {
227 const std::string testFile = kTestDataPath + "morethan4MB.txt";
Yi Jinb592e3b2018-02-01 15:17:04 -0800228 size_t fourMB = (size_t)4 * 1024 * 1024;
Yi Jin6355d2f2018-03-14 15:18:02 -0700229 unique_fd fd(open(testFile.c_str(), O_RDONLY | O_CLOEXEC));
230 ASSERT_NE(fd.get(), -1);
Yi Jin0a3406f2017-06-22 19:23:11 -0700231 int pid = fork();
232 ASSERT_TRUE(pid != -1);
233
234 if (pid == 0) {
Yi Jin6355d2f2018-03-14 15:18:02 -0700235 p2cPipe.writeFd().reset();
236 c2pPipe.readFd().reset();
Yi Jine3dab2d2018-03-22 16:56:39 -0700237 ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
Yi Jin6355d2f2018-03-14 15:18:02 -0700238 p2cPipe.readFd().reset();
239 c2pPipe.writeFd().reset();
Yi Jinb44f7d42017-07-21 12:12:59 -0700240 _exit(EXIT_SUCCESS);
Yi Jin0a3406f2017-06-22 19:23:11 -0700241 } else {
Yi Jin6355d2f2018-03-14 15:18:02 -0700242 p2cPipe.readFd().reset();
243 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700244
Yi Jine3dab2d2018-03-22 16:56:39 -0700245 ASSERT_EQ(NO_ERROR,
246 buffer.readProcessedDataInStream(fd, std::move(p2cPipe.writeFd()),
247 std::move(c2pPipe.readFd()), READ_TIMEOUT));
Yi Jin0ed9b682017-08-18 14:51:20 -0700248 EXPECT_EQ(buffer.size(), fourMB);
Yi Jin0a3406f2017-06-22 19:23:11 -0700249 EXPECT_FALSE(buffer.timedOut());
250 EXPECT_TRUE(buffer.truncated());
251 wait(&pid);
Yi Jinc23fad22017-09-15 17:24:59 -0700252 EncodedBuffer::iterator it = buffer.data();
253 it.rp()->move(fourMB);
Yi Jin0ed9b682017-08-18 14:51:20 -0700254 EXPECT_EQ(it.bytesRead(), fourMB);
Yi Jinc23fad22017-09-15 17:24:59 -0700255 EXPECT_FALSE(it.hasNext());
256
257 it.rp()->rewind();
258 while (it.hasNext()) {
Yi Jin0ed9b682017-08-18 14:51:20 -0700259 char c = 'A' + (it.bytesRead() % 64 / 8);
Yi Jinc23fad22017-09-15 17:24:59 -0700260 ASSERT_TRUE(it.next() == c);
Yi Jin0ed9b682017-08-18 14:51:20 -0700261 }
Yi Jin0a3406f2017-06-22 19:23:11 -0700262 }
263}
264
265TEST_F(FdBufferTest, ReadInStreamTimeOut) {
266 std::string testdata = "timeout test";
Wei Wang254102d2017-11-09 21:45:29 -0800267 ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
Yi Jin0a3406f2017-06-22 19:23:11 -0700268
269 int pid = fork();
270 ASSERT_TRUE(pid != -1);
271
272 if (pid == 0) {
Yi Jin6355d2f2018-03-14 15:18:02 -0700273 p2cPipe.writeFd().reset();
274 c2pPipe.readFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700275 while (true) {
276 sleep(1);
277 }
Yi Jinb44f7d42017-07-21 12:12:59 -0700278 _exit(EXIT_FAILURE);
Yi Jin0a3406f2017-06-22 19:23:11 -0700279 } else {
Yi Jin6355d2f2018-03-14 15:18:02 -0700280 p2cPipe.readFd().reset();
281 c2pPipe.writeFd().reset();
Yi Jin0a3406f2017-06-22 19:23:11 -0700282
Yi Jine3dab2d2018-03-22 16:56:39 -0700283 ASSERT_EQ(NO_ERROR,
284 buffer.readProcessedDataInStream(tf.fd, std::move(p2cPipe.writeFd()),
285 std::move(c2pPipe.readFd()), QUICK_TIMEOUT_MS));
Yi Jin0a3406f2017-06-22 19:23:11 -0700286 EXPECT_TRUE(buffer.timedOut());
Yi Jinb592e3b2018-02-01 15:17:04 -0800287 kill(pid, SIGKILL); // reap the child process
Yi Jin0a3406f2017-06-22 19:23:11 -0700288 }
289}