1 /*
2 +----------------------------------------------------------------------+
3 | Swoole |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 2.0 of the Apache license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.apache.org/licenses/LICENSE-2.0.html |
9 | If you did not receive a copy of the Apache2.0 license and are unable|
10 | to obtain it through the world-wide-web, please send a note to |
11 | license@swoole.com so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | @link https://www.swoole.com/ |
14 | @contact team@swoole.com |
15 | @license https://github.com/swoole/swoole-src/blob/master/LICENSE |
16 | @author Tianfeng Han <mikan.tenny@gmail.com> |
17 +----------------------------------------------------------------------+
18 */
19
20 #include "test_coroutine.h"
21 #include "swoole_file.h"
22 #include "swoole_util.h"
23
24 using swoole::Coroutine;
25 using swoole::String;
26 using swoole::coroutine::System;
27 using swoole::test::coroutine;
28
29 const char *host_1 = "www.baidu.com";
30 const char *host_2 = "www.xxxxxxxxxxxxxxxxxxxxx00000xxxxxxxxx----not_found.com";
31 static const char *test_file = "/tmp/swoole-core-test";
32
TEST(coroutine_hook,file)33 TEST(coroutine_hook, file) {
34 coroutine::run([](void *arg) {
35 char buf[8192];
36 size_t n_buf = sizeof(buf);
37 ASSERT_EQ(swoole_random_bytes(buf, n_buf), n_buf);
38
39 int fd = swoole_coroutine_open(test_file, O_WRONLY | O_TRUNC | O_CREAT, 0666);
40 ASSERT_EQ(swoole_coroutine_write(fd, buf, n_buf), n_buf);
41 swoole_coroutine_close(fd);
42
43 fd = swoole_coroutine_open(test_file, O_RDONLY, 0);
44 char data[8192];
45 ASSERT_EQ(swoole_coroutine_read(fd, data, n_buf), n_buf);
46 ASSERT_EQ(std::string(buf, n_buf), std::string(data, n_buf));
47 swoole_coroutine_close(fd);
48
49 ASSERT_EQ(swoole_coroutine_unlink(test_file), 0);
50 });
51 }
52
TEST(coroutine_hook,gethostbyname)53 TEST(coroutine_hook, gethostbyname) {
54 coroutine::run([](void *arg) {
55 auto result1 = swoole_coroutine_gethostbyname(host_1);
56 ASSERT_NE(result1, nullptr);
57
58 auto result2 = swoole_coroutine_gethostbyname(host_2);
59 ASSERT_EQ(result2, nullptr);
60 ASSERT_EQ(h_errno, HOST_NOT_FOUND);
61 });
62 }
63
TEST(coroutine_hook,getaddrinfo)64 TEST(coroutine_hook, getaddrinfo) {
65 coroutine::run([](void *arg) {
66 struct addrinfo hints;
67 sw_memset_zero(&hints, sizeof(struct addrinfo));
68 hints.ai_family = AF_INET;
69 hints.ai_socktype = SOCK_STREAM;
70 hints.ai_flags = AI_PASSIVE;
71
72 struct addrinfo *result, *curr;
73 int count;
74
75 result = nullptr;
76 auto result1 = swoole_coroutine_getaddrinfo(host_1, "http", &hints, &result);
77 ASSERT_EQ(result1, 0);
78
79 curr = result;
80 count = 0;
81 while (curr && curr->ai_addr) {
82 curr = curr->ai_next;
83 count++;
84 }
85 ASSERT_GE(count, 1);
86 freeaddrinfo(result);
87
88 result = nullptr;
89 auto result2 = swoole_coroutine_getaddrinfo(host_2, nullptr, &hints, &result);
90 ASSERT_EQ(result2, EAI_NONAME);
91 ASSERT_EQ(result, nullptr);
92 freeaddrinfo(result);
93 });
94 }
95
TEST(coroutine_hook,fstat)96 TEST(coroutine_hook, fstat) {
97 coroutine::run([](void *arg) {
98 int fd = swoole_coroutine_open(TEST_TMP_FILE, O_RDONLY, 0);
99 struct stat statbuf_1;
100 swoole_coroutine_fstat(fd, &statbuf_1);
101
102 struct stat statbuf_2;
103 fstat(fd, &statbuf_2);
104
105 ASSERT_EQ(memcmp(&statbuf_1, &statbuf_2, sizeof(statbuf_2)), 0);
106
107 swoole_coroutine_close(fd);
108 });
109 }
110
TEST(coroutine_hook,statvfs)111 TEST(coroutine_hook, statvfs) {
112 coroutine::run([](void *arg) {
113 struct statvfs statbuf_1;
114 swoole_coroutine_statvfs("/tmp", &statbuf_1);
115
116 struct statvfs statbuf_2;
117 statvfs("/tmp", &statbuf_2);
118
119 ASSERT_EQ(memcmp(&statbuf_1, &statbuf_2, sizeof(statbuf_2)), 0);
120 });
121 }
122
TEST(coroutine_hook,dir)123 TEST(coroutine_hook, dir) {
124 coroutine::run([](void *arg) {
125 ASSERT_EQ(swoole_coroutine_mkdir(TEST_TMP_DIR, 0666), 0);
126 ASSERT_EQ(swoole_coroutine_access(TEST_TMP_DIR, R_OK), 0);
127 ASSERT_EQ(swoole_coroutine_rmdir(TEST_TMP_DIR), 0);
128 ASSERT_EQ(access(TEST_TMP_DIR, R_OK), -1);
129 });
130 }
131
TEST(coroutine_hook,socket)132 TEST(coroutine_hook, socket) {
133 coroutine::run([](void *arg) {
134 int sock = swoole_coroutine_socket(AF_INET, SOCK_STREAM, 0);
135 ASSERT_GT(sock, 0);
136 swoole::network::Address sa;
137 std::string ip = System::gethostbyname("www.baidu.com", AF_INET, 10);
138 sa.assign(SW_SOCK_TCP, ip, 80);
139 ASSERT_EQ(swoole_coroutine_connect(sock, &sa.addr.ss, sa.len), 0);
140 ASSERT_EQ(swoole_coroutine_socket_wait_event(sock, SW_EVENT_WRITE, 5), SW_OK);
141
142 const char req[] = "GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\nKeepAlive: off\r\n\r\n";
143 ASSERT_EQ(swoole_coroutine_send(sock, req, strlen(req), 0), strlen(req));
144
145 swoole::String resp(1024);
146
147 while (1) {
148 ssize_t n = swoole_coroutine_recv(sock, resp.value() + resp.length, resp.size - resp.length, 0);
149 if (n <= 0) {
150 break;
151 }
152 resp.length += n;
153 if (resp.length == resp.size) {
154 resp.reserve(resp.size * 2);
155 }
156 }
157
158 ASSERT_GT(resp.length, 100);
159 ASSERT_TRUE(resp.contains("baidu.com"));
160 swoole_coroutine_close(sock);
161 });
162 }
163
TEST(coroutine_hook,rename)164 TEST(coroutine_hook, rename) {
165 coroutine::run([](void *arg) {
166 char buf[8192];
167 size_t n_buf = sizeof(buf);
168 ASSERT_EQ(swoole_random_bytes(buf, n_buf), n_buf);
169
170 int fd = swoole_coroutine_open(test_file, O_WRONLY | O_TRUNC | O_CREAT, 0666);
171 ASSERT_EQ(swoole_coroutine_write(fd, buf, n_buf), n_buf);
172 swoole_coroutine_close(fd);
173
174 std::string to_file_name = std::string(test_file, ".bak");
175 ASSERT_EQ(swoole_coroutine_rename(test_file, to_file_name.c_str()), 0);
176 ASSERT_EQ(access(TEST_TMP_DIR, F_OK), -1);
177 ASSERT_EQ(access(to_file_name.c_str(), F_OK), 0);
178
179 swoole_coroutine_unlink(to_file_name.c_str());
180 });
181 }
182
TEST(coroutine_hook,flock)183 TEST(coroutine_hook, flock) {
184 long start_time = swoole::time<std::chrono::milliseconds>();
185 coroutine::run([&](void *arg) {
186 swoole::Coroutine::create([&](void *arg) {
187 int fd = swoole_coroutine_open(TEST_TMP_FILE, O_WRONLY, 0);
188 ASSERT_EQ(swoole_coroutine_flock(fd, LOCK_EX), 0);
189 System::sleep(0.1);
190 ASSERT_EQ(swoole_coroutine_flock(fd, LOCK_UN), 0);
191
192 ASSERT_EQ(swoole_coroutine_flock(fd, LOCK_SH), 0);
193 ASSERT_EQ(swoole_coroutine_flock(fd, LOCK_UN), 0);
194 ASSERT_LE(swoole::time<std::chrono::milliseconds>() - start_time, 1000);
195 swoole_coroutine_close(fd);
196 });
197 swoole::Coroutine::create([&](void *arg) {
198 int fd = swoole_coroutine_open(TEST_TMP_FILE, O_WRONLY, 0);
199 ASSERT_EQ(swoole_coroutine_flock(fd, LOCK_SH), 0);
200 System::sleep(2);
201 ASSERT_EQ(swoole_coroutine_flock(fd, LOCK_UN), 0);
202 swoole_coroutine_close(fd);
203 });
204 });
205 // LOCK_NB
206 coroutine::run([](void *arg) {
207 int fd1 = swoole_coroutine_open(TEST_TMP_FILE, O_WRONLY, 0);
208 ASSERT_EQ(swoole_coroutine_flock(fd1, LOCK_EX), 0);
209 int fd2 = swoole_coroutine_open(TEST_TMP_FILE, O_WRONLY, 0);
210 ASSERT_EQ(swoole_coroutine_flock(fd2, LOCK_EX | LOCK_NB), -1);
211 ASSERT_EQ(swoole_coroutine_flock(fd1, LOCK_UN), 0);
212 swoole_coroutine_close(fd1);
213 swoole_coroutine_close(fd2);
214 });
215 }
216
TEST(coroutine_hook,read_dir)217 TEST(coroutine_hook, read_dir) {
218 auto fp = opendir("/tmp");
219 std::string dir1(readdir(fp)->d_name);
220 std::string dir2(readdir(fp)->d_name);
221 closedir(fp);
222
223 auto fn = [&]() {
224 auto fp = swoole_coroutine_opendir("/tmp");
225 ASSERT_NE(fp, nullptr);
226 struct dirent *entry;
227
228 entry = swoole_coroutine_readdir(fp);
229 ASSERT_NE(entry, nullptr);
230 ASSERT_STREQ(entry->d_name, dir1.c_str());
231
232 entry = swoole_coroutine_readdir(fp);
233 ASSERT_NE(entry, nullptr);
234 ASSERT_STREQ(entry->d_name, dir2.c_str());
235
236 swoole_coroutine_closedir(fp);
237 };
238
239 coroutine::run([&](void *arg) {
240 fn();
241 });
242 fn();
243 }
244
TEST(coroutine_hook,readlink)245 TEST(coroutine_hook, readlink) {
246 auto fn = []() {
247 char buf1[1024] = {};
248 char buf2[1024] = {};
249
250 auto retval = swoole_coroutine_readlink("/proc/self/cwd", buf1, sizeof(buf1));
251 ASSERT_NE(retval, -1);
252
253 getcwd(buf2, sizeof(buf2));
254 ASSERT_STREQ(buf1, buf2);
255 };
256
257 coroutine::run([&](void *arg) {
258 fn();
259 });
260 fn();
261 }
262
TEST(coroutine_hook,stdio_1)263 TEST(coroutine_hook, stdio_1) {
264 auto fn = []() {
265 FILE *fp1 = swoole_coroutine_fopen(test_file, "w+");
266 const char *str = "hello world";
267 int n = swoole_coroutine_fputs(str, fp1);
268 ASSERT_TRUE(n);
269 swoole_coroutine_fclose(fp1);
270
271 FILE *fp2 = swoole_coroutine_fopen(test_file, "r+");
272 char buf[1024];
273 char *str2 = swoole_coroutine_fgets(buf, sizeof(buf), fp2);
274
275 ASSERT_STREQ(str2, str);
276 swoole_coroutine_fclose(fp2);
277
278 unlink(test_file);
279 };
280
281 coroutine::run([&](void *arg) {
282 fn();
283 });
284 fn();
285 }
286
TEST(coroutine_hook,stdio_2)287 TEST(coroutine_hook, stdio_2) {
288 auto fn = []() {
289 size_t size = 1024;
290
291 FILE *fp1 = swoole_coroutine_fopen(test_file, "w+");
292 String str(size);
293 str.append_random_bytes(size);
294 size_t n = swoole_coroutine_fwrite(str.str, 1, size, fp1);
295 ASSERT_EQ(n, size);
296 swoole_coroutine_fclose(fp1);
297
298 FILE *fp2 = swoole_coroutine_fopen(test_file, "r+");
299 char buf[size];
300 size_t len = swoole_coroutine_fread(buf, 1, size, fp2);
301 ASSERT_EQ(len, size);
302
303 len = swoole_coroutine_fread(buf, 1, size, fp2);
304 ASSERT_EQ(len, 0);
305
306 ASSERT_TRUE(swoole_coroutine_feof(fp2));
307
308 ASSERT_MEMEQ(buf, str.str, size);
309 swoole_coroutine_fclose(fp2);
310
311 unlink(test_file);
312 };
313
314 coroutine::run([&](void *arg) {
315 fn();
316 });
317 fn();
318 }
319