Extremely simple test library - c++

Is there easily embeddable C++ test lib with a friendly license? I would like a single header file. No .cpp files, no five petabytes of includes. So CppUnit and Boost.Test are out.
Basically all I want is to drop single file to project tree, include it and be able to write
testEqual(a,b)
and see if it fail. I'd use assert, but it doesn't work in non-debug mode and can't print values of a and b, and before rewriting assert I'd rather search existing library.

I'm tempted to say "write your own", which is what I have done. On the other hand, you might want to reuse what I wrote: test_util.hpp and test_util.cpp. It is straightforward to inline the one definition from the cpp file into the hpp file. MIT lisence. I have also pasted it into this answer, below.
This lets you write a test file like this:
#include "test_util.hpp"
bool test_one() {
bool ok = true;
CHECK_EQUAL(1, 1);
return ok;
}
int main() {
bool ok = true;
ok &= test_one();
// Alternatively, if you want better error reporting:
ok &= EXEC(test_one);
// ...
return ok ? 0 : 1;
}
Browse around in the tests directory for more inspiration.
// By Magnus Hoff, from http://stackoverflow.com/a/9964394
#ifndef TEST_UTIL_HPP
#define TEST_UTIL_HPP
#include <iostream>
// The error messages are formatted like GCC's error messages, to allow an IDE
// to pick them up as error messages.
#define REPORT(msg) \
std::cerr << __FILE__ << ':' << __LINE__ << ": error: " msg << std::endl;
#define CHECK_EQUAL(a, b) \
if ((a) != (b)) { \
REPORT( \
"Failed test: " #a " == " #b " " \
"(" << (a) << " != " << (b) << ')' \
) \
ok = false; \
}
static bool execute(bool(*f)(), const char* f_name) {
bool result = f();
if (!result) {
std::cerr << "Test failed: " << f_name << std::endl;
}
return result;
}
#define EXEC(f) execute(f, #f)
#endif // TEST_UTIL_HPP

Try google-test https://github.com/google/googletest/
it's really light weight, cross platform and simple.

Related

Specializing macro with arguments

Suppose I have the following macro:
#define LOG(L, ...) func(L, __VA_ARGS__);
Where L can be one of INFO, WARN, FATAL
Now I want to define it for FATAL differently.
#define LOG(FATAL, ...) {func(FATAL, __VA_ARGS__); exit(-1);}
How to accomplish this?
Edit:
As a follow up to above, is there a better way to do it? i.e. by avoiding macros for example.
Macros are mostly a bad choice in C++ – essentially because of they are namespace agnostic and may take effect where it is unexpected.
That said – a sample for how OPs issue could be solved e.g. using token pasting:
#include <iostream>
#define LOG(LEVEL, ...) LOG_##LEVEL(__VA_ARGS__)
#define LOG_INFO(...) log(Info, __VA_ARGS__)
#define LOG_WARN(...) log(Warn, __VA_ARGS__)
#define LOG_FATAL(...) do { log(Error, __VA_ARGS__); std::cerr << "Program aborted!\n"; } while (false)
enum Level { Info, Warn, Error };
void log(Level level, const char *text)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR" };
std::cerr << levelText[level] << ": " << text << '\n';
}
int main()
{
LOG(INFO, "Everything fine. :-)");
LOG(WARN, "Not so fine anymore. :-|");
LOG(FATAL, "Things became worst. :-(");
}
Output:
INFO: Everything fine. :-)
WARNING: Not so fine anymore. :-|
ERROR: Things became worst. :-(
Program aborted!
Live Demo on coliru
Another sample for the follow-up question - with variadic templates instead of macros:
#include <iostream>
enum Level { Info, Warn, Error, Fatal };
template <typename ...ARGS>
void log(Level level, ARGS&& ... args)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR", "FATAL" };
std::cerr << levelText[level] << ": ";
(std::cerr << ... << args);
std::cerr << '\n';
if (level == Fatal) std::cerr << "Program aborted!";
}
int main()
{
log(Info, "Everything fine.", ' ', ":-)");
log(Warn, "Not so fine anymore.", ' ', ":-|");
log(Error, "Things became bad.", ' ', ":-(");
log(Fatal, "Things became worst.", ' ', "XXX");
}
Output:
INFO: Everything fine. :-)
WARNING: Not so fine anymore. :-|
ERROR: Things became bad. :-(
FATAL: Things became worst. XXX
Program aborted!
Live Demo on coliru
I must admit that I needed some help for the parameter unpacking – found here:
SO: What is the easiest way to print a variadic parameter pack using std::ostream?.
Extending Scheffs answer a bit, this one passes the log level as a template argument, allowing the use of if constexpr (as JVApen mentioned in his comment). You'd need to know the respective level for each log output at compile time, but I think that won't be an issue.
enum Level { Info, Warn, Error, Fatal };
template<Level L, typename ...ARGS>
void log(ARGS&& ... args)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR", "FATAL" };
std::cerr << levelText[L] << ": ";
(std::cerr << ... << args);
std::cerr << '\n';
if constexpr (L == Fatal)
std::cerr << "Program aborted\n";
}

