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 #define LOG_TAG "AsyncIO_test.cpp"
17
18 #include <android-base/test_utils.h>
19 #include <fcntl.h>
20 #include <gtest/gtest.h>
21 #include <string>
22 #include <unistd.h>
23 #include <utils/Log.h>
24
25 #include "AsyncIO.h"
26
27 namespace android {
28
29 constexpr int TEST_PACKET_SIZE = 512;
30 constexpr int POOL_COUNT = 10;
31
32 static const std::string dummyDataStr =
33 "/*\n * Copyright 2015 The Android Open Source Project\n *\n * Licensed un"
34 "der the Apache License, Version 2.0 (the \"License\");\n * you may not us"
35 "e this file except in compliance with the License.\n * You may obtain a c"
36 "opy of the License at\n *\n * http://www.apache.org/licenses/LICENSE"
37 "-2.0\n *\n * Unless required by applicable law or agreed to in writing, s"
38 "oftware\n * distributed under the License is distributed on an \"AS IS\" "
39 "BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express o"
40 "r implied.\n * Se";
41
42
43 class AsyncIOTest : public ::testing::Test {
44 protected:
45 TemporaryFile dummy_file;
46
AsyncIOTest()47 AsyncIOTest() {}
~AsyncIOTest()48 ~AsyncIOTest() {}
49 };
50
TEST_F(AsyncIOTest,testRead)51 TEST_F(AsyncIOTest, testRead) {
52 char buf[TEST_PACKET_SIZE + 1];
53 buf[TEST_PACKET_SIZE] = '\0';
54 EXPECT_EQ(write(dummy_file.fd, dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE);
55 struct aiocb aio;
56 struct aiocb *aiol[] = {&aio};
57 aio.aio_fildes = dummy_file.fd;
58 aio.aio_buf = buf;
59 aio.aio_offset = 0;
60 aio.aio_nbytes = TEST_PACKET_SIZE;
61
62 EXPECT_EQ(aio_read(&aio), 0);
63 EXPECT_EQ(aio_suspend(aiol, 1, nullptr), 0);
64 EXPECT_EQ(aio_return(&aio), TEST_PACKET_SIZE);
65 EXPECT_STREQ(buf, dummyDataStr.c_str());
66 }
67
TEST_F(AsyncIOTest,testWrite)68 TEST_F(AsyncIOTest, testWrite) {
69 char buf[TEST_PACKET_SIZE + 1];
70 buf[TEST_PACKET_SIZE] = '\0';
71 struct aiocb aio;
72 struct aiocb *aiol[] = {&aio};
73 aio.aio_fildes = dummy_file.fd;
74 aio.aio_buf = const_cast<char*>(dummyDataStr.c_str());
75 aio.aio_offset = 0;
76 aio.aio_nbytes = TEST_PACKET_SIZE;
77
78 EXPECT_EQ(aio_write(&aio), 0);
79 EXPECT_EQ(aio_suspend(aiol, 1, nullptr), 0);
80 EXPECT_EQ(aio_return(&aio), TEST_PACKET_SIZE);
81 EXPECT_EQ(read(dummy_file.fd, buf, TEST_PACKET_SIZE), TEST_PACKET_SIZE);
82 EXPECT_STREQ(buf, dummyDataStr.c_str());
83 }
84
TEST_F(AsyncIOTest,testError)85 TEST_F(AsyncIOTest, testError) {
86 char buf[TEST_PACKET_SIZE + 1];
87 buf[TEST_PACKET_SIZE] = '\0';
88 struct aiocb aio;
89 struct aiocb *aiol[] = {&aio};
90 aio.aio_fildes = -1;
91 aio.aio_buf = const_cast<char*>(dummyDataStr.c_str());
92 aio.aio_offset = 0;
93 aio.aio_nbytes = TEST_PACKET_SIZE;
94
95 EXPECT_EQ(aio_write(&aio), 0);
96 EXPECT_EQ(aio_suspend(aiol, 1, nullptr), 0);
97 EXPECT_EQ(aio_return(&aio), -1);
98 EXPECT_EQ(aio_error(&aio), EBADF);
99 }
100
TEST_F(AsyncIOTest,testSpliceRead)101 TEST_F(AsyncIOTest, testSpliceRead) {
102 char buf[TEST_PACKET_SIZE + 1];
103 buf[TEST_PACKET_SIZE] = '\0';
104 int pipeFd[2];
105 EXPECT_EQ(pipe(pipeFd), 0);
106 EXPECT_EQ(write(dummy_file.fd, dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE);
107 struct aiocb aio;
108 struct aiocb *aiol[] = {&aio};
109 aio.aio_fildes = dummy_file.fd;
110 aio.aio_sink = pipeFd[1];
111 aio.aio_offset = 0;
112 aio.aio_nbytes = TEST_PACKET_SIZE;
113
114 EXPECT_EQ(aio_splice_read(&aio), 0);
115 EXPECT_EQ(aio_suspend(aiol, 1, nullptr), 0);
116 EXPECT_EQ(aio_return(&aio), TEST_PACKET_SIZE);
117
118 EXPECT_EQ(read(pipeFd[0], buf, TEST_PACKET_SIZE), TEST_PACKET_SIZE);
119 EXPECT_STREQ(buf, dummyDataStr.c_str());
120 }
121
TEST_F(AsyncIOTest,testSpliceWrite)122 TEST_F(AsyncIOTest, testSpliceWrite) {
123 char buf[TEST_PACKET_SIZE + 1];
124 buf[TEST_PACKET_SIZE] = '\0';
125 int pipeFd[2];
126 EXPECT_EQ(pipe(pipeFd), 0);
127 EXPECT_EQ(write(pipeFd[1], dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE);
128 struct aiocb aio;
129 struct aiocb *aiol[] = {&aio};
130 aio.aio_fildes = pipeFd[0];
131 aio.aio_sink = dummy_file.fd;
132 aio.aio_offset = 0;
133 aio.aio_nbytes = TEST_PACKET_SIZE;
134
135 EXPECT_EQ(aio_splice_write(&aio), 0);
136 EXPECT_EQ(aio_suspend(aiol, 1, nullptr), 0);
137 EXPECT_EQ(aio_return(&aio), TEST_PACKET_SIZE);
138 EXPECT_EQ(read(dummy_file.fd, buf, TEST_PACKET_SIZE), TEST_PACKET_SIZE);
139 EXPECT_STREQ(buf, dummyDataStr.c_str());
140 }
141
TEST_F(AsyncIOTest,testPoolWrite)142 TEST_F(AsyncIOTest, testPoolWrite) {
143 aio_pool_write_init();
144 char buf[TEST_PACKET_SIZE * POOL_COUNT + 1];
145 buf[TEST_PACKET_SIZE * POOL_COUNT] = '\0';
146
147 for (int i = 0; i < POOL_COUNT; i++) {
148 struct aiocb *aiop = new struct aiocb;
149 aiop->aio_fildes = dummy_file.fd;
150 aiop->aio_pool_buf = std::unique_ptr<char[]>(new char[TEST_PACKET_SIZE]);
151 memcpy(aiop->aio_pool_buf.get(), dummyDataStr.c_str(), TEST_PACKET_SIZE);
152 aiop->aio_offset = i * TEST_PACKET_SIZE;
153 aiop->aio_nbytes = TEST_PACKET_SIZE;
154 EXPECT_EQ(aio_pool_write(aiop), 0);
155 }
156 aio_pool_end();
157 EXPECT_EQ(read(dummy_file.fd, buf, TEST_PACKET_SIZE * POOL_COUNT), TEST_PACKET_SIZE * POOL_COUNT);
158
159 std::stringstream ss;
160 for (int i = 0; i < POOL_COUNT; i++)
161 ss << dummyDataStr;
162
163 EXPECT_STREQ(buf, ss.str().c_str());
164 }
165
TEST_F(AsyncIOTest,testSplicePoolWrite)166 TEST_F(AsyncIOTest, testSplicePoolWrite) {
167 aio_pool_splice_init();
168 char buf[TEST_PACKET_SIZE * POOL_COUNT + 1];
169 buf[TEST_PACKET_SIZE * POOL_COUNT] = '\0';
170
171 for (int i = 0; i < POOL_COUNT; i++) {
172 int pipeFd[2];
173 EXPECT_EQ(pipe(pipeFd), 0);
174 EXPECT_EQ(write(pipeFd[1], dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE);
175 struct aiocb *aiop = new struct aiocb;
176 aiop->aio_fildes = pipeFd[0];
177 aiop->aio_sink = dummy_file.fd;
178 aiop->aio_offset = i * TEST_PACKET_SIZE;
179 aiop->aio_nbytes = TEST_PACKET_SIZE;
180 EXPECT_EQ(aio_pool_write(aiop), 0);
181 }
182 aio_pool_end();
183 EXPECT_EQ(read(dummy_file.fd, buf, TEST_PACKET_SIZE * POOL_COUNT), TEST_PACKET_SIZE * POOL_COUNT);
184
185 std::stringstream ss;
186 for (int i = 0; i < POOL_COUNT; i++)
187 ss << dummyDataStr;
188
189 EXPECT_STREQ(buf, ss.str().c_str());
190 }
191
192 } // namespace android
193