3

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.

4
  • 1
    It might be a bit OS specific.. Commented Jun 7, 2012 at 22:34
  • This question is answered here. Commented Jun 7, 2012 at 22:38
  • 1
    Consider this. Definitly not a dupe, but related. Might help. Commented Jun 7, 2012 at 22:40
  • After redirecting, did you call flush() after the code under test had run its full course? Commented Jun 7, 2012 at 23:19

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

11 Comments

Is .rdbuf(0) intended to be .rdbuf(o)?
This has caused it to start to hang again somehow. Is there something you know of that cause it not to hang?
It works for me in a small test. Have you run it in a debugger to see where it hangs?
I think the reason it may be hanging is that it is running within another set of macros that I cannot change that also use stdout. Is that possible?
Apparently my standard-fu is failing me here -- where does the standard say that cout.rdbuf(0) is equivalent to what you have?
|
1

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); } }; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.