using stream to log information in C++

I have a C++ class which logs messages to a std::ofstream. In the class definition is this code:
#ifdef NDEBUG
#define FOO_LOG(msg) /* calls to log messages are no-op in release mode */
#else
std::ofstream log_stream;
#define FOO_LOG(msg) if (log_stream.is_open()) { log_stream << msg << std::endl; }
#endif
The constructor for that class has several things it checks, and in certain situations will open the log file similar to this:
#ifndef NDEBUG
log_stream.open("output.log");
#endif
Then in the code, it calls the C macro like this:
FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz)
It is convenient that you can pass multiple params to the FOO_LOG() macro. There are obvious limitations, like when logging messages from multiple threads, but this is only used for simple logging in debug builds.
What I want to know is whether there is a different/better way to deal with the msg parameter in C++? Is there a simpler/cleaner way to implement something similar to FOO_LOG() in C++?
Instead of having #ifdef NDEBUG everywhere in your code you can have a #ifdef NDEBUG at the start of the header to define other useful macros.
For me FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz); feels a bit unnatural. I would have to keep reffering back to the macro definition to see how it's implemented. Instead you can define a macro to behave as an std::ostream and use it as you would any other stream. That way you can do stuff like LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;.
For this answer I had some inspiration from this question.
#include <fstream>
#define NDEBUG
//An ostream class that does nothing
class DummyStream : public std::ostream {
public:
int overflow(int c) { return c; }
} dummyStream;
//Here we let NDEBUG define other macros.
#ifdef NDEBUG
std::ofstream logStream;
std::ostream& oLogStream(*(std::ostream*)&logStream);
#define LOG_STREAM (logStream.is_open() ? oLogStream : dummyStream)
#define OPEN_LOG(log) (logStream.is_open() ? logStream.close(), logStream.open(log, std::ofstream::out | std::ofstream::app) : \
logStream.open(log, std::ofstream::out | std::ofstream::app))
#define CLOSE_LOG() (logStream.close())
#else
#define LOG_STREAM (dummyStream)
#define OPEN_LOG(log) //no-op
#define CLOSE_LOG() //no-op
#endif // NDEBUG
int main(int argc, char* argv[]) {
//will only log if NDEBUG is defined.
OPEN_LOG("log.txt");
std::string stuff("stuff to log");
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
CLOSE_LOG();
//Log is not open so it will not log anything.
stuff = "stuff to not log";
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
return 0;
}
Benifits of this?
LOG_STREAM is treated more intuitively like any other stream.
OPEN_LOG(log) will close already open logs before opening a new one and when NDEBUG is not define it will do nothing.
CLOSE_LOG() will close a log and when NDEBUG is not define it will do nothing.
Don't need to type #ifdef NDEBUG ... #endif everywhere.
dummyStream can be replaced with something like std::cout or some other stream.
Down side?
You have this DummyStream that's just in your code and a few no-op's are performed when LOG_STREAM is used when NDEBUG is not defined.

C++ macro parsing issue

