10 #include <framework/utilities/IOIntercept.h>
11 #include <framework/utilities/testhelpers/Fixtures.h>
12 #include <gtest/gtest.h>
18 using logconvert_params_t = std::tuple<LogConfig::ELogLevel, std::string, std::string, bool, bool>;
24 using IOInterceptDeathTest = IOInterceptTest;
27 class IOInterceptParamTest:
public IOInterceptTest,
public ::testing::WithParamInterface<logconvert_params_t> {};
30 TEST_P(IOInterceptParamTest, ConvertToLogMessage)
34 std::string raw_message, formatted_message;
35 bool useStdout, generateMessage;
36 std::tie(level, raw_message, formatted_message, useStdout, generateMessage) = GetParam();
40 (useStdout ? std::cout : std::cerr) << raw_message;
43 expectMessage(level, generateMessage ? 1 : 0,
true);
44 if (!generateMessage)
return;
46 expectMessageContent(level,
"Output from capture_name:\ncapture_name: " + formatted_message);
52 logconvert_params_t logconvert_params[] = {
79 INSTANTIATE_TEST_SUITE_P(Params, IOInterceptParamTest, ::testing::ValuesIn(logconvert_params));
82 TEST_F(IOInterceptTest, LogMessagesNoFinish)
86 logmessages.setIndent(
"-");
88 std::cout <<
"this is my message";
93 expectMessageContent(
LogConfig::c_Info,
"Output from capture_name:\n-this is my message");
97 TEST_F(IOInterceptTest, InterceptGuard)
100 logmessages.setIndent(
"-");
103 std::cout <<
"this is my message";
105 std::cout <<
"this will not be captured" << std::endl;
109 std::cerr <<
"this is my error";
111 std::cerr <<
"this will not be captured" << std::endl;
112 ASSERT_EQ(m_messages.size(), 2);
114 expectMessageContent(
LogConfig::c_Error,
"Output from capture_name:\n-this is my error");
115 m_messages.pop_back();
116 expectMessageContent(
LogConfig::c_Info,
"Output from capture_name:\n-this is my message");
120 TEST_F(IOInterceptTest, ConvertCheckIndent)
124 std::cout <<
"this is\na multi line message";
127 expectMessageContent(
LogConfig::c_Info,
"Output from indent:\nindent: this is\nindent: a multi line message");
131 TEST_F(IOInterceptTest, ConvertSetIndent)
135 std::cout <<
"this is\na multi line message";
136 capture.setIndent(
"--->");
139 expectMessageContent(
LogConfig::c_Info,
"Output from indent:\n--->this is\n--->a multi line message");
143 TEST_F(IOInterceptTest, ConvertEmptyIndent)
147 capture.setIndent(
"");
148 std::cout <<
"this is\na multi line message";
151 expectMessageContent(
LogConfig::c_Info,
"Output from indent:\nthis is\na multi line message");
155 TEST_F(IOInterceptTest, CaptureStdOut)
158 ASSERT_FALSE(capture.
finish());
159 ASSERT_TRUE(capture.
start());
160 ASSERT_TRUE(capture.
start());
161 std::cout <<
"this is a test";
162 ASSERT_TRUE(capture.
finish());
163 ASSERT_EQ(capture.
getStdOut(),
"this is a test");
164 ASSERT_FALSE(capture.
finish());
165 ASSERT_EQ(capture.
getStdOut(),
"this is a test");
168 ASSERT_TRUE(capture.
start());
169 write(fileno(stdout),
"this is a test", 14);
170 ASSERT_TRUE(capture.
finish());
171 ASSERT_EQ(capture.
getStdOut(),
"this is a test");
175 TEST_F(IOInterceptTest, CaptureStdErr)
178 ASSERT_FALSE(capture.
finish());
179 ASSERT_TRUE(capture.
start());
180 ASSERT_TRUE(capture.
start());
181 std::cerr <<
"this is a test";
182 ASSERT_TRUE(capture.
finish());
183 ASSERT_EQ(capture.
getStdErr(),
"this is a test");
184 ASSERT_FALSE(capture.
finish());
185 ASSERT_EQ(capture.
getStdErr(),
"this is a test");
188 ASSERT_TRUE(capture.
start());
189 write(fileno(stderr),
"this is a test", 14);
190 ASSERT_TRUE(capture.
finish());
191 ASSERT_EQ(capture.
getStdErr(),
"this is a test");
195 TEST_F(IOInterceptTest, CaptureLargeOutput)
198 ASSERT_TRUE(capture.
start());
201 for (
int i = 0; i < 100000; ++i) {
202 std::cout << (char)(i % 255) << std::flush;
203 if (std::cout.good()) written = i + 1;
204 out.push_back(i % 255);
206 ASSERT_TRUE(capture.
finish());
207 const std::string& captured = capture.
getStdOut();
211 ASSERT_TRUE(captured.size() <= out.size());
212 ASSERT_EQ(captured.size(), written);
213 if (captured.size() < out.size()) {
214 std::cout <<
"Output truncated after " << captured.size() <<
" bytes" << std::endl;
216 ASSERT_EQ(captured, out.substr(0, captured.size()));
218 ASSERT_TRUE(capture.
start());
219 std::cout <<
"once more";
220 ASSERT_TRUE(capture.
finish());
221 ASSERT_EQ(capture.
getStdOut(),
"once more");
224 ASSERT_TRUE(capture.
start());
226 ASSERT_TRUE(capture.
finish());
227 ASSERT_EQ(capture.
getStdOut(),
"once more");
233 void generateStdErr()
236 std::cerr <<
"start->";
238 std::cerr <<
"this should not show up" << std::endl << std::flush;
239 write(fileno(stderr),
"nor this\n", 9);
241 std::cerr <<
"<-end";
246 TEST_F(IOInterceptDeathTest, DiscardStdOut)
249 ASSERT_FALSE(discard.
finish());
250 ASSERT_TRUE(discard.
start());
251 ASSERT_TRUE(discard.
start());
252 ASSERT_TRUE(discard.
finish());
253 ASSERT_FALSE(discard.
finish());
256 EXPECT_EXIT(generateStdErr(), ::testing::ExitedWithCode(0),
"^start-><-end$");
264 std::cerr <<
"start->";
266 std::cerr <<
"now we abort" << std::endl;
271 TEST_F(IOInterceptDeathTest, HandleAbort)
273 EXPECT_EXIT(generateAbort(), ::testing::ExitedWithCode(1),
"^start->now we abort\nabort\\(\\) called, exiting\n$");
Class to intercept stdout and stderr and either capture, discard or keep them unmodified depending on...
const std::string & getStdErr() const
Return the captured stderr output if any.
const std::string & getStdOut() const
Return the captured stdout output if any.
bool start()
Start intercepting the output.
bool finish()
Finish intercepting the output.
Simple RAII guard for output interceptor.
Capture stdout and stderr and convert into log messages.
ELogLevel
Definition of the supported log levels.
@ c_Error
Error: for things that went wrong and have to be fixed.
@ c_Info
Info: for informational messages, e.g.
@ c_Warning
Warning: for potential problems that the user should pay attention to.
@ c_Result
Result: for informational summary messages, e.g.
Test fixture to be able to check the contents and types of emitted log messages in detail.
TEST_F(GlobalLabelTest, LargeNumberOfTimeDependentParameters)
Test large number of time-dep params for registration and retrieval.
InterceptorScopeGuard< T > start_intercept(T &interceptor)
Convenience wrapper to simplify use of InterceptorScopeGuard<T>.
Abstract base class for different kinds of events.