mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-04 14:36:37 +00:00
Update libuv
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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); \
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
# if defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# define HAVE_KQUEUE 1
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user