Home | History | Annotate | Line # | Download | only in test
      1 /* Copyright Joyent, Inc. and other Node 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 
     25 #include <string.h>
     26 
     27 #define FIXTURE "testfile"
     28 
     29 static void timer_cb(uv_timer_t* handle);
     30 static void close_cb(uv_handle_t* handle);
     31 static void poll_cb(uv_fs_poll_t* handle,
     32                     int status,
     33                     const uv_stat_t* prev,
     34                     const uv_stat_t* curr);
     35 
     36 static void poll_cb_fail(uv_fs_poll_t* handle,
     37                          int status,
     38                          const uv_stat_t* prev,
     39                          const uv_stat_t* curr);
     40 static void poll_cb_noop(uv_fs_poll_t* handle,
     41                          int status,
     42                          const uv_stat_t* prev,
     43                          const uv_stat_t* curr);
     44 
     45 static uv_fs_poll_t poll_handle;
     46 static uv_timer_t timer_handle;
     47 static uv_loop_t* loop;
     48 
     49 static int poll_cb_called;
     50 static int timer_cb_called;
     51 static int close_cb_called;
     52 
     53 
     54 static void touch_file(const char* path) {
     55   static int count;
     56   FILE* fp;
     57   int i;
     58 
     59   ASSERT((fp = fopen(FIXTURE, "w+")));
     60 
     61   /* Need to change the file size because the poller may not pick up
     62    * sub-second mtime changes.
     63    */
     64   i = ++count;
     65 
     66   while (i--)
     67     fputc('*', fp);
     68 
     69   fclose(fp);
     70 }
     71 
     72 
     73 static void close_cb(uv_handle_t* handle) {
     74   close_cb_called++;
     75 }
     76 
     77 
     78 static void timer_cb(uv_timer_t* handle) {
     79   touch_file(FIXTURE);
     80   timer_cb_called++;
     81 }
     82 
     83 
     84 static void poll_cb_fail(uv_fs_poll_t* handle,
     85                          int status,
     86                          const uv_stat_t* prev,
     87                          const uv_stat_t* curr) {
     88   ASSERT(0 && "fail_cb called");
     89 }
     90 
     91 static void poll_cb_noop(uv_fs_poll_t* handle,
     92                          int status,
     93                          const uv_stat_t* prev,
     94                          const uv_stat_t* curr) {
     95 }
     96 
     97 
     98 static void poll_cb(uv_fs_poll_t* handle,
     99                     int status,
    100                     const uv_stat_t* prev,
    101                     const uv_stat_t* curr) {
    102   uv_stat_t zero_statbuf;
    103 
    104   memset(&zero_statbuf, 0, sizeof(zero_statbuf));
    105 
    106   ASSERT_PTR_EQ(handle, &poll_handle);
    107   ASSERT_EQ(1, uv_is_active((uv_handle_t*) handle));
    108   ASSERT_NOT_NULL(prev);
    109   ASSERT_NOT_NULL(curr);
    110 
    111   switch (poll_cb_called++) {
    112   case 0:
    113     ASSERT_EQ(status, UV_ENOENT);
    114     ASSERT_OK(memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
    115     ASSERT_OK(memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
    116     touch_file(FIXTURE);
    117     break;
    118 
    119   case 1:
    120     ASSERT_OK(status);
    121     ASSERT_OK(memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
    122     ASSERT_NE(0, memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
    123     ASSERT_OK(uv_timer_start(&timer_handle, timer_cb, 20, 0));
    124     break;
    125 
    126   case 2:
    127     ASSERT_OK(status);
    128     ASSERT_NE(0, memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
    129     ASSERT_NE(0, memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
    130     ASSERT_OK(uv_timer_start(&timer_handle, timer_cb, 200, 0));
    131     break;
    132 
    133   case 3:
    134     ASSERT_OK(status);
    135     ASSERT_NE(0, memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
    136     ASSERT_NE(0, memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
    137     remove(FIXTURE);
    138     break;
    139 
    140   case 4:
    141     ASSERT_EQ(status, UV_ENOENT);
    142     ASSERT_NE(0, memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
    143     ASSERT_OK(memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
    144     uv_close((uv_handle_t*)handle, close_cb);
    145     break;
    146 
    147   default:
    148     ASSERT(0);
    149   }
    150 }
    151 
    152 
    153 TEST_IMPL(fs_poll) {
    154   loop = uv_default_loop();
    155 
    156   remove(FIXTURE);
    157 
    158   ASSERT_OK(uv_timer_init(loop, &timer_handle));
    159   ASSERT_OK(uv_fs_poll_init(loop, &poll_handle));
    160   ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb, FIXTURE, 100));
    161   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    162 
    163   ASSERT_EQ(5, poll_cb_called);
    164   ASSERT_EQ(2, timer_cb_called);
    165   ASSERT_EQ(1, close_cb_called);
    166 
    167   MAKE_VALGRIND_HAPPY(loop);
    168   return 0;
    169 }
    170 
    171 
    172 TEST_IMPL(fs_poll_getpath) {
    173   char buf[1024];
    174   size_t len;
    175   loop = uv_default_loop();
    176 
    177   remove(FIXTURE);
    178 
    179   ASSERT_OK(uv_fs_poll_init(loop, &poll_handle));
    180   len = sizeof buf;
    181   ASSERT_EQ(UV_EINVAL, uv_fs_poll_getpath(&poll_handle, buf, &len));
    182   ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
    183   len = sizeof buf;
    184   ASSERT_OK(uv_fs_poll_getpath(&poll_handle, buf, &len));
    185   ASSERT_NE(0, buf[len - 1]);
    186   ASSERT_EQ(buf[len], '\0');
    187   ASSERT_OK(memcmp(buf, FIXTURE, len));
    188 
    189   uv_close((uv_handle_t*) &poll_handle, close_cb);
    190 
    191   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    192 
    193   ASSERT_EQ(1, close_cb_called);
    194 
    195   MAKE_VALGRIND_HAPPY(loop);
    196   return 0;
    197 }
    198 
    199 
    200 TEST_IMPL(fs_poll_close_request) {
    201   uv_loop_t loop;
    202   uv_fs_poll_t poll_handle;
    203 
    204   remove(FIXTURE);
    205 
    206   ASSERT_OK(uv_loop_init(&loop));
    207 
    208   ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
    209   ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
    210   uv_close((uv_handle_t*) &poll_handle, close_cb);
    211   while (close_cb_called == 0)
    212     uv_run(&loop, UV_RUN_ONCE);
    213   ASSERT_EQ(1, close_cb_called);
    214 
    215   MAKE_VALGRIND_HAPPY(&loop);
    216   return 0;
    217 }
    218 
    219 TEST_IMPL(fs_poll_close_request_multi_start_stop) {
    220   uv_loop_t loop;
    221   uv_fs_poll_t poll_handle;
    222   int i;
    223 
    224   remove(FIXTURE);
    225 
    226   ASSERT_OK(uv_loop_init(&loop));
    227 
    228   ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
    229 
    230   for (i = 0; i < 10; ++i) {
    231     ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
    232     ASSERT_OK(uv_fs_poll_stop(&poll_handle));
    233   }
    234   uv_close((uv_handle_t*) &poll_handle, close_cb);
    235   while (close_cb_called == 0)
    236     uv_run(&loop, UV_RUN_ONCE);
    237   ASSERT_EQ(1, close_cb_called);
    238 
    239   MAKE_VALGRIND_HAPPY(&loop);
    240   return 0;
    241 }
    242 
    243 TEST_IMPL(fs_poll_close_request_multi_stop_start) {
    244   uv_loop_t loop;
    245   uv_fs_poll_t poll_handle;
    246   int i;
    247 
    248   remove(FIXTURE);
    249 
    250   ASSERT_OK(uv_loop_init(&loop));
    251 
    252   ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
    253 
    254   for (i = 0; i < 10; ++i) {
    255     ASSERT_OK(uv_fs_poll_stop(&poll_handle));
    256     ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
    257   }
    258   uv_close((uv_handle_t*) &poll_handle, close_cb);
    259   while (close_cb_called == 0)
    260     uv_run(&loop, UV_RUN_ONCE);
    261   ASSERT_EQ(1, close_cb_called);
    262 
    263   MAKE_VALGRIND_HAPPY(&loop);
    264   return 0;
    265 }
    266 
    267 TEST_IMPL(fs_poll_close_request_stop_when_active) {
    268   /* Regression test for https://github.com/libuv/libuv/issues/2287. */
    269   uv_loop_t loop;
    270   uv_fs_poll_t poll_handle;
    271 
    272   remove(FIXTURE);
    273 
    274   ASSERT_OK(uv_loop_init(&loop));
    275 
    276   /* Set up all handles. */
    277   ASSERT_OK(uv_fs_poll_init(&loop, &poll_handle));
    278   ASSERT_OK(uv_fs_poll_start(&poll_handle, poll_cb_noop, FIXTURE, 100));
    279   uv_run(&loop, UV_RUN_ONCE);
    280 
    281   /* Close the timer handle, and do not crash. */
    282   ASSERT_OK(uv_fs_poll_stop(&poll_handle));
    283   uv_run(&loop, UV_RUN_ONCE);
    284 
    285   /* Clean up after the test. */
    286   uv_close((uv_handle_t*) &poll_handle, close_cb);
    287   uv_run(&loop, UV_RUN_ONCE);
    288   ASSERT_EQ(1, close_cb_called);
    289 
    290   MAKE_VALGRIND_HAPPY(&loop);
    291   return 0;
    292 }
    293