I'm trying to use a macro to queue up a single log line locally in an ostringstream and then dump the entire contents of that ostringstream when the line is over. I want to still use stream insert syntax, however. So I want to turn a log line like this:
std::cerr << "Some error in my function. Code is " << errCode << " exiting" << std::endl;
...into this
SERR("Some error in my function. Code is " << errCode << " exiting);
I've got something simple that works well. That is, until I put it in an if-else statement. Obviously my macro is bad but I am at a loss as to what to do.
Here is a small sample program, hacked up to illustrate the problem.:
#include <iostream>
#include <sstream>
#define SERR(x) { std::ostringstream _s; ; _s << x << std::endl; std::cerr << _s.str(); }
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
SERR("No error");
else
SERR("Error");
}
The error message I get from the compiler in this sample is:
1>c:\users\joe\source\repos\consoleapplication5\consoleapplication5\consoleapplication5.cpp(15):
error C2181: illegal else without matching if
Any ideas what I've got wrong here?
(Note I'm not in a place where I can use a 3rd Party logging solution now so it's got to be something simple like this. I could just leave all this as normal std::cerr/std::cout/std::clog messages, if I had to but I'd prefer something simple to minimize the chances of interleaving of log messages from my multithreaded app.)
Just try to expand it and see what you get:
#include <iostream>
#include <sstream>
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
{ std::ostringstream _s; ; _s << "No error" << std::endl; std::cerr << _s.str(); };
else
{ std::ostringstream _s; ; _s << "Error" << std::endl; std::cerr << _s.str(); };
}
Notice how { } block is terminated with ;?
If you need a macro, you should always write it using do { } while (0) like this:
#define SERR(x) \
do { \
std::ostringstream _s; \
_s << (x) << std::endl; \
std::cerr << _s.str(); \
} while (0)
Not only this solves your issue, but also make it mandatory to add ; after the macro. Otherwise people could use it two ways:
SERR("foo") // without ;
...
SERR("bar"); // with ;

Get name of calling function, line number and file name in c++

I have wrote following code to write logs in my log file.
This code is working fine for logging messages but now i have to integrate this in multiple files i need file path of caller, caller function name and line number.
Kindly help me to achieve this .
#include "Source.h"
bool CLogManager::fileOpenError = false;
std::string CLogManager::logFileName = "";
CLogManager* CLogManager::logManager = NULL;
FILE* CLogManager::file = NULL;
CLogManager :: CLogManager(){}
CLogManager :: ~CLogManager()
{
if (file)
fclose(file);
}
CLogManager* CLogManager::getInstance()
{
if(logManager==NULL)
{
logManager = new CLogManager();
logFileName = currentDateTime();
}
return logManager;
}
const std::string CLogManager::currentDateTime()
{
time_t now = time(0);
char currTime[30];
strftime(currTime, sizeof(currTime), "Log_%Y_%m_%dT%H_%M_%S.xml", localtime(&now));
return currTime;
}
void CLogManager::Log (char *message)
{
file = fopen(logFileName.c_str(), "a+");
if(file == NULL)
{
if(fileOpenError == false)
{
std::cout << "There was an error While opening Log File."<<std::endl;
fileOpenError = true;
}
return;
}
fputs(message, file);
fputs("\n", file);
}
int main ()
{
CLogManager::getInstance();
CLogManager::Log("Sorry some error occured");
CLogManager::Log("Please try again");
CLogManager::Log("Wait");
return 0;
}
Since C++ 20, you can use std::source_location.
From the example on CPPReference.com:
#include <iostream>
#include <string_view>
#include <source_location>
void log(const std::string_view message,
const std::source_location location =
std::source_location::current())
{
std::cout << "file: "
<< location.file_name() << "("
<< location.line() << ":"
<< location.column() << ") `"
<< location.function_name() << "`: "
<< message << '\n';
}
template <typename T> void fun(T x)
{
log(x);
}
int main(int, char*[])
{
log("Hello world!");
fun("Hello C++20!");
}
Output:
file: main.cpp(23:8) `int main(int, char**)`: Hello world!
file: main.cpp(18:8) `void fun(T) [with T = const char*]`: Hello C++20!
When I need a fast "printf" logging, I use this marco for message logging that is branded with filename and line:
#define _MSG(msg) do{ std::cerr << __FILE__ << "(#" << __LINE__ << "): " << msg << '\n'; } while( false )
The above macro will inject a msg into a std::cerr pipeline. You can take out parts you need or modify it for your purposes. It hinges on __FILE__ and __LINE__ macros, which are defined by standard:
__FILE__
The presumed name of the current source file (a character string literal).
__LINE__
The presumed line number (within the current source file) of the current source line (an integer
constant).
Function names are not so easy to get, and I don't think there is a nice way to get it.
If you want logging through functions I would define some macro, or make function that would take int and char* for line and file respectively. Something like log(int line, char* source_file, string message).
To utilize the LogManager class that you already have written, you could do something like this:
void CLogManager::Log(char *message, std::string FileName = "Unset", std::string FunctionName = "Unset", int LineNumber = -1)
{
...
}
Then, anywhere you want to use your Logging function as it is right now, you would just do:
::Log(message);
But, if you wanted to include File/Function/Line information, you would do this:
::Log(message, __FILE__, __FUNCTION__, __LINE__);
You can adjust the defaults from "Unset" to anything you wanted (including just ""). I might also suggest in that function that you could have the output be different based upon whether the FileName parameter (passed to the function) is the default or not. That way your log file would look clean.

