30

I'm working on getting some legacy code under unit tests and sometimes the only way to sense an existing program behavior is from the console output.

I see lots of examples online for how to redirect stdout to another file in C++, but is there a way I can redirect it to an in-memory stream so my tests don't have to rely on the disk?

I'd like to get anything that the legacy code sends to stdout into a std::string so I can easily .find on the output.

Edit

The legacy code is so bad that it users a mixture of cout << .. and printf. Here is what I have so far:

void TestSuite::setUp(void)
{
    oldStdoutBuf = std::cout.rdbuf();
    std::cout.rdbuf(consoleOutput.rdbuf());
}
void TestSuite::tearDown(void)
{
    std::cout.rdbuf(oldStdoutBuf);
}

The problem is that this does not capture output using printf. I would like something that gets both. Any ideas?

thelsdj
  • 9,034
  • 10
  • 45
  • 58

4 Answers4

15

std::stringstream may be what you're looking for.

UPDATE
Alright, this is a bit of hack, but maybe you could do this to grab the printf output:

char huge_string_buf[MASSIVE_SIZE];
freopen("NUL", "a", stdout);
setbuf(stdout, huge_string_buffer);

Note you should use "/dev/null" for linux instead of "NUL". That will rapidly start to fill up huge_string_buffer. If you want to be able to continue redirecting output after the buffer is full you'll have to call fflush(), otherwise it will throw an error. See std::setbuf for more info.

Gabe
  • 2,526
  • 1
  • 23
  • 24
  • Accepted your answer as stringstream was good pointer and your UPDATE is about as far as we will probably get without writing some hugely massive convoluted mess, for now I think I'll just write to a file and hopefully I won't need the printf output for many tests. – thelsdj Jul 22 '09 at 00:36
  • 3
    Works well, but if i use multiple unit tests, some fail with an exception because the buffer is already freed and stdout is written into it. In case of only a temporarly redirection into the buffer use a `setbuf(stdout, NULL);` at the end of the usage. – Martze Nov 14 '14 at 11:01
  • See this answer to avoid the "NUL"-Hack on POSIX systems: http://stackoverflow.com/a/19499003/1557062 – sigy Nov 16 '16 at 15:07
3

You can use freopen(..., stdout) and then dump the file into memory or a std::string.

MSN
  • 53,214
  • 7
  • 75
  • 105
  • I would really like to skip having to use the filesystem. Something that only uses ram would be best. – thelsdj Jul 21 '09 at 22:35
2

This may be an alternative:

char bigOutBuf[8192];
char savBuf[8192];

fflush(stdout);
setvbuf(stdout,bigOutBuf,IOFBF,8192);//stdout uses your buffer

//after each operation
strncpy(savBuf,bigOutBuf,8192);//won't flush until full or fflush called

//...

//at long last finished
setbuf(stdout,NULL);//reset to unnamed buffer

This just intercepts the buffered output, so still goes to console or wherever.

Hope this helps.

sth
  • 222,467
  • 53
  • 283
  • 367
cvsdave
  • 1,576
  • 2
  • 12
  • 18
-4

Try sprintf, that's more efficient.

int i;
char str[] = "asdf";
char output[256];
sprintf(output, "asdfasdf %s %d\n", str, i);
streaver91
  • 864
  • 1
  • 8
  • 10