@@ -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 (100 * 1000)

static volatile int num_threads;


static void thread_entry(void* arg) {
ASSERT(arg == (void *) 42);
num_threads++;
/* FIXME write barrier? */
}


BENCHMARK_IMPL(thread_create) {
uint64_t start_time;
double duration;
uv_thread_t tid;
int i, r;

start_time = uv_hrtime();

for (i = 0; i < NUM_THREADS; i++) {
r = uv_thread_create(&tid, thread_entry, (void *) 42);
ASSERT(r == 0);

r = uv_thread_join(&tid);
ASSERT(r == 0);
}

duration = (uv_hrtime() - start_time) / 1e9;

ASSERT(num_threads == NUM_THREADS);

printf("%d threads created in %.2f seconds (%.0f/s)\n",
NUM_THREADS, duration, NUM_THREADS / duration);

return 0;
}
@@ -99,14 +99,34 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
uv_close((uv_handle_t*)handle, close_cb);
}

static void timber_cb_close_handle(uv_timer_t* timer, int status) {
uv_handle_t* handle;

ASSERT(timer != NULL);
ASSERT(status == 0);
handle = timer->data;

uv_close((uv_handle_t*)timer, NULL);
uv_close((uv_handle_t*)handle, close_cb);
}

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(handle == &fs_event);
ASSERT(status == 0);
ASSERT(events == UV_CHANGE);
ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
uv_close((uv_handle_t*)handle, close_cb);

/* Regression test for SunOS: touch should generate just one event. */
{
static uv_timer_t timer;
uv_timer_init(handle->loop, &timer);
timer.data = handle;
uv_timer_start(&timer, timber_cb_close_handle, 250, 0);
}
}

static void timer_cb_dir(uv_timer_t* handle, int status) {
@@ -90,6 +90,7 @@ TEST_DECLARE (spawn_exit_code)
TEST_DECLARE (spawn_stdout)
TEST_DECLARE (spawn_stdin)
TEST_DECLARE (spawn_and_kill)
TEST_DECLARE (spawn_and_kill_with_std)
TEST_DECLARE (spawn_and_ping)
TEST_DECLARE (kill)
TEST_DECLARE (fs_file_noent)
@@ -117,6 +118,10 @@ TEST_DECLARE (fs_open_dir)
TEST_DECLARE (threadpool_queue_work_simple)
TEST_DECLARE (thread_mutex)
TEST_DECLARE (thread_rwlock)
TEST_DECLARE (thread_create)
TEST_DECLARE (strlcpy)
TEST_DECLARE (strlcat)

#ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
TEST_DECLARE (argument_escaping)
@@ -237,6 +242,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_stdout)
TEST_ENTRY (spawn_stdin)
TEST_ENTRY (spawn_and_kill)
TEST_ENTRY (spawn_and_kill_with_std)
TEST_ENTRY (spawn_and_ping)
TEST_ENTRY (kill)
#ifdef _WIN32
@@ -271,6 +277,9 @@ TASK_LIST_START
TEST_ENTRY (threadpool_queue_work_simple)
TEST_ENTRY (thread_mutex)
TEST_ENTRY (thread_rwlock)
TEST_ENTRY (thread_create)
TEST_ENTRY (strlcpy)
TEST_ENTRY (strlcat)

#if 0
/* These are for testing the test runner. */
@@ -231,6 +231,37 @@ TEST_IMPL(spawn_and_kill) {
}


TEST_IMPL(spawn_and_kill_with_std) {
int r;
uv_pipe_t out;
uv_pipe_t in;

init_process_options("spawn_helper4", kill_cb);

uv_pipe_init(uv_default_loop(), &out, 0);
uv_pipe_init(uv_default_loop(), &in, 0);
options.stdout_stream = &out;
options.stdin_stream = &in;

r = uv_spawn(uv_default_loop(), &process, options);
ASSERT(r == 0);

r = uv_timer_init(uv_default_loop(), &timer);
ASSERT(r == 0);

r = uv_timer_start(&timer, timer_cb, 500, 0);
ASSERT(r == 0);

r = uv_run(uv_default_loop());
ASSERT(r == 0);

ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 2); /* Once for process and once for timer. */

return 0;
}


TEST_IMPL(spawn_and_ping) {
uv_write_t write_req;
uv_pipe_t in, out;
@@ -0,0 +1,51 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include "uv.h"
#include "task.h"

#include <stdio.h>
#include <stdlib.h>


static volatile int thread_called;


static void thread_entry(void* arg) {
ASSERT(arg == (void *) 42);
thread_called++;
}


TEST_IMPL(thread_create) {
uv_thread_t tid;
int r;

r = uv_thread_create(&tid, thread_entry, (void *) 42);
ASSERT(r == 0);

r = uv_thread_join(&tid);
ASSERT(r == 0);

ASSERT(thread_called == 1);

return 0;
}
@@ -0,0 +1,97 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include "uv.h"
#include "task.h"

#include <string.h>

#define memeq(a, b, c) (memcmp((a), (b), (c)) == 0)


TEST_IMPL(strlcpy) {
size_t r;

{
char dst[2] = "A";
r = uv_strlcpy(dst, "", 0);
ASSERT(r == 0);
ASSERT(memeq(dst, "A", 1));
}

{
char dst[2] = "A";
r = uv_strlcpy(dst, "B", 1);
ASSERT(r == 0);
ASSERT(memeq(dst, "", 1));
}

{
char dst[2] = "A";
r = uv_strlcpy(dst, "B", 2);
ASSERT(r == 1);
ASSERT(memeq(dst, "B", 2));
}

{
char dst[3] = "AB";
r = uv_strlcpy(dst, "CD", 3);
ASSERT(r == 2);
ASSERT(memeq(dst, "CD", 3));
}

return 0;
}


TEST_IMPL(strlcat) {
size_t r;

{
char dst[2] = "A";
r = uv_strlcat(dst, "B", 1);
ASSERT(r == 1);
ASSERT(memeq(dst, "A", 2));
}

{
char dst[2] = "A";
r = uv_strlcat(dst, "B", 2);
ASSERT(r == 1);
ASSERT(memeq(dst, "A", 2));
}

{
char dst[3] = "A";
r = uv_strlcat(dst, "B", 3);
ASSERT(r == 2);
ASSERT(memeq(dst, "AB", 3));
}

{
char dst[5] = "AB";
r = uv_strlcat(dst, "CD", 5);
ASSERT(r == 4);
ASSERT(memeq(dst, "ABCD", 5));
}

return 0;
}
@@ -9,6 +9,9 @@
'EIO_STACKSIZE=262144'
],
'conditions': [
['OS=="mac"', {
'defines': ['__DARWIN_64_BIT_INO_T=1'],
}],
['OS=="solaris"', {
'cflags': ['-pthreads'],
'ldlags': ['-pthreads'],
@@ -275,6 +278,7 @@
'test/runner.h',
'test/test-get-loadavg.c',
'test/task.h',
'test/test-util.c',
'test/test-async.c',
'test/test-error.c',
'test/test-callback-stack.c',
@@ -313,6 +317,7 @@
'test/test-tcp-writealot.c',
'test/test-threadpool.c',
'test/test-mutexes.c',
'test/test-thread.c',
'test/test-timer-again.c',
'test/test-timer.c',
'test/test-tty.c',
@@ -362,6 +367,7 @@
'test/benchmark-pump.c',
'test/benchmark-sizes.c',
'test/benchmark-spawn.c',
'test/benchmark-thread.c',
'test/benchmark-tcp-write-batch.c',
'test/benchmark-udp-packet-storm.c',
'test/dns-server.c',