diff --git a/deps/uv/.travis.yml b/deps/uv/.travis.yml new file mode 100644 index 0000000000..f3b176feca --- /dev/null +++ b/deps/uv/.travis.yml @@ -0,0 +1,9 @@ +language: node_js + +script: + - "make test" + +notifications: + email: false + irc: + - "irc.freenode.net#libuv" diff --git a/deps/uv/src/unix/linux.c b/deps/uv/src/unix/linux.c index d841c49a7c..17e06741ae 100644 --- a/deps/uv/src/unix/linux.c +++ b/deps/uv/src/unix/linux.c @@ -30,15 +30,99 @@ #include #include -#include #include #include #include +#include #include #undef NANOSEC #define NANOSEC 1000000000 +#undef HAVE_INOTIFY_INIT +#undef HAVE_INOTIFY_INIT1 +#undef HAVE_INOTIFY_ADD_WATCH +#undef HAVE_INOTIFY_RM_WATCH + +#if __NR_inotify_init +# define HAVE_INOTIFY_INIT 1 +#endif +#if __NR_inotify_init1 +# define HAVE_INOTIFY_INIT1 1 +#endif +#if __NR_inotify_add_watch +# define HAVE_INOTIFY_ADD_WATCH 1 +#endif +#if __NR_inotify_rm_watch +# define HAVE_INOTIFY_RM_WATCH 1 +#endif + +#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 +# undef IN_ACCESS +# undef IN_MODIFY +# undef IN_ATTRIB +# undef IN_CLOSE_WRITE +# undef IN_CLOSE_NOWRITE +# undef IN_OPEN +# undef IN_MOVED_FROM +# undef IN_MOVED_TO +# undef IN_CREATE +# undef IN_DELETE +# undef IN_DELETE_SELF +# undef IN_MOVE_SELF +# define IN_ACCESS 0x001 +# define IN_MODIFY 0x002 +# define IN_ATTRIB 0x004 +# define IN_CLOSE_WRITE 0x008 +# define IN_CLOSE_NOWRITE 0x010 +# define IN_OPEN 0x020 +# define IN_MOVED_FROM 0x040 +# define IN_MOVED_TO 0x080 +# define IN_CREATE 0x100 +# define IN_DELETE 0x200 +# define IN_DELETE_SELF 0x400 +# define IN_MOVE_SELF 0x800 +struct inotify_event { + int32_t wd; + uint32_t mask; + uint32_t cookie; + uint32_t len; + /* char name[0]; */ +}; +#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ + +#undef IN_CLOEXEC +#undef IN_NONBLOCK + +#if HAVE_INOTIFY_INIT1 +# define IN_CLOEXEC O_CLOEXEC +# define IN_NONBLOCK O_NONBLOCK +#endif /* HAVE_INOTIFY_INIT1 */ + +#if HAVE_INOTIFY_INIT +inline static int inotify_init(void) { + return syscall(__NR_inotify_init); +} +#endif /* HAVE_INOTIFY_INIT */ + +#if HAVE_INOTIFY_INIT1 +inline static int inotify_init1(int flags) { + return syscall(__NR_inotify_init1, flags); +} +#endif /* HAVE_INOTIFY_INIT1 */ + +#if HAVE_INOTIFY_ADD_WATCH +inline static int inotify_add_watch(int fd, const char* path, uint32_t mask) { + return syscall(__NR_inotify_add_watch, fd, path, mask); +} +#endif /* HAVE_INOTIFY_ADD_WATCH */ + +#if HAVE_INOTIFY_RM_WATCH +inline static int inotify_rm_watch(int fd, uint32_t wd) { + return syscall(__NR_inotify_rm_watch, fd, wd); +} +#endif /* HAVE_INOTIFY_RM_WATCH */ + static char buf[MAXPATHLEN + 1]; @@ -65,6 +149,7 @@ uint64_t uv_hrtime() { return (ts.tv_sec * NANOSEC + ts.tv_nsec); } + void uv_loadavg(double avg[3]) { struct sysinfo info; @@ -87,141 +172,16 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } + uint64_t uv_get_free_memory(void) { return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); } + uint64_t uv_get_total_memory(void) { return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); } -static int new_inotify_fd(void) { -#if defined(IN_NONBLOCK) && defined(IN_CLOEXEC) - return inotify_init1(IN_NONBLOCK | IN_CLOEXEC); -#else - int fd; - - if ((fd = inotify_init()) == -1) - return -1; - - if (uv__cloexec(fd, 1) || uv__nonblock(fd, 1)) { - SAVE_ERRNO(uv__close(fd)); - fd = -1; - } - - return fd; -#endif -} - - -static void uv__inotify_read(EV_P_ ev_io* w, int revents) { - struct inotify_event* e; - uv_fs_event_t* handle; - const char* filename; - ssize_t size; - int events; - char *p; - /* needs to be large enough for sizeof(inotify_event) + strlen(filename) */ - char buf[4096]; - - handle = container_of(w, uv_fs_event_t, read_watcher); - - do { - do { - size = read(handle->fd, buf, sizeof buf); - } - while (size == -1 && errno == EINTR); - - if (size == -1) { - assert(errno == EAGAIN || errno == EWOULDBLOCK); - break; - } - - assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ - - /* Now we have one or more inotify_event structs. */ - for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { - e = (void*)p; - - events = 0; - if (e->mask & (IN_ATTRIB|IN_MODIFY)) - events |= UV_CHANGE; - if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) - events |= UV_RENAME; - - /* inotify does not return the filename when monitoring a single file - * for modifications. Repurpose the filename for API compatibility. - * I'm not convinced this is a good thing, maybe it should go. - */ - filename = e->len ? e->name : basename_r(handle->filename); - - handle->cb(handle, filename, events, 0); - - if (handle->fd == -1) - break; - } - } - while (handle->fd != -1); /* handle might've been closed by callback */ -} - - -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* filename, - uv_fs_event_cb cb, - int flags) { - int events; - int fd; - - loop->counters.fs_event_init++; - - /* We don't support any flags yet. */ - assert(!flags); - - /* - * TODO share a single inotify fd across the event loop? - * We'll run into fs.inotify.max_user_instances if we - * keep creating new inotify fds. - */ - if ((fd = new_inotify_fd()) == -1) { - uv__set_sys_error(loop, errno); - return -1; - } - - events = IN_ATTRIB - | IN_CREATE - | IN_MODIFY - | IN_DELETE - | IN_DELETE_SELF - | IN_MOVED_FROM - | IN_MOVED_TO; - - if (inotify_add_watch(fd, filename, events) == -1) { - uv__set_sys_error(loop, errno); - uv__close(fd); - return -1; - } - - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - handle->filename = strdup(filename); /* this should go! */ - handle->cb = cb; - handle->fd = fd; - - ev_io_init(&handle->read_watcher, uv__inotify_read, fd, EV_READ); - ev_io_start(loop->ev, &handle->read_watcher); - - return 0; -} - - -void uv__fs_event_destroy(uv_fs_event_t* handle) { - ev_io_stop(handle->loop->ev, &handle->read_watcher); - uv__close(handle->fd); - handle->fd = -1; - free(handle->filename); - handle->filename = NULL; -} - char** uv_setup_args(int argc, char** argv) { char **new_argv; @@ -294,6 +254,7 @@ uv_err_t uv_resident_set_memory(size_t* rss) { FILE* f; int itmp; char ctmp; + unsigned int utmp; size_t page_size = getpagesize(); char *cbuf; int foundExeEnd; @@ -331,15 +292,15 @@ uv_err_t uv_resident_set_memory(size_t* rss) { /* TTY owner process group */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Flags */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* Minor faults (no memory page) */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* Minor faults, children */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* Major faults (memory page faults) */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* Major faults, children */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* utime */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* stime */ @@ -353,27 +314,27 @@ uv_err_t uv_resident_set_memory(size_t* rss) { /* 'nice' value */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* jiffies until next timeout */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* jiffies until next SIGALRM */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* start time (jiffies since system boot) */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Virtual memory size */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* Resident set size */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ - *rss = (size_t) itmp * page_size; + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ + *rss = (size_t) utmp * page_size; /* rlim */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* Start of text */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* End of text */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ /* Start of stack */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */ fclose (f); return uv_ok_; @@ -408,7 +369,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), multiplier = ((uint64_t)1000L / ticks), cpuspeed; int numcpus = 0, i = 0; - unsigned long long ticks_user, ticks_sys, ticks_idle, ticks_nice, ticks_intr; + unsigned long ticks_user, ticks_sys, ticks_idle, ticks_nice, ticks_intr; char line[512], speedPath[256], model[512]; FILE *fpStat = fopen("/proc/stat", "r"); FILE *fpModel = fopen("/proc/cpuinfo", "r"); @@ -450,7 +411,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { break; } - sscanf(line, "%*s %llu %llu %llu %llu %*llu %llu", + sscanf(line, "%*s %lu %lu %lu %lu %*s %lu", &ticks_user, &ticks_nice, &ticks_sys, &ticks_idle, &ticks_intr); snprintf(speedPath, sizeof(speedPath), "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_max_freq", i); @@ -572,3 +533,152 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses, free(addresses); } + +#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 + +static int new_inotify_fd(void) { +#if HAVE_INOTIFY_INIT1 + return inotify_init1(IN_NONBLOCK | IN_CLOEXEC); +#else + int fd; + + if ((fd = inotify_init()) == -1) + return -1; + + if (uv__cloexec(fd, 1) || uv__nonblock(fd, 1)) { + SAVE_ERRNO(uv__close(fd)); + fd = -1; + } + + return fd; +#endif +} + + +static void uv__inotify_read(EV_P_ ev_io* w, int revents) { + struct inotify_event* e; + uv_fs_event_t* handle; + const char* filename; + ssize_t size; + int events; + char *p; + /* needs to be large enough for sizeof(inotify_event) + strlen(filename) */ + char buf[4096]; + + handle = container_of(w, uv_fs_event_t, read_watcher); + + do { + do { + size = read(handle->fd, buf, sizeof buf); + } + while (size == -1 && errno == EINTR); + + if (size == -1) { + assert(errno == EAGAIN || errno == EWOULDBLOCK); + break; + } + + assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ + + /* Now we have one or more inotify_event structs. */ + for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { + e = (void*)p; + + events = 0; + if (e->mask & (IN_ATTRIB|IN_MODIFY)) + events |= UV_CHANGE; + if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) + events |= UV_RENAME; + + /* inotify does not return the filename when monitoring a single file + * for modifications. Repurpose the filename for API compatibility. + * I'm not convinced this is a good thing, maybe it should go. + */ + filename = e->len ? (const char*) (e + 1) : basename_r(handle->filename); + + handle->cb(handle, filename, events, 0); + + if (handle->fd == -1) + break; + } + } + while (handle->fd != -1); /* handle might've been closed by callback */ +} + + +int uv_fs_event_init(uv_loop_t* loop, + uv_fs_event_t* handle, + const char* filename, + uv_fs_event_cb cb, + int flags) { + int events; + int fd; + + loop->counters.fs_event_init++; + + /* We don't support any flags yet. */ + assert(!flags); + + /* + * TODO share a single inotify fd across the event loop? + * We'll run into fs.inotify.max_user_instances if we + * keep creating new inotify fds. + */ + if ((fd = new_inotify_fd()) == -1) { + uv__set_sys_error(loop, errno); + return -1; + } + + events = IN_ATTRIB + | IN_CREATE + | IN_MODIFY + | IN_DELETE + | IN_DELETE_SELF + | IN_MOVED_FROM + | IN_MOVED_TO; + + if (inotify_add_watch(fd, filename, events) == -1) { + uv__set_sys_error(loop, errno); + uv__close(fd); + return -1; + } + + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); + handle->filename = strdup(filename); /* this should go! */ + handle->cb = cb; + handle->fd = fd; + + ev_io_init(&handle->read_watcher, uv__inotify_read, fd, EV_READ); + ev_io_start(loop->ev, &handle->read_watcher); + + return 0; +} + + +void uv__fs_event_destroy(uv_fs_event_t* handle) { + ev_io_stop(handle->loop->ev, &handle->read_watcher); + uv__close(handle->fd); + handle->fd = -1; + free(handle->filename); + handle->filename = NULL; +} + +#else /* !HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ + +int uv_fs_event_init(uv_loop_t* loop, + uv_fs_event_t* handle, + const char* filename, + uv_fs_event_cb cb, + int flags) { + loop->counters.fs_event_init++; + uv__set_sys_error(loop, ENOSYS); + return -1; +} + + +void uv__fs_event_destroy(uv_fs_event_t* handle) { + assert(0 && "unreachable"); + abort(); +} + +#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 3bbfa83386..5c20fe4801 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -1047,7 +1047,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, ipc_header_req = (uv_write_t*)&handle->ipc_header_write_req; } else { ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t)); - if (!handle->accept_reqs) { + if (!ipc_header_req) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } } diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index dee77875ae..7965f73aa4 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -822,7 +822,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, if (!REQ_SUCCESS(req)) { /* An error occurred doing the read. */ - if ((handle->flags & UV_HANDLE_READING)) { + if ((handle->flags & UV_HANDLE_READING) || + !(handle->flags & UV_HANDLE_ZERO_READ)) { handle->flags &= ~UV_HANDLE_READING; buf = (handle->flags & UV_HANDLE_ZERO_READ) ? uv_buf_init(NULL, 0) : handle->read_buffer; diff --git a/deps/uv/test/benchmark-thread.c b/deps/uv/test/benchmark-thread.c new file mode 100644 index 0000000000..cc7fd938aa --- /dev/null +++ b/deps/uv/test/benchmark-thread.c @@ -0,0 +1,64 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include + +#define NUM_THREADS (100 * 1000) + +static volatile int num_threads; + + +static void thread_entry(void* arg) { + ASSERT(arg == (void *) 42); + num_threads++; + /* FIXME write barrier? */ +} + + +BENCHMARK_IMPL(thread_create) { + uint64_t start_time; + double duration; + uv_thread_t tid; + int i, r; + + start_time = uv_hrtime(); + + for (i = 0; i < NUM_THREADS; i++) { + r = uv_thread_create(&tid, thread_entry, (void *) 42); + ASSERT(r == 0); + + r = uv_thread_join(&tid); + ASSERT(r == 0); + } + + duration = (uv_hrtime() - start_time) / 1e9; + + ASSERT(num_threads == NUM_THREADS); + + printf("%d threads created in %.2f seconds (%.0f/s)\n", + NUM_THREADS, duration, NUM_THREADS / duration); + + return 0; +} diff --git a/deps/uv/test/test-counters-init.c b/deps/uv/test/test-counters-init.c new file mode 100644 index 0000000000..423d349c3b --- /dev/null +++ b/deps/uv/test/test-counters-init.c @@ -0,0 +1,216 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#define UNIX (defined(__unix__) || defined(__POSIX__) || defined(__APPLE__)) +#include "task.h" +#include "uv.h" +#include + +#if UNIX +#include /* unlink, rmdir, etc. */ +#else +# include +# include +# define unlink _unlink +# define rmdir _rmdir +# define stat _stati64 +# define open _open +# define write _write +# define lseek _lseek +# define close _close +#endif + +static char exepath[1024]; +static size_t exepath_size = 1024; +static char* args[3]; +static uv_fs_t open_req; +static uv_tcp_t tcp; +static uv_udp_t udp; +static uv_pipe_t uvpipe; +static uv_tty_t tty; +static uv_prepare_t prepare; +static uv_check_t check; +static uv_idle_t idle; +static uv_async_t async; +static uv_timer_t timer; +static uv_fs_event_t fs_event; +static uv_process_t process; +static uv_process_options_t options; +static uv_fs_t fs_req; + +static void exit_cb(uv_process_t* process, int exit_status, int term_signal) { + ASSERT(exit_status == 1); + ASSERT(term_signal == 0); + uv_close((uv_handle_t*)process, NULL); +} + +static void init_process_options(char* test, uv_exit_cb exit_cb) { + int r = uv_exepath(exepath, &exepath_size); + ASSERT(r == 0); + exepath[exepath_size] = '\0'; + args[0] = exepath; + args[1] = test; + args[2] = NULL; + options.file = exepath; + options.args = args; + options.exit_cb = exit_cb; +} + +static void create_dir(uv_loop_t* loop, const char* name) { + int r; + uv_fs_t req; + r = uv_fs_rmdir(loop, &req, name, NULL); + r = uv_fs_mkdir(loop, &req, name, 0755, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&req); +} + +static void create_cb(uv_fs_t* req) { + ASSERT(req == &open_req); + ASSERT(req->fs_type == UV_FS_OPEN); + ASSERT(req->result != -1); + uv_fs_req_cleanup(req); + unlink("test_file"); +} + +TEST_IMPL(counters_init) { + int r; + int eio_init_prev; + int req_init_prev; + int handle_init_prev; + int stream_init_prev; + int tcp_init_prev; + int udp_init_prev; + int pipe_init_prev; + int tty_init_prev; + int prepare_init_prev; + int check_init_prev; + int idle_init_prev; + int async_init_prev; + int timer_init_prev; + int process_init_prev; + int fs_event_init_prev; + + /* req_init and eio_init test by uv_fs_open() */ + unlink("test_file"); + req_init_prev = uv_default_loop()->counters.req_init; + eio_init_prev = uv_default_loop()->counters.eio_init; + r = uv_fs_open(uv_default_loop(), &open_req, "test_file", O_WRONLY | O_CREAT, + S_IREAD | S_IWRITE, create_cb); + ASSERT(r == 0); + ASSERT(open_req.result == 0); + ASSERT(uv_default_loop()->counters.req_init == ++req_init_prev); +#ifndef _WIN32 + ASSERT(uv_default_loop()->counters.eio_init == ++eio_init_prev); +#endif + + /* tcp_init, stream_init and handle_init test by uv_tcp_init() */ + tcp_init_prev = uv_default_loop()->counters.tcp_init; + stream_init_prev = uv_default_loop()->counters.stream_init; + handle_init_prev = uv_default_loop()->counters.handle_init; + r = uv_tcp_init(uv_default_loop(), &tcp); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.tcp_init == ++tcp_init_prev); + ASSERT(uv_default_loop()->counters.stream_init == ++stream_init_prev); + ASSERT(uv_default_loop()->counters.handle_init == ++handle_init_prev); + uv_close((uv_handle_t*)&tcp, NULL); + + /* udp_init test by uv_udp_init() */ + udp_init_prev = uv_default_loop()->counters.udp_init; + r = uv_udp_init(uv_default_loop(), &udp); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.udp_init == ++udp_init_prev); + uv_close((uv_handle_t*)&udp, NULL); + + /* pipe_init uv_pipe_init() */ + pipe_init_prev = uv_default_loop()->counters.pipe_init; + uv_pipe_init(uv_default_loop(), &uvpipe, 0); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.pipe_init == ++pipe_init_prev); + uv_close((uv_handle_t*)&uvpipe, NULL); + + /* tty_init test by uv_tty_init()*/ + tty_init_prev = uv_default_loop()->counters.tty_init; + r = uv_tty_init(uv_default_loop(), &tty, 1, 0); + /* uv_tty_init() always returns -1 in run_test in Windows + so that we avoid to check return value. + */ +#ifndef _WIN32 + ASSERT(r == 0); + uv_close((uv_handle_t*)&tty, NULL); +#endif + ASSERT(uv_default_loop()->counters.tty_init == ++tty_init_prev); + + /* prepare_init test by uv_prepare_init() */ + prepare_init_prev = uv_default_loop()->counters.prepare_init; + r = uv_prepare_init(uv_default_loop(), &prepare); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.prepare_init == ++prepare_init_prev); + uv_close((uv_handle_t*)&prepare, NULL); + + /* check_init test by uv_check_init() */ + check_init_prev = uv_default_loop()->counters.check_init; + r = uv_check_init(uv_default_loop(), &check); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.check_init == ++check_init_prev); + uv_close((uv_handle_t*)&check, NULL); + + /* idle_init test by uv_idle_init() */ + idle_init_prev = uv_default_loop()->counters.idle_init; + r = uv_idle_init(uv_default_loop(), &idle); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.idle_init == ++idle_init_prev); + uv_close((uv_handle_t*)&idle, NULL); + + /* async_init test by uv_async_init() */ + async_init_prev = uv_default_loop()->counters.async_init; + r = uv_async_init(uv_default_loop(), &async, NULL); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.async_init == ++async_init_prev); + uv_close((uv_handle_t*)&async, NULL); + + /* timer_init test by uv_timer_init() */ + timer_init_prev = uv_default_loop()->counters.timer_init; + r = uv_timer_init(uv_default_loop(), &timer); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.timer_init == ++timer_init_prev); + uv_close((uv_handle_t*)&timer, NULL); + + /* process_init test by uv_spawn() */ + process_init_prev = uv_default_loop()->counters.process_init; + init_process_options("spawn_helper1", exit_cb); + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.process_init == ++process_init_prev); + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + /* fs_event_init test by uv_fs_event_init() */ + create_dir(uv_default_loop(), "watch_dir"); + fs_event_init_prev = uv_default_loop()->counters.fs_event_init; + r = uv_fs_event_init(uv_default_loop(), &fs_event, "watch_dir", NULL, 0); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.fs_event_init == ++fs_event_init_prev); + r = uv_fs_rmdir(uv_default_loop(), &fs_req, "watch_dir", NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&fs_req); + + return 0; +} diff --git a/deps/uv/test/test-platform-output.c b/deps/uv/test/test-platform-output.c new file mode 100644 index 0000000000..99c0551baa --- /dev/null +++ b/deps/uv/test/test-platform-output.c @@ -0,0 +1,83 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" +#include + + +TEST_IMPL(platform_output) { + char buffer[512]; + size_t rss; + double uptime; + uv_cpu_info_t* cpus; + uv_interface_address_t* interfaces; + int count; + int i; + uv_err_t err; + + err = uv_get_process_title(buffer, sizeof(buffer)); + ASSERT(UV_OK == err.code); + fprintf(stderr, "uv_get_process_title: %s\n", buffer); + + err = uv_resident_set_memory(&rss); + ASSERT(UV_OK == err.code); + fprintf(stderr, "uv_resident_set_memory: %d\n", rss); + + err = uv_uptime(&uptime); + ASSERT(UV_OK == err.code); + fprintf(stderr, "uv_uptime: %f\n", uptime); + + err = uv_cpu_info(&cpus, &count); + ASSERT(UV_OK == err.code); + + fprintf(stderr, "uv_cpu_info:\n"); + for (i = 0; i < count; i++) { + fprintf(stderr, " model: %s\n", cpus[i].model); + fprintf(stderr, " speed: %d\n", cpus[i].speed); + fprintf(stderr, " times.sys: %llu\n", cpus[i].cpu_times.sys); + fprintf(stderr, " times.user: %llu\n", cpus[i].cpu_times.user); + fprintf(stderr, " times.idle: %llu\n", cpus[i].cpu_times.idle); + fprintf(stderr, " times.irq: %llu\n", cpus[i].cpu_times.irq); + fprintf(stderr, " times.nice: %llu\n", cpus[i].cpu_times.nice); + } + uv_free_cpu_info(cpus, count); + + err = uv_interface_addresses(&interfaces, &count); + ASSERT(UV_OK == err.code); + + fprintf(stderr, "uv_interface_addresses:\n"); + for (i = 0; i < count; i++) { + fprintf(stderr, " name: %s\n", interfaces[i].name); + fprintf(stderr, " internal: %d\n", interfaces[i].is_internal); + + if (interfaces[i].address.address4.sin_family == AF_INET) { + uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer)); + } else if (interfaces[i].address.address4.sin_family == AF_INET6) { + uv_ip6_name(&interfaces[i].address.address6, buffer, sizeof(buffer)); + } + + fprintf(stderr, " address: %s\n", buffer); + } + uv_free_interface_addresses(interfaces, count); + + return 0; +} diff --git a/deps/uv/test/test-process-title.c b/deps/uv/test/test-process-title.c new file mode 100644 index 0000000000..59fceda31b --- /dev/null +++ b/deps/uv/test/test-process-title.c @@ -0,0 +1,42 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" +#include + +TEST_IMPL(process_title) { + char buffer[512]; + uv_err_t err; + + err = uv_get_process_title(buffer, sizeof(buffer)); + ASSERT(UV_OK == err.code); + + err = uv_set_process_title("new title"); + ASSERT(UV_OK == err.code); + + err = uv_get_process_title(buffer, sizeof(buffer)); + ASSERT(UV_OK == err.code); + + ASSERT(strcmp(buffer, "new title") == 0); + + return 0; +} diff --git a/deps/uv/test/test-run-once.c b/deps/uv/test/test-run-once.c new file mode 100644 index 0000000000..c03ab88e8f --- /dev/null +++ b/deps/uv/test/test-run-once.c @@ -0,0 +1,44 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +static idle_counter = 0; + +static void idle_cb(uv_idle_t* handle, int status) { + ASSERT(handle != NULL); + ASSERT(status == 0); + idle_counter ++; +} + + +TEST_IMPL(run_once) { + int n; + uv_idle_t h; + uv_idle_init(uv_default_loop(), &h); + uv_idle_start(&h, idle_cb); + for (n = 0; n < 500; n++) { + uv_run_once(uv_default_loop()); + } + ASSERT(n == 500); + return 0; +} diff --git a/deps/uv/test/test-thread.c b/deps/uv/test/test-thread.c new file mode 100644 index 0000000000..61aa55a217 --- /dev/null +++ b/deps/uv/test/test-thread.c @@ -0,0 +1,51 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include + + +static volatile int thread_called; + + +static void thread_entry(void* arg) { + ASSERT(arg == (void *) 42); + thread_called++; +} + + +TEST_IMPL(thread_create) { + uv_thread_t tid; + int r; + + r = uv_thread_create(&tid, thread_entry, (void *) 42); + ASSERT(r == 0); + + r = uv_thread_join(&tid); + ASSERT(r == 0); + + ASSERT(thread_called == 1); + + return 0; +} diff --git a/deps/uv/test/test-util.c b/deps/uv/test/test-util.c new file mode 100644 index 0000000000..d61d3b1285 --- /dev/null +++ b/deps/uv/test/test-util.c @@ -0,0 +1,97 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include + +#define memeq(a, b, c) (memcmp((a), (b), (c)) == 0) + + +TEST_IMPL(strlcpy) { + size_t r; + + { + char dst[2] = "A"; + r = uv_strlcpy(dst, "", 0); + ASSERT(r == 0); + ASSERT(memeq(dst, "A", 1)); + } + + { + char dst[2] = "A"; + r = uv_strlcpy(dst, "B", 1); + ASSERT(r == 0); + ASSERT(memeq(dst, "", 1)); + } + + { + char dst[2] = "A"; + r = uv_strlcpy(dst, "B", 2); + ASSERT(r == 1); + ASSERT(memeq(dst, "B", 2)); + } + + { + char dst[3] = "AB"; + r = uv_strlcpy(dst, "CD", 3); + ASSERT(r == 2); + ASSERT(memeq(dst, "CD", 3)); + } + + return 0; +} + + +TEST_IMPL(strlcat) { + size_t r; + + { + char dst[2] = "A"; + r = uv_strlcat(dst, "B", 1); + ASSERT(r == 1); + ASSERT(memeq(dst, "A", 2)); + } + + { + char dst[2] = "A"; + r = uv_strlcat(dst, "B", 2); + ASSERT(r == 1); + ASSERT(memeq(dst, "A", 2)); + } + + { + char dst[3] = "A"; + r = uv_strlcat(dst, "B", 3); + ASSERT(r == 2); + ASSERT(memeq(dst, "AB", 3)); + } + + { + char dst[5] = "AB"; + r = uv_strlcat(dst, "CD", 5); + ASSERT(r == 4); + ASSERT(memeq(dst, "ABCD", 5)); + } + + return 0; +}