Blame test/test-spawn.c

Packit Service 7c31a4
Packit Service 7c31a4
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service 7c31a4
 * of this software and associated documentation files (the "Software"), to
Packit Service 7c31a4
 * deal in the Software without restriction, including without limitation the
Packit Service 7c31a4
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit Service 7c31a4
 * sell copies of the Software, and to permit persons to whom the Software is
Packit Service 7c31a4
 * furnished to do so, subject to the following conditions:
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * The above copyright notice and this permission notice shall be included in
Packit Service 7c31a4
 * all copies or substantial portions of the Software.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 7c31a4
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 7c31a4
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit Service 7c31a4
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service 7c31a4
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service 7c31a4
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit Service 7c31a4
 * IN THE SOFTWARE.
Packit Service 7c31a4
 */
Packit Service 7c31a4
Packit Service 7c31a4
#include "uv.h"
Packit Service 7c31a4
#include "task.h"
Packit Service 7c31a4
#include <errno.h>
Packit Service 7c31a4
#include <fcntl.h>
Packit Service 7c31a4
#include <stdio.h>
Packit Service 7c31a4
#include <stdlib.h>
Packit Service 7c31a4
#include <string.h>
Packit Service 7c31a4
Packit Service 7c31a4
#ifdef _WIN32
Packit Service 7c31a4
# if defined(__MINGW32__)
Packit Service 7c31a4
#  include <basetyps.h>
Packit Service 7c31a4
# endif
Packit Service 7c31a4
# include <shellapi.h>
Packit Service 7c31a4
# include <wchar.h>
Packit Service 7c31a4
#else
Packit Service 7c31a4
# include <unistd.h>
Packit Service 7c31a4
# include <sys/wait.h>
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int close_cb_called;
Packit Service 7c31a4
static int exit_cb_called;
Packit Service 7c31a4
static uv_process_t process;
Packit Service 7c31a4
static uv_timer_t timer;
Packit Service 7c31a4
static uv_process_options_t options;
Packit Service 7c31a4
static char exepath[1024];
Packit Service 7c31a4
static size_t exepath_size = 1024;
Packit Service 7c31a4
static char* args[5];
Packit Service 7c31a4
static int no_term_signal;
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
static int timer_counter;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
static uv_tcp_t tcp_server;
Packit Service 7c31a4
Packit Service 7c31a4
#define OUTPUT_SIZE 1024
Packit Service 7c31a4
static char output[OUTPUT_SIZE];
Packit Service 7c31a4
static int output_used;
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void close_cb(uv_handle_t* handle) {
Packit Service 7c31a4
  printf("close_cb\n");
Packit Service 7c31a4
  close_cb_called++;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
static void exit_cb(uv_process_t* process,
Packit Service 7c31a4
                    int64_t exit_status,
Packit Service 7c31a4
                    int term_signal) {
Packit Service 7c31a4
  printf("exit_cb\n");
Packit Service 7c31a4
  exit_cb_called++;
Packit Service 7c31a4
  ASSERT(exit_status == 1);
Packit Service 7c31a4
  ASSERT(term_signal == 0);
Packit Service e2ebee
  uv_close((uv_handle_t*) process, close_cb);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fail_cb(uv_process_t* process,
Packit Service 7c31a4
                    int64_t exit_status,
Packit Service 7c31a4
                    int term_signal) {
Packit Service 7c31a4
  ASSERT(0 && "fail_cb called");
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void kill_cb(uv_process_t* process,
Packit Service 7c31a4
                    int64_t exit_status,
Packit Service 7c31a4
                    int term_signal) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  printf("exit_cb\n");
Packit Service 7c31a4
  exit_cb_called++;
Packit Service 7c31a4
#ifdef _WIN32
Packit Service 7c31a4
  ASSERT(exit_status == 1);
Packit Service 7c31a4
#else
Packit Service 7c31a4
  ASSERT(exit_status == 0);
Packit Service 7c31a4
#endif
Packit Service 7c31a4
#if defined(__APPLE__) || defined(__MVS__)
Packit Service 7c31a4
  /*
Packit Service 7c31a4
   * At least starting with Darwin Kernel Version 16.4.0, sending a SIGTERM to a
Packit Service 7c31a4
   * process that is still starting up kills it with SIGKILL instead of SIGTERM.
Packit Service 7c31a4
   * See: https://github.com/libuv/libuv/issues/1226
Packit Service 7c31a4
   */
Packit Service 7c31a4
  ASSERT(no_term_signal || term_signal == SIGTERM || term_signal == SIGKILL);
Packit Service 7c31a4
#else
Packit Service 7c31a4
  ASSERT(no_term_signal || term_signal == SIGTERM);
Packit Service 7c31a4
#endif
Packit Service e2ebee
  uv_close((uv_handle_t*) process, close_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  /*
Packit Service 7c31a4
   * Sending signum == 0 should check if the
Packit Service 7c31a4
   * child process is still alive, not kill it.
Packit Service 7c31a4
   * This process should be dead.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  err = uv_kill(process->pid, 0);
Packit Service 7c31a4
  ASSERT(err == UV_ESRCH);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
static void detach_failure_cb(uv_process_t* process,
Packit Service 7c31a4
                              int64_t exit_status,
Packit Service 7c31a4
                              int term_signal) {
Packit Service 7c31a4
  printf("detach_cb\n");
Packit Service 7c31a4
  exit_cb_called++;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
static void on_alloc(uv_handle_t* handle,
Packit Service 7c31a4
                     size_t suggested_size,
Packit Service 7c31a4
                     uv_buf_t* buf) {
Packit Service 7c31a4
  buf->base = output + output_used;
Packit Service 7c31a4
  buf->len = OUTPUT_SIZE - output_used;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
Packit Service 7c31a4
  if (nread > 0) {
Packit Service 7c31a4
    output_used += nread;
Packit Service 7c31a4
  } else if (nread < 0) {
Packit Service 7c31a4
    ASSERT(nread == UV_EOF);
Packit Service e2ebee
    uv_close((uv_handle_t*) tcp, close_cb);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
static void on_read_once(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
Packit Service 7c31a4
  uv_read_stop(tcp);
Packit Service 7c31a4
  on_read(tcp, nread, buf);
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void write_cb(uv_write_t* req, int status) {
Packit Service 7c31a4
  ASSERT(status == 0);
Packit Service e2ebee
  uv_close((uv_handle_t*) req->handle, close_cb);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void init_process_options(char* test, uv_exit_cb exit_cb) {
Packit Service 7c31a4
  /* Note spawn_helper1 defined in test/run-tests.c */
Packit Service 7c31a4
  int r = uv_exepath(exepath, &exepath_size);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  exepath[exepath_size] = '\0';
Packit Service 7c31a4
  args[0] = exepath;
Packit Service 7c31a4
  args[1] = test;
Packit Service 7c31a4
  args[2] = NULL;
Packit Service 7c31a4
  args[3] = NULL;
Packit Service 7c31a4
  args[4] = NULL;
Packit Service 7c31a4
  options.file = exepath;
Packit Service 7c31a4
  options.args = args;
Packit Service 7c31a4
  options.exit_cb = exit_cb;
Packit Service 7c31a4
  options.flags = 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void timer_cb(uv_timer_t* handle) {
Packit Service e2ebee
  uv_process_kill(&process, SIGTERM);
Packit Service e2ebee
  uv_close((uv_handle_t*) handle, close_cb);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
static void timer_counter_cb(uv_timer_t* handle) {
Packit Service 7c31a4
  ++timer_counter;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_fails) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("", fail_cb);
Packit Service 7c31a4
  options.file = options.args[0] = "program-that-had-better-not-exist";
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == UV_ENOENT || r == UV_EACCES);
Packit Service 7c31a4
  ASSERT(0 == uv_is_active((uv_handle_t*) &process));
Packit Service 7c31a4
  uv_close((uv_handle_t*) &process, NULL);
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  int status;
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("", fail_cb);
Packit Service 7c31a4
  options.file = options.args[0] = "program-that-had-better-not-exist";
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == UV_ENOENT || r == UV_EACCES);
Packit Service 7c31a4
  ASSERT(0 == uv_is_active((uv_handle_t*) &process));
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
Packit Service 7c31a4
  /* verify the child is successfully cleaned up within libuv */
Packit Service 7c31a4
  do
Packit Service 7c31a4
    err = waitpid(process.pid, &status, 0);
Packit Service 7c31a4
  while (err == -1 && errno == EINTR);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(err == -1);
Packit Service 7c31a4
  ASSERT(errno == ECHILD);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_close((uv_handle_t*) &process, NULL);
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_empty_env) {
Packit Service 7c31a4
  char* env[1];
Packit Service 7c31a4
Packit Service 7c31a4
  /* The autotools dynamic library build requires the presence of
Packit Service 7c31a4
   * DYLD_LIBARY_PATH (macOS) or LD_LIBRARY_PATH/LIBPATH (other Unices)
Packit Service 7c31a4
   * in the environment, but of course that doesn't work with
Packit Service 7c31a4
   * the empty environment that we're testing here.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (NULL != getenv("DYLD_LIBRARY_PATH") ||
Packit Service 7c31a4
      NULL != getenv("LD_LIBRARY_PATH") ||
Packit Service 7c31a4
      NULL != getenv("LIBPATH")) {
Packit Service 7c31a4
    RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH/LIBPATH");
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper1", exit_cb);
Packit Service 7c31a4
  options.env = env;
Packit Service 7c31a4
  env[0] = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_exit_code) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper1", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_stdout) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_pipe_t out;
Packit Service 7c31a4
  uv_stdio_container_t stdio[2];
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper2", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &out, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[1].data.stream = (uv_stream_t*) &out;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strcmp("hello world\n", output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_stdout_to_file) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_file file;
Packit Service 7c31a4
  uv_fs_t fs_req;
Packit Service 7c31a4
  uv_stdio_container_t stdio[2];
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Setup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper2", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
Packit Service 7c31a4
      S_IRUSR | S_IWUSR, NULL);
Packit Service 7c31a4
  ASSERT(r != -1);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  file = r;
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[1].data.fd = file;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  buf = uv_buf_init(output, sizeof(output));
Packit Service 7c31a4
  r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
Packit Service 7c31a4
  ASSERT(r == 12);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_fs_close(NULL, &fs_req, file, NULL);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strcmp("hello world\n", output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Cleanup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_stdout_and_stderr_to_file) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_file file;
Packit Service 7c31a4
  uv_fs_t fs_req;
Packit Service 7c31a4
  uv_stdio_container_t stdio[3];
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Setup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper6", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
Packit Service 7c31a4
      S_IRUSR | S_IWUSR, NULL);
Packit Service 7c31a4
  ASSERT(r != -1);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  file = r;
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[1].data.fd = file;
Packit Service 7c31a4
  options.stdio[2].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[2].data.fd = file;
Packit Service 7c31a4
  options.stdio_count = 3;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  buf = uv_buf_init(output, sizeof(output));
Packit Service 7c31a4
  r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
Packit Service 7c31a4
  ASSERT(r == 27);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_fs_close(NULL, &fs_req, file, NULL);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strcmp("hello world\nhello errworld\n", output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Cleanup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_stdout_and_stderr_to_file2) {
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_file file;
Packit Service 7c31a4
  uv_fs_t fs_req;
Packit Service 7c31a4
  uv_stdio_container_t stdio[3];
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Setup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper6", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Replace stderr with our file */
Packit Service 7c31a4
  r = uv_fs_open(NULL,
Packit Service 7c31a4
                 &fs_req,
Packit Service 7c31a4
                 "stdout_file",
Packit Service 7c31a4
                 O_CREAT | O_RDWR,
Packit Service 7c31a4
                 S_IRUSR | S_IWUSR,
Packit Service 7c31a4
                 NULL);
Packit Service 7c31a4
  ASSERT(r != -1);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
  file = dup2(r, STDERR_FILENO);
Packit Service 7c31a4
  ASSERT(file != -1);
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[1].data.fd = file;
Packit Service 7c31a4
  options.stdio[2].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[2].data.fd = file;
Packit Service 7c31a4
  options.stdio_count = 3;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  buf = uv_buf_init(output, sizeof(output));
Packit Service 7c31a4
  r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
Packit Service 7c31a4
  ASSERT(r == 27);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_fs_close(NULL, &fs_req, file, NULL);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strcmp("hello world\nhello errworld\n", output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Cleanup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
#else
Packit Service 7c31a4
  RETURN_SKIP("Unix only test");
Packit Service 7c31a4
#endif
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_file stdout_file;
Packit Service 7c31a4
  uv_file stderr_file;
Packit Service 7c31a4
  uv_fs_t fs_req;
Packit Service 7c31a4
  uv_stdio_container_t stdio[3];
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Setup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
  unlink("stderr_file");
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper6", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  /* open 'stdout_file' and replace STDOUT_FILENO with it */
Packit Service 7c31a4
  r = uv_fs_open(NULL,
Packit Service 7c31a4
                 &fs_req,
Packit Service 7c31a4
                 "stdout_file",
Packit Service 7c31a4
                 O_CREAT | O_RDWR,
Packit Service 7c31a4
                 S_IRUSR | S_IWUSR,
Packit Service 7c31a4
                 NULL);
Packit Service 7c31a4
  ASSERT(r != -1);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
  stdout_file = dup2(r, STDOUT_FILENO);
Packit Service 7c31a4
  ASSERT(stdout_file != -1);
Packit Service 7c31a4
Packit Service 7c31a4
  /* open 'stderr_file' and replace STDERR_FILENO with it */
Packit Service 7c31a4
  r = uv_fs_open(NULL, &fs_req, "stderr_file", O_CREAT | O_RDWR,
Packit Service 7c31a4
      S_IRUSR | S_IWUSR, NULL);
Packit Service 7c31a4
  ASSERT(r != -1);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
  stderr_file = dup2(r, STDERR_FILENO);
Packit Service 7c31a4
  ASSERT(stderr_file != -1);
Packit Service 7c31a4
Packit Service 7c31a4
  /* now we're going to swap them: the child process' stdout will be our
Packit Service 7c31a4
   * stderr_file and vice versa */
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[1].data.fd = stderr_file;
Packit Service 7c31a4
  options.stdio[2].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[2].data.fd = stdout_file;
Packit Service 7c31a4
  options.stdio_count = 3;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  buf = uv_buf_init(output, sizeof(output));
Packit Service 7c31a4
Packit Service 7c31a4
  /* check the content of stdout_file */
Packit Service 7c31a4
  r = uv_fs_read(NULL, &fs_req, stdout_file, &buf, 1, 0, NULL);
Packit Service 7c31a4
  ASSERT(r >= 15);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_fs_close(NULL, &fs_req, stdout_file, NULL);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strncmp("hello errworld\n", output, 15) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* check the content of stderr_file */
Packit Service 7c31a4
  r = uv_fs_read(NULL, &fs_req, stderr_file, &buf, 1, 0, NULL);
Packit Service 7c31a4
  ASSERT(r >= 12);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_fs_close(NULL, &fs_req, stderr_file, NULL);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strncmp("hello world\n", output, 12) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Cleanup. */
Packit Service 7c31a4
  unlink("stdout_file");
Packit Service 7c31a4
  unlink("stderr_file");
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
#else
Packit Service 7c31a4
  RETURN_SKIP("Unix only test");
Packit Service 7c31a4
#endif
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_stdin) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_pipe_t out;
Packit Service 7c31a4
  uv_pipe_t in;
Packit Service 7c31a4
  uv_write_t write_req;
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
  uv_stdio_container_t stdio[2];
Packit Service 7c31a4
  char buffer[] = "hello-from-spawn_stdin";
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper3", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &out, 0);
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &in, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
Packit Service e2ebee
  options.stdio[0].data.stream = (uv_stream_t*) ∈
Packit Service 7c31a4
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[1].data.stream = (uv_stream_t*) &out;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  buf.base = buffer;
Packit Service 7c31a4
  buf.len = sizeof(buffer);
Packit Service e2ebee
  r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 3); /* Once for process twice for the pipe. */
Packit Service 7c31a4
  ASSERT(strcmp(buffer, output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_stdio_greater_than_3) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_pipe_t pipe;
Packit Service 7c31a4
  uv_stdio_container_t stdio[4];
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper5", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &pipe, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[2].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[3].data.stream = (uv_stream_t*) &pip;;
Packit Service 7c31a4
  options.stdio_count = 4;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_read_start((uv_stream_t*) &pipe, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
Packit Service 7c31a4
  printf("output from stdio[3] is: %s", output);
Packit Service 7c31a4
  ASSERT(strcmp("fourth stdio!\n", output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int spawn_tcp_server_helper(void) {
Packit Service 7c31a4
  uv_tcp_t tcp;
Packit Service 7c31a4
  uv_os_sock_t handle;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_tcp_init(uv_default_loop(), &tcp;;
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
#ifdef _WIN32
Packit Service 7c31a4
  handle = _get_osfhandle(3);
Packit Service 7c31a4
#else
Packit Service 7c31a4
  handle = 3;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
  r = uv_tcp_open(&tcp, handle);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Make sure that we can listen on a socket that was
Packit Service 7c31a4
   * passed down from the parent process
Packit Service 7c31a4
   */
Packit Service e2ebee
  r = uv_listen((uv_stream_t*) &tcp, SOMAXCONN, NULL);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  return 1;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_tcp_server) {
Packit Service 7c31a4
  uv_stdio_container_t stdio[4];
Packit Service 7c31a4
  struct sockaddr_in addr;
Packit Service 7c31a4
  int fd;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
#ifdef _WIN32
Packit Service 7c31a4
  uv_os_fd_t handle;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_tcp_server_helper", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
Packit Service 7c31a4
Packit Service 7c31a4
  fd = -1;
Packit Service 7c31a4
  r = uv_tcp_init_ex(uv_default_loop(), &tcp_server, AF_INET);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
#ifdef _WIN32
Packit Service e2ebee
  r = uv_fileno((uv_handle_t*) &tcp_server, &handle);
Packit Service 7c31a4
  fd = _open_osfhandle((intptr_t) handle, 0);
Packit Service 7c31a4
#else
Packit Service e2ebee
  r = uv_fileno((uv_handle_t*) &tcp_server, &fd;;
Packit Service 7c31a4
 #endif
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
  ASSERT(fd > 0);
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[0].data.fd = 0;
Packit Service 7c31a4
  options.stdio[1].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[1].data.fd = 1;
Packit Service 7c31a4
  options.stdio[2].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[2].data.fd = 2;
Packit Service 7c31a4
  options.stdio[3].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[3].data.fd = fd;
Packit Service 7c31a4
  options.stdio_count = 4;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_ignored_stdio) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper6", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = NULL;
Packit Service 7c31a4
  options.stdio_count = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_and_kill) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper4", kill_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_timer_init(uv_default_loop(), &timer;;
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_timer_start(&timer, timer_cb, 500, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 2); /* Once for process and once for timer. */
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_preserve_env) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_pipe_t out;
Packit Service 7c31a4
  uv_stdio_container_t stdio[2];
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper7", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &out, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service 7c31a4
  options.stdio[1].data.stream = (uv_stream_t*) &out;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  r = putenv("ENV_TEST=testval");
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Explicitly set options.env to NULL to test for env clobbering. */
Packit Service 7c31a4
  options.env = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 2);
Packit Service 7c31a4
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strcmp("testval", output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_detached) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper4", detach_failure_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  options.flags |= UV_PROCESS_DETACHED;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service e2ebee
  uv_unref((uv_handle_t*) &process);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(process.pid == uv_process_get_pid(&process));
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_kill(process.pid, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service e2ebee
  r = uv_kill(process.pid, SIGTERM);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_and_kill_with_std) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_pipe_t in, out, err;
Packit Service 7c31a4
  uv_write_t write;
Packit Service 7c31a4
  char message[] = "Nancy's joining me because the message this evening is "
Packit Service 7c31a4
                   "not my message but ours.";
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
  uv_stdio_container_t stdio[3];
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper4", kill_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_pipe_init(uv_default_loop(), &in, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_pipe_init(uv_default_loop(), &out, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_pipe_init(uv_default_loop(), &err, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
Packit Service e2ebee
  options.stdio[0].data.stream = (uv_stream_t*) ∈
Packit Service 7c31a4
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[1].data.stream = (uv_stream_t*) &out;
Packit Service 7c31a4
  options.stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[2].data.stream = (uv_stream_t*) &err;
Packit Service 7c31a4
  options.stdio_count = 3;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  buf = uv_buf_init(message, sizeof message);
Packit Service 7c31a4
  r = uv_write(&write, (uv_stream_t*) &in, &buf, 1, write_cb);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_read_start((uv_stream_t*) &err, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_timer_init(uv_default_loop(), &timer;;
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_timer_start(&timer, timer_cb, 500, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 5); /* process x 1, timer x 1, stdio x 3. */
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_and_ping) {
Packit Service 7c31a4
  uv_write_t write_req;
Packit Service 7c31a4
  uv_pipe_t in, out;
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
  uv_stdio_container_t stdio[2];
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper3", exit_cb);
Packit Service 7c31a4
  buf = uv_buf_init("TEST", 4);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &out, 0);
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &in, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
Packit Service e2ebee
  options.stdio[0].data.stream = (uv_stream_t*) ∈
Packit Service 7c31a4
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[1].data.stream = (uv_stream_t*) &out;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Sending signum == 0 should check if the
Packit Service 7c31a4
   * child process is still alive, not kill it.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  r = uv_process_kill(&process, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service e2ebee
  r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service e2ebee
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(strcmp(output, "TEST") == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_same_stdout_stderr) {
Packit Service 7c31a4
  uv_write_t write_req;
Packit Service 7c31a4
  uv_pipe_t in, out;
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
  uv_stdio_container_t stdio[3];
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper3", exit_cb);
Packit Service 7c31a4
  buf = uv_buf_init("TEST", 4);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &out, 0);
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &in, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
Packit Service e2ebee
  options.stdio[0].data.stream = (uv_stream_t*) ∈
Packit Service 7c31a4
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[1].data.stream = (uv_stream_t*) &out;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Sending signum == 0 should check if the
Packit Service 7c31a4
   * child process is still alive, not kill it.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  r = uv_process_kill(&process, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service e2ebee
  r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service e2ebee
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(strcmp(output, "TEST") == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_closed_process_io) {
Packit Service 7c31a4
  uv_pipe_t in;
Packit Service 7c31a4
  uv_write_t write_req;
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
  uv_stdio_container_t stdio[2];
Packit Service 7c31a4
  static char buffer[] = "hello-from-spawn_stdin\n";
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper3", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &in, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
Packit Service 7c31a4
  options.stdio[0].data.stream = (uv_stream_t*) ∈
Packit Service 7c31a4
  options.stdio_count = 1;
Packit Service 7c31a4
Packit Service 7c31a4
  close(0); /* Close process stdin. */
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
Packit Service 7c31a4
Packit Service 7c31a4
  buf = uv_buf_init(buffer, sizeof(buffer));
Packit Service 7c31a4
  ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 2); /* process, child stdin */
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(kill) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
#ifdef _WIN32
Packit Service 7c31a4
  no_term_signal = 1;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper4", kill_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Verify that uv_spawn() resets the signal disposition. */
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
  {
Packit Service 7c31a4
    sigset_t set;
Packit Service 7c31a4
    sigemptyset(&set);
Packit Service 7c31a4
    sigaddset(&set, SIGTERM);
Packit Service 7c31a4
    ASSERT(0 == pthread_sigmask(SIG_BLOCK, &set, NULL));
Packit Service 7c31a4
  }
Packit Service 7c31a4
  ASSERT(SIG_ERR != signal(SIGTERM, SIG_IGN));
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
  {
Packit Service 7c31a4
    sigset_t set;
Packit Service 7c31a4
    sigemptyset(&set);
Packit Service 7c31a4
    sigaddset(&set, SIGTERM);
Packit Service 7c31a4
    ASSERT(0 == pthread_sigmask(SIG_UNBLOCK, &set, NULL));
Packit Service 7c31a4
  }
Packit Service 7c31a4
  ASSERT(SIG_ERR != signal(SIGTERM, SIG_DFL));
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  /* Sending signum == 0 should check if the
Packit Service 7c31a4
   * child process is still alive, not kill it.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  r = uv_kill(process.pid, 0);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Kill the process. */
Packit Service e2ebee
  r = uv_kill(process.pid, SIGTERM);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifdef _WIN32
Packit Service 7c31a4
TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  uv_pipe_t out;
Packit Service 7c31a4
  char name[64];
Packit Service 7c31a4
  HANDLE pipe_handle;
Packit Service 7c31a4
  uv_stdio_container_t stdio[2];
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper2", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  uv_pipe_init(uv_default_loop(), &out, 0);
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
Packit Service e2ebee
  options.stdio[1].data.stream = (uv_stream_t*) &out;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Create a pipe that'll cause a collision. */
Packit Service 7c31a4
  snprintf(name,
Packit Service 7c31a4
           sizeof(name),
Packit Service 7c31a4
           "\\\\.\\pipe\\uv\\%p-%d",
Packit Service 7c31a4
           &out,
Packit Service 7c31a4
           GetCurrentProcessId());
Packit Service 7c31a4
  pipe_handle = CreateNamedPipeA(name,
Packit Service 7c31a4
                                PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
Packit Service 7c31a4
                                PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
Packit Service 7c31a4
                                10,
Packit Service 7c31a4
                                65536,
Packit Service 7c31a4
                                65536,
Packit Service 7c31a4
                                0,
Packit Service 7c31a4
                                NULL);
Packit Service 7c31a4
  ASSERT(pipe_handle != INVALID_HANDLE_VALUE);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
Packit Service 7c31a4
  printf("output is: %s", output);
Packit Service 7c31a4
  ASSERT(strcmp("hello world\n", output) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#if !defined(USING_UV_SHARED)
Packit Service 7c31a4
int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr);
Packit Service 7c31a4
WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target);
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(argument_escaping) {
Packit Service 7c31a4
  const WCHAR* test_str[] = {
Packit Service 7c31a4
    L"",
Packit Service 7c31a4
    L"HelloWorld",
Packit Service 7c31a4
    L"Hello World",
Packit Service 7c31a4
    L"Hello\"World",
Packit Service 7c31a4
    L"Hello World\\",
Packit Service 7c31a4
    L"Hello\\\"World",
Packit Service 7c31a4
    L"Hello\\World",
Packit Service 7c31a4
    L"Hello\\\\World",
Packit Service 7c31a4
    L"Hello World\\",
Packit Service 7c31a4
    L"c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\""
Packit Service 7c31a4
  };
Packit Service 7c31a4
  const int count = sizeof(test_str) / sizeof(*test_str);
Packit Service 7c31a4
  WCHAR** test_output;
Packit Service 7c31a4
  WCHAR* command_line;
Packit Service 7c31a4
  WCHAR** cracked;
Packit Service 7c31a4
  size_t total_size = 0;
Packit Service 7c31a4
  int i;
Packit Service 7c31a4
  int num_args;
Packit Service 7c31a4
  int result;
Packit Service 7c31a4
Packit Service 7c31a4
  char* verbatim[] = {
Packit Service 7c31a4
    "cmd.exe",
Packit Service 7c31a4
    "/c",
Packit Service 7c31a4
    "c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"",
Packit Service 7c31a4
    NULL
Packit Service 7c31a4
  };
Packit Service 7c31a4
  WCHAR* verbatim_output;
Packit Service 7c31a4
  WCHAR* non_verbatim_output;
Packit Service 7c31a4
Packit Service 7c31a4
  test_output = calloc(count, sizeof(WCHAR*));
Packit Service 7c31a4
  ASSERT(test_output != NULL);
Packit Service 7c31a4
  for (i = 0; i < count; ++i) {
Packit Service 7c31a4
    test_output[i] = calloc(2 * (wcslen(test_str[i]) + 2), sizeof(WCHAR));
Packit Service 7c31a4
    quote_cmd_arg(test_str[i], test_output[i]);
Packit Service 7c31a4
    wprintf(L"input : %s\n", test_str[i]);
Packit Service 7c31a4
    wprintf(L"output: %s\n", test_output[i]);
Packit Service 7c31a4
    total_size += wcslen(test_output[i]) + 1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  command_line = calloc(total_size + 1, sizeof(WCHAR));
Packit Service 7c31a4
  ASSERT(command_line != NULL);
Packit Service 7c31a4
  for (i = 0; i < count; ++i) {
Packit Service 7c31a4
    wcscat(command_line, test_output[i]);
Packit Service 7c31a4
    wcscat(command_line, L" ");
Packit Service 7c31a4
  }
Packit Service 7c31a4
  command_line[total_size - 1] = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
  wprintf(L"command_line: %s\n", command_line);
Packit Service 7c31a4
Packit Service 7c31a4
  cracked = CommandLineToArgvW(command_line, &num_args);
Packit Service 7c31a4
  for (i = 0; i < num_args; ++i) {
Packit Service 7c31a4
    wprintf(L"%d: %s\t%s\n", i, test_str[i], cracked[i]);
Packit Service 7c31a4
    ASSERT(wcscmp(test_str[i], cracked[i]) == 0);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  LocalFree(cracked);
Packit Service 7c31a4
  for (i = 0; i < count; ++i) {
Packit Service 7c31a4
    free(test_output[i]);
Packit Service 7c31a4
  }
Packit Service 7c31a4
  free(test_output);
Packit Service 7c31a4
Packit Service 7c31a4
  result = make_program_args(verbatim, 1, &verbatim_output);
Packit Service 7c31a4
  ASSERT(result == 0);
Packit Service 7c31a4
  result = make_program_args(verbatim, 0, &non_verbatim_output);
Packit Service 7c31a4
  ASSERT(result == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  wprintf(L"    verbatim_output: %s\n", verbatim_output);
Packit Service 7c31a4
  wprintf(L"non_verbatim_output: %s\n", non_verbatim_output);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(wcscmp(verbatim_output,
Packit Service 7c31a4
                L"cmd.exe /c c:\\path\\to\\node.exe --eval "
Packit Service 7c31a4
                L"\"require('c:\\\\path\\\\to\\\\test.js')\"") == 0);
Packit Service 7c31a4
  ASSERT(wcscmp(non_verbatim_output,
Packit Service 7c31a4
                L"cmd.exe /c \"c:\\path\\to\\node.exe --eval "
Packit Service 7c31a4
                L"\\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  free(verbatim_output);
Packit Service 7c31a4
  free(non_verbatim_output);
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int make_program_env(char** env_block, WCHAR** dst_ptr);
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(environment_creation) {
Packit Service 7c31a4
  size_t i;
Packit Service 7c31a4
  char* environment[] = {
Packit Service 7c31a4
    "FOO=BAR",
Packit Service 7c31a4
    "SYSTEM=ROOT", /* substring of a supplied var name */
Packit Service 7c31a4
    "SYSTEMROOTED=OMG", /* supplied var name is a substring */
Packit Service 7c31a4
    "TEMP=C:\\Temp",
Packit Service 7c31a4
    "INVALID",
Packit Service 7c31a4
    "BAZ=QUX",
Packit Service 7c31a4
    "B_Z=QUX",
Packit Service 7c31a4
    "B\xe2\x82\xacZ=QUX",
Packit Service 7c31a4
    "B\xf0\x90\x80\x82Z=QUX",
Packit Service 7c31a4
    "B\xef\xbd\xa1Z=QUX",
Packit Service 7c31a4
    "B\xf0\xa3\x91\x96Z=QUX",
Packit Service 7c31a4
    "BAZ", /* repeat, invalid variable */
Packit Service 7c31a4
    NULL
Packit Service 7c31a4
  };
Packit Service 7c31a4
  WCHAR* wenvironment[] = {
Packit Service 7c31a4
    L"BAZ=QUX",
Packit Service 7c31a4
    L"B_Z=QUX",
Packit Service 7c31a4
    L"B\x20acZ=QUX",
Packit Service 7c31a4
    L"B\xd800\xdc02Z=QUX",
Packit Service 7c31a4
    L"B\xd84d\xdc56Z=QUX",
Packit Service 7c31a4
    L"B\xff61Z=QUX",
Packit Service 7c31a4
    L"FOO=BAR",
Packit Service 7c31a4
    L"SYSTEM=ROOT", /* substring of a supplied var name */
Packit Service 7c31a4
    L"SYSTEMROOTED=OMG", /* supplied var name is a substring */
Packit Service 7c31a4
    L"TEMP=C:\\Temp",
Packit Service 7c31a4
  };
Packit Service 7c31a4
  WCHAR* from_env[] = {
Packit Service 7c31a4
    /* list should be kept in sync with list
Packit Service 7c31a4
     * in process.c, minus variables in wenvironment */
Packit Service 7c31a4
    L"HOMEDRIVE",
Packit Service 7c31a4
    L"HOMEPATH",
Packit Service 7c31a4
    L"LOGONSERVER",
Packit Service 7c31a4
    L"PATH",
Packit Service 7c31a4
    L"USERDOMAIN",
Packit Service 7c31a4
    L"USERNAME",
Packit Service 7c31a4
    L"USERPROFILE",
Packit Service 7c31a4
    L"SYSTEMDRIVE",
Packit Service 7c31a4
    L"SYSTEMROOT",
Packit Service 7c31a4
    L"WINDIR",
Packit Service 7c31a4
    /* test for behavior in the absence of a
Packit Service 7c31a4
     * required-environment variable: */
Packit Service 7c31a4
    L"ZTHIS_ENV_VARIABLE_DOES_NOT_EXIST",
Packit Service 7c31a4
  };
Packit Service 7c31a4
  int found_in_loc_env[ARRAY_SIZE(wenvironment)] = {0};
Packit Service 7c31a4
  int found_in_usr_env[ARRAY_SIZE(from_env)] = {0};
Packit Service 7c31a4
  WCHAR *expected[ARRAY_SIZE(from_env)];
Packit Service 7c31a4
  int result;
Packit Service 7c31a4
  WCHAR* str;
Packit Service 7c31a4
  WCHAR* prev;
Packit Service 7c31a4
  WCHAR* env;
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < ARRAY_SIZE(from_env); i++) {
Packit Service 7c31a4
      /* copy expected additions to environment locally */
Packit Service 7c31a4
      size_t len = GetEnvironmentVariableW(from_env[i], NULL, 0);
Packit Service 7c31a4
      if (len == 0) {
Packit Service 7c31a4
        found_in_usr_env[i] = 1;
Packit Service 7c31a4
        str = malloc(1 * sizeof(WCHAR));
Packit Service 7c31a4
        *str = 0;
Packit Service 7c31a4
        expected[i] = str;
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        size_t name_len = wcslen(from_env[i]);
Packit Service 7c31a4
        str = malloc((name_len+1+len) * sizeof(WCHAR));
Packit Service 7c31a4
        wmemcpy(str, from_env[i], name_len);
Packit Service 7c31a4
        expected[i] = str;
Packit Service 7c31a4
        str += name_len;
Packit Service 7c31a4
        *str++ = L'=';
Packit Service 7c31a4
        GetEnvironmentVariableW(from_env[i], str, len);
Packit Service 7c31a4
     }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  result = make_program_env(environment, &env;;
Packit Service 7c31a4
  ASSERT(result == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  for (str = env, prev = NULL; *str; prev = str, str += wcslen(str) + 1) {
Packit Service 7c31a4
    int found = 0;
Packit Service 7c31a4
#if 0
Packit Service 7c31a4
    _cputws(str);
Packit Service 7c31a4
    putchar('\n');
Packit Service 7c31a4
#endif
Packit Service 7c31a4
    for (i = 0; i < ARRAY_SIZE(wenvironment) && !found; i++) {
Packit Service 7c31a4
      if (!wcscmp(str, wenvironment[i])) {
Packit Service 7c31a4
        ASSERT(!found_in_loc_env[i]);
Packit Service 7c31a4
        found_in_loc_env[i] = 1;
Packit Service 7c31a4
        found = 1;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
    for (i = 0; i < ARRAY_SIZE(expected) && !found; i++) {
Packit Service 7c31a4
      if (!wcscmp(str, expected[i])) {
Packit Service 7c31a4
        ASSERT(!found_in_usr_env[i]);
Packit Service 7c31a4
        found_in_usr_env[i] = 1;
Packit Service 7c31a4
        found = 1;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
    if (prev) { /* verify sort order -- requires Vista */
Packit Service 7c31a4
#if _WIN32_WINNT >= 0x0600 && \
Packit Service 7c31a4
    (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR))
Packit Service 7c31a4
      ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1);
Packit Service 7c31a4
#endif
Packit Service 7c31a4
    }
Packit Service 7c31a4
    ASSERT(found); /* verify that we expected this variable */
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* verify that we found all expected variables */
Packit Service 7c31a4
  for (i = 0; i < ARRAY_SIZE(wenvironment); i++) {
Packit Service 7c31a4
    ASSERT(found_in_loc_env[i]);
Packit Service 7c31a4
  }
Packit Service 7c31a4
  for (i = 0; i < ARRAY_SIZE(expected); i++) {
Packit Service 7c31a4
    ASSERT(found_in_usr_env[i]);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
/* Regression test for issue #909 */
Packit Service 7c31a4
TEST_IMPL(spawn_with_an_odd_path) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  char newpath[2048];
Packit Service 7c31a4
  char *path = getenv("PATH");
Packit Service 7c31a4
  ASSERT(path != NULL);
Packit Service 7c31a4
  snprintf(newpath, 2048, ";.;%s", path);
Packit Service 7c31a4
  SetEnvironmentVariable("PATH", newpath);
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("", exit_cb);
Packit Service 7c31a4
  options.file = options.args[0] = "program-that-had-better-not-exist";
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == UV_ENOENT || r == UV_EACCES);
Packit Service 7c31a4
  ASSERT(0 == uv_is_active((uv_handle_t*) &process));
Packit Service 7c31a4
  uv_close((uv_handle_t*) &process, NULL);
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
TEST_IMPL(spawn_setuid_setgid) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  struct passwd* pw;
Packit Service 7c31a4
  char uidstr[10];
Packit Service 7c31a4
  char gidstr[10];
Packit Service 7c31a4
Packit Service 7c31a4
  /* if not root, then this will fail. */
Packit Service 7c31a4
  uv_uid_t uid = getuid();
Packit Service 7c31a4
  if (uid != 0) {
Packit Service 7c31a4
    RETURN_SKIP("It should be run as root user");
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper_setuid_setgid", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  /* become the "nobody" user. */
Packit Service 7c31a4
  pw = getpwnam("nobody");
Packit Service 7c31a4
  ASSERT(pw != NULL);
Packit Service 7c31a4
  options.uid = pw->pw_uid;
Packit Service 7c31a4
  options.gid = pw->pw_gid;
Packit Service 7c31a4
  snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid);
Packit Service 7c31a4
  snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid);
Packit Service 7c31a4
  options.args[2] = uidstr;
Packit Service 7c31a4
  options.args[3] = gidstr;
Packit Service 7c31a4
  options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  if (r == UV_EACCES)
Packit Service 7c31a4
    RETURN_SKIP("user 'nobody' cannot access the test runner");
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
TEST_IMPL(spawn_setuid_fails) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  /* if root, become nobody. */
Packit Service 7c31a4
  /* On IBMi PASE, there is no nobody user. */
Packit Service 7c31a4
#ifndef __PASE__
Packit Service 7c31a4
  uv_uid_t uid = getuid();
Packit Service 7c31a4
  if (uid == 0) {
Packit Service 7c31a4
    struct passwd* pw;
Packit Service 7c31a4
    pw = getpwnam("nobody");
Packit Service 7c31a4
    ASSERT(pw != NULL);
Packit Service 7c31a4
    ASSERT(0 == setgid(pw->pw_gid));
Packit Service 7c31a4
    ASSERT(0 == setuid(pw->pw_uid));
Packit Service 7c31a4
  }
Packit Service 7c31a4
#endif  /* !__PASE__ */
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper1", fail_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  options.flags |= UV_PROCESS_SETUID;
Packit Service 7c31a4
  /* On IBMi PASE, there is no root user. User may grant 
Packit Service 7c31a4
   * root-like privileges, including setting uid to 0.
Packit Service 7c31a4
   */
Packit Service 7c31a4
#if defined(__PASE__)
Packit Service 7c31a4
  options.uid = -1;
Packit Service 7c31a4
#else
Packit Service 7c31a4
  options.uid = 0;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  /* These flags should be ignored on Unices. */
Packit Service 7c31a4
  options.flags |= UV_PROCESS_WINDOWS_HIDE;
Packit Service 7c31a4
  options.flags |= UV_PROCESS_WINDOWS_HIDE_CONSOLE;
Packit Service 7c31a4
  options.flags |= UV_PROCESS_WINDOWS_HIDE_GUI;
Packit Service 7c31a4
  options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
#if defined(__CYGWIN__)
Packit Service 7c31a4
  ASSERT(r == UV_EINVAL);
Packit Service 7c31a4
#else
Packit Service 7c31a4
  ASSERT(r == UV_EPERM);
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(close_cb_called == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_setgid_fails) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  /* if root, become nobody. */
Packit Service 7c31a4
  /* On IBMi PASE, there is no nobody user. */
Packit Service 7c31a4
#ifndef __PASE__
Packit Service 7c31a4
  uv_uid_t uid = getuid();
Packit Service 7c31a4
  if (uid == 0) {
Packit Service 7c31a4
    struct passwd* pw;
Packit Service 7c31a4
    pw = getpwnam("nobody");
Packit Service 7c31a4
    ASSERT(pw != NULL);
Packit Service 7c31a4
    ASSERT(0 == setgid(pw->pw_gid));
Packit Service 7c31a4
    ASSERT(0 == setuid(pw->pw_uid));
Packit Service 7c31a4
  }
Packit Service 7c31a4
#endif  /* !__PASE__ */
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper1", fail_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  options.flags |= UV_PROCESS_SETGID;
Packit Service 7c31a4
  /* On IBMi PASE, there is no root user. User may grant 
Packit Service 7c31a4
   * root-like privileges, including setting gid to 0.
Packit Service 7c31a4
   */
Packit Service 7c31a4
#if defined(__MVS__) || defined(__PASE__)
Packit Service 7c31a4
  options.gid = -1;
Packit Service 7c31a4
#else
Packit Service 7c31a4
  options.gid = 0;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
#if defined(__CYGWIN__) || defined(__MVS__)
Packit Service 7c31a4
  ASSERT(r == UV_EINVAL);
Packit Service 7c31a4
#else
Packit Service 7c31a4
  ASSERT(r == UV_EPERM);
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(close_cb_called == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifdef _WIN32
Packit Service 7c31a4
Packit Service 7c31a4
static void exit_cb_unexpected(uv_process_t* process,
Packit Service 7c31a4
                               int64_t exit_status,
Packit Service 7c31a4
                               int term_signal) {
Packit Service 7c31a4
  ASSERT(0 && "should not have been called");
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_setuid_fails) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper1", exit_cb_unexpected);
Packit Service 7c31a4
Packit Service 7c31a4
  options.flags |= UV_PROCESS_SETUID;
Packit Service 7c31a4
  options.uid = (uv_uid_t) -42424242;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == UV_ENOTSUP);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(close_cb_called == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_setgid_fails) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper1", exit_cb_unexpected);
Packit Service 7c31a4
Packit Service 7c31a4
  options.flags |= UV_PROCESS_SETGID;
Packit Service 7c31a4
  options.gid = (uv_gid_t) -42424242;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == UV_ENOTSUP);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(close_cb_called == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_auto_unref) {
Packit Service 7c31a4
  init_process_options("spawn_helper1", NULL);
Packit Service 7c31a4
  ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
  ASSERT(0 == uv_is_closing((uv_handle_t*) &process));
Packit Service 7c31a4
  uv_close((uv_handle_t*) &process, NULL);
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
  ASSERT(1 == uv_is_closing((uv_handle_t*) &process));
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
TEST_IMPL(spawn_fs_open) {
Packit Service 7c31a4
  int fd;
Packit Service 7c31a4
  uv_fs_t fs_req;
Packit Service 7c31a4
  uv_pipe_t in;
Packit Service 7c31a4
  uv_write_t write_req;
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
  uv_stdio_container_t stdio[1];
Packit Service 7c31a4
Packit Service 7c31a4
  fd = uv_fs_open(NULL, &fs_req, "/dev/null", O_RDWR, 0, NULL);
Packit Service 7c31a4
  ASSERT(fd >= 0);
Packit Service 7c31a4
  uv_fs_req_cleanup(&fs_req);
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper8", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_pipe_init(uv_default_loop(), &in, 0));
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
Packit Service 7c31a4
  options.stdio[0].data.stream = (uv_stream_t*) ∈
Packit Service 7c31a4
  options.stdio_count = 1;
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
Packit Service 7c31a4
Packit Service 7c31a4
  buf = uv_buf_init((char*) &fd, sizeof(fd));
Packit Service 7c31a4
  ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
Packit Service 7c31a4
  ASSERT(0 == uv_fs_close(NULL, &fs_req, fd, NULL));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 2);  /* One for `in`, one for process */
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif  /* !_WIN32 */
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
TEST_IMPL(closed_fd_events) {
Packit Service 7c31a4
  uv_stdio_container_t stdio[3];
Packit Service 7c31a4
  uv_pipe_t pipe_handle;
Packit Service 7c31a4
  int fd[2];
Packit Service 7c31a4
Packit Service 7c31a4
  /* create a pipe and share it with a child process */
Packit Service 7c31a4
  ASSERT(0 == pipe(fd));
Packit Service 7c31a4
Packit Service 7c31a4
  /* spawn_helper4 blocks indefinitely. */
Packit Service 7c31a4
  init_process_options("spawn_helper4", exit_cb);
Packit Service 7c31a4
  options.stdio_count = 3;
Packit Service 7c31a4
  options.stdio = stdio;
Packit Service 7c31a4
  options.stdio[0].flags = UV_INHERIT_FD;
Packit Service 7c31a4
  options.stdio[0].data.fd = fd[0];
Packit Service 7c31a4
  options.stdio[1].flags = UV_IGNORE;
Packit Service 7c31a4
  options.stdio[2].flags = UV_IGNORE;
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
Packit Service 7c31a4
  uv_unref((uv_handle_t*) &process);
Packit Service 7c31a4
Packit Service 7c31a4
  /* read from the pipe with uv */
Packit Service 7c31a4
  ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0));
Packit Service 7c31a4
  ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0]));
Packit Service 7c31a4
  fd[0] = -1;
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_read_start((uv_stream_t*) &pipe_handle, on_alloc, on_read_once));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(1 == write(fd[1], "", 1));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
Packit Service 7c31a4
Packit Service 7c31a4
  /* should have received just one byte */
Packit Service 7c31a4
  ASSERT(output_used == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  /* close the pipe and see if we still get events */
Packit Service 7c31a4
  uv_close((uv_handle_t*) &pipe_handle, close_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(1 == write(fd[1], "", 1));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(0 == uv_timer_init(uv_default_loop(), &timer));
Packit Service 7c31a4
  ASSERT(0 == uv_timer_start(&timer, timer_counter_cb, 10, 0));
Packit Service 7c31a4
Packit Service 7c31a4
  /* see if any spurious events interrupt the timer */
Packit Service 7c31a4
  if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE))
Packit Service 7c31a4
    /* have to run again to really trigger the timer */
Packit Service 7c31a4
    ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(timer_counter == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  /* cleanup */
Packit Service 7c31a4
  ASSERT(0 == uv_process_kill(&process, /* SIGTERM */ 15));
Packit Service 7c31a4
  ASSERT(0 == close(fd[1]));
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif  /* !_WIN32 */
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_reads_child_path) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  int len;
Packit Service 7c31a4
  char file[64];
Packit Service 7c31a4
  char path[1024];
Packit Service 7c31a4
  char* env[3];
Packit Service 7c31a4
Packit Service 7c31a4
  /* Need to carry over the dynamic linker path when the test runner is
Packit Service 7c31a4
   * linked against libuv.so, see https://github.com/libuv/libuv/issues/85.
Packit Service 7c31a4
   */
Packit Service 7c31a4
#if defined(__APPLE__)
Packit Service 7c31a4
  static const char dyld_path_var[] = "DYLD_LIBRARY_PATH";
Packit Service 7c31a4
#elif defined(__MVS__) || defined(__PASE__)
Packit Service 7c31a4
  static const char dyld_path_var[] = "LIBPATH";
Packit Service 7c31a4
#else
Packit Service 7c31a4
  static const char dyld_path_var[] = "LD_LIBRARY_PATH";
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  /* Set up the process, but make sure that the file to run is relative and
Packit Service 7c31a4
   * requires a lookup into PATH. */
Packit Service 7c31a4
  init_process_options("spawn_helper1", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Set up the PATH env variable */
Packit Service 7c31a4
  for (len = strlen(exepath);
Packit Service 7c31a4
       exepath[len - 1] != '/' && exepath[len - 1] != '\\';
Packit Service 7c31a4
       len--);
Packit Service 7c31a4
  strcpy(file, exepath + len);
Packit Service 7c31a4
  exepath[len] = 0;
Packit Service 7c31a4
  strcpy(path, "PATH=");
Packit Service 7c31a4
  strcpy(path + 5, exepath);
Packit Service 7c31a4
#if defined(__CYGWIN__) || defined(__MSYS__)
Packit Service 7c31a4
  /* Carry over the dynamic linker path in case the test runner
Packit Service 7c31a4
     is linked against cyguv-1.dll or msys-uv-1.dll, see above.  */
Packit Service 7c31a4
  {
Packit Service 7c31a4
    char* syspath = getenv("PATH");
Packit Service 7c31a4
    if (syspath != NULL) {
Packit Service 7c31a4
      strcat(path, ":");
Packit Service 7c31a4
      strcat(path, syspath);
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  env[0] = path;
Packit Service 7c31a4
  env[1] = getenv(dyld_path_var);
Packit Service 7c31a4
  env[2] = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  if (env[1] != NULL) {
Packit Service 7c31a4
    static char buf[1024 + sizeof(dyld_path_var)];
Packit Service 7c31a4
    snprintf(buf, sizeof(buf), "%s=%s", dyld_path_var, env[1]);
Packit Service 7c31a4
    env[1] = buf;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  options.file = file;
Packit Service 7c31a4
  options.args[0] = file;
Packit Service 7c31a4
  options.env = env;
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 1);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
static int mpipe(int *fds) {
Packit Service 7c31a4
  if (pipe(fds) == -1)
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  if (fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
Packit Service 7c31a4
      fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
Packit Service 7c31a4
    close(fds[0]);
Packit Service 7c31a4
    close(fds[1]);
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#else
Packit Service 7c31a4
static int mpipe(int *fds) {
Packit Service 7c31a4
  SECURITY_ATTRIBUTES attr;
Packit Service 7c31a4
  HANDLE readh, writeh;
Packit Service 7c31a4
  attr.nLength = sizeof(attr);
Packit Service 7c31a4
  attr.lpSecurityDescriptor = NULL;
Packit Service 7c31a4
  attr.bInheritHandle = FALSE;
Packit Service 7c31a4
  if (!CreatePipe(&readh, &writeh, &attr, 0))
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  fds[0] = _open_osfhandle((intptr_t)readh, 0);
Packit Service 7c31a4
  fds[1] = _open_osfhandle((intptr_t)writeh, 0);
Packit Service 7c31a4
  if (fds[0] == -1 || fds[1] == -1) {
Packit Service 7c31a4
    CloseHandle(readh);
Packit Service 7c31a4
    CloseHandle(writeh);
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif /* !_WIN32 */
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_inherit_streams) {
Packit Service 7c31a4
  uv_process_t child_req;
Packit Service 7c31a4
  uv_stdio_container_t child_stdio[2];
Packit Service 7c31a4
  int fds_stdin[2];
Packit Service 7c31a4
  int fds_stdout[2];
Packit Service 7c31a4
  uv_pipe_t pipe_stdin_child;
Packit Service 7c31a4
  uv_pipe_t pipe_stdout_child;
Packit Service 7c31a4
  uv_pipe_t pipe_stdin_parent;
Packit Service 7c31a4
  uv_pipe_t pipe_stdout_parent;
Packit Service 7c31a4
  unsigned char ubuf[OUTPUT_SIZE - 1];
Packit Service 7c31a4
  uv_buf_t buf;
Packit Service 7c31a4
  unsigned int i;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  int bidir;
Packit Service 7c31a4
  uv_write_t write_req;
Packit Service 7c31a4
  uv_loop_t* loop;
Packit Service 7c31a4
Packit Service 7c31a4
  init_process_options("spawn_helper9", exit_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  loop = uv_default_loop();
Packit Service 7c31a4
  ASSERT(uv_pipe_init(loop, &pipe_stdin_child, 0) == 0);
Packit Service 7c31a4
  ASSERT(uv_pipe_init(loop, &pipe_stdout_child, 0) == 0);
Packit Service 7c31a4
  ASSERT(uv_pipe_init(loop, &pipe_stdin_parent, 0) == 0);
Packit Service 7c31a4
  ASSERT(uv_pipe_init(loop, &pipe_stdout_parent, 0) == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(mpipe(fds_stdin) != -1);
Packit Service 7c31a4
  ASSERT(mpipe(fds_stdout) != -1);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(uv_pipe_open(&pipe_stdin_child, fds_stdin[0]) == 0);
Packit Service 7c31a4
  ASSERT(uv_pipe_open(&pipe_stdout_child, fds_stdout[1]) == 0);
Packit Service 7c31a4
  ASSERT(uv_pipe_open(&pipe_stdin_parent, fds_stdin[1]) == 0);
Packit Service 7c31a4
  ASSERT(uv_pipe_open(&pipe_stdout_parent, fds_stdout[0]) == 0);
Packit Service 7c31a4
  ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_child));
Packit Service 7c31a4
  ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_child));
Packit Service 7c31a4
  ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdin_parent));
Packit Service 7c31a4
  ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_parent));
Packit Service 7c31a4
  /* Some systems (SVR4) open a bidirectional pipe, most don't. */
Packit Service 7c31a4
  bidir = uv_is_writable((uv_stream_t*) &pipe_stdin_child);
Packit Service 7c31a4
  ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_child) == bidir);
Packit Service 7c31a4
  ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_parent) == bidir);
Packit Service 7c31a4
  ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_parent) == bidir);
Packit Service 7c31a4
Packit Service 7c31a4
  child_stdio[0].flags = UV_INHERIT_STREAM;
Packit Service e2ebee
  child_stdio[0].data.stream = (uv_stream_t *) &pipe_stdin_child;
Packit Service 7c31a4
Packit Service 7c31a4
  child_stdio[1].flags = UV_INHERIT_STREAM;
Packit Service e2ebee
  child_stdio[1].data.stream = (uv_stream_t *) &pipe_stdout_child;
Packit Service 7c31a4
Packit Service 7c31a4
  options.stdio = child_stdio;
Packit Service 7c31a4
  options.stdio_count = 2;
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(uv_spawn(loop, &child_req, &options) == 0);
Packit Service 7c31a4
Packit Service e2ebee
  uv_close((uv_handle_t*) &pipe_stdin_child, NULL);
Packit Service e2ebee
  uv_close((uv_handle_t*) &pipe_stdout_child, NULL);
Packit Service 7c31a4
Packit Service e2ebee
  buf = uv_buf_init((char*) ubuf, sizeof ubuf);
Packit Service 7c31a4
  for (i = 0; i < sizeof ubuf; ++i)
Packit Service 7c31a4
    ubuf[i] = i & 255u;
Packit Service 7c31a4
  memset(output, 0, sizeof ubuf);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_write(&write_req,
Packit Service e2ebee
               (uv_stream_t*) &pipe_stdin_parent,
Packit Service 7c31a4
               &buf,
Packit Service 7c31a4
               1,
Packit Service 7c31a4
               write_cb);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service e2ebee
  r = uv_read_start((uv_stream_t*) &pipe_stdout_parent, on_alloc, on_read);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  r = uv_run(loop, UV_RUN_DEFAULT);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(exit_cb_called == 1);
Packit Service 7c31a4
  ASSERT(close_cb_called == 3);
Packit Service 7c31a4
Packit Service 7c31a4
  r = memcmp(ubuf, output, sizeof ubuf);
Packit Service 7c31a4
  ASSERT(r == 0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
TEST_IMPL(spawn_quoted_path) {
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
  RETURN_SKIP("Test for Windows");
Packit Service 7c31a4
#else
Packit Service 7c31a4
  char* quoted_path_env[2];
Packit Service 7c31a4
  args[0] = "not_existing";
Packit Service 7c31a4
  args[1] = NULL;
Packit Service 7c31a4
  options.file = args[0];
Packit Service 7c31a4
  options.args = args;
Packit Service 7c31a4
  options.exit_cb = exit_cb;
Packit Service 7c31a4
  options.flags = 0;
Packit Service 7c31a4
  /* We test if search_path works correctly with semicolons in quoted path. We
Packit Service 7c31a4
   * will use an invalid drive, so we are sure no executable is spawned. */
Packit Service 7c31a4
  quoted_path_env[0] = "PATH=\"xyz:\\test;\";xyz:\\other";
Packit Service 7c31a4
  quoted_path_env[1] = NULL;
Packit Service 7c31a4
  options.env = quoted_path_env;
Packit Service 7c31a4
Packit Service 7c31a4
  /* We test if libuv will not segfault. */
Packit Service 7c31a4
  uv_spawn(uv_default_loop(), &process, &options);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
/* Helper for child process of spawn_inherit_streams */
Packit Service 7c31a4
#ifndef _WIN32
Packit Service 7c31a4
void spawn_stdin_stdout(void) {
Packit Service 7c31a4
  char buf[1024];
Packit Service 7c31a4
  char* pbuf;
Packit Service 7c31a4
  for (;;) {
Packit Service 7c31a4
    ssize_t r, w, c;
Packit Service 7c31a4
    do {
Packit Service 7c31a4
      r = read(0, buf, sizeof buf);
Packit Service 7c31a4
    } while (r == -1 && errno == EINTR);
Packit Service 7c31a4
    if (r == 0) {
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    ASSERT(r > 0);
Packit Service 7c31a4
    c = r;
Packit Service 7c31a4
    pbuf = buf;
Packit Service 7c31a4
    while (c) {
Packit Service 7c31a4
      do {
Packit Service 7c31a4
        w = write(1, pbuf, (size_t)c);
Packit Service 7c31a4
      } while (w == -1 && errno == EINTR);
Packit Service 7c31a4
      ASSERT(w >= 0);
Packit Service 7c31a4
      pbuf = pbuf + w;
Packit Service 7c31a4
      c = c - w;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
#else
Packit Service 7c31a4
void spawn_stdin_stdout(void) {
Packit Service 7c31a4
  char buf[1024];
Packit Service 7c31a4
  char* pbuf;
Packit Service 7c31a4
  HANDLE h_stdin = GetStdHandle(STD_INPUT_HANDLE);
Packit Service 7c31a4
  HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
Packit Service 7c31a4
  ASSERT(h_stdin != INVALID_HANDLE_VALUE);
Packit Service 7c31a4
  ASSERT(h_stdout != INVALID_HANDLE_VALUE);
Packit Service 7c31a4
  for (;;) {
Packit Service 7c31a4
    DWORD n_read;
Packit Service 7c31a4
    DWORD n_written;
Packit Service 7c31a4
    DWORD to_write;
Packit Service 7c31a4
    if (!ReadFile(h_stdin, buf, sizeof buf, &n_read, NULL)) {
Packit Service 7c31a4
      ASSERT(GetLastError() == ERROR_BROKEN_PIPE);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    to_write = n_read;
Packit Service 7c31a4
    pbuf = buf;
Packit Service 7c31a4
    while (to_write) {
Packit Service 7c31a4
      ASSERT(WriteFile(h_stdout, pbuf, to_write, &n_written, NULL));
Packit Service 7c31a4
      to_write -= n_written;
Packit Service 7c31a4
      pbuf += n_written;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif /* !_WIN32 */