Home | History | Annotate | Line # | Download | only in test
      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 #ifdef _WIN32
     23 
     24 #include "uv.h"
     25 #include "task.h"
     26 
     27 #if defined(__unix__) || defined(__POSIX__) || \
     28     defined(__APPLE__) || defined(__sun) || \
     29     defined(_AIX) || defined(__MVS__) || \
     30     defined(__HAIKU__)
     31 # include <unistd.h> /* unlink, rmdir */
     32 #else
     33 # include <direct.h>
     34 # define rmdir _rmdir
     35 # define unlink _unlink
     36 #endif
     37 
     38 static int flags;
     39 
     40 static uv_fs_t close_req;
     41 static uv_fs_t mkdir_req;
     42 static uv_fs_t open_req;
     43 static uv_fs_t read_req;
     44 static uv_fs_t rmdir_req;
     45 static uv_fs_t unlink_req;
     46 static uv_fs_t write_req;
     47 
     48 static char buf[32];
     49 static uv_buf_t iov;
     50 
     51 /* Opening the same file multiple times quickly can cause uv_fs_open to fail
     52  * with EBUSY, so append an identifier to the file name for each operation */
     53 static int sid = 0;
     54 
     55 #define FILE_NAME_SIZE 128
     56 static char absent_file[FILE_NAME_SIZE];
     57 static char empty_file[FILE_NAME_SIZE];
     58 static char dummy_file[FILE_NAME_SIZE];
     59 static char empty_dir[] = "empty_dir";
     60 
     61 static void setup(void) {
     62   int r;
     63 
     64   /* empty_dir */
     65   r = uv_fs_rmdir(NULL, &rmdir_req, empty_dir, NULL);
     66   ASSERT(r == 0 || r == UV_ENOENT);
     67   ASSERT(rmdir_req.result == 0 || rmdir_req.result == UV_ENOENT);
     68   uv_fs_req_cleanup(&rmdir_req);
     69 
     70   r = uv_fs_mkdir(NULL, &mkdir_req, empty_dir, 0755, NULL);
     71   ASSERT_OK(r);
     72   ASSERT_OK(mkdir_req.result);
     73   uv_fs_req_cleanup(&mkdir_req);
     74 }
     75 
     76 static void refresh(void) {
     77   int r;
     78 
     79   /* absent_file */
     80   sprintf(absent_file, "test_file_%d", sid++);
     81 
     82   r = uv_fs_unlink(NULL, &unlink_req, absent_file, NULL);
     83   ASSERT(r == 0 || r == UV_ENOENT);
     84   ASSERT(unlink_req.result == 0 || unlink_req.result == UV_ENOENT);
     85   uv_fs_req_cleanup(&unlink_req);
     86 
     87   /* empty_file */
     88   sprintf(empty_file, "test_file_%d", sid++);
     89 
     90   r = uv_fs_open(NULL, &open_req, empty_file,
     91     UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
     92   ASSERT_GE(r, 0);
     93   ASSERT_GE(open_req.result, 0);
     94   uv_fs_req_cleanup(&open_req);
     95 
     96   r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
     97   ASSERT_OK(r);
     98   ASSERT_OK(close_req.result);
     99   uv_fs_req_cleanup(&close_req);
    100 
    101   /* dummy_file */
    102   sprintf(dummy_file, "test_file_%d", sid++);
    103 
    104   r = uv_fs_open(NULL, &open_req, dummy_file,
    105     UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
    106   ASSERT_GE(r, 0);
    107   ASSERT_GE(open_req.result, 0);
    108   uv_fs_req_cleanup(&open_req);
    109 
    110   iov = uv_buf_init("a", 1);
    111   r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
    112   ASSERT_EQ(1, r);
    113   ASSERT_EQ(1, write_req.result);
    114   uv_fs_req_cleanup(&write_req);
    115 
    116   r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
    117   ASSERT_OK(r);
    118   ASSERT_OK(close_req.result);
    119   uv_fs_req_cleanup(&close_req);
    120 }
    121 
    122 static void cleanup(void) {
    123   unlink(absent_file);
    124   unlink(empty_file);
    125   unlink(dummy_file);
    126 }
    127 
    128 static void openFail(char *file, int error) {
    129   int r;
    130 
    131   refresh();
    132 
    133   r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
    134   ASSERT_EQ(r, error);
    135   ASSERT_EQ(open_req.result, error);
    136   uv_fs_req_cleanup(&open_req);
    137 
    138   /* Ensure the first call does not create the file */
    139   r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
    140   ASSERT_EQ(r, error);
    141   ASSERT_EQ(open_req.result, error);
    142   uv_fs_req_cleanup(&open_req);
    143 
    144   cleanup();
    145 }
    146 
    147 static void refreshOpen(char *file) {
    148   int r;
    149 
    150   refresh();
    151 
    152   r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
    153   ASSERT_GE(r, 0);
    154   ASSERT_GE(open_req.result, 0);
    155   uv_fs_req_cleanup(&open_req);
    156 }
    157 
    158 static void writeExpect(char *file, char *expected, int size) {
    159   int r;
    160 
    161   refreshOpen(file);
    162 
    163   iov = uv_buf_init("b", 1);
    164   r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
    165   ASSERT_EQ(1, r);
    166   ASSERT_EQ(1, write_req.result);
    167   uv_fs_req_cleanup(&write_req);
    168 
    169   iov = uv_buf_init("c", 1);
    170   r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
    171   ASSERT_EQ(1, r);
    172   ASSERT_EQ(1, write_req.result);
    173   uv_fs_req_cleanup(&write_req);
    174 
    175   r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
    176   ASSERT_OK(r);
    177   ASSERT_OK(close_req.result);
    178   uv_fs_req_cleanup(&close_req);
    179 
    180   /* Check contents */
    181   r = uv_fs_open(NULL, &open_req, file, UV_FS_O_RDONLY, S_IWUSR | S_IRUSR, NULL);
    182   ASSERT_GE(r, 0);
    183   ASSERT_GE(open_req.result, 0);
    184   uv_fs_req_cleanup(&open_req);
    185 
    186   iov = uv_buf_init(buf, sizeof(buf));
    187   r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
    188   ASSERT_EQ(r, size);
    189   ASSERT_EQ(read_req.result, size);
    190   ASSERT_OK(strncmp(buf, expected, size));
    191   uv_fs_req_cleanup(&read_req);
    192 
    193   r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
    194   ASSERT_OK(r);
    195   ASSERT_OK(close_req.result);
    196   uv_fs_req_cleanup(&close_req);
    197 
    198   cleanup();
    199 }
    200 
    201 static void writeFail(char *file, int error) {
    202   int r;
    203 
    204   refreshOpen(file);
    205 
    206   iov = uv_buf_init("z", 1);
    207   r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
    208   ASSERT_EQ(r, error);
    209   ASSERT_EQ(write_req.result, error);
    210   uv_fs_req_cleanup(&write_req);
    211 
    212   iov = uv_buf_init("z", 1);
    213   r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
    214   ASSERT_EQ(r, error);
    215   ASSERT_EQ(write_req.result, error);
    216   uv_fs_req_cleanup(&write_req);
    217 
    218   r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
    219   ASSERT_OK(r);
    220   ASSERT_OK(close_req.result);
    221   uv_fs_req_cleanup(&close_req);
    222 
    223   cleanup();
    224 }
    225 
    226 static void readExpect(char *file, char *expected, int size) {
    227   int r;
    228 
    229   refreshOpen(file);
    230 
    231   iov = uv_buf_init(buf, sizeof(buf));
    232   r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
    233   ASSERT_EQ(r, size);
    234   ASSERT_EQ(read_req.result, size);
    235   ASSERT_OK(strncmp(buf, expected, size));
    236   uv_fs_req_cleanup(&read_req);
    237 
    238   r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
    239   ASSERT_OK(r);
    240   ASSERT_OK(close_req.result);
    241   uv_fs_req_cleanup(&close_req);
    242 
    243   cleanup();
    244 }
    245 
    246 static void readFail(char *file, int error) {
    247   int r;
    248 
    249   refreshOpen(file);
    250 
    251   iov = uv_buf_init(buf, sizeof(buf));
    252   r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
    253   ASSERT_EQ(r, error);
    254   ASSERT_EQ(read_req.result, error);
    255   uv_fs_req_cleanup(&read_req);
    256 
    257   iov = uv_buf_init(buf, sizeof(buf));
    258   r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
    259   ASSERT_EQ(r, error);
    260   ASSERT_EQ(read_req.result, error);
    261   uv_fs_req_cleanup(&read_req);
    262 
    263   r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
    264   ASSERT_OK(r);
    265   ASSERT_OK(close_req.result);
    266   uv_fs_req_cleanup(&close_req);
    267 
    268   cleanup();
    269 }
    270 
    271 static void fs_open_flags(int add_flags) {
    272   /* Follow the order from
    273    * https://github.com/nodejs/node/blob/1a96abe849/lib/internal/fs/utils.js#L329-L354
    274    */
    275 
    276   /* r */
    277   flags = add_flags | UV_FS_O_RDONLY;
    278   openFail(absent_file, UV_ENOENT);
    279   writeFail(empty_file, UV_EBADF);
    280   readExpect(empty_file, "", 0);
    281   writeFail(dummy_file, UV_EBADF);
    282   readExpect(dummy_file, "a", 1);
    283   writeFail(empty_dir, UV_EBADF);
    284   readFail(empty_dir, UV_EISDIR);
    285 
    286   /* rs */
    287   flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC;
    288   openFail(absent_file, UV_ENOENT);
    289   writeFail(empty_file, UV_EBADF);
    290   readExpect(empty_file, "", 0);
    291   writeFail(dummy_file, UV_EBADF);
    292   readExpect(dummy_file, "a", 1);
    293   writeFail(empty_dir, UV_EBADF);
    294   readFail(empty_dir, UV_EISDIR);
    295 
    296   /* r+ */
    297   flags = add_flags | UV_FS_O_RDWR;
    298   openFail(absent_file, UV_ENOENT);
    299   writeExpect(empty_file, "bc", 2);
    300   readExpect(empty_file, "", 0);
    301   writeExpect(dummy_file, "bc", 2);
    302   readExpect(dummy_file, "a", 1);
    303   writeFail(empty_dir, UV_EISDIR);
    304   readFail(empty_dir, UV_EISDIR);
    305 
    306   /* rs+ */
    307   flags = add_flags | UV_FS_O_RDWR | UV_FS_O_SYNC;
    308   openFail(absent_file, UV_ENOENT);
    309   writeExpect(empty_file, "bc", 2);
    310   readExpect(empty_file, "", 0);
    311   writeExpect(dummy_file, "bc", 2);
    312   readExpect(dummy_file, "a", 1);
    313   writeFail(empty_dir, UV_EISDIR);
    314   readFail(empty_dir, UV_EISDIR);
    315 
    316   /* w */
    317   flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY;
    318   writeExpect(absent_file, "bc", 2);
    319   readFail(absent_file, UV_EBADF);
    320   writeExpect(empty_file, "bc", 2);
    321   readFail(empty_file, UV_EBADF);
    322   writeExpect(dummy_file, "bc", 2);
    323   readFail(dummy_file, UV_EBADF);
    324   openFail(empty_dir, UV_EISDIR);
    325 
    326   /* wx */
    327   flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY |
    328     UV_FS_O_EXCL;
    329   writeExpect(absent_file, "bc", 2);
    330   readFail(absent_file, UV_EBADF);
    331   openFail(empty_file, UV_EEXIST);
    332   openFail(dummy_file, UV_EEXIST);
    333   openFail(empty_dir, UV_EEXIST);
    334 
    335   /* w+ */
    336   flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR;
    337   writeExpect(absent_file, "bc", 2);
    338   readExpect(absent_file, "", 0);
    339   writeExpect(empty_file, "bc", 2);
    340   readExpect(empty_file, "", 0);
    341   writeExpect(dummy_file, "bc", 2);
    342   readExpect(dummy_file, "", 0);
    343   openFail(empty_dir, UV_EISDIR);
    344 
    345   /* wx+ */
    346   flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR |
    347     UV_FS_O_EXCL;
    348   writeExpect(absent_file, "bc", 2);
    349   readExpect(absent_file, "", 0);
    350   openFail(empty_file, UV_EEXIST);
    351   openFail(dummy_file, UV_EEXIST);
    352   openFail(empty_dir, UV_EEXIST);
    353 
    354   /* a */
    355   flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY;
    356   writeExpect(absent_file, "bc", 2);
    357   readFail(absent_file, UV_EBADF);
    358   writeExpect(empty_file, "bc", 2);
    359   readFail(empty_file, UV_EBADF);
    360   writeExpect(dummy_file, "abc", 3);
    361   readFail(dummy_file, UV_EBADF);
    362   writeFail(empty_dir, UV_EISDIR);
    363   readFail(empty_dir, UV_EBADF);
    364 
    365   /* ax */
    366   flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
    367     UV_FS_O_EXCL;
    368   writeExpect(absent_file, "bc", 2);
    369   readFail(absent_file, UV_EBADF);
    370   openFail(empty_file, UV_EEXIST);
    371   openFail(dummy_file, UV_EEXIST);
    372   openFail(empty_dir, UV_EEXIST);
    373 
    374   /* as */
    375   flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
    376     UV_FS_O_SYNC;
    377   writeExpect(absent_file, "bc", 2);
    378   readFail(absent_file, UV_EBADF);
    379   writeExpect(empty_file, "bc", 2);
    380   readFail(empty_file, UV_EBADF);
    381   writeExpect(dummy_file, "abc", 3);
    382   readFail(dummy_file, UV_EBADF);
    383   writeFail(empty_dir, UV_EISDIR);
    384   readFail(empty_dir, UV_EBADF);
    385 
    386   /* a+ */
    387   flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR;
    388   writeExpect(absent_file, "bc", 2);
    389   readExpect(absent_file, "", 0);
    390   writeExpect(empty_file, "bc", 2);
    391   readExpect(empty_file, "", 0);
    392   writeExpect(dummy_file, "abc", 3);
    393   readExpect(dummy_file, "a", 1);
    394   writeFail(empty_dir, UV_EISDIR);
    395   readFail(empty_dir, UV_EISDIR);
    396 
    397   /* ax+ */
    398   flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
    399     UV_FS_O_EXCL;
    400   writeExpect(absent_file, "bc", 2);
    401   readExpect(absent_file, "", 0);
    402   openFail(empty_file, UV_EEXIST);
    403   openFail(dummy_file, UV_EEXIST);
    404   openFail(empty_dir, UV_EEXIST);
    405 
    406   /* as+ */
    407   flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
    408     UV_FS_O_SYNC;
    409   writeExpect(absent_file, "bc", 2);
    410   readExpect(absent_file, "", 0);
    411   writeExpect(empty_file, "bc", 2);
    412   readExpect(empty_file, "", 0);
    413   writeExpect(dummy_file, "abc", 3);
    414   readExpect(dummy_file, "a", 1);
    415   writeFail(empty_dir, UV_EISDIR);
    416   readFail(empty_dir, UV_EISDIR);
    417 }
    418 TEST_IMPL(fs_open_flags) {
    419   setup();
    420 
    421   fs_open_flags(0);
    422   fs_open_flags(UV_FS_O_FILEMAP);
    423 
    424   /* Cleanup. */
    425   rmdir(empty_dir);
    426 
    427   MAKE_VALGRIND_HAPPY(uv_default_loop());
    428   return 0;
    429 }
    430 
    431 #else
    432 
    433 typedef int file_has_no_tests;  /* ISO C forbids an empty translation unit. */
    434 
    435 #endif  /* ifndef _WIN32 */
    436