Let's say I have a simple HelloWorld class with a hi() method with the following single line of code:
void HelloWorld::hi(){
printf("Hi!\n");
}
Now let's say I want to test that method with CppUnit.
void HelloWorldTests::testHi() {
HelloWorld hw;
hw.hi(); // <------ ????
// <------ ?????
CPPUNIT_ASSERT(/*????*/);
}
How would I catch the output of the hi() method so that I can compare it to a fixed value in CppUnit?
There is no standard way to capture the output to stdout within a program. You can redirect the output to stdout to a file using freopen(filename, "w", stdout) and then compare the content of the file. The main problem with this approach is that there is no standard approach to restore the original destination.
I'd recommend changing the code to use std::cout instead as this can be easily redirected to a suitable std::streambuf, e.g., an std::stringbuf, using the rdbuf() member. The original stream buffer can be kept and restored once the method writing to std::cout is done:
struct HelloWorld {
void hi() {
std::cout << "hi";
}
};
bool test_hi() {
std::ostringstream out;
std::streambuf* orig_buf(std::cout.rdbuf(out.rdbuf()));
HelloWorld hw;
hw.hi();
std::cout.rdbuf(orig_buf);
return out.str() == "hi";
}
Related
if I want to create a logging class, say
class logging_class {
public:
std::ofstream error;
std::ofstream event;
logging_class() {}
logging_class(string err, string evt) {
error.open(err);
event.open(evt);
}
~logging_class() {
error.close();
event.close();
}
};
so that later I can easily create program log:
logging_class logger("Log_Error.txt","Log_Event.txt");
logger.error << "something wrong";
logger.event << "something interesting";
Now, at the early stage of development, I want to redirect all the output to screen (i.e. std::cout). I don't want to change the usage of logger.error<<"something wrong"; to std::cout<<"something wrong";, because later I will need to change all instances of std::cout to either logger.error or logger.event (maybe thousands of them). Can I make some easy changes in the class logger to do this?
Update: Following Enlico's instruction, I can modify the logging_class as:
class logging_class {
public:
//std::ofstream error;
//std::ofstream event;
std::ostream& error;
std::ostream& event;
logging_class():error(std::cout),event(std::cout) {}
//logging_class(string err, string evt) {
// error.open(err);
// event.open(evt);
//}
//~logging_class() {
// error.close();
// event.close();
//}
};
and after creating object with default constructor:
logging_class logger;
I can now redirect all the logging to screen display.
Think of std::cout of what it actually is: an object. It is just that:
The global objects std::cout and std::wcout control output to […]
So when you say that you want to temporarily use std::cout in place of std::ofstream you're mixing apples (object std::cout) with oranges (class std::ofstream).
What you want to do, instead, is to use std::cout instead of an object of class std::ofstream.
But std::cout is not of class std::ofstream, so error can't hold it; it is of class std::ostream, which is a superclass of the former.
Therefore, as suggested in a comment, you can make error/event references to an object of that class, std::ofstreamstd::ostream&, and initialize them with std::cout or with std::ofstream{"filename.txt"} via an appropriate constructor of the logging_class.
If I want to write my own test.cpp that checks if another .cpp file is outputting the way I want it to output, is there anyway to do it without explicitly printing it?
In other words, is there anything such as
assert(output_of_file_being_tested, "this is the correct output");
where output_of_file_being_tested is something that's supposed to be "cout"ed.
The solution is not to hard-code the output stream. Pass a reference to std::ostream to your code somehow, and use std::stringstream to collect the output in test environment.
For example, this is the content of your "another .cpp" file:
void toBeTested(std::ostream& output) {
output << "this is the correct output";
}
So in your production/release code you may pass std::cout to the function:
void productionCode() {
toBeTested(std::cout);
}
while in the test environment you may collect the output to a sting stream and check it for correctness:
// test.cpp
#include <sstream>
#include <cassert>
void test() {
std::stringstream ss;
toBeTested(ss);
assert(ss.str() == "this is the correct output");
}
In addition to Sergey's great answer above, you may choose to have std::cout as a default parameter.
So, if you have a code:
// Only need console output
using std::cout;
...
void toBeTested()
{
cout << "This is the correct output.";
}
And it is used (or may be frequently used in the future) in many places:
int main()
{
...
toBeTested();
...
toBeTested();
...
// And so on...
return 0;
}
In order to avoid breaking a lot of code and maintaining a simple interface,
you can convert the above function to:
using std::cout;
...
void toBeTested(std::ostream& cout = std::cout)
{
cout << "This is the correct output.";
}
And your main does not need to be touched.
Note that cout of the function now overshadows cout of the global scope. Therefore, this cout can be any output stream, and does not interfere with the global cout.
And now you can test this as above!
#include <sstream>
#include <cassert>
...
void testMyFunctionDisplay()
{
// Arrange
std::ostringstream output_buffer;
// Act
toBeTested(output_buffer);
// Assert
assert(output_buffer.str() == "This is the correct output.");
}
However. it is not necessary to make every function in this way.
It is useful if we want to redirect that function's output to other output streams:
Stringstreams: If you want to use the output somewhere, perhaps for testing the module, or for other purposes in the program.
Files: If you want to maintain the output even after the program termination.
I need redirect the copy of std::cout to the file. I.e. I need see the output in console, and in file. If I use this:
// redirecting cout's output
#include <iostream>
#include <fstream>
using namespace std;
int main () {
streambuf *psbuf, *backup;
ofstream filestr;
filestr.open ("c:\\temp\\test.txt");
backup = cout.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
cout.rdbuf(psbuf); // assign streambuf to cout
cout << "This is written to the file";
cout.rdbuf(backup); // restore cout's original streambuf
filestr.close();
return 0;
}
then I write string to the file, but I see the nothing in console. How can I do it?
The simplest you can do is create an output stream class that does this:
#include <iostream>
#include <fstream>
class my_ostream
{
public:
my_ostream() : my_fstream("some_file.txt") {}; // check if opening file succeeded!!
// for regular output of variables and stuff
template<typename T> my_ostream& operator<<(const T& something)
{
std::cout << something;
my_fstream << something;
return *this;
}
// for manipulators like std::endl
typedef std::ostream& (*stream_function)(std::ostream&);
my_ostream& operator<<(stream_function func)
{
func(std::cout);
func(my_fstream);
return *this;
}
private:
std::ofstream my_fstream;
};
See this ideone link for this code in action: http://ideone.com/T5Cy1M
I can't currently check if the file output is done correctly though it shouldn't be a problem.
You could also use boost::iostreams::tee_device. See C++ "hello world" Boost tee example program for an example.
Your code does not work, because it is the streambuf that determines where the output written to a stream end up, not the stream itself.
C++ does not have any streams or streambufs that support directing the output to multiple destinations, but you could write one yourself.
A software library that I am working with writes a lot of debug output to std::cerr, but redirects that output to a null stream if I tell it to be quiet. This is a simplified main.cpp that shows how the code tries to achieve this:
#include <iostream>
#include <fstream>
#include <cassert>
// The stream that debug output is sent to. By default
// this points to std::cerr.
std::ostream* debugStream(&std::cerr);
// Throughout the library's codebase this function is called
// to get the stream that debug output should be sent to.
std::ostream& DebugStream()
{
return *debugStream;
}
// Null stream. This file stream will never be opened and acts
// as a null stream for DebugStream().
std::ofstream nullStream;
// Redirects debug output to the null stream
void BeQuiet()
{
debugStream = &nullStream;
}
int main(int argc, char** argv)
{
DebugStream() << "foo" << std::endl;
BeQuiet();
DebugStream() << "bar" << std::endl;
assert(debugStream->good());
return 0;
}
When you run this program, you will notice that the string "bar" is correctly sent to the null stream. However, I noticed that the assertion fails. Is this something that I should be concerned about? Or is this just a slightly ugly detail of the approach chosen by the library developers?
If you feel like it, suggestions for better alternatives are welcome. Some constraints:
The library is cross-platform, so I think using opening /dev/null is not a valid solution as it would not work on Windows
The library uses standard C++, so any alternative solutions should not use compiler-specific stuff
There is no real need to be worried about the stream not being good()! Since the output operators don't really do anything wirh a stream in failure mode the different entities being logged are not formatted, i.e., the code does run faster compared to alternative approaches.
Note that you don't really need a second stream to disable output:
Assuming all output operators are well-behaved, you can just set std::ios_base::failbit:
debugStream().setstate(std::ios_base::failbit);
If there are misbehaved output which write to a stream even if it isn't good() you can just set its stream buffer to null:
debugStream().rdbuf(nullptr);
If you really want your stream to remain in good() state, you'd install a stream buffer which just consumes characters. Note, however, that you want to give this stream buffer a buffer as having overflow() called for each char is fairly exensive:
struct nullbuf
: std::streambuf {
char buf[256];
int overflow(int c) {
this->setp(this->buf, this->buf + 256);
return std::char_traits<char>::not_eof(c);
}
};
...
nullbuf sbuf;
debugStream().rdbuf(&sbuf);
...
debugStream().rdbuf(0);
It is necessary to reset the stream's stream buffer because the destructor of an std::ostream will flush the stresm buffer (i.e., it calls pubsync()). Doing so on a destroyed stream buffer won't work.
Personally, I would go with setting std::ios_base::failbit.
In this answer you find a general helper to redirect any stream to any other stream:
class stream_redirector {
public:
stream_redirector(std::ios& stream, std::streambuf* newBuf) :
savedBuf_(stream.rdbuf()), stream_(stream)
{
stream_.rdbuf(newBuf);
}
~stream_redirector() {
stream_.rdbuf(savedBuf_);
}
private:
std::streambuf* savedBuf_;
std::ios& stream_;
};
and now all you need is a no-op stream from this answer which discards anything:
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
// note: the original code is missing the required this->
this->init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
and you're good to go:
int main(int argc, char** argv)
{
std::cerr << "foo" << std::endl;
{
onullstream nos;
stream_redirector sr( std::cerr, nos.rdbuf() );
std::cerr << "bar" << std::endl;
}
std::cerr << "baz" << std::endl;
}
and finally here's a live example in case you want to play with it. This method has the additional benefit that you (and your colleagues) can still use std::cerr in your code and you can turn it off and on again at will :)
Is there any way to keep a stream (to read or write in a file) open from a function to another in C++?
Yes, you can either create the stream outside of the functions and pass it as a parameter to the methods:
void myFunction(ifstream &stream) {...}
Later close the stream when you are done with it: stream.close().
Or create the stream within the first function and return it to the calling method and then pass it to the second function.
Pass it by reference
void myFunction(ifstream &myStream)
Make it global or pass it as an argument but ensure that if you pass it as an argument you past it by reference not by value! If you pass it by value the compiler will NOT complain and weird things start happening.
Since C++11 file stream got move constructor (6). You can use it to pass opened stream between functions. Consider the following code snippet:
#include <iostream>
#include <fstream>
bool open_stream(const std::wstring& filepath, std::ifstream& stream)
{
std::ifstream innerStream;
innerStream.open(filepath.c_str(), std::ios::in | std::ios::binary);
if (innerStream.is_open())
{
stream = std::move(innerStream); // <-- Opened stream state moved to 'stream' variable
return true;
}
return false;
} // <-- innerStream is destructed, but opened stream state is preserved as it was moved to 'stream' variable
Consider the next code to illustrate the usage of open_stream:
int main()
{
std::ifstream outerStream;
std::wcout << L"outerStream is opened: " << outerStream.is_open() << std::endl; // <-- outerStream is opened: 0
if (!open_stream(L"c:\\temp\\test_file.txt", outerStream))
{
return 1;
}
std::wcout << L"outerStream is opened: " << outerStream.is_open() << std::endl; // <-- outerStream is opened: 1
// outerStream is opened and ready for reading here
return 0;
}