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$");
 
const std::string & getStdOut() const
Return the captured stdout output if any.
bool start()
Start intercepting the output.
bool finish()
Finish intercepting the output.
const std::string & getStdErr() const
Return the captured stderr output if any.
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.
InterceptOutput< DiscardStream, DiscardStream > DiscardStdOutStdErr
Discard both stdout and stderr.
InterceptOutput< CaptureStream, KeepStream > CaptureStdOut
Capture only stdout and don't modify stderr.
InterceptorScopeGuard< T > start_intercept(T &interceptor)
Convenience wrapper to simplify use of InterceptorScopeGuard<T>.
InterceptOutput< KeepStream, DiscardStream > DiscardStdErr
Discard only stderr and don't modify stdout.
InterceptOutput< KeepStream, CaptureStream > CaptureStdErr
Capture only stderr and don't modify stdout.
Abstract base class for different kinds of events.