C++ enable/disable debug messages of std::couts on the fly

Is there a way to define/undefine debug messages using std::cout whenever inside a program?
I am aware that there are such things such as #define, #ifndef, but I was thinking is there a cleaner way to having a variable say:
# debug ON
That prints all of my debug data (using std::cout). Consequently, we'll have code like this for debug:
#ifndef DEBUG
// do something useful
#endif
I find the above code cumbersome when you write 100s of debug code.
Thanks!
Carlo
#ifdef DEBUG
#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
#else
#define DEBUG_MSG(str) do { } while ( false )
#endif
int main()
{
DEBUG_MSG("Hello" << ' ' << "World!" << 1 );
return 0;
}
Some logging libraries are pretty heavy weight unless you have complex logging needs. Here's something I just knocked together. Needs a little testing but might meet your requirements:
#include <cstdio>
#include <cstdarg>
class CLog
{
public:
enum { All=0, Debug, Info, Warning, Error, Fatal, None };
static void Write(int nLevel, const char *szFormat, ...);
static void SetLevel(int nLevel);
protected:
static void CheckInit();
static void Init();
private:
CLog();
static bool m_bInitialised;
static int m_nLevel;
};
bool CLog::m_bInitialised;
int CLog::m_nLevel;
void CLog::Write(int nLevel, const char *szFormat, ...)
{
CheckInit();
if (nLevel >= m_nLevel)
{
va_list args;
va_start(args, szFormat);
vprintf(szFormat, args);
va_end(args);
}
}
void CLog::SetLevel(int nLevel)
{
m_nLevel = nLevel;
m_bInitialised = true;
}
void CLog::CheckInit()
{
if (!m_bInitialised)
{
Init();
}
}
void CLog::Init()
{
int nDfltLevel(CLog::All);
// Retrieve your level from an environment variable,
// registry entry or wherecer
SetLevel(nDfltLevel);
}
int main()
{
CLog::Write(CLog::Debug, "testing 1 2 3");
return 0;
}
Probably not. I would recommend using a logging library. I'm not sure what the best option is for C++ anymore, but I've used log4cpp in the past and found it pretty good.
EDIT: I assume on the fly means # runtime. If you just need it to be a compile time flag, then Gianni's answer is probably easiest to implement. Logging libraries give you a lot of flexibility and allow reconfiguration # runtime though.
Another simple solution, involves opening a std::ostream reference to cout in debug mode, and /dev/null in non-debug mode, like so:
In debug.h:
extern std::ostream &dout;
In debug.c
#ifdef DEBUG
std::ostream &dout = cout;
#else
std::ofstream dev_null("/dev/null");
std::ostream &dout = dev_null;
#endif
And then:
dout << "This is a debugging message";
Of course, this would only work on any system where /dev/null points to a null device. Since the dout reference is global here, it would much like cout. In this way, you can point the same stream to multiple output streams, for example to a log file, depending of the value of debug flags, etc.
Although the question is old, and there are some good answers, i want to post also a solution to this. It is like Giannis approach but different. And also, i used std::cerr instead of std::cout, but you can change this really quick.
#include <iostream>
#ifdef DEBUG
# define DEBUG_LOG std::cerr
#else
class log_disabled_output {};
static log_disabled_output log_disabled_output_instance;
template<typename T>
log_disabled_output& operator << (log_disabled_output& any, T const& thing) { return any; }
// std::endl simple, quick and dirty
log_disabled_output& operator << (log_disabled_output& any, std::ostream&(*)(std::ostream&)) { return any; }
# define DEBUG_LOG log_disabled_output_instance
#endif
int main() {
int x=0x12345678;
DEBUG_LOG << "my message " << x << " " << "\n more information" << std::endl;
};
Now you can use it just like a output stream.
(Note: iostream is only included if cerr is used. This will reduce the amount of inclusion if you don't have it already included. -edit: not with std::endl support).
If DEBUG is defined cerr is used to print the error. Otherwise the dummy class log_disabled_output is instantiated statically and operator<< is overloaded to any type. The vantage is; If you disable the logging, a clever compiler will notice that there is nothing to do with the stream and optimize the entire "line" away, so you don't have any overhead if DEBUG is disabled.
I was trying to do the same thing. After some research, I developed the following, and it seems to work. Please comment if you see anything wrong.
ostream DbgMsg(NULL);
enum {
DBGMSG_NONE,
DBGMSG_DEFAULT,
DBGMSG_VERBOSE
} DbgLvl = DBGMSG_DEFAULT;
ostream &DbgMsgDefault(ostream &stream) {
return (DbgLvl>=DBGMSG_DEFAULT) ? cout : stream;
}
ostream &DbgMsgVerbose(ostream &stream) {
return (DbgLvl>=DBGMSG_VERBOSE) ? cout : stream;
}
void main() {
DbgMsg<<DbgMsgDefault<<"default:default"<<endl;
DbgMsg<<DbgMsgVerbose<<"default:verbose"<<endl;
DbgLvl = DBGMSG_NONE;
DbgMsg<<DbgMsgDefault<<"none:default"<<endl;
}
A clean thing to do would be to use cerr.
"cerr" acts essentially as "cout", but always flushes the output (useful for debugging, by the way). If you need to remove all the messages, you can comment out all the cerr messages with a simple find-and-replace (cerr into //cerr).
There are probably even better ways to use cerr and to desactivate it cleanly (which writes into a special stream, the error stream, hence the name).
I hope this helps.
This is what I used (worked with VC++) - here "##" is used for concatennation
#ifdef DEBUG
#define pout cout
#else
#define pout / ## / cout
#endif
For other compilers use this :
#ifdef DEBUG
#define pout cout
#else
#define pout 0 && cout
#endif
Usage :
pout << "hello world" << endl;
I was looking for similar example and sharing my example below:
#include <iostream>
enum debug_option
{
DEBUG_DISABLE,
DEBUG_ENABLE
};
class debug
{
public:
debug_option debug_state;
debug() : debug_state(DEBUG_ENABLE) {} // constr
debug(debug_option state) : debug_state(state) {} // constr
template<typename T>
debug & operator<< (T input)
{
if (this->debug_state == DEBUG_ENABLE)
std::cout << input;
return *this;
}
};
int main()
{
debug log, log_lev2(DEBUG_DISABLE);
log << "print 1..\n" << 55 << " over\n";
log.debug_state = DEBUG_DISABLE;
log << "print 2..\n" << 3 << "over\n";
log_lev2 << "print 3..\n" << 4 << "over\n";
log_lev2.debug_state = DEBUG_ENABLE;
log_lev2 << "print 5..\n";
std::cout << "std::cout << print..\n";
return 0;
}
Better suggestions are always welcome.