, conn()
, out_buf()
, err_buf()
-, cmd_buf() {
+, cmd_buf()
+, name("blank" BLANK_SUFFIX) {
if (cmd) {
// wait for command service startup
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() {
while (i != end) {
size_t len = proc.WriteIn(i, end - i);
if (len == 0) {
- throw runtime_error("failed write to child process' stdin");
+ throw runtime_error("failed write to stdin of " + name);
}
i += len;
}
// buffer exhausted, fetch more data
int len = proc.ReadOut(out_buf.WriteHead(), out_buf.Remain(), 5000);
if (len == 0) {
- throw runtime_error("failed read from child process' stdout");
+ 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) {
- while (!out_buf.Extract(output)) {
- // buffer exhausted, fetch more data
- int len = proc.ReadOut(out_buf.WriteHead(), out_buf.Remain(), 5000);
- if (len == 0) {
- return;
+ 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(), 5000);
+ if (len == 0) {
+ // eof
+ return;
+ }
+ out_buf.Update(len);
}
- out_buf.Update(len);
}
}
string output;
ExhaustOutput(output);
CPPUNIT_ASSERT_EQUAL_MESSAGE(
- "test instance produced unexpected output",
+ "unexpected output of test instance " + name,
string(""), output);
}
// buffer exhausted, fetch more data
int len = proc.ReadErr(err_buf.WriteHead(), err_buf.Remain(), 5000);
if (len == 0) {
- throw runtime_error("failed read from child process' stderr");
+ 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) {
- while (!err_buf.Extract(error)) {
- // buffer exhausted, fetch more data
- int len = proc.ReadErr(err_buf.WriteHead(), err_buf.Remain(), 5000);
- if (len == 0) {
- return;
+ 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(), 5000);
+ if (len == 0) {
+ // eof
+ return;
+ }
+ err_buf.Update(len);
}
- err_buf.Update(len);
}
}
string error;
ExhaustError(error);
CPPUNIT_ASSERT_EQUAL_MESSAGE(
- "test instance produced unexpected error output",
+ "unexpected error output of test instance " + name,
string(""), error);
}
void TestInstance::Terminate() {
- proc.Terminate();
+ if (!proc.Terminated()) {
+ proc.Terminate();
+ }
}
void TestInstance::AssertRunning() {
CPPUNIT_ASSERT_MESSAGE(
- "test instance terminated unexpectedly",
+ "test instance " + name + " terminated unexpectedly",
!proc.Terminated());
}
void TestInstance::AssertTerminated() {
CPPUNIT_ASSERT_MESSAGE(
- "test instance did not terminate as expected",
+ "test instance " + name + " did not terminate as expected",
proc.Terminated());
}
void TestInstance::AssertExitStatus(int expected) {
CPPUNIT_ASSERT_EQUAL_MESSAGE(
- "unexpected exit status from child program",
+ "unexpected exit status from child program " + name,
expected, proc.Join());
}