aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSteven Murdoch <Steven.Murdoch@cl.cam.ac.uk>2011-07-24 23:31:59 +0100
committerunknown <Steven Murdoch@.(none)>2011-07-25 04:08:08 +0100
commit5bf9890b3b18ad98f5ac601992bc08533ce9e209 (patch)
tree8d297ef6fa27c96b7d669fc661b4b1a6ffdea0a2 /src
parent99baa7e45cc65f0683912c59934679df554fa306 (diff)
downloadtor-5bf9890b3b18ad98f5ac601992bc08533ce9e209.tar.gz
tor-5bf9890b3b18ad98f5ac601992bc08533ce9e209.zip
Test case for reading the partial output of a background process
Diffstat (limited to 'src')
-rw-r--r--src/common/util.c14
-rw-r--r--src/common/util.h1
-rw-r--r--src/test/test-child.c4
-rw-r--r--src/test/test_util.c78
4 files changed, 90 insertions, 7 deletions
diff --git a/src/common/util.c b/src/common/util.c
index e63047b91e..5a5f3b5fbd 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -3292,8 +3292,8 @@ tor_get_exit_code(const process_handle_t process_handle)
#ifdef MS_WINDOWS
/* Windows equivalent of read_all */
-static ssize_t
-read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
+ssize_t
+tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
{
size_t numread = 0;
BOOL retval;
@@ -3310,7 +3310,7 @@ read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
"Failed to peek from handle: %s",
format_win32_error(GetLastError()));
return -1;
- } else if (0 == byte_count)
+ } else if (0 == byte_count) {
/* Nothing available: process exited or it is busy */
/* Exit if we don't know whether the process is running */
@@ -3352,8 +3352,8 @@ tor_read_all_from_process_stdout(const process_handle_t process_handle,
char *buf, size_t count)
{
#ifdef MS_WINDOWS
- return read_all_handle(process_handle.stdout_pipe, buf, count,
- process_handle.pid.hProcess);
+ return tor_read_all_handle(process_handle.stdout_pipe, buf, count,
+ process_handle.pid.hProcess);
#else
return read_all(process_handle.stdout_pipe, buf, count, 0);
#endif
@@ -3364,8 +3364,8 @@ tor_read_all_from_process_stderr(const process_handle_t process_handle,
char *buf, size_t count)
{
#ifdef MS_WINDOWS
- return read_all_handle(process_handle.stderr_pipe, buf, count,
- process_handle.pid.hProcess);
+ return tor_read_all_handle(process_handle.stderr_pipe, buf, count,
+ process_handle.pid.hProcess);
#else
return read_all(process_handle.stderr_pipe, buf, count, 0);
#endif
diff --git a/src/common/util.h b/src/common/util.h
index c111ba72f2..2efe557857 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -364,6 +364,7 @@ typedef struct process_handle_s {
process_handle_t tor_spawn_background(const char *const filename,
const char **argv);
int tor_get_exit_code(const process_handle_t pid);
+ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess);
ssize_t tor_read_all_from_process_stdout(const process_handle_t process_handle,
char *buf, size_t count);
ssize_t tor_read_all_from_process_stderr(const process_handle_t process_handle,
diff --git a/src/test/test-child.c b/src/test/test-child.c
index cf49c5d31e..1b9c5e3d57 100644
--- a/src/test/test-child.c
+++ b/src/test/test-child.c
@@ -19,6 +19,10 @@ main(int argc, char **argv)
for (i = 1; i < argc; i++)
fprintf(stdout, "%s\n", argv[i]);
fprintf(stdout, "SLEEPING\n");
+ /* We need to flush stdout so that test_util_spawn_background_partial_read()
+ succeed. Otherwise ReadFile() will get the entire output in one */
+ // XXX: Can we make stdio flush on newline?
+ fflush(stdout);
#ifdef MS_WINDOWS
Sleep(1000);
#else
diff --git a/src/test/test_util.c b/src/test/test_util.c
index c6dc98dc6b..071fd04e87 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1468,6 +1468,83 @@ test_util_spawn_background_fail(void *ptr)
run_util_spawn_background(argv, expected_out, expected_err, 255, expected_status);
}
+/** Helper function for testing tor_spawn_background */
+static void
+test_util_spawn_background_partial_read(void *ptr)
+{
+#ifdef MS_WINDOWS
+ // TODO: Under MSYS, BUILDDIR in orconfig.h needs to be tweaked
+ const char *argv[] = {BUILDDIR "/src/test/test-child.exe", "--test", NULL};
+ const char *expected_out[] = { "OUT\r\n--test\r\nSLEEPING\r\n",
+ "DONE\r\n",
+ NULL };
+ const char *expected_err = "ERR\r\n";
+ int expected_out_ctr;
+#else
+ const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
+ const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n";
+ const char *expected_err = "ERR\r\n";
+#endif
+ const int expected_exit = 0;
+ const int expected_status = 0;
+
+ int retval;
+ ssize_t pos;
+ process_handle_t process_handle;
+ char stdout_buf[100], stderr_buf[100];
+
+ /* Start the program */
+ process_handle = tor_spawn_background(argv[0], argv);
+ tt_int_op(process_handle.status, ==, expected_status);
+
+ /* Check stdout */
+#ifdef MS_WINDOWS
+ for (expected_out_ctr =0; expected_out[expected_out_ctr] != NULL;) {
+ pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
+ sizeof(stdout_buf) - 1, NULL);
+ log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
+
+ /* We would have blocked, keep on trying */
+ if (0 == pos)
+ continue;
+
+ tt_assert(pos >= 0);
+ stdout_buf[pos] = '\0';
+ tt_str_op(stdout_buf, ==, expected_out[expected_out_ctr]);
+ tt_int_op(pos, ==, strlen(expected_out[expected_out_ctr]));
+ expected_out_ctr++;
+ }
+ /* The process should have exited without writing more */
+ pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
+ sizeof(stdout_buf) - 1,
+ process_handle.pid.hProcess);
+ tt_int_op(pos, ==, 0);
+#else
+ pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
+ sizeof(stdout_buf) - 1);
+ tt_assert(pos >= 0);
+ stdout_buf[pos] = '\0';
+ tt_str_op(stdout_buf, ==, expected_out);
+ tt_int_op(pos, ==, strlen(expected_out));
+#endif
+
+ /* Check it terminated correctly */
+ retval = tor_get_exit_code(process_handle);
+ tt_int_op(retval, ==, expected_exit);
+ // TODO: Make test-child exit with something other than 0
+
+ /* Check stderr */
+ pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
+ sizeof(stderr_buf) - 1);
+ tt_assert(pos >= 0);
+ stderr_buf[pos] = '\0';
+ tt_str_op(stderr_buf, ==, expected_err);
+ tt_int_op(pos, ==, strlen(expected_err));
+
+ done:
+ ;
+}
+
static void
test_util_di_ops(void)
{
@@ -1555,6 +1632,7 @@ struct testcase_t util_tests[] = {
#endif
UTIL_TEST(spawn_background_ok, 0),
UTIL_TEST(spawn_background_fail, 0),
+ UTIL_TEST(spawn_background_partial_read, 0),
END_OF_TESTCASES
};