Merge branches/quickjs to trunk. This is the way.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3621 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
119
deps/libuv/test/benchmark-async-pummel.c
vendored
Normal file
119
deps/libuv/test/benchmark-async-pummel.c
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NUM_PINGS (1000 * 1000)
|
||||
#define ACCESS_ONCE(type, var) (*(volatile type*) &(var))
|
||||
|
||||
static unsigned int callbacks;
|
||||
static volatile int done;
|
||||
|
||||
static const char running[] = "running";
|
||||
static const char stop[] = "stop";
|
||||
static const char stopped[] = "stopped";
|
||||
|
||||
|
||||
static void async_cb(uv_async_t* handle) {
|
||||
if (++callbacks == NUM_PINGS) {
|
||||
/* Tell the pummel thread to stop. */
|
||||
ACCESS_ONCE(const char*, handle->data) = stop;
|
||||
|
||||
/* Wait for the pummel thread to acknowledge that it has stoppped. */
|
||||
while (ACCESS_ONCE(const char*, handle->data) != stopped)
|
||||
uv_sleep(0);
|
||||
|
||||
uv_close((uv_handle_t*) handle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void pummel(void* arg) {
|
||||
uv_async_t* handle = (uv_async_t*) arg;
|
||||
|
||||
while (ACCESS_ONCE(const char*, handle->data) == running)
|
||||
uv_async_send(handle);
|
||||
|
||||
/* Acknowledge that we've seen handle->data change. */
|
||||
ACCESS_ONCE(const char*, handle->data) = stopped;
|
||||
}
|
||||
|
||||
|
||||
static int test_async_pummel(int nthreads) {
|
||||
uv_thread_t* tids;
|
||||
uv_async_t handle;
|
||||
uint64_t time;
|
||||
int i;
|
||||
|
||||
tids = calloc(nthreads, sizeof(tids[0]));
|
||||
ASSERT(tids != NULL);
|
||||
|
||||
ASSERT(0 == uv_async_init(uv_default_loop(), &handle, async_cb));
|
||||
ACCESS_ONCE(const char*, handle.data) = running;
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
ASSERT(0 == uv_thread_create(tids + i, pummel, &handle));
|
||||
|
||||
time = uv_hrtime();
|
||||
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
|
||||
time = uv_hrtime() - time;
|
||||
done = 1;
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
ASSERT(0 == uv_thread_join(tids + i));
|
||||
|
||||
printf("async_pummel_%d: %s callbacks in %.2f seconds (%s/sec)\n",
|
||||
nthreads,
|
||||
fmt(callbacks),
|
||||
time / 1e9,
|
||||
fmt(callbacks / (time / 1e9)));
|
||||
|
||||
free(tids);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async_pummel_1) {
|
||||
return test_async_pummel(1);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async_pummel_2) {
|
||||
return test_async_pummel(2);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async_pummel_4) {
|
||||
return test_async_pummel(4);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async_pummel_8) {
|
||||
return test_async_pummel(8);
|
||||
}
|
141
deps/libuv/test/benchmark-async.c
vendored
Normal file
141
deps/libuv/test/benchmark-async.c
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NUM_PINGS (1000 * 1000)
|
||||
|
||||
struct ctx {
|
||||
uv_loop_t loop;
|
||||
uv_thread_t thread;
|
||||
uv_async_t main_async; /* wake up main thread */
|
||||
uv_async_t worker_async; /* wake up worker */
|
||||
unsigned int nthreads;
|
||||
unsigned int main_sent;
|
||||
unsigned int main_seen;
|
||||
unsigned int worker_sent;
|
||||
unsigned int worker_seen;
|
||||
};
|
||||
|
||||
|
||||
static void worker_async_cb(uv_async_t* handle) {
|
||||
struct ctx* ctx = container_of(handle, struct ctx, worker_async);
|
||||
|
||||
ASSERT(0 == uv_async_send(&ctx->main_async));
|
||||
ctx->worker_sent++;
|
||||
ctx->worker_seen++;
|
||||
|
||||
if (ctx->worker_sent >= NUM_PINGS)
|
||||
uv_close((uv_handle_t*) &ctx->worker_async, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void main_async_cb(uv_async_t* handle) {
|
||||
struct ctx* ctx = container_of(handle, struct ctx, main_async);
|
||||
|
||||
ASSERT(0 == uv_async_send(&ctx->worker_async));
|
||||
ctx->main_sent++;
|
||||
ctx->main_seen++;
|
||||
|
||||
if (ctx->main_sent >= NUM_PINGS)
|
||||
uv_close((uv_handle_t*) &ctx->main_async, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void worker(void* arg) {
|
||||
struct ctx* ctx = arg;
|
||||
ASSERT(0 == uv_async_send(&ctx->main_async));
|
||||
ASSERT(0 == uv_run(&ctx->loop, UV_RUN_DEFAULT));
|
||||
uv_loop_close(&ctx->loop);
|
||||
}
|
||||
|
||||
|
||||
static int test_async(int nthreads) {
|
||||
struct ctx* threads;
|
||||
struct ctx* ctx;
|
||||
uint64_t time;
|
||||
int i;
|
||||
|
||||
threads = calloc(nthreads, sizeof(threads[0]));
|
||||
ASSERT(threads != NULL);
|
||||
|
||||
for (i = 0; i < nthreads; i++) {
|
||||
ctx = threads + i;
|
||||
ctx->nthreads = nthreads;
|
||||
ASSERT(0 == uv_loop_init(&ctx->loop));
|
||||
ASSERT(0 == uv_async_init(&ctx->loop, &ctx->worker_async, worker_async_cb));
|
||||
ASSERT(0 == uv_async_init(uv_default_loop(),
|
||||
&ctx->main_async,
|
||||
main_async_cb));
|
||||
ASSERT(0 == uv_thread_create(&ctx->thread, worker, ctx));
|
||||
}
|
||||
|
||||
time = uv_hrtime();
|
||||
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
ASSERT(0 == uv_thread_join(&threads[i].thread));
|
||||
|
||||
time = uv_hrtime() - time;
|
||||
|
||||
for (i = 0; i < nthreads; i++) {
|
||||
ctx = threads + i;
|
||||
ASSERT(ctx->worker_sent == NUM_PINGS);
|
||||
ASSERT(ctx->worker_seen == NUM_PINGS);
|
||||
ASSERT(ctx->main_sent == (unsigned int) NUM_PINGS);
|
||||
ASSERT(ctx->main_seen == (unsigned int) NUM_PINGS);
|
||||
}
|
||||
|
||||
printf("async%d: %.2f sec (%s/sec)\n",
|
||||
nthreads,
|
||||
time / 1e9,
|
||||
fmt(NUM_PINGS / (time / 1e9)));
|
||||
|
||||
free(threads);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async1) {
|
||||
return test_async(1);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async2) {
|
||||
return test_async(2);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async4) {
|
||||
return test_async(4);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(async8) {
|
||||
return test_async(8);
|
||||
}
|
136
deps/libuv/test/benchmark-fs-stat.c
vendored
Normal file
136
deps/libuv/test/benchmark-fs-stat.c
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NUM_SYNC_REQS (10 * 1e5)
|
||||
#define NUM_ASYNC_REQS (1 * (int) 1e5)
|
||||
#define MAX_CONCURRENT_REQS 32
|
||||
|
||||
#define sync_stat(req, path) \
|
||||
do { \
|
||||
uv_fs_stat(NULL, (req), (path), NULL); \
|
||||
uv_fs_req_cleanup((req)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
struct async_req {
|
||||
const char* path;
|
||||
uv_fs_t fs_req;
|
||||
int* count;
|
||||
};
|
||||
|
||||
|
||||
static void warmup(const char* path) {
|
||||
uv_fs_t reqs[MAX_CONCURRENT_REQS];
|
||||
unsigned int i;
|
||||
|
||||
/* warm up the thread pool */
|
||||
for (i = 0; i < ARRAY_SIZE(reqs); i++)
|
||||
uv_fs_stat(uv_default_loop(), reqs + i, path, uv_fs_req_cleanup);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
/* warm up the OS dirent cache */
|
||||
for (i = 0; i < 16; i++)
|
||||
sync_stat(reqs + 0, path);
|
||||
}
|
||||
|
||||
|
||||
static void sync_bench(const char* path) {
|
||||
uint64_t before;
|
||||
uint64_t after;
|
||||
uv_fs_t req;
|
||||
int i;
|
||||
|
||||
/* do the sync benchmark */
|
||||
before = uv_hrtime();
|
||||
|
||||
for (i = 0; i < NUM_SYNC_REQS; i++)
|
||||
sync_stat(&req, path);
|
||||
|
||||
after = uv_hrtime();
|
||||
|
||||
printf("%s stats (sync): %.2fs (%s/s)\n",
|
||||
fmt(1.0 * NUM_SYNC_REQS),
|
||||
(after - before) / 1e9,
|
||||
fmt((1.0 * NUM_SYNC_REQS) / ((after - before) / 1e9)));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
static void stat_cb(uv_fs_t* fs_req) {
|
||||
struct async_req* req = container_of(fs_req, struct async_req, fs_req);
|
||||
uv_fs_req_cleanup(&req->fs_req);
|
||||
if (*req->count == 0) return;
|
||||
uv_fs_stat(uv_default_loop(), &req->fs_req, req->path, stat_cb);
|
||||
(*req->count)--;
|
||||
}
|
||||
|
||||
|
||||
static void async_bench(const char* path) {
|
||||
struct async_req reqs[MAX_CONCURRENT_REQS];
|
||||
struct async_req* req;
|
||||
uint64_t before;
|
||||
uint64_t after;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= MAX_CONCURRENT_REQS; i++) {
|
||||
count = NUM_ASYNC_REQS;
|
||||
|
||||
for (req = reqs; req < reqs + i; req++) {
|
||||
req->path = path;
|
||||
req->count = &count;
|
||||
uv_fs_stat(uv_default_loop(), &req->fs_req, req->path, stat_cb);
|
||||
}
|
||||
|
||||
before = uv_hrtime();
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
after = uv_hrtime();
|
||||
|
||||
printf("%s stats (%d concurrent): %.2fs (%s/s)\n",
|
||||
fmt(1.0 * NUM_ASYNC_REQS),
|
||||
i,
|
||||
(after - before) / 1e9,
|
||||
fmt((1.0 * NUM_ASYNC_REQS) / ((after - before) / 1e9)));
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This benchmark aims to measure the overhead of doing I/O syscalls from
|
||||
* the thread pool. The stat() syscall was chosen because its results are
|
||||
* easy for the operating system to cache, taking the actual I/O overhead
|
||||
* out of the equation.
|
||||
*/
|
||||
BENCHMARK_IMPL(fs_stat) {
|
||||
const char path[] = ".";
|
||||
warmup(path);
|
||||
sync_bench(path);
|
||||
async_bench(path);
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
92
deps/libuv/test/benchmark-getaddrinfo.c
vendored
Normal file
92
deps/libuv/test/benchmark-getaddrinfo.c
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CONCURRENT_CALLS 10
|
||||
#define TOTAL_CALLS 10000
|
||||
|
||||
static const char* name = "localhost";
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static uv_getaddrinfo_t handles[CONCURRENT_CALLS];
|
||||
|
||||
static int calls_initiated = 0;
|
||||
static int calls_completed = 0;
|
||||
static int64_t start_time;
|
||||
static int64_t end_time;
|
||||
|
||||
|
||||
static void getaddrinfo_initiate(uv_getaddrinfo_t* handle);
|
||||
|
||||
|
||||
static void getaddrinfo_cb(uv_getaddrinfo_t* handle, int status,
|
||||
struct addrinfo* res) {
|
||||
ASSERT(status == 0);
|
||||
calls_completed++;
|
||||
if (calls_initiated < TOTAL_CALLS) {
|
||||
getaddrinfo_initiate(handle);
|
||||
}
|
||||
|
||||
uv_freeaddrinfo(res);
|
||||
}
|
||||
|
||||
|
||||
static void getaddrinfo_initiate(uv_getaddrinfo_t* handle) {
|
||||
int r;
|
||||
|
||||
calls_initiated++;
|
||||
|
||||
r = uv_getaddrinfo(loop, handle, &getaddrinfo_cb, name, NULL, NULL);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(getaddrinfo) {
|
||||
int i;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
uv_update_time(loop);
|
||||
start_time = uv_now(loop);
|
||||
|
||||
for (i = 0; i < CONCURRENT_CALLS; i++) {
|
||||
getaddrinfo_initiate(&handles[i]);
|
||||
}
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_update_time(loop);
|
||||
end_time = uv_now(loop);
|
||||
|
||||
ASSERT(calls_initiated == TOTAL_CALLS);
|
||||
ASSERT(calls_completed == TOTAL_CALLS);
|
||||
|
||||
fprintf(stderr, "getaddrinfo: %.0f req/s\n",
|
||||
(double) calls_completed / (double) (end_time - start_time) * 1000.0);
|
||||
fflush(stderr);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
164
deps/libuv/test/benchmark-list.h
vendored
Normal file
164
deps/libuv/test/benchmark-list.h
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
BENCHMARK_DECLARE (sizes)
|
||||
BENCHMARK_DECLARE (loop_count)
|
||||
BENCHMARK_DECLARE (loop_count_timed)
|
||||
BENCHMARK_DECLARE (ping_pongs)
|
||||
BENCHMARK_DECLARE (ping_udp)
|
||||
BENCHMARK_DECLARE (tcp_write_batch)
|
||||
BENCHMARK_DECLARE (tcp4_pound_100)
|
||||
BENCHMARK_DECLARE (tcp4_pound_1000)
|
||||
BENCHMARK_DECLARE (pipe_pound_100)
|
||||
BENCHMARK_DECLARE (pipe_pound_1000)
|
||||
BENCHMARK_DECLARE (tcp_pump100_client)
|
||||
BENCHMARK_DECLARE (tcp_pump1_client)
|
||||
BENCHMARK_DECLARE (pipe_pump100_client)
|
||||
BENCHMARK_DECLARE (pipe_pump1_client)
|
||||
|
||||
BENCHMARK_DECLARE (tcp_multi_accept2)
|
||||
BENCHMARK_DECLARE (tcp_multi_accept4)
|
||||
BENCHMARK_DECLARE (tcp_multi_accept8)
|
||||
|
||||
/* Run until X packets have been sent/received. */
|
||||
BENCHMARK_DECLARE (udp_pummel_1v1)
|
||||
BENCHMARK_DECLARE (udp_pummel_1v10)
|
||||
BENCHMARK_DECLARE (udp_pummel_1v100)
|
||||
BENCHMARK_DECLARE (udp_pummel_1v1000)
|
||||
BENCHMARK_DECLARE (udp_pummel_10v10)
|
||||
BENCHMARK_DECLARE (udp_pummel_10v100)
|
||||
BENCHMARK_DECLARE (udp_pummel_10v1000)
|
||||
BENCHMARK_DECLARE (udp_pummel_100v100)
|
||||
BENCHMARK_DECLARE (udp_pummel_100v1000)
|
||||
BENCHMARK_DECLARE (udp_pummel_1000v1000)
|
||||
|
||||
/* Run until X seconds have elapsed. */
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_1v1)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_1v10)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_1v100)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_1v1000)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_10v10)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_10v100)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_10v1000)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_100v100)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_100v1000)
|
||||
BENCHMARK_DECLARE (udp_timed_pummel_1000v1000)
|
||||
|
||||
BENCHMARK_DECLARE (getaddrinfo)
|
||||
BENCHMARK_DECLARE (fs_stat)
|
||||
BENCHMARK_DECLARE (async1)
|
||||
BENCHMARK_DECLARE (async2)
|
||||
BENCHMARK_DECLARE (async4)
|
||||
BENCHMARK_DECLARE (async8)
|
||||
BENCHMARK_DECLARE (async_pummel_1)
|
||||
BENCHMARK_DECLARE (async_pummel_2)
|
||||
BENCHMARK_DECLARE (async_pummel_4)
|
||||
BENCHMARK_DECLARE (async_pummel_8)
|
||||
BENCHMARK_DECLARE (spawn)
|
||||
BENCHMARK_DECLARE (thread_create)
|
||||
BENCHMARK_DECLARE (million_async)
|
||||
BENCHMARK_DECLARE (million_timers)
|
||||
HELPER_DECLARE (tcp4_blackhole_server)
|
||||
HELPER_DECLARE (tcp_pump_server)
|
||||
HELPER_DECLARE (pipe_pump_server)
|
||||
HELPER_DECLARE (tcp4_echo_server)
|
||||
HELPER_DECLARE (pipe_echo_server)
|
||||
HELPER_DECLARE (dns_server)
|
||||
|
||||
TASK_LIST_START
|
||||
BENCHMARK_ENTRY (sizes)
|
||||
BENCHMARK_ENTRY (loop_count)
|
||||
BENCHMARK_ENTRY (loop_count_timed)
|
||||
|
||||
BENCHMARK_ENTRY (ping_pongs)
|
||||
BENCHMARK_HELPER (ping_pongs, tcp4_echo_server)
|
||||
|
||||
BENCHMARK_ENTRY (tcp_write_batch)
|
||||
BENCHMARK_HELPER (tcp_write_batch, tcp4_blackhole_server)
|
||||
|
||||
BENCHMARK_ENTRY (tcp_pump100_client)
|
||||
BENCHMARK_HELPER (tcp_pump100_client, tcp_pump_server)
|
||||
|
||||
BENCHMARK_ENTRY (tcp_pump1_client)
|
||||
BENCHMARK_HELPER (tcp_pump1_client, tcp_pump_server)
|
||||
|
||||
BENCHMARK_ENTRY (tcp4_pound_100)
|
||||
BENCHMARK_HELPER (tcp4_pound_100, tcp4_echo_server)
|
||||
|
||||
BENCHMARK_ENTRY (tcp4_pound_1000)
|
||||
BENCHMARK_HELPER (tcp4_pound_1000, tcp4_echo_server)
|
||||
|
||||
BENCHMARK_ENTRY (pipe_pump100_client)
|
||||
BENCHMARK_HELPER (pipe_pump100_client, pipe_pump_server)
|
||||
|
||||
BENCHMARK_ENTRY (pipe_pump1_client)
|
||||
BENCHMARK_HELPER (pipe_pump1_client, pipe_pump_server)
|
||||
|
||||
BENCHMARK_ENTRY (pipe_pound_100)
|
||||
BENCHMARK_HELPER (pipe_pound_100, pipe_echo_server)
|
||||
|
||||
BENCHMARK_ENTRY (pipe_pound_1000)
|
||||
BENCHMARK_HELPER (pipe_pound_1000, pipe_echo_server)
|
||||
|
||||
BENCHMARK_ENTRY (tcp_multi_accept2)
|
||||
BENCHMARK_ENTRY (tcp_multi_accept4)
|
||||
BENCHMARK_ENTRY (tcp_multi_accept8)
|
||||
|
||||
BENCHMARK_ENTRY (udp_pummel_1v1)
|
||||
BENCHMARK_ENTRY (udp_pummel_1v10)
|
||||
BENCHMARK_ENTRY (udp_pummel_1v100)
|
||||
BENCHMARK_ENTRY (udp_pummel_1v1000)
|
||||
BENCHMARK_ENTRY (udp_pummel_10v10)
|
||||
BENCHMARK_ENTRY (udp_pummel_10v100)
|
||||
BENCHMARK_ENTRY (udp_pummel_10v1000)
|
||||
BENCHMARK_ENTRY (udp_pummel_100v100)
|
||||
BENCHMARK_ENTRY (udp_pummel_100v1000)
|
||||
BENCHMARK_ENTRY (udp_pummel_1000v1000)
|
||||
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_1v1)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_1v10)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_1v100)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_1v1000)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_10v10)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_10v100)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_10v1000)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_100v100)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_100v1000)
|
||||
BENCHMARK_ENTRY (udp_timed_pummel_1000v1000)
|
||||
|
||||
BENCHMARK_ENTRY (getaddrinfo)
|
||||
|
||||
BENCHMARK_ENTRY (fs_stat)
|
||||
|
||||
BENCHMARK_ENTRY (async1)
|
||||
BENCHMARK_ENTRY (async2)
|
||||
BENCHMARK_ENTRY (async4)
|
||||
BENCHMARK_ENTRY (async8)
|
||||
BENCHMARK_ENTRY (async_pummel_1)
|
||||
BENCHMARK_ENTRY (async_pummel_2)
|
||||
BENCHMARK_ENTRY (async_pummel_4)
|
||||
BENCHMARK_ENTRY (async_pummel_8)
|
||||
|
||||
BENCHMARK_ENTRY (spawn)
|
||||
BENCHMARK_ENTRY (thread_create)
|
||||
BENCHMARK_ENTRY (million_async)
|
||||
BENCHMARK_ENTRY (million_timers)
|
||||
TASK_LIST_END
|
92
deps/libuv/test/benchmark-loop-count.c
vendored
Normal file
92
deps/libuv/test/benchmark-loop-count.c
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NUM_TICKS (2 * 1000 * 1000)
|
||||
|
||||
static unsigned long ticks;
|
||||
static uv_idle_t idle_handle;
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
|
||||
static void idle_cb(uv_idle_t* handle) {
|
||||
if (++ticks == NUM_TICKS)
|
||||
uv_idle_stop(handle);
|
||||
}
|
||||
|
||||
|
||||
static void idle2_cb(uv_idle_t* handle) {
|
||||
ticks++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
uv_idle_stop(&idle_handle);
|
||||
uv_timer_stop(&timer_handle);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(loop_count) {
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
uint64_t ns;
|
||||
|
||||
uv_idle_init(loop, &idle_handle);
|
||||
uv_idle_start(&idle_handle, idle_cb);
|
||||
|
||||
ns = uv_hrtime();
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ns = uv_hrtime() - ns;
|
||||
|
||||
ASSERT(ticks == NUM_TICKS);
|
||||
|
||||
fprintf(stderr, "loop_count: %d ticks in %.2fs (%.0f/s)\n",
|
||||
NUM_TICKS,
|
||||
ns / 1e9,
|
||||
NUM_TICKS / (ns / 1e9));
|
||||
fflush(stderr);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(loop_count_timed) {
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
|
||||
uv_idle_init(loop, &idle_handle);
|
||||
uv_idle_start(&idle_handle, idle2_cb);
|
||||
|
||||
uv_timer_init(loop, &timer_handle);
|
||||
uv_timer_start(&timer_handle, timer_cb, 5000, 0);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
fprintf(stderr, "loop_count: %lu ticks (%.0f ticks/s)\n", ticks, ticks / 5.0);
|
||||
fflush(stderr);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
112
deps/libuv/test/benchmark-million-async.c
vendored
Normal file
112
deps/libuv/test/benchmark-million-async.c
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
struct async_container {
|
||||
unsigned async_events;
|
||||
unsigned handles_seen;
|
||||
uv_async_t async_handles[1024 * 1024];
|
||||
};
|
||||
|
||||
static volatile int done;
|
||||
static uv_thread_t thread_id;
|
||||
static struct async_container* container;
|
||||
|
||||
|
||||
static unsigned fastrand(void) {
|
||||
static unsigned g = 0;
|
||||
g = g * 214013 + 2531011;
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
static void thread_cb(void* arg) {
|
||||
unsigned i;
|
||||
|
||||
while (done == 0) {
|
||||
i = fastrand() % ARRAY_SIZE(container->async_handles);
|
||||
uv_async_send(container->async_handles + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void async_cb(uv_async_t* handle) {
|
||||
container->async_events++;
|
||||
handle->data = handle;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
unsigned i;
|
||||
|
||||
done = 1;
|
||||
ASSERT(0 == uv_thread_join(&thread_id));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(container->async_handles); i++) {
|
||||
uv_async_t* handle = container->async_handles + i;
|
||||
|
||||
if (handle->data != NULL)
|
||||
container->handles_seen++;
|
||||
|
||||
uv_close((uv_handle_t*) handle, NULL);
|
||||
}
|
||||
|
||||
uv_close((uv_handle_t*) handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(million_async) {
|
||||
uv_timer_t timer_handle;
|
||||
uv_async_t* handle;
|
||||
uv_loop_t* loop;
|
||||
int timeout;
|
||||
unsigned i;
|
||||
|
||||
loop = uv_default_loop();
|
||||
timeout = 5000;
|
||||
|
||||
container = malloc(sizeof(*container));
|
||||
ASSERT(container != NULL);
|
||||
container->async_events = 0;
|
||||
container->handles_seen = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(container->async_handles); i++) {
|
||||
handle = container->async_handles + i;
|
||||
ASSERT(0 == uv_async_init(loop, handle, async_cb));
|
||||
handle->data = NULL;
|
||||
}
|
||||
|
||||
ASSERT(0 == uv_timer_init(loop, &timer_handle));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, timeout, 0));
|
||||
ASSERT(0 == uv_thread_create(&thread_id, thread_cb, NULL));
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
printf("%s async events in %.1f seconds (%s/s, %s unique handles seen)\n",
|
||||
fmt(container->async_events),
|
||||
timeout / 1000.,
|
||||
fmt(container->async_events / (timeout / 1000.)),
|
||||
fmt(container->handles_seen));
|
||||
free(container);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
86
deps/libuv/test/benchmark-million-timers.c
vendored
Normal file
86
deps/libuv/test/benchmark-million-timers.c
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#define NUM_TIMERS (10 * 1000 * 1000)
|
||||
|
||||
static int timer_cb_called;
|
||||
static int close_cb_called;
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
timer_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(million_timers) {
|
||||
uv_timer_t* timers;
|
||||
uv_loop_t* loop;
|
||||
uint64_t before_all;
|
||||
uint64_t before_run;
|
||||
uint64_t after_run;
|
||||
uint64_t after_all;
|
||||
int timeout;
|
||||
int i;
|
||||
|
||||
timers = malloc(NUM_TIMERS * sizeof(timers[0]));
|
||||
ASSERT(timers != NULL);
|
||||
|
||||
loop = uv_default_loop();
|
||||
timeout = 0;
|
||||
|
||||
before_all = uv_hrtime();
|
||||
for (i = 0; i < NUM_TIMERS; i++) {
|
||||
if (i % 1000 == 0) timeout++;
|
||||
ASSERT(0 == uv_timer_init(loop, timers + i));
|
||||
ASSERT(0 == uv_timer_start(timers + i, timer_cb, timeout, 0));
|
||||
}
|
||||
|
||||
before_run = uv_hrtime();
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
after_run = uv_hrtime();
|
||||
|
||||
for (i = 0; i < NUM_TIMERS; i++)
|
||||
uv_close((uv_handle_t*) (timers + i), close_cb);
|
||||
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
after_all = uv_hrtime();
|
||||
|
||||
ASSERT(timer_cb_called == NUM_TIMERS);
|
||||
ASSERT(close_cb_called == NUM_TIMERS);
|
||||
free(timers);
|
||||
|
||||
fprintf(stderr, "%.2f seconds total\n", (after_all - before_all) / 1e9);
|
||||
fprintf(stderr, "%.2f seconds init\n", (before_run - before_all) / 1e9);
|
||||
fprintf(stderr, "%.2f seconds dispatch\n", (after_run - before_run) / 1e9);
|
||||
fprintf(stderr, "%.2f seconds cleanup\n", (after_all - after_run) / 1e9);
|
||||
fflush(stderr);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
451
deps/libuv/test/benchmark-multi-accept.c
vendored
Normal file
451
deps/libuv/test/benchmark-multi-accept.c
vendored
Normal file
@ -0,0 +1,451 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#define IPC_PIPE_NAME TEST_PIPENAME
|
||||
#define NUM_CONNECTS (250 * 1000)
|
||||
|
||||
union stream_handle {
|
||||
uv_pipe_t pipe;
|
||||
uv_tcp_t tcp;
|
||||
};
|
||||
|
||||
/* Use as (uv_stream_t *) &handle_storage -- it's kind of clunky but it
|
||||
* avoids aliasing warnings.
|
||||
*/
|
||||
typedef unsigned char handle_storage_t[sizeof(union stream_handle)];
|
||||
|
||||
/* Used for passing around the listen handle, not part of the benchmark proper.
|
||||
* We have an overabundance of server types here. It works like this:
|
||||
*
|
||||
* 1. The main thread starts an IPC pipe server.
|
||||
* 2. The worker threads connect to the IPC server and obtain a listen handle.
|
||||
* 3. The worker threads start accepting requests on the listen handle.
|
||||
* 4. The main thread starts connecting repeatedly.
|
||||
*
|
||||
* Step #4 should perhaps be farmed out over several threads.
|
||||
*/
|
||||
struct ipc_server_ctx {
|
||||
handle_storage_t server_handle;
|
||||
unsigned int num_connects;
|
||||
uv_pipe_t ipc_pipe;
|
||||
};
|
||||
|
||||
struct ipc_peer_ctx {
|
||||
handle_storage_t peer_handle;
|
||||
uv_write_t write_req;
|
||||
};
|
||||
|
||||
struct ipc_client_ctx {
|
||||
uv_connect_t connect_req;
|
||||
uv_stream_t* server_handle;
|
||||
uv_pipe_t ipc_pipe;
|
||||
char scratch[16];
|
||||
};
|
||||
|
||||
/* Used in the actual benchmark. */
|
||||
struct server_ctx {
|
||||
handle_storage_t server_handle;
|
||||
unsigned int num_connects;
|
||||
uv_async_t async_handle;
|
||||
uv_thread_t thread_id;
|
||||
uv_sem_t semaphore;
|
||||
};
|
||||
|
||||
struct client_ctx {
|
||||
handle_storage_t client_handle;
|
||||
unsigned int num_connects;
|
||||
uv_connect_t connect_req;
|
||||
uv_idle_t idle_handle;
|
||||
};
|
||||
|
||||
static void ipc_connection_cb(uv_stream_t* ipc_pipe, int status);
|
||||
static void ipc_write_cb(uv_write_t* req, int status);
|
||||
static void ipc_close_cb(uv_handle_t* handle);
|
||||
static void ipc_connect_cb(uv_connect_t* req, int status);
|
||||
static void ipc_read_cb(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf);
|
||||
static void ipc_alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf);
|
||||
|
||||
static void sv_async_cb(uv_async_t* handle);
|
||||
static void sv_connection_cb(uv_stream_t* server_handle, int status);
|
||||
static void sv_read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf);
|
||||
static void sv_alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf);
|
||||
|
||||
static void cl_connect_cb(uv_connect_t* req, int status);
|
||||
static void cl_idle_cb(uv_idle_t* handle);
|
||||
static void cl_close_cb(uv_handle_t* handle);
|
||||
|
||||
static struct sockaddr_in listen_addr;
|
||||
|
||||
|
||||
static void ipc_connection_cb(uv_stream_t* ipc_pipe, int status) {
|
||||
struct ipc_server_ctx* sc;
|
||||
struct ipc_peer_ctx* pc;
|
||||
uv_loop_t* loop;
|
||||
uv_buf_t buf;
|
||||
|
||||
loop = ipc_pipe->loop;
|
||||
buf = uv_buf_init("PING", 4);
|
||||
sc = container_of(ipc_pipe, struct ipc_server_ctx, ipc_pipe);
|
||||
pc = calloc(1, sizeof(*pc));
|
||||
ASSERT(pc != NULL);
|
||||
|
||||
if (ipc_pipe->type == UV_TCP)
|
||||
ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) &pc->peer_handle));
|
||||
else if (ipc_pipe->type == UV_NAMED_PIPE)
|
||||
ASSERT(0 == uv_pipe_init(loop, (uv_pipe_t*) &pc->peer_handle, 1));
|
||||
else
|
||||
ASSERT(0);
|
||||
|
||||
ASSERT(0 == uv_accept(ipc_pipe, (uv_stream_t*) &pc->peer_handle));
|
||||
ASSERT(0 == uv_write2(&pc->write_req,
|
||||
(uv_stream_t*) &pc->peer_handle,
|
||||
&buf,
|
||||
1,
|
||||
(uv_stream_t*) &sc->server_handle,
|
||||
ipc_write_cb));
|
||||
|
||||
if (--sc->num_connects == 0)
|
||||
uv_close((uv_handle_t*) ipc_pipe, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void ipc_write_cb(uv_write_t* req, int status) {
|
||||
struct ipc_peer_ctx* ctx;
|
||||
ctx = container_of(req, struct ipc_peer_ctx, write_req);
|
||||
uv_close((uv_handle_t*) &ctx->peer_handle, ipc_close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void ipc_close_cb(uv_handle_t* handle) {
|
||||
struct ipc_peer_ctx* ctx;
|
||||
ctx = container_of(handle, struct ipc_peer_ctx, peer_handle);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void ipc_connect_cb(uv_connect_t* req, int status) {
|
||||
struct ipc_client_ctx* ctx;
|
||||
ctx = container_of(req, struct ipc_client_ctx, connect_req);
|
||||
ASSERT(0 == status);
|
||||
ASSERT(0 == uv_read_start((uv_stream_t*) &ctx->ipc_pipe,
|
||||
ipc_alloc_cb,
|
||||
ipc_read_cb));
|
||||
}
|
||||
|
||||
|
||||
static void ipc_alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
struct ipc_client_ctx* ctx;
|
||||
ctx = container_of(handle, struct ipc_client_ctx, ipc_pipe);
|
||||
buf->base = ctx->scratch;
|
||||
buf->len = sizeof(ctx->scratch);
|
||||
}
|
||||
|
||||
|
||||
static void ipc_read_cb(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
struct ipc_client_ctx* ctx;
|
||||
uv_loop_t* loop;
|
||||
uv_handle_type type;
|
||||
uv_pipe_t* ipc_pipe;
|
||||
|
||||
ipc_pipe = (uv_pipe_t*) handle;
|
||||
ctx = container_of(ipc_pipe, struct ipc_client_ctx, ipc_pipe);
|
||||
loop = ipc_pipe->loop;
|
||||
|
||||
ASSERT(1 == uv_pipe_pending_count(ipc_pipe));
|
||||
type = uv_pipe_pending_type(ipc_pipe);
|
||||
if (type == UV_TCP)
|
||||
ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) ctx->server_handle));
|
||||
else if (type == UV_NAMED_PIPE)
|
||||
ASSERT(0 == uv_pipe_init(loop, (uv_pipe_t*) ctx->server_handle, 0));
|
||||
else
|
||||
ASSERT(0);
|
||||
|
||||
ASSERT(0 == uv_accept(handle, ctx->server_handle));
|
||||
uv_close((uv_handle_t*) &ctx->ipc_pipe, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Set up an IPC pipe server that hands out listen sockets to the worker
|
||||
* threads. It's kind of cumbersome for such a simple operation, maybe we
|
||||
* should revive uv_import() and uv_export().
|
||||
*/
|
||||
static void send_listen_handles(uv_handle_type type,
|
||||
unsigned int num_servers,
|
||||
struct server_ctx* servers) {
|
||||
struct ipc_server_ctx ctx;
|
||||
uv_loop_t* loop;
|
||||
unsigned int i;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ctx.num_connects = num_servers;
|
||||
|
||||
if (type == UV_TCP) {
|
||||
ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) &ctx.server_handle));
|
||||
ASSERT(0 == uv_tcp_bind((uv_tcp_t*) &ctx.server_handle,
|
||||
(const struct sockaddr*) &listen_addr,
|
||||
0));
|
||||
}
|
||||
else
|
||||
ASSERT(0);
|
||||
/* We need to initialize this pipe with ipc=0 - this is not a uv_pipe we'll
|
||||
* be sending handles over, it's just for listening for new connections.
|
||||
* If we accept a connection then the connected pipe must be initialized
|
||||
* with ipc=1.
|
||||
*/
|
||||
ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 0));
|
||||
ASSERT(0 == uv_pipe_bind(&ctx.ipc_pipe, IPC_PIPE_NAME));
|
||||
ASSERT(0 == uv_listen((uv_stream_t*) &ctx.ipc_pipe, 128, ipc_connection_cb));
|
||||
|
||||
for (i = 0; i < num_servers; i++)
|
||||
uv_sem_post(&servers[i].semaphore);
|
||||
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
uv_close((uv_handle_t*) &ctx.server_handle, NULL);
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
|
||||
for (i = 0; i < num_servers; i++)
|
||||
uv_sem_wait(&servers[i].semaphore);
|
||||
}
|
||||
|
||||
|
||||
static void get_listen_handle(uv_loop_t* loop, uv_stream_t* server_handle) {
|
||||
struct ipc_client_ctx ctx;
|
||||
|
||||
ctx.server_handle = server_handle;
|
||||
ctx.server_handle->data = "server handle";
|
||||
|
||||
ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 1));
|
||||
uv_pipe_connect(&ctx.connect_req,
|
||||
&ctx.ipc_pipe,
|
||||
IPC_PIPE_NAME,
|
||||
ipc_connect_cb);
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
}
|
||||
|
||||
|
||||
static void server_cb(void *arg) {
|
||||
struct server_ctx *ctx;
|
||||
uv_loop_t loop;
|
||||
|
||||
ctx = arg;
|
||||
ASSERT(0 == uv_loop_init(&loop));
|
||||
|
||||
ASSERT(0 == uv_async_init(&loop, &ctx->async_handle, sv_async_cb));
|
||||
uv_unref((uv_handle_t*) &ctx->async_handle);
|
||||
|
||||
/* Wait until the main thread is ready. */
|
||||
uv_sem_wait(&ctx->semaphore);
|
||||
get_listen_handle(&loop, (uv_stream_t*) &ctx->server_handle);
|
||||
uv_sem_post(&ctx->semaphore);
|
||||
|
||||
/* Now start the actual benchmark. */
|
||||
ASSERT(0 == uv_listen((uv_stream_t*) &ctx->server_handle,
|
||||
128,
|
||||
sv_connection_cb));
|
||||
ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
|
||||
|
||||
uv_loop_close(&loop);
|
||||
}
|
||||
|
||||
|
||||
static void sv_async_cb(uv_async_t* handle) {
|
||||
struct server_ctx* ctx;
|
||||
ctx = container_of(handle, struct server_ctx, async_handle);
|
||||
uv_close((uv_handle_t*) &ctx->server_handle, NULL);
|
||||
uv_close((uv_handle_t*) &ctx->async_handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void sv_connection_cb(uv_stream_t* server_handle, int status) {
|
||||
handle_storage_t* storage;
|
||||
struct server_ctx* ctx;
|
||||
|
||||
ctx = container_of(server_handle, struct server_ctx, server_handle);
|
||||
ASSERT(status == 0);
|
||||
|
||||
storage = malloc(sizeof(*storage));
|
||||
ASSERT(storage != NULL);
|
||||
|
||||
if (server_handle->type == UV_TCP)
|
||||
ASSERT(0 == uv_tcp_init(server_handle->loop, (uv_tcp_t*) storage));
|
||||
else if (server_handle->type == UV_NAMED_PIPE)
|
||||
ASSERT(0 == uv_pipe_init(server_handle->loop, (uv_pipe_t*) storage, 0));
|
||||
else
|
||||
ASSERT(0);
|
||||
|
||||
ASSERT(0 == uv_accept(server_handle, (uv_stream_t*) storage));
|
||||
ASSERT(0 == uv_read_start((uv_stream_t*) storage, sv_alloc_cb, sv_read_cb));
|
||||
ctx->num_connects++;
|
||||
}
|
||||
|
||||
|
||||
static void sv_alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
static char slab[32];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void sv_read_cb(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
ASSERT(nread == UV_EOF);
|
||||
uv_close((uv_handle_t*) handle, (uv_close_cb) free);
|
||||
}
|
||||
|
||||
|
||||
static void cl_connect_cb(uv_connect_t* req, int status) {
|
||||
struct client_ctx* ctx = container_of(req, struct client_ctx, connect_req);
|
||||
uv_idle_start(&ctx->idle_handle, cl_idle_cb);
|
||||
ASSERT(0 == status);
|
||||
}
|
||||
|
||||
|
||||
static void cl_idle_cb(uv_idle_t* handle) {
|
||||
struct client_ctx* ctx = container_of(handle, struct client_ctx, idle_handle);
|
||||
uv_close((uv_handle_t*) &ctx->client_handle, cl_close_cb);
|
||||
uv_idle_stop(&ctx->idle_handle);
|
||||
}
|
||||
|
||||
|
||||
static void cl_close_cb(uv_handle_t* handle) {
|
||||
struct client_ctx* ctx;
|
||||
|
||||
ctx = container_of(handle, struct client_ctx, client_handle);
|
||||
|
||||
if (--ctx->num_connects == 0) {
|
||||
uv_close((uv_handle_t*) &ctx->idle_handle, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(0 == uv_tcp_init(handle->loop, (uv_tcp_t*) &ctx->client_handle));
|
||||
ASSERT(0 == uv_tcp_connect(&ctx->connect_req,
|
||||
(uv_tcp_t*) &ctx->client_handle,
|
||||
(const struct sockaddr*) &listen_addr,
|
||||
cl_connect_cb));
|
||||
}
|
||||
|
||||
|
||||
static int test_tcp(unsigned int num_servers, unsigned int num_clients) {
|
||||
struct server_ctx* servers;
|
||||
struct client_ctx* clients;
|
||||
uv_loop_t* loop;
|
||||
uv_tcp_t* handle;
|
||||
unsigned int i;
|
||||
double time;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &listen_addr));
|
||||
loop = uv_default_loop();
|
||||
|
||||
servers = calloc(num_servers, sizeof(servers[0]));
|
||||
clients = calloc(num_clients, sizeof(clients[0]));
|
||||
ASSERT(servers != NULL);
|
||||
ASSERT(clients != NULL);
|
||||
|
||||
/* We're making the assumption here that from the perspective of the
|
||||
* OS scheduler, threads are functionally equivalent to and interchangeable
|
||||
* with full-blown processes.
|
||||
*/
|
||||
for (i = 0; i < num_servers; i++) {
|
||||
struct server_ctx* ctx = servers + i;
|
||||
ASSERT(0 == uv_sem_init(&ctx->semaphore, 0));
|
||||
ASSERT(0 == uv_thread_create(&ctx->thread_id, server_cb, ctx));
|
||||
}
|
||||
|
||||
send_listen_handles(UV_TCP, num_servers, servers);
|
||||
|
||||
for (i = 0; i < num_clients; i++) {
|
||||
struct client_ctx* ctx = clients + i;
|
||||
ctx->num_connects = NUM_CONNECTS / num_clients;
|
||||
handle = (uv_tcp_t*) &ctx->client_handle;
|
||||
handle->data = "client handle";
|
||||
ASSERT(0 == uv_tcp_init(loop, handle));
|
||||
ASSERT(0 == uv_tcp_connect(&ctx->connect_req,
|
||||
handle,
|
||||
(const struct sockaddr*) &listen_addr,
|
||||
cl_connect_cb));
|
||||
ASSERT(0 == uv_idle_init(loop, &ctx->idle_handle));
|
||||
}
|
||||
|
||||
{
|
||||
uint64_t t = uv_hrtime();
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
t = uv_hrtime() - t;
|
||||
time = t / 1e9;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_servers; i++) {
|
||||
struct server_ctx* ctx = servers + i;
|
||||
uv_async_send(&ctx->async_handle);
|
||||
ASSERT(0 == uv_thread_join(&ctx->thread_id));
|
||||
uv_sem_destroy(&ctx->semaphore);
|
||||
}
|
||||
|
||||
printf("accept%u: %.0f accepts/sec (%u total)\n",
|
||||
num_servers,
|
||||
NUM_CONNECTS / time,
|
||||
NUM_CONNECTS);
|
||||
|
||||
for (i = 0; i < num_servers; i++) {
|
||||
struct server_ctx* ctx = servers + i;
|
||||
printf(" thread #%u: %.0f accepts/sec (%u total, %.1f%%)\n",
|
||||
i,
|
||||
ctx->num_connects / time,
|
||||
ctx->num_connects,
|
||||
ctx->num_connects * 100.0 / NUM_CONNECTS);
|
||||
}
|
||||
|
||||
free(clients);
|
||||
free(servers);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp_multi_accept2) {
|
||||
return test_tcp(2, 40);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp_multi_accept4) {
|
||||
return test_tcp(4, 40);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp_multi_accept8) {
|
||||
return test_tcp(8, 40);
|
||||
}
|
221
deps/libuv/test/benchmark-ping-pongs.c
vendored
Normal file
221
deps/libuv/test/benchmark-ping-pongs.c
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Run the benchmark for this many ms */
|
||||
#define TIME 5000
|
||||
|
||||
|
||||
typedef struct {
|
||||
int pongs;
|
||||
int state;
|
||||
uv_tcp_t tcp;
|
||||
uv_connect_t connect_req;
|
||||
uv_shutdown_t shutdown_req;
|
||||
} pinger_t;
|
||||
|
||||
typedef struct buf_s {
|
||||
uv_buf_t uv_buf_t;
|
||||
struct buf_s* next;
|
||||
} buf_t;
|
||||
|
||||
|
||||
static char PING[] = "PING\n";
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static buf_t* buf_freelist = NULL;
|
||||
static int pinger_shutdown_cb_called;
|
||||
static int completed_pingers = 0;
|
||||
static int64_t start_time;
|
||||
|
||||
|
||||
static void buf_alloc(uv_handle_t* tcp, size_t size, uv_buf_t* buf) {
|
||||
buf_t* ab;
|
||||
|
||||
ab = buf_freelist;
|
||||
if (ab != NULL)
|
||||
buf_freelist = ab->next;
|
||||
else {
|
||||
ab = malloc(size + sizeof(*ab));
|
||||
ab->uv_buf_t.len = size;
|
||||
ab->uv_buf_t.base = (char*) (ab + 1);
|
||||
}
|
||||
|
||||
*buf = ab->uv_buf_t;
|
||||
}
|
||||
|
||||
|
||||
static void buf_free(const uv_buf_t* buf) {
|
||||
buf_t* ab = (buf_t*) buf->base - 1;
|
||||
ab->next = buf_freelist;
|
||||
buf_freelist = ab;
|
||||
}
|
||||
|
||||
|
||||
static void pinger_close_cb(uv_handle_t* handle) {
|
||||
pinger_t* pinger;
|
||||
|
||||
pinger = (pinger_t*)handle->data;
|
||||
fprintf(stderr, "ping_pongs: %d roundtrips/s\n", (1000 * pinger->pongs) / TIME);
|
||||
fflush(stderr);
|
||||
|
||||
free(pinger);
|
||||
|
||||
completed_pingers++;
|
||||
}
|
||||
|
||||
|
||||
static void pinger_write_cb(uv_write_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
|
||||
free(req);
|
||||
}
|
||||
|
||||
|
||||
static void pinger_write_ping(pinger_t* pinger) {
|
||||
uv_write_t* req;
|
||||
uv_buf_t buf;
|
||||
|
||||
buf = uv_buf_init(PING, sizeof(PING) - 1);
|
||||
|
||||
req = malloc(sizeof *req);
|
||||
if (uv_write(req, (uv_stream_t*) &pinger->tcp, &buf, 1, pinger_write_cb)) {
|
||||
FATAL("uv_write failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void pinger_shutdown_cb(uv_shutdown_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
pinger_shutdown_cb_called++;
|
||||
|
||||
/*
|
||||
* The close callback has not been triggered yet. We must wait for EOF
|
||||
* until we close the connection.
|
||||
*/
|
||||
ASSERT(completed_pingers == 0);
|
||||
}
|
||||
|
||||
|
||||
static void pinger_read_cb(uv_stream_t* tcp,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
ssize_t i;
|
||||
pinger_t* pinger;
|
||||
|
||||
pinger = (pinger_t*)tcp->data;
|
||||
|
||||
if (nread < 0) {
|
||||
ASSERT(nread == UV_EOF);
|
||||
|
||||
if (buf->base) {
|
||||
buf_free(buf);
|
||||
}
|
||||
|
||||
ASSERT(pinger_shutdown_cb_called == 1);
|
||||
uv_close((uv_handle_t*)tcp, pinger_close_cb);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now we count the pings */
|
||||
for (i = 0; i < nread; i++) {
|
||||
ASSERT(buf->base[i] == PING[pinger->state]);
|
||||
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
|
||||
if (pinger->state == 0) {
|
||||
pinger->pongs++;
|
||||
if (uv_now(loop) - start_time > TIME) {
|
||||
uv_shutdown(&pinger->shutdown_req,
|
||||
(uv_stream_t*) tcp,
|
||||
pinger_shutdown_cb);
|
||||
break;
|
||||
} else {
|
||||
pinger_write_ping(pinger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf_free(buf);
|
||||
}
|
||||
|
||||
|
||||
static void pinger_connect_cb(uv_connect_t* req, int status) {
|
||||
pinger_t *pinger = (pinger_t*)req->handle->data;
|
||||
|
||||
ASSERT(status == 0);
|
||||
|
||||
pinger_write_ping(pinger);
|
||||
|
||||
if (uv_read_start(req->handle, buf_alloc, pinger_read_cb)) {
|
||||
FATAL("uv_read_start failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void pinger_new(void) {
|
||||
struct sockaddr_in client_addr;
|
||||
struct sockaddr_in server_addr;
|
||||
pinger_t *pinger;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &client_addr));
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
|
||||
pinger = malloc(sizeof(*pinger));
|
||||
pinger->state = 0;
|
||||
pinger->pongs = 0;
|
||||
|
||||
/* Try to connect to the server and do NUM_PINGS ping-pongs. */
|
||||
r = uv_tcp_init(loop, &pinger->tcp);
|
||||
ASSERT(!r);
|
||||
|
||||
pinger->tcp.data = pinger;
|
||||
|
||||
ASSERT(0 == uv_tcp_bind(&pinger->tcp,
|
||||
(const struct sockaddr*) &client_addr,
|
||||
0));
|
||||
|
||||
r = uv_tcp_connect(&pinger->connect_req,
|
||||
&pinger->tcp,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
pinger_connect_cb);
|
||||
ASSERT(!r);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(ping_pongs) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
start_time = uv_now(loop);
|
||||
|
||||
pinger_new();
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(completed_pingers == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
163
deps/libuv/test/benchmark-ping-udp.c
vendored
Normal file
163
deps/libuv/test/benchmark-ping-udp.c
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
/* Copyright libuv project 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Run the benchmark for this many ms */
|
||||
#define TIME 5000
|
||||
|
||||
typedef struct {
|
||||
int pongs;
|
||||
int state;
|
||||
uv_udp_t udp;
|
||||
struct sockaddr_in server_addr;
|
||||
} pinger_t;
|
||||
|
||||
typedef struct buf_s {
|
||||
uv_buf_t uv_buf_t;
|
||||
struct buf_s* next;
|
||||
} buf_t;
|
||||
|
||||
static char PING[] = "PING\n";
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static int completed_pingers;
|
||||
static unsigned long completed_pings;
|
||||
static int64_t start_time;
|
||||
|
||||
|
||||
static void buf_alloc(uv_handle_t* tcp, size_t size, uv_buf_t* buf) {
|
||||
static char slab[64 * 1024];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void buf_free(const uv_buf_t* buf) {
|
||||
}
|
||||
|
||||
|
||||
static void pinger_close_cb(uv_handle_t* handle) {
|
||||
pinger_t* pinger;
|
||||
|
||||
pinger = (pinger_t*)handle->data;
|
||||
#if DEBUG
|
||||
fprintf(stderr, "ping_pongs: %d roundtrips/s\n",
|
||||
pinger->pongs / (TIME / 1000));
|
||||
#endif
|
||||
|
||||
completed_pings += pinger->pongs;
|
||||
completed_pingers++;
|
||||
free(pinger);
|
||||
}
|
||||
|
||||
static void pinger_write_ping(pinger_t* pinger) {
|
||||
uv_buf_t buf;
|
||||
int r;
|
||||
|
||||
buf = uv_buf_init(PING, sizeof(PING) - 1);
|
||||
r = uv_udp_try_send(&pinger->udp, &buf, 1,
|
||||
(const struct sockaddr*) &pinger->server_addr);
|
||||
if (r < 0)
|
||||
FATAL("uv_udp_send failed");
|
||||
}
|
||||
|
||||
static void pinger_read_cb(uv_udp_t* udp,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf,
|
||||
const struct sockaddr* addr,
|
||||
unsigned flags) {
|
||||
ssize_t i;
|
||||
pinger_t* pinger;
|
||||
pinger = (pinger_t*)udp->data;
|
||||
|
||||
/* Now we count the pings */
|
||||
for (i = 0; i < nread; i++) {
|
||||
ASSERT(buf->base[i] == PING[pinger->state]);
|
||||
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
|
||||
if (pinger->state == 0) {
|
||||
pinger->pongs++;
|
||||
if (uv_now(loop) - start_time > TIME) {
|
||||
uv_close((uv_handle_t*)udp, pinger_close_cb);
|
||||
break;
|
||||
}
|
||||
pinger_write_ping(pinger);
|
||||
}
|
||||
}
|
||||
|
||||
buf_free(buf);
|
||||
}
|
||||
|
||||
static void udp_pinger_new(void) {
|
||||
pinger_t* pinger = malloc(sizeof(*pinger));
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &pinger->server_addr));
|
||||
pinger->state = 0;
|
||||
pinger->pongs = 0;
|
||||
|
||||
/* Try to do NUM_PINGS ping-pongs (connection-less). */
|
||||
r = uv_udp_init(loop, &pinger->udp);
|
||||
ASSERT(r == 0);
|
||||
|
||||
pinger->udp.data = pinger;
|
||||
|
||||
/* Start pinging */
|
||||
if (0 != uv_udp_recv_start(&pinger->udp, buf_alloc, pinger_read_cb)) {
|
||||
FATAL("uv_udp_read_start failed");
|
||||
}
|
||||
pinger_write_ping(pinger);
|
||||
}
|
||||
|
||||
static int ping_udp(unsigned pingers) {
|
||||
unsigned i;
|
||||
|
||||
loop = uv_default_loop();
|
||||
start_time = uv_now(loop);
|
||||
|
||||
for (i = 0; i < pingers; ++i) {
|
||||
udp_pinger_new();
|
||||
}
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(completed_pingers >= 1);
|
||||
|
||||
fprintf(stderr, "ping_pongs: %d pingers, ~ %lu roundtrips/s\n",
|
||||
completed_pingers, completed_pings / (TIME/1000));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define X(PINGERS) \
|
||||
BENCHMARK_IMPL(ping_udp##PINGERS) {\
|
||||
return ping_udp(PINGERS); \
|
||||
}
|
||||
|
||||
X(1)
|
||||
X(10)
|
||||
X(100)
|
||||
|
||||
#undef X
|
351
deps/libuv/test/benchmark-pound.c
vendored
Normal file
351
deps/libuv/test/benchmark-pound.c
vendored
Normal file
@ -0,0 +1,351 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
/* Update this is you're going to run > 1000 concurrent requests. */
|
||||
#define MAX_CONNS 1000
|
||||
|
||||
#undef NANOSEC
|
||||
#define NANOSEC ((uint64_t) 1e9)
|
||||
|
||||
#undef DEBUG
|
||||
#define DEBUG 0
|
||||
|
||||
struct conn_rec_s;
|
||||
|
||||
typedef void (*setup_fn)(int num, void* arg);
|
||||
typedef void (*make_connect_fn)(struct conn_rec_s* conn);
|
||||
typedef int (*connect_fn)(int num, make_connect_fn make_connect, void* arg);
|
||||
|
||||
/* Base class for tcp_conn_rec and pipe_conn_rec.
|
||||
* The ordering of fields matters!
|
||||
*/
|
||||
typedef struct conn_rec_s {
|
||||
int i;
|
||||
uv_connect_t conn_req;
|
||||
uv_write_t write_req;
|
||||
make_connect_fn make_connect;
|
||||
uv_stream_t stream;
|
||||
} conn_rec;
|
||||
|
||||
typedef struct {
|
||||
int i;
|
||||
uv_connect_t conn_req;
|
||||
uv_write_t write_req;
|
||||
make_connect_fn make_connect;
|
||||
uv_tcp_t stream;
|
||||
} tcp_conn_rec;
|
||||
|
||||
typedef struct {
|
||||
int i;
|
||||
uv_connect_t conn_req;
|
||||
uv_write_t write_req;
|
||||
make_connect_fn make_connect;
|
||||
uv_pipe_t stream;
|
||||
} pipe_conn_rec;
|
||||
|
||||
static char buffer[] = "QS";
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static tcp_conn_rec tcp_conns[MAX_CONNS];
|
||||
static pipe_conn_rec pipe_conns[MAX_CONNS];
|
||||
|
||||
static uint64_t start; /* in ms */
|
||||
static int closed_streams;
|
||||
static int conns_failed;
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
||||
static void connect_cb(uv_connect_t* conn_req, int status);
|
||||
static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
||||
static void close_cb(uv_handle_t* handle);
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
static char slab[65536];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void after_write(uv_write_t* req, int status) {
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "write error %s\n", uv_err_name(status));
|
||||
uv_close((uv_handle_t*)req->handle, close_cb);
|
||||
conns_failed++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
conn_rec* conn;
|
||||
uv_buf_t buf;
|
||||
int r;
|
||||
|
||||
if (status != 0) {
|
||||
#if DEBUG
|
||||
fprintf(stderr, "connect error %s\n", uv_err_name(status));
|
||||
#endif
|
||||
uv_close((uv_handle_t*)req->handle, close_cb);
|
||||
conns_failed++;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
|
||||
conn = (conn_rec*)req->data;
|
||||
ASSERT(conn != NULL);
|
||||
|
||||
#if DEBUG
|
||||
printf("connect_cb %d\n", conn->i);
|
||||
#endif
|
||||
|
||||
r = uv_read_start(&conn->stream, alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
buf.base = buffer;
|
||||
buf.len = sizeof(buffer) - 1;
|
||||
|
||||
r = uv_write(&conn->write_req, &conn->stream, &buf, 1, after_write);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
||||
|
||||
ASSERT(stream != NULL);
|
||||
|
||||
#if DEBUG
|
||||
printf("read_cb %d\n", p->i);
|
||||
#endif
|
||||
|
||||
uv_close((uv_handle_t*)stream, close_cb);
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread == UV_EOF) {
|
||||
;
|
||||
} else if (nread == UV_ECONNRESET) {
|
||||
conns_failed++;
|
||||
} else {
|
||||
fprintf(stderr, "read error %s\n", uv_err_name(nread));
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
conn_rec* p = (conn_rec*)handle->data;
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
closed_streams++;
|
||||
|
||||
#if DEBUG
|
||||
printf("close_cb %d\n", p->i);
|
||||
#endif
|
||||
|
||||
if (uv_now(loop) - start < 10000) {
|
||||
p->make_connect(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void tcp_do_setup(int num, void* arg) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
tcp_conns[i].i = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void pipe_do_setup(int num, void* arg) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
pipe_conns[i].i = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void tcp_make_connect(conn_rec* p) {
|
||||
struct sockaddr_in addr;
|
||||
tcp_conn_rec* tp;
|
||||
int r;
|
||||
|
||||
tp = (tcp_conn_rec*) p;
|
||||
|
||||
r = uv_tcp_init(loop, (uv_tcp_t*)&p->stream);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_connect(&tp->conn_req,
|
||||
(uv_tcp_t*) &p->stream,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_tcp_connect error %s\n", uv_err_name(r));
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("make connect %d\n", p->i);
|
||||
#endif
|
||||
|
||||
p->conn_req.data = p;
|
||||
p->write_req.data = p;
|
||||
p->stream.data = p;
|
||||
}
|
||||
|
||||
|
||||
static void pipe_make_connect(conn_rec* p) {
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(loop, (uv_pipe_t*)&p->stream, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_pipe_connect(&((pipe_conn_rec*) p)->conn_req,
|
||||
(uv_pipe_t*) &p->stream,
|
||||
TEST_PIPENAME,
|
||||
connect_cb);
|
||||
|
||||
#if DEBUG
|
||||
printf("make connect %d\n", p->i);
|
||||
#endif
|
||||
|
||||
p->conn_req.data = p;
|
||||
p->write_req.data = p;
|
||||
p->stream.data = p;
|
||||
}
|
||||
|
||||
|
||||
static int tcp_do_connect(int num, make_connect_fn make_connect, void* arg) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
tcp_make_connect((conn_rec*)&tcp_conns[i]);
|
||||
tcp_conns[i].make_connect = make_connect;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int pipe_do_connect(int num, make_connect_fn make_connect, void* arg) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
pipe_make_connect((conn_rec*)&pipe_conns[i]);
|
||||
pipe_conns[i].make_connect = make_connect;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int pound_it(int concurrency,
|
||||
const char* type,
|
||||
setup_fn do_setup,
|
||||
connect_fn do_connect,
|
||||
make_connect_fn make_connect,
|
||||
void* arg) {
|
||||
double secs;
|
||||
int r;
|
||||
uint64_t start_time; /* in ns */
|
||||
uint64_t end_time;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
uv_update_time(loop);
|
||||
start = uv_now(loop);
|
||||
|
||||
/* Run benchmark for at least five seconds. */
|
||||
start_time = uv_hrtime();
|
||||
|
||||
do_setup(concurrency, arg);
|
||||
|
||||
r = do_connect(concurrency, make_connect, arg);
|
||||
ASSERT(!r);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
end_time = uv_hrtime();
|
||||
|
||||
/* Number of fractional seconds it took to run the benchmark. */
|
||||
secs = (double)(end_time - start_time) / NANOSEC;
|
||||
|
||||
fprintf(stderr, "%s-conn-pound-%d: %.0f accepts/s (%d failed)\n",
|
||||
type,
|
||||
concurrency,
|
||||
closed_streams / secs,
|
||||
conns_failed);
|
||||
fflush(stderr);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp4_pound_100) {
|
||||
return pound_it(100,
|
||||
"tcp",
|
||||
tcp_do_setup,
|
||||
tcp_do_connect,
|
||||
tcp_make_connect,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp4_pound_1000) {
|
||||
return pound_it(1000,
|
||||
"tcp",
|
||||
tcp_do_setup,
|
||||
tcp_do_connect,
|
||||
tcp_make_connect,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(pipe_pound_100) {
|
||||
return pound_it(100,
|
||||
"pipe",
|
||||
pipe_do_setup,
|
||||
pipe_do_connect,
|
||||
pipe_make_connect,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(pipe_pound_1000) {
|
||||
return pound_it(1000,
|
||||
"pipe",
|
||||
pipe_do_setup,
|
||||
pipe_do_connect,
|
||||
pipe_make_connect,
|
||||
NULL);
|
||||
}
|
476
deps/libuv/test/benchmark-pump.c
vendored
Normal file
476
deps/libuv/test/benchmark-pump.c
vendored
Normal file
@ -0,0 +1,476 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static int TARGET_CONNECTIONS;
|
||||
#define WRITE_BUFFER_SIZE 8192
|
||||
#define MAX_SIMULTANEOUS_CONNECTS 100
|
||||
|
||||
#define PRINT_STATS 0
|
||||
#define STATS_INTERVAL 1000 /* msec */
|
||||
#define STATS_COUNT 5
|
||||
|
||||
|
||||
static void do_write(uv_stream_t*);
|
||||
static void maybe_connect_some(void);
|
||||
|
||||
static uv_req_t* req_alloc(void);
|
||||
static void req_free(uv_req_t* uv_req);
|
||||
|
||||
static void buf_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf);
|
||||
static void buf_free(const uv_buf_t* buf);
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static uv_tcp_t tcpServer;
|
||||
static uv_pipe_t pipeServer;
|
||||
static uv_stream_t* server;
|
||||
static struct sockaddr_in listen_addr;
|
||||
static struct sockaddr_in connect_addr;
|
||||
|
||||
static int64_t start_time;
|
||||
|
||||
static int max_connect_socket = 0;
|
||||
static int max_read_sockets = 0;
|
||||
static int read_sockets = 0;
|
||||
static int write_sockets = 0;
|
||||
|
||||
static int64_t nrecv = 0;
|
||||
static int64_t nrecv_total = 0;
|
||||
static int64_t nsent = 0;
|
||||
static int64_t nsent_total = 0;
|
||||
|
||||
static int stats_left = 0;
|
||||
|
||||
static char write_buffer[WRITE_BUFFER_SIZE];
|
||||
|
||||
/* Make this as large as you need. */
|
||||
#define MAX_WRITE_HANDLES 1000
|
||||
|
||||
static stream_type type;
|
||||
|
||||
static uv_tcp_t tcp_write_handles[MAX_WRITE_HANDLES];
|
||||
static uv_pipe_t pipe_write_handles[MAX_WRITE_HANDLES];
|
||||
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
|
||||
static double gbit(int64_t bytes, int64_t passed_ms) {
|
||||
double gbits = ((double)bytes / (1024 * 1024 * 1024)) * 8;
|
||||
return gbits / ((double)passed_ms / 1000);
|
||||
}
|
||||
|
||||
|
||||
static void show_stats(uv_timer_t* handle) {
|
||||
int64_t diff;
|
||||
int i;
|
||||
|
||||
#if PRINT_STATS
|
||||
fprintf(stderr, "connections: %d, write: %.1f gbit/s\n",
|
||||
write_sockets,
|
||||
gbit(nsent, STATS_INTERVAL));
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
/* Exit if the show is over */
|
||||
if (!--stats_left) {
|
||||
|
||||
uv_update_time(loop);
|
||||
diff = uv_now(loop) - start_time;
|
||||
|
||||
fprintf(stderr, "%s_pump%d_client: %.1f gbit/s\n",
|
||||
type == TCP ? "tcp" : "pipe",
|
||||
write_sockets,
|
||||
gbit(nsent_total, diff));
|
||||
fflush(stderr);
|
||||
|
||||
for (i = 0; i < write_sockets; i++) {
|
||||
if (type == TCP)
|
||||
uv_close((uv_handle_t*) &tcp_write_handles[i], NULL);
|
||||
else
|
||||
uv_close((uv_handle_t*) &pipe_write_handles[i], NULL);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Reset read and write counters */
|
||||
nrecv = 0;
|
||||
nsent = 0;
|
||||
}
|
||||
|
||||
|
||||
static void read_show_stats(void) {
|
||||
int64_t diff;
|
||||
|
||||
uv_update_time(loop);
|
||||
diff = uv_now(loop) - start_time;
|
||||
|
||||
fprintf(stderr, "%s_pump%d_server: %.1f gbit/s\n",
|
||||
type == TCP ? "tcp" : "pipe",
|
||||
max_read_sockets,
|
||||
gbit(nrecv_total, diff));
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void read_sockets_close_cb(uv_handle_t* handle) {
|
||||
free(handle);
|
||||
read_sockets--;
|
||||
|
||||
/* If it's past the first second and everyone has closed their connection
|
||||
* Then print stats.
|
||||
*/
|
||||
if (uv_now(loop) - start_time > 1000 && read_sockets == 0) {
|
||||
read_show_stats();
|
||||
uv_close((uv_handle_t*)server, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void start_stats_collection(void) {
|
||||
int r;
|
||||
|
||||
/* Show-stats timer */
|
||||
stats_left = STATS_COUNT;
|
||||
r = uv_timer_init(loop, &timer_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&timer_handle, show_stats, STATS_INTERVAL, STATS_INTERVAL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_update_time(loop);
|
||||
start_time = uv_now(loop);
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* stream, ssize_t bytes, const uv_buf_t* buf) {
|
||||
if (nrecv_total == 0) {
|
||||
ASSERT(start_time == 0);
|
||||
uv_update_time(loop);
|
||||
start_time = uv_now(loop);
|
||||
}
|
||||
|
||||
if (bytes < 0) {
|
||||
uv_close((uv_handle_t*)stream, read_sockets_close_cb);
|
||||
return;
|
||||
}
|
||||
|
||||
buf_free(buf);
|
||||
|
||||
nrecv += bytes;
|
||||
nrecv_total += bytes;
|
||||
}
|
||||
|
||||
|
||||
static void write_cb(uv_write_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
|
||||
req_free((uv_req_t*) req);
|
||||
|
||||
nsent += sizeof write_buffer;
|
||||
nsent_total += sizeof write_buffer;
|
||||
|
||||
do_write((uv_stream_t*) req->handle);
|
||||
}
|
||||
|
||||
|
||||
static void do_write(uv_stream_t* stream) {
|
||||
uv_write_t* req;
|
||||
uv_buf_t buf;
|
||||
int r;
|
||||
|
||||
buf.base = (char*) &write_buffer;
|
||||
buf.len = sizeof write_buffer;
|
||||
|
||||
req = (uv_write_t*) req_alloc();
|
||||
r = uv_write(req, stream, &buf, 1, write_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
int i;
|
||||
|
||||
if (status) {
|
||||
fprintf(stderr, "%s", uv_strerror(status));
|
||||
fflush(stderr);
|
||||
}
|
||||
ASSERT(status == 0);
|
||||
|
||||
write_sockets++;
|
||||
req_free((uv_req_t*) req);
|
||||
|
||||
maybe_connect_some();
|
||||
|
||||
if (write_sockets == TARGET_CONNECTIONS) {
|
||||
start_stats_collection();
|
||||
|
||||
/* Yay! start writing */
|
||||
for (i = 0; i < write_sockets; i++) {
|
||||
if (type == TCP)
|
||||
do_write((uv_stream_t*) &tcp_write_handles[i]);
|
||||
else
|
||||
do_write((uv_stream_t*) &pipe_write_handles[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void maybe_connect_some(void) {
|
||||
uv_connect_t* req;
|
||||
uv_tcp_t* tcp;
|
||||
uv_pipe_t* pipe;
|
||||
int r;
|
||||
|
||||
while (max_connect_socket < TARGET_CONNECTIONS &&
|
||||
max_connect_socket < write_sockets + MAX_SIMULTANEOUS_CONNECTS) {
|
||||
if (type == TCP) {
|
||||
tcp = &tcp_write_handles[max_connect_socket++];
|
||||
|
||||
r = uv_tcp_init(loop, tcp);
|
||||
ASSERT(r == 0);
|
||||
|
||||
req = (uv_connect_t*) req_alloc();
|
||||
r = uv_tcp_connect(req,
|
||||
tcp,
|
||||
(const struct sockaddr*) &connect_addr,
|
||||
connect_cb);
|
||||
ASSERT(r == 0);
|
||||
} else {
|
||||
pipe = &pipe_write_handles[max_connect_socket++];
|
||||
|
||||
r = uv_pipe_init(loop, pipe, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
req = (uv_connect_t*) req_alloc();
|
||||
uv_pipe_connect(req, pipe, TEST_PIPENAME, connect_cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* s, int status) {
|
||||
uv_stream_t* stream;
|
||||
int r;
|
||||
|
||||
ASSERT(server == s);
|
||||
ASSERT(status == 0);
|
||||
|
||||
if (type == TCP) {
|
||||
stream = (uv_stream_t*)malloc(sizeof(uv_tcp_t));
|
||||
r = uv_tcp_init(loop, (uv_tcp_t*)stream);
|
||||
ASSERT(r == 0);
|
||||
} else {
|
||||
stream = (uv_stream_t*)malloc(sizeof(uv_pipe_t));
|
||||
r = uv_pipe_init(loop, (uv_pipe_t*)stream, 0);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
r = uv_accept(s, stream);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start(stream, buf_alloc, read_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
read_sockets++;
|
||||
max_read_sockets++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Request allocator
|
||||
*/
|
||||
|
||||
typedef struct req_list_s {
|
||||
union uv_any_req uv_req;
|
||||
struct req_list_s* next;
|
||||
} req_list_t;
|
||||
|
||||
|
||||
static req_list_t* req_freelist = NULL;
|
||||
|
||||
|
||||
static uv_req_t* req_alloc(void) {
|
||||
req_list_t* req;
|
||||
|
||||
req = req_freelist;
|
||||
if (req != NULL) {
|
||||
req_freelist = req->next;
|
||||
return (uv_req_t*) req;
|
||||
}
|
||||
|
||||
req = (req_list_t*) malloc(sizeof *req);
|
||||
return (uv_req_t*) req;
|
||||
}
|
||||
|
||||
|
||||
static void req_free(uv_req_t* uv_req) {
|
||||
req_list_t* req = (req_list_t*) uv_req;
|
||||
|
||||
req->next = req_freelist;
|
||||
req_freelist = req;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Buffer allocator
|
||||
*/
|
||||
|
||||
typedef struct buf_list_s {
|
||||
uv_buf_t uv_buf_t;
|
||||
struct buf_list_s* next;
|
||||
} buf_list_t;
|
||||
|
||||
|
||||
static buf_list_t* buf_freelist = NULL;
|
||||
|
||||
|
||||
static void buf_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
buf_list_t* ab;
|
||||
|
||||
ab = buf_freelist;
|
||||
if (ab != NULL)
|
||||
buf_freelist = ab->next;
|
||||
else {
|
||||
ab = malloc(size + sizeof(*ab));
|
||||
ab->uv_buf_t.len = size;
|
||||
ab->uv_buf_t.base = (char*) (ab + 1);
|
||||
}
|
||||
|
||||
*buf = ab->uv_buf_t;
|
||||
}
|
||||
|
||||
|
||||
static void buf_free(const uv_buf_t* buf) {
|
||||
buf_list_t* ab = (buf_list_t*) buf->base - 1;
|
||||
ab->next = buf_freelist;
|
||||
buf_freelist = ab;
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(tcp_pump_server) {
|
||||
int r;
|
||||
|
||||
type = TCP;
|
||||
loop = uv_default_loop();
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &listen_addr));
|
||||
|
||||
/* Server */
|
||||
server = (uv_stream_t*)&tcpServer;
|
||||
r = uv_tcp_init(loop, &tcpServer);
|
||||
ASSERT(r == 0);
|
||||
r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &listen_addr, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_listen((uv_stream_t*)&tcpServer, MAX_WRITE_HANDLES, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(pipe_pump_server) {
|
||||
int r;
|
||||
type = PIPE;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* Server */
|
||||
server = (uv_stream_t*)&pipeServer;
|
||||
r = uv_pipe_init(loop, &pipeServer, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_pipe_bind(&pipeServer, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
r = uv_listen((uv_stream_t*)&pipeServer, MAX_WRITE_HANDLES, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void tcp_pump(int n) {
|
||||
ASSERT(n <= MAX_WRITE_HANDLES);
|
||||
TARGET_CONNECTIONS = n;
|
||||
type = TCP;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &connect_addr));
|
||||
|
||||
/* Start making connections */
|
||||
maybe_connect_some();
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
}
|
||||
|
||||
|
||||
static void pipe_pump(int n) {
|
||||
ASSERT(n <= MAX_WRITE_HANDLES);
|
||||
TARGET_CONNECTIONS = n;
|
||||
type = PIPE;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* Start making connections */
|
||||
maybe_connect_some();
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp_pump100_client) {
|
||||
tcp_pump(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp_pump1_client) {
|
||||
tcp_pump(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(pipe_pump100_client) {
|
||||
pipe_pump(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(pipe_pump1_client) {
|
||||
pipe_pump(1);
|
||||
return 0;
|
||||
}
|
46
deps/libuv/test/benchmark-sizes.c
vendored
Normal file
46
deps/libuv/test/benchmark-sizes.c
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
|
||||
BENCHMARK_IMPL(sizes) {
|
||||
fprintf(stderr, "uv_shutdown_t: %u bytes\n", (unsigned int) sizeof(uv_shutdown_t));
|
||||
fprintf(stderr, "uv_write_t: %u bytes\n", (unsigned int) sizeof(uv_write_t));
|
||||
fprintf(stderr, "uv_connect_t: %u bytes\n", (unsigned int) sizeof(uv_connect_t));
|
||||
fprintf(stderr, "uv_udp_send_t: %u bytes\n", (unsigned int) sizeof(uv_udp_send_t));
|
||||
fprintf(stderr, "uv_tcp_t: %u bytes\n", (unsigned int) sizeof(uv_tcp_t));
|
||||
fprintf(stderr, "uv_pipe_t: %u bytes\n", (unsigned int) sizeof(uv_pipe_t));
|
||||
fprintf(stderr, "uv_tty_t: %u bytes\n", (unsigned int) sizeof(uv_tty_t));
|
||||
fprintf(stderr, "uv_prepare_t: %u bytes\n", (unsigned int) sizeof(uv_prepare_t));
|
||||
fprintf(stderr, "uv_check_t: %u bytes\n", (unsigned int) sizeof(uv_check_t));
|
||||
fprintf(stderr, "uv_idle_t: %u bytes\n", (unsigned int) sizeof(uv_idle_t));
|
||||
fprintf(stderr, "uv_async_t: %u bytes\n", (unsigned int) sizeof(uv_async_t));
|
||||
fprintf(stderr, "uv_timer_t: %u bytes\n", (unsigned int) sizeof(uv_timer_t));
|
||||
fprintf(stderr, "uv_fs_poll_t: %u bytes\n", (unsigned int) sizeof(uv_fs_poll_t));
|
||||
fprintf(stderr, "uv_fs_event_t: %u bytes\n", (unsigned int) sizeof(uv_fs_event_t));
|
||||
fprintf(stderr, "uv_process_t: %u bytes\n", (unsigned int) sizeof(uv_process_t));
|
||||
fprintf(stderr, "uv_poll_t: %u bytes\n", (unsigned int) sizeof(uv_poll_t));
|
||||
fprintf(stderr, "uv_loop_t: %u bytes\n", (unsigned int) sizeof(uv_loop_t));
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
}
|
164
deps/libuv/test/benchmark-spawn.c
vendored
Normal file
164
deps/libuv/test/benchmark-spawn.c
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* This benchmark spawns itself 1000 times. */
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static int N = 1000;
|
||||
static int done;
|
||||
|
||||
static uv_process_t process;
|
||||
static uv_process_options_t options;
|
||||
static char exepath[1024];
|
||||
static size_t exepath_size = 1024;
|
||||
static char* args[3];
|
||||
static uv_pipe_t out;
|
||||
|
||||
#define OUTPUT_SIZE 1024
|
||||
static char output[OUTPUT_SIZE];
|
||||
static int output_used;
|
||||
|
||||
static int process_open;
|
||||
static int pipe_open;
|
||||
|
||||
|
||||
static void spawn(void);
|
||||
|
||||
|
||||
static void maybe_spawn(void) {
|
||||
if (process_open == 0 && pipe_open == 0) {
|
||||
done++;
|
||||
if (done < N) {
|
||||
spawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void process_close_cb(uv_handle_t* handle) {
|
||||
ASSERT(process_open == 1);
|
||||
process_open = 0;
|
||||
maybe_spawn();
|
||||
}
|
||||
|
||||
|
||||
static void exit_cb(uv_process_t* process,
|
||||
int64_t exit_status,
|
||||
int term_signal) {
|
||||
ASSERT(exit_status == 42);
|
||||
ASSERT(term_signal == 0);
|
||||
uv_close((uv_handle_t*)process, process_close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void on_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
buf->base = output + output_used;
|
||||
buf->len = OUTPUT_SIZE - output_used;
|
||||
}
|
||||
|
||||
|
||||
static void pipe_close_cb(uv_handle_t* pipe) {
|
||||
ASSERT(pipe_open == 1);
|
||||
pipe_open = 0;
|
||||
maybe_spawn();
|
||||
}
|
||||
|
||||
|
||||
static void on_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* buf) {
|
||||
if (nread > 0) {
|
||||
ASSERT(pipe_open == 1);
|
||||
output_used += nread;
|
||||
} else if (nread < 0) {
|
||||
if (nread == UV_EOF) {
|
||||
uv_close((uv_handle_t*)pipe, pipe_close_cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void spawn(void) {
|
||||
uv_stdio_container_t stdio[2];
|
||||
int r;
|
||||
|
||||
ASSERT(process_open == 0);
|
||||
ASSERT(pipe_open == 0);
|
||||
|
||||
args[0] = exepath;
|
||||
args[1] = "spawn_helper";
|
||||
args[2] = NULL;
|
||||
options.file = exepath;
|
||||
options.args = args;
|
||||
options.exit_cb = exit_cb;
|
||||
|
||||
uv_pipe_init(loop, &out, 0);
|
||||
|
||||
options.stdio = stdio;
|
||||
options.stdio_count = 2;
|
||||
options.stdio[0].flags = UV_IGNORE;
|
||||
options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
|
||||
options.stdio[1].data.stream = (uv_stream_t*)&out;
|
||||
|
||||
r = uv_spawn(loop, &process, &options);
|
||||
ASSERT(r == 0);
|
||||
|
||||
process_open = 1;
|
||||
pipe_open = 1;
|
||||
output_used = 0;
|
||||
|
||||
r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(spawn) {
|
||||
int r;
|
||||
static int64_t start_time, end_time;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
r = uv_exepath(exepath, &exepath_size);
|
||||
ASSERT(r == 0);
|
||||
exepath[exepath_size] = '\0';
|
||||
|
||||
uv_update_time(loop);
|
||||
start_time = uv_now(loop);
|
||||
|
||||
spawn();
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_update_time(loop);
|
||||
end_time = uv_now(loop);
|
||||
|
||||
fprintf(stderr, "spawn: %.0f spawns/s\n",
|
||||
(double) N / (double) (end_time - start_time) * 1000.0);
|
||||
fflush(stderr);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
144
deps/libuv/test/benchmark-tcp-write-batch.c
vendored
Normal file
144
deps/libuv/test/benchmark-tcp-write-batch.c
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define WRITE_REQ_DATA "Hello, world."
|
||||
#define NUM_WRITE_REQS (1000 * 1000)
|
||||
|
||||
typedef struct {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
} write_req;
|
||||
|
||||
|
||||
static write_req* write_reqs;
|
||||
static uv_tcp_t tcp_client;
|
||||
static uv_connect_t connect_req;
|
||||
static uv_shutdown_t shutdown_req;
|
||||
|
||||
static int shutdown_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
static int write_cb_called = 0;
|
||||
static int close_cb_called = 0;
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status);
|
||||
static void write_cb(uv_write_t* req, int status);
|
||||
static void shutdown_cb(uv_shutdown_t* req, int status);
|
||||
static void close_cb(uv_handle_t* handle);
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
write_req* w;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
ASSERT(req->handle == (uv_stream_t*)&tcp_client);
|
||||
|
||||
for (i = 0; i < NUM_WRITE_REQS; i++) {
|
||||
w = &write_reqs[i];
|
||||
r = uv_write(&w->req, req->handle, &w->buf, 1, write_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void write_cb(uv_write_t* req, int status) {
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
write_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void shutdown_cb(uv_shutdown_t* req, int status) {
|
||||
ASSERT(req->handle == (uv_stream_t*)&tcp_client);
|
||||
ASSERT(req->handle->write_queue_size == 0);
|
||||
|
||||
uv_close((uv_handle_t*)req->handle, close_cb);
|
||||
free(write_reqs);
|
||||
|
||||
shutdown_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle == (uv_handle_t*)&tcp_client);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(tcp_write_batch) {
|
||||
struct sockaddr_in addr;
|
||||
uv_loop_t* loop;
|
||||
uint64_t start;
|
||||
uint64_t stop;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
write_reqs = malloc(sizeof(*write_reqs) * NUM_WRITE_REQS);
|
||||
ASSERT(write_reqs != NULL);
|
||||
|
||||
/* Prepare the data to write out. */
|
||||
for (i = 0; i < NUM_WRITE_REQS; i++) {
|
||||
write_reqs[i].buf = uv_buf_init(WRITE_REQ_DATA,
|
||||
sizeof(WRITE_REQ_DATA) - 1);
|
||||
}
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(loop, &tcp_client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_connect(&connect_req,
|
||||
&tcp_client,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
start = uv_hrtime();
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
stop = uv_hrtime();
|
||||
|
||||
ASSERT(connect_cb_called == 1);
|
||||
ASSERT(write_cb_called == NUM_WRITE_REQS);
|
||||
ASSERT(shutdown_cb_called == 1);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
printf("%ld write requests in %.2fs.\n",
|
||||
(long)NUM_WRITE_REQS,
|
||||
(stop - start) / 1e9);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
64
deps/libuv/test/benchmark-thread.c
vendored
Normal file
64
deps/libuv/test/benchmark-thread.c
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NUM_THREADS (20 * 1000)
|
||||
|
||||
static volatile int num_threads;
|
||||
|
||||
|
||||
static void thread_entry(void* arg) {
|
||||
ASSERT(arg == (void *) 42);
|
||||
num_threads++;
|
||||
/* FIXME write barrier? */
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(thread_create) {
|
||||
uint64_t start_time;
|
||||
double duration;
|
||||
uv_thread_t tid;
|
||||
int i, r;
|
||||
|
||||
start_time = uv_hrtime();
|
||||
|
||||
for (i = 0; i < NUM_THREADS; i++) {
|
||||
r = uv_thread_create(&tid, thread_entry, (void *) 42);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_thread_join(&tid);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
duration = (uv_hrtime() - start_time) / 1e9;
|
||||
|
||||
ASSERT(num_threads == NUM_THREADS);
|
||||
|
||||
printf("%d threads created in %.2f seconds (%.0f/s)\n",
|
||||
NUM_THREADS, duration, NUM_THREADS / duration);
|
||||
|
||||
return 0;
|
||||
}
|
243
deps/libuv/test/benchmark-udp-pummel.c
vendored
Normal file
243
deps/libuv/test/benchmark-udp-pummel.c
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN"
|
||||
|
||||
#define TEST_DURATION 5000 /* ms */
|
||||
|
||||
#define BASE_PORT 12345
|
||||
|
||||
struct sender_state {
|
||||
struct sockaddr_in addr;
|
||||
uv_udp_send_t send_req;
|
||||
uv_udp_t udp_handle;
|
||||
};
|
||||
|
||||
struct receiver_state {
|
||||
struct sockaddr_in addr;
|
||||
uv_udp_t udp_handle;
|
||||
};
|
||||
|
||||
/* not used in timed mode */
|
||||
static unsigned int packet_counter = (unsigned int) 1e6;
|
||||
|
||||
static int n_senders_;
|
||||
static int n_receivers_;
|
||||
static uv_buf_t bufs[5];
|
||||
static struct sender_state senders[1024];
|
||||
static struct receiver_state receivers[1024];
|
||||
|
||||
static unsigned int send_cb_called;
|
||||
static unsigned int recv_cb_called;
|
||||
static unsigned int close_cb_called;
|
||||
static int timed;
|
||||
static int exiting;
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
static char slab[65536];
|
||||
ASSERT(suggested_size <= sizeof(slab));
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void send_cb(uv_udp_send_t* req, int status) {
|
||||
struct sender_state* s;
|
||||
|
||||
ASSERT(req != NULL);
|
||||
|
||||
if (status != 0) {
|
||||
ASSERT(status == UV_ECANCELED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (exiting)
|
||||
return;
|
||||
|
||||
s = container_of(req, struct sender_state, send_req);
|
||||
ASSERT(req->handle == &s->udp_handle);
|
||||
|
||||
if (timed)
|
||||
goto send;
|
||||
|
||||
if (packet_counter == 0) {
|
||||
uv_close((uv_handle_t*)&s->udp_handle, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
packet_counter--;
|
||||
|
||||
send:
|
||||
ASSERT(0 == uv_udp_send(&s->send_req,
|
||||
&s->udp_handle,
|
||||
bufs,
|
||||
ARRAY_SIZE(bufs),
|
||||
(const struct sockaddr*) &s->addr,
|
||||
send_cb));
|
||||
send_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void recv_cb(uv_udp_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf,
|
||||
const struct sockaddr* addr,
|
||||
unsigned flags) {
|
||||
if (nread == 0)
|
||||
return;
|
||||
|
||||
if (nread < 0) {
|
||||
ASSERT(nread == UV_ECANCELED);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(addr->sa_family == AF_INET);
|
||||
ASSERT(!memcmp(buf->base, EXPECTED, nread));
|
||||
|
||||
recv_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void timeout_cb(uv_timer_t* timer) {
|
||||
int i;
|
||||
|
||||
exiting = 1;
|
||||
|
||||
for (i = 0; i < n_senders_; i++)
|
||||
uv_close((uv_handle_t*)&senders[i].udp_handle, close_cb);
|
||||
|
||||
for (i = 0; i < n_receivers_; i++)
|
||||
uv_close((uv_handle_t*)&receivers[i].udp_handle, close_cb);
|
||||
}
|
||||
|
||||
|
||||
static int pummel(unsigned int n_senders,
|
||||
unsigned int n_receivers,
|
||||
unsigned long timeout) {
|
||||
uv_timer_t timer_handle;
|
||||
uint64_t duration;
|
||||
uv_loop_t* loop;
|
||||
unsigned int i;
|
||||
|
||||
ASSERT(n_senders <= ARRAY_SIZE(senders));
|
||||
ASSERT(n_receivers <= ARRAY_SIZE(receivers));
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
n_senders_ = n_senders;
|
||||
n_receivers_ = n_receivers;
|
||||
|
||||
if (timeout) {
|
||||
ASSERT(0 == uv_timer_init(loop, &timer_handle));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timeout_cb, timeout, 0));
|
||||
/* Timer should not keep loop alive. */
|
||||
uv_unref((uv_handle_t*)&timer_handle);
|
||||
timed = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_receivers; i++) {
|
||||
struct receiver_state* s = receivers + i;
|
||||
struct sockaddr_in addr;
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", BASE_PORT + i, &addr));
|
||||
ASSERT(0 == uv_udp_init(loop, &s->udp_handle));
|
||||
ASSERT(0 == uv_udp_bind(&s->udp_handle, (const struct sockaddr*) &addr, 0));
|
||||
ASSERT(0 == uv_udp_recv_start(&s->udp_handle, alloc_cb, recv_cb));
|
||||
uv_unref((uv_handle_t*)&s->udp_handle);
|
||||
}
|
||||
|
||||
bufs[0] = uv_buf_init(EXPECTED + 0, 10);
|
||||
bufs[1] = uv_buf_init(EXPECTED + 10, 10);
|
||||
bufs[2] = uv_buf_init(EXPECTED + 20, 10);
|
||||
bufs[3] = uv_buf_init(EXPECTED + 30, 10);
|
||||
bufs[4] = uv_buf_init(EXPECTED + 40, 5);
|
||||
|
||||
for (i = 0; i < n_senders; i++) {
|
||||
struct sender_state* s = senders + i;
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1",
|
||||
BASE_PORT + (i % n_receivers),
|
||||
&s->addr));
|
||||
ASSERT(0 == uv_udp_init(loop, &s->udp_handle));
|
||||
ASSERT(0 == uv_udp_send(&s->send_req,
|
||||
&s->udp_handle,
|
||||
bufs,
|
||||
ARRAY_SIZE(bufs),
|
||||
(const struct sockaddr*) &s->addr,
|
||||
send_cb));
|
||||
}
|
||||
|
||||
duration = uv_hrtime();
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
duration = uv_hrtime() - duration;
|
||||
/* convert from nanoseconds to milliseconds */
|
||||
duration = duration / (uint64_t) 1e6;
|
||||
|
||||
printf("udp_pummel_%dv%d: %.0f/s received, %.0f/s sent. "
|
||||
"%u received, %u sent in %.1f seconds.\n",
|
||||
n_receivers,
|
||||
n_senders,
|
||||
recv_cb_called / (duration / 1000.0),
|
||||
send_cb_called / (duration / 1000.0),
|
||||
recv_cb_called,
|
||||
send_cb_called,
|
||||
duration / 1000.0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define X(a, b) \
|
||||
BENCHMARK_IMPL(udp_pummel_##a##v##b) { \
|
||||
return pummel(a, b, 0); \
|
||||
} \
|
||||
BENCHMARK_IMPL(udp_timed_pummel_##a##v##b) { \
|
||||
return pummel(a, b, TEST_DURATION); \
|
||||
}
|
||||
|
||||
X(1, 1)
|
||||
X(1, 10)
|
||||
X(1, 100)
|
||||
X(1, 1000)
|
||||
X(10, 10)
|
||||
X(10, 100)
|
||||
X(10, 1000)
|
||||
X(100, 10)
|
||||
X(100, 100)
|
||||
X(100, 1000)
|
||||
X(1000, 1000)
|
||||
|
||||
#undef X
|
121
deps/libuv/test/blackhole-server.c
vendored
Normal file
121
deps/libuv/test/blackhole-server.c
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
uv_tcp_t handle;
|
||||
uv_shutdown_t shutdown_req;
|
||||
} conn_rec;
|
||||
|
||||
static uv_tcp_t tcp_server;
|
||||
|
||||
static void connection_cb(uv_stream_t* stream, int status);
|
||||
static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
||||
static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
||||
static void shutdown_cb(uv_shutdown_t* req, int status);
|
||||
static void close_cb(uv_handle_t* handle);
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* stream, int status) {
|
||||
conn_rec* conn;
|
||||
int r;
|
||||
|
||||
ASSERT(status == 0);
|
||||
ASSERT(stream == (uv_stream_t*)&tcp_server);
|
||||
|
||||
conn = malloc(sizeof *conn);
|
||||
ASSERT(conn != NULL);
|
||||
|
||||
r = uv_tcp_init(stream->loop, &conn->handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_accept(stream, (uv_stream_t*)&conn->handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*)&conn->handle, alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
static char slab[65536];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
||||
conn_rec* conn;
|
||||
int r;
|
||||
|
||||
if (nread >= 0)
|
||||
return;
|
||||
|
||||
ASSERT(nread == UV_EOF);
|
||||
|
||||
conn = container_of(stream, conn_rec, handle);
|
||||
|
||||
r = uv_shutdown(&conn->shutdown_req, stream, shutdown_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void shutdown_cb(uv_shutdown_t* req, int status) {
|
||||
conn_rec* conn = container_of(req, conn_rec, shutdown_req);
|
||||
uv_close((uv_handle_t*)&conn->handle, close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
conn_rec* conn = container_of(handle, conn_rec, handle);
|
||||
free(conn);
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(tcp4_blackhole_server) {
|
||||
struct sockaddr_in addr;
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(loop, &tcp_server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(0 && "Blackhole server dropped out of event loop.");
|
||||
|
||||
return 0;
|
||||
}
|
340
deps/libuv/test/dns-server.c
vendored
Normal file
340
deps/libuv/test/dns-server.c
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
} write_req_t;
|
||||
|
||||
|
||||
/* used to track multiple DNS requests received */
|
||||
typedef struct {
|
||||
char* prevbuf_ptr;
|
||||
int prevbuf_pos;
|
||||
int prevbuf_rem;
|
||||
} dnsstate;
|
||||
|
||||
|
||||
/* modify handle to append dnsstate */
|
||||
typedef struct {
|
||||
uv_tcp_t handle;
|
||||
dnsstate state;
|
||||
} dnshandle;
|
||||
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
|
||||
static uv_tcp_t server;
|
||||
|
||||
|
||||
static void after_write(uv_write_t* req, int status);
|
||||
static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf);
|
||||
static void on_close(uv_handle_t* peer);
|
||||
static void on_connection(uv_stream_t*, int status);
|
||||
|
||||
#define WRITE_BUF_LEN (64*1024)
|
||||
#define DNSREC_LEN (4)
|
||||
|
||||
#define LEN_OFFSET 0
|
||||
#define QUERYID_OFFSET 2
|
||||
|
||||
static unsigned char DNSRsp[] = {
|
||||
0, 43, 0, 0, 0x81, 0x80, 0, 1, 0, 1, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static unsigned char qrecord[] = {
|
||||
5, 'e', 'c', 'h', 'o', 's', 3, 's', 'r', 'v', 0, 0, 1, 0, 1
|
||||
};
|
||||
|
||||
static unsigned char arecord[] = {
|
||||
0xc0, 0x0c, 0, 1, 0, 1, 0, 0, 5, 0xbd, 0, 4, 10, 0, 1, 1
|
||||
};
|
||||
|
||||
|
||||
static void after_write(uv_write_t* req, int status) {
|
||||
write_req_t* wr;
|
||||
|
||||
if (status) {
|
||||
fprintf(stderr, "uv_write error: %s\n", uv_strerror(status));
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
wr = (write_req_t*) req;
|
||||
|
||||
/* Free the read/write buffer and the request */
|
||||
free(wr->buf.base);
|
||||
free(wr);
|
||||
}
|
||||
|
||||
|
||||
static void after_shutdown(uv_shutdown_t* req, int status) {
|
||||
uv_close((uv_handle_t*) req->handle, on_close);
|
||||
free(req);
|
||||
}
|
||||
|
||||
|
||||
static void addrsp(write_req_t* wr, char* hdr) {
|
||||
char * dnsrsp;
|
||||
short int rsplen;
|
||||
short int* reclen;
|
||||
|
||||
rsplen = sizeof(DNSRsp) + sizeof(qrecord) + sizeof(arecord);
|
||||
|
||||
ASSERT (rsplen + wr->buf.len < WRITE_BUF_LEN);
|
||||
|
||||
dnsrsp = wr->buf.base + wr->buf.len;
|
||||
|
||||
/* copy stock response */
|
||||
memcpy(dnsrsp, DNSRsp, sizeof(DNSRsp));
|
||||
memcpy(dnsrsp + sizeof(DNSRsp), qrecord, sizeof(qrecord));
|
||||
memcpy(dnsrsp + sizeof(DNSRsp) + sizeof(qrecord), arecord, sizeof(arecord));
|
||||
|
||||
/* overwrite with network order length and id from request header */
|
||||
reclen = (short int*)dnsrsp;
|
||||
*reclen = htons(rsplen-2);
|
||||
dnsrsp[QUERYID_OFFSET] = hdr[QUERYID_OFFSET];
|
||||
dnsrsp[QUERYID_OFFSET+1] = hdr[QUERYID_OFFSET+1];
|
||||
|
||||
wr->buf.len += rsplen;
|
||||
}
|
||||
|
||||
static void process_req(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
write_req_t* wr;
|
||||
dnshandle* dns = (dnshandle*)handle;
|
||||
char hdrbuf[DNSREC_LEN];
|
||||
int hdrbuf_remaining = DNSREC_LEN;
|
||||
int rec_remaining = 0;
|
||||
int readbuf_remaining;
|
||||
char* dnsreq;
|
||||
char* hdrstart;
|
||||
int usingprev = 0;
|
||||
|
||||
wr = (write_req_t*) malloc(sizeof *wr);
|
||||
wr->buf.base = (char*)malloc(WRITE_BUF_LEN);
|
||||
wr->buf.len = 0;
|
||||
|
||||
if (dns->state.prevbuf_ptr != NULL) {
|
||||
dnsreq = dns->state.prevbuf_ptr + dns->state.prevbuf_pos;
|
||||
readbuf_remaining = dns->state.prevbuf_rem;
|
||||
usingprev = 1;
|
||||
} else {
|
||||
dnsreq = buf->base;
|
||||
readbuf_remaining = nread;
|
||||
}
|
||||
hdrstart = dnsreq;
|
||||
|
||||
while (dnsreq != NULL) {
|
||||
/* something to process */
|
||||
while (readbuf_remaining > 0) {
|
||||
/* something to process in current buffer */
|
||||
if (hdrbuf_remaining > 0) {
|
||||
/* process len and id */
|
||||
if (readbuf_remaining < hdrbuf_remaining) {
|
||||
/* too little to get request header. save for next buffer */
|
||||
memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining],
|
||||
dnsreq,
|
||||
readbuf_remaining);
|
||||
hdrbuf_remaining = DNSREC_LEN - readbuf_remaining;
|
||||
break;
|
||||
} else {
|
||||
/* save header */
|
||||
memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining],
|
||||
dnsreq,
|
||||
hdrbuf_remaining);
|
||||
dnsreq += hdrbuf_remaining;
|
||||
readbuf_remaining -= hdrbuf_remaining;
|
||||
hdrbuf_remaining = 0;
|
||||
|
||||
/* get record length */
|
||||
rec_remaining = (unsigned) hdrbuf[0] * 256 + (unsigned) hdrbuf[1];
|
||||
rec_remaining -= (DNSREC_LEN - 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (rec_remaining <= readbuf_remaining) {
|
||||
/* prepare reply */
|
||||
addrsp(wr, hdrbuf);
|
||||
|
||||
/* move to next record */
|
||||
dnsreq += rec_remaining;
|
||||
hdrstart = dnsreq;
|
||||
readbuf_remaining -= rec_remaining;
|
||||
rec_remaining = 0;
|
||||
hdrbuf_remaining = DNSREC_LEN;
|
||||
} else {
|
||||
/* otherwise this buffer is done. */
|
||||
rec_remaining -= readbuf_remaining;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we had to use bytes from prev buffer, start processing the current
|
||||
* one.
|
||||
*/
|
||||
if (usingprev == 1) {
|
||||
/* free previous buffer */
|
||||
free(dns->state.prevbuf_ptr);
|
||||
dnsreq = buf->base;
|
||||
readbuf_remaining = nread;
|
||||
usingprev = 0;
|
||||
} else {
|
||||
dnsreq = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* send write buffer */
|
||||
if (wr->buf.len > 0) {
|
||||
if (uv_write((uv_write_t*) &wr->req, handle, &wr->buf, 1, after_write)) {
|
||||
FATAL("uv_write failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (readbuf_remaining > 0) {
|
||||
/* save start of record position, so we can continue on next read */
|
||||
dns->state.prevbuf_ptr = buf->base;
|
||||
dns->state.prevbuf_pos = hdrstart - buf->base;
|
||||
dns->state.prevbuf_rem = nread - dns->state.prevbuf_pos;
|
||||
} else {
|
||||
/* nothing left in this buffer */
|
||||
dns->state.prevbuf_ptr = NULL;
|
||||
dns->state.prevbuf_pos = 0;
|
||||
dns->state.prevbuf_rem = 0;
|
||||
free(buf->base);
|
||||
}
|
||||
}
|
||||
|
||||
static void after_read(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
uv_shutdown_t* req;
|
||||
|
||||
if (nread < 0) {
|
||||
/* Error or EOF */
|
||||
ASSERT(nread == UV_EOF);
|
||||
|
||||
if (buf->base) {
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
req = malloc(sizeof *req);
|
||||
uv_shutdown(req, handle, after_shutdown);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread == 0) {
|
||||
/* Everything OK, but nothing read. */
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
/* process requests and send responses */
|
||||
process_req(handle, nread, buf);
|
||||
}
|
||||
|
||||
|
||||
static void on_close(uv_handle_t* peer) {
|
||||
free(peer);
|
||||
}
|
||||
|
||||
|
||||
static void buf_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status) {
|
||||
dnshandle* handle;
|
||||
int r;
|
||||
|
||||
ASSERT(status == 0);
|
||||
|
||||
handle = (dnshandle*) malloc(sizeof *handle);
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
/* initialize read buffer state */
|
||||
handle->state.prevbuf_ptr = 0;
|
||||
handle->state.prevbuf_pos = 0;
|
||||
handle->state.prevbuf_rem = 0;
|
||||
|
||||
r = uv_tcp_init(loop, (uv_tcp_t*)handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*)handle, buf_alloc, after_read);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static int dns_start(int port) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", port, &addr));
|
||||
|
||||
r = uv_tcp_init(loop, &server);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Socket creation error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Bind error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, 128, on_connection);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Listen error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(dns_server) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
if (dns_start(TEST_PORT_2))
|
||||
return 1;
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
return 0;
|
||||
}
|
407
deps/libuv/test/echo-server.c
vendored
Normal file
407
deps/libuv/test/echo-server.c
vendored
Normal file
@ -0,0 +1,407 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
} write_req_t;
|
||||
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static int server_closed;
|
||||
static stream_type serverType;
|
||||
static uv_tcp_t tcpServer;
|
||||
static uv_udp_t udpServer;
|
||||
static uv_pipe_t pipeServer;
|
||||
static uv_handle_t* server;
|
||||
static uv_udp_send_t* send_freelist;
|
||||
|
||||
static void after_write(uv_write_t* req, int status);
|
||||
static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf);
|
||||
static void on_close(uv_handle_t* peer);
|
||||
static void on_server_close(uv_handle_t* handle);
|
||||
static void on_connection(uv_stream_t*, int status);
|
||||
|
||||
|
||||
static void after_write(uv_write_t* req, int status) {
|
||||
write_req_t* wr;
|
||||
|
||||
/* Free the read/write buffer and the request */
|
||||
wr = (write_req_t*) req;
|
||||
free(wr->buf.base);
|
||||
free(wr);
|
||||
|
||||
if (status == 0)
|
||||
return;
|
||||
|
||||
fprintf(stderr,
|
||||
"uv_write error: %s - %s\n",
|
||||
uv_err_name(status),
|
||||
uv_strerror(status));
|
||||
}
|
||||
|
||||
|
||||
static void after_shutdown(uv_shutdown_t* req, int status) {
|
||||
uv_close((uv_handle_t*) req->handle, on_close);
|
||||
free(req);
|
||||
}
|
||||
|
||||
|
||||
static void after_read(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
int i;
|
||||
write_req_t *wr;
|
||||
uv_shutdown_t* sreq;
|
||||
|
||||
if (nread < 0) {
|
||||
/* Error or EOF */
|
||||
ASSERT(nread == UV_EOF);
|
||||
|
||||
free(buf->base);
|
||||
sreq = malloc(sizeof* sreq);
|
||||
ASSERT(0 == uv_shutdown(sreq, handle, after_shutdown));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread == 0) {
|
||||
/* Everything OK, but nothing read. */
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan for the letter Q which signals that we should quit the server.
|
||||
* If we get QS it means close the stream.
|
||||
*/
|
||||
if (!server_closed) {
|
||||
for (i = 0; i < nread; i++) {
|
||||
if (buf->base[i] == 'Q') {
|
||||
if (i + 1 < nread && buf->base[i + 1] == 'S') {
|
||||
free(buf->base);
|
||||
uv_close((uv_handle_t*)handle, on_close);
|
||||
return;
|
||||
} else {
|
||||
uv_close(server, on_server_close);
|
||||
server_closed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wr = (write_req_t*) malloc(sizeof *wr);
|
||||
ASSERT(wr != NULL);
|
||||
wr->buf = uv_buf_init(buf->base, nread);
|
||||
|
||||
if (uv_write(&wr->req, handle, &wr->buf, 1, after_write)) {
|
||||
FATAL("uv_write failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_close(uv_handle_t* peer) {
|
||||
free(peer);
|
||||
}
|
||||
|
||||
|
||||
static void echo_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
static void slab_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
/* up to 16 datagrams at once */
|
||||
static char slab[16 * 64 * 1024];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status) {
|
||||
uv_stream_t* stream;
|
||||
int r;
|
||||
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "Connect error %s\n", uv_err_name(status));
|
||||
}
|
||||
ASSERT(status == 0);
|
||||
|
||||
switch (serverType) {
|
||||
case TCP:
|
||||
stream = malloc(sizeof(uv_tcp_t));
|
||||
ASSERT(stream != NULL);
|
||||
r = uv_tcp_init(loop, (uv_tcp_t*)stream);
|
||||
ASSERT(r == 0);
|
||||
break;
|
||||
|
||||
case PIPE:
|
||||
stream = malloc(sizeof(uv_pipe_t));
|
||||
ASSERT(stream != NULL);
|
||||
r = uv_pipe_init(loop, (uv_pipe_t*)stream, 0);
|
||||
ASSERT(r == 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(0 && "Bad serverType");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* associate server with stream */
|
||||
stream->data = server;
|
||||
|
||||
r = uv_accept(server, stream);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start(stream, echo_alloc, after_read);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void on_server_close(uv_handle_t* handle) {
|
||||
ASSERT(handle == server);
|
||||
}
|
||||
|
||||
static uv_udp_send_t* send_alloc(void) {
|
||||
uv_udp_send_t* req = send_freelist;
|
||||
if (req != NULL)
|
||||
send_freelist = req->data;
|
||||
else
|
||||
req = malloc(sizeof(*req));
|
||||
return req;
|
||||
}
|
||||
|
||||
static void on_send(uv_udp_send_t* req, int status) {
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
req->data = send_freelist;
|
||||
send_freelist = req;
|
||||
}
|
||||
|
||||
static void on_recv(uv_udp_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* rcvbuf,
|
||||
const struct sockaddr* addr,
|
||||
unsigned flags) {
|
||||
uv_buf_t sndbuf;
|
||||
|
||||
if (nread == 0) {
|
||||
/* Everything OK, but nothing read. */
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(nread > 0);
|
||||
ASSERT(addr->sa_family == AF_INET);
|
||||
|
||||
uv_udp_send_t* req = send_alloc();
|
||||
ASSERT(req != NULL);
|
||||
sndbuf = uv_buf_init(rcvbuf->base, nread);
|
||||
ASSERT(0 <= uv_udp_send(req, handle, &sndbuf, 1, addr, on_send));
|
||||
}
|
||||
|
||||
static int tcp4_echo_start(int port) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", port, &addr));
|
||||
|
||||
server = (uv_handle_t*)&tcpServer;
|
||||
serverType = TCP;
|
||||
|
||||
r = uv_tcp_init(loop, &tcpServer);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Socket creation error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &addr, 0);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Bind error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcpServer, SOMAXCONN, on_connection);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int tcp6_echo_start(int port) {
|
||||
struct sockaddr_in6 addr6;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip6_addr("::1", port, &addr6));
|
||||
|
||||
server = (uv_handle_t*)&tcpServer;
|
||||
serverType = TCP;
|
||||
|
||||
r = uv_tcp_init(loop, &tcpServer);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Socket creation error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* IPv6 is optional as not all platforms support it */
|
||||
r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &addr6, 0);
|
||||
if (r) {
|
||||
/* show message but return OK */
|
||||
fprintf(stderr, "IPv6 not supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcpServer, SOMAXCONN, on_connection);
|
||||
if (r) {
|
||||
/* TODO: Error codes */
|
||||
fprintf(stderr, "Listen error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int udp4_echo_start(int port) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", port, &addr));
|
||||
server = (uv_handle_t*)&udpServer;
|
||||
serverType = UDP;
|
||||
|
||||
r = uv_udp_init(loop, &udpServer);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_udp_init: %s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_udp_bind(&udpServer, (const struct sockaddr*) &addr, 0);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_udp_bind: %s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_udp_recv_start(&udpServer, slab_alloc, on_recv);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_udp_recv_start: %s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int pipe_echo_start(char* pipeName) {
|
||||
int r;
|
||||
|
||||
#ifndef _WIN32
|
||||
{
|
||||
uv_fs_t req;
|
||||
uv_fs_unlink(NULL, &req, pipeName, NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
#endif
|
||||
|
||||
server = (uv_handle_t*)&pipeServer;
|
||||
serverType = PIPE;
|
||||
|
||||
r = uv_pipe_init(loop, &pipeServer, 0);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_pipe_init: %s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_pipe_bind(&pipeServer, pipeName);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_pipe_bind: %s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_listen((uv_stream_t*)&pipeServer, SOMAXCONN, on_connection);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_pipe_listen: %s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(tcp4_echo_server) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
if (tcp4_echo_start(TEST_PORT))
|
||||
return 1;
|
||||
|
||||
notify_parent_process();
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(tcp6_echo_server) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
if (tcp6_echo_start(TEST_PORT))
|
||||
return 1;
|
||||
|
||||
notify_parent_process();
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(pipe_echo_server) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
if (pipe_echo_start(TEST_PIPENAME))
|
||||
return 1;
|
||||
|
||||
notify_parent_process();
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HELPER_IMPL(udp4_echo_server) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
if (udp4_echo_start(TEST_PORT))
|
||||
return 1;
|
||||
|
||||
notify_parent_process();
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
return 0;
|
||||
}
|
0
deps/libuv/test/fixtures/empty_file
vendored
Normal file
0
deps/libuv/test/fixtures/empty_file
vendored
Normal file
1
deps/libuv/test/fixtures/load_error.node
vendored
Normal file
1
deps/libuv/test/fixtures/load_error.node
vendored
Normal file
@ -0,0 +1 @@
|
||||
foobar
|
1
deps/libuv/test/fixtures/lorem_ipsum.txt
vendored
Normal file
1
deps/libuv/test/fixtures/lorem_ipsum.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
64
deps/libuv/test/run-benchmarks.c
vendored
Normal file
64
deps/libuv/test/run-benchmarks.c
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "runner.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Actual benchmarks and helpers are defined in benchmark-list.h */
|
||||
#include "benchmark-list.h"
|
||||
|
||||
|
||||
static int maybe_run_test(int argc, char **argv);
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
platform_init(argc, argv);
|
||||
|
||||
switch (argc) {
|
||||
case 1: return run_tests(1);
|
||||
case 2: return maybe_run_test(argc, argv);
|
||||
case 3: return run_test_part(argv[1], argv[2]);
|
||||
default:
|
||||
fprintf(stderr, "Too many arguments.\n");
|
||||
fflush(stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int maybe_run_test(int argc, char **argv) {
|
||||
if (strcmp(argv[1], "--list") == 0) {
|
||||
print_tests(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper") == 0) {
|
||||
printf("hello world\n");
|
||||
return 42;
|
||||
}
|
||||
|
||||
return run_test(argv[1], 1, 1);
|
||||
}
|
248
deps/libuv/test/run-tests.c
vendored
Normal file
248
deps/libuv/test/run-tests.c
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "uv.h"
|
||||
#include "runner.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Actual tests and helpers are defined in test-list.h */
|
||||
#include "test-list.h"
|
||||
|
||||
int ipc_helper(int listen_after_write);
|
||||
int ipc_helper_heavy_traffic_deadlock_bug(void);
|
||||
int ipc_helper_tcp_connection(void);
|
||||
int ipc_helper_closed_handle(void);
|
||||
int ipc_send_recv_helper(void);
|
||||
int ipc_helper_bind_twice(void);
|
||||
int ipc_helper_send_zero(void);
|
||||
int stdio_over_pipes_helper(void);
|
||||
void spawn_stdin_stdout(void);
|
||||
void process_title_big_argv(void);
|
||||
int spawn_tcp_server_helper(void);
|
||||
|
||||
static int maybe_run_test(int argc, char **argv);
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#ifndef _WIN32
|
||||
if (0 == geteuid() && NULL == getenv("UV_RUN_AS_ROOT")) {
|
||||
fprintf(stderr, "The libuv test suite cannot be run as root.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
platform_init(argc, argv);
|
||||
argv = uv_setup_args(argc, argv);
|
||||
|
||||
switch (argc) {
|
||||
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);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#ifndef __SUNPRO_C
|
||||
return EXIT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int maybe_run_test(int argc, char **argv) {
|
||||
if (strcmp(argv[1], "--list") == 0) {
|
||||
print_tests(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
|
||||
return ipc_helper(0);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
|
||||
return ipc_helper(1);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) {
|
||||
return ipc_helper_heavy_traffic_deadlock_bug();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
|
||||
return ipc_send_recv_helper();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) {
|
||||
return ipc_helper_tcp_connection();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_closed_handle") == 0) {
|
||||
return ipc_helper_closed_handle();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) {
|
||||
return ipc_helper_bind_twice();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_send_zero") == 0) {
|
||||
return ipc_helper_send_zero();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
|
||||
return stdio_over_pipes_helper();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper1") == 0) {
|
||||
notify_parent_process();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper2") == 0) {
|
||||
notify_parent_process();
|
||||
printf("hello world\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_tcp_server_helper") == 0) {
|
||||
notify_parent_process();
|
||||
return spawn_tcp_server_helper();
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper3") == 0) {
|
||||
char buffer[256];
|
||||
notify_parent_process();
|
||||
ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin));
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
fputs(buffer, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper4") == 0) {
|
||||
notify_parent_process();
|
||||
/* Never surrender, never return! */
|
||||
while (1) uv_sleep(10000);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper5") == 0) {
|
||||
const char out[] = "fourth stdio!\n";
|
||||
notify_parent_process();
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD bytes;
|
||||
WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL);
|
||||
#else
|
||||
ssize_t r;
|
||||
|
||||
do
|
||||
r = write(3, out, sizeof(out) - 1);
|
||||
while (r == -1 && errno == EINTR);
|
||||
|
||||
fsync(3);
|
||||
#endif
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper6") == 0) {
|
||||
int r;
|
||||
|
||||
notify_parent_process();
|
||||
|
||||
r = fprintf(stdout, "hello world\n");
|
||||
ASSERT(r > 0);
|
||||
|
||||
r = fprintf(stderr, "hello errworld\n");
|
||||
ASSERT(r > 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper7") == 0) {
|
||||
int r;
|
||||
char *test;
|
||||
|
||||
notify_parent_process();
|
||||
|
||||
/* Test if the test value from the parent is still set */
|
||||
test = getenv("ENV_TEST");
|
||||
ASSERT(test != NULL);
|
||||
|
||||
r = fprintf(stdout, "%s", test);
|
||||
ASSERT(r > 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (strcmp(argv[1], "spawn_helper8") == 0) {
|
||||
int fd;
|
||||
|
||||
notify_parent_process();
|
||||
ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd)));
|
||||
ASSERT(fd > 2);
|
||||
# if defined(__PASE__) /* On IBMi PASE, write() returns 1 */
|
||||
ASSERT(1 == write(fd, "x", 1));
|
||||
# else
|
||||
ASSERT(-1 == write(fd, "x", 1));
|
||||
# endif /* !__PASE__ */
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper9") == 0) {
|
||||
notify_parent_process();
|
||||
spawn_stdin_stdout();
|
||||
return 1;
|
||||
}
|
||||
|
||||
#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());
|
||||
notify_parent_process();
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
if (strcmp(argv[1], "process_title_big_argv_helper") == 0) {
|
||||
notify_parent_process();
|
||||
process_title_big_argv();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return run_test(argv[1], 0, 1);
|
||||
}
|
445
deps/libuv/test/runner-unix.c
vendored
Normal file
445
deps/libuv/test/runner-unix.c
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runner-unix.h"
|
||||
#include "runner.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h> /* uintptr_t */
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h> /* usleep */
|
||||
#include <string.h> /* strdup */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
extern char** environ;
|
||||
|
||||
static void closefd(int fd) {
|
||||
if (close(fd) == 0 || errno == EINTR || errno == EINPROGRESS)
|
||||
return;
|
||||
|
||||
perror("close");
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
void notify_parent_process(void) {
|
||||
char* arg;
|
||||
int fd;
|
||||
|
||||
arg = getenv("UV_TEST_RUNNER_FD");
|
||||
if (arg == NULL)
|
||||
return;
|
||||
|
||||
fd = atoi(arg);
|
||||
assert(fd > STDERR_FILENO);
|
||||
unsetenv("UV_TEST_RUNNER_FD");
|
||||
closefd(fd);
|
||||
}
|
||||
|
||||
|
||||
/* Do platform-specific initialization. */
|
||||
void platform_init(int argc, char **argv) {
|
||||
/* Disable stdio output buffering. */
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
snprintf(executable_path, sizeof(executable_path), "%s", argv[0]);
|
||||
}
|
||||
|
||||
|
||||
/* Invoke "argv[0] test-name [test-part]". Store process info in *p. Make sure
|
||||
* that all stdio output of the processes is buffered up. */
|
||||
int process_start(char* name, char* part, process_info_t* p, int is_helper) {
|
||||
FILE* stdout_file;
|
||||
int stdout_fd;
|
||||
const char* arg;
|
||||
char* args[16];
|
||||
int pipefd[2];
|
||||
char fdstr[8];
|
||||
ssize_t rc;
|
||||
int n;
|
||||
pid_t pid;
|
||||
|
||||
arg = getenv("UV_USE_VALGRIND");
|
||||
n = 0;
|
||||
|
||||
/* Disable valgrind for helpers, it complains about helpers leaking memory.
|
||||
* They're killed after the test and as such never get a chance to clean up.
|
||||
*/
|
||||
if (is_helper == 0 && arg != NULL && atoi(arg) != 0) {
|
||||
args[n++] = "valgrind";
|
||||
args[n++] = "--quiet";
|
||||
args[n++] = "--leak-check=full";
|
||||
args[n++] = "--show-reachable=yes";
|
||||
args[n++] = "--error-exitcode=125";
|
||||
}
|
||||
|
||||
args[n++] = executable_path;
|
||||
args[n++] = name;
|
||||
args[n++] = part;
|
||||
args[n++] = NULL;
|
||||
|
||||
stdout_file = tmpfile();
|
||||
stdout_fd = fileno(stdout_file);
|
||||
if (!stdout_file) {
|
||||
perror("tmpfile");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_helper) {
|
||||
if (pipe(pipefd)) {
|
||||
perror("pipe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(fdstr, sizeof(fdstr), "%d", pipefd[1]);
|
||||
if (setenv("UV_TEST_RUNNER_FD", fdstr, /* overwrite */ 1)) {
|
||||
perror("setenv");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
p->terminated = 0;
|
||||
p->status = 0;
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
perror("fork");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
if (is_helper)
|
||||
closefd(pipefd[0]);
|
||||
dup2(stdout_fd, STDOUT_FILENO);
|
||||
dup2(stdout_fd, STDERR_FILENO);
|
||||
execve(args[0], args, environ);
|
||||
perror("execve()");
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
p->pid = pid;
|
||||
p->name = strdup(name);
|
||||
p->stdout_file = stdout_file;
|
||||
|
||||
if (!is_helper)
|
||||
return 0;
|
||||
|
||||
closefd(pipefd[1]);
|
||||
unsetenv("UV_TEST_RUNNER_FD");
|
||||
|
||||
do
|
||||
rc = read(pipefd[0], &n, 1);
|
||||
while (rc == -1 && errno == EINTR);
|
||||
|
||||
closefd(pipefd[0]);
|
||||
|
||||
if (rc == -1) {
|
||||
perror("read");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc > 0) {
|
||||
fprintf(stderr, "EOF expected but got data.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int pipe[2];
|
||||
process_info_t* vec;
|
||||
int n;
|
||||
} dowait_args;
|
||||
|
||||
|
||||
/* This function is run inside a pthread. We do this so that we can possibly
|
||||
* timeout.
|
||||
*/
|
||||
static void* dowait(void* data) {
|
||||
dowait_args* args = data;
|
||||
|
||||
int i, r;
|
||||
process_info_t* p;
|
||||
|
||||
for (i = 0; i < args->n; i++) {
|
||||
p = (process_info_t*)(args->vec + i * sizeof(process_info_t));
|
||||
if (p->terminated) continue;
|
||||
r = waitpid(p->pid, &p->status, 0);
|
||||
if (r < 0) {
|
||||
perror("waitpid");
|
||||
return NULL;
|
||||
}
|
||||
p->terminated = 1;
|
||||
}
|
||||
|
||||
if (args->pipe[1] >= 0) {
|
||||
/* Write a character to the main thread to notify it about this. */
|
||||
ssize_t r;
|
||||
|
||||
do
|
||||
r = write(args->pipe[1], "", 1);
|
||||
while (r == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Wait for all `n` processes in `vec` to terminate. Time out after `timeout`
|
||||
* msec, or never if timeout == -1. Return 0 if all processes are terminated,
|
||||
* -1 on error, -2 on timeout. */
|
||||
int process_wait(process_info_t* vec, int n, int timeout) {
|
||||
int i;
|
||||
int r;
|
||||
int retval;
|
||||
process_info_t* p;
|
||||
dowait_args args;
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
unsigned int elapsed_ms;
|
||||
struct timeval timebase;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
|
||||
args.vec = vec;
|
||||
args.n = n;
|
||||
args.pipe[0] = -1;
|
||||
args.pipe[1] = -1;
|
||||
|
||||
/* The simple case is where there is no timeout */
|
||||
if (timeout == -1) {
|
||||
dowait(&args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Hard case. Do the wait with a timeout.
|
||||
*
|
||||
* Assumption: we are the only ones making this call right now. Otherwise
|
||||
* we'd need to lock vec.
|
||||
*/
|
||||
|
||||
r = pipe((int*)&(args.pipe));
|
||||
if (r) {
|
||||
perror("pipe()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (pthread_attr_destroy(&attr))
|
||||
abort();
|
||||
|
||||
if (r) {
|
||||
perror("pthread_create()");
|
||||
retval = -1;
|
||||
goto terminate;
|
||||
}
|
||||
|
||||
if (gettimeofday(&timebase, NULL))
|
||||
abort();
|
||||
|
||||
tv = timebase;
|
||||
for (;;) {
|
||||
/* Check that gettimeofday() doesn't jump back in time. */
|
||||
assert(tv.tv_sec > timebase.tv_sec ||
|
||||
(tv.tv_sec == timebase.tv_sec && tv.tv_usec >= timebase.tv_usec));
|
||||
|
||||
elapsed_ms =
|
||||
(tv.tv_sec - timebase.tv_sec) * 1000 +
|
||||
(tv.tv_usec / 1000) -
|
||||
(timebase.tv_usec / 1000);
|
||||
|
||||
r = 0; /* Timeout. */
|
||||
if (elapsed_ms >= (unsigned) timeout)
|
||||
break;
|
||||
|
||||
tv.tv_sec = (timeout - elapsed_ms) / 1000;
|
||||
tv.tv_usec = (timeout - elapsed_ms) % 1000 * 1000;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(args.pipe[0], &fds);
|
||||
|
||||
r = select(args.pipe[0] + 1, &fds, NULL, NULL, &tv);
|
||||
if (!(r == -1 && errno == EINTR))
|
||||
break;
|
||||
|
||||
if (gettimeofday(&tv, NULL))
|
||||
abort();
|
||||
}
|
||||
|
||||
if (r == -1) {
|
||||
perror("select()");
|
||||
retval = -1;
|
||||
|
||||
} else if (r) {
|
||||
/* The thread completed successfully. */
|
||||
retval = 0;
|
||||
|
||||
} else {
|
||||
/* Timeout. Kill all the children. */
|
||||
for (i = 0; i < n; i++) {
|
||||
p = (process_info_t*)(vec + i * sizeof(process_info_t));
|
||||
kill(p->pid, SIGTERM);
|
||||
}
|
||||
retval = -2;
|
||||
}
|
||||
|
||||
if (pthread_join(tid, NULL))
|
||||
abort();
|
||||
|
||||
terminate:
|
||||
close(args.pipe[0]);
|
||||
close(args.pipe[1]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the number of bytes in the stdio output buffer for process `p`. */
|
||||
long int process_output_size(process_info_t *p) {
|
||||
/* Size of the p->stdout_file */
|
||||
struct stat buf;
|
||||
|
||||
int r = fstat(fileno(p->stdout_file), &buf);
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (long)buf.st_size;
|
||||
}
|
||||
|
||||
|
||||
/* Copy the contents of the stdio output buffer to `fd`. */
|
||||
int process_copy_output(process_info_t* p, FILE* stream) {
|
||||
char buf[1024];
|
||||
int r;
|
||||
|
||||
r = fseek(p->stdout_file, 0, SEEK_SET);
|
||||
if (r < 0) {
|
||||
perror("fseek");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: what if the line is longer than buf */
|
||||
while ((r = fread(buf, 1, sizeof(buf), p->stdout_file)) != 0)
|
||||
print_lines(buf, r, stream);
|
||||
|
||||
if (ferror(p->stdout_file)) {
|
||||
perror("read");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Copy the last line of the stdio output buffer to `buffer` */
|
||||
int process_read_last_line(process_info_t *p,
|
||||
char* buffer,
|
||||
size_t buffer_len) {
|
||||
char* ptr;
|
||||
|
||||
int r = fseek(p->stdout_file, 0, SEEK_SET);
|
||||
if (r < 0) {
|
||||
perror("fseek");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer[0] = '\0';
|
||||
|
||||
while (fgets(buffer, buffer_len, p->stdout_file) != NULL) {
|
||||
for (ptr = buffer; *ptr && *ptr != '\r' && *ptr != '\n'; ptr++)
|
||||
;
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
if (ferror(p->stdout_file)) {
|
||||
perror("read");
|
||||
buffer[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return the name that was specified when `p` was started by process_start */
|
||||
char* process_get_name(process_info_t *p) {
|
||||
return p->name;
|
||||
}
|
||||
|
||||
|
||||
/* Terminate process `p`. */
|
||||
int process_terminate(process_info_t *p) {
|
||||
return kill(p->pid, SIGTERM);
|
||||
}
|
||||
|
||||
|
||||
/* Return the exit code of process p. On error, return -1. */
|
||||
int process_reap(process_info_t *p) {
|
||||
if (WIFEXITED(p->status)) {
|
||||
return WEXITSTATUS(p->status);
|
||||
} else {
|
||||
return p->status; /* ? */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */
|
||||
void process_cleanup(process_info_t *p) {
|
||||
fclose(p->stdout_file);
|
||||
free(p->name);
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
}
|
36
deps/libuv/test/runner-unix.h
vendored
Normal file
36
deps/libuv/test/runner-unix.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TEST_RUNNER_UNIX_H
|
||||
#define TEST_RUNNER_UNIX_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h> /* FILE */
|
||||
|
||||
typedef struct {
|
||||
FILE* stdout_file;
|
||||
pid_t pid;
|
||||
char* name;
|
||||
int status;
|
||||
int terminated;
|
||||
} process_info_t;
|
||||
|
||||
#endif /* TEST_RUNNER_UNIX_H */
|
346
deps/libuv/test/runner-win.c
vendored
Normal file
346
deps/libuv/test/runner-win.c
vendored
Normal file
@ -0,0 +1,346 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <process.h>
|
||||
#if !defined(__MINGW32__)
|
||||
# include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "task.h"
|
||||
#include "runner.h"
|
||||
|
||||
|
||||
/*
|
||||
* Define the stuff that MinGW doesn't have
|
||||
*/
|
||||
#ifndef GetFileSizeEx
|
||||
WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile,
|
||||
PLARGE_INTEGER lpFileSize);
|
||||
#endif
|
||||
|
||||
|
||||
/* Do platform-specific initialization. */
|
||||
void platform_init(int argc, char **argv) {
|
||||
/* Disable the "application crashed" popup. */
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
|
||||
SEM_NOOPENFILEERRORBOX);
|
||||
#if !defined(__MINGW32__)
|
||||
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
|
||||
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
|
||||
#endif
|
||||
|
||||
_setmode(0, _O_BINARY);
|
||||
_setmode(1, _O_BINARY);
|
||||
_setmode(2, _O_BINARY);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_set_fmode(_O_BINARY);
|
||||
#else
|
||||
_fmode = _O_BINARY;
|
||||
#endif
|
||||
|
||||
/* Disable stdio output buffering. */
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
|
||||
strcpy(executable_path, argv[0]);
|
||||
}
|
||||
|
||||
|
||||
int process_start(char *name, char *part, process_info_t *p, int is_helper) {
|
||||
HANDLE file = INVALID_HANDLE_VALUE;
|
||||
HANDLE nul = INVALID_HANDLE_VALUE;
|
||||
WCHAR path[MAX_PATH], filename[MAX_PATH];
|
||||
WCHAR image[MAX_PATH + 1];
|
||||
WCHAR args[MAX_PATH * 2];
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION pi;
|
||||
DWORD result;
|
||||
|
||||
if (!is_helper) {
|
||||
/* Give the helpers time to settle. Race-y, fix this. */
|
||||
uv_sleep(250);
|
||||
}
|
||||
|
||||
if (GetTempPathW(sizeof(path) / sizeof(WCHAR), (WCHAR*)&path) == 0)
|
||||
goto error;
|
||||
if (GetTempFileNameW((WCHAR*)&path, L"uv", 0, (WCHAR*)&filename) == 0)
|
||||
goto error;
|
||||
|
||||
file = CreateFileW((WCHAR*)filename,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
|
||||
NULL);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
goto error;
|
||||
|
||||
if (!SetHandleInformation(file, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
|
||||
goto error;
|
||||
|
||||
nul = CreateFileA("nul",
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (nul == INVALID_HANDLE_VALUE)
|
||||
goto error;
|
||||
|
||||
if (!SetHandleInformation(nul, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
|
||||
goto error;
|
||||
|
||||
result = GetModuleFileNameW(NULL,
|
||||
(WCHAR*) &image,
|
||||
sizeof(image) / sizeof(WCHAR));
|
||||
if (result == 0 || result == sizeof(image))
|
||||
goto error;
|
||||
|
||||
if (part) {
|
||||
if (_snwprintf((WCHAR*)args,
|
||||
sizeof(args) / sizeof(WCHAR),
|
||||
L"\"%s\" %S %S",
|
||||
image,
|
||||
name,
|
||||
part) < 0) {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
if (_snwprintf((WCHAR*)args,
|
||||
sizeof(args) / sizeof(WCHAR),
|
||||
L"\"%s\" %S",
|
||||
image,
|
||||
name) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
memset((void*)&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdInput = nul;
|
||||
si.hStdOutput = file;
|
||||
si.hStdError = file;
|
||||
|
||||
if (!CreateProcessW(image, args, NULL, NULL, TRUE,
|
||||
0, NULL, NULL, &si, &pi))
|
||||
goto error;
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
SetHandleInformation(nul, HANDLE_FLAG_INHERIT, 0);
|
||||
SetHandleInformation(file, HANDLE_FLAG_INHERIT, 0);
|
||||
|
||||
p->stdio_in = nul;
|
||||
p->stdio_out = file;
|
||||
p->process = pi.hProcess;
|
||||
p->name = part;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (file != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(file);
|
||||
if (nul != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(nul);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Timeout is in msecs. Set timeout < 0 to never time out. Returns 0 when all
|
||||
* processes are terminated, -2 on timeout. */
|
||||
int process_wait(process_info_t *vec, int n, int timeout) {
|
||||
int i;
|
||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
||||
DWORD timeout_api, result;
|
||||
|
||||
/* If there's nothing to wait for, return immediately. */
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
ASSERT(n <= MAXIMUM_WAIT_OBJECTS);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
handles[i] = vec[i].process;
|
||||
|
||||
if (timeout >= 0) {
|
||||
timeout_api = (DWORD)timeout;
|
||||
} else {
|
||||
timeout_api = INFINITE;
|
||||
}
|
||||
|
||||
result = WaitForMultipleObjects(n, handles, TRUE, timeout_api);
|
||||
|
||||
if (result < WAIT_OBJECT_0 + n) {
|
||||
/* All processes are terminated. */
|
||||
return 0;
|
||||
}
|
||||
if (result == WAIT_TIMEOUT) {
|
||||
return -2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
long int process_output_size(process_info_t *p) {
|
||||
LARGE_INTEGER size;
|
||||
if (!GetFileSizeEx(p->stdio_out, &size))
|
||||
return -1;
|
||||
return (long int)size.QuadPart;
|
||||
}
|
||||
|
||||
|
||||
int process_copy_output(process_info_t* p, FILE* stream) {
|
||||
char buf[1024];
|
||||
int fd, r;
|
||||
|
||||
fd = _open_osfhandle((intptr_t)p->stdio_out, _O_RDONLY | _O_TEXT);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
r = _lseek(fd, 0, SEEK_SET);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
while ((r = _read(fd, buf, sizeof(buf))) != 0)
|
||||
print_lines(buf, r, stream);
|
||||
|
||||
_close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int process_read_last_line(process_info_t *p,
|
||||
char * buffer,
|
||||
size_t buffer_len) {
|
||||
DWORD size;
|
||||
DWORD read;
|
||||
DWORD start;
|
||||
OVERLAPPED overlapped;
|
||||
|
||||
ASSERT(buffer_len > 0);
|
||||
|
||||
size = GetFileSize(p->stdio_out, NULL);
|
||||
if (size == INVALID_FILE_SIZE)
|
||||
return -1;
|
||||
|
||||
if (size == 0) {
|
||||
buffer[0] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&overlapped, 0, sizeof overlapped);
|
||||
if (size >= buffer_len)
|
||||
overlapped.Offset = size - buffer_len - 1;
|
||||
|
||||
if (!ReadFile(p->stdio_out, buffer, buffer_len - 1, &read, &overlapped))
|
||||
return -1;
|
||||
|
||||
start = read;
|
||||
while (start-- > 0) {
|
||||
if (buffer[start] == '\n' || buffer[start] == '\r')
|
||||
break;
|
||||
}
|
||||
|
||||
if (start > 0)
|
||||
memmove(buffer, buffer + start, read - start);
|
||||
|
||||
buffer[read - start] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char* process_get_name(process_info_t *p) {
|
||||
return p->name;
|
||||
}
|
||||
|
||||
|
||||
int process_terminate(process_info_t *p) {
|
||||
if (!TerminateProcess(p->process, 1))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int process_reap(process_info_t *p) {
|
||||
DWORD exitCode;
|
||||
if (!GetExitCodeProcess(p->process, &exitCode))
|
||||
return -1;
|
||||
return (int)exitCode;
|
||||
}
|
||||
|
||||
|
||||
void process_cleanup(process_info_t *p) {
|
||||
CloseHandle(p->process);
|
||||
CloseHandle(p->stdio_in);
|
||||
}
|
||||
|
||||
|
||||
static int clear_line(void) {
|
||||
HANDLE handle;
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
COORD coord;
|
||||
DWORD written;
|
||||
|
||||
handle = (HANDLE)_get_osfhandle(fileno(stderr));
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(handle, &info))
|
||||
return -1;
|
||||
|
||||
coord = info.dwCursorPosition;
|
||||
if (coord.Y <= 0)
|
||||
return -1;
|
||||
|
||||
coord.X = 0;
|
||||
|
||||
if (!SetConsoleCursorPosition(handle, coord))
|
||||
return -1;
|
||||
|
||||
if (!FillConsoleOutputCharacterW(handle,
|
||||
0x20,
|
||||
info.dwSize.X,
|
||||
coord,
|
||||
&written)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void rewind_cursor() {
|
||||
if (clear_line() == -1) {
|
||||
/* If clear_line fails (stdout is not a console), print a newline. */
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
41
deps/libuv/test/runner-win.h
vendored
Normal file
41
deps/libuv/test/runner-win.h
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Don't complain about write(), fileno() etc. being deprecated. */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
|
||||
extern int snprintf(char*, size_t, const char*, ...);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
HANDLE process;
|
||||
HANDLE stdio_in;
|
||||
HANDLE stdio_out;
|
||||
char *name;
|
||||
} process_info_t;
|
453
deps/libuv/test/runner.c
vendored
Normal file
453
deps/libuv/test/runner.c
vendored
Normal file
@ -0,0 +1,453 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "runner.h"
|
||||
#include "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
char executable_path[sizeof(executable_path)];
|
||||
|
||||
|
||||
static int compare_task(const void* va, const void* vb) {
|
||||
const task_entry_t* a = va;
|
||||
const task_entry_t* b = vb;
|
||||
return strcmp(a->task_name, b->task_name);
|
||||
}
|
||||
|
||||
|
||||
const char* fmt(double d) {
|
||||
static char buf[1024];
|
||||
static char* p;
|
||||
uint64_t v;
|
||||
|
||||
if (p == NULL)
|
||||
p = buf;
|
||||
|
||||
p += 31;
|
||||
|
||||
if (p >= buf + sizeof(buf))
|
||||
return "<buffer too small>";
|
||||
|
||||
v = (uint64_t) d;
|
||||
|
||||
#if 0 /* works but we don't care about fractional precision */
|
||||
if (d - v >= 0.01) {
|
||||
*--p = '0' + (uint64_t) (d * 100) % 10;
|
||||
*--p = '0' + (uint64_t) (d * 10) % 10;
|
||||
*--p = '.';
|
||||
}
|
||||
#endif
|
||||
|
||||
if (v == 0)
|
||||
*--p = '0';
|
||||
|
||||
while (v) {
|
||||
if (v) *--p = '0' + (v % 10), v /= 10;
|
||||
if (v) *--p = '0' + (v % 10), v /= 10;
|
||||
if (v) *--p = '0' + (v % 10), v /= 10;
|
||||
if (v) *--p = ',';
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
int run_tests(int benchmark_output) {
|
||||
int actual;
|
||||
int total;
|
||||
int passed;
|
||||
int failed;
|
||||
int skipped;
|
||||
int current;
|
||||
int test_result;
|
||||
int skip;
|
||||
task_entry_t* task;
|
||||
|
||||
/* Count the number of tests. */
|
||||
actual = 0;
|
||||
total = 0;
|
||||
for (task = TASKS; task->main; task++, actual++) {
|
||||
if (!task->is_helper) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep platform_output first. */
|
||||
skip = (actual > 0 && 0 == strcmp(TASKS[0].task_name, "platform_output"));
|
||||
qsort(TASKS + skip, actual - skip, sizeof(TASKS[0]), compare_task);
|
||||
|
||||
fprintf(stderr, "1..%d\n", total);
|
||||
fflush(stderr);
|
||||
|
||||
/* Run all tests. */
|
||||
passed = 0;
|
||||
failed = 0;
|
||||
skipped = 0;
|
||||
current = 1;
|
||||
for (task = TASKS; task->main; task++) {
|
||||
if (task->is_helper) {
|
||||
continue;
|
||||
}
|
||||
|
||||
test_result = run_test(task->task_name, benchmark_output, current);
|
||||
switch (test_result) {
|
||||
case TEST_OK: passed++; break;
|
||||
case TEST_SKIP: skipped++; break;
|
||||
default: failed++;
|
||||
}
|
||||
current++;
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
void log_tap_result(int test_count,
|
||||
const char* test,
|
||||
int status,
|
||||
process_info_t* process) {
|
||||
const char* result;
|
||||
const char* directive;
|
||||
char reason[1024];
|
||||
int reason_length;
|
||||
|
||||
switch (status) {
|
||||
case TEST_OK:
|
||||
result = "ok";
|
||||
directive = "";
|
||||
break;
|
||||
case TEST_SKIP:
|
||||
result = "ok";
|
||||
directive = " # SKIP ";
|
||||
break;
|
||||
default:
|
||||
result = "not ok";
|
||||
directive = "";
|
||||
}
|
||||
|
||||
if (status == TEST_SKIP && process_output_size(process) > 0) {
|
||||
process_read_last_line(process, reason, sizeof reason);
|
||||
reason_length = strlen(reason);
|
||||
if (reason_length > 0 && reason[reason_length - 1] == '\n')
|
||||
reason[reason_length - 1] = '\0';
|
||||
} else {
|
||||
reason[0] = '\0';
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s %d - %s%s%s\n", result, test_count, test, directive, reason);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
int run_test(const char* test,
|
||||
int benchmark_output,
|
||||
int test_count) {
|
||||
char errmsg[1024] = "";
|
||||
process_info_t processes[1024];
|
||||
process_info_t *main_proc;
|
||||
task_entry_t* task;
|
||||
int timeout_multiplier;
|
||||
int process_count;
|
||||
int result;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
status = 255;
|
||||
main_proc = NULL;
|
||||
process_count = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Clean up stale socket from previous run. */
|
||||
remove(TEST_PIPENAME);
|
||||
remove(TEST_PIPENAME_2);
|
||||
remove(TEST_PIPENAME_3);
|
||||
#endif
|
||||
|
||||
/* If it's a helper the user asks for, start it directly. */
|
||||
for (task = TASKS; task->main; task++) {
|
||||
if (task->is_helper && strcmp(test, task->process_name) == 0) {
|
||||
return task->main();
|
||||
}
|
||||
}
|
||||
|
||||
/* Start the helpers first. */
|
||||
for (task = TASKS; task->main; task++) {
|
||||
if (strcmp(test, task->task_name) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip the test itself. */
|
||||
if (!task->is_helper) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (process_start(task->task_name,
|
||||
task->process_name,
|
||||
&processes[process_count],
|
||||
1 /* is_helper */) == -1) {
|
||||
snprintf(errmsg,
|
||||
sizeof errmsg,
|
||||
"Process `%s` failed to start.",
|
||||
task->process_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
process_count++;
|
||||
}
|
||||
|
||||
/* Now start the test itself. */
|
||||
for (task = TASKS; task->main; task++) {
|
||||
if (strcmp(test, task->task_name) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (task->is_helper) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (process_start(task->task_name,
|
||||
task->process_name,
|
||||
&processes[process_count],
|
||||
0 /* !is_helper */) == -1) {
|
||||
snprintf(errmsg,
|
||||
sizeof errmsg,
|
||||
"Process `%s` failed to start.",
|
||||
task->process_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
main_proc = &processes[process_count];
|
||||
process_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (main_proc == NULL) {
|
||||
snprintf(errmsg,
|
||||
sizeof errmsg,
|
||||
"No test with that name: %s",
|
||||
test);
|
||||
goto out;
|
||||
}
|
||||
|
||||
timeout_multiplier = 1;
|
||||
#ifndef _WIN32
|
||||
do {
|
||||
const char* var;
|
||||
|
||||
var = getenv("UV_TEST_TIMEOUT_MULTIPLIER");
|
||||
if (var == NULL)
|
||||
break;
|
||||
|
||||
timeout_multiplier = atoi(var);
|
||||
if (timeout_multiplier <= 0)
|
||||
timeout_multiplier = 1;
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
result = process_wait(main_proc, 1, task->timeout * timeout_multiplier);
|
||||
if (result == -1) {
|
||||
FATAL("process_wait failed");
|
||||
} else if (result == -2) {
|
||||
/* Don't have to clean up the process, process_wait() has killed it. */
|
||||
snprintf(errmsg,
|
||||
sizeof errmsg,
|
||||
"timeout");
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = process_reap(main_proc);
|
||||
if (status != TEST_OK) {
|
||||
snprintf(errmsg,
|
||||
sizeof errmsg,
|
||||
"exit code %d",
|
||||
status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (benchmark_output) {
|
||||
/* Give the helpers time to clean up their act. */
|
||||
uv_sleep(1000);
|
||||
}
|
||||
|
||||
out:
|
||||
/* Reap running processes except the main process, it's already dead. */
|
||||
for (i = 0; i < process_count - 1; i++) {
|
||||
process_terminate(&processes[i]);
|
||||
}
|
||||
|
||||
if (process_count > 0 &&
|
||||
process_wait(processes, process_count - 1, -1) < 0) {
|
||||
FATAL("process_wait failed");
|
||||
}
|
||||
|
||||
log_tap_result(test_count, test, status, &processes[i]);
|
||||
|
||||
/* Show error and output from processes if the test failed. */
|
||||
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++) {
|
||||
switch (process_output_size(&processes[i])) {
|
||||
case -1:
|
||||
fprintf(stderr, "Output from process `%s`: (unavailable)\n",
|
||||
process_get_name(&processes[i]));
|
||||
fflush(stderr);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
fprintf(stderr, "Output from process `%s`: (no output)\n",
|
||||
process_get_name(&processes[i]));
|
||||
fflush(stderr);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i]));
|
||||
fflush(stderr);
|
||||
process_copy_output(&processes[i], stderr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* In benchmark mode show concise output from the main process. */
|
||||
} else if (benchmark_output) {
|
||||
switch (process_output_size(main_proc)) {
|
||||
case -1:
|
||||
fprintf(stderr, "%s: (unavailable)\n", test);
|
||||
fflush(stderr);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
fprintf(stderr, "%s: (no output)\n", test);
|
||||
fflush(stderr);
|
||||
break;
|
||||
|
||||
default:
|
||||
for (i = 0; i < process_count; i++) {
|
||||
process_copy_output(&processes[i], stderr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up all process handles. */
|
||||
for (i = 0; i < process_count; i++) {
|
||||
process_cleanup(&processes[i]);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the status code of the task part
|
||||
* or 255 if no matching task was not found.
|
||||
*/
|
||||
int run_test_part(const char* test, const char* part) {
|
||||
task_entry_t* task;
|
||||
int r;
|
||||
|
||||
for (task = TASKS; task->main; task++) {
|
||||
if (strcmp(test, task->task_name) == 0 &&
|
||||
strcmp(part, task->process_name) == 0) {
|
||||
r = task->main();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "No test part with that name: %s:%s\n", test, part);
|
||||
fflush(stderr);
|
||||
return 255;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int find_helpers(const task_entry_t* task,
|
||||
const task_entry_t** helpers) {
|
||||
const task_entry_t* helper;
|
||||
int n_helpers;
|
||||
|
||||
for (n_helpers = 0, helper = TASKS; helper->main; helper++) {
|
||||
if (helper->is_helper && strcmp(helper->task_name, task->task_name) == 0) {
|
||||
*helpers++ = helper;
|
||||
n_helpers++;
|
||||
}
|
||||
}
|
||||
|
||||
return n_helpers;
|
||||
}
|
||||
|
||||
|
||||
void print_tests(FILE* stream) {
|
||||
const task_entry_t* helpers[1024];
|
||||
const task_entry_t* task;
|
||||
int n_helpers;
|
||||
int n_tasks;
|
||||
int i;
|
||||
|
||||
for (n_tasks = 0, task = TASKS; task->main; n_tasks++, task++);
|
||||
qsort(TASKS, n_tasks, sizeof(TASKS[0]), compare_task);
|
||||
|
||||
for (task = TASKS; task->main; task++) {
|
||||
if (task->is_helper) {
|
||||
continue;
|
||||
}
|
||||
|
||||
n_helpers = find_helpers(task, helpers);
|
||||
if (n_helpers) {
|
||||
printf("%-25s (helpers:", task->task_name);
|
||||
for (i = 0; i < n_helpers; i++) {
|
||||
printf(" %s", helpers[i]->process_name);
|
||||
}
|
||||
printf(")\n");
|
||||
} else {
|
||||
printf("%s\n", task->task_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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))) {
|
||||
fputs("# ", stream);
|
||||
fwrite(start, 1, (int)(end - start), stream);
|
||||
fputs("\n", stream);
|
||||
fflush(stream);
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
end = &buffer[size];
|
||||
if (start < end) {
|
||||
fputs("# ", stream);
|
||||
fwrite(start, 1, (int)(end - start), stream);
|
||||
fputs("\n", stream);
|
||||
fflush(stream);
|
||||
}
|
||||
}
|
172
deps/libuv/test/runner.h
vendored
Normal file
172
deps/libuv/test/runner.h
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef RUNNER_H_
|
||||
#define RUNNER_H_
|
||||
|
||||
#include <limits.h> /* PATH_MAX */
|
||||
#include <stdio.h> /* FILE */
|
||||
|
||||
|
||||
/*
|
||||
* The maximum number of processes (main + helpers) that a test / benchmark
|
||||
* can have.
|
||||
*/
|
||||
#define MAX_PROCESSES 8
|
||||
|
||||
|
||||
/*
|
||||
* Struct to store both tests and to define helper processes for tasks.
|
||||
*/
|
||||
typedef struct {
|
||||
char *task_name;
|
||||
char *process_name;
|
||||
int (*main)(void);
|
||||
int is_helper;
|
||||
int show_output;
|
||||
|
||||
/*
|
||||
* The time in milliseconds after which a single test or benchmark times out.
|
||||
*/
|
||||
int timeout;
|
||||
} task_entry_t, bench_entry_t;
|
||||
|
||||
|
||||
/*
|
||||
* Macros used by test-list.h and benchmark-list.h.
|
||||
*/
|
||||
#define TASK_LIST_START \
|
||||
task_entry_t TASKS[] = {
|
||||
|
||||
#define TASK_LIST_END \
|
||||
{ 0, 0, 0, 0, 0, 0 } \
|
||||
};
|
||||
|
||||
#define TEST_DECLARE(name) \
|
||||
int run_test_##name(void);
|
||||
|
||||
#define TEST_ENTRY(name) \
|
||||
{ #name, #name, &run_test_##name, 0, 0, 5000 },
|
||||
|
||||
#define TEST_ENTRY_CUSTOM(name, is_helper, show_output, timeout) \
|
||||
{ #name, #name, &run_test_##name, is_helper, show_output, timeout },
|
||||
|
||||
#define BENCHMARK_DECLARE(name) \
|
||||
int run_benchmark_##name(void);
|
||||
|
||||
#define BENCHMARK_ENTRY(name) \
|
||||
{ #name, #name, &run_benchmark_##name, 0, 0, 60000 },
|
||||
|
||||
#define HELPER_DECLARE(name) \
|
||||
int run_helper_##name(void);
|
||||
|
||||
#define HELPER_ENTRY(task_name, name) \
|
||||
{ #task_name, #name, &run_helper_##name, 1, 0, 0 },
|
||||
|
||||
#define TEST_HELPER HELPER_ENTRY
|
||||
#define BENCHMARK_HELPER HELPER_ENTRY
|
||||
|
||||
extern char executable_path[4096];
|
||||
|
||||
/*
|
||||
* Include platform-dependent definitions
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
# include "runner-win.h"
|
||||
#else
|
||||
# include "runner-unix.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* The array that is filled by test-list.h or benchmark-list.h */
|
||||
extern task_entry_t TASKS[];
|
||||
|
||||
/*
|
||||
* Run all tests.
|
||||
*/
|
||||
int run_tests(int benchmark_output);
|
||||
|
||||
/*
|
||||
* Run a single test. Starts up any helpers.
|
||||
*/
|
||||
int run_test(const char* test,
|
||||
int benchmark_output,
|
||||
int test_count);
|
||||
|
||||
/*
|
||||
* Run a test part, i.e. the test or one of its helpers.
|
||||
*/
|
||||
int run_test_part(const char* test, const char* part);
|
||||
|
||||
|
||||
/*
|
||||
* Print tests in sorted order to `stream`. Used by `./run-tests --list`.
|
||||
*/
|
||||
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
|
||||
* All functions return 0 on success, -1 on failure, unless specified
|
||||
* otherwise.
|
||||
*/
|
||||
|
||||
/* Do platform-specific initialization. */
|
||||
void platform_init(int argc, char** argv);
|
||||
|
||||
/* Invoke "argv[0] test-name [test-part]". Store process info in *p. Make sure
|
||||
* that all stdio output of the processes is buffered up. */
|
||||
int process_start(char *name, char* part, process_info_t *p, int is_helper);
|
||||
|
||||
/* Wait for all `n` processes in `vec` to terminate. Time out after `timeout`
|
||||
* msec, or never if timeout == -1. Return 0 if all processes are terminated,
|
||||
* -1 on error, -2 on timeout. */
|
||||
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 `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,
|
||||
char * buffer,
|
||||
size_t buffer_len);
|
||||
|
||||
/* Return the name that was specified when `p` was started by process_start */
|
||||
char* process_get_name(process_info_t *p);
|
||||
|
||||
/* Terminate process `p`. */
|
||||
int process_terminate(process_info_t *p);
|
||||
|
||||
/* Return the exit code of process p. On error, return -1. */
|
||||
int process_reap(process_info_t *p);
|
||||
|
||||
/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */
|
||||
void process_cleanup(process_info_t *p);
|
||||
|
||||
/* Move the console cursor one line up and back to the first column. */
|
||||
void rewind_cursor(void);
|
||||
|
||||
#endif /* RUNNER_H_ */
|
373
deps/libuv/test/task.h
vendored
Normal file
373
deps/libuv/test/task.h
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TASK_H_
|
||||
#define TASK_H_
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <sys/time.h>
|
||||
# include <sys/resource.h> /* setrlimit() */
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic ignored "-Wvariadic-macros"
|
||||
# pragma clang diagnostic ignored "-Wc99-extensions"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wvariadic-macros"
|
||||
#endif
|
||||
|
||||
#define TEST_PORT 9123
|
||||
#define TEST_PORT_2 9124
|
||||
|
||||
#ifdef _WIN32
|
||||
# define TEST_PIPENAME "\\\\?\\pipe\\uv-test"
|
||||
# define TEST_PIPENAME_2 "\\\\?\\pipe\\uv-test2"
|
||||
# define TEST_PIPENAME_3 "\\\\?\\pipe\\uv-test3"
|
||||
#else
|
||||
# define TEST_PIPENAME "/tmp/uv-test-sock"
|
||||
# define TEST_PIPENAME_2 "/tmp/uv-test-sock2"
|
||||
# define TEST_PIPENAME_3 "/tmp/uv-test-sock3"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
# ifndef S_IRUSR
|
||||
# define S_IRUSR _S_IREAD
|
||||
# endif
|
||||
# ifndef S_IWUSR
|
||||
# define S_IWUSR _S_IWRITE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
#define container_of(ptr, type, member) \
|
||||
((type *) ((char *) (ptr) - offsetof(type, member)))
|
||||
|
||||
typedef enum {
|
||||
TCP = 0,
|
||||
UDP,
|
||||
PIPE
|
||||
} stream_type;
|
||||
|
||||
/* Die with fatal error. */
|
||||
#define FATAL(msg) \
|
||||
do { \
|
||||
fprintf(stderr, \
|
||||
"Fatal error in %s on line %d: %s\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
msg); \
|
||||
fflush(stderr); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
/* Have our own assert, so we are sure it does not get optimized away in
|
||||
* a release build.
|
||||
*/
|
||||
#define ASSERT(expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
fprintf(stderr, \
|
||||
"Assertion failed in %s on line %d: %s\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#expr); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_BASE(a, operator, b, type, conv) \
|
||||
do { \
|
||||
type eval_a = (type) (a); \
|
||||
type eval_b = (type) (b); \
|
||||
if (!(eval_a operator eval_b)) { \
|
||||
fprintf(stderr, \
|
||||
"Assertion failed in %s on line %d: `%s %s %s` " \
|
||||
"(%"conv" %s %"conv")\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#a, \
|
||||
#operator, \
|
||||
#b, \
|
||||
eval_a, \
|
||||
#operator, \
|
||||
eval_b); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_BASE_STR(expr, a, operator, b, type, conv) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
fprintf(stderr, \
|
||||
"Assertion failed in %s on line %d: `%s %s %s` " \
|
||||
"(%"conv" %s %"conv")\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#a, \
|
||||
#operator, \
|
||||
#b, \
|
||||
(type)a, \
|
||||
#operator, \
|
||||
(type)b); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_BASE_LEN(expr, a, operator, b, conv, len) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
fprintf(stderr, \
|
||||
"Assertion failed in %s on line %d: `%s %s %s` " \
|
||||
"(%.*"#conv" %s %.*"#conv")\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#a, \
|
||||
#operator, \
|
||||
#b, \
|
||||
(int)len, \
|
||||
a, \
|
||||
#operator, \
|
||||
(int)len, \
|
||||
b); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_BASE_HEX(expr, a, operator, b, size) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
int i; \
|
||||
unsigned char* a_ = (unsigned char*)a; \
|
||||
unsigned char* b_ = (unsigned char*)b; \
|
||||
fprintf(stderr, \
|
||||
"Assertion failed in %s on line %d: `%s %s %s` (", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#a, \
|
||||
#operator, \
|
||||
#b); \
|
||||
for (i = 0; i < size; ++i) { \
|
||||
if (i > 0) fprintf(stderr, ":"); \
|
||||
fprintf(stderr, "%02X", a_[i]); \
|
||||
} \
|
||||
fprintf(stderr, " %s ", #operator); \
|
||||
for (i = 0; i < size; ++i) { \
|
||||
if (i > 0) fprintf(stderr, ":"); \
|
||||
fprintf(stderr, "%02X", b_[i]); \
|
||||
} \
|
||||
fprintf(stderr, ")\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_INT_BASE(a, operator, b, type, conv) \
|
||||
ASSERT_BASE(a, operator, b, type, conv)
|
||||
|
||||
#define ASSERT_EQ(a, b) ASSERT_INT_BASE(a, ==, b, int64_t, PRId64)
|
||||
#define ASSERT_GE(a, b) ASSERT_INT_BASE(a, >=, b, int64_t, PRId64)
|
||||
#define ASSERT_GT(a, b) ASSERT_INT_BASE(a, >, b, int64_t, PRId64)
|
||||
#define ASSERT_LE(a, b) ASSERT_INT_BASE(a, <=, b, int64_t, PRId64)
|
||||
#define ASSERT_LT(a, b) ASSERT_INT_BASE(a, <, b, int64_t, PRId64)
|
||||
#define ASSERT_NE(a, b) ASSERT_INT_BASE(a, !=, b, int64_t, PRId64)
|
||||
|
||||
#define ASSERT_UINT64_EQ(a, b) ASSERT_INT_BASE(a, ==, b, uint64_t, PRIu64)
|
||||
#define ASSERT_UINT64_GE(a, b) ASSERT_INT_BASE(a, >=, b, uint64_t, PRIu64)
|
||||
#define ASSERT_UINT64_GT(a, b) ASSERT_INT_BASE(a, >, b, uint64_t, PRIu64)
|
||||
#define ASSERT_UINT64_LE(a, b) ASSERT_INT_BASE(a, <=, b, uint64_t, PRIu64)
|
||||
#define ASSERT_UINT64_LT(a, b) ASSERT_INT_BASE(a, <, b, uint64_t, PRIu64)
|
||||
#define ASSERT_UINT64_NE(a, b) ASSERT_INT_BASE(a, !=, b, uint64_t, PRIu64)
|
||||
|
||||
#define ASSERT_STR_EQ(a, b) \
|
||||
ASSERT_BASE_STR(strcmp(a, b) == 0, a, == , b, char*, "s")
|
||||
|
||||
#define ASSERT_STR_NE(a, b) \
|
||||
ASSERT_BASE_STR(strcmp(a, b) != 0, a, !=, b, char*, "s")
|
||||
|
||||
#define ASSERT_MEM_EQ(a, b, size) \
|
||||
ASSERT_BASE_LEN(memcmp(a, b, size) == 0, a, ==, b, s, size)
|
||||
|
||||
#define ASSERT_MEM_NE(a, b, size) \
|
||||
ASSERT_BASE_LEN(memcmp(a, b, size) != 0, a, !=, b, s, size)
|
||||
|
||||
#define ASSERT_MEM_HEX_EQ(a, b, size) \
|
||||
ASSERT_BASE_HEX(memcmp(a, b, size) == 0, a, ==, b, size)
|
||||
|
||||
#define ASSERT_MEM_HEX_NE(a, b, size) \
|
||||
ASSERT_BASE_HEX(memcmp(a, b, size) != 0, a, !=, b, size)
|
||||
|
||||
#define ASSERT_NULL(a) \
|
||||
ASSERT_BASE(a, ==, NULL, void*, "p")
|
||||
|
||||
#define ASSERT_NOT_NULL(a) \
|
||||
ASSERT_BASE(a, !=, NULL, void*, "p")
|
||||
|
||||
#define ASSERT_PTR_EQ(a, b) \
|
||||
ASSERT_BASE(a, ==, b, void*, "p")
|
||||
|
||||
#define ASSERT_PTR_NE(a, b) \
|
||||
ASSERT_BASE(a, !=, b, void*, "p")
|
||||
|
||||
/* This macro cleans up the main loop. This is used to avoid valgrind
|
||||
* warnings about memory being "leaked" by the main event loop.
|
||||
*/
|
||||
#define MAKE_VALGRIND_HAPPY() \
|
||||
do { \
|
||||
close_loop(uv_default_loop()); \
|
||||
ASSERT(0 == uv_loop_close(uv_default_loop())); \
|
||||
uv_library_shutdown(); \
|
||||
} while (0)
|
||||
|
||||
/* Just sugar for wrapping the main() for a task or helper. */
|
||||
#define TEST_IMPL(name) \
|
||||
int run_test_##name(void); \
|
||||
int run_test_##name(void)
|
||||
|
||||
#define BENCHMARK_IMPL(name) \
|
||||
int run_benchmark_##name(void); \
|
||||
int run_benchmark_##name(void)
|
||||
|
||||
#define HELPER_IMPL(name) \
|
||||
int run_helper_##name(void); \
|
||||
int run_helper_##name(void)
|
||||
|
||||
/* Format big numbers nicely. WARNING: leaks memory. */
|
||||
const char* fmt(double d);
|
||||
|
||||
/* Reserved test exit codes. */
|
||||
enum test_status {
|
||||
TEST_OK = 0,
|
||||
TEST_SKIP
|
||||
};
|
||||
|
||||
#define RETURN_OK() \
|
||||
do { \
|
||||
return TEST_OK; \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_SKIP(explanation) \
|
||||
do { \
|
||||
fprintf(stderr, "%s\n", explanation); \
|
||||
fflush(stderr); \
|
||||
return TEST_SKIP; \
|
||||
} while (0)
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
# define TEST_FILE_LIMIT(num) \
|
||||
do { \
|
||||
struct rlimit lim; \
|
||||
lim.rlim_cur = (num); \
|
||||
lim.rlim_max = lim.rlim_cur; \
|
||||
if (setrlimit(RLIMIT_NOFILE, &lim)) \
|
||||
RETURN_SKIP("File descriptor limit too low."); \
|
||||
} while (0)
|
||||
|
||||
#else /* defined(_WIN32) */
|
||||
|
||||
# define TEST_FILE_LIMIT(num) do {} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
|
||||
extern int snprintf(char*, size_t, const char*, ...);
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || \
|
||||
defined(__GNUC__) || \
|
||||
defined(__INTEL_COMPILER)
|
||||
# define UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define notify_parent_process() ((void) 0)
|
||||
#else
|
||||
extern void notify_parent_process(void);
|
||||
#endif
|
||||
|
||||
/* Fully close a loop */
|
||||
static void close_walk_cb(uv_handle_t* handle, void* arg) {
|
||||
if (!uv_is_closing(handle))
|
||||
uv_close(handle, NULL);
|
||||
}
|
||||
|
||||
UNUSED static void close_loop(uv_loop_t* loop) {
|
||||
uv_walk(loop, close_walk_cb, NULL);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
||||
|
||||
UNUSED static int can_ipv6(void) {
|
||||
uv_interface_address_t* addr;
|
||||
int supported;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
if (uv_interface_addresses(&addr, &count))
|
||||
return 0; /* Assume no IPv6 support on failure. */
|
||||
|
||||
supported = 0;
|
||||
for (i = 0; supported == 0 && i < count; i += 1)
|
||||
supported = (AF_INET6 == addr[i].address.address6.sin6_family);
|
||||
|
||||
uv_free_interface_addresses(addr, count);
|
||||
return supported;
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__)
|
||||
# define NO_FS_EVENTS "Filesystem watching not supported on this platform."
|
||||
#endif
|
||||
|
||||
#if defined(__MSYS__)
|
||||
# define NO_SEND_HANDLE_ON_PIPE \
|
||||
"MSYS2 runtime does not support sending handles on pipes."
|
||||
#elif defined(__CYGWIN__)
|
||||
# define NO_SEND_HANDLE_ON_PIPE \
|
||||
"Cygwin runtime does not support sending handles on pipes."
|
||||
#endif
|
||||
|
||||
#if defined(__MSYS__)
|
||||
# define NO_SELF_CONNECT \
|
||||
"MSYS2 runtime hangs on listen+connect in same process."
|
||||
#elif defined(__CYGWIN__)
|
||||
# define NO_SELF_CONNECT \
|
||||
"Cygwin runtime hangs on listen+connect in same process."
|
||||
#endif
|
||||
|
||||
#endif /* TASK_H_ */
|
84
deps/libuv/test/test-active.c
vendored
Normal file
84
deps/libuv/test/test-active.c
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static int close_cb_called = 0;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(0 && "timer_cb should not have been called");
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(active) {
|
||||
int r;
|
||||
uv_timer_t timer;
|
||||
|
||||
r = uv_timer_init(uv_default_loop(), &timer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* uv_is_active() and uv_is_closing() should always return either 0 or 1. */
|
||||
ASSERT(0 == uv_is_active((uv_handle_t*) &timer));
|
||||
ASSERT(0 == uv_is_closing((uv_handle_t*) &timer));
|
||||
|
||||
r = uv_timer_start(&timer, timer_cb, 1000, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(1 == uv_is_active((uv_handle_t*) &timer));
|
||||
ASSERT(0 == uv_is_closing((uv_handle_t*) &timer));
|
||||
|
||||
r = uv_timer_stop(&timer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(0 == uv_is_active((uv_handle_t*) &timer));
|
||||
ASSERT(0 == uv_is_closing((uv_handle_t*) &timer));
|
||||
|
||||
r = uv_timer_start(&timer, timer_cb, 1000, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(1 == uv_is_active((uv_handle_t*) &timer));
|
||||
ASSERT(0 == uv_is_closing((uv_handle_t*) &timer));
|
||||
|
||||
uv_close((uv_handle_t*) &timer, close_cb);
|
||||
|
||||
ASSERT(0 == uv_is_active((uv_handle_t*) &timer));
|
||||
ASSERT(1 == uv_is_closing((uv_handle_t*) &timer));
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
64
deps/libuv/test/test-async-null-cb.c
vendored
Normal file
64
deps/libuv/test/test-async-null-cb.c
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
static uv_async_t async_handle;
|
||||
static uv_check_t check_handle;
|
||||
static int check_cb_called;
|
||||
static uv_thread_t thread;
|
||||
|
||||
|
||||
static void thread_cb(void* dummy) {
|
||||
(void) &dummy;
|
||||
uv_async_send(&async_handle);
|
||||
}
|
||||
|
||||
|
||||
static void check_cb(uv_check_t* handle) {
|
||||
ASSERT(check_cb_called == 0);
|
||||
uv_close((uv_handle_t*) &async_handle, NULL);
|
||||
uv_close((uv_handle_t*) &check_handle, NULL);
|
||||
check_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(async_null_cb) {
|
||||
/*
|
||||
* Fill async_handle with garbage values.
|
||||
* uv_async_init() should properly initialize struct fields regardless of
|
||||
* initial values.
|
||||
* This is added to verify paddings between fields do not affect behavior.
|
||||
*/
|
||||
memset(&async_handle, 0xff, sizeof(async_handle));
|
||||
|
||||
ASSERT(0 == uv_async_init(uv_default_loop(), &async_handle, NULL));
|
||||
ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle));
|
||||
ASSERT(0 == uv_check_start(&check_handle, check_cb));
|
||||
ASSERT(0 == uv_thread_create(&thread, thread_cb, NULL));
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
ASSERT(1 == check_cb_called);
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
134
deps/libuv/test/test-async.c
vendored
Normal file
134
deps/libuv/test/test-async.c
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static uv_thread_t thread;
|
||||
static uv_mutex_t mutex;
|
||||
|
||||
static uv_prepare_t prepare;
|
||||
static uv_async_t async;
|
||||
|
||||
static volatile int async_cb_called;
|
||||
static int prepare_cb_called;
|
||||
static int close_cb_called;
|
||||
|
||||
|
||||
static void thread_cb(void *arg) {
|
||||
int n;
|
||||
int r;
|
||||
|
||||
for (;;) {
|
||||
uv_mutex_lock(&mutex);
|
||||
n = async_cb_called;
|
||||
uv_mutex_unlock(&mutex);
|
||||
|
||||
if (n == 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
r = uv_async_send(&async);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Work around a bug in Valgrind.
|
||||
*
|
||||
* Valgrind runs threads not in parallel but sequentially, i.e. one after
|
||||
* the other. It also doesn't preempt them, instead it depends on threads
|
||||
* yielding voluntarily by making a syscall.
|
||||
*
|
||||
* That never happens here: the pipe that is associated with the async
|
||||
* handle is written to once but that's too early for Valgrind's scheduler
|
||||
* to kick in. Afterwards, the thread busy-loops, starving the main thread.
|
||||
* Therefore, we yield.
|
||||
*
|
||||
* This behavior has been observed with Valgrind 3.7.0 and 3.9.0.
|
||||
*/
|
||||
uv_sleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void async_cb(uv_async_t* handle) {
|
||||
int n;
|
||||
|
||||
ASSERT(handle == &async);
|
||||
|
||||
uv_mutex_lock(&mutex);
|
||||
n = ++async_cb_called;
|
||||
uv_mutex_unlock(&mutex);
|
||||
|
||||
if (n == 3) {
|
||||
uv_close((uv_handle_t*)&async, close_cb);
|
||||
uv_close((uv_handle_t*)&prepare, close_cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void prepare_cb(uv_prepare_t* handle) {
|
||||
int r;
|
||||
|
||||
ASSERT(handle == &prepare);
|
||||
|
||||
if (prepare_cb_called++)
|
||||
return;
|
||||
|
||||
r = uv_thread_create(&thread, thread_cb, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(async) {
|
||||
int r;
|
||||
|
||||
r = uv_mutex_init(&mutex);
|
||||
ASSERT(r == 0);
|
||||
uv_mutex_lock(&mutex);
|
||||
|
||||
r = uv_prepare_init(uv_default_loop(), &prepare);
|
||||
ASSERT(r == 0);
|
||||
r = uv_prepare_start(&prepare, prepare_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_async_init(uv_default_loop(), &async, async_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(prepare_cb_called > 0);
|
||||
ASSERT(async_cb_called == 3);
|
||||
ASSERT(close_cb_called == 2);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
148
deps/libuv/test/test-barrier.c
vendored
Normal file
148
deps/libuv/test/test-barrier.c
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct {
|
||||
uv_barrier_t barrier;
|
||||
int delay;
|
||||
volatile int posted;
|
||||
int main_barrier_wait_rval;
|
||||
int worker_barrier_wait_rval;
|
||||
} worker_config;
|
||||
|
||||
|
||||
static void worker(void* arg) {
|
||||
worker_config* c = arg;
|
||||
|
||||
if (c->delay)
|
||||
uv_sleep(c->delay);
|
||||
|
||||
c->worker_barrier_wait_rval = uv_barrier_wait(&c->barrier);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(barrier_1) {
|
||||
uv_thread_t thread;
|
||||
worker_config wc;
|
||||
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
|
||||
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
|
||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||
|
||||
uv_sleep(100);
|
||||
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
uv_barrier_destroy(&wc.barrier);
|
||||
|
||||
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(barrier_2) {
|
||||
uv_thread_t thread;
|
||||
worker_config wc;
|
||||
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.delay = 100;
|
||||
|
||||
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
|
||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||
|
||||
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
uv_barrier_destroy(&wc.barrier);
|
||||
|
||||
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(barrier_3) {
|
||||
uv_thread_t thread;
|
||||
worker_config wc;
|
||||
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
|
||||
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
|
||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||
|
||||
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
uv_barrier_destroy(&wc.barrier);
|
||||
|
||||
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serial_worker(void* data) {
|
||||
uv_barrier_t* barrier;
|
||||
|
||||
barrier = data;
|
||||
if (uv_barrier_wait(barrier) > 0)
|
||||
uv_barrier_destroy(barrier);
|
||||
|
||||
uv_sleep(100); /* Wait a bit before terminating. */
|
||||
}
|
||||
|
||||
/* Ensure that uv_barrier_wait returns positive only after all threads have
|
||||
* exited the barrier. If this value is returned too early and the barrier is
|
||||
* destroyed prematurely, then this test may see a crash. */
|
||||
TEST_IMPL(barrier_serial_thread) {
|
||||
uv_thread_t threads[4];
|
||||
uv_barrier_t barrier;
|
||||
unsigned i;
|
||||
|
||||
ASSERT(0 == uv_barrier_init(&barrier, ARRAY_SIZE(threads) + 1));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(threads); ++i)
|
||||
ASSERT(0 == uv_thread_create(&threads[i], serial_worker, &barrier));
|
||||
|
||||
if (uv_barrier_wait(&barrier) > 0)
|
||||
uv_barrier_destroy(&barrier);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(threads); ++i)
|
||||
ASSERT(0 == uv_thread_join(&threads[i]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Single thread uv_barrier_wait should return correct return value. */
|
||||
TEST_IMPL(barrier_serial_thread_single) {
|
||||
uv_barrier_t barrier;
|
||||
|
||||
ASSERT(0 == uv_barrier_init(&barrier, 1));
|
||||
ASSERT(0 < uv_barrier_wait(&barrier));
|
||||
uv_barrier_destroy(&barrier);
|
||||
return 0;
|
||||
}
|
77
deps/libuv/test/test-callback-order.c
vendored
Normal file
77
deps/libuv/test/test-callback-order.c
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static int idle_cb_called;
|
||||
static int timer_cb_called;
|
||||
|
||||
static uv_idle_t idle_handle;
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
|
||||
/* idle_cb should run before timer_cb */
|
||||
static void idle_cb(uv_idle_t* handle) {
|
||||
ASSERT(idle_cb_called == 0);
|
||||
ASSERT(timer_cb_called == 0);
|
||||
uv_idle_stop(handle);
|
||||
idle_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(idle_cb_called == 1);
|
||||
ASSERT(timer_cb_called == 0);
|
||||
uv_timer_stop(handle);
|
||||
timer_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void next_tick(uv_idle_t* handle) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
uv_idle_stop(handle);
|
||||
uv_idle_init(loop, &idle_handle);
|
||||
uv_idle_start(&idle_handle, idle_cb);
|
||||
uv_timer_init(loop, &timer_handle);
|
||||
uv_timer_start(&timer_handle, timer_cb, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(callback_order) {
|
||||
uv_loop_t* loop;
|
||||
uv_idle_t idle;
|
||||
|
||||
loop = uv_default_loop();
|
||||
uv_idle_init(loop, &idle);
|
||||
uv_idle_start(&idle, next_tick);
|
||||
|
||||
ASSERT(idle_cb_called == 0);
|
||||
ASSERT(timer_cb_called == 0);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(idle_cb_called == 1);
|
||||
ASSERT(timer_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
204
deps/libuv/test/test-callback-stack.c
vendored
Normal file
204
deps/libuv/test/test-callback-stack.c
vendored
Normal file
@ -0,0 +1,204 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: Add explanation of why we want on_close to be called from fresh
|
||||
* stack.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
static const char MESSAGE[] = "Failure is for the weak. Everyone dies alone.";
|
||||
|
||||
static uv_tcp_t client;
|
||||
static uv_timer_t timer;
|
||||
static uv_connect_t connect_req;
|
||||
static uv_write_t write_req;
|
||||
static uv_shutdown_t shutdown_req;
|
||||
|
||||
static int nested = 0;
|
||||
static int close_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
static int write_cb_called = 0;
|
||||
static int timer_cb_called = 0;
|
||||
static int bytes_received = 0;
|
||||
static int shutdown_cb_called = 0;
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
buf->len = size;
|
||||
buf->base = malloc(size);
|
||||
ASSERT(buf->base != NULL);
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(nested == 0 && "close_cb must be called from a fresh stack");
|
||||
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void shutdown_cb(uv_shutdown_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
ASSERT(nested == 0 && "shutdown_cb must be called from a fresh stack");
|
||||
|
||||
shutdown_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
|
||||
ASSERT(nested == 0 && "read_cb must be called from a fresh stack");
|
||||
|
||||
printf("Read. nread == %d\n", (int)nread);
|
||||
free(buf->base);
|
||||
|
||||
if (nread == 0) {
|
||||
return;
|
||||
|
||||
} else if (nread < 0) {
|
||||
ASSERT(nread == UV_EOF);
|
||||
|
||||
nested++;
|
||||
uv_close((uv_handle_t*)tcp, close_cb);
|
||||
nested--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_received += nread;
|
||||
|
||||
/* We call shutdown here because when bytes_received == sizeof MESSAGE there
|
||||
* will be no more data sent nor received, so here it would be possible for a
|
||||
* backend to call shutdown_cb immediately and *not* from a fresh stack. */
|
||||
if (bytes_received == sizeof MESSAGE) {
|
||||
nested++;
|
||||
|
||||
puts("Shutdown");
|
||||
|
||||
if (uv_shutdown(&shutdown_req, (uv_stream_t*)tcp, shutdown_cb)) {
|
||||
FATAL("uv_shutdown failed");
|
||||
}
|
||||
nested--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(handle == &timer);
|
||||
ASSERT(nested == 0 && "timer_cb must be called from a fresh stack");
|
||||
|
||||
puts("Timeout complete. Now read data...");
|
||||
|
||||
nested++;
|
||||
if (uv_read_start((uv_stream_t*)&client, alloc_cb, read_cb)) {
|
||||
FATAL("uv_read_start failed");
|
||||
}
|
||||
nested--;
|
||||
|
||||
timer_cb_called++;
|
||||
|
||||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void write_cb(uv_write_t* req, int status) {
|
||||
int r;
|
||||
|
||||
ASSERT(status == 0);
|
||||
ASSERT(nested == 0 && "write_cb must be called from a fresh stack");
|
||||
|
||||
puts("Data written. 500ms timeout...");
|
||||
|
||||
/* After the data has been sent, we're going to wait for a while, then start
|
||||
* reading. This makes us certain that the message has been echoed back to
|
||||
* our receive buffer when we start reading. This maximizes the temptation
|
||||
* for the backend to use dirty stack for calling read_cb. */
|
||||
nested++;
|
||||
r = uv_timer_init(uv_default_loop(), &timer);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&timer, timer_cb, 500, 0);
|
||||
ASSERT(r == 0);
|
||||
nested--;
|
||||
|
||||
write_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
uv_buf_t buf;
|
||||
|
||||
puts("Connected. Write some data to echo server...");
|
||||
|
||||
ASSERT(status == 0);
|
||||
ASSERT(nested == 0 && "connect_cb must be called from a fresh stack");
|
||||
|
||||
nested++;
|
||||
|
||||
buf.base = (char*) &MESSAGE;
|
||||
buf.len = sizeof MESSAGE;
|
||||
|
||||
if (uv_write(&write_req, (uv_stream_t*)req->handle, &buf, 1, write_cb)) {
|
||||
FATAL("uv_write failed");
|
||||
}
|
||||
|
||||
nested--;
|
||||
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(callback_stack) {
|
||||
struct sockaddr_in addr;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
if (uv_tcp_init(uv_default_loop(), &client)) {
|
||||
FATAL("uv_tcp_init failed");
|
||||
}
|
||||
|
||||
puts("Connecting...");
|
||||
|
||||
nested++;
|
||||
|
||||
if (uv_tcp_connect(&connect_req,
|
||||
&client,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb)) {
|
||||
FATAL("uv_tcp_connect failed");
|
||||
}
|
||||
nested--;
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(nested == 0);
|
||||
ASSERT(connect_cb_called == 1 && "connect_cb must be called exactly once");
|
||||
ASSERT(write_cb_called == 1 && "write_cb must be called exactly once");
|
||||
ASSERT(timer_cb_called == 1 && "timer_cb must be called exactly once");
|
||||
ASSERT(bytes_received == sizeof MESSAGE);
|
||||
ASSERT(shutdown_cb_called == 1 && "shutdown_cb must be called exactly once");
|
||||
ASSERT(close_cb_called == 2 && "close_cb must be called exactly twice");
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
80
deps/libuv/test/test-close-fd.c
vendored
Normal file
80
deps/libuv/test/test-close-fd.c
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static unsigned int read_cb_called;
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
static char slab[1];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
|
||||
switch (++read_cb_called) {
|
||||
case 1:
|
||||
ASSERT(nread == 1);
|
||||
uv_read_stop(handle);
|
||||
break;
|
||||
case 2:
|
||||
ASSERT(nread == UV_EOF);
|
||||
uv_close((uv_handle_t *) handle, NULL);
|
||||
break;
|
||||
default:
|
||||
ASSERT(!"read_cb_called > 2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_IMPL(close_fd) {
|
||||
uv_pipe_t pipe_handle;
|
||||
int fd[2];
|
||||
|
||||
ASSERT(0 == pipe(fd));
|
||||
ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0));
|
||||
ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0]));
|
||||
fd[0] = -1; /* uv_pipe_open() takes ownership of the file descriptor. */
|
||||
ASSERT(1 == write(fd[1], "", 1));
|
||||
ASSERT(0 == close(fd[1]));
|
||||
fd[1] = -1;
|
||||
ASSERT(0 == uv_read_start((uv_stream_t *) &pipe_handle, alloc_cb, read_cb));
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(1 == read_cb_called);
|
||||
ASSERT(0 == uv_is_active((const uv_handle_t *) &pipe_handle));
|
||||
ASSERT(0 == uv_read_start((uv_stream_t *) &pipe_handle, alloc_cb, read_cb));
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(2 == read_cb_called);
|
||||
ASSERT(0 != uv_is_closing((const uv_handle_t *) &pipe_handle));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
|
||||
|
||||
#endif /* !_WIN32 */
|
80
deps/libuv/test/test-close-order.c
vendored
Normal file
80
deps/libuv/test/test-close-order.c
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static int check_cb_called;
|
||||
static int timer_cb_called;
|
||||
static int close_cb_called;
|
||||
|
||||
static uv_check_t check_handle;
|
||||
static uv_timer_t timer_handle1;
|
||||
static uv_timer_t timer_handle2;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
/* check_cb should run before any close_cb */
|
||||
static void check_cb(uv_check_t* handle) {
|
||||
ASSERT(check_cb_called == 0);
|
||||
ASSERT(timer_cb_called == 1);
|
||||
ASSERT(close_cb_called == 0);
|
||||
uv_close((uv_handle_t*) handle, close_cb);
|
||||
uv_close((uv_handle_t*) &timer_handle2, close_cb);
|
||||
check_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
uv_close((uv_handle_t*) handle, close_cb);
|
||||
timer_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(close_order) {
|
||||
uv_loop_t* loop;
|
||||
loop = uv_default_loop();
|
||||
|
||||
uv_check_init(loop, &check_handle);
|
||||
uv_check_start(&check_handle, check_cb);
|
||||
uv_timer_init(loop, &timer_handle1);
|
||||
uv_timer_start(&timer_handle1, timer_cb, 0, 0);
|
||||
uv_timer_init(loop, &timer_handle2);
|
||||
uv_timer_start(&timer_handle2, timer_cb, 100000, 0);
|
||||
|
||||
ASSERT(check_cb_called == 0);
|
||||
ASSERT(close_cb_called == 0);
|
||||
ASSERT(timer_cb_called == 0);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(check_cb_called == 1);
|
||||
ASSERT(close_cb_called == 3);
|
||||
ASSERT(timer_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
267
deps/libuv/test/test-condvar.c
vendored
Normal file
267
deps/libuv/test/test-condvar.c
vendored
Normal file
@ -0,0 +1,267 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
struct worker_config;
|
||||
|
||||
typedef void (*signal_func)(struct worker_config* c, int* flag);
|
||||
typedef int (*wait_func)(struct worker_config* c, const int* flag);
|
||||
|
||||
typedef struct worker_config {
|
||||
uv_sem_t sem_waiting; /* post before waiting. */
|
||||
uv_sem_t sem_signaled; /* post after signaling. */
|
||||
uv_mutex_t mutex;
|
||||
uv_cond_t cond;
|
||||
int use_broadcast;
|
||||
int posted_1;
|
||||
int posted_2;
|
||||
signal_func signal_cond;
|
||||
wait_func wait_cond;
|
||||
} worker_config;
|
||||
|
||||
void worker_config_init(worker_config* wc,
|
||||
int use_broadcast,
|
||||
signal_func signal_f,
|
||||
wait_func wait_f) {
|
||||
/* Wipe. */
|
||||
memset(wc, 0, sizeof(*wc));
|
||||
|
||||
/* Copy vars. */
|
||||
wc->signal_cond = signal_f;
|
||||
wc->wait_cond = wait_f;
|
||||
wc->use_broadcast = use_broadcast;
|
||||
|
||||
/* Init. */
|
||||
ASSERT(0 == uv_sem_init(&wc->sem_waiting, 0));
|
||||
ASSERT(0 == uv_sem_init(&wc->sem_signaled, 0));
|
||||
ASSERT(0 == uv_cond_init(&wc->cond));
|
||||
ASSERT(0 == uv_mutex_init(&wc->mutex));
|
||||
}
|
||||
|
||||
void worker_config_destroy(worker_config* wc) {
|
||||
uv_mutex_destroy(&wc->mutex);
|
||||
uv_cond_destroy(&wc->cond);
|
||||
uv_sem_destroy(&wc->sem_signaled);
|
||||
uv_sem_destroy(&wc->sem_waiting);
|
||||
}
|
||||
|
||||
/* arg is a worker_config.
|
||||
* Call signal_cond then wait_cond.
|
||||
* Partner should call wait then signal. */
|
||||
static void worker(void* arg) {
|
||||
worker_config* c = arg;
|
||||
c->signal_cond(c, &c->posted_1);
|
||||
c->wait_cond(c, &c->posted_2);
|
||||
}
|
||||
|
||||
/* 1. Signal a waiting waiter.
|
||||
* 2. Tell waiter we finished. */
|
||||
static void condvar_signal(worker_config* c, int* flag) {
|
||||
/* Wait until waiter holds mutex and is preparing to wait. */
|
||||
uv_sem_wait(&c->sem_waiting);
|
||||
|
||||
/* Make sure waiter has begun waiting. */
|
||||
uv_mutex_lock(&c->mutex);
|
||||
|
||||
/* Help waiter differentiate between spurious and legitimate wakeup. */
|
||||
ASSERT(*flag == 0);
|
||||
*flag = 1;
|
||||
|
||||
if (c->use_broadcast)
|
||||
uv_cond_broadcast(&c->cond);
|
||||
else
|
||||
uv_cond_signal(&c->cond);
|
||||
|
||||
uv_mutex_unlock(&c->mutex);
|
||||
|
||||
/* Done signaling. */
|
||||
uv_sem_post(&c->sem_signaled);
|
||||
}
|
||||
|
||||
/* 1. Wait on a signal.
|
||||
* 2. Ensure that the signaler finished. */
|
||||
static int condvar_wait(worker_config* c, const int* flag) {
|
||||
uv_mutex_lock(&c->mutex);
|
||||
|
||||
/* Tell signal'er that I am waiting. */
|
||||
uv_sem_post(&c->sem_waiting);
|
||||
|
||||
/* Wait until I get a non-spurious signal. */
|
||||
do {
|
||||
uv_cond_wait(&c->cond, &c->mutex);
|
||||
} while (*flag == 0);
|
||||
ASSERT(*flag == 1);
|
||||
|
||||
uv_mutex_unlock(&c->mutex);
|
||||
|
||||
/* Wait for my signal'er to finish. */
|
||||
uv_sem_wait(&c->sem_signaled);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* uv_cond_wait: One thread signals, the other waits. */
|
||||
TEST_IMPL(condvar_1) {
|
||||
worker_config wc;
|
||||
uv_thread_t thread;
|
||||
|
||||
/* Helper signal-then-wait. */
|
||||
worker_config_init(&wc, 0, condvar_signal, condvar_wait);
|
||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||
|
||||
/* We wait-then-signal. */
|
||||
ASSERT(0 == wc.wait_cond(&wc, &wc.posted_1));
|
||||
wc.signal_cond(&wc, &wc.posted_2);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
worker_config_destroy(&wc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* uv_cond_wait: One thread broadcasts, the other waits. */
|
||||
TEST_IMPL(condvar_2) {
|
||||
worker_config wc;
|
||||
uv_thread_t thread;
|
||||
|
||||
/* Helper to signal-then-wait. */
|
||||
worker_config_init(&wc, 1, condvar_signal, condvar_wait);
|
||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||
|
||||
/* We wait-then-signal. */
|
||||
ASSERT(0 == wc.wait_cond(&wc, &wc.posted_1));
|
||||
wc.signal_cond(&wc, &wc.posted_2);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
worker_config_destroy(&wc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 1. Wait on a signal (hopefully not timeout, else we'll hang).
|
||||
* 2. Ensure that the signaler finished. */
|
||||
static int condvar_timedwait(worker_config* c, const int* flag) {
|
||||
int r;
|
||||
|
||||
r = 0;
|
||||
|
||||
uv_mutex_lock(&c->mutex);
|
||||
|
||||
/* Tell signal'er that I am waiting. */
|
||||
uv_sem_post(&c->sem_waiting);
|
||||
|
||||
/* Wait until I get a non-spurious signal. */
|
||||
do {
|
||||
r = uv_cond_timedwait(&c->cond, &c->mutex, (uint64_t)(1 * 1e9)); /* 1 s */
|
||||
ASSERT(r == 0); /* Should not time out. */
|
||||
} while (*flag == 0);
|
||||
ASSERT(*flag == 1);
|
||||
|
||||
uv_mutex_unlock(&c->mutex);
|
||||
|
||||
/* Wait for my signal'er to finish. */
|
||||
uv_sem_wait(&c->sem_signaled);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* uv_cond_timedwait: One thread signals, the other timedwaits. */
|
||||
TEST_IMPL(condvar_3) {
|
||||
worker_config wc;
|
||||
uv_thread_t thread;
|
||||
|
||||
/* Helper to signal-then-wait. */
|
||||
worker_config_init(&wc, 0, condvar_signal, condvar_timedwait);
|
||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||
|
||||
/* We wait-then-signal. */
|
||||
wc.wait_cond(&wc, &wc.posted_1);
|
||||
wc.signal_cond(&wc, &wc.posted_2);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
worker_config_destroy(&wc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* uv_cond_timedwait: One thread broadcasts, the other waits. */
|
||||
TEST_IMPL(condvar_4) {
|
||||
worker_config wc;
|
||||
uv_thread_t thread;
|
||||
|
||||
/* Helper to signal-then-wait. */
|
||||
worker_config_init(&wc, 1, condvar_signal, condvar_timedwait);
|
||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||
|
||||
/* We wait-then-signal. */
|
||||
wc.wait_cond(&wc, &wc.posted_1);
|
||||
wc.signal_cond(&wc, &wc.posted_2);
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
worker_config_destroy(&wc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* uv_cond_timedwait: One thread waits, no signal. Timeout should be delivered. */
|
||||
TEST_IMPL(condvar_5) {
|
||||
worker_config wc;
|
||||
int r;
|
||||
/* ns */
|
||||
uint64_t before;
|
||||
uint64_t after;
|
||||
uint64_t elapsed;
|
||||
uint64_t timeout;
|
||||
|
||||
timeout = 100 * 1000 * 1000; /* 100 ms in ns */
|
||||
|
||||
/* Mostly irrelevant. We need cond and mutex initialized. */
|
||||
worker_config_init(&wc, 0, NULL, NULL);
|
||||
|
||||
uv_mutex_lock(&wc.mutex);
|
||||
|
||||
/* We wait.
|
||||
* No signaler, so this will only return if timeout is delivered. */
|
||||
before = uv_hrtime();
|
||||
r = uv_cond_timedwait(&wc.cond, &wc.mutex, timeout);
|
||||
after = uv_hrtime();
|
||||
|
||||
uv_mutex_unlock(&wc.mutex);
|
||||
|
||||
/* It timed out. */
|
||||
ASSERT(r == UV_ETIMEDOUT);
|
||||
|
||||
/* It must have taken at least timeout, modulo system timer ticks.
|
||||
* But it should not take too much longer.
|
||||
* cf. MSDN docs:
|
||||
* https://msdn.microsoft.com/en-us/library/ms687069(VS.85).aspx */
|
||||
elapsed = after - before;
|
||||
ASSERT(0.75 * timeout <= elapsed); /* 1.0 too large for Windows. */
|
||||
ASSERT(elapsed <= 5.0 * timeout); /* MacOS has reported failures up to 1.75. */
|
||||
|
||||
worker_config_destroy(&wc);
|
||||
|
||||
return 0;
|
||||
}
|
63
deps/libuv/test/test-connect-unspecified.c
vendored
Normal file
63
deps/libuv/test/test-connect-unspecified.c
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static void connect_4(uv_connect_t* req, int status) {
|
||||
ASSERT(status != UV_EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
static void connect_6(uv_connect_t* req, int status) {
|
||||
ASSERT(status != UV_EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
TEST_IMPL(connect_unspecified) {
|
||||
uv_loop_t* loop;
|
||||
uv_tcp_t socket4;
|
||||
struct sockaddr_in addr4;
|
||||
uv_connect_t connect4;
|
||||
uv_tcp_t socket6;
|
||||
struct sockaddr_in6 addr6;
|
||||
uv_connect_t connect6;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
ASSERT(uv_tcp_init(loop, &socket4) == 0);
|
||||
ASSERT(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr4) == 0);
|
||||
ASSERT(uv_tcp_connect(&connect4,
|
||||
&socket4,
|
||||
(const struct sockaddr*) &addr4,
|
||||
connect_4) == 0);
|
||||
|
||||
if (can_ipv6()) {
|
||||
ASSERT(uv_tcp_init(loop, &socket6) == 0);
|
||||
ASSERT(uv_ip6_addr("::", TEST_PORT, &addr6) == 0);
|
||||
ASSERT(uv_tcp_connect(&connect6,
|
||||
&socket6,
|
||||
(const struct sockaddr*) &addr6,
|
||||
connect_6) == 0);
|
||||
}
|
||||
|
||||
ASSERT(uv_run(loop, UV_RUN_DEFAULT) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
161
deps/libuv/test/test-connection-fail.c
vendored
Normal file
161
deps/libuv/test/test-connection-fail.c
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static uv_tcp_t tcp;
|
||||
static uv_connect_t req;
|
||||
static int connect_cb_calls;
|
||||
static int close_cb_calls;
|
||||
|
||||
static uv_timer_t timer;
|
||||
static int timer_close_cb_calls;
|
||||
static int timer_cb_calls;
|
||||
|
||||
|
||||
static void on_close(uv_handle_t* handle) {
|
||||
close_cb_calls++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_close_cb(uv_handle_t* handle) {
|
||||
timer_close_cb_calls++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
timer_cb_calls++;
|
||||
|
||||
/*
|
||||
* These are the important asserts. The connection callback has been made,
|
||||
* but libuv hasn't automatically closed the socket. The user must
|
||||
* uv_close the handle manually.
|
||||
*/
|
||||
ASSERT(close_cb_calls == 0);
|
||||
ASSERT(connect_cb_calls == 1);
|
||||
|
||||
/* Close the tcp handle. */
|
||||
uv_close((uv_handle_t*)&tcp, on_close);
|
||||
|
||||
/* Close the timer. */
|
||||
uv_close((uv_handle_t*)handle, timer_close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void on_connect_with_close(uv_connect_t *req, int status) {
|
||||
ASSERT((uv_stream_t*) &tcp == req->handle);
|
||||
ASSERT(status == UV_ECONNREFUSED);
|
||||
connect_cb_calls++;
|
||||
|
||||
ASSERT(close_cb_calls == 0);
|
||||
uv_close((uv_handle_t*)req->handle, on_close);
|
||||
}
|
||||
|
||||
|
||||
static void on_connect_without_close(uv_connect_t *req, int status) {
|
||||
ASSERT(status == UV_ECONNREFUSED);
|
||||
connect_cb_calls++;
|
||||
|
||||
uv_timer_start(&timer, timer_cb, 100, 0);
|
||||
|
||||
ASSERT(close_cb_calls == 0);
|
||||
}
|
||||
|
||||
|
||||
static void connection_fail(uv_connect_cb connect_cb) {
|
||||
struct sockaddr_in client_addr, server_addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &client_addr));
|
||||
|
||||
/* There should be no servers listening on this port. */
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
|
||||
|
||||
/* Try to connect to the server and do NUM_PINGS ping-pongs. */
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp);
|
||||
ASSERT(!r);
|
||||
|
||||
/* We are never doing multiple reads/connects at a time anyway. so these
|
||||
* handles can be pre-initialized. */
|
||||
ASSERT(0 == uv_tcp_bind(&tcp, (const struct sockaddr*) &client_addr, 0));
|
||||
|
||||
r = uv_tcp_connect(&req,
|
||||
&tcp,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
connect_cb);
|
||||
ASSERT(!r);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(connect_cb_calls == 1);
|
||||
ASSERT(close_cb_calls == 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This test attempts to connect to a port where no server is running. We
|
||||
* expect an error.
|
||||
*/
|
||||
TEST_IMPL(connection_fail) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
connection_fail(on_connect_with_close);
|
||||
|
||||
ASSERT(timer_close_cb_calls == 0);
|
||||
ASSERT(timer_cb_calls == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This test is the same as the first except it check that the close
|
||||
* callback of the tcp handle hasn't been made after the failed connection
|
||||
* attempt.
|
||||
*/
|
||||
TEST_IMPL(connection_fail_doesnt_auto_close) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
int r;
|
||||
|
||||
r = uv_timer_init(uv_default_loop(), &timer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
connection_fail(on_connect_without_close);
|
||||
|
||||
ASSERT(timer_close_cb_calls == 1);
|
||||
ASSERT(timer_cb_calls == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
57
deps/libuv/test/test-cwd-and-chdir.c
vendored
Normal file
57
deps/libuv/test/test-cwd-and-chdir.c
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
#define PATHMAX 4096
|
||||
|
||||
TEST_IMPL(cwd_and_chdir) {
|
||||
char buffer_orig[PATHMAX];
|
||||
char buffer_new[PATHMAX];
|
||||
size_t size1;
|
||||
size_t size2;
|
||||
int err;
|
||||
|
||||
size1 = 1;
|
||||
err = uv_cwd(buffer_orig, &size1);
|
||||
ASSERT(err == UV_ENOBUFS);
|
||||
ASSERT(size1 > 1);
|
||||
|
||||
size1 = sizeof buffer_orig;
|
||||
err = uv_cwd(buffer_orig, &size1);
|
||||
ASSERT(err == 0);
|
||||
ASSERT(size1 > 0);
|
||||
ASSERT(buffer_orig[size1] != '/');
|
||||
|
||||
err = uv_chdir(buffer_orig);
|
||||
ASSERT(err == 0);
|
||||
|
||||
size2 = sizeof buffer_new;
|
||||
err = uv_cwd(buffer_new, &size2);
|
||||
ASSERT(err == 0);
|
||||
|
||||
ASSERT(size1 == size2);
|
||||
ASSERT(strcmp(buffer_orig, buffer_new) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
59
deps/libuv/test/test-default-loop-close.c
vendored
Normal file
59
deps/libuv/test/test-default-loop-close.c
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
static int timer_cb_called;
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* timer) {
|
||||
timer_cb_called++;
|
||||
uv_close((uv_handle_t*) timer, NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(default_loop_close) {
|
||||
uv_loop_t* loop;
|
||||
uv_timer_t timer_handle;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(loop != NULL);
|
||||
|
||||
ASSERT(0 == uv_timer_init(loop, &timer_handle));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1, 0));
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT(1 == timer_cb_called);
|
||||
ASSERT(0 == uv_loop_close(loop));
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(loop != NULL);
|
||||
|
||||
ASSERT(0 == uv_timer_init(loop, &timer_handle));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1, 0));
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT(2 == timer_cb_called);
|
||||
ASSERT(0 == uv_loop_close(loop));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
189
deps/libuv/test/test-delayed-accept.c
vendored
Normal file
189
deps/libuv/test/test-delayed-accept.c
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int connection_cb_called = 0;
|
||||
static int do_accept_called = 0;
|
||||
static int close_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
buf->base = malloc(size);
|
||||
buf->len = size;
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
free(handle);
|
||||
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void do_accept(uv_timer_t* timer_handle) {
|
||||
uv_tcp_t* server;
|
||||
uv_tcp_t* accepted_handle = (uv_tcp_t*)malloc(sizeof *accepted_handle);
|
||||
int r;
|
||||
|
||||
ASSERT(timer_handle != NULL);
|
||||
ASSERT(accepted_handle != NULL);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), accepted_handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
server = (uv_tcp_t*)timer_handle->data;
|
||||
r = uv_accept((uv_stream_t*)server, (uv_stream_t*)accepted_handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
do_accept_called++;
|
||||
|
||||
/* Immediately close the accepted handle. */
|
||||
uv_close((uv_handle_t*)accepted_handle, close_cb);
|
||||
|
||||
/* After accepting the two clients close the server handle */
|
||||
if (do_accept_called == 2) {
|
||||
uv_close((uv_handle_t*)server, close_cb);
|
||||
}
|
||||
|
||||
/* Dispose the timer. */
|
||||
uv_close((uv_handle_t*)timer_handle, close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* tcp, int status) {
|
||||
int r;
|
||||
uv_timer_t* timer_handle;
|
||||
|
||||
ASSERT(status == 0);
|
||||
|
||||
timer_handle = (uv_timer_t*)malloc(sizeof *timer_handle);
|
||||
ASSERT(timer_handle != NULL);
|
||||
|
||||
/* Accept the client after 1 second */
|
||||
r = uv_timer_init(uv_default_loop(), timer_handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
timer_handle->data = tcp;
|
||||
|
||||
r = uv_timer_start(timer_handle, do_accept, 1000, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
connection_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void start_server(void) {
|
||||
struct sockaddr_in addr;
|
||||
uv_tcp_t* server = (uv_tcp_t*)malloc(sizeof *server);
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
ASSERT(server != NULL);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), server);
|
||||
ASSERT(r == 0);
|
||||
r = uv_tcp_bind(server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)server, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
|
||||
/* The server will not send anything, it should close gracefully. */
|
||||
|
||||
if (buf->base) {
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
if (nread >= 0) {
|
||||
ASSERT(nread == 0);
|
||||
} else {
|
||||
ASSERT(tcp != NULL);
|
||||
ASSERT(nread == UV_EOF);
|
||||
uv_close((uv_handle_t*)tcp, close_cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
int r;
|
||||
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
|
||||
/* Not that the server will send anything, but otherwise we'll never know
|
||||
* when the server closes the connection. */
|
||||
r = uv_read_start((uv_stream_t*)(req->handle), alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
connect_cb_called++;
|
||||
|
||||
free(req);
|
||||
}
|
||||
|
||||
|
||||
static void client_connect(void) {
|
||||
struct sockaddr_in addr;
|
||||
uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof *client);
|
||||
uv_connect_t* connect_req = malloc(sizeof *connect_req);
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
ASSERT(client != NULL);
|
||||
ASSERT(connect_req != NULL);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_connect(connect_req,
|
||||
client,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_IMPL(delayed_accept) {
|
||||
start_server();
|
||||
|
||||
client_connect();
|
||||
client_connect();
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(connection_cb_called == 2);
|
||||
ASSERT(do_accept_called == 2);
|
||||
ASSERT(connect_cb_called == 2);
|
||||
ASSERT(close_cb_called == 7);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
61
deps/libuv/test/test-dlerror.c
vendored
Normal file
61
deps/libuv/test/test-dlerror.c
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
TEST_IMPL(dlerror) {
|
||||
const char* path = "test/fixtures/load_error.node";
|
||||
const char* dlerror_no_error = "no error";
|
||||
const char* msg;
|
||||
uv_lib_t lib;
|
||||
int r;
|
||||
|
||||
lib.errmsg = NULL;
|
||||
lib.handle = NULL;
|
||||
msg = uv_dlerror(&lib);
|
||||
ASSERT(msg != NULL);
|
||||
ASSERT(strstr(msg, dlerror_no_error) != NULL);
|
||||
|
||||
r = uv_dlopen(path, &lib);
|
||||
ASSERT(r == -1);
|
||||
|
||||
msg = uv_dlerror(&lib);
|
||||
ASSERT(msg != NULL);
|
||||
#if !defined(__OpenBSD__) && !defined(__QNX__)
|
||||
ASSERT(strstr(msg, path) != NULL);
|
||||
#endif
|
||||
ASSERT(strstr(msg, dlerror_no_error) == NULL);
|
||||
|
||||
/* Should return the same error twice in a row. */
|
||||
msg = uv_dlerror(&lib);
|
||||
ASSERT(msg != NULL);
|
||||
#if !defined(__OpenBSD__) && !defined(__QNX__)
|
||||
ASSERT(strstr(msg, path) != NULL);
|
||||
#endif
|
||||
ASSERT(strstr(msg, dlerror_no_error) == NULL);
|
||||
|
||||
uv_dlclose(&lib);
|
||||
|
||||
return 0;
|
||||
}
|
94
deps/libuv/test/test-eintr-handling.c
vendored
Normal file
94
deps/libuv/test/test-eintr-handling.c
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/* Copyright libuv project 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"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
TEST_IMPL(eintr_handling) {
|
||||
RETURN_SKIP("Test not implemented on Windows.");
|
||||
}
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static uv_loop_t* loop;
|
||||
static uv_fs_t read_req;
|
||||
static uv_buf_t iov;
|
||||
|
||||
static char buf[32];
|
||||
static char test_buf[] = "test-buffer\n";
|
||||
int pipe_fds[2];
|
||||
|
||||
struct thread_ctx {
|
||||
uv_barrier_t barrier;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static void thread_main(void* arg) {
|
||||
int nwritten;
|
||||
ASSERT(0 == kill(getpid(), SIGUSR1));
|
||||
|
||||
do
|
||||
nwritten = write(pipe_fds[1], test_buf, sizeof(test_buf));
|
||||
while (nwritten == -1 && errno == EINTR);
|
||||
|
||||
ASSERT(nwritten == sizeof(test_buf));
|
||||
}
|
||||
|
||||
static void sig_func(uv_signal_t* handle, int signum) {
|
||||
uv_signal_stop(handle);
|
||||
}
|
||||
|
||||
TEST_IMPL(eintr_handling) {
|
||||
struct thread_ctx ctx;
|
||||
uv_thread_t thread;
|
||||
uv_signal_t signal;
|
||||
int nread;
|
||||
|
||||
iov = uv_buf_init(buf, sizeof(buf));
|
||||
loop = uv_default_loop();
|
||||
|
||||
ASSERT(0 == uv_signal_init(loop, &signal));
|
||||
ASSERT(0 == uv_signal_start(&signal, sig_func, SIGUSR1));
|
||||
|
||||
ASSERT(0 == pipe(pipe_fds));
|
||||
ASSERT(0 == uv_thread_create(&thread, thread_main, &ctx));
|
||||
|
||||
nread = uv_fs_read(loop, &read_req, pipe_fds[0], &iov, 1, -1, NULL);
|
||||
|
||||
ASSERT(nread == sizeof(test_buf));
|
||||
ASSERT(0 == strcmp(buf, test_buf));
|
||||
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
|
||||
ASSERT(0 == close(pipe_fds[0]));
|
||||
ASSERT(0 == close(pipe_fds[1]));
|
||||
uv_close((uv_handle_t*) &signal, NULL);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !_WIN32 */
|
139
deps/libuv/test/test-embed.c
vendored
Normal file
139
deps/libuv/test/test-embed.c
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef HAVE_KQUEUE
|
||||
# if defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# define HAVE_KQUEUE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EPOLL
|
||||
# if defined(__linux__)
|
||||
# define HAVE_EPOLL 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
|
||||
|
||||
#if defined(HAVE_KQUEUE)
|
||||
# include <sys/types.h>
|
||||
# include <sys/event.h>
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EPOLL)
|
||||
# include <sys/epoll.h>
|
||||
#endif
|
||||
|
||||
static uv_thread_t embed_thread;
|
||||
static uv_sem_t embed_sem;
|
||||
static uv_timer_t embed_timer;
|
||||
static uv_async_t embed_async;
|
||||
static volatile int embed_closed;
|
||||
|
||||
static int embed_timer_called;
|
||||
|
||||
|
||||
static void embed_thread_runner(void* arg) {
|
||||
int r;
|
||||
int fd;
|
||||
int timeout;
|
||||
|
||||
while (!embed_closed) {
|
||||
fd = uv_backend_fd(uv_default_loop());
|
||||
timeout = uv_backend_timeout(uv_default_loop());
|
||||
|
||||
do {
|
||||
#if defined(HAVE_KQUEUE)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = timeout / 1000;
|
||||
ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||
r = kevent(fd, NULL, 0, NULL, 0, &ts);
|
||||
#elif defined(HAVE_EPOLL)
|
||||
{
|
||||
struct epoll_event ev;
|
||||
r = epoll_wait(fd, &ev, 1, timeout);
|
||||
}
|
||||
#endif
|
||||
} while (r == -1 && errno == EINTR);
|
||||
uv_async_send(&embed_async);
|
||||
uv_sem_wait(&embed_sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void embed_cb(uv_async_t* async) {
|
||||
uv_run(uv_default_loop(), UV_RUN_ONCE);
|
||||
|
||||
uv_sem_post(&embed_sem);
|
||||
}
|
||||
|
||||
|
||||
static void embed_timer_cb(uv_timer_t* timer) {
|
||||
embed_timer_called++;
|
||||
embed_closed = 1;
|
||||
|
||||
uv_close((uv_handle_t*) &embed_async, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
TEST_IMPL(embed) {
|
||||
#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
|
||||
uv_loop_t external;
|
||||
|
||||
ASSERT(0 == uv_loop_init(&external));
|
||||
|
||||
embed_timer_called = 0;
|
||||
embed_closed = 0;
|
||||
|
||||
uv_async_init(&external, &embed_async, embed_cb);
|
||||
|
||||
/* Start timer in default loop */
|
||||
uv_timer_init(uv_default_loop(), &embed_timer);
|
||||
uv_timer_start(&embed_timer, embed_timer_cb, 250, 0);
|
||||
|
||||
/* Start worker that will interrupt external loop */
|
||||
uv_sem_init(&embed_sem, 0);
|
||||
uv_thread_create(&embed_thread, embed_thread_runner, NULL);
|
||||
|
||||
/* But run external loop */
|
||||
uv_run(&external, UV_RUN_DEFAULT);
|
||||
|
||||
uv_thread_join(&embed_thread);
|
||||
uv_loop_close(&external);
|
||||
|
||||
ASSERT(embed_timer_called == 1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
121
deps/libuv/test/test-emfile.c
vendored
Normal file
121
deps/libuv/test/test-emfile.c
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void connection_cb(uv_stream_t* server_handle, int status);
|
||||
static void connect_cb(uv_connect_t* req, int status);
|
||||
|
||||
static const int maxfd = 31;
|
||||
static unsigned connect_cb_called;
|
||||
static uv_tcp_t server_handle;
|
||||
static uv_tcp_t client_handle;
|
||||
|
||||
|
||||
TEST_IMPL(emfile) {
|
||||
struct sockaddr_in addr;
|
||||
struct rlimit limits;
|
||||
uv_connect_t connect_req;
|
||||
uv_loop_t* loop;
|
||||
int first_fd;
|
||||
#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 this OS");
|
||||
#endif
|
||||
|
||||
/* Lower the file descriptor limit and use up all fds save one. */
|
||||
limits.rlim_cur = limits.rlim_max = maxfd + 1;
|
||||
if (setrlimit(RLIMIT_NOFILE, &limits)) {
|
||||
ASSERT(errno == EPERM); /* Valgrind blocks the setrlimit() call. */
|
||||
RETURN_SKIP("setrlimit(RLIMIT_NOFILE) failed, running under valgrind?");
|
||||
}
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
ASSERT(0 == uv_tcp_init(loop, &server_handle));
|
||||
ASSERT(0 == uv_tcp_init(loop, &client_handle));
|
||||
ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0));
|
||||
ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb));
|
||||
|
||||
/* Remember the first one so we can clean up afterwards. */
|
||||
do
|
||||
first_fd = dup(0);
|
||||
while (first_fd == -1 && errno == EINTR);
|
||||
ASSERT(first_fd > 0);
|
||||
|
||||
while (dup(0) != -1 || errno == EINTR);
|
||||
ASSERT(errno == EMFILE);
|
||||
close(maxfd);
|
||||
|
||||
/* Now connect and use up the last available file descriptor. The EMFILE
|
||||
* handling logic in src/unix/stream.c should ensure that connect_cb() runs
|
||||
* whereas connection_cb() should *not* run.
|
||||
*/
|
||||
ASSERT(0 == uv_tcp_connect(&connect_req,
|
||||
&client_handle,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb));
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT(1 == connect_cb_called);
|
||||
|
||||
/* Close the dups again. Ignore errors in the unlikely event that the
|
||||
* file descriptors were not contiguous.
|
||||
*/
|
||||
while (first_fd < maxfd) {
|
||||
close(first_fd);
|
||||
first_fd += 1;
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* server_handle, int status) {
|
||||
ASSERT(0 && "connection_cb should not be called.");
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
/* |status| should equal 0 because the connection should have been accepted,
|
||||
* it's just that the server immediately closes it again.
|
||||
*/
|
||||
ASSERT(0 == status);
|
||||
connect_cb_called += 1;
|
||||
uv_close((uv_handle_t*) &server_handle, NULL);
|
||||
uv_close((uv_handle_t*) &client_handle, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
|
||||
|
||||
#endif /* !_WIN32 */
|
170
deps/libuv/test/test-env-vars.c
vendored
Normal file
170
deps/libuv/test/test-env-vars.c
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
/* Copyright libuv 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 <string.h>
|
||||
|
||||
#define BUF_SIZE 10
|
||||
|
||||
TEST_IMPL(env_vars) {
|
||||
const char* name = "UV_TEST_FOO";
|
||||
const char* name2 = "UV_TEST_FOO2";
|
||||
char buf[BUF_SIZE];
|
||||
size_t size;
|
||||
int i, r, envcount, found, found_win_special;
|
||||
uv_env_item_t* envitems;
|
||||
|
||||
/* Reject invalid inputs when setting an environment variable */
|
||||
r = uv_os_setenv(NULL, "foo");
|
||||
ASSERT(r == UV_EINVAL);
|
||||
r = uv_os_setenv(name, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
r = uv_os_setenv(NULL, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
/* Reject invalid inputs when retrieving an environment variable */
|
||||
size = BUF_SIZE;
|
||||
r = uv_os_getenv(NULL, buf, &size);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
r = uv_os_getenv(name, NULL, &size);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
r = uv_os_getenv(name, buf, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
size = 0;
|
||||
r = uv_os_getenv(name, buf, &size);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
/* Reject invalid inputs when deleting an environment variable */
|
||||
r = uv_os_unsetenv(NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
/* Successfully set an environment variable */
|
||||
r = uv_os_setenv(name, "123456789");
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Successfully read an environment variable */
|
||||
size = BUF_SIZE;
|
||||
buf[0] = '\0';
|
||||
r = uv_os_getenv(name, buf, &size);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(strcmp(buf, "123456789") == 0);
|
||||
ASSERT(size == BUF_SIZE - 1);
|
||||
|
||||
/* Return UV_ENOBUFS if the buffer cannot hold the environment variable */
|
||||
size = BUF_SIZE - 1;
|
||||
buf[0] = '\0';
|
||||
r = uv_os_getenv(name, buf, &size);
|
||||
ASSERT(r == UV_ENOBUFS);
|
||||
ASSERT(size == BUF_SIZE);
|
||||
|
||||
/* Successfully delete an environment variable */
|
||||
r = uv_os_unsetenv(name);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Return UV_ENOENT retrieving an environment variable that does not exist */
|
||||
r = uv_os_getenv(name, buf, &size);
|
||||
ASSERT(r == UV_ENOENT);
|
||||
|
||||
/* Successfully delete an environment variable that does not exist */
|
||||
r = uv_os_unsetenv(name);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Setting an environment variable to the empty string does not delete it. */
|
||||
r = uv_os_setenv(name, "");
|
||||
ASSERT(r == 0);
|
||||
size = BUF_SIZE;
|
||||
r = uv_os_getenv(name, buf, &size);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(size == 0);
|
||||
ASSERT(strlen(buf) == 0);
|
||||
|
||||
/* Check getting all env variables. */
|
||||
r = uv_os_setenv(name, "123456789");
|
||||
ASSERT(r == 0);
|
||||
r = uv_os_setenv(name2, "");
|
||||
ASSERT(r == 0);
|
||||
#ifdef _WIN32
|
||||
/* Create a special environment variable on Windows in case there are no
|
||||
naturally occurring ones. */
|
||||
r = uv_os_setenv("=Z:", "\\");
|
||||
ASSERT(r == 0);
|
||||
#endif
|
||||
|
||||
r = uv_os_environ(&envitems, &envcount);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(envcount > 0);
|
||||
|
||||
found = 0;
|
||||
found_win_special = 0;
|
||||
|
||||
for (i = 0; i < envcount; i++) {
|
||||
/* printf("Env: %s = %s\n", envitems[i].name, envitems[i].value); */
|
||||
if (strcmp(envitems[i].name, name) == 0) {
|
||||
found++;
|
||||
ASSERT(strcmp(envitems[i].value, "123456789") == 0);
|
||||
} else if (strcmp(envitems[i].name, name2) == 0) {
|
||||
found++;
|
||||
ASSERT(strlen(envitems[i].value) == 0);
|
||||
} else if (envitems[i].name[0] == '=') {
|
||||
found_win_special++;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(found == 2);
|
||||
#ifdef _WIN32
|
||||
ASSERT(found_win_special > 0);
|
||||
#endif
|
||||
|
||||
uv_os_free_environ(envitems, envcount);
|
||||
|
||||
r = uv_os_unsetenv(name);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_os_unsetenv(name2);
|
||||
ASSERT(r == 0);
|
||||
|
||||
for (i = 1; i <= 4; i++) {
|
||||
size_t n;
|
||||
char* p;
|
||||
|
||||
n = i * 32768;
|
||||
size = n + 1;
|
||||
|
||||
p = malloc(size);
|
||||
ASSERT_NOT_NULL(p);
|
||||
|
||||
memset(p, 'x', n);
|
||||
p[n] = '\0';
|
||||
|
||||
ASSERT_EQ(0, uv_os_setenv(name, p));
|
||||
ASSERT_EQ(0, uv_os_getenv(name, p, &size));
|
||||
ASSERT_EQ(n, size);
|
||||
|
||||
for (n = 0; n < size; n++)
|
||||
ASSERT_EQ('x', p[n]);
|
||||
|
||||
ASSERT_EQ(0, uv_os_unsetenv(name));
|
||||
free(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
79
deps/libuv/test/test-error.c
vendored
Normal file
79
deps/libuv/test/test-error.c
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#if defined(_WIN32)
|
||||
# include "../src/win/winapi.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
* Synthetic errors (errors that originate from within libuv, not the system)
|
||||
* should produce sensible error messages when run through uv_strerror().
|
||||
*
|
||||
* See https://github.com/joyent/libuv/issues/210
|
||||
*/
|
||||
TEST_IMPL(error_message) {
|
||||
char buf[32];
|
||||
|
||||
/* Cop out. Can't do proper checks on systems with
|
||||
* i18n-ized error messages...
|
||||
*/
|
||||
if (strcmp(uv_strerror(0), "Success") != 0) {
|
||||
printf("i18n error messages detected, skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ASSERT(strstr(uv_strerror(UV_EINVAL), "Success") == NULL);
|
||||
ASSERT(strcmp(uv_strerror(1337), "Unknown error") == 0);
|
||||
ASSERT(strcmp(uv_strerror(-1337), "Unknown error") == 0);
|
||||
|
||||
ASSERT(strstr(uv_strerror_r(UV_EINVAL, buf, sizeof(buf)), "Success") == NULL);
|
||||
ASSERT(strstr(uv_strerror_r(1337, buf, sizeof(buf)), "1337") != NULL);
|
||||
ASSERT(strstr(uv_strerror_r(-1337, buf, sizeof(buf)), "-1337") != NULL);
|
||||
|
||||
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;
|
||||
}
|
29
deps/libuv/test/test-fail-always.c
vendored
Normal file
29
deps/libuv/test/test-fail-always.c
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
|
||||
|
||||
TEST_IMPL(fail_always) {
|
||||
/* This test always fails. It is used to test the test runner. */
|
||||
FATAL("Yes, it always fails");
|
||||
return 2;
|
||||
}
|
683
deps/libuv/test/test-fork.c
vendored
Normal file
683
deps/libuv/test/test-fork.c
vendored
Normal file
@ -0,0 +1,683 @@
|
||||
/* Copyright libuv project 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.
|
||||
*/
|
||||
|
||||
/* These tests are Unix only. */
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static int timer_cb_called;
|
||||
static int socket_cb_called;
|
||||
|
||||
static void timer_cb(uv_timer_t* timer) {
|
||||
timer_cb_called++;
|
||||
uv_close((uv_handle_t*) timer, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int socket_cb_read_fd;
|
||||
static int socket_cb_read_size;
|
||||
static char socket_cb_read_buf[1024];
|
||||
|
||||
|
||||
static void socket_cb(uv_poll_t* poll, int status, int events) {
|
||||
ssize_t cnt;
|
||||
socket_cb_called++;
|
||||
ASSERT(0 == status);
|
||||
printf("Socket cb got events %d\n", events);
|
||||
ASSERT(UV_READABLE == (events & UV_READABLE));
|
||||
if (socket_cb_read_fd) {
|
||||
cnt = read(socket_cb_read_fd, socket_cb_read_buf, socket_cb_read_size);
|
||||
ASSERT(cnt == socket_cb_read_size);
|
||||
}
|
||||
uv_close((uv_handle_t*) poll, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void run_timer_loop_once(void) {
|
||||
uv_loop_t* loop;
|
||||
uv_timer_t timer_handle;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
timer_cb_called = 0; /* Reset for the child. */
|
||||
|
||||
ASSERT(0 == uv_timer_init(loop, &timer_handle));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1, 0));
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT(1 == timer_cb_called);
|
||||
}
|
||||
|
||||
|
||||
static void assert_wait_child(pid_t child_pid) {
|
||||
pid_t waited_pid;
|
||||
int child_stat;
|
||||
|
||||
waited_pid = waitpid(child_pid, &child_stat, 0);
|
||||
printf("Waited pid is %d with status %d\n", waited_pid, child_stat);
|
||||
if (waited_pid == -1) {
|
||||
perror("Failed to wait");
|
||||
}
|
||||
ASSERT(child_pid == waited_pid);
|
||||
ASSERT(WIFEXITED(child_stat)); /* Clean exit, not a signal. */
|
||||
ASSERT(!WIFSIGNALED(child_stat));
|
||||
ASSERT(0 == WEXITSTATUS(child_stat));
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_timer) {
|
||||
/* Timers continue to work after we fork. */
|
||||
|
||||
/*
|
||||
* Establish the loop before we fork to make sure that it
|
||||
* has state to get reset after the fork.
|
||||
*/
|
||||
pid_t child_pid;
|
||||
|
||||
run_timer_loop_once();
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
|
||||
if (child_pid != 0) {
|
||||
/* parent */
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* child */
|
||||
ASSERT(0 == uv_loop_fork(uv_default_loop()));
|
||||
run_timer_loop_once();
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_socketpair) {
|
||||
/* A socket opened in the parent and accept'd in the
|
||||
child works after a fork. */
|
||||
pid_t child_pid;
|
||||
int socket_fds[2];
|
||||
uv_poll_t poll_handle;
|
||||
|
||||
/* Prime the loop. */
|
||||
run_timer_loop_once();
|
||||
|
||||
ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds));
|
||||
|
||||
/* Create the server watcher in the parent, use it in the child. */
|
||||
ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, socket_fds[0]));
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
|
||||
if (child_pid != 0) {
|
||||
/* parent */
|
||||
ASSERT(3 == send(socket_fds[1], "hi\n", 3, 0));
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* child */
|
||||
ASSERT(0 == uv_loop_fork(uv_default_loop()));
|
||||
ASSERT(0 == socket_cb_called);
|
||||
ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, socket_cb));
|
||||
printf("Going to run the loop in the child\n");
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(1 == socket_cb_called);
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_socketpair_started) {
|
||||
/* A socket opened in the parent and accept'd in the
|
||||
child works after a fork, even if the watcher was already
|
||||
started, and then stopped in the parent. */
|
||||
pid_t child_pid;
|
||||
int socket_fds[2];
|
||||
int sync_pipe[2];
|
||||
char sync_buf[1];
|
||||
uv_poll_t poll_handle;
|
||||
|
||||
ASSERT(0 == pipe(sync_pipe));
|
||||
|
||||
/* Prime the loop. */
|
||||
run_timer_loop_once();
|
||||
|
||||
ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds));
|
||||
|
||||
/* Create and start the server watcher in the parent, use it in the child. */
|
||||
ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, socket_fds[0]));
|
||||
ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, socket_cb));
|
||||
|
||||
/* Run the loop AFTER the poll watcher is registered to make sure it
|
||||
gets passed to the kernel. Use NOWAIT and expect a non-zero
|
||||
return to prove the poll watcher is active.
|
||||
*/
|
||||
ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_NOWAIT));
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
|
||||
if (child_pid != 0) {
|
||||
/* parent */
|
||||
ASSERT(0 == uv_poll_stop(&poll_handle));
|
||||
uv_close((uv_handle_t*)&poll_handle, NULL);
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(0 == socket_cb_called);
|
||||
ASSERT(1 == write(sync_pipe[1], "1", 1)); /* alert child */
|
||||
ASSERT(3 == send(socket_fds[1], "hi\n", 3, 0));
|
||||
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(0 == socket_cb_called);
|
||||
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* child */
|
||||
printf("Child is %d\n", getpid());
|
||||
ASSERT(1 == read(sync_pipe[0], sync_buf, 1)); /* wait for parent */
|
||||
ASSERT(0 == uv_loop_fork(uv_default_loop()));
|
||||
ASSERT(0 == socket_cb_called);
|
||||
|
||||
printf("Going to run the loop in the child\n");
|
||||
socket_cb_read_fd = socket_fds[0];
|
||||
socket_cb_read_size = 3;
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(1 == socket_cb_called);
|
||||
printf("Buf %s\n", socket_cb_read_buf);
|
||||
ASSERT(0 == strcmp("hi\n", socket_cb_read_buf));
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int fork_signal_cb_called;
|
||||
|
||||
void fork_signal_to_child_cb(uv_signal_t* handle, int signum)
|
||||
{
|
||||
fork_signal_cb_called = signum;
|
||||
uv_close((uv_handle_t*)handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_signal_to_child) {
|
||||
/* A signal handler installed before forking
|
||||
is run only in the child when the child is signalled. */
|
||||
uv_signal_t signal_handle;
|
||||
pid_t child_pid;
|
||||
int sync_pipe[2];
|
||||
char sync_buf[1];
|
||||
|
||||
fork_signal_cb_called = 0; /* reset */
|
||||
|
||||
ASSERT(0 == pipe(sync_pipe));
|
||||
|
||||
/* Prime the loop. */
|
||||
run_timer_loop_once();
|
||||
|
||||
ASSERT(0 == uv_signal_init(uv_default_loop(), &signal_handle));
|
||||
ASSERT(0 == uv_signal_start(&signal_handle, fork_signal_to_child_cb, SIGUSR1));
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
|
||||
if (child_pid != 0) {
|
||||
/* parent */
|
||||
ASSERT(1 == read(sync_pipe[0], sync_buf, 1)); /* wait for child */
|
||||
ASSERT(0 == kill(child_pid, SIGUSR1));
|
||||
/* Run the loop, make sure we don't get the signal. */
|
||||
printf("Running loop in parent\n");
|
||||
uv_unref((uv_handle_t*)&signal_handle);
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT));
|
||||
ASSERT(0 == fork_signal_cb_called);
|
||||
printf("Waiting for child in parent\n");
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* child */
|
||||
ASSERT(0 == uv_loop_fork(uv_default_loop()));
|
||||
ASSERT(1 == write(sync_pipe[1], "1", 1)); /* alert parent */
|
||||
/* Get the signal. */
|
||||
ASSERT(0 != uv_loop_alive(uv_default_loop()));
|
||||
printf("Running loop in child\n");
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
|
||||
ASSERT(SIGUSR1 == fork_signal_cb_called);
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_signal_to_child_closed) {
|
||||
/* A signal handler installed before forking
|
||||
doesn't get received anywhere when the child is signalled,
|
||||
but isnt running the loop. */
|
||||
uv_signal_t signal_handle;
|
||||
pid_t child_pid;
|
||||
int sync_pipe[2];
|
||||
int sync_pipe2[2];
|
||||
char sync_buf[1];
|
||||
int r;
|
||||
|
||||
fork_signal_cb_called = 0; /* reset */
|
||||
|
||||
ASSERT(0 == pipe(sync_pipe));
|
||||
ASSERT(0 == pipe(sync_pipe2));
|
||||
|
||||
/* Prime the loop. */
|
||||
run_timer_loop_once();
|
||||
|
||||
ASSERT(0 == uv_signal_init(uv_default_loop(), &signal_handle));
|
||||
ASSERT(0 == uv_signal_start(&signal_handle, fork_signal_to_child_cb, SIGUSR1));
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
|
||||
if (child_pid != 0) {
|
||||
/* parent */
|
||||
printf("Wating on child in parent\n");
|
||||
ASSERT(1 == read(sync_pipe[0], sync_buf, 1)); /* wait for child */
|
||||
printf("Parent killing child\n");
|
||||
ASSERT(0 == kill(child_pid, SIGUSR1));
|
||||
/* Run the loop, make sure we don't get the signal. */
|
||||
printf("Running loop in parent\n");
|
||||
uv_unref((uv_handle_t*)&signal_handle); /* so the loop can exit;
|
||||
we *shouldn't* get any signals */
|
||||
run_timer_loop_once(); /* but while we share a pipe, we do, so
|
||||
have something active. */
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
|
||||
printf("Signal in parent %d\n", fork_signal_cb_called);
|
||||
ASSERT(0 == fork_signal_cb_called);
|
||||
ASSERT(1 == write(sync_pipe2[1], "1", 1)); /* alert child */
|
||||
printf("Waiting for child in parent\n");
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* Child. Our signal handler should still be installed. */
|
||||
ASSERT(0 == uv_loop_fork(uv_default_loop()));
|
||||
printf("Checking loop in child\n");
|
||||
ASSERT(0 != uv_loop_alive(uv_default_loop()));
|
||||
printf("Alerting parent in child\n");
|
||||
ASSERT(1 == write(sync_pipe[1], "1", 1)); /* alert parent */
|
||||
/* Don't run the loop. Wait for the parent to call us */
|
||||
printf("Waiting on parent in child\n");
|
||||
/* Wait for parent. read may fail if the parent tripped an ASSERT
|
||||
and exited, so this ASSERT is generous.
|
||||
*/
|
||||
r = read(sync_pipe2[0], sync_buf, 1);
|
||||
ASSERT(-1 <= r && r <= 1);
|
||||
ASSERT(0 == fork_signal_cb_called);
|
||||
printf("Exiting child \n");
|
||||
/* Note that we're deliberately not running the loop
|
||||
* in the child, and also not closing the loop's handles,
|
||||
* so the child default loop can't be cleanly closed.
|
||||
* We need to explicitly exit to avoid an automatic failure
|
||||
* in that case.
|
||||
*/
|
||||
exit(0);
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void create_file(const char* name) {
|
||||
int r;
|
||||
uv_file file;
|
||||
uv_fs_t req;
|
||||
|
||||
r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
file = r;
|
||||
uv_fs_req_cleanup(&req);
|
||||
r = uv_fs_close(NULL, &req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
|
||||
|
||||
static void touch_file(const char* name) {
|
||||
int r;
|
||||
uv_file file;
|
||||
uv_fs_t req;
|
||||
uv_buf_t buf;
|
||||
|
||||
r = uv_fs_open(NULL, &req, name, O_RDWR, 0, NULL);
|
||||
ASSERT(r >= 0);
|
||||
file = r;
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
buf = uv_buf_init("foo", 4);
|
||||
r = uv_fs_write(NULL, &req, file, &buf, 1, -1, NULL);
|
||||
ASSERT(r >= 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_close(NULL, &req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
|
||||
|
||||
static int timer_cb_touch_called;
|
||||
|
||||
static void timer_cb_touch(uv_timer_t* timer) {
|
||||
uv_close((uv_handle_t*)timer, NULL);
|
||||
touch_file("watch_file");
|
||||
timer_cb_touch_called++;
|
||||
}
|
||||
|
||||
|
||||
static int fs_event_cb_called;
|
||||
|
||||
static void fs_event_cb_file_current_dir(uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
int events,
|
||||
int status) {
|
||||
ASSERT(fs_event_cb_called == 0);
|
||||
++fs_event_cb_called;
|
||||
ASSERT(status == 0);
|
||||
#if defined(__APPLE__) || defined(__linux__)
|
||||
ASSERT(strcmp(filename, "watch_file") == 0);
|
||||
#else
|
||||
ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
|
||||
#endif
|
||||
uv_close((uv_handle_t*)handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void assert_watch_file_current_dir(uv_loop_t* const loop, int file_or_dir) {
|
||||
uv_timer_t timer;
|
||||
uv_fs_event_t fs_event;
|
||||
int r;
|
||||
|
||||
/* Setup */
|
||||
remove("watch_file");
|
||||
create_file("watch_file");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
/* watching a dir is the only way to get fsevents involved on apple
|
||||
platforms */
|
||||
r = uv_fs_event_start(&fs_event,
|
||||
fs_event_cb_file_current_dir,
|
||||
file_or_dir == 1 ? "." : "watch_file",
|
||||
0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_timer_start(&timer, timer_cb_touch, 100, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(timer_cb_touch_called == 0);
|
||||
ASSERT(fs_event_cb_called == 0);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(timer_cb_touch_called == 1);
|
||||
ASSERT(fs_event_cb_called == 1);
|
||||
|
||||
/* Cleanup */
|
||||
remove("watch_file");
|
||||
fs_event_cb_called = 0;
|
||||
timer_cb_touch_called = 0;
|
||||
uv_run(loop, UV_RUN_DEFAULT); /* flush pending closes */
|
||||
}
|
||||
|
||||
|
||||
#define FS_TEST_FILE 0
|
||||
#define FS_TEST_DIR 1
|
||||
|
||||
static int _do_fork_fs_events_child(int file_or_dir) {
|
||||
/* basic fsevents work in the child after a fork */
|
||||
pid_t child_pid;
|
||||
uv_loop_t loop;
|
||||
|
||||
/* Watch in the parent, prime the loop and/or threads. */
|
||||
assert_watch_file_current_dir(uv_default_loop(), file_or_dir);
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
|
||||
if (child_pid != 0) {
|
||||
/* parent */
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* child */
|
||||
/* Ee can watch in a new loop, but dirs only work
|
||||
if we're on linux. */
|
||||
#if defined(__APPLE__)
|
||||
file_or_dir = FS_TEST_FILE;
|
||||
#endif
|
||||
printf("Running child\n");
|
||||
uv_loop_init(&loop);
|
||||
printf("Child first watch\n");
|
||||
assert_watch_file_current_dir(&loop, file_or_dir);
|
||||
ASSERT(0 == uv_loop_close(&loop));
|
||||
printf("Child second watch default loop\n");
|
||||
/* Ee can watch in the default loop. */
|
||||
ASSERT(0 == uv_loop_fork(uv_default_loop()));
|
||||
/* On some platforms (OS X), if we don't update the time now,
|
||||
* the timer cb fires before the event loop enters uv__io_poll,
|
||||
* instead of after, meaning we don't see the change! This may be
|
||||
* a general race.
|
||||
*/
|
||||
uv_update_time(uv_default_loop());
|
||||
assert_watch_file_current_dir(uv_default_loop(), file_or_dir);
|
||||
|
||||
/* We can close the parent loop successfully too. This is
|
||||
especially important on Apple platforms where if we're not
|
||||
careful trying to touch the CFRunLoop, even just to shut it
|
||||
down, that we allocated in the FS_TEST_DIR case would crash. */
|
||||
ASSERT(0 == uv_loop_close(uv_default_loop()));
|
||||
|
||||
printf("Exiting child \n");
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_fs_events_child) {
|
||||
#if defined(NO_FS_EVENTS)
|
||||
RETURN_SKIP(NO_FS_EVENTS);
|
||||
#endif
|
||||
return _do_fork_fs_events_child(FS_TEST_FILE);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_fs_events_child_dir) {
|
||||
#if defined(NO_FS_EVENTS)
|
||||
RETURN_SKIP(NO_FS_EVENTS);
|
||||
#endif
|
||||
#if defined(__APPLE__) || defined (__linux__)
|
||||
return _do_fork_fs_events_child(FS_TEST_DIR);
|
||||
#else
|
||||
/* You can't spin up a cfrunloop thread on an apple platform
|
||||
and then fork. See
|
||||
http://objectivistc.tumblr.com/post/16187948939/you-must-exec-a-core-foundation-fork-safety-tale
|
||||
*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fork_fs_events_file_parent_child) {
|
||||
#if defined(NO_FS_EVENTS)
|
||||
RETURN_SKIP(NO_FS_EVENTS);
|
||||
#endif
|
||||
#if defined(__sun) || defined(_AIX) || defined(__MVS__)
|
||||
/* It's not possible to implement this without additional
|
||||
* bookkeeping on SunOS. For AIX it is possible, but has to be
|
||||
* written. See https://github.com/libuv/libuv/pull/846#issuecomment-287170420
|
||||
* TODO: On z/OS, we need to open another message queue and subscribe to the
|
||||
* same events as the parent.
|
||||
*/
|
||||
return 0;
|
||||
#else
|
||||
/* Establishing a started fs events watcher in the parent should
|
||||
still work in the child. */
|
||||
uv_timer_t timer;
|
||||
uv_fs_event_t fs_event;
|
||||
int r;
|
||||
pid_t child_pid;
|
||||
uv_loop_t* loop;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* Setup */
|
||||
remove("watch_file");
|
||||
create_file("watch_file");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fs_event_start(&fs_event,
|
||||
fs_event_cb_file_current_dir,
|
||||
"watch_file",
|
||||
0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
if (child_pid != 0) {
|
||||
/* parent */
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* child */
|
||||
printf("Running child\n");
|
||||
ASSERT(0 == uv_loop_fork(loop));
|
||||
|
||||
r = uv_timer_start(&timer, timer_cb_touch, 100, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(timer_cb_touch_called == 0);
|
||||
ASSERT(fs_event_cb_called == 0);
|
||||
printf("Running loop in child \n");
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(timer_cb_touch_called == 1);
|
||||
ASSERT(fs_event_cb_called == 1);
|
||||
|
||||
/* Cleanup */
|
||||
remove("watch_file");
|
||||
fs_event_cb_called = 0;
|
||||
timer_cb_touch_called = 0;
|
||||
uv_run(loop, UV_RUN_DEFAULT); /* Flush pending closes. */
|
||||
}
|
||||
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int work_cb_count;
|
||||
static int after_work_cb_count;
|
||||
|
||||
|
||||
static void work_cb(uv_work_t* req) {
|
||||
work_cb_count++;
|
||||
}
|
||||
|
||||
|
||||
static void after_work_cb(uv_work_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
after_work_cb_count++;
|
||||
}
|
||||
|
||||
|
||||
static void assert_run_work(uv_loop_t* const loop) {
|
||||
uv_work_t work_req;
|
||||
int r;
|
||||
|
||||
ASSERT(work_cb_count == 0);
|
||||
ASSERT(after_work_cb_count == 0);
|
||||
printf("Queue in %d\n", getpid());
|
||||
r = uv_queue_work(loop, &work_req, work_cb, after_work_cb);
|
||||
ASSERT(r == 0);
|
||||
printf("Running in %d\n", getpid());
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(work_cb_count == 1);
|
||||
ASSERT(after_work_cb_count == 1);
|
||||
|
||||
/* cleanup */
|
||||
work_cb_count = 0;
|
||||
after_work_cb_count = 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef __MVS__
|
||||
TEST_IMPL(fork_threadpool_queue_work_simple) {
|
||||
/* The threadpool works in a child process. */
|
||||
|
||||
pid_t child_pid;
|
||||
uv_loop_t loop;
|
||||
|
||||
/* Prime the pool and default loop. */
|
||||
assert_run_work(uv_default_loop());
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT(child_pid != -1);
|
||||
|
||||
if (child_pid != 0) {
|
||||
/* Parent. We can still run work. */
|
||||
assert_run_work(uv_default_loop());
|
||||
assert_wait_child(child_pid);
|
||||
} else {
|
||||
/* Child. We can work in a new loop. */
|
||||
printf("Running child in %d\n", getpid());
|
||||
uv_loop_init(&loop);
|
||||
printf("Child first watch\n");
|
||||
assert_run_work(&loop);
|
||||
uv_loop_close(&loop);
|
||||
printf("Child second watch default loop\n");
|
||||
/* We can work in the default loop. */
|
||||
ASSERT(0 == uv_loop_fork(uv_default_loop()));
|
||||
assert_run_work(uv_default_loop());
|
||||
printf("Exiting child \n");
|
||||
}
|
||||
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
#endif /* !__MVS__ */
|
||||
|
||||
#else
|
||||
|
||||
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
|
||||
|
||||
#endif /* !_WIN32 */
|
217
deps/libuv/test/test-fs-copyfile.c
vendored
Normal file
217
deps/libuv/test/test-fs-copyfile.c
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
/* Copyright libuv project 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"
|
||||
|
||||
#if defined(__unix__) || defined(__POSIX__) || \
|
||||
defined(__APPLE__) || defined(__sun) || \
|
||||
defined(_AIX) || defined(__MVS__) || \
|
||||
defined(__HAIKU__) || defined(__QNX__)
|
||||
#include <unistd.h> /* unlink, etc. */
|
||||
#else
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
# define unlink _unlink
|
||||
#endif
|
||||
|
||||
static const char fixture[] = "test/fixtures/load_error.node";
|
||||
static const char dst[] = "test_file_dst";
|
||||
static int result_check_count;
|
||||
|
||||
|
||||
static void fail_cb(uv_fs_t* req) {
|
||||
FATAL("fail_cb should not have been called");
|
||||
}
|
||||
|
||||
static void handle_result(uv_fs_t* req) {
|
||||
uv_fs_t stat_req;
|
||||
uint64_t size;
|
||||
uint64_t mode;
|
||||
int r;
|
||||
|
||||
ASSERT(req->fs_type == UV_FS_COPYFILE);
|
||||
ASSERT(req->result == 0);
|
||||
|
||||
/* Verify that the file size and mode are the same. */
|
||||
r = uv_fs_stat(NULL, &stat_req, req->path, NULL);
|
||||
ASSERT(r == 0);
|
||||
size = stat_req.statbuf.st_size;
|
||||
mode = stat_req.statbuf.st_mode;
|
||||
uv_fs_req_cleanup(&stat_req);
|
||||
r = uv_fs_stat(NULL, &stat_req, dst, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(stat_req.statbuf.st_size == size);
|
||||
ASSERT(stat_req.statbuf.st_mode == mode);
|
||||
uv_fs_req_cleanup(&stat_req);
|
||||
uv_fs_req_cleanup(req);
|
||||
result_check_count++;
|
||||
}
|
||||
|
||||
|
||||
static void touch_file(const char* name, unsigned int size) {
|
||||
uv_file file;
|
||||
uv_fs_t req;
|
||||
uv_buf_t buf;
|
||||
int r;
|
||||
unsigned int i;
|
||||
|
||||
r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IWUSR | S_IRUSR, NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
ASSERT(r >= 0);
|
||||
file = r;
|
||||
|
||||
buf = uv_buf_init("a", 1);
|
||||
|
||||
/* Inefficient but simple. */
|
||||
for (i = 0; i < size; i++) {
|
||||
r = uv_fs_write(NULL, &req, file, &buf, 1, i, NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
ASSERT(r >= 0);
|
||||
}
|
||||
|
||||
r = uv_fs_close(NULL, &req, file, NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_copyfile) {
|
||||
const char src[] = "test_file_src";
|
||||
uv_loop_t* loop;
|
||||
uv_fs_t req;
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* Fails with EINVAL if bad flags are passed. */
|
||||
r = uv_fs_copyfile(NULL, &req, src, dst, -1, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* Fails with ENOENT if source does not exist. */
|
||||
unlink(src);
|
||||
unlink(dst);
|
||||
r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
|
||||
ASSERT(req.result == UV_ENOENT);
|
||||
ASSERT(r == UV_ENOENT);
|
||||
uv_fs_req_cleanup(&req);
|
||||
/* The destination should not exist. */
|
||||
r = uv_fs_stat(NULL, &req, dst, NULL);
|
||||
ASSERT(r != 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* Succeeds if src and dst files are identical. */
|
||||
touch_file(src, 12);
|
||||
r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
/* Verify that the src file did not get truncated. */
|
||||
r = uv_fs_stat(NULL, &req, src, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_EQ(req.statbuf.st_size, 12);
|
||||
uv_fs_req_cleanup(&req);
|
||||
unlink(src);
|
||||
|
||||
/* Copies file synchronously. Creates new file. */
|
||||
unlink(dst);
|
||||
r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
handle_result(&req);
|
||||
|
||||
/* Copies a file of size zero. */
|
||||
unlink(dst);
|
||||
touch_file(src, 0);
|
||||
r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
handle_result(&req);
|
||||
|
||||
/* Copies file synchronously. Overwrites existing file. */
|
||||
r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
handle_result(&req);
|
||||
|
||||
/* Fails to overwrites existing file. */
|
||||
r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_EXCL, NULL);
|
||||
ASSERT(r == UV_EEXIST);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* Truncates when an existing destination is larger than the source file. */
|
||||
touch_file(src, 1);
|
||||
r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
handle_result(&req);
|
||||
|
||||
/* Copies a larger file. */
|
||||
unlink(dst);
|
||||
touch_file(src, 4096 * 2);
|
||||
r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
handle_result(&req);
|
||||
unlink(src);
|
||||
|
||||
/* Copies file asynchronously */
|
||||
unlink(dst);
|
||||
r = uv_fs_copyfile(loop, &req, fixture, dst, 0, handle_result);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(result_check_count == 5);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(result_check_count == 6);
|
||||
|
||||
/* If the flags are invalid, the loop should not be kept open */
|
||||
unlink(dst);
|
||||
r = uv_fs_copyfile(loop, &req, fixture, dst, -1, fail_cb);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
/* Copies file using UV_FS_COPYFILE_FICLONE. */
|
||||
unlink(dst);
|
||||
r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE, NULL);
|
||||
ASSERT(r == 0);
|
||||
handle_result(&req);
|
||||
|
||||
/* Copies file using UV_FS_COPYFILE_FICLONE_FORCE. */
|
||||
unlink(dst);
|
||||
r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE_FORCE,
|
||||
NULL);
|
||||
ASSERT(r <= 0);
|
||||
|
||||
if (r == 0)
|
||||
handle_result(&req);
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Copying respects permissions/mode. */
|
||||
unlink(dst);
|
||||
touch_file(dst, 0);
|
||||
chmod(dst, S_IRUSR|S_IRGRP|S_IROTH); /* Sets file mode to 444 (read-only). */
|
||||
r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
|
||||
/* On IBMi PASE, qsecofr users can overwrite read-only files */
|
||||
# ifndef __PASE__
|
||||
ASSERT(req.result == UV_EACCES);
|
||||
ASSERT(r == UV_EACCES);
|
||||
# endif
|
||||
uv_fs_req_cleanup(&req);
|
||||
#endif
|
||||
|
||||
unlink(dst); /* Cleanup */
|
||||
return 0;
|
||||
}
|
1173
deps/libuv/test/test-fs-event.c
vendored
Normal file
1173
deps/libuv/test/test-fs-event.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
133
deps/libuv/test/test-fs-fd-hash.c
vendored
Normal file
133
deps/libuv/test/test-fs-fd-hash.c
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
/* Copyright libuv project 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.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && !defined(USING_UV_SHARED)
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "../src/win/fs-fd-hash-inl.h"
|
||||
|
||||
|
||||
#define HASH_MAX 1000000000
|
||||
#define HASH_INC (1000 * UV__FD_HASH_SIZE + 2)
|
||||
#define BUCKET_MAX (UV__FD_HASH_SIZE * UV__FD_HASH_GROUP_SIZE * 10)
|
||||
#define BUCKET_INC UV__FD_HASH_SIZE
|
||||
#define FD_DIFF 9
|
||||
|
||||
|
||||
void assert_nonexistent(int fd) {
|
||||
struct uv__fd_info_s info = { 0 };
|
||||
ASSERT(!uv__fd_hash_get(fd, &info));
|
||||
ASSERT(!uv__fd_hash_remove(fd, &info));
|
||||
}
|
||||
|
||||
void assert_existent(int fd) {
|
||||
struct uv__fd_info_s info = { 0 };
|
||||
ASSERT(uv__fd_hash_get(fd, &info));
|
||||
ASSERT(info.flags == fd + FD_DIFF);
|
||||
}
|
||||
|
||||
void assert_insertion(int fd) {
|
||||
struct uv__fd_info_s info = { 0 };
|
||||
assert_nonexistent(fd);
|
||||
info.flags = fd + FD_DIFF;
|
||||
uv__fd_hash_add(fd, &info);
|
||||
assert_existent(fd);
|
||||
}
|
||||
|
||||
void assert_removal(int fd) {
|
||||
struct uv__fd_info_s info = { 0 };
|
||||
assert_existent(fd);
|
||||
uv__fd_hash_remove(fd, &info);
|
||||
ASSERT(info.flags == fd + FD_DIFF);
|
||||
assert_nonexistent(fd);
|
||||
}
|
||||
|
||||
|
||||
/* Run a function for a set of values up to a very high number */
|
||||
#define RUN_HASH(function) \
|
||||
do { \
|
||||
for (fd = 0; fd < HASH_MAX; fd += HASH_INC) { \
|
||||
function(fd); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Run a function for a set of values that will cause many collisions */
|
||||
#define RUN_COLLISIONS(function) \
|
||||
do { \
|
||||
for (fd = 1; fd < BUCKET_MAX; fd += BUCKET_INC) { \
|
||||
function(fd); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
TEST_IMPL(fs_fd_hash) {
|
||||
int fd;
|
||||
|
||||
uv__fd_hash_init();
|
||||
|
||||
/* Empty table */
|
||||
RUN_HASH(assert_nonexistent);
|
||||
RUN_COLLISIONS(assert_nonexistent);
|
||||
|
||||
/* Fill up */
|
||||
RUN_HASH(assert_insertion);
|
||||
RUN_COLLISIONS(assert_insertion);
|
||||
|
||||
/* Full */
|
||||
RUN_HASH(assert_existent);
|
||||
RUN_COLLISIONS(assert_existent);
|
||||
|
||||
/* Update */
|
||||
{
|
||||
struct uv__fd_info_s info = { 0 };
|
||||
info.flags = FD_DIFF + FD_DIFF;
|
||||
uv__fd_hash_add(0, &info);
|
||||
}
|
||||
{
|
||||
struct uv__fd_info_s info = { 0 };
|
||||
ASSERT(uv__fd_hash_get(0, &info));
|
||||
ASSERT(info.flags == FD_DIFF + FD_DIFF);
|
||||
}
|
||||
{
|
||||
/* Leave as it was, will be again tested below */
|
||||
struct uv__fd_info_s info = { 0 };
|
||||
info.flags = FD_DIFF;
|
||||
uv__fd_hash_add(0, &info);
|
||||
}
|
||||
|
||||
/* Remove all */
|
||||
RUN_HASH(assert_removal);
|
||||
RUN_COLLISIONS(assert_removal);
|
||||
|
||||
/* Empty table */
|
||||
RUN_HASH(assert_nonexistent);
|
||||
RUN_COLLISIONS(assert_nonexistent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
|
||||
|
||||
#endif /* ifndef _WIN32 */
|
435
deps/libuv/test/test-fs-open-flags.c
vendored
Normal file
435
deps/libuv/test/test-fs-open-flags.c
vendored
Normal file
@ -0,0 +1,435 @@
|
||||
/* Copyright libuv project 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.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#if defined(__unix__) || defined(__POSIX__) || \
|
||||
defined(__APPLE__) || defined(__sun) || \
|
||||
defined(_AIX) || defined(__MVS__) || \
|
||||
defined(__HAIKU__)
|
||||
# include <unistd.h> /* unlink, rmdir */
|
||||
#else
|
||||
# include <direct.h>
|
||||
# define rmdir _rmdir
|
||||
# define unlink _unlink
|
||||
#endif
|
||||
|
||||
static int flags;
|
||||
|
||||
static uv_fs_t close_req;
|
||||
static uv_fs_t mkdir_req;
|
||||
static uv_fs_t open_req;
|
||||
static uv_fs_t read_req;
|
||||
static uv_fs_t rmdir_req;
|
||||
static uv_fs_t unlink_req;
|
||||
static uv_fs_t write_req;
|
||||
|
||||
static char buf[32];
|
||||
static uv_buf_t iov;
|
||||
|
||||
/* Opening the same file multiple times quickly can cause uv_fs_open to fail
|
||||
* with EBUSY, so append an identifier to the file name for each operation */
|
||||
static int sid = 0;
|
||||
|
||||
#define FILE_NAME_SIZE 128
|
||||
static char absent_file[FILE_NAME_SIZE];
|
||||
static char empty_file[FILE_NAME_SIZE];
|
||||
static char dummy_file[FILE_NAME_SIZE];
|
||||
static char empty_dir[] = "empty_dir";
|
||||
|
||||
static void setup(void) {
|
||||
int r;
|
||||
|
||||
/* empty_dir */
|
||||
r = uv_fs_rmdir(NULL, &rmdir_req, empty_dir, NULL);
|
||||
ASSERT(r == 0 || r == UV_ENOENT);
|
||||
ASSERT(rmdir_req.result == 0 || rmdir_req.result == UV_ENOENT);
|
||||
uv_fs_req_cleanup(&rmdir_req);
|
||||
|
||||
r = uv_fs_mkdir(NULL, &mkdir_req, empty_dir, 0755, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(mkdir_req.result == 0);
|
||||
uv_fs_req_cleanup(&mkdir_req);
|
||||
}
|
||||
|
||||
static void refresh(void) {
|
||||
int r;
|
||||
|
||||
/* absent_file */
|
||||
sprintf(absent_file, "test_file_%d", sid++);
|
||||
|
||||
r = uv_fs_unlink(NULL, &unlink_req, absent_file, NULL);
|
||||
ASSERT(r == 0 || r == UV_ENOENT);
|
||||
ASSERT(unlink_req.result == 0 || unlink_req.result == UV_ENOENT);
|
||||
uv_fs_req_cleanup(&unlink_req);
|
||||
|
||||
/* empty_file */
|
||||
sprintf(empty_file, "test_file_%d", sid++);
|
||||
|
||||
r = uv_fs_open(NULL, &open_req, empty_file,
|
||||
UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
ASSERT(open_req.result >= 0);
|
||||
uv_fs_req_cleanup(&open_req);
|
||||
|
||||
r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(close_req.result == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
/* dummy_file */
|
||||
sprintf(dummy_file, "test_file_%d", sid++);
|
||||
|
||||
r = uv_fs_open(NULL, &open_req, dummy_file,
|
||||
UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
ASSERT(open_req.result >= 0);
|
||||
uv_fs_req_cleanup(&open_req);
|
||||
|
||||
iov = uv_buf_init("a", 1);
|
||||
r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == 1);
|
||||
ASSERT(write_req.result == 1);
|
||||
uv_fs_req_cleanup(&write_req);
|
||||
|
||||
r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(close_req.result == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
}
|
||||
|
||||
static void cleanup(void) {
|
||||
unlink(absent_file);
|
||||
unlink(empty_file);
|
||||
unlink(dummy_file);
|
||||
}
|
||||
|
||||
static void openFail(char *file, int error) {
|
||||
int r;
|
||||
|
||||
refresh();
|
||||
|
||||
r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r == error);
|
||||
ASSERT(open_req.result == error);
|
||||
uv_fs_req_cleanup(&open_req);
|
||||
|
||||
/* Ensure the first call does not create the file */
|
||||
r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r == error);
|
||||
ASSERT(open_req.result == error);
|
||||
uv_fs_req_cleanup(&open_req);
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
static void refreshOpen(char *file) {
|
||||
int r;
|
||||
|
||||
refresh();
|
||||
|
||||
r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
ASSERT(open_req.result >= 0);
|
||||
uv_fs_req_cleanup(&open_req);
|
||||
}
|
||||
|
||||
static void writeExpect(char *file, char *expected, int size) {
|
||||
int r;
|
||||
|
||||
refreshOpen(file);
|
||||
|
||||
iov = uv_buf_init("b", 1);
|
||||
r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == 1);
|
||||
ASSERT(write_req.result == 1);
|
||||
uv_fs_req_cleanup(&write_req);
|
||||
|
||||
iov = uv_buf_init("c", 1);
|
||||
r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == 1);
|
||||
ASSERT(write_req.result == 1);
|
||||
uv_fs_req_cleanup(&write_req);
|
||||
|
||||
r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(close_req.result == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
/* Check contents */
|
||||
r = uv_fs_open(NULL, &open_req, file, UV_FS_O_RDONLY, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
ASSERT(open_req.result >= 0);
|
||||
uv_fs_req_cleanup(&open_req);
|
||||
|
||||
iov = uv_buf_init(buf, sizeof(buf));
|
||||
r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == size);
|
||||
ASSERT(read_req.result == size);
|
||||
ASSERT(strncmp(buf, expected, size) == 0);
|
||||
uv_fs_req_cleanup(&read_req);
|
||||
|
||||
r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(close_req.result == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
static void writeFail(char *file, int error) {
|
||||
int r;
|
||||
|
||||
refreshOpen(file);
|
||||
|
||||
iov = uv_buf_init("z", 1);
|
||||
r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == error);
|
||||
ASSERT(write_req.result == error);
|
||||
uv_fs_req_cleanup(&write_req);
|
||||
|
||||
iov = uv_buf_init("z", 1);
|
||||
r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == error);
|
||||
ASSERT(write_req.result == error);
|
||||
uv_fs_req_cleanup(&write_req);
|
||||
|
||||
r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(close_req.result == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
static void readExpect(char *file, char *expected, int size) {
|
||||
int r;
|
||||
|
||||
refreshOpen(file);
|
||||
|
||||
iov = uv_buf_init(buf, sizeof(buf));
|
||||
r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == size);
|
||||
ASSERT(read_req.result == size);
|
||||
ASSERT(strncmp(buf, expected, size) == 0);
|
||||
uv_fs_req_cleanup(&read_req);
|
||||
|
||||
r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(close_req.result == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
static void readFail(char *file, int error) {
|
||||
int r;
|
||||
|
||||
refreshOpen(file);
|
||||
|
||||
iov = uv_buf_init(buf, sizeof(buf));
|
||||
r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == error);
|
||||
ASSERT(read_req.result == error);
|
||||
uv_fs_req_cleanup(&read_req);
|
||||
|
||||
iov = uv_buf_init(buf, sizeof(buf));
|
||||
r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
|
||||
ASSERT(r == error);
|
||||
ASSERT(read_req.result == error);
|
||||
uv_fs_req_cleanup(&read_req);
|
||||
|
||||
r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(close_req.result == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
static void fs_open_flags(int add_flags) {
|
||||
/* Follow the order from
|
||||
* https://github.com/nodejs/node/blob/1a96abe849/lib/internal/fs/utils.js#L329-L354
|
||||
*/
|
||||
|
||||
/* r */
|
||||
flags = add_flags | UV_FS_O_RDONLY;
|
||||
openFail(absent_file, UV_ENOENT);
|
||||
writeFail(empty_file, UV_EPERM);
|
||||
readExpect(empty_file, "", 0);
|
||||
writeFail(dummy_file, UV_EPERM);
|
||||
readExpect(dummy_file, "a", 1);
|
||||
writeFail(empty_dir, UV_EPERM);
|
||||
readFail(empty_dir, UV_EISDIR);
|
||||
|
||||
/* rs */
|
||||
flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC;
|
||||
openFail(absent_file, UV_ENOENT);
|
||||
writeFail(empty_file, UV_EPERM);
|
||||
readExpect(empty_file, "", 0);
|
||||
writeFail(dummy_file, UV_EPERM);
|
||||
readExpect(dummy_file, "a", 1);
|
||||
writeFail(empty_dir, UV_EPERM);
|
||||
readFail(empty_dir, UV_EISDIR);
|
||||
|
||||
/* r+ */
|
||||
flags = add_flags | UV_FS_O_RDWR;
|
||||
openFail(absent_file, UV_ENOENT);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readExpect(empty_file, "", 0);
|
||||
writeExpect(dummy_file, "bc", 2);
|
||||
readExpect(dummy_file, "a", 1);
|
||||
writeFail(empty_dir, UV_EISDIR);
|
||||
readFail(empty_dir, UV_EISDIR);
|
||||
|
||||
/* rs+ */
|
||||
flags = add_flags | UV_FS_O_RDWR | UV_FS_O_SYNC;
|
||||
openFail(absent_file, UV_ENOENT);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readExpect(empty_file, "", 0);
|
||||
writeExpect(dummy_file, "bc", 2);
|
||||
readExpect(dummy_file, "a", 1);
|
||||
writeFail(empty_dir, UV_EISDIR);
|
||||
readFail(empty_dir, UV_EISDIR);
|
||||
|
||||
/* w */
|
||||
flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readFail(absent_file, UV_EPERM);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readFail(empty_file, UV_EPERM);
|
||||
writeExpect(dummy_file, "bc", 2);
|
||||
readFail(dummy_file, UV_EPERM);
|
||||
openFail(empty_dir, UV_EISDIR);
|
||||
|
||||
/* wx */
|
||||
flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY |
|
||||
UV_FS_O_EXCL;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readFail(absent_file, UV_EPERM);
|
||||
openFail(empty_file, UV_EEXIST);
|
||||
openFail(dummy_file, UV_EEXIST);
|
||||
openFail(empty_dir, UV_EEXIST);
|
||||
|
||||
/* w+ */
|
||||
flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readExpect(absent_file, "", 0);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readExpect(empty_file, "", 0);
|
||||
writeExpect(dummy_file, "bc", 2);
|
||||
readExpect(dummy_file, "", 0);
|
||||
openFail(empty_dir, UV_EISDIR);
|
||||
|
||||
/* wx+ */
|
||||
flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR |
|
||||
UV_FS_O_EXCL;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readExpect(absent_file, "", 0);
|
||||
openFail(empty_file, UV_EEXIST);
|
||||
openFail(dummy_file, UV_EEXIST);
|
||||
openFail(empty_dir, UV_EEXIST);
|
||||
|
||||
/* a */
|
||||
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readFail(absent_file, UV_EPERM);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readFail(empty_file, UV_EPERM);
|
||||
writeExpect(dummy_file, "abc", 3);
|
||||
readFail(dummy_file, UV_EPERM);
|
||||
writeFail(empty_dir, UV_EISDIR);
|
||||
readFail(empty_dir, UV_EPERM);
|
||||
|
||||
/* ax */
|
||||
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
|
||||
UV_FS_O_EXCL;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readFail(absent_file, UV_EPERM);
|
||||
openFail(empty_file, UV_EEXIST);
|
||||
openFail(dummy_file, UV_EEXIST);
|
||||
openFail(empty_dir, UV_EEXIST);
|
||||
|
||||
/* as */
|
||||
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
|
||||
UV_FS_O_SYNC;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readFail(absent_file, UV_EPERM);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readFail(empty_file, UV_EPERM);
|
||||
writeExpect(dummy_file, "abc", 3);
|
||||
readFail(dummy_file, UV_EPERM);
|
||||
writeFail(empty_dir, UV_EISDIR);
|
||||
readFail(empty_dir, UV_EPERM);
|
||||
|
||||
/* a+ */
|
||||
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readExpect(absent_file, "", 0);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readExpect(empty_file, "", 0);
|
||||
writeExpect(dummy_file, "abc", 3);
|
||||
readExpect(dummy_file, "a", 1);
|
||||
writeFail(empty_dir, UV_EISDIR);
|
||||
readFail(empty_dir, UV_EISDIR);
|
||||
|
||||
/* ax+ */
|
||||
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
|
||||
UV_FS_O_EXCL;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readExpect(absent_file, "", 0);
|
||||
openFail(empty_file, UV_EEXIST);
|
||||
openFail(dummy_file, UV_EEXIST);
|
||||
openFail(empty_dir, UV_EEXIST);
|
||||
|
||||
/* as+ */
|
||||
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
|
||||
UV_FS_O_SYNC;
|
||||
writeExpect(absent_file, "bc", 2);
|
||||
readExpect(absent_file, "", 0);
|
||||
writeExpect(empty_file, "bc", 2);
|
||||
readExpect(empty_file, "", 0);
|
||||
writeExpect(dummy_file, "abc", 3);
|
||||
readExpect(dummy_file, "a", 1);
|
||||
writeFail(empty_dir, UV_EISDIR);
|
||||
readFail(empty_dir, UV_EISDIR);
|
||||
}
|
||||
TEST_IMPL(fs_open_flags) {
|
||||
setup();
|
||||
|
||||
fs_open_flags(0);
|
||||
fs_open_flags(UV_FS_O_FILEMAP);
|
||||
|
||||
/* Cleanup. */
|
||||
rmdir(empty_dir);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
|
||||
|
||||
#endif /* ifndef _WIN32 */
|
300
deps/libuv/test/test-fs-poll.c
vendored
Normal file
300
deps/libuv/test/test-fs-poll.c
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define FIXTURE "testfile"
|
||||
|
||||
static void timer_cb(uv_timer_t* handle);
|
||||
static void close_cb(uv_handle_t* handle);
|
||||
static void poll_cb(uv_fs_poll_t* handle,
|
||||
int status,
|
||||
const uv_stat_t* prev,
|
||||
const uv_stat_t* curr);
|
||||
|
||||
static void poll_cb_fail(uv_fs_poll_t* handle,
|
||||
int status,
|
||||
const uv_stat_t* prev,
|
||||
const uv_stat_t* curr);
|
||||
static void poll_cb_noop(uv_fs_poll_t* handle,
|
||||
int status,
|
||||
const uv_stat_t* prev,
|
||||
const uv_stat_t* curr);
|
||||
|
||||
static uv_fs_poll_t poll_handle;
|
||||
static uv_timer_t timer_handle;
|
||||
static uv_loop_t* loop;
|
||||
|
||||
static int poll_cb_called;
|
||||
static int timer_cb_called;
|
||||
static int close_cb_called;
|
||||
|
||||
|
||||
static void touch_file(const char* path) {
|
||||
static int count;
|
||||
FILE* fp;
|
||||
int i;
|
||||
|
||||
ASSERT((fp = fopen(FIXTURE, "w+")));
|
||||
|
||||
/* Need to change the file size because the poller may not pick up
|
||||
* sub-second mtime changes.
|
||||
*/
|
||||
i = ++count;
|
||||
|
||||
while (i--)
|
||||
fputc('*', fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
touch_file(FIXTURE);
|
||||
timer_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void poll_cb_fail(uv_fs_poll_t* handle,
|
||||
int status,
|
||||
const uv_stat_t* prev,
|
||||
const uv_stat_t* curr) {
|
||||
ASSERT(0 && "fail_cb called");
|
||||
}
|
||||
|
||||
static void poll_cb_noop(uv_fs_poll_t* handle,
|
||||
int status,
|
||||
const uv_stat_t* prev,
|
||||
const uv_stat_t* curr) {
|
||||
}
|
||||
|
||||
|
||||
static void poll_cb(uv_fs_poll_t* handle,
|
||||
int status,
|
||||
const uv_stat_t* prev,
|
||||
const uv_stat_t* curr) {
|
||||
uv_stat_t zero_statbuf;
|
||||
|
||||
memset(&zero_statbuf, 0, sizeof(zero_statbuf));
|
||||
|
||||
ASSERT(handle == &poll_handle);
|
||||
ASSERT(1 == uv_is_active((uv_handle_t*) handle));
|
||||
ASSERT(prev != NULL);
|
||||
ASSERT(curr != NULL);
|
||||
|
||||
switch (poll_cb_called++) {
|
||||
case 0:
|
||||
ASSERT(status == UV_ENOENT);
|
||||
ASSERT(0 == memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
ASSERT(0 == memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
touch_file(FIXTURE);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ASSERT(status == 0);
|
||||
ASSERT(0 == memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 20, 0));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ASSERT(status == 0);
|
||||
ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 200, 0));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ASSERT(status == 0);
|
||||
ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
remove(FIXTURE);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ASSERT(status == UV_ENOENT);
|
||||
ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
ASSERT(0 == memcmp(curr, &zero_statbuf, sizeof(zero_statbuf)));
|
||||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_poll) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
remove(FIXTURE);
|
||||
|
||||
ASSERT(0 == uv_timer_init(loop, &timer_handle));
|
||||
ASSERT(0 == uv_fs_poll_init(loop, &poll_handle));
|
||||
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb, FIXTURE, 100));
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
|
||||
ASSERT(poll_cb_called == 5);
|
||||
ASSERT(timer_cb_called == 2);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_poll_getpath) {
|
||||
char buf[1024];
|
||||
size_t len;
|
||||
loop = uv_default_loop();
|
||||
|
||||
remove(FIXTURE);
|
||||
|
||||
ASSERT(0 == uv_fs_poll_init(loop, &poll_handle));
|
||||
len = sizeof buf;
|
||||
ASSERT(UV_EINVAL == uv_fs_poll_getpath(&poll_handle, buf, &len));
|
||||
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
|
||||
len = sizeof buf;
|
||||
ASSERT(0 == uv_fs_poll_getpath(&poll_handle, buf, &len));
|
||||
ASSERT(buf[len - 1] != 0);
|
||||
ASSERT(buf[len] == '\0');
|
||||
ASSERT(0 == memcmp(buf, FIXTURE, len));
|
||||
|
||||
uv_close((uv_handle_t*) &poll_handle, close_cb);
|
||||
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_poll_close_request) {
|
||||
uv_loop_t loop;
|
||||
uv_fs_poll_t poll_handle;
|
||||
|
||||
remove(FIXTURE);
|
||||
|
||||
ASSERT(0 == uv_loop_init(&loop));
|
||||
|
||||
ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
|
||||
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
|
||||
uv_close((uv_handle_t*) &poll_handle, close_cb);
|
||||
while (close_cb_called == 0)
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
ASSERT(0 == uv_loop_close(&loop));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_poll_close_request_multi_start_stop) {
|
||||
uv_loop_t loop;
|
||||
uv_fs_poll_t poll_handle;
|
||||
int i;
|
||||
|
||||
remove(FIXTURE);
|
||||
|
||||
ASSERT(0 == uv_loop_init(&loop));
|
||||
|
||||
ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
|
||||
ASSERT(0 == uv_fs_poll_stop(&poll_handle));
|
||||
}
|
||||
uv_close((uv_handle_t*) &poll_handle, close_cb);
|
||||
while (close_cb_called == 0)
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
ASSERT(0 == uv_loop_close(&loop));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_poll_close_request_multi_stop_start) {
|
||||
uv_loop_t loop;
|
||||
uv_fs_poll_t poll_handle;
|
||||
int i;
|
||||
|
||||
remove(FIXTURE);
|
||||
|
||||
ASSERT(0 == uv_loop_init(&loop));
|
||||
|
||||
ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT(0 == uv_fs_poll_stop(&poll_handle));
|
||||
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
|
||||
}
|
||||
uv_close((uv_handle_t*) &poll_handle, close_cb);
|
||||
while (close_cb_called == 0)
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
ASSERT(0 == uv_loop_close(&loop));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_poll_close_request_stop_when_active) {
|
||||
/* Regression test for https://github.com/libuv/libuv/issues/2287. */
|
||||
uv_loop_t loop;
|
||||
uv_fs_poll_t poll_handle;
|
||||
|
||||
remove(FIXTURE);
|
||||
|
||||
ASSERT(0 == uv_loop_init(&loop));
|
||||
|
||||
/* Set up all handles. */
|
||||
ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
|
||||
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_noop, FIXTURE, 100));
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
|
||||
/* Close the timer handle, and do not crash. */
|
||||
ASSERT(0 == uv_fs_poll_stop(&poll_handle));
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
|
||||
/* Clean up after the test. */
|
||||
uv_close((uv_handle_t*) &poll_handle, close_cb);
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
ASSERT(0 == uv_loop_close(&loop));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
462
deps/libuv/test/test-fs-readdir.c
vendored
Normal file
462
deps/libuv/test/test-fs-readdir.c
vendored
Normal file
@ -0,0 +1,462 @@
|
||||
/* Copyright libuv project 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 <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
static uv_fs_t opendir_req;
|
||||
static uv_fs_t readdir_req;
|
||||
static uv_fs_t closedir_req;
|
||||
|
||||
static uv_dirent_t dirents[1];
|
||||
|
||||
static int empty_opendir_cb_count;
|
||||
static int empty_closedir_cb_count;
|
||||
|
||||
static void cleanup_test_files(void) {
|
||||
uv_fs_t req;
|
||||
|
||||
uv_fs_unlink(NULL, &req, "test_dir/file1", NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
uv_fs_unlink(NULL, &req, "test_dir/file2", NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
uv_fs_rmdir(NULL, &req, "test_dir/test_subdir", NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
uv_fs_rmdir(NULL, &req, "test_dir", NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
|
||||
static void empty_closedir_cb(uv_fs_t* req) {
|
||||
ASSERT(req == &closedir_req);
|
||||
ASSERT(req->fs_type == UV_FS_CLOSEDIR);
|
||||
ASSERT(req->result == 0);
|
||||
++empty_closedir_cb_count;
|
||||
uv_fs_req_cleanup(req);
|
||||
}
|
||||
|
||||
static void empty_readdir_cb(uv_fs_t* req) {
|
||||
uv_dir_t* dir;
|
||||
int r;
|
||||
|
||||
ASSERT(req == &readdir_req);
|
||||
ASSERT(req->fs_type == UV_FS_READDIR);
|
||||
ASSERT(req->result == 0);
|
||||
dir = req->ptr;
|
||||
uv_fs_req_cleanup(req);
|
||||
r = uv_fs_closedir(uv_default_loop(),
|
||||
&closedir_req,
|
||||
dir,
|
||||
empty_closedir_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
static void empty_opendir_cb(uv_fs_t* req) {
|
||||
uv_dir_t* dir;
|
||||
int r;
|
||||
|
||||
ASSERT(req == &opendir_req);
|
||||
ASSERT(req->fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(req->result == 0);
|
||||
ASSERT(req->ptr != NULL);
|
||||
dir = req->ptr;
|
||||
dir->dirents = dirents;
|
||||
dir->nentries = ARRAY_SIZE(dirents);
|
||||
r = uv_fs_readdir(uv_default_loop(),
|
||||
&readdir_req,
|
||||
dir,
|
||||
empty_readdir_cb);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(req);
|
||||
++empty_opendir_cb_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test makes sure that both synchronous and asynchronous flavors
|
||||
* of the uv_fs_opendir() -> uv_fs_readdir() -> uv_fs_closedir() sequence work
|
||||
* as expected when processing an empty directory.
|
||||
*/
|
||||
TEST_IMPL(fs_readdir_empty_dir) {
|
||||
const char* path;
|
||||
uv_fs_t mkdir_req;
|
||||
uv_fs_t rmdir_req;
|
||||
int r;
|
||||
int nb_entries_read;
|
||||
uv_dir_t* dir;
|
||||
|
||||
path = "./empty_dir/";
|
||||
uv_fs_mkdir(uv_default_loop(), &mkdir_req, path, 0777, NULL);
|
||||
uv_fs_req_cleanup(&mkdir_req);
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
|
||||
/* Testing the synchronous flavor. */
|
||||
r = uv_fs_opendir(uv_default_loop(),
|
||||
&opendir_req,
|
||||
path,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(opendir_req.fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(opendir_req.result == 0);
|
||||
ASSERT(opendir_req.ptr != NULL);
|
||||
dir = opendir_req.ptr;
|
||||
uv_fs_req_cleanup(&opendir_req);
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&readdir_req, 0xdb, sizeof(readdir_req));
|
||||
dir->dirents = dirents;
|
||||
dir->nentries = ARRAY_SIZE(dirents);
|
||||
nb_entries_read = uv_fs_readdir(uv_default_loop(),
|
||||
&readdir_req,
|
||||
dir,
|
||||
NULL);
|
||||
ASSERT(nb_entries_read == 0);
|
||||
uv_fs_req_cleanup(&readdir_req);
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&closedir_req, 0xdb, sizeof(closedir_req));
|
||||
uv_fs_closedir(uv_default_loop(), &closedir_req, dir, NULL);
|
||||
ASSERT(closedir_req.result == 0);
|
||||
uv_fs_req_cleanup(&closedir_req);
|
||||
|
||||
/* Testing the asynchronous flavor. */
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
memset(&readdir_req, 0xdb, sizeof(readdir_req));
|
||||
memset(&closedir_req, 0xdb, sizeof(closedir_req));
|
||||
|
||||
r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, empty_opendir_cb);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(empty_opendir_cb_count == 0);
|
||||
ASSERT(empty_closedir_cb_count == 0);
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(empty_opendir_cb_count == 1);
|
||||
ASSERT(empty_closedir_cb_count == 1);
|
||||
uv_fs_rmdir(uv_default_loop(), &rmdir_req, path, NULL);
|
||||
uv_fs_req_cleanup(&rmdir_req);
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test makes sure that reading a non-existing directory with
|
||||
* uv_fs_{open,read}_dir() returns proper error codes.
|
||||
*/
|
||||
|
||||
static int non_existing_opendir_cb_count;
|
||||
|
||||
static void non_existing_opendir_cb(uv_fs_t* req) {
|
||||
ASSERT(req == &opendir_req);
|
||||
ASSERT(req->fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(req->result == UV_ENOENT);
|
||||
ASSERT(req->ptr == NULL);
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
++non_existing_opendir_cb_count;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_readdir_non_existing_dir) {
|
||||
const char* path;
|
||||
int r;
|
||||
|
||||
path = "./non-existing-dir/";
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
|
||||
/* Testing the synchronous flavor. */
|
||||
r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, NULL);
|
||||
ASSERT(r == UV_ENOENT);
|
||||
ASSERT(opendir_req.fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(opendir_req.result == UV_ENOENT);
|
||||
ASSERT(opendir_req.ptr == NULL);
|
||||
uv_fs_req_cleanup(&opendir_req);
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
|
||||
/* Testing the async flavor. */
|
||||
r = uv_fs_opendir(uv_default_loop(),
|
||||
&opendir_req,
|
||||
path,
|
||||
non_existing_opendir_cb);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(non_existing_opendir_cb_count == 0);
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(non_existing_opendir_cb_count == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test makes sure that reading a file as a directory reports correct
|
||||
* error codes.
|
||||
*/
|
||||
|
||||
static int file_opendir_cb_count;
|
||||
|
||||
static void file_opendir_cb(uv_fs_t* req) {
|
||||
ASSERT(req == &opendir_req);
|
||||
ASSERT(req->fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(req->result == UV_ENOTDIR);
|
||||
ASSERT(req->ptr == NULL);
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
++file_opendir_cb_count;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_readdir_file) {
|
||||
const char* path;
|
||||
int r;
|
||||
|
||||
path = "test/fixtures/empty_file";
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
|
||||
/* Testing the synchronous flavor. */
|
||||
r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, NULL);
|
||||
|
||||
ASSERT(r == UV_ENOTDIR);
|
||||
ASSERT(opendir_req.fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(opendir_req.result == UV_ENOTDIR);
|
||||
ASSERT(opendir_req.ptr == NULL);
|
||||
|
||||
uv_fs_req_cleanup(&opendir_req);
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
|
||||
/* Testing the async flavor. */
|
||||
r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, file_opendir_cb);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(file_opendir_cb_count == 0);
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(file_opendir_cb_count == 1);
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test makes sure that reading a non-empty directory with
|
||||
* uv_fs_{open,read}_dir() returns proper directory entries, including the
|
||||
* correct entry types.
|
||||
*/
|
||||
|
||||
static int non_empty_opendir_cb_count;
|
||||
static int non_empty_readdir_cb_count;
|
||||
static int non_empty_closedir_cb_count;
|
||||
|
||||
static void non_empty_closedir_cb(uv_fs_t* req) {
|
||||
ASSERT(req == &closedir_req);
|
||||
ASSERT(req->result == 0);
|
||||
uv_fs_req_cleanup(req);
|
||||
++non_empty_closedir_cb_count;
|
||||
}
|
||||
|
||||
static void non_empty_readdir_cb(uv_fs_t* req) {
|
||||
uv_dir_t* dir;
|
||||
|
||||
ASSERT(req == &readdir_req);
|
||||
ASSERT(req->fs_type == UV_FS_READDIR);
|
||||
dir = req->ptr;
|
||||
|
||||
if (req->result == 0) {
|
||||
uv_fs_req_cleanup(req);
|
||||
ASSERT(non_empty_readdir_cb_count == 3);
|
||||
uv_fs_closedir(uv_default_loop(),
|
||||
&closedir_req,
|
||||
dir,
|
||||
non_empty_closedir_cb);
|
||||
} else {
|
||||
ASSERT(req->result == 1);
|
||||
ASSERT(dir->dirents == dirents);
|
||||
ASSERT(strcmp(dirents[0].name, "file1") == 0 ||
|
||||
strcmp(dirents[0].name, "file2") == 0 ||
|
||||
strcmp(dirents[0].name, "test_subdir") == 0);
|
||||
#ifdef HAVE_DIRENT_TYPES
|
||||
if (!strcmp(dirents[0].name, "test_subdir"))
|
||||
ASSERT(dirents[0].type == UV_DIRENT_DIR);
|
||||
else
|
||||
ASSERT(dirents[0].type == UV_DIRENT_FILE);
|
||||
#else
|
||||
ASSERT(dirents[0].type == UV_DIRENT_UNKNOWN);
|
||||
#endif /* HAVE_DIRENT_TYPES */
|
||||
|
||||
++non_empty_readdir_cb_count;
|
||||
uv_fs_req_cleanup(req);
|
||||
dir->dirents = dirents;
|
||||
dir->nentries = ARRAY_SIZE(dirents);
|
||||
uv_fs_readdir(uv_default_loop(),
|
||||
&readdir_req,
|
||||
dir,
|
||||
non_empty_readdir_cb);
|
||||
}
|
||||
}
|
||||
|
||||
static void non_empty_opendir_cb(uv_fs_t* req) {
|
||||
uv_dir_t* dir;
|
||||
int r;
|
||||
|
||||
ASSERT(req == &opendir_req);
|
||||
ASSERT(req->fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(req->result == 0);
|
||||
ASSERT(req->ptr != NULL);
|
||||
|
||||
dir = req->ptr;
|
||||
dir->dirents = dirents;
|
||||
dir->nentries = ARRAY_SIZE(dirents);
|
||||
|
||||
r = uv_fs_readdir(uv_default_loop(),
|
||||
&readdir_req,
|
||||
dir,
|
||||
non_empty_readdir_cb);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(req);
|
||||
++non_empty_opendir_cb_count;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_readdir_non_empty_dir) {
|
||||
size_t entries_count;
|
||||
uv_fs_t mkdir_req;
|
||||
uv_fs_t rmdir_req;
|
||||
uv_fs_t create_req;
|
||||
uv_fs_t close_req;
|
||||
uv_dir_t* dir;
|
||||
int r;
|
||||
|
||||
cleanup_test_files();
|
||||
|
||||
r = uv_fs_mkdir(uv_default_loop(), &mkdir_req, "test_dir", 0755, NULL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Create two files synchronously. */
|
||||
r = uv_fs_open(uv_default_loop(),
|
||||
&create_req,
|
||||
"test_dir/file1",
|
||||
O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR,
|
||||
NULL);
|
||||
ASSERT(r >= 0);
|
||||
uv_fs_req_cleanup(&create_req);
|
||||
r = uv_fs_close(uv_default_loop(),
|
||||
&close_req,
|
||||
create_req.result,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
r = uv_fs_open(uv_default_loop(),
|
||||
&create_req,
|
||||
"test_dir/file2",
|
||||
O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR,
|
||||
NULL);
|
||||
ASSERT(r >= 0);
|
||||
uv_fs_req_cleanup(&create_req);
|
||||
r = uv_fs_close(uv_default_loop(),
|
||||
&close_req,
|
||||
create_req.result,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
r = uv_fs_mkdir(uv_default_loop(),
|
||||
&mkdir_req,
|
||||
"test_dir/test_subdir",
|
||||
0755,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&mkdir_req);
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
|
||||
/* Testing the synchronous flavor. */
|
||||
r = uv_fs_opendir(uv_default_loop(), &opendir_req, "test_dir", NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(opendir_req.fs_type == UV_FS_OPENDIR);
|
||||
ASSERT(opendir_req.result == 0);
|
||||
ASSERT(opendir_req.ptr != NULL);
|
||||
|
||||
entries_count = 0;
|
||||
dir = opendir_req.ptr;
|
||||
dir->dirents = dirents;
|
||||
dir->nentries = ARRAY_SIZE(dirents);
|
||||
uv_fs_req_cleanup(&opendir_req);
|
||||
|
||||
while (uv_fs_readdir(uv_default_loop(),
|
||||
&readdir_req,
|
||||
dir,
|
||||
NULL) != 0) {
|
||||
ASSERT(strcmp(dirents[0].name, "file1") == 0 ||
|
||||
strcmp(dirents[0].name, "file2") == 0 ||
|
||||
strcmp(dirents[0].name, "test_subdir") == 0);
|
||||
#ifdef HAVE_DIRENT_TYPES
|
||||
if (!strcmp(dirents[0].name, "test_subdir"))
|
||||
ASSERT(dirents[0].type == UV_DIRENT_DIR);
|
||||
else
|
||||
ASSERT(dirents[0].type == UV_DIRENT_FILE);
|
||||
#else
|
||||
ASSERT(dirents[0].type == UV_DIRENT_UNKNOWN);
|
||||
#endif /* HAVE_DIRENT_TYPES */
|
||||
uv_fs_req_cleanup(&readdir_req);
|
||||
++entries_count;
|
||||
}
|
||||
|
||||
ASSERT(entries_count == 3);
|
||||
uv_fs_req_cleanup(&readdir_req);
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&closedir_req, 0xdb, sizeof(closedir_req));
|
||||
uv_fs_closedir(uv_default_loop(), &closedir_req, dir, NULL);
|
||||
ASSERT(closedir_req.result == 0);
|
||||
uv_fs_req_cleanup(&closedir_req);
|
||||
|
||||
/* Testing the asynchronous flavor. */
|
||||
|
||||
/* Fill the req to ensure that required fields are cleaned up. */
|
||||
memset(&opendir_req, 0xdb, sizeof(opendir_req));
|
||||
|
||||
r = uv_fs_opendir(uv_default_loop(),
|
||||
&opendir_req,
|
||||
"test_dir",
|
||||
non_empty_opendir_cb);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(non_empty_opendir_cb_count == 0);
|
||||
ASSERT(non_empty_closedir_cb_count == 0);
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(non_empty_opendir_cb_count == 1);
|
||||
ASSERT(non_empty_closedir_cb_count == 1);
|
||||
|
||||
uv_fs_rmdir(uv_default_loop(), &rmdir_req, "test_subdir", NULL);
|
||||
uv_fs_req_cleanup(&rmdir_req);
|
||||
|
||||
cleanup_test_files();
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
4417
deps/libuv/test/test-fs.c
vendored
Normal file
4417
deps/libuv/test/test-fs.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
106
deps/libuv/test/test-get-currentexe.c
vendored
Normal file
106
deps/libuv/test/test-get-currentexe.c
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define PATHMAX 4096
|
||||
extern char executable_path[];
|
||||
|
||||
TEST_IMPL(get_currentexe) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
char buffer[PATHMAX];
|
||||
char path[PATHMAX];
|
||||
size_t size;
|
||||
char* match;
|
||||
int r;
|
||||
|
||||
size = sizeof(buffer) / sizeof(buffer[0]);
|
||||
r = uv_exepath(buffer, &size);
|
||||
ASSERT(!r);
|
||||
|
||||
#ifdef _WIN32
|
||||
snprintf(path, sizeof(path), "%s", executable_path);
|
||||
#else
|
||||
ASSERT(NULL != realpath(executable_path, path));
|
||||
#endif
|
||||
|
||||
match = strstr(buffer, path);
|
||||
/* Verify that the path returned from uv_exepath is a subdirectory of
|
||||
* executable_path.
|
||||
*/
|
||||
ASSERT(match && !strcmp(match, path));
|
||||
ASSERT(size == strlen(buffer));
|
||||
|
||||
/* Negative tests */
|
||||
size = sizeof(buffer) / sizeof(buffer[0]);
|
||||
r = uv_exepath(NULL, &size);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
r = uv_exepath(buffer, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
size = 0;
|
||||
r = uv_exepath(buffer, &size);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
memset(buffer, -1, sizeof(buffer));
|
||||
|
||||
size = 1;
|
||||
r = uv_exepath(buffer, &size);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(size == 0);
|
||||
ASSERT(buffer[0] == '\0');
|
||||
|
||||
memset(buffer, -1, sizeof(buffer));
|
||||
|
||||
size = 2;
|
||||
r = uv_exepath(buffer, &size);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(size == 1);
|
||||
ASSERT(buffer[0] != '\0');
|
||||
ASSERT(buffer[1] == '\0');
|
||||
|
||||
/* Verify uv_exepath is not affected by uv_set_process_title(). */
|
||||
r = uv_set_process_title("foobar");
|
||||
ASSERT_EQ(r, 0);
|
||||
size = sizeof(buffer);
|
||||
r = uv_exepath(buffer, &size);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
match = strstr(buffer, path);
|
||||
/* Verify that the path returned from uv_exepath is a subdirectory of
|
||||
* executable_path.
|
||||
*/
|
||||
ASSERT_NOT_NULL(match);
|
||||
ASSERT_STR_EQ(match, path);
|
||||
ASSERT_EQ(size, strlen(buffer));
|
||||
return 0;
|
||||
}
|
35
deps/libuv/test/test-get-loadavg.c
vendored
Normal file
35
deps/libuv/test/test-get-loadavg.c
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
TEST_IMPL(get_loadavg) {
|
||||
|
||||
double avg[3] = {-1, -1, -1};
|
||||
uv_loadavg(avg);
|
||||
|
||||
ASSERT(avg[0] >= 0);
|
||||
ASSERT(avg[1] >= 0);
|
||||
ASSERT(avg[2] >= 0);
|
||||
|
||||
return 0;
|
||||
}
|
44
deps/libuv/test/test-get-memory.c
vendored
Normal file
44
deps/libuv/test/test-get-memory.c
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
TEST_IMPL(get_memory) {
|
||||
uint64_t free_mem = uv_get_free_memory();
|
||||
uint64_t total_mem = uv_get_total_memory();
|
||||
uint64_t constrained_mem = uv_get_constrained_memory();
|
||||
|
||||
printf("free_mem=%llu, total_mem=%llu, constrained_mem=%llu\n",
|
||||
(unsigned long long) free_mem,
|
||||
(unsigned long long) total_mem,
|
||||
(unsigned long long) constrained_mem);
|
||||
|
||||
ASSERT(free_mem > 0);
|
||||
ASSERT(total_mem > 0);
|
||||
/* On IBMi PASE, the amount of memory in use is always zero. */
|
||||
#ifdef __PASE__
|
||||
ASSERT(total_mem == free_mem);
|
||||
#else
|
||||
ASSERT(total_mem > free_mem);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
93
deps/libuv/test/test-get-passwd.c
vendored
Normal file
93
deps/libuv/test/test-get-passwd.c
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
/* Copyright libuv 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 <string.h>
|
||||
|
||||
TEST_IMPL(get_passwd) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
uv_passwd_t pwd;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
/* Test the normal case */
|
||||
r = uv_os_get_passwd(&pwd);
|
||||
ASSERT(r == 0);
|
||||
len = strlen(pwd.username);
|
||||
ASSERT(len > 0);
|
||||
|
||||
#ifdef _WIN32
|
||||
ASSERT(pwd.shell == NULL);
|
||||
#else
|
||||
len = strlen(pwd.shell);
|
||||
# ifndef __PASE__
|
||||
ASSERT(len > 0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
len = strlen(pwd.homedir);
|
||||
ASSERT(len > 0);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (len == 3 && pwd.homedir[1] == ':')
|
||||
ASSERT(pwd.homedir[2] == '\\');
|
||||
else
|
||||
ASSERT(pwd.homedir[len - 1] != '\\');
|
||||
#else
|
||||
if (len == 1)
|
||||
ASSERT(pwd.homedir[0] == '/');
|
||||
else
|
||||
ASSERT(pwd.homedir[len - 1] != '/');
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
ASSERT(pwd.uid == -1);
|
||||
ASSERT(pwd.gid == -1);
|
||||
#else
|
||||
ASSERT(pwd.uid >= 0);
|
||||
ASSERT(pwd.gid >= 0);
|
||||
#endif
|
||||
|
||||
/* Test uv_os_free_passwd() */
|
||||
uv_os_free_passwd(&pwd);
|
||||
|
||||
ASSERT(pwd.username == NULL);
|
||||
ASSERT(pwd.shell == NULL);
|
||||
ASSERT(pwd.homedir == NULL);
|
||||
|
||||
/* Test a double free */
|
||||
uv_os_free_passwd(&pwd);
|
||||
|
||||
ASSERT(pwd.username == NULL);
|
||||
ASSERT(pwd.shell == NULL);
|
||||
ASSERT(pwd.homedir == NULL);
|
||||
|
||||
/* Test invalid input */
|
||||
r = uv_os_get_passwd(NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
215
deps/libuv/test/test-getaddrinfo.c
vendored
Normal file
215
deps/libuv/test/test-getaddrinfo.c
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CONCURRENT_COUNT 10
|
||||
|
||||
static const char* name = "localhost";
|
||||
|
||||
static int getaddrinfo_cbs = 0;
|
||||
|
||||
/* data used for running multiple calls concurrently */
|
||||
static uv_getaddrinfo_t* getaddrinfo_handle;
|
||||
static uv_getaddrinfo_t getaddrinfo_handles[CONCURRENT_COUNT];
|
||||
static int callback_counts[CONCURRENT_COUNT];
|
||||
static int fail_cb_called;
|
||||
|
||||
|
||||
static void getaddrinfo_fail_cb(uv_getaddrinfo_t* req,
|
||||
int status,
|
||||
struct addrinfo* res) {
|
||||
|
||||
ASSERT(fail_cb_called == 0);
|
||||
ASSERT(status < 0);
|
||||
ASSERT(res == NULL);
|
||||
uv_freeaddrinfo(res); /* Should not crash. */
|
||||
fail_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void getaddrinfo_basic_cb(uv_getaddrinfo_t* handle,
|
||||
int status,
|
||||
struct addrinfo* res) {
|
||||
ASSERT(handle == getaddrinfo_handle);
|
||||
getaddrinfo_cbs++;
|
||||
free(handle);
|
||||
uv_freeaddrinfo(res);
|
||||
}
|
||||
|
||||
|
||||
static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle,
|
||||
int status,
|
||||
struct addrinfo* res) {
|
||||
int i;
|
||||
int* data = (int*)handle->data;
|
||||
|
||||
for (i = 0; i < CONCURRENT_COUNT; i++) {
|
||||
if (&getaddrinfo_handles[i] == handle) {
|
||||
ASSERT(i == *data);
|
||||
|
||||
callback_counts[i]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT (i < CONCURRENT_COUNT);
|
||||
|
||||
free(data);
|
||||
uv_freeaddrinfo(res);
|
||||
|
||||
getaddrinfo_cbs++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_fail) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
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,
|
||||
getaddrinfo_fail_cb,
|
||||
"xyzzy.xyzzy.xyzzy.",
|
||||
NULL,
|
||||
NULL));
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(fail_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_fail_sync) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
uv_getaddrinfo_t req;
|
||||
|
||||
/* Use a FQDN by ending in a period */
|
||||
ASSERT(0 > uv_getaddrinfo(uv_default_loop(),
|
||||
&req,
|
||||
NULL,
|
||||
"xyzzy.xyzzy.xyzzy.",
|
||||
NULL,
|
||||
NULL));
|
||||
uv_freeaddrinfo(req.addrinfo);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_basic) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
int r;
|
||||
getaddrinfo_handle = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t));
|
||||
|
||||
r = uv_getaddrinfo(uv_default_loop(),
|
||||
getaddrinfo_handle,
|
||||
&getaddrinfo_basic_cb,
|
||||
name,
|
||||
NULL,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(getaddrinfo_cbs == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_basic_sync) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
uv_getaddrinfo_t req;
|
||||
|
||||
ASSERT(0 == uv_getaddrinfo(uv_default_loop(),
|
||||
&req,
|
||||
NULL,
|
||||
name,
|
||||
NULL,
|
||||
NULL));
|
||||
uv_freeaddrinfo(req.addrinfo);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_concurrent) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
int i, r;
|
||||
int* data;
|
||||
|
||||
for (i = 0; i < CONCURRENT_COUNT; i++) {
|
||||
callback_counts[i] = 0;
|
||||
|
||||
data = (int*)malloc(sizeof(int));
|
||||
ASSERT(data != NULL);
|
||||
*data = i;
|
||||
getaddrinfo_handles[i].data = data;
|
||||
|
||||
r = uv_getaddrinfo(uv_default_loop(),
|
||||
&getaddrinfo_handles[i],
|
||||
&getaddrinfo_cuncurrent_cb,
|
||||
name,
|
||||
NULL,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
for (i = 0; i < CONCURRENT_COUNT; i++) {
|
||||
ASSERT(callback_counts[i] == 1);
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
58
deps/libuv/test/test-gethostname.c
vendored
Normal file
58
deps/libuv/test/test-gethostname.c
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/* Copyright libuv 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 <string.h>
|
||||
|
||||
TEST_IMPL(gethostname) {
|
||||
char buf[UV_MAXHOSTNAMESIZE];
|
||||
size_t size;
|
||||
size_t enobufs_size;
|
||||
int r;
|
||||
|
||||
/* Reject invalid inputs */
|
||||
size = 1;
|
||||
r = uv_os_gethostname(NULL, &size);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
r = uv_os_gethostname(buf, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
size = 0;
|
||||
r = uv_os_gethostname(buf, &size);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
/* Return UV_ENOBUFS if the buffer cannot hold the hostname */
|
||||
enobufs_size = 1;
|
||||
buf[0] = '\0';
|
||||
r = uv_os_gethostname(buf, &enobufs_size);
|
||||
ASSERT(r == UV_ENOBUFS);
|
||||
ASSERT(buf[0] == '\0');
|
||||
ASSERT(enobufs_size > 1);
|
||||
|
||||
/* Successfully get the hostname */
|
||||
size = UV_MAXHOSTNAMESIZE;
|
||||
r = uv_os_gethostname(buf, &size);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(size > 0 && size == strlen(buf));
|
||||
ASSERT(size + 1 == enobufs_size);
|
||||
|
||||
return 0;
|
||||
}
|
116
deps/libuv/test/test-getnameinfo.c
vendored
Normal file
116
deps/libuv/test/test-getnameinfo.c
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static const char* address_ip4 = "127.0.0.1";
|
||||
static const char* address_ip6 = "::1";
|
||||
static const int port = 80;
|
||||
|
||||
static struct sockaddr_in addr4;
|
||||
static struct sockaddr_in6 addr6;
|
||||
static uv_getnameinfo_t req;
|
||||
|
||||
static void getnameinfo_req(uv_getnameinfo_t* handle,
|
||||
int status,
|
||||
const char* hostname,
|
||||
const char* service) {
|
||||
ASSERT(handle != NULL);
|
||||
ASSERT(status == 0);
|
||||
ASSERT(hostname != NULL);
|
||||
ASSERT(service != NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getnameinfo_basic_ip4) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
int r;
|
||||
|
||||
r = uv_ip4_addr(address_ip4, port, &addr4);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_getnameinfo(uv_default_loop(),
|
||||
&req,
|
||||
&getnameinfo_req,
|
||||
(const struct sockaddr*)&addr4,
|
||||
0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getnameinfo_basic_ip4_sync) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
ASSERT(0 == uv_ip4_addr(address_ip4, port, &addr4));
|
||||
|
||||
ASSERT(0 == uv_getnameinfo(uv_default_loop(),
|
||||
&req,
|
||||
NULL,
|
||||
(const struct sockaddr*)&addr4,
|
||||
0));
|
||||
ASSERT(req.host[0] != '\0');
|
||||
ASSERT(req.service[0] != '\0');
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getnameinfo_basic_ip6) {
|
||||
/* TODO(gengjiawen): Fix test on QEMU. */
|
||||
#if defined(__QEMU__)
|
||||
RETURN_SKIP("Test does not currently work in QEMU");
|
||||
#endif
|
||||
|
||||
int r;
|
||||
|
||||
r = uv_ip6_addr(address_ip6, port, &addr6);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_getnameinfo(uv_default_loop(),
|
||||
&req,
|
||||
&getnameinfo_req,
|
||||
(const struct sockaddr*)&addr6,
|
||||
0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
361
deps/libuv/test/test-getsockname.c
vendored
Normal file
361
deps/libuv/test/test-getsockname.c
vendored
Normal file
@ -0,0 +1,361 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static const int server_port = TEST_PORT;
|
||||
/* Will be updated right after making the uv_connect_call */
|
||||
static int connect_port = -1;
|
||||
|
||||
static int getsocknamecount = 0;
|
||||
static int getpeernamecount = 0;
|
||||
|
||||
static uv_loop_t* loop;
|
||||
static uv_tcp_t tcp;
|
||||
static uv_udp_t udp;
|
||||
static uv_connect_t connect_req;
|
||||
static uv_tcp_t tcpServer;
|
||||
static uv_udp_t udpServer;
|
||||
static uv_udp_send_t send_req;
|
||||
|
||||
|
||||
static void alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
|
||||
static void on_close(uv_handle_t* peer) {
|
||||
free(peer);
|
||||
uv_close((uv_handle_t*)&tcpServer, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void after_shutdown(uv_shutdown_t* req, int status) {
|
||||
uv_close((uv_handle_t*) req->handle, on_close);
|
||||
free(req);
|
||||
}
|
||||
|
||||
|
||||
static void after_read(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
uv_shutdown_t* req;
|
||||
int r;
|
||||
|
||||
if (buf->base) {
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
req = (uv_shutdown_t*) malloc(sizeof *req);
|
||||
r = uv_shutdown(req, handle, after_shutdown);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void check_sockname(struct sockaddr* addr, const char* compare_ip,
|
||||
int compare_port, const char* context) {
|
||||
struct sockaddr_in check_addr = *(struct sockaddr_in*) addr;
|
||||
struct sockaddr_in compare_addr;
|
||||
char check_ip[17];
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr(compare_ip, compare_port, &compare_addr));
|
||||
|
||||
/* Both addresses should be ipv4 */
|
||||
ASSERT(check_addr.sin_family == AF_INET);
|
||||
ASSERT(compare_addr.sin_family == AF_INET);
|
||||
|
||||
/* Check if the ip matches */
|
||||
ASSERT(memcmp(&check_addr.sin_addr,
|
||||
&compare_addr.sin_addr,
|
||||
sizeof compare_addr.sin_addr) == 0);
|
||||
|
||||
/* Check if the port matches. If port == 0 anything goes. */
|
||||
ASSERT(compare_port == 0 || check_addr.sin_port == compare_addr.sin_port);
|
||||
|
||||
r = uv_ip4_name(&check_addr, (char*) check_ip, sizeof check_ip);
|
||||
ASSERT(r == 0);
|
||||
|
||||
printf("%s: %s:%d\n", context, check_ip, ntohs(check_addr.sin_port));
|
||||
}
|
||||
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status) {
|
||||
struct sockaddr sockname, peername;
|
||||
int namelen;
|
||||
uv_tcp_t* handle;
|
||||
int r;
|
||||
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "Connect error %s\n", uv_err_name(status));
|
||||
}
|
||||
ASSERT(status == 0);
|
||||
|
||||
handle = malloc(sizeof(*handle));
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
r = uv_tcp_init(loop, handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* associate server with stream */
|
||||
handle->data = server;
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getsockname(handle, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "127.0.0.1", server_port, "accepted socket");
|
||||
getsocknamecount++;
|
||||
|
||||
namelen = sizeof peername;
|
||||
r = uv_tcp_getpeername(handle, &peername, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&peername, "127.0.0.1", connect_port, "accepted socket peer");
|
||||
getpeernamecount++;
|
||||
|
||||
r = uv_read_start((uv_stream_t*)handle, alloc, after_read);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void on_connect(uv_connect_t* req, int status) {
|
||||
struct sockaddr sockname, peername;
|
||||
int r, namelen;
|
||||
|
||||
ASSERT(status == 0);
|
||||
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getsockname((uv_tcp_t*) req->handle, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "127.0.0.1", 0, "connected socket");
|
||||
getsocknamecount++;
|
||||
|
||||
namelen = sizeof peername;
|
||||
r = uv_tcp_getpeername((uv_tcp_t*) req->handle, &peername, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&peername, "127.0.0.1", server_port, "connected socket peer");
|
||||
getpeernamecount++;
|
||||
|
||||
uv_close((uv_handle_t*)&tcp, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int tcp_listener(void) {
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr sockname, peername;
|
||||
int namelen;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", server_port, &addr));
|
||||
|
||||
r = uv_tcp_init(loop, &tcpServer);
|
||||
if (r) {
|
||||
fprintf(stderr, "Socket creation error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &addr, 0);
|
||||
if (r) {
|
||||
fprintf(stderr, "Bind error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcpServer, 128, on_connection);
|
||||
if (r) {
|
||||
fprintf(stderr, "Listen error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&sockname, -1, sizeof sockname);
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getsockname(&tcpServer, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "0.0.0.0", server_port, "server socket");
|
||||
getsocknamecount++;
|
||||
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getpeername(&tcpServer, &peername, &namelen);
|
||||
ASSERT(r == UV_ENOTCONN);
|
||||
getpeernamecount++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void tcp_connector(void) {
|
||||
struct sockaddr_in server_addr;
|
||||
struct sockaddr sockname;
|
||||
int r, namelen;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", server_port, &server_addr));
|
||||
|
||||
r = uv_tcp_init(loop, &tcp);
|
||||
tcp.data = &connect_req;
|
||||
ASSERT(!r);
|
||||
|
||||
r = uv_tcp_connect(&connect_req,
|
||||
&tcp,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
on_connect);
|
||||
ASSERT(!r);
|
||||
|
||||
/* Fetch the actual port used by the connecting socket. */
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getsockname(&tcp, &sockname, &namelen);
|
||||
ASSERT(!r);
|
||||
ASSERT(sockname.sa_family == AF_INET);
|
||||
connect_port = ntohs(((struct sockaddr_in*) &sockname)->sin_port);
|
||||
ASSERT(connect_port > 0);
|
||||
}
|
||||
|
||||
|
||||
static void udp_recv(uv_udp_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf,
|
||||
const struct sockaddr* addr,
|
||||
unsigned flags) {
|
||||
struct sockaddr sockname;
|
||||
int namelen;
|
||||
int r;
|
||||
|
||||
ASSERT(nread >= 0);
|
||||
free(buf->base);
|
||||
|
||||
if (nread == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&sockname, -1, sizeof sockname);
|
||||
namelen = sizeof(sockname);
|
||||
r = uv_udp_getsockname(&udp, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "0.0.0.0", 0, "udp receiving socket");
|
||||
getsocknamecount++;
|
||||
|
||||
uv_close((uv_handle_t*) &udp, NULL);
|
||||
uv_close((uv_handle_t*) handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void udp_send(uv_udp_send_t* req, int status) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int udp_listener(void) {
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr sockname;
|
||||
int namelen;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", server_port, &addr));
|
||||
|
||||
r = uv_udp_init(loop, &udpServer);
|
||||
if (r) {
|
||||
fprintf(stderr, "Socket creation error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = uv_udp_bind(&udpServer, (const struct sockaddr*) &addr, 0);
|
||||
if (r) {
|
||||
fprintf(stderr, "Bind error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&sockname, -1, sizeof sockname);
|
||||
namelen = sizeof sockname;
|
||||
r = uv_udp_getsockname(&udpServer, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "0.0.0.0", server_port, "udp listener socket");
|
||||
getsocknamecount++;
|
||||
|
||||
r = uv_udp_recv_start(&udpServer, alloc, udp_recv);
|
||||
ASSERT(r == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void udp_sender(void) {
|
||||
struct sockaddr_in server_addr;
|
||||
uv_buf_t buf;
|
||||
int r;
|
||||
|
||||
r = uv_udp_init(loop, &udp);
|
||||
ASSERT(!r);
|
||||
|
||||
buf = uv_buf_init("PING", 4);
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", server_port, &server_addr));
|
||||
|
||||
r = uv_udp_send(&send_req,
|
||||
&udp,
|
||||
&buf,
|
||||
1,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
udp_send);
|
||||
ASSERT(!r);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getsockname_tcp) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
if (tcp_listener())
|
||||
return 1;
|
||||
|
||||
tcp_connector();
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(getsocknamecount == 3);
|
||||
ASSERT(getpeernamecount == 3);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getsockname_udp) {
|
||||
loop = uv_default_loop();
|
||||
|
||||
if (udp_listener())
|
||||
return 1;
|
||||
|
||||
udp_sender();
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(getsocknamecount == 2);
|
||||
|
||||
ASSERT(udp.send_queue_size == 0);
|
||||
ASSERT(udpServer.send_queue_size == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
109
deps/libuv/test/test-getters-setters.c
vendored
Normal file
109
deps/libuv/test/test-getters-setters.c
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/* Copyright libuv project 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 <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int cookie1;
|
||||
int cookie2;
|
||||
int cookie3;
|
||||
|
||||
|
||||
TEST_IMPL(handle_type_name) {
|
||||
ASSERT(strcmp(uv_handle_type_name(UV_NAMED_PIPE), "pipe") == 0);
|
||||
ASSERT(strcmp(uv_handle_type_name(UV_UDP), "udp") == 0);
|
||||
ASSERT(strcmp(uv_handle_type_name(UV_FILE), "file") == 0);
|
||||
ASSERT(uv_handle_type_name(UV_HANDLE_TYPE_MAX) == NULL);
|
||||
ASSERT(uv_handle_type_name(UV_HANDLE_TYPE_MAX + 1) == NULL);
|
||||
ASSERT(uv_handle_type_name(UV_UNKNOWN_HANDLE) == NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(req_type_name) {
|
||||
ASSERT(strcmp(uv_req_type_name(UV_REQ), "req") == 0);
|
||||
ASSERT(strcmp(uv_req_type_name(UV_UDP_SEND), "udp_send") == 0);
|
||||
ASSERT(strcmp(uv_req_type_name(UV_WORK), "work") == 0);
|
||||
ASSERT(uv_req_type_name(UV_REQ_TYPE_MAX) == NULL);
|
||||
ASSERT(uv_req_type_name(UV_REQ_TYPE_MAX + 1) == NULL);
|
||||
ASSERT(uv_req_type_name(UV_UNKNOWN_REQ) == NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getters_setters) {
|
||||
uv_loop_t* loop;
|
||||
uv_pipe_t* pipe;
|
||||
uv_fs_t* fs;
|
||||
int r;
|
||||
|
||||
loop = malloc(uv_loop_size());
|
||||
ASSERT(loop != NULL);
|
||||
r = uv_loop_init(loop);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_loop_set_data(loop, &cookie1);
|
||||
ASSERT(loop->data == &cookie1);
|
||||
ASSERT(uv_loop_get_data(loop) == &cookie1);
|
||||
|
||||
pipe = malloc(uv_handle_size(UV_NAMED_PIPE));
|
||||
r = uv_pipe_init(loop, pipe, 0);
|
||||
ASSERT(uv_handle_get_type((uv_handle_t*)pipe) == UV_NAMED_PIPE);
|
||||
|
||||
ASSERT(uv_handle_get_loop((uv_handle_t*)pipe) == loop);
|
||||
pipe->data = &cookie2;
|
||||
ASSERT(uv_handle_get_data((uv_handle_t*)pipe) == &cookie2);
|
||||
uv_handle_set_data((uv_handle_t*)pipe, &cookie1);
|
||||
ASSERT(uv_handle_get_data((uv_handle_t*)pipe) == &cookie1);
|
||||
ASSERT(pipe->data == &cookie1);
|
||||
|
||||
ASSERT(uv_stream_get_write_queue_size((uv_stream_t*)pipe) == 0);
|
||||
pipe->write_queue_size++;
|
||||
ASSERT(uv_stream_get_write_queue_size((uv_stream_t*)pipe) == 1);
|
||||
pipe->write_queue_size--;
|
||||
uv_close((uv_handle_t*)pipe, NULL);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
fs = malloc(uv_req_size(UV_FS));
|
||||
uv_fs_stat(loop, fs, ".", NULL);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(uv_fs_get_type(fs) == UV_FS_STAT);
|
||||
ASSERT(uv_fs_get_result(fs) == 0);
|
||||
ASSERT(uv_fs_get_ptr(fs) == uv_fs_get_statbuf(fs));
|
||||
ASSERT(uv_fs_get_statbuf(fs)->st_mode & S_IFDIR);
|
||||
ASSERT(strcmp(uv_fs_get_path(fs), ".") == 0);
|
||||
uv_fs_req_cleanup(fs);
|
||||
|
||||
r = uv_loop_close(loop);
|
||||
ASSERT(r == 0);
|
||||
|
||||
free(pipe);
|
||||
free(fs);
|
||||
free(loop);
|
||||
return 0;
|
||||
}
|
39
deps/libuv/test/test-gettimeofday.c
vendored
Normal file
39
deps/libuv/test/test-gettimeofday.c
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/* Copyright libuv project 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"
|
||||
|
||||
TEST_IMPL(gettimeofday) {
|
||||
uv_timeval64_t tv;
|
||||
int r;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
r = uv_gettimeofday(&tv);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(tv.tv_sec != 0);
|
||||
|
||||
/* Test invalid input. */
|
||||
r = uv_gettimeofday(NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
125
deps/libuv/test/test-handle-fileno.c
vendored
Normal file
125
deps/libuv/test/test-handle-fileno.c
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
static int get_tty_fd(void) {
|
||||
/* Make sure we have an FD that refers to a tty */
|
||||
#ifdef _WIN32
|
||||
HANDLE handle;
|
||||
handle = CreateFileA("conin$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
return _open_osfhandle((intptr_t) handle, 0);
|
||||
#else /* unix */
|
||||
return open("/dev/tty", O_RDONLY, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(handle_fileno) {
|
||||
int r;
|
||||
int tty_fd;
|
||||
struct sockaddr_in addr;
|
||||
uv_os_fd_t fd;
|
||||
uv_tcp_t tcp;
|
||||
uv_udp_t udp;
|
||||
uv_pipe_t pipe;
|
||||
uv_tty_t tty;
|
||||
uv_idle_t idle;
|
||||
uv_loop_t* loop;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_idle_init(loop, &idle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fileno((uv_handle_t*) &idle, &fd);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
uv_close((uv_handle_t*) &idle, NULL);
|
||||
|
||||
r = uv_tcp_init(loop, &tcp);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fileno((uv_handle_t*) &tcp, &fd);
|
||||
ASSERT(r == UV_EBADF);
|
||||
r = uv_tcp_bind(&tcp, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fileno((uv_handle_t*) &tcp, &fd);
|
||||
ASSERT(r == 0);
|
||||
uv_close((uv_handle_t*) &tcp, NULL);
|
||||
r = uv_fileno((uv_handle_t*) &tcp, &fd);
|
||||
ASSERT(r == UV_EBADF);
|
||||
|
||||
r = uv_udp_init(loop, &udp);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fileno((uv_handle_t*) &udp, &fd);
|
||||
ASSERT(r == UV_EBADF);
|
||||
r = uv_udp_bind(&udp, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fileno((uv_handle_t*) &udp, &fd);
|
||||
ASSERT(r == 0);
|
||||
uv_close((uv_handle_t*) &udp, NULL);
|
||||
r = uv_fileno((uv_handle_t*) &udp, &fd);
|
||||
ASSERT(r == UV_EBADF);
|
||||
|
||||
r = uv_pipe_init(loop, &pipe, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fileno((uv_handle_t*) &pipe, &fd);
|
||||
ASSERT(r == UV_EBADF);
|
||||
r = uv_pipe_bind(&pipe, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fileno((uv_handle_t*) &pipe, &fd);
|
||||
ASSERT(r == 0);
|
||||
uv_close((uv_handle_t*) &pipe, NULL);
|
||||
r = uv_fileno((uv_handle_t*) &pipe, &fd);
|
||||
ASSERT(r == UV_EBADF);
|
||||
|
||||
tty_fd = get_tty_fd();
|
||||
if (tty_fd < 0) {
|
||||
fprintf(stderr, "Cannot open a TTY fd");
|
||||
fflush(stderr);
|
||||
} else {
|
||||
r = uv_tty_init(loop, &tty, tty_fd, 0);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(uv_is_readable((uv_stream_t*) &tty));
|
||||
ASSERT(!uv_is_writable((uv_stream_t*) &tty));
|
||||
r = uv_fileno((uv_handle_t*) &tty, &fd);
|
||||
ASSERT(r == 0);
|
||||
uv_close((uv_handle_t*) &tty, NULL);
|
||||
r = uv_fileno((uv_handle_t*) &tty, &fd);
|
||||
ASSERT(r == UV_EBADF);
|
||||
ASSERT(!uv_is_readable((uv_stream_t*) &tty));
|
||||
ASSERT(!uv_is_writable((uv_stream_t*) &tty));
|
||||
}
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
72
deps/libuv/test/test-homedir.c
vendored
Normal file
72
deps/libuv/test/test-homedir.c
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/* Copyright libuv project 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 <string.h>
|
||||
|
||||
#define PATHMAX 4096
|
||||
#define SMALLPATH 1
|
||||
|
||||
TEST_IMPL(homedir) {
|
||||
char homedir[PATHMAX];
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
/* Test the normal case */
|
||||
len = sizeof homedir;
|
||||
homedir[0] = '\0';
|
||||
ASSERT(strlen(homedir) == 0);
|
||||
r = uv_os_homedir(homedir, &len);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(strlen(homedir) == len);
|
||||
ASSERT(len > 0);
|
||||
ASSERT(homedir[len] == '\0');
|
||||
|
||||
#ifdef _WIN32
|
||||
if (len == 3 && homedir[1] == ':')
|
||||
ASSERT(homedir[2] == '\\');
|
||||
else
|
||||
ASSERT(homedir[len - 1] != '\\');
|
||||
#else
|
||||
if (len == 1)
|
||||
ASSERT(homedir[0] == '/');
|
||||
else
|
||||
ASSERT(homedir[len - 1] != '/');
|
||||
#endif
|
||||
|
||||
/* Test the case where the buffer is too small */
|
||||
len = SMALLPATH;
|
||||
r = uv_os_homedir(homedir, &len);
|
||||
ASSERT(r == UV_ENOBUFS);
|
||||
ASSERT(len > SMALLPATH);
|
||||
|
||||
/* Test invalid inputs */
|
||||
r = uv_os_homedir(NULL, &len);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
r = uv_os_homedir(homedir, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
len = 0;
|
||||
r = uv_os_homedir(homedir, &len);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
52
deps/libuv/test/test-hrtime.c
vendored
Normal file
52
deps/libuv/test/test-hrtime.c
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#ifndef MILLISEC
|
||||
# define MILLISEC 1000
|
||||
#endif
|
||||
|
||||
#ifndef NANOSEC
|
||||
# define NANOSEC ((uint64_t) 1e9)
|
||||
#endif
|
||||
|
||||
|
||||
TEST_IMPL(hrtime) {
|
||||
uint64_t a, b, diff;
|
||||
int i = 75;
|
||||
while (i > 0) {
|
||||
a = uv_hrtime();
|
||||
uv_sleep(45);
|
||||
b = uv_hrtime();
|
||||
|
||||
diff = b - a;
|
||||
|
||||
/* The windows Sleep() function has only a resolution of 10-20 ms. Check
|
||||
* that the difference between the two hrtime values has a reasonable
|
||||
* lower bound.
|
||||
*/
|
||||
ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC);
|
||||
--i;
|
||||
}
|
||||
return 0;
|
||||
}
|
99
deps/libuv/test/test-idle.c
vendored
Normal file
99
deps/libuv/test/test-idle.c
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
static uv_idle_t idle_handle;
|
||||
static uv_check_t check_handle;
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
static int idle_cb_called = 0;
|
||||
static int check_cb_called = 0;
|
||||
static int timer_cb_called = 0;
|
||||
static int close_cb_called = 0;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(handle == &timer_handle);
|
||||
|
||||
uv_close((uv_handle_t*) &idle_handle, close_cb);
|
||||
uv_close((uv_handle_t*) &check_handle, close_cb);
|
||||
uv_close((uv_handle_t*) &timer_handle, close_cb);
|
||||
|
||||
timer_cb_called++;
|
||||
fprintf(stderr, "timer_cb %d\n", timer_cb_called);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
static void idle_cb(uv_idle_t* handle) {
|
||||
ASSERT(handle == &idle_handle);
|
||||
|
||||
idle_cb_called++;
|
||||
fprintf(stderr, "idle_cb %d\n", idle_cb_called);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
static void check_cb(uv_check_t* handle) {
|
||||
ASSERT(handle == &check_handle);
|
||||
|
||||
check_cb_called++;
|
||||
fprintf(stderr, "check_cb %d\n", check_cb_called);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(idle_starvation) {
|
||||
int r;
|
||||
|
||||
r = uv_idle_init(uv_default_loop(), &idle_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_idle_start(&idle_handle, idle_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_check_init(uv_default_loop(), &check_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_check_start(&check_handle, check_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_timer_init(uv_default_loop(), &timer_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&timer_handle, timer_cb, 50, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(idle_cb_called > 0);
|
||||
ASSERT(timer_cb_called == 1);
|
||||
ASSERT(close_cb_called == 3);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
195
deps/libuv/test/test-idna.c
vendored
Normal file
195
deps/libuv/test/test-idna.c
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/* Copyright The 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 "task.h"
|
||||
#include "../src/idna.c"
|
||||
#include <string.h>
|
||||
|
||||
TEST_IMPL(utf8_decode1) {
|
||||
const char* p;
|
||||
char b[32];
|
||||
int i;
|
||||
|
||||
/* ASCII. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "%c\x7F", 0x00);
|
||||
ASSERT(0 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 1);
|
||||
ASSERT(127 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 2);
|
||||
|
||||
/* Two-byte sequences. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "\xC2\x80\xDF\xBF");
|
||||
ASSERT(128 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 2);
|
||||
ASSERT(0x7FF == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 4);
|
||||
|
||||
/* Three-byte sequences. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "\xE0\xA0\x80\xEF\xBF\xBF");
|
||||
ASSERT(0x800 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 3);
|
||||
ASSERT(0xFFFF == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 6);
|
||||
|
||||
/* Four-byte sequences. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "\xF0\x90\x80\x80\xF4\x8F\xBF\xBF");
|
||||
ASSERT(0x10000 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 4);
|
||||
ASSERT(0x10FFFF == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 8);
|
||||
|
||||
/* Four-byte sequences > U+10FFFF; disallowed. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "\xF4\x90\xC0\xC0\xF7\xBF\xBF\xBF");
|
||||
ASSERT((unsigned) -1 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 4);
|
||||
ASSERT((unsigned) -1 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 8);
|
||||
|
||||
/* Overlong; disallowed. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "\xC0\x80\xC1\x80");
|
||||
ASSERT((unsigned) -1 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 2);
|
||||
ASSERT((unsigned) -1 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 4);
|
||||
|
||||
/* Surrogate pairs; disallowed. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "\xED\xA0\x80\xED\xA3\xBF");
|
||||
ASSERT((unsigned) -1 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 3);
|
||||
ASSERT((unsigned) -1 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + 6);
|
||||
|
||||
/* Simply illegal. */
|
||||
p = b;
|
||||
snprintf(b, sizeof(b), "\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF");
|
||||
|
||||
for (i = 1; i <= 8; i++) {
|
||||
ASSERT((unsigned) -1 == uv__utf8_decode1(&p, b + sizeof(b)));
|
||||
ASSERT(p == b + i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Doesn't work on z/OS because that platform uses EBCDIC, not ASCII. */
|
||||
#ifndef __MVS__
|
||||
|
||||
#define F(input, err) \
|
||||
do { \
|
||||
char d[256] = {0}; \
|
||||
static const char s[] = "" input ""; \
|
||||
ASSERT(err == uv__idna_toascii(s, s + sizeof(s) - 1, d, d + sizeof(d))); \
|
||||
} while (0)
|
||||
|
||||
#define T(input, expected) \
|
||||
do { \
|
||||
long n; \
|
||||
char d1[256] = {0}; \
|
||||
char d2[256] = {0}; \
|
||||
static const char s[] = "" input ""; \
|
||||
n = uv__idna_toascii(s, s + sizeof(s) - 1, d1, d1 + sizeof(d1)); \
|
||||
ASSERT(n == sizeof(expected)); \
|
||||
ASSERT(0 == memcmp(d1, expected, n)); \
|
||||
/* Sanity check: encoding twice should not change the output. */ \
|
||||
n = uv__idna_toascii(d1, d1 + strlen(d1), d2, d2 + sizeof(d2)); \
|
||||
ASSERT(n == sizeof(expected)); \
|
||||
ASSERT(0 == memcmp(d2, expected, n)); \
|
||||
ASSERT(0 == memcmp(d1, d2, sizeof(d2))); \
|
||||
} while (0)
|
||||
|
||||
TEST_IMPL(idna_toascii) {
|
||||
/* Illegal inputs. */
|
||||
F("\xC0\x80\xC1\x80", UV_EINVAL); /* Overlong UTF-8 sequence. */
|
||||
F("\xC0\x80\xC1\x80.com", UV_EINVAL); /* Overlong UTF-8 sequence. */
|
||||
/* No conversion. */
|
||||
T("", "");
|
||||
T(".", ".");
|
||||
T(".com", ".com");
|
||||
T("example", "example");
|
||||
T("example-", "example-");
|
||||
T("straße.de", "xn--strae-oqa.de");
|
||||
/* Test cases adapted from punycode.js. Most are from RFC 3492. */
|
||||
T("foo.bar", "foo.bar");
|
||||
T("mañana.com", "xn--maana-pta.com");
|
||||
T("example.com.", "example.com.");
|
||||
T("bücher.com", "xn--bcher-kva.com");
|
||||
T("café.com", "xn--caf-dma.com");
|
||||
T("café.café.com", "xn--caf-dma.xn--caf-dma.com");
|
||||
T("☃-⌘.com", "xn----dqo34k.com");
|
||||
T("퐀☃-⌘.com", "xn----dqo34kn65z.com");
|
||||
T("💩.la", "xn--ls8h.la");
|
||||
T("mañana.com", "xn--maana-pta.com");
|
||||
T("mañana。com", "xn--maana-pta.com");
|
||||
T("mañana.com", "xn--maana-pta.com");
|
||||
T("mañana。com", "xn--maana-pta.com");
|
||||
T("ü", "xn--tda");
|
||||
T(".ü", ".xn--tda");
|
||||
T("ü.ü", "xn--tda.xn--tda");
|
||||
T("ü.ü.", "xn--tda.xn--tda.");
|
||||
T("üëäö♥", "xn--4can8av2009b");
|
||||
T("Willst du die Blüthe des frühen, die Früchte des späteren Jahres",
|
||||
"xn--Willst du die Blthe des frhen, "
|
||||
"die Frchte des spteren Jahres-x9e96lkal");
|
||||
T("ليهمابتكلموشعربي؟", "xn--egbpdaj6bu4bxfgehfvwxn");
|
||||
T("他们为什么不说中文", "xn--ihqwcrb4cv8a8dqg056pqjye");
|
||||
T("他們爲什麽不說中文", "xn--ihqwctvzc91f659drss3x8bo0yb");
|
||||
T("Pročprostěnemluvíčesky", "xn--Proprostnemluvesky-uyb24dma41a");
|
||||
T("למההםפשוטלאמדבריםעברית", "xn--4dbcagdahymbxekheh6e0a7fei0b");
|
||||
T("यहलोगहिन्दीक्योंनहींबोलसकतेहैं",
|
||||
"xn--i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd");
|
||||
T("なぜみんな日本語を話してくれないのか",
|
||||
"xn--n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa");
|
||||
T("세계의모든사람들이한국어를이해한다면얼마나좋을까",
|
||||
"xn--989aomsvi5e83db1d2a355cv1e0vak1d"
|
||||
"wrv93d5xbh15a0dt30a5jpsd879ccm6fea98c");
|
||||
T("почемужеонинеговорятпорусски", "xn--b1abfaaepdrnnbgefbadotcwatmq2g4l");
|
||||
T("PorquénopuedensimplementehablarenEspañol",
|
||||
"xn--PorqunopuedensimplementehablarenEspaol-fmd56a");
|
||||
T("TạisaohọkhôngthểchỉnóitiếngViệt",
|
||||
"xn--TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g");
|
||||
T("3年B組金八先生", "xn--3B-ww4c5e180e575a65lsy2b");
|
||||
T("安室奈美恵-with-SUPER-MONKEYS",
|
||||
"xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n");
|
||||
T("Hello-Another-Way-それぞれの場所",
|
||||
"xn--Hello-Another-Way--fc4qua05auwb3674vfr0b");
|
||||
T("ひとつ屋根の下2", "xn--2-u9tlzr9756bt3uc0v");
|
||||
T("MajiでKoiする5秒前", "xn--MajiKoi5-783gue6qz075azm5e");
|
||||
T("パフィーdeルンバ", "xn--de-jg4avhby1noc0d");
|
||||
T("そのスピードで", "xn--d9juau41awczczp");
|
||||
T("-> $1.00 <-", "-> $1.00 <-");
|
||||
/* Test cases from https://unicode.org/reports/tr46/ */
|
||||
T("faß.de", "xn--fa-hia.de");
|
||||
T("βόλος.com", "xn--nxasmm1c.com");
|
||||
T("ශ්රී.com", "xn--10cl1a0b660p.com");
|
||||
T("نامهای.com", "xn--mgba3gch31f060k.com");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef T
|
||||
|
||||
#endif /* __MVS__ */
|
55
deps/libuv/test/test-ip4-addr.c
vendored
Normal file
55
deps/libuv/test/test-ip4-addr.c
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
TEST_IMPL(ip4_addr) {
|
||||
struct sockaddr_in addr;
|
||||
char dst[16];
|
||||
|
||||
ASSERT(0 == uv_inet_ntop(AF_INET, "\xFF\xFF\xFF\xFF", dst, sizeof(dst)));
|
||||
ASSERT(0 == strcmp(dst, "255.255.255.255"));
|
||||
ASSERT(UV_ENOSPC == uv_inet_ntop(AF_INET, "\xFF\xFF\xFF\xFF",
|
||||
dst, sizeof(dst) - 1));
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
ASSERT(0 == uv_ip4_addr("255.255.255.255", TEST_PORT, &addr));
|
||||
ASSERT(UV_EINVAL == uv_ip4_addr("255.255.255*000", TEST_PORT, &addr));
|
||||
ASSERT(UV_EINVAL == uv_ip4_addr("255.255.255.256", TEST_PORT, &addr));
|
||||
ASSERT(UV_EINVAL == uv_ip4_addr("2555.0.0.0", TEST_PORT, &addr));
|
||||
ASSERT(UV_EINVAL == uv_ip4_addr("255", TEST_PORT, &addr));
|
||||
|
||||
#ifdef SIN6_LEN
|
||||
ASSERT(addr.sin_len == sizeof(addr));
|
||||
#endif
|
||||
|
||||
/* for broken address family */
|
||||
ASSERT(UV_EAFNOSUPPORT == uv_inet_pton(42, "127.0.0.1",
|
||||
&addr.sin_addr.s_addr));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
171
deps/libuv/test/test-ip6-addr.c
vendored
Normal file
171
deps/libuv/test/test-ip6-addr.c
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __linux__
|
||||
# include <sys/socket.h>
|
||||
# include <net/if.h>
|
||||
#endif
|
||||
|
||||
|
||||
TEST_IMPL(ip6_addr_link_local) {
|
||||
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||
/* FIXME: Does Cygwin support this? */
|
||||
RETURN_SKIP("FIXME: This test needs more investigation on Cygwin");
|
||||
#endif
|
||||
char string_address[INET6_ADDRSTRLEN];
|
||||
uv_interface_address_t* addresses;
|
||||
uv_interface_address_t* address;
|
||||
struct sockaddr_in6 addr;
|
||||
unsigned int iface_index;
|
||||
const char* device_name;
|
||||
/* 40 bytes address, 16 bytes device name, plus reserve. */
|
||||
char scoped_addr[128];
|
||||
size_t scoped_addr_len;
|
||||
char interface_id[UV_IF_NAMESIZE];
|
||||
size_t interface_id_len;
|
||||
int count;
|
||||
int ix;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_interface_addresses(&addresses, &count));
|
||||
|
||||
for (ix = 0; ix < count; ix++) {
|
||||
address = addresses + ix;
|
||||
|
||||
if (address->address.address6.sin6_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
ASSERT(0 == uv_inet_ntop(AF_INET6,
|
||||
&address->address.address6.sin6_addr,
|
||||
string_address,
|
||||
sizeof(string_address)));
|
||||
|
||||
/* Skip addresses that are not link-local. */
|
||||
if (strncmp(string_address, "fe80::", 6) != 0)
|
||||
continue;
|
||||
|
||||
iface_index = address->address.address6.sin6_scope_id;
|
||||
device_name = address->name;
|
||||
|
||||
scoped_addr_len = sizeof(scoped_addr);
|
||||
ASSERT(0 == uv_if_indextoname(iface_index, scoped_addr, &scoped_addr_len));
|
||||
#ifndef _WIN32
|
||||
/* This assert fails on Windows, as Windows semantics are different. */
|
||||
ASSERT(0 == strcmp(device_name, scoped_addr));
|
||||
#endif
|
||||
|
||||
interface_id_len = sizeof(interface_id);
|
||||
r = uv_if_indextoiid(iface_index, interface_id, &interface_id_len);
|
||||
ASSERT(0 == r);
|
||||
#ifdef _WIN32
|
||||
/* On Windows, the interface identifier is the numeric string of the index. */
|
||||
ASSERT(strtoul(interface_id, NULL, 10) == iface_index);
|
||||
#else
|
||||
/* On Unix/Linux, the interface identifier is the interface device name. */
|
||||
ASSERT(0 == strcmp(device_name, interface_id));
|
||||
#endif
|
||||
|
||||
snprintf(scoped_addr,
|
||||
sizeof(scoped_addr),
|
||||
"%s%%%s",
|
||||
string_address,
|
||||
interface_id);
|
||||
|
||||
fprintf(stderr, "Testing link-local address %s "
|
||||
"(iface_index: 0x%02x, device_name: %s)\n",
|
||||
scoped_addr,
|
||||
iface_index,
|
||||
device_name);
|
||||
fflush(stderr);
|
||||
|
||||
ASSERT(0 == uv_ip6_addr(scoped_addr, TEST_PORT, &addr));
|
||||
fprintf(stderr, "Got scope_id 0x%02x\n", addr.sin6_scope_id);
|
||||
fflush(stderr);
|
||||
ASSERT(iface_index == addr.sin6_scope_id);
|
||||
}
|
||||
|
||||
uv_free_interface_addresses(addresses, count);
|
||||
|
||||
scoped_addr_len = sizeof(scoped_addr);
|
||||
ASSERT(0 != uv_if_indextoname((unsigned int)-1, scoped_addr, &scoped_addr_len));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define GOOD_ADDR_LIST(X) \
|
||||
X("::") \
|
||||
X("::1") \
|
||||
X("fe80::1") \
|
||||
X("fe80::") \
|
||||
X("fe80::2acf:daff:fedd:342a") \
|
||||
X("fe80:0:0:0:2acf:daff:fedd:342a") \
|
||||
X("fe80:0:0:0:2acf:daff:1.2.3.4") \
|
||||
X("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") \
|
||||
|
||||
#define BAD_ADDR_LIST(X) \
|
||||
X(":::1") \
|
||||
X("abcde::1") \
|
||||
X("fe80:0:0:0:2acf:daff:fedd:342a:5678") \
|
||||
X("fe80:0:0:0:2acf:daff:abcd:1.2.3.4") \
|
||||
X("fe80:0:0:2acf:daff:1.2.3.4.5") \
|
||||
X("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255.255") \
|
||||
|
||||
#define TEST_GOOD(ADDR) \
|
||||
ASSERT(0 == uv_inet_pton(AF_INET6, ADDR, &addr)); \
|
||||
ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \
|
||||
ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \
|
||||
ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \
|
||||
|
||||
#define TEST_BAD(ADDR) \
|
||||
ASSERT(0 != uv_inet_pton(AF_INET6, ADDR, &addr)); \
|
||||
ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \
|
||||
ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \
|
||||
ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \
|
||||
|
||||
TEST_IMPL(ip6_pton) {
|
||||
struct in6_addr addr;
|
||||
|
||||
GOOD_ADDR_LIST(TEST_GOOD)
|
||||
BAD_ADDR_LIST(TEST_BAD)
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef GOOD_ADDR_LIST
|
||||
#undef BAD_ADDR_LIST
|
||||
|
||||
#ifdef SIN6_LEN
|
||||
TEST_IMPL(ip6_sin6_len) {
|
||||
struct sockaddr_in6 s;
|
||||
ASSERT(uv_ip6_addr("::", 0, &s) < 0);
|
||||
ASSERT(s.sin6_len == sizeof(s));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
159
deps/libuv/test/test-ipc-heavy-traffic-deadlock-bug.c
vendored
Normal file
159
deps/libuv/test/test-ipc-heavy-traffic-deadlock-bug.c
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
/* Copyright libuv project 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 "task.h"
|
||||
#include "uv.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* See test-ipc.c */
|
||||
void spawn_helper(uv_pipe_t* channel,
|
||||
uv_process_t* process,
|
||||
const char* helper);
|
||||
|
||||
#define NUM_WRITES 256
|
||||
#define BUFFERS_PER_WRITE 3
|
||||
#define BUFFER_SIZE 0x2000 /* 8 kb. */
|
||||
#define BUFFER_CONTENT 42
|
||||
|
||||
#define XFER_SIZE (NUM_WRITES * BUFFERS_PER_WRITE * BUFFER_SIZE)
|
||||
|
||||
struct write_info {
|
||||
uv_write_t write_req;
|
||||
char buffers[BUFFER_SIZE][BUFFERS_PER_WRITE];
|
||||
};
|
||||
|
||||
static uv_shutdown_t shutdown_req;
|
||||
|
||||
static size_t bytes_written;
|
||||
static size_t bytes_read;
|
||||
|
||||
static void write_cb(uv_write_t* req, int status) {
|
||||
struct write_info* write_info =
|
||||
container_of(req, struct write_info, write_req);
|
||||
ASSERT(status == 0);
|
||||
bytes_written += BUFFERS_PER_WRITE * BUFFER_SIZE;
|
||||
free(write_info);
|
||||
}
|
||||
|
||||
static void shutdown_cb(uv_shutdown_t* req, int status) {
|
||||
ASSERT(status == 0 || status == UV_ENOTCONN);
|
||||
uv_close((uv_handle_t*) req->handle, NULL);
|
||||
}
|
||||
|
||||
static void do_write(uv_stream_t* handle) {
|
||||
struct write_info* write_info;
|
||||
uv_buf_t bufs[BUFFERS_PER_WRITE];
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
write_info = malloc(sizeof *write_info);
|
||||
ASSERT(write_info != NULL);
|
||||
|
||||
for (i = 0; i < BUFFERS_PER_WRITE; i++) {
|
||||
memset(&write_info->buffers[i], BUFFER_CONTENT, BUFFER_SIZE);
|
||||
bufs[i] = uv_buf_init(write_info->buffers[i], BUFFER_SIZE);
|
||||
}
|
||||
|
||||
r = uv_write(
|
||||
&write_info->write_req, handle, bufs, BUFFERS_PER_WRITE, write_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = (int) suggested_size;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
|
||||
ssize_t i;
|
||||
int r;
|
||||
|
||||
ASSERT(nread >= 0);
|
||||
bytes_read += nread;
|
||||
|
||||
for (i = 0; i < nread; i++)
|
||||
ASSERT(buf->base[i] == BUFFER_CONTENT);
|
||||
free(buf->base);
|
||||
|
||||
if (bytes_read >= XFER_SIZE) {
|
||||
r = uv_read_stop(handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_shutdown(&shutdown_req, handle, shutdown_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_writes_and_reads(uv_stream_t* handle) {
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
bytes_written = 0;
|
||||
bytes_read = 0;
|
||||
|
||||
for (i = 0; i < NUM_WRITES; i++) {
|
||||
do_write(handle);
|
||||
}
|
||||
|
||||
r = uv_read_start(handle, alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(handle->loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(bytes_written == XFER_SIZE);
|
||||
ASSERT(bytes_read == XFER_SIZE);
|
||||
}
|
||||
|
||||
TEST_IMPL(ipc_heavy_traffic_deadlock_bug) {
|
||||
uv_pipe_t pipe;
|
||||
uv_process_t process;
|
||||
|
||||
spawn_helper(&pipe, &process, "ipc_helper_heavy_traffic_deadlock_bug");
|
||||
do_writes_and_reads((uv_stream_t*) &pipe);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipc_helper_heavy_traffic_deadlock_bug(void) {
|
||||
uv_pipe_t pipe;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &pipe, 1);
|
||||
ASSERT(r == 0);
|
||||
r = uv_pipe_open(&pipe, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
notify_parent_process();
|
||||
do_writes_and_reads((uv_stream_t*) &pipe);
|
||||
uv_sleep(100);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
429
deps/libuv/test/test-ipc-send-recv.c
vendored
Normal file
429
deps/libuv/test/test-ipc-send-recv.c
vendored
Normal file
@ -0,0 +1,429 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* See test-ipc.c */
|
||||
void spawn_helper(uv_pipe_t* channel,
|
||||
uv_process_t* process,
|
||||
const char* helper);
|
||||
|
||||
void ipc_send_recv_helper_threadproc(void* arg);
|
||||
|
||||
union handles {
|
||||
uv_handle_t handle;
|
||||
uv_stream_t stream;
|
||||
uv_pipe_t pipe;
|
||||
uv_tcp_t tcp;
|
||||
uv_tty_t tty;
|
||||
};
|
||||
|
||||
struct test_ctx {
|
||||
uv_pipe_t channel;
|
||||
uv_connect_t connect_req;
|
||||
uv_write_t write_req;
|
||||
uv_write_t write_req2;
|
||||
uv_handle_type expected_type;
|
||||
union handles send;
|
||||
union handles send2;
|
||||
union handles recv;
|
||||
union handles recv2;
|
||||
};
|
||||
|
||||
struct echo_ctx {
|
||||
uv_pipe_t listen;
|
||||
uv_pipe_t channel;
|
||||
uv_write_t write_req;
|
||||
uv_write_t write_req2;
|
||||
uv_handle_type expected_type;
|
||||
union handles recv;
|
||||
union handles recv2;
|
||||
};
|
||||
|
||||
static struct test_ctx ctx;
|
||||
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_count;
|
||||
static int recv_cb_count;
|
||||
static int write2_cb_called;
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
/* we're not actually reading anything so a small buffer is okay */
|
||||
static char slab[8];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void recv_cb(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
uv_handle_type pending;
|
||||
uv_pipe_t* pipe;
|
||||
int r;
|
||||
union handles* recv;
|
||||
|
||||
pipe = (uv_pipe_t*) handle;
|
||||
ASSERT(pipe == &ctx.channel);
|
||||
|
||||
do {
|
||||
if (++recv_cb_count == 1) {
|
||||
recv = &ctx.recv;
|
||||
} else {
|
||||
recv = &ctx.recv2;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
pending = uv_pipe_pending_type(pipe);
|
||||
ASSERT(pending == ctx.expected_type);
|
||||
|
||||
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_count == 2) {
|
||||
uv_close((uv_handle_t*)&ctx.channel, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
int r;
|
||||
uv_buf_t buf;
|
||||
|
||||
ASSERT(req == &ctx.connect_req);
|
||||
ASSERT(status == 0);
|
||||
|
||||
buf = uv_buf_init(".", 1);
|
||||
r = uv_write2(&ctx.write_req,
|
||||
(uv_stream_t*)&ctx.channel,
|
||||
&buf, 1,
|
||||
&ctx.send.stream,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Perform two writes to the same pipe to make sure that on Windows we are
|
||||
* not running into issue 505:
|
||||
* https://github.com/libuv/libuv/issues/505 */
|
||||
buf = uv_buf_init(".", 1);
|
||||
r = uv_write2(&ctx.write_req2,
|
||||
(uv_stream_t*)&ctx.channel,
|
||||
&buf, 1,
|
||||
&ctx.send2.stream,
|
||||
NULL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
static int run_test(int inprocess) {
|
||||
uv_process_t process;
|
||||
uv_thread_t tid;
|
||||
int r;
|
||||
|
||||
if (inprocess) {
|
||||
r = uv_thread_create(&tid, ipc_send_recv_helper_threadproc, (void *) 42);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_sleep(1000);
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_pipe_connect(&ctx.connect_req, &ctx.channel, TEST_PIPENAME_3, connect_cb);
|
||||
} else {
|
||||
spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper");
|
||||
|
||||
connect_cb(&ctx.connect_req, 0);
|
||||
}
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(recv_cb_count == 2);
|
||||
|
||||
if (inprocess) {
|
||||
r = uv_thread_join(&tid);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_ipc_send_recv_pipe(int inprocess) {
|
||||
int r;
|
||||
|
||||
ctx.expected_type = UV_NAMED_PIPE;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &ctx.send.pipe, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_bind(&ctx.send.pipe, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &ctx.send2.pipe, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_bind(&ctx.send2.pipe, TEST_PIPENAME_2);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = run_test(inprocess);
|
||||
ASSERT(r == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(ipc_send_recv_pipe) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
return run_ipc_send_recv_pipe(0);
|
||||
}
|
||||
|
||||
TEST_IMPL(ipc_send_recv_pipe_inprocess) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
return run_ipc_send_recv_pipe(1);
|
||||
}
|
||||
|
||||
static int run_ipc_send_recv_tcp(int inprocess) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
ctx.expected_type = UV_TCP;
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &ctx.send.tcp);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &ctx.send2.tcp);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&ctx.send.tcp, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&ctx.send2.tcp, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = run_test(inprocess);
|
||||
ASSERT(r == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(ipc_send_recv_tcp) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
return run_ipc_send_recv_tcp(0);
|
||||
}
|
||||
|
||||
TEST_IMPL(ipc_send_recv_tcp_inprocess) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
return run_ipc_send_recv_tcp(1);
|
||||
}
|
||||
|
||||
|
||||
/* Everything here runs in a child process or second thread. */
|
||||
|
||||
static void write2_cb(uv_write_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
|
||||
/* After two successful writes in the child process, allow the child
|
||||
* process to be closed. */
|
||||
if (++write2_cb_called == 2 && (is_child_process || is_in_process)) {
|
||||
uv_close(&ctx2.recv.handle, NULL);
|
||||
uv_close(&ctx2.recv2.handle, NULL);
|
||||
uv_close((uv_handle_t*)&ctx2.channel, NULL);
|
||||
uv_close((uv_handle_t*)&ctx2.listen, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void read_cb(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* rdbuf) {
|
||||
uv_buf_t wrbuf;
|
||||
uv_pipe_t* pipe;
|
||||
uv_handle_type pending;
|
||||
int r;
|
||||
union handles* recv;
|
||||
uv_write_t* write_req;
|
||||
|
||||
if (nread == UV_EOF || nread == UV_ECONNABORTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
pipe = (uv_pipe_t*) handle;
|
||||
do {
|
||||
if (++read_cb_count == 2) {
|
||||
recv = &ctx2.recv;
|
||||
write_req = &ctx2.write_req;
|
||||
} else {
|
||||
recv = &ctx2.recv2;
|
||||
write_req = &ctx2.write_req2;
|
||||
}
|
||||
|
||||
ASSERT(pipe == &ctx2.channel);
|
||||
ASSERT(nread >= 0);
|
||||
ASSERT(uv_pipe_pending_count(pipe) > 0);
|
||||
|
||||
pending = uv_pipe_pending_type(pipe);
|
||||
ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP);
|
||||
|
||||
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);
|
||||
|
||||
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(void) {
|
||||
int r;
|
||||
ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx2.channel));
|
||||
ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx2.channel));
|
||||
ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx2.channel));
|
||||
|
||||
r = uv_read_start((uv_stream_t*)&ctx2.channel, alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
static void listen_cb(uv_stream_t* handle, int status) {
|
||||
int r;
|
||||
ASSERT(handle == (uv_stream_t*)&ctx2.listen);
|
||||
ASSERT(status == 0);
|
||||
|
||||
r = uv_accept((uv_stream_t*)&ctx2.listen, (uv_stream_t*)&ctx2.channel);
|
||||
ASSERT(r == 0);
|
||||
|
||||
send_recv_start();
|
||||
}
|
||||
|
||||
int run_ipc_send_recv_helper(uv_loop_t* loop, int inprocess) {
|
||||
int r;
|
||||
|
||||
is_in_process = inprocess;
|
||||
|
||||
memset(&ctx2, 0, sizeof(ctx2));
|
||||
|
||||
r = uv_pipe_init(loop, &ctx2.listen, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_init(loop, &ctx2.channel, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
if (inprocess) {
|
||||
r = uv_pipe_bind(&ctx2.listen, TEST_PIPENAME_3);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&ctx2.listen, SOMAXCONN, listen_cb);
|
||||
ASSERT(r == 0);
|
||||
} else {
|
||||
r = uv_pipe_open(&ctx2.channel, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
send_recv_start();
|
||||
}
|
||||
|
||||
notify_parent_process();
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stdin is a duplex channel over which a handle is sent.
|
||||
* We receive it and send it back where it came from.
|
||||
*/
|
||||
int ipc_send_recv_helper(void) {
|
||||
int r;
|
||||
|
||||
r = run_ipc_send_recv_helper(uv_default_loop(), 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipc_send_recv_helper_threadproc(void* arg) {
|
||||
int r;
|
||||
uv_loop_t loop;
|
||||
|
||||
r = uv_loop_init(&loop);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = run_ipc_send_recv_helper(&loop, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_loop_close(&loop);
|
||||
ASSERT(r == 0);
|
||||
}
|
979
deps/libuv/test/test-ipc.c
vendored
Normal file
979
deps/libuv/test/test-ipc.c
vendored
Normal file
@ -0,0 +1,979 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static uv_pipe_t channel;
|
||||
static uv_tcp_t tcp_server;
|
||||
static uv_tcp_t tcp_server2;
|
||||
static uv_tcp_t tcp_connection;
|
||||
|
||||
static int exit_cb_called;
|
||||
static int read_cb_called;
|
||||
static int tcp_write_cb_called;
|
||||
static int tcp_read_cb_called;
|
||||
static int on_pipe_read_called;
|
||||
static int local_conn_accepted;
|
||||
static int remote_conn_accepted;
|
||||
static int tcp_server_listening;
|
||||
static uv_write_t write_req;
|
||||
static uv_write_t write_req2;
|
||||
static uv_write_t conn_notify_req;
|
||||
static int close_cb_called;
|
||||
static int connection_accepted;
|
||||
static int tcp_conn_read_cb_called;
|
||||
static int tcp_conn_write_cb_called;
|
||||
static int closed_handle_data_read;
|
||||
static int closed_handle_write;
|
||||
static int send_zero_write;
|
||||
|
||||
typedef struct {
|
||||
uv_connect_t conn_req;
|
||||
uv_write_t tcp_write_req;
|
||||
uv_tcp_t conn;
|
||||
} tcp_conn;
|
||||
|
||||
#define CONN_COUNT 100
|
||||
#define BACKLOG 128
|
||||
#define LARGE_SIZE 100000
|
||||
|
||||
static uv_buf_t large_buf;
|
||||
static char buffer[LARGE_SIZE];
|
||||
static uv_write_t write_reqs[300];
|
||||
static int write_reqs_completed;
|
||||
|
||||
static unsigned int write_until_data_queued(void);
|
||||
static void send_handle_and_close(void);
|
||||
|
||||
|
||||
static void close_server_conn_cb(uv_handle_t* handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status) {
|
||||
uv_tcp_t* conn;
|
||||
int r;
|
||||
|
||||
if (!local_conn_accepted) {
|
||||
/* Accept the connection and close it. Also and close the server. */
|
||||
ASSERT_EQ(status, 0);
|
||||
ASSERT_PTR_EQ(&tcp_server, server);
|
||||
|
||||
conn = malloc(sizeof(*conn));
|
||||
ASSERT_NOT_NULL(conn);
|
||||
r = uv_tcp_init(server->loop, conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_close((uv_handle_t*)conn, close_server_conn_cb);
|
||||
uv_close((uv_handle_t*)server, NULL);
|
||||
local_conn_accepted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void exit_cb(uv_process_t* process,
|
||||
int64_t exit_status,
|
||||
int term_signal) {
|
||||
printf("exit_cb\n");
|
||||
exit_cb_called++;
|
||||
ASSERT_EQ(exit_status, 0);
|
||||
ASSERT_EQ(term_signal, 0);
|
||||
uv_close((uv_handle_t*)process, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void on_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
|
||||
static void close_client_conn_cb(uv_handle_t* handle) {
|
||||
tcp_conn* p = (tcp_conn*)handle->data;
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
uv_close((uv_handle_t*)req->handle, close_client_conn_cb);
|
||||
}
|
||||
|
||||
|
||||
static void make_many_connections(void) {
|
||||
tcp_conn* conn;
|
||||
struct sockaddr_in addr;
|
||||
int r, i;
|
||||
|
||||
for (i = 0; i < CONN_COUNT; i++) {
|
||||
conn = malloc(sizeof(*conn));
|
||||
ASSERT_NOT_NULL(conn);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &conn->conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_connect(&conn->conn_req,
|
||||
(uv_tcp_t*) &conn->conn,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
conn->conn.data = conn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_read(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
int r;
|
||||
uv_pipe_t* pipe;
|
||||
uv_handle_type pending;
|
||||
uv_buf_t outbuf;
|
||||
|
||||
pipe = (uv_pipe_t*) handle;
|
||||
|
||||
if (nread == 0) {
|
||||
/* Everything OK, but nothing read. */
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread == UV_EOF) {
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("error recving on channel: %s\n", uv_strerror(nread));
|
||||
abort();
|
||||
}
|
||||
|
||||
fprintf(stderr, "got %d bytes\n", (int)nread);
|
||||
|
||||
pending = uv_pipe_pending_type(pipe);
|
||||
if (!tcp_server_listening) {
|
||||
ASSERT_EQ(1, uv_pipe_pending_count(pipe));
|
||||
ASSERT_GT(nread, 0);
|
||||
ASSERT_NOT_NULL(buf->base);
|
||||
ASSERT_NE(pending, UV_UNKNOWN_HANDLE);
|
||||
read_cb_called++;
|
||||
|
||||
/* Accept the pending TCP server, and start listening on it. */
|
||||
ASSERT_EQ(pending, UV_TCP);
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
tcp_server_listening = 1;
|
||||
|
||||
/* Make sure that the expected data is correctly multiplexed. */
|
||||
ASSERT_MEM_EQ("hello\n", buf->base, nread);
|
||||
|
||||
outbuf = uv_buf_init("world\n", 6);
|
||||
r = uv_write(&write_req, (uv_stream_t*)pipe, &outbuf, 1, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
/* Create a bunch of connections to get both servers to accept. */
|
||||
make_many_connections();
|
||||
} else if (memcmp("accepted_connection\n", buf->base, nread) == 0) {
|
||||
/* Remote server has accepted a connection. Close the channel. */
|
||||
ASSERT_EQ(0, uv_pipe_pending_count(pipe));
|
||||
ASSERT_EQ(pending, UV_UNKNOWN_HANDLE);
|
||||
remote_conn_accepted = 1;
|
||||
uv_close((uv_handle_t*)&channel, NULL);
|
||||
}
|
||||
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void on_read_listen_after_bound_twice(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
int r;
|
||||
uv_pipe_t* pipe;
|
||||
uv_handle_type pending;
|
||||
|
||||
pipe = (uv_pipe_t*) handle;
|
||||
|
||||
if (nread == 0) {
|
||||
/* Everything OK, but nothing read. */
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread == UV_EOF) {
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("error recving on channel: %s\n", uv_strerror(nread));
|
||||
abort();
|
||||
}
|
||||
|
||||
fprintf(stderr, "got %d bytes\n", (int)nread);
|
||||
|
||||
ASSERT_GT(uv_pipe_pending_count(pipe), 0);
|
||||
pending = uv_pipe_pending_type(pipe);
|
||||
ASSERT_GT(nread, 0);
|
||||
ASSERT_NOT_NULL(buf->base);
|
||||
ASSERT_NE(pending, UV_UNKNOWN_HANDLE);
|
||||
read_cb_called++;
|
||||
|
||||
if (read_cb_called == 1) {
|
||||
/* Accept the first TCP server, and start listening on it. */
|
||||
ASSERT_EQ(pending, UV_TCP);
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
} else if (read_cb_called == 2) {
|
||||
/* Accept the second TCP server, and start listening on it. */
|
||||
ASSERT_EQ(pending, UV_TCP);
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server2);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server2);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcp_server2, BACKLOG, on_connection);
|
||||
ASSERT_EQ(r, UV_EADDRINUSE);
|
||||
|
||||
uv_close((uv_handle_t*)&tcp_server, NULL);
|
||||
uv_close((uv_handle_t*)&tcp_server2, NULL);
|
||||
ASSERT_EQ(0, uv_pipe_pending_count(pipe));
|
||||
uv_close((uv_handle_t*)&channel, NULL);
|
||||
}
|
||||
|
||||
free(buf->base);
|
||||
}
|
||||
#endif
|
||||
|
||||
void spawn_helper(uv_pipe_t* channel,
|
||||
uv_process_t* process,
|
||||
const char* helper) {
|
||||
uv_process_options_t options;
|
||||
size_t exepath_size;
|
||||
char exepath[1024];
|
||||
char* args[3];
|
||||
int r;
|
||||
uv_stdio_container_t stdio[3];
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), channel, 1);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_NE(channel->ipc, 0);
|
||||
|
||||
exepath_size = sizeof(exepath);
|
||||
r = uv_exepath(exepath, &exepath_size);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
exepath[exepath_size] = '\0';
|
||||
args[0] = exepath;
|
||||
args[1] = (char*)helper;
|
||||
args[2] = NULL;
|
||||
|
||||
memset(&options, 0, sizeof(options));
|
||||
options.file = exepath;
|
||||
options.args = args;
|
||||
options.exit_cb = exit_cb;
|
||||
options.stdio = stdio;
|
||||
options.stdio_count = ARRAY_SIZE(stdio);
|
||||
|
||||
stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE;
|
||||
stdio[0].data.stream = (uv_stream_t*) channel;
|
||||
stdio[1].flags = UV_INHERIT_FD;
|
||||
stdio[1].data.fd = 1;
|
||||
stdio[2].flags = UV_INHERIT_FD;
|
||||
stdio[2].data.fd = 2;
|
||||
|
||||
r = uv_spawn(uv_default_loop(), process, &options);
|
||||
ASSERT_EQ(r, 0);
|
||||
}
|
||||
|
||||
|
||||
static void on_tcp_write(uv_write_t* req, int status) {
|
||||
ASSERT_EQ(status, 0);
|
||||
ASSERT_PTR_EQ(req->handle, &tcp_connection);
|
||||
tcp_write_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void on_read_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
|
||||
static void on_tcp_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
|
||||
ASSERT_GT(nread, 0);
|
||||
ASSERT_MEM_EQ("hello again\n", buf->base, nread);
|
||||
ASSERT_PTR_EQ(tcp, &tcp_connection);
|
||||
free(buf->base);
|
||||
|
||||
tcp_read_cb_called++;
|
||||
|
||||
uv_close((uv_handle_t*)tcp, NULL);
|
||||
uv_close((uv_handle_t*)&channel, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void on_read_connection(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
int r;
|
||||
uv_buf_t outbuf;
|
||||
uv_pipe_t* pipe;
|
||||
uv_handle_type pending;
|
||||
|
||||
pipe = (uv_pipe_t*) handle;
|
||||
if (nread == 0) {
|
||||
/* Everything OK, but nothing read. */
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread == UV_EOF) {
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("error recving on channel: %s\n", uv_strerror(nread));
|
||||
abort();
|
||||
}
|
||||
|
||||
fprintf(stderr, "got %d bytes\n", (int)nread);
|
||||
|
||||
ASSERT_EQ(1, uv_pipe_pending_count(pipe));
|
||||
pending = uv_pipe_pending_type(pipe);
|
||||
|
||||
ASSERT_GT(nread, 0);
|
||||
ASSERT_NOT_NULL(buf->base);
|
||||
ASSERT_NE(pending, UV_UNKNOWN_HANDLE);
|
||||
read_cb_called++;
|
||||
|
||||
/* Accept the pending TCP connection */
|
||||
ASSERT_EQ(pending, UV_TCP);
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_accept(handle, (uv_stream_t*)&tcp_connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
/* Make sure that the expected data is correctly multiplexed. */
|
||||
ASSERT_MEM_EQ("hello\n", buf->base, nread);
|
||||
|
||||
/* Write/read to/from the connection */
|
||||
outbuf = uv_buf_init("world\n", 6);
|
||||
r = uv_write(&write_req, (uv_stream_t*)&tcp_connection, &outbuf, 1,
|
||||
on_tcp_write);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*)&tcp_connection, on_read_alloc, on_tcp_read);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
static void on_read_closed_handle(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
if (nread == 0 || nread == UV_EOF) {
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
printf("error recving on channel: %s\n", uv_strerror(nread));
|
||||
abort();
|
||||
}
|
||||
|
||||
closed_handle_data_read += nread;
|
||||
free(buf->base);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void on_read_send_zero(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
ASSERT(nread == 0 || nread == UV_EOF);
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
|
||||
static int run_ipc_test(const char* helper, uv_read_cb read_cb) {
|
||||
uv_process_t process;
|
||||
int r;
|
||||
|
||||
spawn_helper(&channel, &process, helper);
|
||||
uv_read_start((uv_stream_t*)&channel, on_alloc, read_cb);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(ipc_listen_before_write) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
int r = run_ipc_test("ipc_helper_listen_before_write", on_read);
|
||||
ASSERT_EQ(local_conn_accepted, 1);
|
||||
ASSERT_EQ(remote_conn_accepted, 1);
|
||||
ASSERT_EQ(read_cb_called, 1);
|
||||
ASSERT_EQ(exit_cb_called, 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(ipc_listen_after_write) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
int r = run_ipc_test("ipc_helper_listen_after_write", on_read);
|
||||
ASSERT_EQ(local_conn_accepted, 1);
|
||||
ASSERT_EQ(remote_conn_accepted, 1);
|
||||
ASSERT_EQ(read_cb_called, 1);
|
||||
ASSERT_EQ(exit_cb_called, 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(ipc_tcp_connection) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
int r = run_ipc_test("ipc_helper_tcp_connection", on_read_connection);
|
||||
ASSERT_EQ(read_cb_called, 1);
|
||||
ASSERT_EQ(tcp_write_cb_called, 1);
|
||||
ASSERT_EQ(tcp_read_cb_called, 1);
|
||||
ASSERT_EQ(exit_cb_called, 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
TEST_IMPL(ipc_closed_handle) {
|
||||
int r;
|
||||
r = run_ipc_test("ipc_helper_closed_handle", on_read_closed_handle);
|
||||
ASSERT_EQ(r, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST_IMPL(listen_with_simultaneous_accepts) {
|
||||
uv_tcp_t server;
|
||||
int r;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_simultaneous_accepts(&server, 1);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_EQ(server.reqs_pending, 32);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(listen_no_simultaneous_accepts) {
|
||||
uv_tcp_t server;
|
||||
int r;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_simultaneous_accepts(&server, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_EQ(server.reqs_pending, 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(ipc_listen_after_bind_twice) {
|
||||
#if defined(NO_SEND_HANDLE_ON_PIPE)
|
||||
RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
|
||||
#endif
|
||||
int r = run_ipc_test("ipc_helper_bind_twice", on_read_listen_after_bound_twice);
|
||||
ASSERT_EQ(read_cb_called, 2);
|
||||
ASSERT_EQ(exit_cb_called, 1);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_IMPL(ipc_send_zero) {
|
||||
int r;
|
||||
r = run_ipc_test("ipc_helper_send_zero", on_read_send_zero);
|
||||
ASSERT_EQ(r, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Everything here runs in a child process. */
|
||||
|
||||
static tcp_conn conn;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void conn_notify_write_cb(uv_write_t* req, int status) {
|
||||
uv_close((uv_handle_t*)&tcp_server, close_cb);
|
||||
uv_close((uv_handle_t*)&channel, close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void tcp_connection_write_cb(uv_write_t* req, int status) {
|
||||
ASSERT_PTR_EQ(&conn.conn, req->handle);
|
||||
uv_close((uv_handle_t*)req->handle, close_cb);
|
||||
uv_close((uv_handle_t*)&channel, close_cb);
|
||||
uv_close((uv_handle_t*)&tcp_server, close_cb);
|
||||
tcp_conn_write_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void closed_handle_large_write_cb(uv_write_t* req, int status) {
|
||||
ASSERT_EQ(status, 0);
|
||||
ASSERT(closed_handle_data_read = LARGE_SIZE);
|
||||
if (++write_reqs_completed == ARRAY_SIZE(write_reqs)) {
|
||||
write_reqs_completed = 0;
|
||||
if (write_until_data_queued() > 0)
|
||||
send_handle_and_close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void closed_handle_write_cb(uv_write_t* req, int status) {
|
||||
ASSERT_EQ(status, UV_EBADF);
|
||||
closed_handle_write = 1;
|
||||
}
|
||||
|
||||
|
||||
static void send_zero_write_cb(uv_write_t* req, int status) {
|
||||
ASSERT_EQ(status, 0);
|
||||
send_zero_write++;
|
||||
}
|
||||
|
||||
static void on_tcp_child_process_read(uv_stream_t* tcp,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
uv_buf_t outbuf;
|
||||
int r;
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread == UV_EOF) {
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("error recving on tcp connection: %s\n", uv_strerror(nread));
|
||||
abort();
|
||||
}
|
||||
|
||||
ASSERT_GT(nread, 0);
|
||||
ASSERT_MEM_EQ("world\n", buf->base, nread);
|
||||
on_pipe_read_called++;
|
||||
free(buf->base);
|
||||
|
||||
/* Write to the socket */
|
||||
outbuf = uv_buf_init("hello again\n", 12);
|
||||
r = uv_write(&conn.tcp_write_req, tcp, &outbuf, 1, tcp_connection_write_cb);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
tcp_conn_read_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connect_child_process_cb(uv_connect_t* req, int status) {
|
||||
int r;
|
||||
|
||||
ASSERT_EQ(status, 0);
|
||||
r = uv_read_start(req->handle, on_read_alloc, on_tcp_child_process_read);
|
||||
ASSERT_EQ(r, 0);
|
||||
}
|
||||
|
||||
|
||||
static void ipc_on_connection(uv_stream_t* server, int status) {
|
||||
int r;
|
||||
uv_buf_t buf;
|
||||
|
||||
if (!connection_accepted) {
|
||||
/*
|
||||
* Accept the connection and close it. Also let the other
|
||||
* side know.
|
||||
*/
|
||||
ASSERT_EQ(status, 0);
|
||||
ASSERT_PTR_EQ(&tcp_server, server);
|
||||
|
||||
r = uv_tcp_init(server->loop, &conn.conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)&conn.conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_close((uv_handle_t*)&conn.conn, close_cb);
|
||||
|
||||
buf = uv_buf_init("accepted_connection\n", 20);
|
||||
r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1,
|
||||
NULL, conn_notify_write_cb);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
connection_accepted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) {
|
||||
int r;
|
||||
uv_buf_t buf;
|
||||
uv_tcp_t* conn;
|
||||
|
||||
ASSERT_EQ(status, 0);
|
||||
ASSERT_PTR_EQ(&tcp_server, server);
|
||||
|
||||
conn = malloc(sizeof(*conn));
|
||||
ASSERT_NOT_NULL(conn);
|
||||
|
||||
r = uv_tcp_init(server->loop, conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
/* Send the accepted connection to the other process */
|
||||
buf = uv_buf_init("hello\n", 6);
|
||||
r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1,
|
||||
(uv_stream_t*)conn, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*) conn,
|
||||
on_read_alloc,
|
||||
on_tcp_child_process_read);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_close((uv_handle_t*)conn, close_cb);
|
||||
}
|
||||
|
||||
|
||||
int ipc_helper(int listen_after_write) {
|
||||
/*
|
||||
* This is launched from test-ipc.c. stdin is a duplex channel that we
|
||||
* over which a handle will be transmitted.
|
||||
*/
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
uv_buf_t buf;
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &channel, 1);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_pipe_open(&channel, 0);
|
||||
|
||||
ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
if (!listen_after_write) {
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
}
|
||||
|
||||
buf = uv_buf_init("hello\n", 6);
|
||||
r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,
|
||||
(uv_stream_t*)&tcp_server, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
if (listen_after_write) {
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
}
|
||||
|
||||
notify_parent_process();
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(connection_accepted, 1);
|
||||
ASSERT_EQ(close_cb_called, 3);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ipc_helper_tcp_connection(void) {
|
||||
/*
|
||||
* This is launched from test-ipc.c. stdin is a duplex channel
|
||||
* over which a handle will be transmitted.
|
||||
*/
|
||||
|
||||
int r;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &channel, 1);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_pipe_open(&channel, 0);
|
||||
|
||||
ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection_tcp_conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
/* Make a connection to the server */
|
||||
r = uv_tcp_init(uv_default_loop(), &conn.conn);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_connect(&conn.conn_req,
|
||||
(uv_tcp_t*) &conn.conn,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_child_process_cb);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(tcp_conn_read_cb_called, 1);
|
||||
ASSERT_EQ(tcp_conn_write_cb_called, 1);
|
||||
ASSERT_EQ(close_cb_called, 4);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int write_until_data_queued() {
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
r = uv_write(&write_reqs[i],
|
||||
(uv_stream_t*)&channel,
|
||||
&large_buf,
|
||||
1,
|
||||
closed_handle_large_write_cb);
|
||||
ASSERT_EQ(r, 0);
|
||||
i++;
|
||||
} while (channel.write_queue_size == 0 &&
|
||||
i < ARRAY_SIZE(write_reqs));
|
||||
|
||||
return channel.write_queue_size;
|
||||
}
|
||||
|
||||
static void send_handle_and_close() {
|
||||
int r;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_write2(&write_req,
|
||||
(uv_stream_t*)&channel,
|
||||
&large_buf,
|
||||
1,
|
||||
(uv_stream_t*)&tcp_server,
|
||||
closed_handle_write_cb);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_close((uv_handle_t*)&tcp_server, NULL);
|
||||
}
|
||||
|
||||
int ipc_helper_closed_handle(void) {
|
||||
int r;
|
||||
|
||||
memset(buffer, '.', LARGE_SIZE);
|
||||
large_buf = uv_buf_init(buffer, LARGE_SIZE);
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &channel, 1);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_pipe_open(&channel, 0);
|
||||
|
||||
ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
|
||||
|
||||
if (write_until_data_queued() > 0)
|
||||
send_handle_and_close();
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(closed_handle_write, 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ipc_helper_bind_twice(void) {
|
||||
/*
|
||||
* This is launched from test-ipc.c. stdin is a duplex channel
|
||||
* over which two handles will be transmitted.
|
||||
*/
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
uv_buf_t buf;
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &channel, 1);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_pipe_open(&channel, 0);
|
||||
|
||||
ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
|
||||
|
||||
buf = uv_buf_init("hello\n", 6);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||
ASSERT_EQ(r, 0);
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server2);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,
|
||||
(uv_stream_t*)&tcp_server, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1,
|
||||
(uv_stream_t*)&tcp_server2, NULL);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipc_helper_send_zero(void) {
|
||||
int r;
|
||||
uv_buf_t zero_buf;
|
||||
|
||||
zero_buf = uv_buf_init(0, 0);
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &channel, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_pipe_open(&channel, 0);
|
||||
|
||||
ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
|
||||
ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
|
||||
|
||||
r = uv_write(&write_req,
|
||||
(uv_stream_t*)&channel,
|
||||
&zero_buf,
|
||||
1,
|
||||
send_zero_write_cb);
|
||||
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(send_zero_write, 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
1127
deps/libuv/test/test-list.h
vendored
Normal file
1127
deps/libuv/test/test-list.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
67
deps/libuv/test/test-loop-alive.c
vendored
Normal file
67
deps/libuv/test/test-loop-alive.c
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(handle);
|
||||
}
|
||||
|
||||
|
||||
static uv_work_t work_req;
|
||||
|
||||
static void work_cb(uv_work_t* req) {
|
||||
ASSERT(req);
|
||||
}
|
||||
|
||||
static void after_work_cb(uv_work_t* req, int status) {
|
||||
ASSERT(req);
|
||||
ASSERT(status == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(loop_alive) {
|
||||
int r;
|
||||
ASSERT(!uv_loop_alive(uv_default_loop()));
|
||||
|
||||
/* loops with handles are alive */
|
||||
uv_timer_init(uv_default_loop(), &timer_handle);
|
||||
uv_timer_start(&timer_handle, timer_cb, 100, 0);
|
||||
ASSERT(uv_loop_alive(uv_default_loop()));
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(!uv_loop_alive(uv_default_loop()));
|
||||
|
||||
/* loops with requests are alive */
|
||||
r = uv_queue_work(uv_default_loop(), &work_req, work_cb, after_work_cb);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(uv_loop_alive(uv_default_loop()));
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(!uv_loop_alive(uv_default_loop()));
|
||||
|
||||
return 0;
|
||||
}
|
75
deps/libuv/test/test-loop-close.c
vendored
Normal file
75
deps/libuv/test/test-loop-close.c
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(handle);
|
||||
uv_stop(handle->loop);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
ASSERT(UV_EBUSY == uv_loop_close(&loop));
|
||||
|
||||
uv_run(&loop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_close((uv_handle_t*) &timer_handle, NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
static void loop_instant_close_work_cb(uv_work_t* req) {
|
||||
}
|
||||
|
||||
static void loop_instant_close_after_work_cb(uv_work_t* req, int status) {
|
||||
}
|
||||
|
||||
TEST_IMPL(loop_instant_close) {
|
||||
static uv_loop_t loop;
|
||||
static uv_work_t req;
|
||||
ASSERT(0 == uv_loop_init(&loop));
|
||||
ASSERT(0 == uv_queue_work(&loop,
|
||||
&req,
|
||||
loop_instant_close_work_cb,
|
||||
loop_instant_close_after_work_cb));
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
38
deps/libuv/test/test-loop-configure.c
vendored
Normal file
38
deps/libuv/test/test-loop-configure.c
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2014, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
uv_close((uv_handle_t*) handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(loop_configure) {
|
||||
uv_timer_t timer_handle;
|
||||
uv_loop_t loop;
|
||||
ASSERT(0 == uv_loop_init(&loop));
|
||||
#ifdef _WIN32
|
||||
ASSERT(UV_ENOSYS == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, 0));
|
||||
#else
|
||||
ASSERT(0 == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, SIGPROF));
|
||||
#endif
|
||||
ASSERT(0 == uv_timer_init(&loop, &timer_handle));
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 10, 0));
|
||||
ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
|
||||
ASSERT(0 == uv_loop_close(&loop));
|
||||
return 0;
|
||||
}
|
337
deps/libuv/test/test-loop-handles.c
vendored
Normal file
337
deps/libuv/test/test-loop-handles.c
vendored
Normal file
@ -0,0 +1,337 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Tests commented out with XXX are ones that are failing on Linux */
|
||||
|
||||
/*
|
||||
* Purpose of this test is to check semantics of starting and stopping
|
||||
* prepare, check and idle watchers.
|
||||
*
|
||||
* - A watcher must be able to safely stop or close itself;
|
||||
* - Once a watcher is stopped or closed its callback should never be called.
|
||||
* - If a watcher is closed, it is implicitly stopped and its close_cb should
|
||||
* be called exactly once.
|
||||
* - A watcher can safely start and stop other watchers of the same type.
|
||||
* - Prepare and check watchers are called once per event loop iterations.
|
||||
* - All active idle watchers are queued when the event loop has no more work
|
||||
* to do. This is done repeatedly until all idle watchers are inactive.
|
||||
* - If a watcher starts another watcher of the same type its callback is not
|
||||
* immediately queued. For check and prepare watchers, that means that if
|
||||
* a watcher makes another of the same type active, it'll not be called until
|
||||
* the next event loop iteration. For idle. watchers this means that the
|
||||
* newly activated idle watcher might not be queued immediately.
|
||||
* - Prepare, check, idle watchers keep the event loop alive even when they're
|
||||
* not active.
|
||||
*
|
||||
* This is what the test globally does:
|
||||
*
|
||||
* - prepare_1 is always active and counts event loop iterations. It also
|
||||
* creates and starts prepare_2 every other iteration. Finally it verifies
|
||||
* that no idle watchers are active before polling.
|
||||
* - prepare_2 is started by prepare_1 every other iteration. It immediately
|
||||
* stops itself. It verifies that a watcher is not queued immediately
|
||||
* if created by another watcher of the same type.
|
||||
* - There's a check watcher that stops the event loop after a certain number
|
||||
* of iterations. It starts a varying number of idle_1 watchers.
|
||||
* - Idle_1 watchers stop themselves after being called a few times. All idle_1
|
||||
* watchers try to start the idle_2 watcher if it is not already started or
|
||||
* awaiting its close callback.
|
||||
* - The idle_2 watcher always exists but immediately closes itself after
|
||||
* being started by a check_1 watcher. It verifies that a watcher is
|
||||
* implicitly stopped when closed, and that a watcher can close itself
|
||||
* safely.
|
||||
* - There is a repeating timer. It does not keep the event loop alive
|
||||
* (ev_unref) but makes sure that the loop keeps polling the system for
|
||||
* events.
|
||||
*/
|
||||
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#define IDLE_COUNT 7
|
||||
#define ITERATIONS 21
|
||||
#define TIMEOUT 100
|
||||
|
||||
|
||||
static uv_prepare_t prepare_1_handle;
|
||||
static uv_prepare_t prepare_2_handle;
|
||||
|
||||
static uv_check_t check_handle;
|
||||
|
||||
static uv_idle_t idle_1_handles[IDLE_COUNT];
|
||||
static uv_idle_t idle_2_handle;
|
||||
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
|
||||
static int loop_iteration = 0;
|
||||
|
||||
static int prepare_1_cb_called = 0;
|
||||
static int prepare_1_close_cb_called = 0;
|
||||
|
||||
static int prepare_2_cb_called = 0;
|
||||
static int prepare_2_close_cb_called = 0;
|
||||
|
||||
static int check_cb_called = 0;
|
||||
static int check_close_cb_called = 0;
|
||||
|
||||
static int idle_1_cb_called = 0;
|
||||
static int idle_1_close_cb_called = 0;
|
||||
static int idles_1_active = 0;
|
||||
|
||||
static int idle_2_cb_called = 0;
|
||||
static int idle_2_close_cb_called = 0;
|
||||
static int idle_2_cb_started = 0;
|
||||
static int idle_2_is_active = 0;
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(handle == &timer_handle);
|
||||
}
|
||||
|
||||
|
||||
static void idle_2_close_cb(uv_handle_t* handle) {
|
||||
fprintf(stderr, "%s", "IDLE_2_CLOSE_CB\n");
|
||||
fflush(stderr);
|
||||
|
||||
ASSERT(handle == (uv_handle_t*)&idle_2_handle);
|
||||
|
||||
ASSERT(idle_2_is_active);
|
||||
|
||||
idle_2_close_cb_called++;
|
||||
idle_2_is_active = 0;
|
||||
}
|
||||
|
||||
|
||||
static void idle_2_cb(uv_idle_t* handle) {
|
||||
fprintf(stderr, "%s", "IDLE_2_CB\n");
|
||||
fflush(stderr);
|
||||
|
||||
ASSERT(handle == &idle_2_handle);
|
||||
|
||||
idle_2_cb_called++;
|
||||
|
||||
uv_close((uv_handle_t*)handle, idle_2_close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void idle_1_cb(uv_idle_t* handle) {
|
||||
int r;
|
||||
|
||||
fprintf(stderr, "%s", "IDLE_1_CB\n");
|
||||
fflush(stderr);
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
ASSERT(idles_1_active > 0);
|
||||
|
||||
/* Init idle_2 and make it active */
|
||||
if (!idle_2_is_active && !uv_is_closing((uv_handle_t*)&idle_2_handle)) {
|
||||
r = uv_idle_init(uv_default_loop(), &idle_2_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_idle_start(&idle_2_handle, idle_2_cb);
|
||||
ASSERT(r == 0);
|
||||
idle_2_is_active = 1;
|
||||
idle_2_cb_started++;
|
||||
}
|
||||
|
||||
idle_1_cb_called++;
|
||||
|
||||
if (idle_1_cb_called % 5 == 0) {
|
||||
r = uv_idle_stop((uv_idle_t*)handle);
|
||||
ASSERT(r == 0);
|
||||
idles_1_active--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void idle_1_close_cb(uv_handle_t* handle) {
|
||||
fprintf(stderr, "%s", "IDLE_1_CLOSE_CB\n");
|
||||
fflush(stderr);
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
idle_1_close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void prepare_1_close_cb(uv_handle_t* handle) {
|
||||
fprintf(stderr, "%s", "PREPARE_1_CLOSE_CB");
|
||||
fflush(stderr);
|
||||
ASSERT(handle == (uv_handle_t*)&prepare_1_handle);
|
||||
|
||||
prepare_1_close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void check_close_cb(uv_handle_t* handle) {
|
||||
fprintf(stderr, "%s", "CHECK_CLOSE_CB\n");
|
||||
fflush(stderr);
|
||||
ASSERT(handle == (uv_handle_t*)&check_handle);
|
||||
|
||||
check_close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void prepare_2_close_cb(uv_handle_t* handle) {
|
||||
fprintf(stderr, "%s", "PREPARE_2_CLOSE_CB\n");
|
||||
fflush(stderr);
|
||||
ASSERT(handle == (uv_handle_t*)&prepare_2_handle);
|
||||
|
||||
prepare_2_close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void check_cb(uv_check_t* handle) {
|
||||
int i, r;
|
||||
|
||||
fprintf(stderr, "%s", "CHECK_CB\n");
|
||||
fflush(stderr);
|
||||
ASSERT(handle == &check_handle);
|
||||
|
||||
if (loop_iteration < ITERATIONS) {
|
||||
/* Make some idle watchers active */
|
||||
for (i = 0; i < 1 + (loop_iteration % IDLE_COUNT); i++) {
|
||||
r = uv_idle_start(&idle_1_handles[i], idle_1_cb);
|
||||
ASSERT(r == 0);
|
||||
idles_1_active++;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* End of the test - close all handles */
|
||||
uv_close((uv_handle_t*)&prepare_1_handle, prepare_1_close_cb);
|
||||
uv_close((uv_handle_t*)&check_handle, check_close_cb);
|
||||
uv_close((uv_handle_t*)&prepare_2_handle, prepare_2_close_cb);
|
||||
|
||||
for (i = 0; i < IDLE_COUNT; i++) {
|
||||
uv_close((uv_handle_t*)&idle_1_handles[i], idle_1_close_cb);
|
||||
}
|
||||
|
||||
/* This handle is closed/recreated every time, close it only if it is
|
||||
* active. */
|
||||
if (idle_2_is_active) {
|
||||
uv_close((uv_handle_t*)&idle_2_handle, idle_2_close_cb);
|
||||
}
|
||||
}
|
||||
|
||||
check_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void prepare_2_cb(uv_prepare_t* handle) {
|
||||
int r;
|
||||
|
||||
fprintf(stderr, "%s", "PREPARE_2_CB\n");
|
||||
fflush(stderr);
|
||||
ASSERT(handle == &prepare_2_handle);
|
||||
|
||||
/* Prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), and it
|
||||
* stops itself immediately. A started watcher is not queued until the next
|
||||
* round, so when this callback is made (loop_iteration % 2 == 0) cannot be
|
||||
* true. */
|
||||
ASSERT(loop_iteration % 2 != 0);
|
||||
|
||||
r = uv_prepare_stop((uv_prepare_t*)handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
prepare_2_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void prepare_1_cb(uv_prepare_t* handle) {
|
||||
int r;
|
||||
|
||||
fprintf(stderr, "%s", "PREPARE_1_CB\n");
|
||||
fflush(stderr);
|
||||
ASSERT(handle == &prepare_1_handle);
|
||||
|
||||
if (loop_iteration % 2 == 0) {
|
||||
r = uv_prepare_start(&prepare_2_handle, prepare_2_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
prepare_1_cb_called++;
|
||||
loop_iteration++;
|
||||
|
||||
printf("Loop iteration %d of %d.\n", loop_iteration, ITERATIONS);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(loop_handles) {
|
||||
int i;
|
||||
int r;
|
||||
|
||||
r = uv_prepare_init(uv_default_loop(), &prepare_1_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_prepare_start(&prepare_1_handle, prepare_1_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_check_init(uv_default_loop(), &check_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_check_start(&check_handle, check_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* initialize only, prepare_2 is started by prepare_1_cb */
|
||||
r = uv_prepare_init(uv_default_loop(), &prepare_2_handle);
|
||||
ASSERT(r == 0);
|
||||
|
||||
for (i = 0; i < IDLE_COUNT; i++) {
|
||||
/* initialize only, idle_1 handles are started by check_cb */
|
||||
r = uv_idle_init(uv_default_loop(), &idle_1_handles[i]);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
/* don't init or start idle_2, both is done by idle_1_cb */
|
||||
|
||||
/* The timer callback is there to keep the event loop polling unref it as it
|
||||
* is not supposed to keep the loop alive */
|
||||
r = uv_timer_init(uv_default_loop(), &timer_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&timer_handle, timer_cb, TIMEOUT, TIMEOUT);
|
||||
ASSERT(r == 0);
|
||||
uv_unref((uv_handle_t*)&timer_handle);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(loop_iteration == ITERATIONS);
|
||||
|
||||
ASSERT(prepare_1_cb_called == ITERATIONS);
|
||||
ASSERT(prepare_1_close_cb_called == 1);
|
||||
|
||||
ASSERT(prepare_2_cb_called == ITERATIONS / 2);
|
||||
ASSERT(prepare_2_close_cb_called == 1);
|
||||
|
||||
ASSERT(check_cb_called == ITERATIONS);
|
||||
ASSERT(check_close_cb_called == 1);
|
||||
|
||||
/* idle_1_cb should be called a lot */
|
||||
ASSERT(idle_1_close_cb_called == IDLE_COUNT);
|
||||
|
||||
ASSERT(idle_2_close_cb_called == idle_2_cb_started);
|
||||
ASSERT(idle_2_is_active == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
71
deps/libuv/test/test-loop-stop.c
vendored
Normal file
71
deps/libuv/test/test-loop-stop.c
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
static uv_prepare_t prepare_handle;
|
||||
static uv_timer_t timer_handle;
|
||||
static int prepare_called = 0;
|
||||
static int timer_called = 0;
|
||||
static int num_ticks = 10;
|
||||
|
||||
|
||||
static void prepare_cb(uv_prepare_t* handle) {
|
||||
ASSERT(handle == &prepare_handle);
|
||||
prepare_called++;
|
||||
if (prepare_called == num_ticks)
|
||||
uv_prepare_stop(handle);
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
ASSERT(handle == &timer_handle);
|
||||
timer_called++;
|
||||
if (timer_called == 1)
|
||||
uv_stop(uv_default_loop());
|
||||
else if (timer_called == num_ticks)
|
||||
uv_timer_stop(handle);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(loop_stop) {
|
||||
int r;
|
||||
uv_prepare_init(uv_default_loop(), &prepare_handle);
|
||||
uv_prepare_start(&prepare_handle, prepare_cb);
|
||||
uv_timer_init(uv_default_loop(), &timer_handle);
|
||||
uv_timer_start(&timer_handle, timer_cb, 100, 100);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r != 0);
|
||||
ASSERT(timer_called == 1);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_NOWAIT);
|
||||
ASSERT(r != 0);
|
||||
ASSERT(prepare_called > 1);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(timer_called == 10);
|
||||
ASSERT(prepare_called == 10);
|
||||
|
||||
return 0;
|
||||
}
|
63
deps/libuv/test/test-loop-time.c
vendored
Normal file
63
deps/libuv/test/test-loop-time.c
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
TEST_IMPL(loop_update_time) {
|
||||
uint64_t start;
|
||||
|
||||
start = uv_now(uv_default_loop());
|
||||
while (uv_now(uv_default_loop()) - start < 1000)
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cb(uv_timer_t* timer) {
|
||||
uv_close((uv_handle_t*)timer, NULL);
|
||||
}
|
||||
|
||||
TEST_IMPL(loop_backend_timeout) {
|
||||
uv_loop_t *loop = uv_default_loop();
|
||||
uv_timer_t timer;
|
||||
int r;
|
||||
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(!uv_loop_alive(loop));
|
||||
ASSERT(uv_backend_timeout(loop) == 0);
|
||||
|
||||
r = uv_timer_start(&timer, cb, 1000, 0); /* 1 sec */
|
||||
ASSERT(r == 0);
|
||||
ASSERT(uv_backend_timeout(loop) > 100); /* 0.1 sec */
|
||||
ASSERT(uv_backend_timeout(loop) <= 1000); /* 1 sec */
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(uv_backend_timeout(loop) == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
135
deps/libuv/test/test-metrics.c
vendored
Normal file
135
deps/libuv/test/test-metrics.c
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
/* Copyright libuv project 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 <string.h> /* memset */
|
||||
|
||||
#define UV_NS_TO_MS 1000000
|
||||
|
||||
|
||||
static void timer_spin_cb(uv_timer_t* handle) {
|
||||
uint64_t t;
|
||||
|
||||
(*(int*) handle->data)++;
|
||||
t = uv_hrtime();
|
||||
/* Spin for 500 ms to spin loop time out of the delta check. */
|
||||
while (uv_hrtime() - t < 600 * UV_NS_TO_MS) { }
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(metrics_idle_time) {
|
||||
const uint64_t timeout = 1000;
|
||||
uv_timer_t timer;
|
||||
uint64_t idle_time;
|
||||
int cntr;
|
||||
|
||||
cntr = 0;
|
||||
timer.data = &cntr;
|
||||
|
||||
ASSERT_EQ(0, uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME));
|
||||
ASSERT_EQ(0, uv_timer_init(uv_default_loop(), &timer));
|
||||
ASSERT_EQ(0, uv_timer_start(&timer, timer_spin_cb, timeout, 0));
|
||||
|
||||
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT_GT(cntr, 0);
|
||||
|
||||
idle_time = uv_metrics_idle_time(uv_default_loop());
|
||||
|
||||
/* Permissive check that the idle time matches within the timeout ±500 ms. */
|
||||
ASSERT((idle_time <= (timeout + 500) * UV_NS_TO_MS) &&
|
||||
(idle_time >= (timeout - 500) * UV_NS_TO_MS));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void metrics_routine_cb(void* arg) {
|
||||
const uint64_t timeout = 1000;
|
||||
uv_loop_t loop;
|
||||
uv_timer_t timer;
|
||||
uint64_t idle_time;
|
||||
int cntr;
|
||||
|
||||
cntr = 0;
|
||||
timer.data = &cntr;
|
||||
|
||||
ASSERT_EQ(0, uv_loop_init(&loop));
|
||||
ASSERT_EQ(0, uv_loop_configure(&loop, UV_METRICS_IDLE_TIME));
|
||||
ASSERT_EQ(0, uv_timer_init(&loop, &timer));
|
||||
ASSERT_EQ(0, uv_timer_start(&timer, timer_spin_cb, timeout, 0));
|
||||
|
||||
ASSERT_EQ(0, uv_run(&loop, UV_RUN_DEFAULT));
|
||||
ASSERT_GT(cntr, 0);
|
||||
|
||||
idle_time = uv_metrics_idle_time(&loop);
|
||||
|
||||
/* Only checking that idle time is greater than the lower bound since there
|
||||
* may have been thread contention, causing the event loop to be delayed in
|
||||
* the idle phase longer than expected.
|
||||
*/
|
||||
ASSERT_GE(idle_time, (timeout - 500) * UV_NS_TO_MS);
|
||||
|
||||
close_loop(&loop);
|
||||
ASSERT_EQ(0, uv_loop_close(&loop));
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(metrics_idle_time_thread) {
|
||||
uv_thread_t threads[5];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ASSERT_EQ(0, uv_thread_create(&threads[i], metrics_routine_cb, NULL));
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
uv_thread_join(&threads[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void timer_noop_cb(uv_timer_t* handle) {
|
||||
(*(int*) handle->data)++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(metrics_idle_time_zero) {
|
||||
uv_timer_t timer;
|
||||
int cntr;
|
||||
|
||||
cntr = 0;
|
||||
timer.data = &cntr;
|
||||
ASSERT_EQ(0, uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME));
|
||||
ASSERT_EQ(0, uv_timer_init(uv_default_loop(), &timer));
|
||||
ASSERT_EQ(0, uv_timer_start(&timer, timer_noop_cb, 0, 0));
|
||||
|
||||
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
|
||||
ASSERT_GT(cntr, 0);
|
||||
ASSERT_EQ(0, uv_metrics_idle_time(uv_default_loop()));
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
109
deps/libuv/test/test-multiple-listen.c
vendored
Normal file
109
deps/libuv/test/test-multiple-listen.c
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int connection_cb_called = 0;
|
||||
static int close_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
static uv_tcp_t server;
|
||||
static uv_tcp_t client;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* tcp, int status) {
|
||||
ASSERT(status == 0);
|
||||
uv_close((uv_handle_t*)&server, close_cb);
|
||||
connection_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void start_server(void) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
free(req);
|
||||
uv_close((uv_handle_t*)&client, close_cb);
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void client_connect(void) {
|
||||
struct sockaddr_in addr;
|
||||
uv_connect_t* connect_req = malloc(sizeof *connect_req);
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
ASSERT(connect_req != NULL);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_connect(connect_req,
|
||||
&client,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_IMPL(multiple_listen) {
|
||||
start_server();
|
||||
|
||||
client_connect();
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(connection_cb_called == 1);
|
||||
ASSERT(connect_cb_called == 1);
|
||||
ASSERT(close_cb_called == 2);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
182
deps/libuv/test/test-mutexes.c
vendored
Normal file
182
deps/libuv/test/test-mutexes.c
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static uv_cond_t condvar;
|
||||
static uv_mutex_t mutex;
|
||||
static uv_rwlock_t rwlock;
|
||||
static int step;
|
||||
|
||||
/* The mutex and rwlock tests are really poor.
|
||||
* They're very basic sanity checks and nothing more.
|
||||
* Apologies if that rhymes.
|
||||
*/
|
||||
|
||||
TEST_IMPL(thread_mutex) {
|
||||
uv_mutex_t mutex;
|
||||
int r;
|
||||
|
||||
r = uv_mutex_init(&mutex);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_mutex_lock(&mutex);
|
||||
uv_mutex_unlock(&mutex);
|
||||
uv_mutex_destroy(&mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(thread_mutex_recursive) {
|
||||
uv_mutex_t mutex;
|
||||
int r;
|
||||
|
||||
r = uv_mutex_init_recursive(&mutex);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_mutex_lock(&mutex);
|
||||
uv_mutex_lock(&mutex);
|
||||
ASSERT(0 == uv_mutex_trylock(&mutex));
|
||||
|
||||
uv_mutex_unlock(&mutex);
|
||||
uv_mutex_unlock(&mutex);
|
||||
uv_mutex_unlock(&mutex);
|
||||
uv_mutex_destroy(&mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(thread_rwlock) {
|
||||
uv_rwlock_t rwlock;
|
||||
int r;
|
||||
|
||||
r = uv_rwlock_init(&rwlock);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_rwlock_rdlock(&rwlock);
|
||||
uv_rwlock_rdunlock(&rwlock);
|
||||
uv_rwlock_wrlock(&rwlock);
|
||||
uv_rwlock_wrunlock(&rwlock);
|
||||
uv_rwlock_destroy(&rwlock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Call when holding |mutex|. */
|
||||
static void synchronize_nowait(void) {
|
||||
step += 1;
|
||||
uv_cond_signal(&condvar);
|
||||
}
|
||||
|
||||
|
||||
/* Call when holding |mutex|. */
|
||||
static void synchronize(void) {
|
||||
int current;
|
||||
|
||||
synchronize_nowait();
|
||||
/* Wait for the other thread. Guard against spurious wakeups. */
|
||||
for (current = step; current == step; uv_cond_wait(&condvar, &mutex));
|
||||
ASSERT(step == current + 1);
|
||||
}
|
||||
|
||||
|
||||
static void thread_rwlock_trylock_peer(void* unused) {
|
||||
(void) &unused;
|
||||
|
||||
uv_mutex_lock(&mutex);
|
||||
|
||||
/* Write lock held by other thread. */
|
||||
ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock));
|
||||
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
|
||||
synchronize();
|
||||
|
||||
/* Read lock held by other thread. */
|
||||
ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
|
||||
uv_rwlock_rdunlock(&rwlock);
|
||||
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
|
||||
synchronize();
|
||||
|
||||
/* Acquire write lock. */
|
||||
ASSERT(0 == uv_rwlock_trywrlock(&rwlock));
|
||||
synchronize();
|
||||
|
||||
/* Release write lock and acquire read lock. */
|
||||
uv_rwlock_wrunlock(&rwlock);
|
||||
ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
|
||||
synchronize();
|
||||
|
||||
uv_rwlock_rdunlock(&rwlock);
|
||||
synchronize_nowait(); /* Signal main thread we're going away. */
|
||||
uv_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(thread_rwlock_trylock) {
|
||||
uv_thread_t thread;
|
||||
|
||||
ASSERT(0 == uv_cond_init(&condvar));
|
||||
ASSERT(0 == uv_mutex_init(&mutex));
|
||||
ASSERT(0 == uv_rwlock_init(&rwlock));
|
||||
|
||||
uv_mutex_lock(&mutex);
|
||||
ASSERT(0 == uv_thread_create(&thread, thread_rwlock_trylock_peer, NULL));
|
||||
|
||||
/* Hold write lock. */
|
||||
ASSERT(0 == uv_rwlock_trywrlock(&rwlock));
|
||||
synchronize(); /* Releases the mutex to the other thread. */
|
||||
|
||||
/* Release write lock and acquire read lock. Pthreads doesn't support
|
||||
* the notion of upgrading or downgrading rwlocks, so neither do we.
|
||||
*/
|
||||
uv_rwlock_wrunlock(&rwlock);
|
||||
ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
|
||||
synchronize();
|
||||
|
||||
/* Release read lock. */
|
||||
uv_rwlock_rdunlock(&rwlock);
|
||||
synchronize();
|
||||
|
||||
/* Write lock held by other thread. */
|
||||
ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock));
|
||||
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
|
||||
synchronize();
|
||||
|
||||
/* Read lock held by other thread. */
|
||||
ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
|
||||
uv_rwlock_rdunlock(&rwlock);
|
||||
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
|
||||
synchronize();
|
||||
|
||||
ASSERT(0 == uv_thread_join(&thread));
|
||||
uv_rwlock_destroy(&rwlock);
|
||||
uv_mutex_unlock(&mutex);
|
||||
uv_mutex_destroy(&mutex);
|
||||
uv_cond_destroy(&condvar);
|
||||
|
||||
return 0;
|
||||
}
|
140
deps/libuv/test/test-osx-select.c
vendored
Normal file
140
deps/libuv/test/test-osx-select.c
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
|
||||
static int read_count;
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
static char slab[1024];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
||||
fprintf(stdout, "got data %d\n", ++read_count);
|
||||
fflush(stdout);
|
||||
|
||||
if (read_count == 3)
|
||||
uv_close((uv_handle_t*) stream, NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(osx_select) {
|
||||
int r;
|
||||
int fd;
|
||||
size_t i;
|
||||
size_t len;
|
||||
const char* str;
|
||||
uv_tty_t tty;
|
||||
|
||||
fd = open("/dev/tty", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Cannot open /dev/tty as read-only: %s\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return TEST_SKIP;
|
||||
}
|
||||
|
||||
r = uv_tty_init(uv_default_loop(), &tty, fd, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_read_start((uv_stream_t*) &tty, alloc_cb, read_cb);
|
||||
|
||||
/* Emulate user-input */
|
||||
str = "got some input\n"
|
||||
"with a couple of lines\n"
|
||||
"feel pretty happy\n";
|
||||
for (i = 0, len = strlen(str); i < len; i++) {
|
||||
r = ioctl(fd, TIOCSTI, str + i);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(read_count == 3);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(osx_select_many_fds) {
|
||||
int r;
|
||||
int fd;
|
||||
size_t i;
|
||||
size_t len;
|
||||
const char* str;
|
||||
struct sockaddr_in addr;
|
||||
uv_tty_t tty;
|
||||
uv_tcp_t tcps[1500];
|
||||
|
||||
TEST_FILE_LIMIT(ARRAY_SIZE(tcps) + 100);
|
||||
|
||||
r = uv_ip4_addr("127.0.0.1", 0, &addr);
|
||||
ASSERT(r == 0);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tcps); i++) {
|
||||
r = uv_tcp_init(uv_default_loop(), &tcps[i]);
|
||||
ASSERT(r == 0);
|
||||
r = uv_tcp_bind(&tcps[i], (const struct sockaddr *) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
uv_unref((uv_handle_t*) &tcps[i]);
|
||||
}
|
||||
|
||||
fd = open("/dev/tty", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Cannot open /dev/tty as read-only: %s\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return TEST_SKIP;
|
||||
}
|
||||
|
||||
r = uv_tty_init(uv_default_loop(), &tty, fd, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*) &tty, alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Emulate user-input */
|
||||
str = "got some input\n"
|
||||
"with a couple of lines\n"
|
||||
"feel pretty happy\n";
|
||||
for (i = 0, len = strlen(str); i < len; i++) {
|
||||
r = ioctl(fd, TIOCSTI, str + i);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(read_count == 3);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
28
deps/libuv/test/test-pass-always.c
vendored
Normal file
28
deps/libuv/test/test-pass-always.c
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
|
||||
|
||||
TEST_IMPL(pass_always) {
|
||||
/* This test always passes. It is used to test the test runner. */
|
||||
return 0;
|
||||
}
|
301
deps/libuv/test/test-ping-pong.c
vendored
Normal file
301
deps/libuv/test/test-ping-pong.c
vendored
Normal file
@ -0,0 +1,301 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int completed_pingers = 0;
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__MVS__)
|
||||
#define NUM_PINGS 100 /* fewer pings to avoid timeout */
|
||||
#else
|
||||
#define NUM_PINGS 1000
|
||||
#endif
|
||||
|
||||
/* 64 bytes is enough for a pinger */
|
||||
#define BUFSIZE 10240
|
||||
|
||||
static char PING[] = "PING\n";
|
||||
static int pinger_on_connect_count;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int vectored_writes;
|
||||
int pongs;
|
||||
int state;
|
||||
union {
|
||||
uv_tcp_t tcp;
|
||||
uv_pipe_t pipe;
|
||||
} stream;
|
||||
uv_connect_t connect_req;
|
||||
char read_buffer[BUFSIZE];
|
||||
} pinger_t;
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
buf->base = malloc(size);
|
||||
buf->len = size;
|
||||
}
|
||||
|
||||
|
||||
static void pinger_on_close(uv_handle_t* handle) {
|
||||
pinger_t* pinger = (pinger_t*)handle->data;
|
||||
|
||||
ASSERT(NUM_PINGS == pinger->pongs);
|
||||
|
||||
free(pinger);
|
||||
|
||||
completed_pingers++;
|
||||
}
|
||||
|
||||
|
||||
static void pinger_after_write(uv_write_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
free(req);
|
||||
}
|
||||
|
||||
|
||||
static void pinger_write_ping(pinger_t* pinger) {
|
||||
uv_write_t* req;
|
||||
uv_buf_t bufs[sizeof PING - 1];
|
||||
int i, nbufs;
|
||||
|
||||
if (!pinger->vectored_writes) {
|
||||
/* Write a single buffer. */
|
||||
nbufs = 1;
|
||||
bufs[0] = uv_buf_init(PING, sizeof PING - 1);
|
||||
} else {
|
||||
/* Write multiple buffers, each with one byte in them. */
|
||||
nbufs = sizeof PING - 1;
|
||||
for (i = 0; i < nbufs; i++) {
|
||||
bufs[i] = uv_buf_init(&PING[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
req = malloc(sizeof(*req));
|
||||
if (uv_write(req,
|
||||
(uv_stream_t*) &pinger->stream.tcp,
|
||||
bufs,
|
||||
nbufs,
|
||||
pinger_after_write)) {
|
||||
FATAL("uv_write failed");
|
||||
}
|
||||
|
||||
puts("PING");
|
||||
}
|
||||
|
||||
|
||||
static void pinger_read_cb(uv_stream_t* stream,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
ssize_t i;
|
||||
pinger_t* pinger;
|
||||
|
||||
pinger = (pinger_t*) stream->data;
|
||||
|
||||
if (nread < 0) {
|
||||
ASSERT(nread == UV_EOF);
|
||||
|
||||
puts("got EOF");
|
||||
free(buf->base);
|
||||
|
||||
uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now we count the pings */
|
||||
for (i = 0; i < nread; i++) {
|
||||
ASSERT(buf->base[i] == PING[pinger->state]);
|
||||
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
|
||||
|
||||
if (pinger->state != 0)
|
||||
continue;
|
||||
|
||||
printf("PONG %d\n", pinger->pongs);
|
||||
pinger->pongs++;
|
||||
|
||||
if (pinger->pongs < NUM_PINGS) {
|
||||
pinger_write_ping(pinger);
|
||||
} else {
|
||||
uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
|
||||
static void pinger_on_connect(uv_connect_t* req, int status) {
|
||||
pinger_t* pinger = (pinger_t*)req->handle->data;
|
||||
|
||||
pinger_on_connect_count++;
|
||||
|
||||
ASSERT(status == 0);
|
||||
|
||||
ASSERT(1 == uv_is_readable(req->handle));
|
||||
ASSERT(1 == uv_is_writable(req->handle));
|
||||
ASSERT(0 == uv_is_closing((uv_handle_t *) req->handle));
|
||||
|
||||
pinger_write_ping(pinger);
|
||||
|
||||
uv_read_start((uv_stream_t*)(req->handle), alloc_cb, pinger_read_cb);
|
||||
}
|
||||
|
||||
|
||||
/* same ping-pong test, but using IPv6 connection */
|
||||
static void tcp_pinger_v6_new(int vectored_writes) {
|
||||
int r;
|
||||
struct sockaddr_in6 server_addr;
|
||||
pinger_t* pinger;
|
||||
|
||||
|
||||
ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &server_addr));
|
||||
pinger = malloc(sizeof(*pinger));
|
||||
ASSERT(pinger != NULL);
|
||||
pinger->vectored_writes = vectored_writes;
|
||||
pinger->state = 0;
|
||||
pinger->pongs = 0;
|
||||
|
||||
/* Try to connect to the server and do NUM_PINGS ping-pongs. */
|
||||
r = uv_tcp_init(uv_default_loop(), &pinger->stream.tcp);
|
||||
pinger->stream.tcp.data = pinger;
|
||||
ASSERT(!r);
|
||||
|
||||
/* We are never doing multiple reads/connects at a time anyway, so these
|
||||
* handles can be pre-initialized. */
|
||||
r = uv_tcp_connect(&pinger->connect_req,
|
||||
&pinger->stream.tcp,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
pinger_on_connect);
|
||||
ASSERT(!r);
|
||||
|
||||
/* Synchronous connect callbacks are not allowed. */
|
||||
ASSERT(pinger_on_connect_count == 0);
|
||||
}
|
||||
|
||||
|
||||
static void tcp_pinger_new(int vectored_writes) {
|
||||
int r;
|
||||
struct sockaddr_in server_addr;
|
||||
pinger_t* pinger;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
|
||||
pinger = malloc(sizeof(*pinger));
|
||||
ASSERT(pinger != NULL);
|
||||
pinger->vectored_writes = vectored_writes;
|
||||
pinger->state = 0;
|
||||
pinger->pongs = 0;
|
||||
|
||||
/* Try to connect to the server and do NUM_PINGS ping-pongs. */
|
||||
r = uv_tcp_init(uv_default_loop(), &pinger->stream.tcp);
|
||||
pinger->stream.tcp.data = pinger;
|
||||
ASSERT(!r);
|
||||
|
||||
/* We are never doing multiple reads/connects at a time anyway, so these
|
||||
* handles can be pre-initialized. */
|
||||
r = uv_tcp_connect(&pinger->connect_req,
|
||||
&pinger->stream.tcp,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
pinger_on_connect);
|
||||
ASSERT(!r);
|
||||
|
||||
/* Synchronous connect callbacks are not allowed. */
|
||||
ASSERT(pinger_on_connect_count == 0);
|
||||
}
|
||||
|
||||
|
||||
static void pipe_pinger_new(int vectored_writes) {
|
||||
int r;
|
||||
pinger_t* pinger;
|
||||
|
||||
pinger = malloc(sizeof(*pinger));
|
||||
ASSERT(pinger != NULL);
|
||||
pinger->vectored_writes = vectored_writes;
|
||||
pinger->state = 0;
|
||||
pinger->pongs = 0;
|
||||
|
||||
/* Try to connect to the server and do NUM_PINGS ping-pongs. */
|
||||
r = uv_pipe_init(uv_default_loop(), &pinger->stream.pipe, 0);
|
||||
pinger->stream.pipe.data = pinger;
|
||||
ASSERT(!r);
|
||||
|
||||
/* We are never doing multiple reads/connects at a time anyway, so these
|
||||
* handles can be pre-initialized. */
|
||||
uv_pipe_connect(&pinger->connect_req, &pinger->stream.pipe, TEST_PIPENAME,
|
||||
pinger_on_connect);
|
||||
|
||||
/* Synchronous connect callbacks are not allowed. */
|
||||
ASSERT(pinger_on_connect_count == 0);
|
||||
}
|
||||
|
||||
|
||||
static int run_ping_pong_test(void) {
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(completed_pingers == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_ping_pong) {
|
||||
tcp_pinger_new(0);
|
||||
return run_ping_pong_test();
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_ping_pong_vec) {
|
||||
tcp_pinger_new(1);
|
||||
return run_ping_pong_test();
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp6_ping_pong) {
|
||||
if (!can_ipv6())
|
||||
RETURN_SKIP("IPv6 not supported");
|
||||
tcp_pinger_v6_new(0);
|
||||
return run_ping_pong_test();
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp6_ping_pong_vec) {
|
||||
if (!can_ipv6())
|
||||
RETURN_SKIP("IPv6 not supported");
|
||||
tcp_pinger_v6_new(1);
|
||||
return run_ping_pong_test();
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_ping_pong) {
|
||||
pipe_pinger_new(0);
|
||||
return run_ping_pong_test();
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_ping_pong_vec) {
|
||||
pipe_pinger_new(1);
|
||||
return run_ping_pong_test();
|
||||
}
|
139
deps/libuv/test/test-pipe-bind-error.c
vendored
Normal file
139
deps/libuv/test/test-pipe-bind-error.c
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
# define BAD_PIPENAME "bad-pipe"
|
||||
#else
|
||||
# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there"
|
||||
#endif
|
||||
|
||||
|
||||
static int close_cb_called = 0;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_bind_error_addrinuse) {
|
||||
uv_pipe_t server1, server2;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &server1, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_pipe_bind(&server1, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &server2, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_pipe_bind(&server2, TEST_PIPENAME);
|
||||
ASSERT(r == UV_EADDRINUSE);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server1, SOMAXCONN, NULL);
|
||||
ASSERT(r == 0);
|
||||
r = uv_listen((uv_stream_t*)&server2, SOMAXCONN, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
uv_close((uv_handle_t*)&server1, close_cb);
|
||||
uv_close((uv_handle_t*)&server2, close_cb);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 2);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_bind_error_addrnotavail) {
|
||||
uv_pipe_t server;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &server, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_bind(&server, BAD_PIPENAME);
|
||||
ASSERT(r == UV_EACCES);
|
||||
|
||||
uv_close((uv_handle_t*)&server, close_cb);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_bind_error_inval) {
|
||||
uv_pipe_t server;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &server, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_pipe_bind(&server, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
r = uv_pipe_bind(&server, TEST_PIPENAME_2);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
uv_close((uv_handle_t*)&server, close_cb);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_listen_without_bind) {
|
||||
#if defined(NO_SELF_CONNECT)
|
||||
RETURN_SKIP(NO_SELF_CONNECT);
|
||||
#endif
|
||||
uv_pipe_t server;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &server, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
uv_close((uv_handle_t*)&server, close_cb);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
112
deps/libuv/test/test-pipe-close-stdout-read-stdin.c
vendored
Normal file
112
deps/libuv/test/test-pipe-close-stdout-read-stdin.c
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t* buf)
|
||||
{
|
||||
static char buffer[1024];
|
||||
|
||||
buf->base = buffer;
|
||||
buf->len = sizeof(buffer);
|
||||
}
|
||||
|
||||
void read_stdin(uv_stream_t *stream, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
if (nread < 0) {
|
||||
uv_close((uv_handle_t*)stream, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This test is a reproduction of joyent/libuv#1419 .
|
||||
*/
|
||||
TEST_IMPL(pipe_close_stdout_read_stdin) {
|
||||
int r = -1;
|
||||
int pid;
|
||||
int fd[2];
|
||||
int status;
|
||||
char buf;
|
||||
uv_pipe_t stdin_pipe;
|
||||
|
||||
r = pipe(fd);
|
||||
ASSERT(r == 0);
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
/*
|
||||
* Make the read side of the pipe our stdin.
|
||||
* The write side will be closed by the parent process.
|
||||
*/
|
||||
close(fd[1]);
|
||||
/* block until write end of pipe is closed */
|
||||
r = read(fd[0], &buf, 1);
|
||||
ASSERT(-1 <= r && r <= 1);
|
||||
close(0);
|
||||
r = dup(fd[0]);
|
||||
ASSERT(r != -1);
|
||||
|
||||
/* Create a stream that reads from the pipe. */
|
||||
r = uv_pipe_init(uv_default_loop(), (uv_pipe_t *)&stdin_pipe, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_open((uv_pipe_t *)&stdin_pipe, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t *)&stdin_pipe, alloc_buffer, read_stdin);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/*
|
||||
* Because the other end of the pipe was closed, there should
|
||||
* be no event left to process after one run of the event loop.
|
||||
* Otherwise, it means that events were not processed correctly.
|
||||
*/
|
||||
ASSERT(uv_run(uv_default_loop(), UV_RUN_NOWAIT) == 0);
|
||||
} else {
|
||||
/*
|
||||
* Close both ends of the pipe so that the child
|
||||
* get a POLLHUP event when it tries to read from
|
||||
* the other end.
|
||||
*/
|
||||
close(fd[1]);
|
||||
close(fd[0]);
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
ASSERT(WIFEXITED(status) && WEXITSTATUS(status) == 0);
|
||||
}
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
|
||||
|
||||
#endif /* ifndef _WIN32 */
|
95
deps/libuv/test/test-pipe-connect-error.c
vendored
Normal file
95
deps/libuv/test/test-pipe-connect-error.c
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
# define BAD_PIPENAME "bad-pipe"
|
||||
#else
|
||||
# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there"
|
||||
#endif
|
||||
|
||||
|
||||
static int close_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* connect_req, int status) {
|
||||
ASSERT(status == UV_ENOENT);
|
||||
uv_close((uv_handle_t*)connect_req->handle, close_cb);
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb_file(uv_connect_t* connect_req, int status) {
|
||||
ASSERT(status == UV_ENOTSOCK || status == UV_ECONNREFUSED);
|
||||
uv_close((uv_handle_t*)connect_req->handle, close_cb);
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_bad_name) {
|
||||
uv_pipe_t client;
|
||||
uv_connect_t req;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &client, 0);
|
||||
ASSERT(r == 0);
|
||||
uv_pipe_connect(&req, &client, BAD_PIPENAME, connect_cb);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
ASSERT(connect_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_to_file) {
|
||||
const char* path = "test/fixtures/empty_file";
|
||||
uv_pipe_t client;
|
||||
uv_connect_t req;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &client, 0);
|
||||
ASSERT(r == 0);
|
||||
uv_pipe_connect(&req, &client, path, connect_cb_file);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
ASSERT(connect_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
107
deps/libuv/test/test-pipe-connect-multiple.c
vendored
Normal file
107
deps/libuv/test/test-pipe-connect-multiple.c
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
|
||||
* 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>
|
||||
|
||||
|
||||
static int connection_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
|
||||
#define NUM_CLIENTS 4
|
||||
|
||||
typedef struct {
|
||||
uv_pipe_t pipe_handle;
|
||||
uv_connect_t conn_req;
|
||||
} client_t;
|
||||
|
||||
static uv_pipe_t server_handle;
|
||||
static client_t clients[NUM_CLIENTS];
|
||||
static uv_pipe_t connections[NUM_CLIENTS];
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* server, int status) {
|
||||
int r;
|
||||
uv_pipe_t* conn;
|
||||
ASSERT(status == 0);
|
||||
|
||||
conn = &connections[connection_cb_called];
|
||||
r = uv_pipe_init(server->loop, conn, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)conn);
|
||||
ASSERT(r == 0);
|
||||
|
||||
if (++connection_cb_called == NUM_CLIENTS &&
|
||||
connect_cb_called == NUM_CLIENTS) {
|
||||
uv_stop(server->loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* connect_req, int status) {
|
||||
ASSERT(status == 0);
|
||||
if (++connect_cb_called == NUM_CLIENTS &&
|
||||
connection_cb_called == NUM_CLIENTS) {
|
||||
uv_stop(connect_req->handle->loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_multiple) {
|
||||
#if defined(NO_SELF_CONNECT)
|
||||
RETURN_SKIP(NO_SELF_CONNECT);
|
||||
#endif
|
||||
int i;
|
||||
int r;
|
||||
uv_loop_t* loop;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
r = uv_pipe_init(loop, &server_handle, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_bind(&server_handle, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server_handle, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
for (i = 0; i < NUM_CLIENTS; i++) {
|
||||
r = uv_pipe_init(loop, &clients[i].pipe_handle, 0);
|
||||
ASSERT(r == 0);
|
||||
uv_pipe_connect(&clients[i].conn_req,
|
||||
&clients[i].pipe_handle,
|
||||
TEST_PIPENAME,
|
||||
connect_cb);
|
||||
}
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(connection_cb_called == NUM_CLIENTS);
|
||||
ASSERT(connect_cb_called == NUM_CLIENTS);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
83
deps/libuv/test/test-pipe-connect-prepare.c
vendored
Normal file
83
deps/libuv/test/test-pipe-connect-prepare.c
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
/* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
|
||||
* 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>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
# define BAD_PIPENAME "bad-pipe"
|
||||
#else
|
||||
# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there"
|
||||
#endif
|
||||
|
||||
|
||||
static int close_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
|
||||
static uv_pipe_t pipe_handle;
|
||||
static uv_prepare_t prepare_handle;
|
||||
static uv_connect_t conn_req;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* connect_req, int status) {
|
||||
ASSERT(status == UV_ENOENT);
|
||||
connect_cb_called++;
|
||||
uv_close((uv_handle_t*)&prepare_handle, close_cb);
|
||||
uv_close((uv_handle_t*)&pipe_handle, close_cb);
|
||||
}
|
||||
|
||||
|
||||
static void prepare_cb(uv_prepare_t* handle) {
|
||||
ASSERT(handle == &prepare_handle);
|
||||
uv_pipe_connect(&conn_req, &pipe_handle, BAD_PIPENAME, connect_cb);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_on_prepare) {
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &pipe_handle, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_prepare_init(uv_default_loop(), &prepare_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_prepare_start(&prepare_handle, prepare_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(close_cb_called == 2);
|
||||
ASSERT(connect_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user