]> git.localhorst.tv Git - blank.git/blobdiff - tst/integration/TestInstance.cpp
test missing option arguments
[blank.git] / tst / integration / TestInstance.cpp
index f9bc7273cc563ec9831bbdafb35a5b91bca0d5f7..df87bfd4146e6affd4894201182edd5ddf13b99f 100644 (file)
@@ -10,13 +10,20 @@ namespace test {
 
 namespace {
 
-Process::Arguments combine_args(const TempDir &dir, const Process::Arguments &in, bool cmd) {
+Process::Arguments combine_args(
+       const TempDir &dir,
+       const Process::Arguments &in,
+       bool cmd,
+       bool temp_save
+) {
        Process::Arguments out;
        out.reserve(in.size() + (cmd ? 5 : 3));
        out.emplace_back("blank");
        out.insert(out.end(), in.begin(), in.end());
-       out.emplace_back("--save-path");
-       out.emplace_back(dir.Path());
+       if (temp_save) {
+               out.emplace_back("--save-path");
+               out.emplace_back(dir.Path());
+       }
        if (cmd) {
                out.emplace_back("--cmd-port");
                out.emplace_back("12354");
@@ -26,23 +33,24 @@ Process::Arguments combine_args(const TempDir &dir, const Process::Arguments &in
 
 }
 
-TestInstance::TestInstance(const Process::Arguments &args, bool cmd)
+TestInstance::TestInstance(const Process::Arguments &args, bool cmd, bool temp_save)
 : dir()
-, proc(
-       "./blank" BLANK_SUFFIX,
-       combine_args(dir, args, cmd),
-       { })
+, proc("./blank" BLANK_SUFFIX, combine_args(dir, args, cmd, temp_save))
 , conn()
 , out_buf()
 , err_buf()
-, cmd_buf() {
+, cmd_buf()
+, name("blank" BLANK_SUFFIX) {
        if (cmd) {
                // wait for command service startup
-               // TODO: timeouts for reading from process
                WaitOutputLine("listening on TCP port 12354");
                // connect to command service
                conn = tcp::Socket("localhost", 12354);
        }
+       for (const auto &arg : args) {
+               name += ' ';
+               name += arg;
+       }
 }
 
 TestInstance::~TestInstance() {
@@ -51,10 +59,14 @@ TestInstance::~TestInstance() {
 
 
 void TestInstance::WriteInput(const string &data) {
+       AssertRunning();
        const char *i = data.c_str();
        const char *end = i + data.length();
        while (i != end) {
                size_t len = proc.WriteIn(i, end - i);
+               if (len == 0) {
+                       throw runtime_error("failed write to stdin of " + name);
+               }
                i += len;
        }
 }
@@ -62,57 +74,174 @@ void TestInstance::WriteInput(const string &data) {
 void TestInstance::ReadOutputLine(string &line) {
        while (!out_buf.Extract(line)) {
                // buffer exhausted, fetch more data
-               out_buf.Update(proc.ReadOut(out_buf.WriteHead(), out_buf.Remain()));
+               int len = proc.ReadOut(out_buf.WriteHead(), out_buf.Remain(), 10000);
+               if (len == 0) {
+                       throw runtime_error("failed read from stdout of " + name);
+               }
+               out_buf.Update(len);
        }
 }
 
 void TestInstance::AssertOutputLine(const string &expected) {
        string line;
-       ReadOutputLine(line);
+       if (past_out.empty()) {
+               ReadOutputLine(line);
+       } else {
+               line = past_out.front();
+               past_out.pop_front();
+       }
        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected line in stdout",
+               "unexpected line in stdout of " + name,
                expected, line);
 }
 
 void TestInstance::WaitOutputLine(const string &expected) {
+       for (list<string>::iterator i(past_out.begin()); i != past_out.end(); ++i) {
+               if (*i == expected) {
+                       past_out.erase(i);
+                       return;
+               }
+       }
        string line;
        while (true) {
                ReadOutputLine(line);
                if (line == expected) {
                        return;
+               } else {
+                       past_out.push_back(line);
                }
        }
 }
 
+void TestInstance::ExhaustOutput(string &output) {
+       output.clear();
+       for (const auto &line : past_out) {
+               output += line;
+               output += '\n';
+       }
+       past_out.clear();
+       string line;
+       while (true) {
+               if (out_buf.Extract(line)) {
+                       output += line;
+                       output += '\n';
+               } else {
+                       // buffer exhausted, fetch more data
+                       int len = proc.ReadOut(out_buf.WriteHead(), out_buf.Remain(), 10000);
+                       if (len == 0) {
+                               // eof
+                               return;
+                       }
+                       out_buf.Update(len);
+               }
+       }
+}
+
+void TestInstance::AssertNoOutput() {
+       string output;
+       ExhaustOutput(output);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected output of test instance " + name,
+               string(""), output);
+}
+
+
 void TestInstance::ReadErrorLine(string &line) {
        while (!err_buf.Extract(line)) {
                // buffer exhausted, fetch more data
-               err_buf.Update(proc.ReadErr(err_buf.WriteHead(), err_buf.Remain()));
+               int len = proc.ReadErr(err_buf.WriteHead(), err_buf.Remain(), 10000);
+               if (len == 0) {
+                       throw runtime_error("failed read from stderr of " + name);
+               }
+               err_buf.Update(len);
        }
 }
 
 void TestInstance::AssertErrorLine(const string &expected) {
        string line;
-       ReadErrorLine(line);
+       if (past_err.empty()) {
+               ReadErrorLine(line);
+       } else {
+               line = past_err.front();
+               past_err.pop_front();
+       }
        CPPUNIT_ASSERT_EQUAL_MESSAGE(
                "unexpected line in stderr",
                expected, line);
 }
 
 void TestInstance::WaitErrorLine(const string &expected) {
+       for (list<string>::iterator i(past_err.begin()); i != past_err.end(); ++i) {
+               if (*i == expected) {
+                       past_err.erase(i);
+                       return;
+               }
+       }
        string line;
        while (true) {
                ReadErrorLine(line);
                if (line == expected) {
                        return;
+               } else {
+                       past_err.push_back(line);
                }
        }
 }
 
+void TestInstance::ExhaustError(string &error) {
+       error.clear();
+       for (const auto &line : past_err) {
+               error += line;
+               error += '\n';
+       }
+       past_err.clear();
+       string line;
+       while (true) {
+               if (err_buf.Extract(line)) {
+                       error += line;
+                       error += '\n';
+               } else {
+                       // buffer exhausted, fetch more data
+                       int len = proc.ReadErr(err_buf.WriteHead(), err_buf.Remain(), 10000);
+                       if (len == 0) {
+                               // eof
+                               return;
+                       }
+                       err_buf.Update(len);
+               }
+       }
+}
+
+void TestInstance::AssertNoError() {
+       string error;
+       ExhaustError(error);
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "unexpected error output of test instance " + name,
+               string(""), error);
+}
+
+
+void TestInstance::Terminate() {
+       if (!proc.Terminated()) {
+               proc.Terminate();
+       }
+}
+
+void TestInstance::AssertRunning() {
+       CPPUNIT_ASSERT_MESSAGE(
+               "test instance " + name + " terminated unexpectedly",
+               !proc.Terminated());
+}
+
+void TestInstance::AssertTerminated() {
+       CPPUNIT_ASSERT_MESSAGE(
+               "test instance " + name + " did not terminate as expected",
+               proc.Terminated());
+}
 
 void TestInstance::AssertExitStatus(int expected) {
        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-               "unexpected line in stderr",
+               "unexpected exit status from child program " + name,
                expected, proc.Join());
 }