Mercurial
comparison third_party/libuv/test/test-fs-readdir.c @ 160:948de3f54cea
[ThirdParty] Added libuv
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Wed, 14 Jan 2026 19:39:52 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 159:05cf9467a1c3 | 160:948de3f54cea |
|---|---|
| 1 /* Copyright libuv project contributors. All rights reserved. | |
| 2 * | |
| 3 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 4 * of this software and associated documentation files (the "Software"), to | |
| 5 * deal in the Software without restriction, including without limitation the | |
| 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
| 7 * sell copies of the Software, and to permit persons to whom the Software is | |
| 8 * furnished to do so, subject to the following conditions: | |
| 9 * | |
| 10 * The above copyright notice and this permission notice shall be included in | |
| 11 * all copies or substantial portions of the Software. | |
| 12 * | |
| 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 19 * IN THE SOFTWARE. | |
| 20 */ | |
| 21 | |
| 22 #include "uv.h" | |
| 23 #include "task.h" | |
| 24 #include <fcntl.h> | |
| 25 #include <string.h> | |
| 26 | |
| 27 static uv_fs_t opendir_req; | |
| 28 static uv_fs_t readdir_req; | |
| 29 static uv_fs_t closedir_req; | |
| 30 | |
| 31 static uv_dirent_t dirents[1]; | |
| 32 static uv_dirent_t symlink_dirents[2]; | |
| 33 | |
| 34 static int empty_opendir_cb_count; | |
| 35 static int empty_closedir_cb_count; | |
| 36 | |
| 37 static void cleanup_test_files(void) { | |
| 38 uv_fs_t req; | |
| 39 | |
| 40 uv_fs_unlink(NULL, &req, "test_dir/file1", NULL); | |
| 41 uv_fs_req_cleanup(&req); | |
| 42 uv_fs_unlink(NULL, &req, "test_dir/file2", NULL); | |
| 43 uv_fs_req_cleanup(&req); | |
| 44 uv_fs_rmdir(NULL, &req, "test_dir/test_subdir", NULL); | |
| 45 uv_fs_req_cleanup(&req); | |
| 46 uv_fs_rmdir(NULL, &req, "test_dir", NULL); | |
| 47 uv_fs_req_cleanup(&req); | |
| 48 } | |
| 49 | |
| 50 static void empty_closedir_cb(uv_fs_t* req) { | |
| 51 ASSERT_PTR_EQ(req, &closedir_req); | |
| 52 ASSERT_EQ(req->fs_type, UV_FS_CLOSEDIR); | |
| 53 ASSERT_OK(req->result); | |
| 54 ++empty_closedir_cb_count; | |
| 55 uv_fs_req_cleanup(req); | |
| 56 } | |
| 57 | |
| 58 static void empty_readdir_cb(uv_fs_t* req) { | |
| 59 uv_dir_t* dir; | |
| 60 int r; | |
| 61 | |
| 62 ASSERT_PTR_EQ(req, &readdir_req); | |
| 63 ASSERT_EQ(req->fs_type, UV_FS_READDIR); | |
| 64 ASSERT_OK(req->result); | |
| 65 dir = req->ptr; | |
| 66 uv_fs_req_cleanup(req); | |
| 67 r = uv_fs_closedir(uv_default_loop(), | |
| 68 &closedir_req, | |
| 69 dir, | |
| 70 empty_closedir_cb); | |
| 71 ASSERT_OK(r); | |
| 72 } | |
| 73 | |
| 74 static void empty_opendir_cb(uv_fs_t* req) { | |
| 75 uv_dir_t* dir; | |
| 76 int r; | |
| 77 | |
| 78 ASSERT_PTR_EQ(req, &opendir_req); | |
| 79 ASSERT_EQ(req->fs_type, UV_FS_OPENDIR); | |
| 80 ASSERT_OK(req->result); | |
| 81 ASSERT_NOT_NULL(req->ptr); | |
| 82 dir = req->ptr; | |
| 83 dir->dirents = dirents; | |
| 84 dir->nentries = ARRAY_SIZE(dirents); | |
| 85 r = uv_fs_readdir(uv_default_loop(), | |
| 86 &readdir_req, | |
| 87 dir, | |
| 88 empty_readdir_cb); | |
| 89 ASSERT_OK(r); | |
| 90 uv_fs_req_cleanup(req); | |
| 91 ++empty_opendir_cb_count; | |
| 92 } | |
| 93 | |
| 94 /* | |
| 95 * This test makes sure that both synchronous and asynchronous flavors | |
| 96 * of the uv_fs_opendir() -> uv_fs_readdir() -> uv_fs_closedir() sequence work | |
| 97 * as expected when processing an empty directory. | |
| 98 */ | |
| 99 TEST_IMPL(fs_readdir_empty_dir) { | |
| 100 const char* path; | |
| 101 uv_fs_t mkdir_req; | |
| 102 uv_fs_t rmdir_req; | |
| 103 int r; | |
| 104 int nb_entries_read; | |
| 105 uv_dir_t* dir; | |
| 106 | |
| 107 path = "./empty_dir/"; | |
| 108 uv_fs_mkdir(uv_default_loop(), &mkdir_req, path, 0777, NULL); | |
| 109 uv_fs_req_cleanup(&mkdir_req); | |
| 110 | |
| 111 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 112 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 113 | |
| 114 /* Testing the synchronous flavor. */ | |
| 115 r = uv_fs_opendir(uv_default_loop(), | |
| 116 &opendir_req, | |
| 117 path, | |
| 118 NULL); | |
| 119 ASSERT_OK(r); | |
| 120 ASSERT_EQ(opendir_req.fs_type, UV_FS_OPENDIR); | |
| 121 ASSERT_OK(opendir_req.result); | |
| 122 ASSERT_NOT_NULL(opendir_req.ptr); | |
| 123 dir = opendir_req.ptr; | |
| 124 uv_fs_req_cleanup(&opendir_req); | |
| 125 | |
| 126 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 127 memset(&readdir_req, 0xdb, sizeof(readdir_req)); | |
| 128 dir->dirents = dirents; | |
| 129 dir->nentries = ARRAY_SIZE(dirents); | |
| 130 nb_entries_read = uv_fs_readdir(uv_default_loop(), | |
| 131 &readdir_req, | |
| 132 dir, | |
| 133 NULL); | |
| 134 ASSERT_OK(nb_entries_read); | |
| 135 uv_fs_req_cleanup(&readdir_req); | |
| 136 | |
| 137 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 138 memset(&closedir_req, 0xdb, sizeof(closedir_req)); | |
| 139 uv_fs_closedir(uv_default_loop(), &closedir_req, dir, NULL); | |
| 140 ASSERT_OK(closedir_req.result); | |
| 141 uv_fs_req_cleanup(&closedir_req); | |
| 142 | |
| 143 /* Testing the asynchronous flavor. */ | |
| 144 | |
| 145 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 146 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 147 memset(&readdir_req, 0xdb, sizeof(readdir_req)); | |
| 148 memset(&closedir_req, 0xdb, sizeof(closedir_req)); | |
| 149 | |
| 150 r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, empty_opendir_cb); | |
| 151 ASSERT_OK(r); | |
| 152 ASSERT_OK(empty_opendir_cb_count); | |
| 153 ASSERT_OK(empty_closedir_cb_count); | |
| 154 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); | |
| 155 ASSERT_OK(r); | |
| 156 ASSERT_EQ(1, empty_opendir_cb_count); | |
| 157 ASSERT_EQ(1, empty_closedir_cb_count); | |
| 158 uv_fs_rmdir(uv_default_loop(), &rmdir_req, path, NULL); | |
| 159 uv_fs_req_cleanup(&rmdir_req); | |
| 160 MAKE_VALGRIND_HAPPY(uv_default_loop()); | |
| 161 return 0; | |
| 162 } | |
| 163 | |
| 164 /* | |
| 165 * This test makes sure that reading a non-existing directory with | |
| 166 * uv_fs_{open,read}_dir() returns proper error codes. | |
| 167 */ | |
| 168 | |
| 169 static int non_existing_opendir_cb_count; | |
| 170 | |
| 171 static void non_existing_opendir_cb(uv_fs_t* req) { | |
| 172 ASSERT_PTR_EQ(req, &opendir_req); | |
| 173 ASSERT_EQ(req->fs_type, UV_FS_OPENDIR); | |
| 174 ASSERT_EQ(req->result, UV_ENOENT); | |
| 175 ASSERT_NULL(req->ptr); | |
| 176 | |
| 177 uv_fs_req_cleanup(req); | |
| 178 ++non_existing_opendir_cb_count; | |
| 179 } | |
| 180 | |
| 181 TEST_IMPL(fs_readdir_non_existing_dir) { | |
| 182 const char* path; | |
| 183 int r; | |
| 184 | |
| 185 path = "./non-existing-dir/"; | |
| 186 | |
| 187 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 188 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 189 | |
| 190 /* Testing the synchronous flavor. */ | |
| 191 r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, NULL); | |
| 192 ASSERT_EQ(r, UV_ENOENT); | |
| 193 ASSERT_EQ(opendir_req.fs_type, UV_FS_OPENDIR); | |
| 194 ASSERT_EQ(opendir_req.result, UV_ENOENT); | |
| 195 ASSERT_NULL(opendir_req.ptr); | |
| 196 uv_fs_req_cleanup(&opendir_req); | |
| 197 | |
| 198 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 199 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 200 | |
| 201 /* Testing the async flavor. */ | |
| 202 r = uv_fs_opendir(uv_default_loop(), | |
| 203 &opendir_req, | |
| 204 path, | |
| 205 non_existing_opendir_cb); | |
| 206 ASSERT_OK(r); | |
| 207 ASSERT_OK(non_existing_opendir_cb_count); | |
| 208 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); | |
| 209 ASSERT_OK(r); | |
| 210 ASSERT_EQ(1, non_existing_opendir_cb_count); | |
| 211 | |
| 212 MAKE_VALGRIND_HAPPY(uv_default_loop()); | |
| 213 return 0; | |
| 214 } | |
| 215 | |
| 216 /* | |
| 217 * This test makes sure that reading a file as a directory reports correct | |
| 218 * error codes. | |
| 219 */ | |
| 220 | |
| 221 static int file_opendir_cb_count; | |
| 222 | |
| 223 static void file_opendir_cb(uv_fs_t* req) { | |
| 224 ASSERT_PTR_EQ(req, &opendir_req); | |
| 225 ASSERT_EQ(req->fs_type, UV_FS_OPENDIR); | |
| 226 ASSERT_EQ(req->result, UV_ENOTDIR); | |
| 227 ASSERT_NULL(req->ptr); | |
| 228 | |
| 229 uv_fs_req_cleanup(req); | |
| 230 ++file_opendir_cb_count; | |
| 231 } | |
| 232 | |
| 233 TEST_IMPL(fs_readdir_file) { | |
| 234 const char* path; | |
| 235 int r; | |
| 236 | |
| 237 path = "test/fixtures/empty_file"; | |
| 238 | |
| 239 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 240 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 241 | |
| 242 /* Testing the synchronous flavor. */ | |
| 243 r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, NULL); | |
| 244 | |
| 245 ASSERT_EQ(r, UV_ENOTDIR); | |
| 246 ASSERT_EQ(opendir_req.fs_type, UV_FS_OPENDIR); | |
| 247 ASSERT_EQ(opendir_req.result, UV_ENOTDIR); | |
| 248 ASSERT_NULL(opendir_req.ptr); | |
| 249 | |
| 250 uv_fs_req_cleanup(&opendir_req); | |
| 251 | |
| 252 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 253 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 254 | |
| 255 /* Testing the async flavor. */ | |
| 256 r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, file_opendir_cb); | |
| 257 ASSERT_OK(r); | |
| 258 ASSERT_OK(file_opendir_cb_count); | |
| 259 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); | |
| 260 ASSERT_OK(r); | |
| 261 ASSERT_EQ(1, file_opendir_cb_count); | |
| 262 MAKE_VALGRIND_HAPPY(uv_default_loop()); | |
| 263 return 0; | |
| 264 } | |
| 265 | |
| 266 /* | |
| 267 * This test makes sure that reading a non-empty directory with | |
| 268 * uv_fs_{open,read}_dir() returns proper directory entries, including the | |
| 269 * correct entry types. | |
| 270 */ | |
| 271 | |
| 272 static int non_empty_opendir_cb_count; | |
| 273 static int non_empty_readdir_cb_count; | |
| 274 static int non_empty_closedir_cb_count; | |
| 275 | |
| 276 static void non_empty_closedir_cb(uv_fs_t* req) { | |
| 277 ASSERT_PTR_EQ(req, &closedir_req); | |
| 278 ASSERT_OK(req->result); | |
| 279 uv_fs_req_cleanup(req); | |
| 280 ++non_empty_closedir_cb_count; | |
| 281 } | |
| 282 | |
| 283 static void non_empty_readdir_cb(uv_fs_t* req) { | |
| 284 uv_dir_t* dir; | |
| 285 | |
| 286 ASSERT_PTR_EQ(req, &readdir_req); | |
| 287 ASSERT_EQ(req->fs_type, UV_FS_READDIR); | |
| 288 dir = req->ptr; | |
| 289 | |
| 290 if (req->result == 0) { | |
| 291 uv_fs_req_cleanup(req); | |
| 292 ASSERT_EQ(3, non_empty_readdir_cb_count); | |
| 293 uv_fs_closedir(uv_default_loop(), | |
| 294 &closedir_req, | |
| 295 dir, | |
| 296 non_empty_closedir_cb); | |
| 297 } else { | |
| 298 ASSERT_EQ(1, req->result); | |
| 299 ASSERT_PTR_EQ(dir->dirents, dirents); | |
| 300 ASSERT(strcmp(dirents[0].name, "file1") == 0 || | |
| 301 strcmp(dirents[0].name, "file2") == 0 || | |
| 302 strcmp(dirents[0].name, "test_subdir") == 0); | |
| 303 #ifdef HAVE_DIRENT_TYPES | |
| 304 if (!strcmp(dirents[0].name, "test_subdir")) | |
| 305 ASSERT_EQ(dirents[0].type, UV_DIRENT_DIR); | |
| 306 else | |
| 307 ASSERT_EQ(dirents[0].type, UV_DIRENT_FILE); | |
| 308 #else | |
| 309 ASSERT_EQ(dirents[0].type, UV_DIRENT_UNKNOWN); | |
| 310 #endif /* HAVE_DIRENT_TYPES */ | |
| 311 | |
| 312 ++non_empty_readdir_cb_count; | |
| 313 uv_fs_req_cleanup(req); | |
| 314 dir->dirents = dirents; | |
| 315 dir->nentries = ARRAY_SIZE(dirents); | |
| 316 uv_fs_readdir(uv_default_loop(), | |
| 317 &readdir_req, | |
| 318 dir, | |
| 319 non_empty_readdir_cb); | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 static void non_empty_opendir_cb(uv_fs_t* req) { | |
| 324 uv_dir_t* dir; | |
| 325 int r; | |
| 326 | |
| 327 ASSERT_PTR_EQ(req, &opendir_req); | |
| 328 ASSERT_EQ(req->fs_type, UV_FS_OPENDIR); | |
| 329 ASSERT_OK(req->result); | |
| 330 ASSERT_NOT_NULL(req->ptr); | |
| 331 | |
| 332 dir = req->ptr; | |
| 333 dir->dirents = dirents; | |
| 334 dir->nentries = ARRAY_SIZE(dirents); | |
| 335 | |
| 336 r = uv_fs_readdir(uv_default_loop(), | |
| 337 &readdir_req, | |
| 338 dir, | |
| 339 non_empty_readdir_cb); | |
| 340 ASSERT_OK(r); | |
| 341 uv_fs_req_cleanup(req); | |
| 342 ++non_empty_opendir_cb_count; | |
| 343 } | |
| 344 | |
| 345 TEST_IMPL(fs_readdir_non_empty_dir) { | |
| 346 size_t entries_count; | |
| 347 uv_fs_t mkdir_req; | |
| 348 uv_fs_t rmdir_req; | |
| 349 uv_fs_t create_req; | |
| 350 uv_fs_t close_req; | |
| 351 uv_dir_t* dir; | |
| 352 int r; | |
| 353 | |
| 354 cleanup_test_files(); | |
| 355 | |
| 356 r = uv_fs_mkdir(uv_default_loop(), &mkdir_req, "test_dir", 0755, NULL); | |
| 357 ASSERT_OK(r); | |
| 358 | |
| 359 /* Create two files synchronously. */ | |
| 360 r = uv_fs_open(uv_default_loop(), | |
| 361 &create_req, | |
| 362 "test_dir/file1", | |
| 363 UV_FS_O_WRONLY | UV_FS_O_CREAT, S_IWUSR | S_IRUSR, | |
| 364 NULL); | |
| 365 ASSERT_GE(r, 0); | |
| 366 uv_fs_req_cleanup(&create_req); | |
| 367 r = uv_fs_close(uv_default_loop(), | |
| 368 &close_req, | |
| 369 create_req.result, | |
| 370 NULL); | |
| 371 ASSERT_OK(r); | |
| 372 uv_fs_req_cleanup(&close_req); | |
| 373 | |
| 374 r = uv_fs_open(uv_default_loop(), | |
| 375 &create_req, | |
| 376 "test_dir/file2", | |
| 377 UV_FS_O_WRONLY | UV_FS_O_CREAT, S_IWUSR | S_IRUSR, | |
| 378 NULL); | |
| 379 ASSERT_GE(r, 0); | |
| 380 uv_fs_req_cleanup(&create_req); | |
| 381 r = uv_fs_close(uv_default_loop(), | |
| 382 &close_req, | |
| 383 create_req.result, | |
| 384 NULL); | |
| 385 ASSERT_OK(r); | |
| 386 uv_fs_req_cleanup(&close_req); | |
| 387 | |
| 388 r = uv_fs_mkdir(uv_default_loop(), | |
| 389 &mkdir_req, | |
| 390 "test_dir/test_subdir", | |
| 391 0755, | |
| 392 NULL); | |
| 393 ASSERT_OK(r); | |
| 394 uv_fs_req_cleanup(&mkdir_req); | |
| 395 | |
| 396 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 397 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 398 | |
| 399 /* Testing the synchronous flavor. */ | |
| 400 r = uv_fs_opendir(uv_default_loop(), &opendir_req, "test_dir", NULL); | |
| 401 ASSERT_OK(r); | |
| 402 ASSERT_EQ(opendir_req.fs_type, UV_FS_OPENDIR); | |
| 403 ASSERT_OK(opendir_req.result); | |
| 404 ASSERT_NOT_NULL(opendir_req.ptr); | |
| 405 | |
| 406 entries_count = 0; | |
| 407 dir = opendir_req.ptr; | |
| 408 dir->dirents = dirents; | |
| 409 dir->nentries = ARRAY_SIZE(dirents); | |
| 410 uv_fs_req_cleanup(&opendir_req); | |
| 411 | |
| 412 while (uv_fs_readdir(uv_default_loop(), | |
| 413 &readdir_req, | |
| 414 dir, | |
| 415 NULL) != 0) { | |
| 416 ASSERT(strcmp(dirents[0].name, "file1") == 0 || | |
| 417 strcmp(dirents[0].name, "file2") == 0 || | |
| 418 strcmp(dirents[0].name, "test_subdir") == 0); | |
| 419 #ifdef HAVE_DIRENT_TYPES | |
| 420 if (!strcmp(dirents[0].name, "test_subdir")) | |
| 421 ASSERT_EQ(dirents[0].type, UV_DIRENT_DIR); | |
| 422 else | |
| 423 ASSERT_EQ(dirents[0].type, UV_DIRENT_FILE); | |
| 424 #else | |
| 425 ASSERT_EQ(dirents[0].type, UV_DIRENT_UNKNOWN); | |
| 426 #endif /* HAVE_DIRENT_TYPES */ | |
| 427 uv_fs_req_cleanup(&readdir_req); | |
| 428 ++entries_count; | |
| 429 } | |
| 430 | |
| 431 ASSERT_EQ(3, entries_count); | |
| 432 uv_fs_req_cleanup(&readdir_req); | |
| 433 | |
| 434 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 435 memset(&closedir_req, 0xdb, sizeof(closedir_req)); | |
| 436 uv_fs_closedir(uv_default_loop(), &closedir_req, dir, NULL); | |
| 437 ASSERT_OK(closedir_req.result); | |
| 438 uv_fs_req_cleanup(&closedir_req); | |
| 439 | |
| 440 /* Testing the asynchronous flavor. */ | |
| 441 | |
| 442 /* Fill the req to ensure that required fields are cleaned up. */ | |
| 443 memset(&opendir_req, 0xdb, sizeof(opendir_req)); | |
| 444 | |
| 445 r = uv_fs_opendir(uv_default_loop(), | |
| 446 &opendir_req, | |
| 447 "test_dir", | |
| 448 non_empty_opendir_cb); | |
| 449 ASSERT_OK(r); | |
| 450 ASSERT_OK(non_empty_opendir_cb_count); | |
| 451 ASSERT_OK(non_empty_closedir_cb_count); | |
| 452 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); | |
| 453 ASSERT_OK(r); | |
| 454 ASSERT_EQ(1, non_empty_opendir_cb_count); | |
| 455 ASSERT_EQ(1, non_empty_closedir_cb_count); | |
| 456 | |
| 457 uv_fs_rmdir(uv_default_loop(), &rmdir_req, "test_subdir", NULL); | |
| 458 uv_fs_req_cleanup(&rmdir_req); | |
| 459 | |
| 460 cleanup_test_files(); | |
| 461 MAKE_VALGRIND_HAPPY(uv_default_loop()); | |
| 462 return 0; | |
| 463 } | |
| 464 | |
| 465 static void readdir_symlink_readdir_cb(uv_fs_t* req) { | |
| 466 uv_dir_t* dir; | |
| 467 | |
| 468 ASSERT_PTR_EQ(req, &readdir_req); | |
| 469 ASSERT_EQ(req->fs_type, UV_FS_READDIR); | |
| 470 dir = req->ptr; | |
| 471 | |
| 472 if (req->result == 0) { | |
| 473 uv_fs_req_cleanup(req); | |
| 474 ASSERT_EQ(3, non_empty_readdir_cb_count); | |
| 475 uv_fs_closedir(uv_default_loop(), | |
| 476 &closedir_req, | |
| 477 dir, | |
| 478 non_empty_closedir_cb); | |
| 479 } else { | |
| 480 if (strcmp(symlink_dirents[0].name, "test_symlink") == 0) { | |
| 481 ASSERT_EQ(symlink_dirents[0].type, UV_DIRENT_LINK); | |
| 482 } else { | |
| 483 ASSERT_EQ(symlink_dirents[1].type, UV_DIRENT_LINK); | |
| 484 } | |
| 485 uv_fs_req_cleanup(req); | |
| 486 } | |
| 487 } | |
| 488 | |
| 489 static void readdir_symlink_opendir_cb(uv_fs_t* req) { | |
| 490 uv_dir_t* dir; | |
| 491 int r; | |
| 492 | |
| 493 ASSERT_PTR_EQ(req, &opendir_req); | |
| 494 ASSERT_EQ(req->fs_type, UV_FS_OPENDIR); | |
| 495 ASSERT_OK(req->result); | |
| 496 ASSERT_NOT_NULL(req->ptr); | |
| 497 | |
| 498 dir = req->ptr; | |
| 499 dir->dirents = symlink_dirents; | |
| 500 dir->nentries = ARRAY_SIZE(symlink_dirents); | |
| 501 | |
| 502 r = uv_fs_readdir(uv_default_loop(), | |
| 503 &readdir_req, | |
| 504 dir, | |
| 505 readdir_symlink_readdir_cb); | |
| 506 ASSERT_OK(r); | |
| 507 uv_fs_req_cleanup(req); | |
| 508 } | |
| 509 | |
| 510 static void cleanup_symlink_test_files(void) { | |
| 511 uv_fs_t req; | |
| 512 | |
| 513 uv_fs_rmdir(NULL, &req, "test_symlink_dir/test_subdir", NULL); | |
| 514 uv_fs_req_cleanup(&req); | |
| 515 uv_fs_unlink(NULL, &req, "test_symlink_dir/test_symlink", NULL); | |
| 516 uv_fs_req_cleanup(&req); | |
| 517 uv_fs_rmdir(NULL, &req, "test_symlink_dir", NULL); | |
| 518 uv_fs_req_cleanup(&req); | |
| 519 } | |
| 520 | |
| 521 TEST_IMPL(fs_readdir_symlink) { | |
| 522 | |
| 523 uv_fs_t mkdir_req; | |
| 524 uv_fs_t symlink_req; | |
| 525 int r; | |
| 526 | |
| 527 cleanup_symlink_test_files(); | |
| 528 | |
| 529 r = uv_fs_mkdir(uv_default_loop(), &mkdir_req, "test_symlink_dir", 0755, NULL); | |
| 530 ASSERT_OK(r); | |
| 531 | |
| 532 r = uv_fs_mkdir(uv_default_loop(), &mkdir_req, "test_symlink_dir/test_subdir", 0755, NULL); | |
| 533 ASSERT_OK(r); | |
| 534 | |
| 535 r = uv_fs_symlink(uv_default_loop(), &symlink_req, "test_symlink_dir/test_subdir", "test_symlink_dir/test_symlink", UV_FS_SYMLINK_DIR, NULL); | |
| 536 ASSERT_OK(r); | |
| 537 | |
| 538 r = uv_fs_opendir(uv_default_loop(), &opendir_req, "test_symlink_dir", readdir_symlink_opendir_cb); | |
| 539 ASSERT_OK(r); | |
| 540 | |
| 541 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); | |
| 542 ASSERT_OK(r); | |
| 543 | |
| 544 cleanup_symlink_test_files(); | |
| 545 | |
| 546 MAKE_VALGRIND_HAPPY(uv_default_loop()); | |
| 547 return 0; | |
| 548 } |