]> git.localhorst.tv Git - blank.git/blob - tst/integration/TestInstance.cpp
timeouts reading from spawned processes
[blank.git] / tst / integration / TestInstance.cpp
1 #include "TestInstance.hpp"
2
3 #include <cppunit/extensions/HelperMacros.h>
4
5 using namespace std;
6
7
8 namespace blank {
9 namespace test {
10
11 namespace {
12
13 Process::Arguments combine_args(const TempDir &dir, const Process::Arguments &in, bool cmd) {
14         Process::Arguments out;
15         out.reserve(in.size() + (cmd ? 5 : 3));
16         out.emplace_back("blank");
17         out.insert(out.end(), in.begin(), in.end());
18         out.emplace_back("--save-path");
19         out.emplace_back(dir.Path());
20         if (cmd) {
21                 out.emplace_back("--cmd-port");
22                 out.emplace_back("12354");
23         }
24         return out;
25 }
26
27 }
28
29 TestInstance::TestInstance(const Process::Arguments &args, bool cmd)
30 : dir()
31 , proc("./blank" BLANK_SUFFIX, combine_args(dir, args, cmd))
32 , conn()
33 , out_buf()
34 , err_buf()
35 , cmd_buf() {
36         if (cmd) {
37                 // wait for command service startup
38                 WaitOutputLine("listening on TCP port 12354");
39                 // connect to command service
40                 conn = tcp::Socket("localhost", 12354);
41         }
42 }
43
44 TestInstance::~TestInstance() {
45         proc.Terminate();
46 }
47
48
49 void TestInstance::WriteInput(const string &data) {
50         AssertRunning();
51         const char *i = data.c_str();
52         const char *end = i + data.length();
53         while (i != end) {
54                 size_t len = proc.WriteIn(i, end - i);
55                 if (len == 0) {
56                         throw runtime_error("failed write to child process' stdin");
57                 }
58                 i += len;
59         }
60 }
61
62 void TestInstance::ReadOutputLine(string &line) {
63         while (!out_buf.Extract(line)) {
64                 // buffer exhausted, fetch more data
65                 int len = proc.ReadOut(out_buf.WriteHead(), out_buf.Remain(), 5000);
66                 if (len == 0) {
67                         throw runtime_error("failed read from child process' stdout");
68                 }
69                 out_buf.Update(len);
70         }
71 }
72
73 void TestInstance::AssertOutputLine(const string &expected) {
74         string line;
75         ReadOutputLine(line);
76         CPPUNIT_ASSERT_EQUAL_MESSAGE(
77                 "unexpected line in stdout",
78                 expected, line);
79 }
80
81 void TestInstance::WaitOutputLine(const string &expected) {
82         string line;
83         while (true) {
84                 ReadOutputLine(line);
85                 if (line == expected) {
86                         return;
87                 }
88         }
89 }
90
91 void TestInstance::ExhaustOutput(string &output) {
92         while (!out_buf.Extract(output)) {
93                 // buffer exhausted, fetch more data
94                 int len = proc.ReadOut(out_buf.WriteHead(), out_buf.Remain(), 5000);
95                 if (len == 0) {
96                         return;
97                 }
98                 out_buf.Update(len);
99         }
100 }
101
102 void TestInstance::AssertNoOutput() {
103         string output;
104         ExhaustOutput(output);
105         CPPUNIT_ASSERT_EQUAL_MESSAGE(
106                 "test instance produced unexpected output",
107                 string(""), output);
108 }
109
110
111 void TestInstance::ReadErrorLine(string &line) {
112         while (!err_buf.Extract(line)) {
113                 // buffer exhausted, fetch more data
114                 int len = proc.ReadErr(err_buf.WriteHead(), err_buf.Remain(), 5000);
115                 if (len == 0) {
116                         throw runtime_error("failed read from child process' stderr");
117                 }
118                 err_buf.Update(len);
119         }
120 }
121
122 void TestInstance::AssertErrorLine(const string &expected) {
123         string line;
124         ReadErrorLine(line);
125         CPPUNIT_ASSERT_EQUAL_MESSAGE(
126                 "unexpected line in stderr",
127                 expected, line);
128 }
129
130 void TestInstance::WaitErrorLine(const string &expected) {
131         string line;
132         while (true) {
133                 ReadErrorLine(line);
134                 if (line == expected) {
135                         return;
136                 }
137         }
138 }
139
140 void TestInstance::ExhaustError(string &error) {
141         while (!err_buf.Extract(error)) {
142                 // buffer exhausted, fetch more data
143                 int len = proc.ReadErr(err_buf.WriteHead(), err_buf.Remain(), 5000);
144                 if (len == 0) {
145                         return;
146                 }
147                 err_buf.Update(len);
148         }
149 }
150
151 void TestInstance::AssertNoError() {
152         string error;
153         ExhaustError(error);
154         CPPUNIT_ASSERT_EQUAL_MESSAGE(
155                 "test instance produced unexpected error output",
156                 string(""), error);
157 }
158
159
160 void TestInstance::Terminate() {
161         proc.Terminate();
162 }
163
164 void TestInstance::AssertRunning() {
165         CPPUNIT_ASSERT_MESSAGE(
166                 "test instance terminated unexpectedly",
167                 !proc.Terminated());
168 }
169
170 void TestInstance::AssertTerminated() {
171         CPPUNIT_ASSERT_MESSAGE(
172                 "test instance did not terminate as expected",
173                 proc.Terminated());
174 }
175
176 void TestInstance::AssertExitStatus(int expected) {
177         CPPUNIT_ASSERT_EQUAL_MESSAGE(
178                 "unexpected exit status from child program",
179                 expected, proc.Join());
180 }
181
182
183 void TestInstance::WaitCommandMessage(const string &line) {
184         WaitCommandLine(" > " + line);
185 }
186
187 void TestInstance::WaitCommandError(const string &line) {
188         WaitCommandLine(" ! " + line);
189 }
190
191 void TestInstance::WaitCommandBroadcast(const string &line) {
192         WaitCommandLine(" @ " + line);
193 }
194
195 void TestInstance::WaitCommandLine(const string &expected) {
196         string line;
197         while (true) {
198                 if (!cmd_buf.Extract(line)) {
199                         // buffer exhausted, fetch more data
200                         cmd_buf.Update(conn.Recv(cmd_buf.WriteHead(), cmd_buf.Remain()));
201                         continue;
202                 }
203                 if (line == expected) {
204                         return;
205                 }
206         }
207 }
208
209 }
210 }