Update libuv

This commit is contained in:
KimLS
2017-02-25 14:30:35 -08:00
parent d402b25d69
commit 6033f48b47
115 changed files with 4304 additions and 893 deletions
+13
View File
@@ -56,6 +56,7 @@ int main(int argc, char **argv) {
case 1: return run_tests(0);
case 2: return maybe_run_test(argc, argv);
case 3: return run_test_part(argv[1], argv[2]);
case 4: return maybe_run_test(argc, argv);
default:
fprintf(stderr, "Too many arguments.\n");
fflush(stderr);
@@ -177,5 +178,17 @@ static int maybe_run_test(int argc, char **argv) {
return spawn_stdin_stdout();
}
#ifndef _WIN32
if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) {
uv_uid_t uid = atoi(argv[2]);
uv_gid_t gid = atoi(argv[3]);
ASSERT(uid == getuid());
ASSERT(gid == getgid());
return 1;
}
#endif /* !_WIN32 */
return run_test(argv[1], 0, 1);
}
+20 -22
View File
@@ -43,11 +43,6 @@
/* Do platform-specific initialization. */
int platform_init(int argc, char **argv) {
const char* tap;
tap = getenv("UV_TAP_OUTPUT");
tap_output = (tap != NULL && atoi(tap) > 0);
/* Disable stdio output buffering. */
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
@@ -206,7 +201,11 @@ int process_wait(process_info_t* vec, int n, int timeout) {
if (pthread_attr_init(&attr))
abort();
#if defined(__MVS__)
if (pthread_attr_setstacksize(&attr, 1024 * 1024))
#else
if (pthread_attr_setstacksize(&attr, 256 * 1024))
#endif
abort();
r = pthread_create(&tid, &attr, dowait, &args);
@@ -294,8 +293,7 @@ long int process_output_size(process_info_t *p) {
/* Copy the contents of the stdio output buffer to `fd`. */
int process_copy_output(process_info_t *p, int fd) {
ssize_t nwritten;
int process_copy_output(process_info_t* p, FILE* stream) {
char buf[1024];
int r;
@@ -306,20 +304,8 @@ int process_copy_output(process_info_t *p, int fd) {
}
/* TODO: what if the line is longer than buf */
while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) {
/* TODO: what if write doesn't write the whole buffer... */
nwritten = 0;
if (tap_output)
nwritten += write(fd, "#", 1);
nwritten += write(fd, buf, strlen(buf));
if (nwritten < 0) {
perror("write");
return -1;
}
}
while (fgets(buf, sizeof(buf), p->stdout_file) != NULL)
print_lines(buf, strlen(buf), stream);
if (ferror(p->stdout_file)) {
perror("read");
@@ -390,11 +376,23 @@ void process_cleanup(process_info_t *p) {
/* Move the console cursor one line up and back to the first column. */
void rewind_cursor(void) {
#if defined(__MVS__)
fprintf(stderr, "\047[2K\r");
#else
fprintf(stderr, "\033[2K\r");
#endif
}
/* Pause the calling thread for a number of milliseconds. */
void uv_sleep(int msec) {
usleep(msec * 1000);
int sec;
int usec;
sec = msec / 1000;
usec = (msec % 1000) * 1000;
if (sec > 0)
sleep(sec);
if (usec > 0)
usleep(usec);
}
+3 -30
View File
@@ -44,11 +44,6 @@
/* Do platform-specific initialization. */
int platform_init(int argc, char **argv) {
const char* tap;
tap = getenv("UV_TAP_OUTPUT");
tap_output = (tap != NULL && atoi(tap) > 0);
/* Disable the "application crashed" popup. */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
@@ -213,10 +208,9 @@ long int process_output_size(process_info_t *p) {
}
int process_copy_output(process_info_t *p, int fd) {
int process_copy_output(process_info_t* p, FILE* stream) {
DWORD read;
char buf[1024];
char *line, *start;
if (SetFilePointer(p->stdio_out,
0,
@@ -225,29 +219,8 @@ int process_copy_output(process_info_t *p, int fd) {
return -1;
}
if (tap_output)
write(fd, "#", 1);
while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) &&
read > 0) {
if (tap_output) {
start = buf;
while ((line = strchr(start, '\n')) != NULL) {
write(fd, start, line - start + 1);
write(fd, "#", 1);
start = line + 1;
}
if (start < buf + read)
write(fd, start, buf + read - start);
} else {
write(fd, buf, read);
}
}
if (tap_output)
write(fd, "\n", 1);
while (ReadFile(p->stdio_out, &buf, sizeof(buf), &read, NULL) && read > 0)
print_lines(buf, read, stream);
if (GetLastError() != ERROR_HANDLE_EOF)
return -1;
+29 -73
View File
@@ -28,31 +28,6 @@
char executable_path[sizeof(executable_path)];
int tap_output = 0;
static void log_progress(int total,
int passed,
int failed,
int todos,
int skipped,
const char* name) {
int progress;
if (total == 0)
total = 1;
progress = 100 * (passed + failed + skipped + todos) / total;
fprintf(stderr, "[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s",
progress,
passed,
failed,
todos,
skipped,
name);
fflush(stderr);
}
const char* fmt(double d) {
static char buf[1024];
@@ -95,7 +70,6 @@ int run_tests(int benchmark_output) {
int total;
int passed;
int failed;
int todos;
int skipped;
int current;
int test_result;
@@ -109,15 +83,12 @@ int run_tests(int benchmark_output) {
}
}
if (tap_output) {
fprintf(stderr, "1..%d\n", total);
fflush(stderr);
}
fprintf(stderr, "1..%d\n", total);
fflush(stderr);
/* Run all tests. */
passed = 0;
failed = 0;
todos = 0;
skipped = 0;
current = 1;
for (task = TASKS; task->main; task++) {
@@ -125,30 +96,15 @@ int run_tests(int benchmark_output) {
continue;
}
if (!tap_output)
rewind_cursor();
if (!benchmark_output && !tap_output) {
log_progress(total, passed, failed, todos, skipped, task->task_name);
}
test_result = run_test(task->task_name, benchmark_output, current);
switch (test_result) {
case TEST_OK: passed++; break;
case TEST_TODO: todos++; break;
case TEST_SKIP: skipped++; break;
default: failed++;
}
current++;
}
if (!tap_output)
rewind_cursor();
if (!benchmark_output && !tap_output) {
log_progress(total, passed, failed, todos, skipped, "Done.\n");
}
return failed;
}
@@ -166,10 +122,6 @@ void log_tap_result(int test_count,
result = "ok";
directive = "";
break;
case TEST_TODO:
result = "not ok";
directive = " # TODO ";
break;
case TEST_SKIP:
result = "ok";
directive = " # SKIP ";
@@ -179,8 +131,7 @@ void log_tap_result(int test_count,
directive = "";
}
if ((status == TEST_SKIP || status == TEST_TODO) &&
process_output_size(process) > 0) {
if (status == TEST_SKIP && process_output_size(process) > 0) {
process_read_last_line(process, reason, sizeof reason);
} else {
reason[0] = '\0';
@@ -194,7 +145,7 @@ void log_tap_result(int test_count,
int run_test(const char* test,
int benchmark_output,
int test_count) {
char errmsg[1024] = "no error";
char errmsg[1024] = "";
process_info_t processes[1024];
process_info_t *main_proc;
task_entry_t* task;
@@ -319,22 +270,13 @@ out:
FATAL("process_wait failed");
}
if (tap_output)
log_tap_result(test_count, test, status, &processes[i]);
log_tap_result(test_count, test, status, &processes[i]);
/* Show error and output from processes if the test failed. */
if (status != 0 || task->show_output) {
if (tap_output) {
fprintf(stderr, "#");
} else if (status == TEST_TODO) {
fprintf(stderr, "\n`%s` todo\n", test);
} else if (status == TEST_SKIP) {
fprintf(stderr, "\n`%s` skipped\n", test);
} else if (status != 0) {
fprintf(stderr, "\n`%s` failed: %s\n", test, errmsg);
} else {
fprintf(stderr, "\n");
}
if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) {
if (strlen(errmsg) > 0)
fprintf(stderr, "# %s\n", errmsg);
fprintf(stderr, "# ");
fflush(stderr);
for (i = 0; i < process_count; i++) {
@@ -354,15 +296,11 @@ out:
default:
fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i]));
fflush(stderr);
process_copy_output(&processes[i], fileno(stderr));
process_copy_output(&processes[i], stderr);
break;
}
}
if (!tap_output) {
fprintf(stderr, "=============================================================\n");
}
/* In benchmark mode show concise output from the main process. */
} else if (benchmark_output) {
switch (process_output_size(main_proc)) {
@@ -378,7 +316,7 @@ out:
default:
for (i = 0; i < process_count; i++) {
process_copy_output(&processes[i], fileno(stderr));
process_copy_output(&processes[i], stderr);
}
break;
}
@@ -464,3 +402,21 @@ void print_tests(FILE* stream) {
}
}
}
void print_lines(const char* buffer, size_t size, FILE* stream) {
const char* start;
const char* end;
start = buffer;
while ((end = memchr(start, '\n', &buffer[size] - start))) {
fprintf(stream, "# %.*s\n", (int) (end - start), start);
fflush(stream);
start = end + 1;
}
if (start < &buffer[size]) {
fprintf(stream, "# %s\n", start);
fflush(stream);
}
}
+4 -5
View File
@@ -126,6 +126,8 @@ int run_test_part(const char* test, const char* part);
*/
void print_tests(FILE* stream);
/* Print lines in |buffer| as TAP diagnostics to |stream|. */
void print_lines(const char* buffer, size_t size, FILE* stream);
/*
* Stuff that should be implemented by test-runner-<platform>.h
@@ -148,8 +150,8 @@ int process_wait(process_info_t *vec, int n, int timeout);
/* Returns the number of bytes in the stdio output buffer for process `p`. */
long int process_output_size(process_info_t *p);
/* Copy the contents of the stdio output buffer to `fd`. */
int process_copy_output(process_info_t *p, int fd);
/* Copy the contents of the stdio output buffer to `stream`. */
int process_copy_output(process_info_t* p, FILE* stream);
/* Copy the last line of the stdio output buffer to `buffer` */
int process_read_last_line(process_info_t *p,
@@ -172,7 +174,4 @@ void process_cleanup(process_info_t *p);
/* Move the console cursor one line up and back to the first column. */
void rewind_cursor(void);
/* trigger output as tap */
extern int tap_output;
#endif /* RUNNER_H_ */
-8
View File
@@ -136,7 +136,6 @@ const char* fmt(double d);
/* Reserved test exit codes. */
enum test_status {
TEST_OK = 0,
TEST_TODO,
TEST_SKIP
};
@@ -145,13 +144,6 @@ enum test_status {
return TEST_OK; \
} while (0)
#define RETURN_TODO(explanation) \
do { \
fprintf(stderr, "%s\n", explanation); \
fflush(stderr); \
return TEST_TODO; \
} while (0)
#define RETURN_SKIP(explanation) \
do { \
fprintf(stderr, "%s\n", explanation); \
+1
View File
@@ -29,6 +29,7 @@
# if defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_KQUEUE 1
+2 -2
View File
@@ -38,12 +38,12 @@ static uv_tcp_t client_handle;
TEST_IMPL(emfile) {
#ifdef _AIX
#if defined(_AIX) || defined(__MVS__)
/* On AIX, if a 'accept' call fails ECONNRESET is set on the socket
* which causes uv__emfile_trick to not work as intended and this test
* to fail.
*/
RETURN_SKIP("uv__emfile_trick does not work on AIX");
RETURN_SKIP("uv__emfile_trick does not work on this OS");
#endif
struct sockaddr_in addr;
struct rlimit limits;
+23
View File
@@ -21,6 +21,9 @@
#include "uv.h"
#include "task.h"
#if defined(_WIN32)
# include "../src/win/winapi.h"
#endif
#include <stdio.h>
#include <stdlib.h>
@@ -48,3 +51,23 @@ TEST_IMPL(error_message) {
return 0;
}
TEST_IMPL(sys_error) {
#if defined(_WIN32)
ASSERT(uv_translate_sys_error(ERROR_NOACCESS) == UV_EACCES);
ASSERT(uv_translate_sys_error(ERROR_ELEVATION_REQUIRED) == UV_EACCES);
ASSERT(uv_translate_sys_error(WSAEADDRINUSE) == UV_EADDRINUSE);
ASSERT(uv_translate_sys_error(ERROR_BAD_PIPE) == UV_EPIPE);
#else
ASSERT(uv_translate_sys_error(EPERM) == UV_EPERM);
ASSERT(uv_translate_sys_error(EPIPE) == UV_EPIPE);
ASSERT(uv_translate_sys_error(EINVAL) == UV_EINVAL);
#endif
ASSERT(uv_translate_sys_error(UV_EINVAL) == UV_EINVAL);
ASSERT(uv_translate_sys_error(UV_ERANGE) == UV_ERANGE);
ASSERT(uv_translate_sys_error(UV_EACCES) == UV_EACCES);
ASSERT(uv_translate_sys_error(0) == 0);
return 0;
}
+134 -41
View File
@@ -29,12 +29,19 @@
# if defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_KQUEUE 1
# endif
#endif
#if defined(__arm__)/* Increase the timeout so the test passes on arm CI bots */
# define CREATE_TIMEOUT 100
#else
# define CREATE_TIMEOUT 1
#endif
static uv_fs_event_t fs_event;
static const char file_prefix[] = "fsevent-";
static const int fs_event_file_count = 16;
@@ -53,6 +60,14 @@ static char fs_event_filename[PATH_MAX];
static char fs_event_filename[1024];
#endif /* defined(PATH_MAX) */
static int timer_cb_touch_called;
static int timer_cb_exact_called;
static void fs_event_fail(uv_fs_event_t* handle,
const char* filename,
int events,
int status) {
ASSERT(0 && "should never be called");
}
static void create_dir(const char* name) {
int r;
@@ -143,7 +158,10 @@ static void fs_event_create_files(uv_timer_t* handle) {
if (++fs_event_created < fs_event_file_count) {
/* Create another file on a different event loop tick. We do it this way
* to avoid fs events coalescing into one fs event. */
ASSERT(0 == uv_timer_start(&timer, fs_event_create_files, 1, 0));
ASSERT(0 == uv_timer_start(&timer,
fs_event_create_files,
CREATE_TIMEOUT,
0));
}
}
@@ -254,6 +272,14 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
const char* filename,
int events,
int status) {
#ifdef _WIN32
/* Each file created (or deleted) will cause this callback to be called twice
* under Windows: once with the name of the file, and second time with the
* name of the directory. We will ignore the callback for the directory
* itself. */
if (filename && strcmp(filename, file_prefix_in_subdir) == 0)
return;
#endif
fs_event_cb_called++;
ASSERT(handle == &fs_event);
ASSERT(status == 0);
@@ -345,6 +371,21 @@ static void timer_cb_touch(uv_timer_t* timer) {
timer_cb_touch_called++;
}
static void timer_cb_exact(uv_timer_t* handle) {
int r;
if (timer_cb_exact_called == 0) {
touch_file("watch_dir/file.js");
} else {
uv_close((uv_handle_t*)handle, NULL);
r = uv_fs_event_stop(&fs_event);
ASSERT(r == 0);
uv_close((uv_handle_t*) &fs_event, NULL);
}
++timer_cb_exact_called;
}
static void timer_cb_watch_twice(uv_timer_t* handle) {
uv_fs_event_t* handles = handle->data;
uv_close((uv_handle_t*) (handles + 0), NULL);
@@ -353,6 +394,10 @@ static void timer_cb_watch_twice(uv_timer_t* handle) {
}
TEST_IMPL(fs_event_watch_dir) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop = uv_default_loop();
int r;
@@ -432,6 +477,10 @@ TEST_IMPL(fs_event_watch_dir_recursive) {
TEST_IMPL(fs_event_watch_file) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop = uv_default_loop();
int r;
@@ -467,7 +516,54 @@ TEST_IMPL(fs_event_watch_file) {
return 0;
}
TEST_IMPL(fs_event_watch_file_exact_path) {
/*
This test watches a file named "file.jsx" and modifies a file named
"file.js". The test verifies that no events occur for file.jsx.
*/
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop;
int r;
loop = uv_default_loop();
/* Setup */
remove("watch_dir/file.js");
remove("watch_dir/file.jsx");
remove("watch_dir/");
create_dir("watch_dir");
create_file("watch_dir/file.js");
create_file("watch_dir/file.jsx");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file.jsx", 0);
ASSERT(r == 0);
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
r = uv_timer_start(&timer, timer_cb_exact, 100, 100);
ASSERT(r == 0);
r = uv_run(loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(timer_cb_exact_called == 2);
/* Cleanup */
remove("watch_dir/file.js");
remove("watch_dir/file.jsx");
remove("watch_dir/");
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_event_watch_file_twice) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
const char path[] = "test/fixtures/empty_file";
uv_fs_event_t watchers[2];
uv_timer_t timer;
@@ -489,6 +585,9 @@ TEST_IMPL(fs_event_watch_file_twice) {
}
TEST_IMPL(fs_event_watch_file_current_dir) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_timer_t timer;
uv_loop_t* loop;
int r;
@@ -559,6 +658,10 @@ TEST_IMPL(fs_event_watch_file_root_dir) {
#endif
TEST_IMPL(fs_event_no_callback_after_close) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop = uv_default_loop();
int r;
@@ -593,6 +696,10 @@ TEST_IMPL(fs_event_no_callback_after_close) {
}
TEST_IMPL(fs_event_no_callback_on_close) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop = uv_default_loop();
int r;
@@ -626,12 +733,6 @@ TEST_IMPL(fs_event_no_callback_on_close) {
}
static void fs_event_fail(uv_fs_event_t* handle, const char* filename,
int events, int status) {
ASSERT(0 && "should never be called");
}
static void timer_cb(uv_timer_t* handle) {
int r;
@@ -646,6 +747,9 @@ static void timer_cb(uv_timer_t* handle) {
TEST_IMPL(fs_event_immediate_close) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_timer_t timer;
uv_loop_t* loop;
int r;
@@ -668,6 +772,9 @@ TEST_IMPL(fs_event_immediate_close) {
TEST_IMPL(fs_event_close_with_pending_event) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop;
int r;
@@ -698,20 +805,6 @@ TEST_IMPL(fs_event_close_with_pending_event) {
return 0;
}
#if defined(HAVE_KQUEUE) || defined(_AIX)
/* kqueue doesn't register fs events if you don't have an active watcher.
* The file descriptor needs to be part of the kqueue set of interest and
* that's not the case until we actually enter the event loop.
* This is also observed on AIX with ahafs.
*/
TEST_IMPL(fs_event_close_in_callback) {
fprintf(stderr, "Skipping test, doesn't work with kqueue and AIX.\n");
return 0;
}
#else /* !HAVE_KQUEUE || !_AIX */
static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename,
int events, int status) {
ASSERT(status == 0);
@@ -724,52 +817,49 @@ static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename,
}
}
TEST_IMPL(fs_event_close_in_callback) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop;
int r;
loop = uv_default_loop();
fs_event_unlink_files(NULL);
create_dir("watch_dir");
create_file("watch_dir/file1");
create_file("watch_dir/file2");
create_file("watch_dir/file3");
create_file("watch_dir/file4");
create_file("watch_dir/file5");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_cb_close, "watch_dir", 0);
ASSERT(r == 0);
/* Generate a couple of fs events. */
touch_file("watch_dir/file1");
touch_file("watch_dir/file2");
touch_file("watch_dir/file3");
touch_file("watch_dir/file4");
touch_file("watch_dir/file5");
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
r = uv_timer_start(&timer, fs_event_create_files, 100, 0);
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(close_cb_called == 1);
uv_close((uv_handle_t*)&timer, close_cb);
uv_run(loop, UV_RUN_ONCE);
ASSERT(close_cb_called == 2);
ASSERT(fs_event_cb_called == 3);
/* Clean up */
remove("watch_dir/file1");
remove("watch_dir/file2");
remove("watch_dir/file3");
remove("watch_dir/file4");
remove("watch_dir/file5");
fs_event_unlink_files(NULL);
remove("watch_dir/");
MAKE_VALGRIND_HAPPY();
return 0;
}
#endif /* HAVE_KQUEUE || _AIX */
TEST_IMPL(fs_event_start_and_close) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop;
uv_fs_event_t fs_event1;
uv_fs_event_t fs_event2;
@@ -802,6 +892,9 @@ TEST_IMPL(fs_event_start_and_close) {
}
TEST_IMPL(fs_event_getpath) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_loop_t* loop = uv_default_loop();
int r;
char buf[1024];
+85 -12
View File
@@ -29,7 +29,7 @@
/* FIXME we shouldn't need to branch in this file */
#if defined(__unix__) || defined(__POSIX__) || \
defined(__APPLE__) || defined(_AIX)
defined(__APPLE__) || defined(_AIX) || defined(__MVS__)
#include <unistd.h> /* unlink, rmdir, etc. */
#else
# include <direct.h>
@@ -510,6 +510,18 @@ static void empty_scandir_cb(uv_fs_t* req) {
scandir_cb_count++;
}
static void non_existent_scandir_cb(uv_fs_t* req) {
uv_dirent_t dent;
ASSERT(req == &scandir_req);
ASSERT(req->fs_type == UV_FS_SCANDIR);
ASSERT(req->result == UV_ENOENT);
ASSERT(req->ptr == NULL);
ASSERT(UV_ENOENT == uv_fs_scandir_next(req, &dent));
uv_fs_req_cleanup(req);
scandir_cb_count++;
}
static void file_scandir_cb(uv_fs_t* req) {
ASSERT(req == &scandir_req);
@@ -662,8 +674,8 @@ static void check_utime(const char* path, double atime, double mtime) {
ASSERT(req.result == 0);
s = &req.statbuf;
ASSERT(s->st_atim.tv_sec == atime);
ASSERT(s->st_mtim.tv_sec == mtime);
ASSERT(s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime);
ASSERT(s->st_mtim.tv_sec + (s->st_mtim.tv_nsec / 1000000000.0) == mtime);
uv_fs_req_cleanup(&req);
}
@@ -1134,10 +1146,22 @@ TEST_IMPL(fs_fstat) {
ASSERT(s->st_mtim.tv_nsec == 0);
ASSERT(s->st_ctim.tv_sec == t.st_ctime);
ASSERT(s->st_ctim.tv_nsec == 0);
#elif defined(__sun) || \
defined(_BSD_SOURCE) || \
defined(_SVID_SOURCE) || \
defined(_XOPEN_SOURCE) || \
#elif defined(__ANDROID__)
ASSERT(s->st_atim.tv_sec == t.st_atime);
ASSERT(s->st_atim.tv_nsec == t.st_atimensec);
ASSERT(s->st_mtim.tv_sec == t.st_mtime);
ASSERT(s->st_mtim.tv_nsec == t.st_mtimensec);
ASSERT(s->st_ctim.tv_sec == t.st_ctime);
ASSERT(s->st_ctim.tv_nsec == t.st_ctimensec);
#elif defined(__sun) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__) || \
defined(_GNU_SOURCE) || \
defined(_BSD_SOURCE) || \
defined(_SVID_SOURCE) || \
defined(_XOPEN_SOURCE) || \
defined(_DEFAULT_SOURCE)
ASSERT(s->st_atim.tv_sec == t.st_atim.tv_sec);
ASSERT(s->st_atim.tv_nsec == t.st_atim.tv_nsec);
@@ -1145,10 +1169,8 @@ TEST_IMPL(fs_fstat) {
ASSERT(s->st_mtim.tv_nsec == t.st_mtim.tv_nsec);
ASSERT(s->st_ctim.tv_sec == t.st_ctim.tv_sec);
ASSERT(s->st_ctim.tv_nsec == t.st_ctim.tv_nsec);
# if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# if defined(__FreeBSD__) || \
defined(__NetBSD__)
ASSERT(s->st_birthtim.tv_sec == t.st_birthtim.tv_sec);
ASSERT(s->st_birthtim.tv_nsec == t.st_birthtim.tv_nsec);
ASSERT(s->st_flags == t.st_flags);
@@ -1968,6 +1990,15 @@ TEST_IMPL(fs_utime) {
atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
/*
* Test sub-second timestamps only on Windows (assuming NTFS). Some other
* platforms support sub-second timestamps, but that support is filesystem-
* dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps.
*/
#ifdef _WIN32
mtime += 0.444; /* 1982-09-10 11:22:33.444 */
#endif
r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
@@ -2055,6 +2086,15 @@ TEST_IMPL(fs_futime) {
atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
/*
* Test sub-second timestamps only on Windows (assuming NTFS). Some other
* platforms support sub-second timestamps, but that support is filesystem-
* dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps.
*/
#ifdef _WIN32
mtime += 0.444; /* 1982-09-10 11:22:33.444 */
#endif
r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
@@ -2147,6 +2187,39 @@ TEST_IMPL(fs_scandir_empty_dir) {
}
TEST_IMPL(fs_scandir_non_existent_dir) {
const char* path;
uv_fs_t req;
uv_dirent_t dent;
int r;
path = "./non_existent_dir/";
loop = uv_default_loop();
uv_fs_rmdir(NULL, &req, path, NULL);
uv_fs_req_cleanup(&req);
/* Fill the req to ensure that required fields are cleaned up */
memset(&req, 0xdb, sizeof(req));
r = uv_fs_scandir(NULL, &req, path, 0, NULL);
ASSERT(r == UV_ENOENT);
ASSERT(req.result == UV_ENOENT);
ASSERT(req.ptr == NULL);
ASSERT(UV_ENOENT == uv_fs_scandir_next(&req, &dent));
uv_fs_req_cleanup(&req);
r = uv_fs_scandir(loop, &scandir_req, path, 0, non_existent_scandir_cb);
ASSERT(r == 0);
ASSERT(scandir_cb_count == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(scandir_cb_count == 1);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_scandir_file) {
const char* path;
int r;
@@ -2605,7 +2678,7 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) {
r = uv_fs_read(NULL, &read_req, open_req1.result,
iovs, iovcount, offset, NULL);
ASSERT(r >= 0);
ASSERT(read_req.result == sizeof(test_buf) * iovcount);
ASSERT((size_t)read_req.result == sizeof(test_buf) * iovcount);
for (index = 0; index < iovcount; ++index)
ASSERT(strncmp(buffer + index * sizeof(test_buf),
+7
View File
@@ -83,6 +83,13 @@ static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle,
TEST_IMPL(getaddrinfo_fail) {
uv_getaddrinfo_t req;
ASSERT(UV_EINVAL == uv_getaddrinfo(uv_default_loop(),
&req,
(uv_getaddrinfo_cb) abort,
NULL,
NULL,
NULL));
/* Use a FQDN by ending in a period */
ASSERT(0 == uv_getaddrinfo(uv_default_loop(),
&req,
+67 -62
View File
@@ -68,8 +68,8 @@ static struct echo_ctx ctx2;
/* Used in write2_cb to decide if we need to cleanup or not */
static int is_child_process;
static int is_in_process;
static int read_cb_called;
static int recv_cb_called;
static int read_cb_count;
static int recv_cb_count;
static int write2_cb_called;
@@ -91,43 +91,46 @@ static void recv_cb(uv_stream_t* handle,
int r;
union handles* recv;
if (++recv_cb_called == 1) {
recv = &ctx.recv;
} else {
recv = &ctx.recv2;
}
pipe = (uv_pipe_t*) handle;
ASSERT(pipe == &ctx.channel);
/* Depending on the OS, the final recv_cb can be called after the child
* process has terminated which can result in nread being UV_EOF instead of
* the number of bytes read. Since the other end of the pipe has closed this
* UV_EOF is an acceptable value. */
if (nread == UV_EOF) {
/* UV_EOF is only acceptable for the final recv_cb call */
ASSERT(recv_cb_called == 2);
} else {
ASSERT(nread >= 0);
ASSERT(1 == uv_pipe_pending_count(pipe));
do {
if (++recv_cb_count == 1) {
recv = &ctx.recv;
} else {
recv = &ctx.recv2;
}
pending = uv_pipe_pending_type(pipe);
ASSERT(pending == ctx.expected_type);
/* Depending on the OS, the final recv_cb can be called after
* the child process has terminated which can result in nread
* being UV_EOF instead of the number of bytes read. Since
* the other end of the pipe has closed this UV_EOF is an
* acceptable value. */
if (nread == UV_EOF) {
/* UV_EOF is only acceptable for the final recv_cb call */
ASSERT(recv_cb_count == 2);
} else {
ASSERT(nread >= 0);
ASSERT(uv_pipe_pending_count(pipe) > 0);
if (pending == UV_NAMED_PIPE)
r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0);
else if (pending == UV_TCP)
r = uv_tcp_init(ctx.channel.loop, &recv->tcp);
else
abort();
ASSERT(r == 0);
pending = uv_pipe_pending_type(pipe);
ASSERT(pending == ctx.expected_type);
r = uv_accept(handle, &recv->stream);
ASSERT(r == 0);
}
if (pending == UV_NAMED_PIPE)
r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0);
else if (pending == UV_TCP)
r = uv_tcp_init(ctx.channel.loop, &recv->tcp);
else
abort();
ASSERT(r == 0);
r = uv_accept(handle, &recv->stream);
ASSERT(r == 0);
}
} while (uv_pipe_pending_count(pipe) > 0);
/* Close after two writes received */
if (recv_cb_called == 2) {
if (recv_cb_count == 2) {
uv_close((uv_handle_t*)&ctx.channel, NULL);
}
}
@@ -186,7 +189,7 @@ static int run_test(int inprocess) {
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(recv_cb_called == 2);
ASSERT(recv_cb_count == 2);
if (inprocess) {
r = uv_thread_join(&tid);
@@ -293,41 +296,43 @@ static void read_cb(uv_stream_t* handle,
return;
}
if (++read_cb_called == 2) {
recv = &ctx2.recv;
write_req = &ctx2.write_req;
} else {
recv = &ctx2.recv2;
write_req = &ctx2.write_req2;
}
pipe = (uv_pipe_t*) handle;
ASSERT(pipe == &ctx2.channel);
ASSERT(nread >= 0);
ASSERT(1 == uv_pipe_pending_count(pipe));
do {
if (++read_cb_count == 2) {
recv = &ctx2.recv;
write_req = &ctx2.write_req;
} else {
recv = &ctx2.recv2;
write_req = &ctx2.write_req2;
}
pending = uv_pipe_pending_type(pipe);
ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP);
ASSERT(pipe == &ctx2.channel);
ASSERT(nread >= 0);
ASSERT(uv_pipe_pending_count(pipe) > 0);
if (pending == UV_NAMED_PIPE)
r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0);
else if (pending == UV_TCP)
r = uv_tcp_init(ctx2.channel.loop, &recv->tcp);
else
abort();
ASSERT(r == 0);
pending = uv_pipe_pending_type(pipe);
ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP);
r = uv_accept(handle, &recv->stream);
ASSERT(r == 0);
if (pending == UV_NAMED_PIPE)
r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0);
else if (pending == UV_TCP)
r = uv_tcp_init(ctx2.channel.loop, &recv->tcp);
else
abort();
ASSERT(r == 0);
wrbuf = uv_buf_init(".", 1);
r = uv_write2(write_req,
(uv_stream_t*)&ctx2.channel,
&wrbuf,
1,
&recv->stream,
write2_cb);
ASSERT(r == 0);
r = uv_accept(handle, &recv->stream);
ASSERT(r == 0);
wrbuf = uv_buf_init(".", 1);
r = uv_write2(write_req,
(uv_stream_t*)&ctx2.channel,
&wrbuf,
1,
&recv->stream,
write2_cb);
ASSERT(r == 0);
} while (uv_pipe_pending_count(pipe) > 0);
}
static void send_recv_start() {
+33 -2
View File
@@ -19,6 +19,8 @@
* IN THE SOFTWARE.
*/
#include "uv.h"
TEST_DECLARE (platform_output)
TEST_DECLARE (callback_order)
TEST_DECLARE (close_order)
@@ -45,6 +47,8 @@ TEST_DECLARE (semaphore_3)
TEST_DECLARE (tty)
#ifdef _WIN32
TEST_DECLARE (tty_raw)
TEST_DECLARE (tty_empty_write)
TEST_DECLARE (tty_large_write)
#endif
TEST_DECLARE (tty_file)
TEST_DECLARE (tty_pty)
@@ -59,6 +63,7 @@ TEST_DECLARE (ipc_send_recv_pipe_inprocess)
TEST_DECLARE (ipc_send_recv_tcp)
TEST_DECLARE (ipc_send_recv_tcp_inprocess)
TEST_DECLARE (ipc_tcp_connection)
TEST_DECLARE (tcp_alloc_cb_fail)
TEST_DECLARE (tcp_ping_pong)
TEST_DECLARE (tcp_ping_pong_v6)
TEST_DECLARE (pipe_ping_pong)
@@ -104,6 +109,7 @@ TEST_DECLARE (tcp_bind6_error_addrnotavail)
TEST_DECLARE (tcp_bind6_error_fault)
TEST_DECLARE (tcp_bind6_error_inval)
TEST_DECLARE (tcp_bind6_localhost_ok)
TEST_DECLARE (udp_alloc_cb_fail)
TEST_DECLARE (udp_bind)
TEST_DECLARE (udp_bind_reuseaddr)
TEST_DECLARE (udp_create_early)
@@ -148,6 +154,7 @@ TEST_DECLARE (shutdown_eof)
TEST_DECLARE (shutdown_twice)
TEST_DECLARE (callback_stack)
TEST_DECLARE (error_message)
TEST_DECLARE (sys_error)
TEST_DECLARE (timer)
TEST_DECLARE (timer_init)
TEST_DECLARE (timer_again)
@@ -273,6 +280,7 @@ TEST_DECLARE (fs_read_file_eof)
TEST_DECLARE (fs_event_watch_dir)
TEST_DECLARE (fs_event_watch_dir_recursive)
TEST_DECLARE (fs_event_watch_file)
TEST_DECLARE (fs_event_watch_file_exact_path)
TEST_DECLARE (fs_event_watch_file_twice)
TEST_DECLARE (fs_event_watch_file_current_dir)
#ifdef _WIN32
@@ -287,6 +295,7 @@ TEST_DECLARE (fs_event_start_and_close)
TEST_DECLARE (fs_event_error_reporting)
TEST_DECLARE (fs_event_getpath)
TEST_DECLARE (fs_scandir_empty_dir)
TEST_DECLARE (fs_scandir_non_existent_dir)
TEST_DECLARE (fs_scandir_file)
TEST_DECLARE (fs_open_dir)
TEST_DECLARE (fs_rename_to_existing_file)
@@ -314,13 +323,19 @@ TEST_DECLARE (poll_duplex)
TEST_DECLARE (poll_unidirectional)
TEST_DECLARE (poll_close)
TEST_DECLARE (poll_bad_fdtype)
#ifdef __linux__
TEST_DECLARE (poll_nested_epoll)
#endif
#ifdef UV_HAVE_KQUEUE
TEST_DECLARE (poll_nested_kqueue)
#endif
TEST_DECLARE (ip4_addr)
TEST_DECLARE (ip6_addr_link_local)
#ifdef _WIN32
TEST_DECLARE (poll_close_doesnt_corrupt_stack)
TEST_DECLARE (poll_closesocket)
#ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
#if !defined(USING_UV_SHARED)
TEST_DECLARE (argument_escaping)
@@ -331,6 +346,7 @@ TEST_DECLARE (listen_no_simultaneous_accepts)
TEST_DECLARE (fs_stat_root)
TEST_DECLARE (spawn_with_an_odd_path)
TEST_DECLARE (ipc_listen_after_bind_twice)
TEST_DECLARE (win32_signum_number)
#else
TEST_DECLARE (emfile)
TEST_DECLARE (close_fd)
@@ -392,6 +408,8 @@ TASK_LIST_START
TEST_ENTRY (tty)
#ifdef _WIN32
TEST_ENTRY (tty_raw)
TEST_ENTRY (tty_empty_write)
TEST_ENTRY (tty_large_write)
#endif
TEST_ENTRY (tty_file)
TEST_ENTRY (tty_pty)
@@ -407,6 +425,8 @@ TASK_LIST_START
TEST_ENTRY (ipc_send_recv_tcp_inprocess)
TEST_ENTRY (ipc_tcp_connection)
TEST_ENTRY (tcp_alloc_cb_fail)
TEST_ENTRY (tcp_ping_pong)
TEST_HELPER (tcp_ping_pong, tcp4_echo_server)
@@ -474,6 +494,7 @@ TASK_LIST_START
TEST_ENTRY (tcp_bind6_error_inval)
TEST_ENTRY (tcp_bind6_localhost_ok)
TEST_ENTRY (udp_alloc_cb_fail)
TEST_ENTRY (udp_bind)
TEST_ENTRY (udp_bind_reuseaddr)
TEST_ENTRY (udp_create_early)
@@ -528,6 +549,7 @@ TASK_LIST_START
TEST_HELPER (callback_stack, tcp4_echo_server)
TEST_ENTRY (error_message)
TEST_ENTRY (sys_error)
TEST_ENTRY (timer)
TEST_ENTRY (timer_init)
@@ -624,6 +646,12 @@ TASK_LIST_START
TEST_ENTRY (poll_unidirectional)
TEST_ENTRY (poll_close)
TEST_ENTRY (poll_bad_fdtype)
#ifdef __linux__
TEST_ENTRY (poll_nested_epoll)
#endif
#ifdef UV_HAVE_KQUEUE
TEST_ENTRY (poll_nested_kqueue)
#endif
TEST_ENTRY (socket_buffer_size)
@@ -655,9 +683,9 @@ TASK_LIST_START
TEST_ENTRY (fs_poll_getpath)
TEST_ENTRY (kill)
#ifdef _WIN32
TEST_ENTRY (poll_close_doesnt_corrupt_stack)
TEST_ENTRY (poll_closesocket)
#ifdef _WIN32
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
#if !defined(USING_UV_SHARED)
TEST_ENTRY (argument_escaping)
@@ -668,6 +696,7 @@ TASK_LIST_START
TEST_ENTRY (fs_stat_root)
TEST_ENTRY (spawn_with_an_odd_path)
TEST_ENTRY (ipc_listen_after_bind_twice)
TEST_ENTRY (win32_signum_number)
#else
TEST_ENTRY (emfile)
TEST_ENTRY (close_fd)
@@ -710,6 +739,7 @@ TASK_LIST_START
TEST_ENTRY (fs_event_watch_dir)
TEST_ENTRY (fs_event_watch_dir_recursive)
TEST_ENTRY (fs_event_watch_file)
TEST_ENTRY (fs_event_watch_file_exact_path)
TEST_ENTRY (fs_event_watch_file_twice)
TEST_ENTRY (fs_event_watch_file_current_dir)
#ifdef _WIN32
@@ -724,6 +754,7 @@ TASK_LIST_START
TEST_ENTRY (fs_event_error_reporting)
TEST_ENTRY (fs_event_getpath)
TEST_ENTRY (fs_scandir_empty_dir)
TEST_ENTRY (fs_scandir_non_existent_dir)
TEST_ENTRY (fs_scandir_file)
TEST_ENTRY (fs_open_dir)
TEST_ENTRY (fs_rename_to_existing_file)
+4
View File
@@ -34,7 +34,9 @@ TEST_IMPL(loop_close) {
int r;
uv_loop_t loop;
loop.data = &loop;
ASSERT(0 == uv_loop_init(&loop));
ASSERT(loop.data == (void*) &loop);
uv_timer_init(&loop, &timer_handle);
uv_timer_start(&timer_handle, timer_cb, 100, 100);
@@ -47,7 +49,9 @@ TEST_IMPL(loop_close) {
r = uv_run(&loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(loop.data == (void*) &loop);
ASSERT(0 == uv_loop_close(&loop));
ASSERT(loop.data == (void*) &loop);
return 0;
}
+2 -3
View File
@@ -231,7 +231,7 @@ TEST_IMPL(pipe_getsockname_blocking) {
len1 = sizeof buf1;
r = uv_pipe_getsockname(&pipe_client, buf1, &len1);
ASSERT(r == 0);
ASSERT(buf1[len1 - 1] != 0);
ASSERT(len1 == 0); /* It's an annonymous pipe. */
r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL);
ASSERT(r == 0);
@@ -240,7 +240,7 @@ TEST_IMPL(pipe_getsockname_blocking) {
len2 = sizeof buf2;
r = uv_pipe_getsockname(&pipe_client, buf2, &len2);
ASSERT(r == 0);
ASSERT(buf2[len2 - 1] != 0);
ASSERT(len2 == 0); /* It's an annonymous pipe. */
r = uv_read_stop((uv_stream_t*)&pipe_client);
ASSERT(r == 0);
@@ -255,7 +255,6 @@ TEST_IMPL(pipe_getsockname_blocking) {
ASSERT(pipe_close_cb_called == 1);
_close(readfd);
CloseHandle(writeh);
#endif
-2
View File
@@ -61,8 +61,6 @@ TEST_IMPL(platform_output) {
ASSERT(rusage.ru_utime.tv_usec >= 0);
ASSERT(rusage.ru_stime.tv_sec >= 0);
ASSERT(rusage.ru_stime.tv_usec >= 0);
ASSERT(rusage.ru_majflt >= 0);
ASSERT(rusage.ru_maxrss >= 0);
printf("uv_getrusage:\n");
printf(" user: %llu sec %llu microsec\n",
(unsigned long long) rusage.ru_utime.tv_sec,
@@ -19,8 +19,6 @@
* IN THE SOFTWARE.
*/
#ifdef _WIN32
#include <errno.h>
#include <stdio.h>
@@ -37,6 +35,7 @@
uv_os_sock_t sock;
uv_poll_t handle;
#ifdef _WIN32
static int close_cb_called = 0;
@@ -69,9 +68,13 @@ static void NO_INLINE close_socket_and_verify_stack() {
for (i = 0; i < ARRAY_SIZE(data); i++)
ASSERT(data[i] == MARKER);
}
#endif
TEST_IMPL(poll_close_doesnt_corrupt_stack) {
#ifndef _WIN32
RETURN_SKIP("Test only relevant on Windows");
#else
struct WSAData wsa_data;
int r;
unsigned long on;
@@ -109,6 +112,5 @@ TEST_IMPL(poll_close_doesnt_corrupt_stack) {
MAKE_VALGRIND_HAPPY();
return 0;
#endif
}
#endif /* _WIN32 */
+6 -2
View File
@@ -19,7 +19,6 @@
* IN THE SOFTWARE.
*/
#ifdef _WIN32
#include <errno.h>
@@ -29,6 +28,7 @@
uv_os_sock_t sock;
uv_poll_t handle;
#ifdef _WIN32
static int close_cb_called = 0;
@@ -50,9 +50,13 @@ static void poll_cb(uv_poll_t* h, int status, int events) {
uv_close((uv_handle_t*) &handle, close_cb);
}
#endif
TEST_IMPL(poll_closesocket) {
#ifndef _WIN32
RETURN_SKIP("Test only relevant on Windows");
#else
struct WSAData wsa_data;
int r;
unsigned long on;
@@ -85,5 +89,5 @@ TEST_IMPL(poll_closesocket) {
MAKE_VALGRIND_HAPPY();
return 0;
}
#endif
}
+61 -7
View File
@@ -31,6 +31,16 @@
#include "uv.h"
#include "task.h"
#ifdef __linux__
# include <sys/epoll.h>
#endif
#ifdef UV_HAVE_KQUEUE
# include <sys/types.h>
# include <sys/event.h>
# include <sys/time.h>
#endif
#define NUM_CLIENTS 5
#define TRANSFER_BYTES (1 << 16)
@@ -72,9 +82,9 @@ static int closed_connections = 0;
static int valid_writable_wakeups = 0;
static int spurious_writable_wakeups = 0;
#ifndef _AIX
#if !defined(_AIX) && !defined(__MVS__)
static int disconnects = 0;
#endif /* !_AIX */
#endif /* !_AIX && !__MVS__ */
static int got_eagain(void) {
#ifdef _WIN32
@@ -378,7 +388,7 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
new_events &= ~UV_WRITABLE;
}
}
#ifndef _AIX
#if !defined(_AIX) && !defined(__MVS__)
if (events & UV_DISCONNECT) {
context->got_disconnect = 1;
++disconnects;
@@ -386,9 +396,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
}
if (context->got_fin && context->sent_fin && context->got_disconnect) {
#else /* _AIX */
#else /* _AIX && __MVS__ */
if (context->got_fin && context->sent_fin) {
#endif /* !_AIx */
#endif /* !_AIX && !__MVS__ */
/* Sent and received FIN. Close and destroy context. */
close_socket(context->sock);
destroy_connection_context(context);
@@ -556,7 +566,7 @@ static void start_poll_test(void) {
spurious_writable_wakeups > 20);
ASSERT(closed_connections == NUM_CLIENTS * 2);
#ifndef _AIX
#if !defined(_AIX) && !defined(__MVS__)
ASSERT(disconnects == NUM_CLIENTS * 2);
#endif
MAKE_VALGRIND_HAPPY();
@@ -584,7 +594,7 @@ TEST_IMPL(poll_unidirectional) {
*/
TEST_IMPL(poll_bad_fdtype) {
#if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__sun) && \
!defined(_AIX)
!defined(_AIX) && !defined(__MVS__) && !defined(__FreeBSD_kernel__)
uv_poll_t poll_handle;
int fd;
@@ -601,3 +611,47 @@ TEST_IMPL(poll_bad_fdtype) {
MAKE_VALGRIND_HAPPY();
return 0;
}
#ifdef __linux__
TEST_IMPL(poll_nested_epoll) {
uv_poll_t poll_handle;
int fd;
fd = epoll_create(1);
ASSERT(fd != -1);
ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, fd));
ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, (uv_poll_cb) abort));
ASSERT(0 != uv_run(uv_default_loop(), UV_RUN_NOWAIT));
uv_close((uv_handle_t*) &poll_handle, NULL);
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(0 == close(fd));
MAKE_VALGRIND_HAPPY();
return 0;
}
#endif /* __linux__ */
#ifdef UV_HAVE_KQUEUE
TEST_IMPL(poll_nested_kqueue) {
uv_poll_t poll_handle;
int fd;
fd = kqueue();
ASSERT(fd != -1);
ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, fd));
ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, (uv_poll_cb) abort));
ASSERT(0 != uv_run(uv_default_loop(), UV_RUN_NOWAIT));
uv_close((uv_handle_t*) &poll_handle, NULL);
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(0 == close(fd));
MAKE_VALGRIND_HAPPY();
return 0;
}
#endif /* UV_HAVE_KQUEUE */
+23 -1
View File
@@ -41,13 +41,35 @@ static void set_title(const char* title) {
}
static void uv_get_process_title_edge_cases() {
char buffer[512];
int r;
/* Test a NULL buffer */
r = uv_get_process_title(NULL, 100);
ASSERT(r == UV_EINVAL);
/* Test size of zero */
r = uv_get_process_title(buffer, 0);
ASSERT(r == UV_EINVAL);
/* Test for insufficient buffer size */
r = uv_get_process_title(buffer, 1);
ASSERT(r == UV_ENOBUFS);
}
TEST_IMPL(process_title) {
#if defined(__sun) || defined(_AIX)
#if defined(__sun)
RETURN_SKIP("uv_(get|set)_process_title is not implemented.");
#else
/* Check for format string vulnerabilities. */
set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s");
set_title("new title");
/* Check uv_get_process_title() edge cases */
uv_get_process_title_edge_cases();
return 0;
#endif
}
+3
View File
@@ -194,6 +194,9 @@ TEST_IMPL(timer_ref2) {
TEST_IMPL(fs_event_ref) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_fs_event_t h;
uv_fs_event_init(uv_default_loop(), &h);
uv_fs_event_start(&h, (uv_fs_event_cb)fail_cb, ".", 0);
+31 -4
View File
@@ -19,13 +19,40 @@
* IN THE SOFTWARE.
*/
/* This test does not pretend to be cross-platform. */
#ifndef _WIN32
#include "uv.h"
#include "task.h"
/* For Windows we test only signum handling */
#ifdef _WIN32
static void signum_test_cb(uv_signal_t* handle, int signum) {
FATAL("signum_test_cb should not be called");
}
TEST_IMPL(win32_signum_number) {
uv_signal_t signal;
uv_loop_t* loop;
loop = uv_default_loop();
uv_signal_init(loop, &signal);
ASSERT(uv_signal_start(&signal, signum_test_cb, 0) == UV_EINVAL);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGINT) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGBREAK) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGHUP) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGWINCH) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGILL) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGABRT_COMPAT) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGFPE) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGSEGV) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGTERM) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, SIGABRT) == 0);
ASSERT(uv_signal_start(&signal, signum_test_cb, -1) == UV_EINVAL);
ASSERT(uv_signal_start(&signal, signum_test_cb, NSIG) == UV_EINVAL);
ASSERT(uv_signal_start(&signal, signum_test_cb, 1024) == UV_EINVAL);
MAKE_VALGRIND_HAPPY();
return 0;
}
#else
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
+16 -4
View File
@@ -46,7 +46,7 @@ static uv_timer_t timer;
static uv_process_options_t options;
static char exepath[1024];
static size_t exepath_size = 1024;
static char* args[3];
static char* args[5];
static int no_term_signal;
static int timer_counter;
@@ -147,6 +147,8 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) {
args[0] = exepath;
args[1] = test;
args[2] = NULL;
args[3] = NULL;
args[4] = NULL;
options.file = exepath;
options.args = args;
options.exit_cb = exit_cb;
@@ -1226,21 +1228,26 @@ TEST_IMPL(spawn_with_an_odd_path) {
TEST_IMPL(spawn_setuid_setgid) {
int r;
struct passwd* pw;
char uidstr[10];
char gidstr[10];
/* if not root, then this will fail. */
uv_uid_t uid = getuid();
if (uid != 0) {
fprintf(stderr, "spawn_setuid_setgid skipped: not root\n");
return 0;
RETURN_SKIP("It should be run as root user");
}
init_process_options("spawn_helper1", exit_cb);
init_process_options("spawn_helper_setuid_setgid", exit_cb);
/* become the "nobody" user. */
pw = getpwnam("nobody");
ASSERT(pw != NULL);
options.uid = pw->pw_uid;
options.gid = pw->pw_gid;
snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid);
snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid);
options.args[2] = uidstr;
options.args[3] = gidstr;
options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID;
r = uv_spawn(uv_default_loop(), &process, &options);
@@ -1431,6 +1438,9 @@ TEST_IMPL(spawn_fs_open) {
#ifndef _WIN32
TEST_IMPL(closed_fd_events) {
#if defined(__MVS__)
RETURN_SKIP("Filesystem watching not supported on this platform.");
#endif
uv_stdio_container_t stdio[3];
uv_pipe_t pipe_handle;
int fd[2];
@@ -1500,6 +1510,8 @@ TEST_IMPL(spawn_reads_child_path) {
*/
#if defined(__APPLE__)
static const char dyld_path_var[] = "DYLD_LIBRARY_PATH";
#elif defined __MVS__
static const char dyld_path_var[] = "LIBPATH";
#else
static const char dyld_path_var[] = "LD_LIBRARY_PATH";
#endif
+123
View File
@@ -0,0 +1,123 @@
/* Copyright libuv project and 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "uv.h"
#include "task.h"
static uv_tcp_t server;
static uv_tcp_t client;
static uv_tcp_t incoming;
static int connect_cb_called;
static int close_cb_called;
static int connection_cb_called;
static uv_write_t write_req;
static char hello[] = "HELLO!";
static void close_cb(uv_handle_t* handle) {
close_cb_called++;
}
static void write_cb(uv_write_t* req, int status) {
ASSERT(status == 0);
}
static void conn_alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
/* Do nothing, read_cb should be called with UV_ENOBUFS. */
}
static void conn_read_cb(uv_stream_t* stream,
ssize_t nread,
const uv_buf_t* buf) {
ASSERT(nread == UV_ENOBUFS);
ASSERT(buf->base == NULL);
ASSERT(buf->len == 0);
uv_close((uv_handle_t*) &incoming, close_cb);
uv_close((uv_handle_t*) &client, close_cb);
uv_close((uv_handle_t*) &server, close_cb);
}
static void connect_cb(uv_connect_t* req, int status) {
int r;
uv_buf_t buf;
ASSERT(status == 0);
connect_cb_called++;
buf = uv_buf_init(hello, sizeof(hello));
r = uv_write(&write_req, req->handle, &buf, 1, write_cb);
ASSERT(r == 0);
}
static void connection_cb(uv_stream_t* tcp, int status) {
ASSERT(status == 0);
ASSERT(0 == uv_tcp_init(tcp->loop, &incoming));
ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming));
ASSERT(0 == uv_read_start((uv_stream_t*) &incoming,
conn_alloc_cb,
conn_read_cb));
connection_cb_called++;
}
static void start_server(void) {
struct sockaddr_in addr;
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
ASSERT(0 == uv_tcp_init(uv_default_loop(), &server));
ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr, 0));
ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb));
}
TEST_IMPL(tcp_alloc_cb_fail) {
uv_connect_t connect_req;
struct sockaddr_in addr;
start_server();
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
ASSERT(0 == uv_tcp_init(uv_default_loop(), &client));
ASSERT(0 == uv_tcp_connect(&connect_req,
&client,
(struct sockaddr*) &addr,
connect_cb));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(connect_cb_called == 1);
ASSERT(connection_cb_called == 1);
ASSERT(close_cb_called == 3);
MAKE_VALGRIND_HAPPY();
return 0;
}
+15 -9
View File
@@ -40,6 +40,7 @@ static unsigned int got_connections;
static unsigned int close_cb_called;
static unsigned int write_cb_called;
static unsigned int read_cb_called;
static unsigned int pending_incoming;
static void close_cb(uv_handle_t* handle) {
close_cb_called++;
@@ -58,8 +59,11 @@ static void connect_cb(uv_connect_t* req, int status) {
if (req == &tcp_check_req) {
ASSERT(status != 0);
/* Close check and incoming[0], time to finish test */
uv_close((uv_handle_t*) &tcp_incoming[0], close_cb);
/*
* Time to finish the test: close both the check and pending incoming
* connections
*/
uv_close((uv_handle_t*) &tcp_incoming[pending_incoming], close_cb);
uv_close((uv_handle_t*) &tcp_check, close_cb);
return;
}
@@ -84,8 +88,8 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
uv_loop_t* loop;
unsigned int i;
/* Only first stream should receive read events */
ASSERT(stream == (uv_stream_t*) &tcp_incoming[0]);
pending_incoming = (uv_tcp_t*) stream - &tcp_incoming[0];
ASSERT(pending_incoming < got_connections);
ASSERT(0 == uv_read_stop(stream));
ASSERT(1 == nread);
@@ -93,8 +97,13 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
read_cb_called++;
/* Close all active incomings, except current one */
for (i = 1; i < got_connections; i++)
uv_close((uv_handle_t*) &tcp_incoming[i], close_cb);
for (i = 0; i < got_connections; i++) {
if (i != pending_incoming)
uv_close((uv_handle_t*) &tcp_incoming[i], close_cb);
}
/* Close server, so no one will connect to it */
uv_close((uv_handle_t*) &tcp_server, close_cb);
/* Create new fd that should be one of the closed incomings */
ASSERT(0 == uv_tcp_init(loop, &tcp_check));
@@ -103,9 +112,6 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
(const struct sockaddr*) &addr,
connect_cb));
ASSERT(0 == uv_read_start((uv_stream_t*) &tcp_check, alloc_cb, read_cb));
/* Close server, so no one will connect to it */
uv_close((uv_handle_t*) &tcp_server, close_cb);
}
static void connection_cb(uv_stream_t* server, int status) {
@@ -29,6 +29,7 @@ static uv_tcp_t tcp_handle;
static int connect_cb_called;
static int timer1_cb_called;
static int close_cb_called;
static int netunreach_errors;
static void close_cb(uv_handle_t* handle) {
@@ -37,9 +38,15 @@ static void close_cb(uv_handle_t* handle) {
static void connect_cb(uv_connect_t* req, int status) {
ASSERT(status == UV_ECANCELED);
/* The expected error is UV_ECANCELED but the test tries to connect to what
* is basically an arbitrary address in the expectation that no network path
* exists, so UV_ENETUNREACH is an equally plausible outcome.
*/
ASSERT(status == UV_ECANCELED || status == UV_ENETUNREACH);
uv_timer_stop(&timer2_handle);
connect_cb_called++;
if (status == UV_ENETUNREACH)
netunreach_errors++;
}
@@ -82,5 +89,9 @@ TEST_IMPL(tcp_close_while_connecting) {
ASSERT(close_cb_called == 2);
MAKE_VALGRIND_HAPPY();
if (netunreach_errors > 0)
RETURN_SKIP("Network unreachable.");
return 0;
}
+2 -2
View File
@@ -46,13 +46,13 @@ static void close_cb(uv_handle_t* handle) {
close_cb_called++;
}
void timer_cb(uv_timer_t* handle) {
static void timer_cb(uv_timer_t* handle) {
uv_close((uv_handle_t*) &client, close_cb);
uv_close((uv_handle_t*) &server, close_cb);
uv_close((uv_handle_t*) &incoming, close_cb);
}
void write_cb(uv_write_t* req, int status) {
static void write_cb(uv_write_t* req, int status) {
if (status == 0)
write_callbacks++;
else if (status == UV_ECANCELED)
+4
View File
@@ -26,7 +26,11 @@
#define WRITES 3
#if defined(__arm__) /* Decrease the chunks so the test passes on arm CI bots */
#define CHUNKS_PER_WRITE 2048
#else
#define CHUNKS_PER_WRITE 4096
#endif
#define CHUNK_SIZE 10024 /* 10 kb */
#define TOTAL_BYTES (WRITES * CHUNKS_PER_WRITE * CHUNK_SIZE)
+24 -81
View File
@@ -37,77 +37,45 @@ struct cancel_info {
uv_timer_t timer_handle;
};
static uv_cond_t signal_cond;
static uv_mutex_t signal_mutex;
static uv_mutex_t wait_mutex;
static unsigned num_threads;
static unsigned fs_cb_called;
static unsigned work_cb_called;
static unsigned done_cb_called;
static unsigned done2_cb_called;
static unsigned timer_cb_called;
static uv_work_t pause_reqs[4];
static uv_sem_t pause_sems[ARRAY_SIZE(pause_reqs)];
static void work_cb(uv_work_t* req) {
uv_mutex_lock(&signal_mutex);
uv_cond_signal(&signal_cond);
uv_mutex_unlock(&signal_mutex);
uv_mutex_lock(&wait_mutex);
uv_mutex_unlock(&wait_mutex);
work_cb_called++;
uv_sem_wait(pause_sems + (req - pause_reqs));
}
static void done_cb(uv_work_t* req, int status) {
done_cb_called++;
free(req);
uv_sem_destroy(pause_sems + (req - pause_reqs));
}
static void saturate_threadpool(void) {
uv_work_t* req;
uv_loop_t* loop;
char buf[64];
size_t i;
ASSERT(0 == uv_cond_init(&signal_cond));
ASSERT(0 == uv_mutex_init(&signal_mutex));
ASSERT(0 == uv_mutex_init(&wait_mutex));
snprintf(buf, sizeof(buf), "UV_THREADPOOL_SIZE=%zu", ARRAY_SIZE(pause_reqs));
putenv(buf);
uv_mutex_lock(&signal_mutex);
uv_mutex_lock(&wait_mutex);
for (num_threads = 0; /* empty */; num_threads++) {
req = malloc(sizeof(*req));
ASSERT(req != NULL);
ASSERT(0 == uv_queue_work(uv_default_loop(), req, work_cb, done_cb));
/* Expect to get signalled within 350 ms, otherwise assume that
* the thread pool is saturated. As with any timing dependent test,
* this is obviously not ideal.
*/
if (uv_cond_timedwait(&signal_cond,
&signal_mutex,
(uint64_t) (350 * 1e6))) {
ASSERT(0 == uv_cancel((uv_req_t*) req));
break;
}
loop = uv_default_loop();
for (i = 0; i < ARRAY_SIZE(pause_reqs); i += 1) {
ASSERT(0 == uv_sem_init(pause_sems + i, 0));
ASSERT(0 == uv_queue_work(loop, pause_reqs + i, work_cb, done_cb));
}
}
static void unblock_threadpool(void) {
uv_mutex_unlock(&signal_mutex);
uv_mutex_unlock(&wait_mutex);
}
size_t i;
static void cleanup_threadpool(void) {
ASSERT(done_cb_called == num_threads + 1); /* +1 == cancelled work req. */
ASSERT(work_cb_called == num_threads);
uv_cond_destroy(&signal_cond);
uv_mutex_destroy(&signal_mutex);
uv_mutex_destroy(&wait_mutex);
for (i = 0; i < ARRAY_SIZE(pause_reqs); i += 1)
uv_sem_post(pause_sems + i);
}
@@ -166,12 +134,9 @@ static void timer_cb(uv_timer_t* handle) {
}
static void nop_work_cb(uv_work_t* req) {
}
static void nop_done_cb(uv_work_t* req, int status) {
req->data = "OK";
ASSERT(status == UV_ECANCELED);
done_cb_called++;
}
@@ -203,8 +168,6 @@ TEST_IMPL(threadpool_cancel_getaddrinfo) {
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
ASSERT(1 == timer_cb_called);
cleanup_threadpool();
MAKE_VALGRIND_HAPPY();
return 0;
}
@@ -241,8 +204,6 @@ TEST_IMPL(threadpool_cancel_getnameinfo) {
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
ASSERT(1 == timer_cb_called);
cleanup_threadpool();
MAKE_VALGRIND_HAPPY();
return 0;
}
@@ -267,8 +228,6 @@ TEST_IMPL(threadpool_cancel_work) {
ASSERT(1 == timer_cb_called);
ASSERT(ARRAY_SIZE(reqs) == done2_cb_called);
cleanup_threadpool();
MAKE_VALGRIND_HAPPY();
return 0;
}
@@ -322,7 +281,6 @@ TEST_IMPL(threadpool_cancel_fs) {
ASSERT(n == fs_cb_called);
ASSERT(1 == timer_cb_called);
cleanup_threadpool();
MAKE_VALGRIND_HAPPY();
return 0;
@@ -332,30 +290,15 @@ TEST_IMPL(threadpool_cancel_fs) {
TEST_IMPL(threadpool_cancel_single) {
uv_loop_t* loop;
uv_work_t req;
int cancelled;
int i;
saturate_threadpool();
loop = uv_default_loop();
for (i = 0; i < 5000; i++) {
req.data = NULL;
ASSERT(0 == uv_queue_work(loop, &req, nop_work_cb, nop_done_cb));
cancelled = uv_cancel((uv_req_t*) &req);
if (cancelled == 0)
break;
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
}
if (cancelled != 0) {
fputs("Failed to cancel a work req in 5,000 iterations, giving up.\n",
stderr);
return 1;
}
ASSERT(req.data == NULL);
ASSERT(0 == uv_queue_work(loop, &req, (uv_work_cb) abort, nop_done_cb));
ASSERT(0 == uv_cancel((uv_req_t*) &req));
ASSERT(0 == done_cb_called);
unblock_threadpool();
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
ASSERT(req.data != NULL); /* Should have been updated by nop_done_cb(). */
ASSERT(1 == done_cb_called);
MAKE_VALGRIND_HAPPY();
return 0;
+103 -5
View File
@@ -28,7 +28,7 @@
#else /* Unix */
# include <fcntl.h>
# include <unistd.h>
# if defined(__linux__)
# if (defined(__linux__) || defined(__GLIBC__)) && !defined(__ANDROID__)
# include <pty.h>
# elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
# include <util.h>
@@ -212,6 +212,96 @@ TEST_IMPL(tty_raw) {
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_empty_write) {
int r;
int ttyout_fd;
uv_tty_t tty_out;
char dummy[1];
uv_buf_t bufs[1];
uv_loop_t* loop;
/* Make sure we have an FD that refers to a tty */
HANDLE handle;
loop = uv_default_loop();
handle = CreateFileA("conout$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
ASSERT(handle != INVALID_HANDLE_VALUE);
ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
ASSERT(ttyout_fd >= 0);
ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */
ASSERT(r == 0);
bufs[0].len = 0;
bufs[0].base = &dummy;
r = uv_try_write((uv_stream_t*) &tty_out, bufs, 1);
ASSERT(r == 0);
uv_close((uv_handle_t*) &tty_out, NULL);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tty_large_write) {
int r;
int ttyout_fd;
uv_tty_t tty_out;
char dummy[10000];
uv_buf_t bufs[1];
uv_loop_t* loop;
/* Make sure we have an FD that refers to a tty */
HANDLE handle;
loop = uv_default_loop();
handle = CreateFileA("conout$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
ASSERT(handle != INVALID_HANDLE_VALUE);
ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
ASSERT(ttyout_fd >= 0);
ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */
ASSERT(r == 0);
memset(dummy, '.', sizeof(dummy) - 1);
dummy[sizeof(dummy) - 1] = '\n';
bufs[0] = uv_buf_init(dummy, sizeof(dummy));
r = uv_try_write((uv_stream_t*) &tty_out, bufs, 1);
ASSERT(r == 10000);
uv_close((uv_handle_t*) &tty_out, NULL);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
#endif
@@ -260,16 +350,24 @@ TEST_IMPL(tty_file) {
}
TEST_IMPL(tty_pty) {
# if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
int master_fd, slave_fd;
#if defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
(defined(__linux__) && !defined(__ANDROID__)) || \
defined(__NetBSD__) || \
defined(__OpenBSD__)
int master_fd, slave_fd, r;
struct winsize w;
uv_loop_t loop;
uv_tty_t master_tty, slave_tty;
ASSERT(0 == uv_loop_init(&loop));
ASSERT(0 == openpty(&master_fd, &slave_fd, NULL, NULL, &w));
r = openpty(&master_fd, &slave_fd, NULL, NULL, &w);
if (r != 0)
RETURN_SKIP("No pty available, skipping.");
ASSERT(0 == uv_tty_init(&loop, &slave_tty, slave_fd, 0));
ASSERT(0 == uv_tty_init(&loop, &master_tty, master_fd, 0));
/* Check if the file descriptor was reopened. If it is,
+197
View File
@@ -0,0 +1,197 @@
/* Copyright libuv project 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHECK_HANDLE(handle) \
ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
static uv_udp_t server;
static uv_udp_t client;
static int cl_send_cb_called;
static int cl_recv_cb_called;
static int sv_send_cb_called;
static int sv_recv_cb_called;
static int close_cb_called;
static void sv_alloc_cb(uv_handle_t* handle,
size_t suggested_size,
uv_buf_t* buf) {
static char slab[65536];
CHECK_HANDLE(handle);
buf->base = slab;
buf->len = sizeof(slab);
}
static void cl_alloc_cb(uv_handle_t* handle,
size_t suggested_size,
uv_buf_t* buf) {
/* Do nothing, recv_cb should be called with UV_ENOBUFS. */
}
static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
ASSERT(1 == uv_is_closing(handle));
close_cb_called++;
}
static void cl_recv_cb(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* buf,
const struct sockaddr* addr,
unsigned flags) {
CHECK_HANDLE(handle);
ASSERT(flags == 0);
ASSERT(nread == UV_ENOBUFS);
cl_recv_cb_called++;
uv_close((uv_handle_t*) handle, close_cb);
}
static void cl_send_cb(uv_udp_send_t* req, int status) {
int r;
ASSERT(req != NULL);
ASSERT(status == 0);
CHECK_HANDLE(req->handle);
r = uv_udp_recv_start(req->handle, cl_alloc_cb, cl_recv_cb);
ASSERT(r == 0);
cl_send_cb_called++;
}
static void sv_send_cb(uv_udp_send_t* req, int status) {
ASSERT(req != NULL);
ASSERT(status == 0);
CHECK_HANDLE(req->handle);
uv_close((uv_handle_t*) req->handle, close_cb);
free(req);
sv_send_cb_called++;
}
static void sv_recv_cb(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* rcvbuf,
const struct sockaddr* addr,
unsigned flags) {
uv_udp_send_t* req;
uv_buf_t sndbuf;
int r;
if (nread < 0) {
ASSERT(0 && "unexpected error");
}
if (nread == 0) {
/* Returning unused buffer */
/* Don't count towards sv_recv_cb_called */
ASSERT(addr == NULL);
return;
}
CHECK_HANDLE(handle);
ASSERT(flags == 0);
ASSERT(addr != NULL);
ASSERT(nread == 4);
ASSERT(!memcmp("PING", rcvbuf->base, nread));
r = uv_udp_recv_stop(handle);
ASSERT(r == 0);
req = malloc(sizeof *req);
ASSERT(req != NULL);
sndbuf = uv_buf_init("PONG", 4);
r = uv_udp_send(req, handle, &sndbuf, 1, addr, sv_send_cb);
ASSERT(r == 0);
sv_recv_cb_called++;
}
TEST_IMPL(udp_alloc_cb_fail) {
struct sockaddr_in addr;
uv_udp_send_t req;
uv_buf_t buf;
int r;
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
r = uv_udp_init(uv_default_loop(), &server);
ASSERT(r == 0);
r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0);
r = uv_udp_recv_start(&server, sv_alloc_cb, sv_recv_cb);
ASSERT(r == 0);
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
r = uv_udp_init(uv_default_loop(), &client);
ASSERT(r == 0);
buf = uv_buf_init("PING", 4);
r = uv_udp_send(&req,
&client,
&buf,
1,
(const struct sockaddr*) &addr,
cl_send_cb);
ASSERT(r == 0);
ASSERT(close_cb_called == 0);
ASSERT(cl_send_cb_called == 0);
ASSERT(cl_recv_cb_called == 0);
ASSERT(sv_send_cb_called == 0);
ASSERT(sv_recv_cb_called == 0);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(cl_send_cb_called == 1);
ASSERT(cl_recv_cb_called == 1);
ASSERT(sv_send_cb_called == 1);
ASSERT(sv_recv_cb_called == 1);
ASSERT(close_cb_called == 2);
MAKE_VALGRIND_HAPPY();
return 0;
}
+3 -3
View File
@@ -26,7 +26,7 @@
#include <stdlib.h>
#include <string.h>
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <sys/sysctl.h>
#endif
@@ -47,7 +47,7 @@ static int send_cb_called;
static int recv_cb_called;
static int close_cb_called;
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int can_ipv6_ipv4_dual() {
int v6only;
size_t size = sizeof(int);
@@ -166,7 +166,7 @@ TEST_IMPL(udp_dual_stack) {
if (!can_ipv6())
RETURN_SKIP("IPv6 not supported");
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (!can_ipv6_ipv4_dual())
RETURN_SKIP("IPv6-IPv4 dual stack not supported");
#endif
@@ -72,7 +72,7 @@ TEST_IMPL(udp_multicast_interface6) {
r = uv_udp_bind(&server, (const struct sockaddr*)&baddr, 0);
ASSERT(r == 0);
#if defined(__APPLE__) || defined(__FreeBSD__)
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
r = uv_udp_set_multicast_interface(&server, "::1%lo0");
#else
r = uv_udp_set_multicast_interface(&server, NULL);
+4 -1
View File
@@ -119,7 +119,10 @@ TEST_IMPL(udp_multicast_join6) {
ASSERT(r == 0);
/* join the multicast channel */
#if defined(__APPLE__) || defined(_AIX)
#if defined(__APPLE__) || \
defined(_AIX) || \
defined(__MVS__) || \
defined(__FreeBSD_kernel__)
r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP);
#else
r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP);
+11
View File
@@ -52,7 +52,14 @@ static int udp_options_test(const struct sockaddr* addr) {
/* values 1-255 should work */
for (i = 1; i <= 255; i++) {
r = uv_udp_set_ttl(&h, i);
#if defined(__MVS__)
if (addr->sa_family == AF_INET6)
ASSERT(r == 0);
else
ASSERT(r == UV_ENOTSUP);
#else
ASSERT(r == 0);
#endif
}
for (i = 0; i < (int) ARRAY_SIZE(invalid_ttls); i++) {
@@ -113,7 +120,11 @@ TEST_IMPL(udp_no_autobind) {
ASSERT(0 == uv_udp_init(loop, &h));
ASSERT(UV_EBADF == uv_udp_set_multicast_ttl(&h, 32));
ASSERT(UV_EBADF == uv_udp_set_broadcast(&h, 1));
#if defined(__MVS__)
ASSERT(UV_ENOTSUP == uv_udp_set_ttl(&h, 1));
#else
ASSERT(UV_EBADF == uv_udp_set_ttl(&h, 1));
#endif
ASSERT(UV_EBADF == uv_udp_set_multicast_loop(&h, 1));
ASSERT(UV_EBADF == uv_udp_set_multicast_interface(&h, "0.0.0.0"));
@@ -59,6 +59,9 @@ static void close_cb(uv_handle_t* handle) {
TEST_IMPL(watcher_cross_stop) {
#if defined(__MVS__)
RETURN_SKIP("zOS does not allow address or port reuse when using UDP sockets");
#endif
uv_loop_t* loop = uv_default_loop();
unsigned int i;
struct sockaddr_in addr;