Home | History | Annotate | Line # | Download | only in test
      1      1.1  christos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
      2      1.1  christos  *
      3      1.1  christos  * Permission is hereby granted, free of charge, to any person obtaining a copy
      4      1.1  christos  * of this software and associated documentation files (the "Software"), to
      5      1.1  christos  * deal in the Software without restriction, including without limitation the
      6      1.1  christos  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
      7      1.1  christos  * sell copies of the Software, and to permit persons to whom the Software is
      8      1.1  christos  * furnished to do so, subject to the following conditions:
      9      1.1  christos  *
     10      1.1  christos  * The above copyright notice and this permission notice shall be included in
     11      1.1  christos  * all copies or substantial portions of the Software.
     12      1.1  christos  *
     13      1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14      1.1  christos  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15      1.1  christos  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16      1.1  christos  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17      1.1  christos  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     18      1.1  christos  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     19      1.1  christos  * IN THE SOFTWARE.
     20      1.1  christos  */
     21      1.1  christos 
     22      1.1  christos #include "uv.h"
     23      1.1  christos #include "task.h"
     24      1.1  christos 
     25      1.1  christos #ifndef _WIN32
     26      1.1  christos #include <unistd.h>
     27      1.1  christos #endif
     28      1.1  christos 
     29      1.1  christos TEST_IMPL(kill_invalid_signum) {
     30      1.1  christos   uv_pid_t pid;
     31      1.1  christos 
     32      1.1  christos   pid = uv_os_getpid();
     33      1.1  christos 
     34  1.1.1.2  christos   ASSERT_EQ(uv_kill(pid, -1), UV_EINVAL);
     35      1.1  christos #ifdef _WIN32
     36      1.1  christos   /* NSIG is not available on all platforms. */
     37  1.1.1.2  christos   ASSERT_EQ(uv_kill(pid, NSIG), UV_EINVAL);
     38      1.1  christos #endif
     39  1.1.1.2  christos   ASSERT_EQ(uv_kill(pid, 4096), UV_EINVAL);
     40      1.1  christos 
     41  1.1.1.2  christos   MAKE_VALGRIND_HAPPY(uv_default_loop());
     42      1.1  christos   return 0;
     43      1.1  christos }
     44      1.1  christos 
     45      1.1  christos /* For Windows we test only signum handling */
     46      1.1  christos #ifdef _WIN32
     47      1.1  christos static void signum_test_cb(uv_signal_t* handle, int signum) {
     48      1.1  christos   FATAL("signum_test_cb should not be called");
     49      1.1  christos }
     50      1.1  christos 
     51      1.1  christos TEST_IMPL(win32_signum_number) {
     52      1.1  christos   uv_signal_t signal;
     53      1.1  christos   uv_loop_t* loop;
     54      1.1  christos 
     55      1.1  christos   loop = uv_default_loop();
     56      1.1  christos   uv_signal_init(loop, &signal);
     57      1.1  christos 
     58  1.1.1.2  christos   ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, 0), UV_EINVAL);
     59  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGINT));
     60  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGBREAK));
     61  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGHUP));
     62  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGWINCH));
     63  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGILL));
     64  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGABRT_COMPAT));
     65  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGFPE));
     66  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGSEGV));
     67  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGTERM));
     68  1.1.1.2  christos   ASSERT_OK(uv_signal_start(&signal, signum_test_cb, SIGABRT));
     69  1.1.1.2  christos   ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, -1), UV_EINVAL);
     70  1.1.1.2  christos   ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, NSIG), UV_EINVAL);
     71  1.1.1.2  christos   ASSERT_EQ(uv_signal_start(&signal, signum_test_cb, 1024), UV_EINVAL);
     72  1.1.1.2  christos   MAKE_VALGRIND_HAPPY(loop);
     73      1.1  christos   return 0;
     74      1.1  christos }
     75      1.1  christos #else
     76      1.1  christos #include <errno.h>
     77      1.1  christos #include <signal.h>
     78      1.1  christos #include <stdarg.h>
     79      1.1  christos #include <stdio.h>
     80      1.1  christos #include <stdlib.h>
     81      1.1  christos #include <string.h>
     82      1.1  christos #include <unistd.h>
     83      1.1  christos 
     84      1.1  christos #define NSIGNALS  10
     85      1.1  christos 
     86      1.1  christos struct timer_ctx {
     87      1.1  christos   unsigned int ncalls;
     88      1.1  christos   uv_timer_t handle;
     89      1.1  christos   int signum;
     90      1.1  christos };
     91      1.1  christos 
     92      1.1  christos struct signal_ctx {
     93      1.1  christos   enum { CLOSE, STOP, NOOP } stop_or_close;
     94      1.1  christos   unsigned int ncalls;
     95      1.1  christos   uv_signal_t handle;
     96      1.1  christos   int signum;
     97      1.1  christos   int one_shot;
     98      1.1  christos };
     99      1.1  christos 
    100      1.1  christos 
    101      1.1  christos static void signal_cb(uv_signal_t* handle, int signum) {
    102      1.1  christos   struct signal_ctx* ctx = container_of(handle, struct signal_ctx, handle);
    103  1.1.1.2  christos   ASSERT_EQ(signum, ctx->signum);
    104      1.1  christos   if (++ctx->ncalls == NSIGNALS) {
    105      1.1  christos     if (ctx->stop_or_close == STOP)
    106      1.1  christos       uv_signal_stop(handle);
    107      1.1  christos     else if (ctx->stop_or_close == CLOSE)
    108      1.1  christos       uv_close((uv_handle_t*)handle, NULL);
    109      1.1  christos     else
    110      1.1  christos       ASSERT(0);
    111      1.1  christos   }
    112      1.1  christos }
    113      1.1  christos 
    114      1.1  christos static void signal_cb_one_shot(uv_signal_t* handle, int signum) {
    115      1.1  christos   struct signal_ctx* ctx = container_of(handle, struct signal_ctx, handle);
    116  1.1.1.2  christos   ASSERT_EQ(signum, ctx->signum);
    117  1.1.1.2  christos   ASSERT_EQ(1, ++ctx->ncalls);
    118      1.1  christos   if (ctx->stop_or_close == CLOSE)
    119      1.1  christos     uv_close((uv_handle_t*)handle, NULL);
    120      1.1  christos }
    121      1.1  christos 
    122      1.1  christos 
    123      1.1  christos static void timer_cb(uv_timer_t* handle) {
    124      1.1  christos   struct timer_ctx* ctx = container_of(handle, struct timer_ctx, handle);
    125      1.1  christos 
    126      1.1  christos   raise(ctx->signum);
    127      1.1  christos 
    128      1.1  christos   if (++ctx->ncalls == NSIGNALS)
    129      1.1  christos     uv_close((uv_handle_t*)handle, NULL);
    130      1.1  christos }
    131      1.1  christos 
    132      1.1  christos 
    133      1.1  christos static void start_watcher(uv_loop_t* loop,
    134      1.1  christos                           int signum,
    135      1.1  christos                           struct signal_ctx* ctx,
    136      1.1  christos                           int one_shot) {
    137      1.1  christos   ctx->ncalls = 0;
    138      1.1  christos   ctx->signum = signum;
    139      1.1  christos   ctx->stop_or_close = CLOSE;
    140      1.1  christos   ctx->one_shot = one_shot;
    141  1.1.1.2  christos   ASSERT_OK(uv_signal_init(loop, &ctx->handle));
    142      1.1  christos   if (one_shot)
    143  1.1.1.2  christos     ASSERT_OK(uv_signal_start_oneshot(&ctx->handle, signal_cb_one_shot, signum));
    144      1.1  christos   else
    145  1.1.1.2  christos     ASSERT_OK(uv_signal_start(&ctx->handle, signal_cb, signum));
    146      1.1  christos }
    147      1.1  christos 
    148      1.1  christos static void start_timer(uv_loop_t* loop, int signum, struct timer_ctx* ctx) {
    149      1.1  christos   ctx->ncalls = 0;
    150      1.1  christos   ctx->signum = signum;
    151  1.1.1.2  christos   ASSERT_OK(uv_timer_init(loop, &ctx->handle));
    152  1.1.1.2  christos   ASSERT_OK(uv_timer_start(&ctx->handle, timer_cb, 5, 5));
    153      1.1  christos }
    154      1.1  christos 
    155      1.1  christos 
    156      1.1  christos TEST_IMPL(we_get_signal) {
    157      1.1  christos   struct signal_ctx sc;
    158      1.1  christos   struct timer_ctx tc;
    159      1.1  christos   uv_loop_t* loop;
    160      1.1  christos 
    161      1.1  christos   loop = uv_default_loop();
    162      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    163      1.1  christos   start_watcher(loop, SIGCHLD, &sc, 0);
    164      1.1  christos   sc.stop_or_close = STOP; /* stop, don't close the signal handle */
    165  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    166  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    167  1.1.1.2  christos   ASSERT_EQ(sc.ncalls, NSIGNALS);
    168      1.1  christos 
    169      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    170  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    171  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    172  1.1.1.2  christos   ASSERT_EQ(sc.ncalls, NSIGNALS);
    173      1.1  christos 
    174      1.1  christos   sc.ncalls = 0;
    175      1.1  christos   sc.stop_or_close = CLOSE; /* now close it when it's done */
    176      1.1  christos   uv_signal_start(&sc.handle, signal_cb, SIGCHLD);
    177      1.1  christos 
    178      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    179  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    180  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    181  1.1.1.2  christos   ASSERT_EQ(sc.ncalls, NSIGNALS);
    182      1.1  christos 
    183  1.1.1.2  christos   MAKE_VALGRIND_HAPPY(loop);
    184      1.1  christos   return 0;
    185      1.1  christos }
    186      1.1  christos 
    187      1.1  christos 
    188      1.1  christos TEST_IMPL(we_get_signals) {
    189      1.1  christos   struct signal_ctx sc[4];
    190      1.1  christos   struct timer_ctx tc[2];
    191      1.1  christos   uv_loop_t* loop;
    192      1.1  christos   unsigned int i;
    193      1.1  christos 
    194      1.1  christos   loop = uv_default_loop();
    195      1.1  christos   start_watcher(loop, SIGUSR1, sc + 0, 0);
    196      1.1  christos   start_watcher(loop, SIGUSR1, sc + 1, 0);
    197      1.1  christos   start_watcher(loop, SIGUSR2, sc + 2, 0);
    198      1.1  christos   start_watcher(loop, SIGUSR2, sc + 3, 0);
    199      1.1  christos   start_timer(loop, SIGUSR1, tc + 0);
    200      1.1  christos   start_timer(loop, SIGUSR2, tc + 1);
    201  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    202      1.1  christos 
    203      1.1  christos   for (i = 0; i < ARRAY_SIZE(sc); i++)
    204  1.1.1.2  christos     ASSERT_EQ(sc[i].ncalls, NSIGNALS);
    205      1.1  christos 
    206      1.1  christos   for (i = 0; i < ARRAY_SIZE(tc); i++)
    207  1.1.1.2  christos     ASSERT_EQ(tc[i].ncalls, NSIGNALS);
    208      1.1  christos 
    209  1.1.1.2  christos   MAKE_VALGRIND_HAPPY(loop);
    210      1.1  christos   return 0;
    211      1.1  christos }
    212      1.1  christos 
    213      1.1  christos TEST_IMPL(we_get_signal_one_shot) {
    214      1.1  christos   struct signal_ctx sc;
    215      1.1  christos   struct timer_ctx tc;
    216      1.1  christos   uv_loop_t* loop;
    217      1.1  christos 
    218      1.1  christos   loop = uv_default_loop();
    219      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    220      1.1  christos   start_watcher(loop, SIGCHLD, &sc, 1);
    221      1.1  christos   sc.stop_or_close = NOOP;
    222  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    223  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    224  1.1.1.2  christos   ASSERT_EQ(1, sc.ncalls);
    225      1.1  christos 
    226      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    227  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    228  1.1.1.2  christos   ASSERT_EQ(1, sc.ncalls);
    229      1.1  christos 
    230      1.1  christos   sc.ncalls = 0;
    231      1.1  christos   sc.stop_or_close = CLOSE; /* now close it when it's done */
    232      1.1  christos   uv_signal_start_oneshot(&sc.handle, signal_cb_one_shot, SIGCHLD);
    233      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    234  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    235  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    236  1.1.1.2  christos   ASSERT_EQ(1, sc.ncalls);
    237      1.1  christos 
    238  1.1.1.2  christos   MAKE_VALGRIND_HAPPY(loop);
    239      1.1  christos   return 0;
    240      1.1  christos }
    241      1.1  christos 
    242      1.1  christos TEST_IMPL(we_get_signals_mixed) {
    243      1.1  christos   struct signal_ctx sc[4];
    244      1.1  christos   struct timer_ctx tc;
    245      1.1  christos   uv_loop_t* loop;
    246      1.1  christos 
    247      1.1  christos   loop = uv_default_loop();
    248      1.1  christos 
    249      1.1  christos   /* 2 one-shot */
    250      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    251      1.1  christos   start_watcher(loop, SIGCHLD, sc + 0, 1);
    252      1.1  christos   start_watcher(loop, SIGCHLD, sc + 1, 1);
    253      1.1  christos   sc[0].stop_or_close = CLOSE;
    254      1.1  christos   sc[1].stop_or_close = CLOSE;
    255  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    256  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    257  1.1.1.2  christos   ASSERT_EQ(1, sc[0].ncalls);
    258  1.1.1.2  christos   ASSERT_EQ(1, sc[1].ncalls);
    259      1.1  christos 
    260      1.1  christos   /* 2 one-shot, 1 normal then remove normal */
    261      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    262      1.1  christos   start_watcher(loop, SIGCHLD, sc + 0, 1);
    263      1.1  christos   start_watcher(loop, SIGCHLD, sc + 1, 1);
    264      1.1  christos   sc[0].stop_or_close = CLOSE;
    265      1.1  christos   sc[1].stop_or_close = CLOSE;
    266      1.1  christos   start_watcher(loop, SIGCHLD, sc + 2, 0);
    267      1.1  christos   uv_close((uv_handle_t*)&(sc[2]).handle, NULL);
    268  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    269  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    270  1.1.1.2  christos   ASSERT_EQ(1, sc[0].ncalls);
    271  1.1.1.2  christos   ASSERT_EQ(1, sc[1].ncalls);
    272  1.1.1.2  christos   ASSERT_OK(sc[2].ncalls);
    273      1.1  christos 
    274      1.1  christos   /* 2 normal, 1 one-shot then remove one-shot */
    275      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    276      1.1  christos   start_watcher(loop, SIGCHLD, sc + 0, 0);
    277      1.1  christos   start_watcher(loop, SIGCHLD, sc + 1, 0);
    278      1.1  christos   sc[0].stop_or_close = CLOSE;
    279      1.1  christos   sc[1].stop_or_close = CLOSE;
    280      1.1  christos   start_watcher(loop, SIGCHLD, sc + 2, 1);
    281      1.1  christos   uv_close((uv_handle_t*)&(sc[2]).handle, NULL);
    282  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    283  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    284  1.1.1.2  christos   ASSERT_EQ(sc[0].ncalls, NSIGNALS);
    285  1.1.1.2  christos   ASSERT_EQ(sc[1].ncalls, NSIGNALS);
    286  1.1.1.2  christos   ASSERT_OK(sc[2].ncalls);
    287      1.1  christos 
    288      1.1  christos   /* 2 normal, 2 one-shot then remove 2 normal */
    289      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    290      1.1  christos   start_watcher(loop, SIGCHLD, sc + 0, 0);
    291      1.1  christos   start_watcher(loop, SIGCHLD, sc + 1, 0);
    292      1.1  christos   start_watcher(loop, SIGCHLD, sc + 2, 1);
    293      1.1  christos   start_watcher(loop, SIGCHLD, sc + 3, 1);
    294      1.1  christos   sc[2].stop_or_close = CLOSE;
    295      1.1  christos   sc[3].stop_or_close = CLOSE;
    296      1.1  christos   uv_close((uv_handle_t*)&(sc[0]).handle, NULL);
    297      1.1  christos   uv_close((uv_handle_t*)&(sc[1]).handle, NULL);
    298  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    299  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    300  1.1.1.2  christos   ASSERT_OK(sc[0].ncalls);
    301  1.1.1.2  christos   ASSERT_OK(sc[1].ncalls);
    302  1.1.1.2  christos   ASSERT_EQ(1, sc[2].ncalls);
    303  1.1.1.2  christos   ASSERT_EQ(1, sc[2].ncalls);
    304      1.1  christos 
    305      1.1  christos   /* 1 normal, 1 one-shot, 2 normal then remove 1st normal, 2nd normal */
    306      1.1  christos   start_timer(loop, SIGCHLD, &tc);
    307      1.1  christos   start_watcher(loop, SIGCHLD, sc + 0, 0);
    308      1.1  christos   start_watcher(loop, SIGCHLD, sc + 1, 1);
    309      1.1  christos   start_watcher(loop, SIGCHLD, sc + 2, 0);
    310      1.1  christos   start_watcher(loop, SIGCHLD, sc + 3, 0);
    311      1.1  christos   sc[3].stop_or_close = CLOSE;
    312      1.1  christos   uv_close((uv_handle_t*)&(sc[0]).handle, NULL);
    313      1.1  christos   uv_close((uv_handle_t*)&(sc[2]).handle, NULL);
    314  1.1.1.2  christos   ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
    315  1.1.1.2  christos   ASSERT_EQ(tc.ncalls, NSIGNALS);
    316  1.1.1.2  christos   ASSERT_OK(sc[0].ncalls);
    317  1.1.1.2  christos   ASSERT_EQ(1, sc[1].ncalls);
    318  1.1.1.2  christos   ASSERT_OK(sc[2].ncalls);
    319  1.1.1.2  christos   ASSERT_EQ(sc[3].ncalls, NSIGNALS);
    320      1.1  christos 
    321  1.1.1.2  christos   MAKE_VALGRIND_HAPPY(loop);
    322      1.1  christos   return 0;
    323      1.1  christos }
    324      1.1  christos 
    325      1.1  christos #endif /* _WIN32 */
    326