aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests/slaveproc
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /vespalib/src/tests/slaveproc
Publish
Diffstat (limited to 'vespalib/src/tests/slaveproc')
-rw-r--r--vespalib/src/tests/slaveproc/.gitignore4
-rw-r--r--vespalib/src/tests/slaveproc/CMakeLists.txt8
-rw-r--r--vespalib/src/tests/slaveproc/DESC2
-rw-r--r--vespalib/src/tests/slaveproc/FILES1
-rw-r--r--vespalib/src/tests/slaveproc/slaveproc_test.cpp186
5 files changed, 201 insertions, 0 deletions
diff --git a/vespalib/src/tests/slaveproc/.gitignore b/vespalib/src/tests/slaveproc/.gitignore
new file mode 100644
index 00000000000..8851e99df13
--- /dev/null
+++ b/vespalib/src/tests/slaveproc/.gitignore
@@ -0,0 +1,4 @@
+.depend
+Makefile
+slaveproc_test
+vespalib_slaveproc_test_app
diff --git a/vespalib/src/tests/slaveproc/CMakeLists.txt b/vespalib/src/tests/slaveproc/CMakeLists.txt
new file mode 100644
index 00000000000..7a834bc0962
--- /dev/null
+++ b/vespalib/src/tests/slaveproc/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(vespalib_slaveproc_test_app
+ SOURCES
+ slaveproc_test.cpp
+ DEPENDS
+ vespalib
+)
+vespa_add_test(NAME vespalib_slaveproc_test_app COMMAND vespalib_slaveproc_test_app)
diff --git a/vespalib/src/tests/slaveproc/DESC b/vespalib/src/tests/slaveproc/DESC
new file mode 100644
index 00000000000..42f92a9e42e
--- /dev/null
+++ b/vespalib/src/tests/slaveproc/DESC
@@ -0,0 +1,2 @@
+Test the SlaveProc class, a wrapper for FastOS_Process that simplifies
+writing to stdin and reading from stdout of sub-processes.
diff --git a/vespalib/src/tests/slaveproc/FILES b/vespalib/src/tests/slaveproc/FILES
new file mode 100644
index 00000000000..f2c61607b2d
--- /dev/null
+++ b/vespalib/src/tests/slaveproc/FILES
@@ -0,0 +1 @@
+slaveproc.cpp
diff --git a/vespalib/src/tests/slaveproc/slaveproc_test.cpp b/vespalib/src/tests/slaveproc/slaveproc_test.cpp
new file mode 100644
index 00000000000..95f8021f7d2
--- /dev/null
+++ b/vespalib/src/tests/slaveproc/slaveproc_test.cpp
@@ -0,0 +1,186 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/util/slaveproc.h>
+
+using vespalib::SlaveProc;
+
+TEST("simple run, ignore output") {
+ EXPECT_TRUE(SlaveProc::run("echo foo"));
+}
+
+TEST("simple run, ignore output, failure") {
+ EXPECT_TRUE(!SlaveProc::run("false"));
+}
+
+TEST("simple run, ignore output, timeout") {
+ EXPECT_TRUE(!SlaveProc::run("sleep 60", 10));
+}
+
+TEST("simple run") {
+ std::string out;
+ EXPECT_TRUE(SlaveProc::run("echo -n foo", out));
+ EXPECT_EQUAL(out, "foo");
+}
+
+TEST("simple run, strip single-line trailing newline") {
+ std::string out;
+ EXPECT_TRUE(SlaveProc::run("echo foo", out));
+ EXPECT_EQUAL(out, "foo");
+}
+
+TEST("simple run, don't strip multi-line output") {
+ std::string out;
+ EXPECT_TRUE(SlaveProc::run("echo -e \"foo\\n\"", out));
+ EXPECT_EQUAL(out, "foo\n\n");
+}
+
+TEST("simple run with input") {
+ std::string in = "bar";
+ std::string out;
+ EXPECT_TRUE(SlaveProc::run(in, "cat", out));
+ EXPECT_EQUAL(out, "bar");
+}
+
+TEST("simple run with input, strip single-line trailing newline") {
+ std::string in = "bar\n";
+ std::string out;
+ EXPECT_TRUE(SlaveProc::run(in, "cat", out));
+ EXPECT_EQUAL(out, "bar");
+}
+
+TEST("simple run with input, don't strip multi-line output") {
+ std::string in = "bar\n\n";
+ std::string out;
+ EXPECT_TRUE(SlaveProc::run(in, "cat", out));
+ EXPECT_EQUAL("bar\n\n", out);
+}
+
+TEST_MT("simple run, partial output due to timeout", 2) {
+ std::string out;
+ std::vector<size_t> timeouts({150, 300, 3000, 6000, 60000});
+ for (size_t timeout: timeouts) {
+ fprintf(stderr, "... verifying partial output with%s input (timeout = %zu)\n",
+ (thread_id == 0) ? "out" : "", timeout);
+ if (thread_id == 0) {
+ out.clear();
+ EXPECT_TRUE(!SlaveProc::run("echo foo; sleep 600; echo bar", out, timeout));
+ } else {
+ out.clear();
+ std::string in = "ignored\n";
+ EXPECT_TRUE(!SlaveProc::run(in, "echo foo; sleep 600; echo bar", out, timeout));
+ }
+ if (out == "foo") {
+ break;
+ }
+ }
+ EXPECT_EQUAL(out, "foo");
+}
+
+TEST("proc failure") {
+ SlaveProc proc("false");
+ // read with length 0 will wait for output
+ EXPECT_TRUE(proc.read(NULL, 0) == 0);
+ EXPECT_TRUE(proc.wait(60000));
+ EXPECT_TRUE(!proc.running());
+ EXPECT_TRUE(proc.failed());
+}
+
+TEST("basic read/write") {
+ int x;
+ int read;
+ char buf[64];
+ SlaveProc proc("cat");
+
+ EXPECT_TRUE(proc.running());
+ EXPECT_TRUE(!proc.failed());
+ EXPECT_TRUE(proc.write("foo", 3));
+ for (x = 0, read = 0; x < 10 && read < 3; ++x) {
+ read += proc.read(buf + read, sizeof(buf) - read);
+ }
+ EXPECT_TRUE(read == 3 && memcmp(buf, "foo", 3) == 0);
+ EXPECT_TRUE(proc.write("bar!", 4));
+ for (x = 0, read = 0; x < 10 && read < 4; ++x) {
+ read += proc.read(buf + read, sizeof(buf) - read);
+ }
+ EXPECT_TRUE(read == 4 && memcmp(buf, "bar!", 4) == 0);
+ EXPECT_TRUE(!proc.eof()); // not eof yet
+ EXPECT_TRUE(proc.close()); // close stdin
+ EXPECT_TRUE(!proc.eof()); // eof not detected yet
+ EXPECT_TRUE(proc.read(buf, sizeof(buf)) == 0);
+ EXPECT_TRUE(proc.eof());
+ EXPECT_TRUE(proc.read(buf, sizeof(buf)) == 0);
+ EXPECT_TRUE(proc.wait(60000));
+ EXPECT_TRUE(!proc.running());
+ EXPECT_TRUE(!proc.failed());
+}
+
+TEST("continuos run, readLine") {
+ std::string str;
+ SlaveProc proc("cat");
+
+ EXPECT_TRUE(proc.running());
+ EXPECT_TRUE(!proc.failed());
+ EXPECT_TRUE(proc.write("foo\n", 4));
+ EXPECT_TRUE(proc.readLine(str));
+ EXPECT_EQUAL(str, "foo");
+ EXPECT_TRUE(proc.write("bar!\n", 5));
+ EXPECT_TRUE(proc.readLine(str));
+ EXPECT_EQUAL(str, "bar!");
+ EXPECT_TRUE(!proc.eof()); // not eof yet
+ EXPECT_TRUE(proc.close()); // close stdin
+ EXPECT_TRUE(!proc.eof()); // eof not detected yet
+ EXPECT_TRUE(!proc.readLine(str));
+ EXPECT_EQUAL(str, "");
+ EXPECT_TRUE(proc.eof());
+ EXPECT_TRUE(!proc.readLine(str));
+ EXPECT_EQUAL(str, "");
+ EXPECT_TRUE(proc.wait(60000));
+ EXPECT_TRUE(!proc.running());
+ EXPECT_TRUE(!proc.failed());
+}
+
+TEST("readLine, eof flushes last line") {
+ std::string str;
+ SlaveProc proc("cat");
+
+ EXPECT_TRUE(proc.running());
+ EXPECT_TRUE(!proc.failed());
+ EXPECT_TRUE(proc.write("foo\n", 4));
+ EXPECT_TRUE(proc.readLine(str));
+ EXPECT_EQUAL(str, "foo");
+ EXPECT_TRUE(proc.write("bar!", 4));
+ EXPECT_TRUE(!proc.eof()); // not eof yet
+ EXPECT_TRUE(proc.close()); // close stdin
+ EXPECT_TRUE(!proc.eof()); // eof not detected yet
+ EXPECT_TRUE(proc.readLine(str));
+ EXPECT_EQUAL(str, "bar!");
+ EXPECT_TRUE(proc.eof());
+ EXPECT_TRUE(!proc.readLine(str));
+ EXPECT_EQUAL(str, "");
+ EXPECT_TRUE(proc.wait(60000));
+ EXPECT_TRUE(!proc.running());
+ EXPECT_TRUE(!proc.failed());
+}
+
+TEST("long continuos run, readLine") {
+ std::string in;
+ std::string out;
+ SlaveProc proc("cat");
+
+ EXPECT_TRUE(proc.running());
+ EXPECT_TRUE(!proc.failed());
+ for (uint32_t i = 0; i < 10000; ++i) {
+ char num[32];
+ sprintf(num, "%d", i);
+ in.assign("long continous run, line ");
+ in.append(num).append("\n");
+ EXPECT_TRUE(proc.write(in.data(), in.length()));
+ in.erase(in.size() - 1, 1);
+ EXPECT_TRUE(proc.readLine(out));
+ EXPECT_EQUAL(in, out);
+ }
+ EXPECT_TRUE(proc.running());
+ EXPECT_TRUE(!proc.failed());
+}
+
+TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); }