I'm writing a unit test and therefore, cannot change the code within the file that I'm testing. The code that I'm testing has messages in cout that I am trying to redirect into a file to check to make sure that the program is outputting the right messages. Does anyone have a way to redirect stdout in another program that won't cause a lag? I have tried freopen() and that causes my program to hang for some reason.
2 Answers
You could create a filebuf then replace cout's streambuf with it:
{ std::filebuf f; f.open("output.txt", std::ios::out); std::streambuf* o = std::cout.rdbuf(&f); std::cout << "hello" << std::endl; // endl will flush the stream std::cout.rdbuf(o); } You need to restore cout's original streambuf again (or set it to a null pointer) or it will probably crash when the global streams are flushed and destroyed, because the filebuf will already have gone out of scope.
11 Comments
.rdbuf(0) intended to be .rdbuf(o)?cout.rdbuf(0) is equivalent to what you have?You can use 'open()' and 'dup2()'. You can use the helpers provided below. An example of how to use them:
void code_to_test () { std::cout << "Here we go" << std::endl; std::cerr << "Danger danger" << std::endl; } run_test(code_to_test); The run_test helper invokes redirection, and runs the test code.
template <typename TEST> void run_test (TEST t, bool append = false) { flush_output(); Redirect o(1, "/tmp/test_stdout", append); Redirect e(2, "/tmp/test_stderr", append); t(); flush_output(); } The flush_output helper flushes the streams.
void flush_output () { fflush(stdout); fflush(stderr); std::cout.flush(); std::cerr.flush(); } The Redirect class effects the redirection in the constructor. It restores the original descriptors back in the destructor.
class Redirect { int m_what; int m_old_what; public: Redirect (int what, std::string where, bool append = false) : m_what(what), m_old_what(dup(what)) { int flags = O_CREAT|O_WRONLY; if (append) flags |= O_APPEND; int f = open(where.c_str(), flags, 0660); dup2(f, m_what); close(f); } ~Redirect () { dup2(m_old_what, m_what); close(m_old_what); } };
flush()after the code under test had run its full course?