Unit test for ensuring conditionally compiled code in c++ - c++

This is a standard C++ ASSERT macro defined in my code -
#ifndef DEBUG
#define ASSERT(n)
#else
#define ASSERT(n) \
if (!(n)){ \
printf("%s - Failed ", #n); \
printf("On %s ", __DATE__); \
printf("At %s ", __TIME__); \
printf("In File %s ", __FILE__); \
printf("At Line %d\n", __LINE__); \
exit(1);}
#endif
I want to ensure that my build always contains this code, by binding a unit test around it. The test should check that if #DEBUG preprocessor is not supplied (i.e. it is release mode), a conditional check applied in unit test should fail with ASSERT macro failing and containing the message given above.
Is there an established way to achieve this? I am using google test framework to achieve this, but unable to achieve the result. Test fails with standard assertion message, not the custom assertion I am trying it to fail with.
My code is as below -
TEST(VerifyNormalInitialization, VerifyAssert)
{
static int index = 0;
static int num = 4;
ASSERT(index == num);
EXPECT_FATAL_FAILURE(ASSERT(index == num),"Failed");
}

First the obvious the following raises only an error when DEBUG is defined.
ASSERT(index == num);
ASSERT(index != num);
For unit tests for both cases: production and development, you need to compile both ways.
You might effect that by your own #define/#undef DEBUG.
Good practice? I do not know; I was not aware that this was something worthwile testing. Maybe just a verification that ASSERTs are active during development. And that is something for an installation check.

Consider
EXPECT_FATAL_FAILURE(if (!(index == num)){ ... },"Failed");
Does that look like valid C++? It is not.
Consider writing a macro which passes along #n, __FILE__ etc to a proper function. If you insist on using a macro alone, then it needs to be a single expression and not a statement, something along the lines of:
#define STR2(x) #x
#define STR(x) STR2(x)
#define ASSERT(n) \
( \
fprintf(stderr, \
#n " - Failed on " __DATE__ " at " __TIME__ \
" in file " __FILE__ " at line " STR(__LINE__) \
), \
exit(EXIT_FAILURE) \
)
This is using compile-time string concatenation to prepare the whole string. Everything in this expression is string literals, and two string literals such as "hello" and "world" get concatenated by the pre-processor as "helloworld".
The "stringification" macros are just there to convert the integer __LINE__ into a string literal. Stringification - how does it work?
Note that the ), is the comma operator, which is used to allow two function calls in the same expression.

Related

How to call macro that uses token pasting?

I am trying to print ffmpeg version in a C++ program. I see that in the /libavutil/version.h there is AV_VERSION which should tell the version number in the format x.x.x.
As a test I used some random numbers as function parameters like this: std::string version = AV_VERSION(3,4,2);. The same error I get if I use LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR and LIBAVUTIL_VERSION_MICRO from the file. That was actually my first try to print the version number.
The error I get is invalid suffix '.2' on floating constant or invalid suffix '.101' on floating constant if I try to print std::cout << AV_VERSION(LIBAVUTIL_VERSION_MAJOR,LIBAVUTIL_VERSION_MINOR,LIBAVUTIL_VERSION_MICRO) << std::endl;
I do understand that the preprocessor is thinking that the token is a float, hence the error. How do you actually use this type of macro funtion?
That macro is in the file I mentioned above, so it must be a way to call that macro function without giving an error, thinking that is a mature library, and I guess other libraries use something similar for printing version number.
Here is how AV_VERSION is defined in the header file and how I call it:
#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c))
#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c
#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)
#define AV_VERSION_MAJOR(a) ((a) >> 16)
#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8)
#define AV_VERSION_MICRO(a) ((a) & 0xFF)
#define LIBAVUTIL_VERSION_MAJOR 57
#define LIBAVUTIL_VERSION_MINOR 9
#define LIBAVUTIL_VERSION_MICRO 101
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
LIBAVUTIL_VERSION_MICRO)
#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
LIBAVUTIL_VERSION_MICRO)
int main()
{
std::string version = AV_VERSION(3,4,2);
std::cout << AV_VERSION(LIBAVUTIL_VERSION_MAJOR,LIBAVUTIL_VERSION_MINOR,LIBAVUTIL_VERSION_MICRO) << std::endl;
return 0;
}
I coud've skip this error but as I'm trying to learn C++ I am pretty sure that I will find more of this type of macros so no point to avoid learning them now as I'm facing them.
Thanks in advance!
You need to use a stringize expansion. Because of how the preprocessor works, this involves two macros:
#define STR(x) #x
#define XSTR(x) STR(x)
The macro STR will take whatever parameter you give it and make that a string literal.
The macro XSTR will first expand its parameter x and the result will be the parameter to STR.
To illustrate:
STR(LIBAVUTIL_VERSION) will give "LIBAVUTIL_VERSION"
XSTR(LIBAVUTIL_VERSION) will give "57.9.101"
Demo according to your code:
int main()
{
std::string version1 = XSTR(LIBAVUTIL_VERSION);
std::string version2 = XSTR(AV_VERSION(3,4,2));
std::cout << version1 << "\n";
std::cout << version2 << "\n";
return 0;
}
Output:
57.9.101
3.4.2

How to get catch2 to print the compared C-style string's contents?

I'm using catch2 (latest release - 2.13.6 as of this moment), and in my testcases I have a bunch of checks similar to the following:
CHECK(!strcmp(my_str, "some literal string here"));
where the literal is different for each testcase and obviously so is my_str's contents.
When such a check fails, what I get on the output is the following:
/path/to/test_source_file.cpp:123: FAILED:
CHECK( !strcmp(my_str, "some literal string here") )
with expansion:
false
but I don't get the stirng within my_str printed out. What's the best way to get the above to print (some of) the contents of my_str as well?
Notes:
You may not assume my_str is null-terminated.
Code must relatively succinct.
I would rather not convert anything to an std::string, but if you must do that, I'm not ruling it out.
My own hacky solution is the following:
#define PRINTING_CHECK(expected_, actual_) \
do { \
INFO( "actual_ = " << '"' << actual_ << '"'); \
INFO( "expected_ = " << '"' << expected_ << '"'); \
CHECK(!strcmp(actual_, expected_)); \
} while (false) \
but I was hoping there might be something more elegant.

Easy way of constructing information message for throwing std::exception using preprocessor macros

At certain points of my code I want to throw an exception and give it some information about the code where I've thrown it. Something like
void Foo() {
if(condition)
throw std::logic_error(ERROR_MSG);
}
// somewhere later in code
try {
Foo()
} catch (std::exception & e) {
e.what();
}
Now the question is – how do i construct this error message? I would like to give information about the file, the line of code, the function name and a bit of an own information. Something (I suspect) should be pretty standard usage – but after an extensive search I still didn't find something useful about this (as I thought) easy subject.
I just would like to write something like this
throw std::logic_arrow("Whoops! Error in (" +
__func__ + ") " + __FILE__ + ":" + __LINE__);
But this doesn't seem to work for various reasons. Here is what I achieved so far with my search:
There is already a similar question here, but this is about if one should use these macros, not how
This question deals with concatenating __FILE__ and __LINE__ in a macro, so I was a bit further to my answer
The __func__ macro seems to make difficulties, since "These identifiers are variables, not preprocessor macros, and may not be used to initialize char arrays or be concatenated with string literals" following to the gcc homepage. Well, it is now a variable I can use for instance in the printf function like here – but I didn't manage to master the transfer to my own problem
One guy was worried about a cleaner solution than Macros, using inline functions, so I could even improve a solution
C++14 techniques where suggested in another thread, using operator ""s
Just do this:
throw std::logic_error(std::string{} + "Whoops! Error in (" +
__func__ + ") " + __FILE__ + ":" + std::to_string(__LINE__));
live example
Sometimes you can format it like the IDE does its own error messages, then get double-click support.
throw std::logic_error(std::string{} + __FILE__ + "(" + std::to_string(__LINE__) + "): [" + __func__ +"] " + "Whoops! Error! Whodathunk.");
or somesuch.
template<class E>
[[noreturn]] void fancy_throw( std::string msg,
char const* file, char const* function,
std::size_t line
) {
throw E( std::string{} + file + "(" + std::to_string(line) + "): [" +
function + "] " + msg );
}
#define EXCEPTION( TYPE, MESSAGE ) \
fancy_throw<TYPE>( MESSAGE, __FILE__, __func__, __LINE__ )
and we get:
EXCEPTION( std::logic_error, "Whoops! Error! Whodathunk." );
live example
I think this is poor. Instead, we can have a SOURCE_ERROR macro:
inline std::string make_source_error( std::string msg,
char const* file, char const* function,
std::size_t line
) {
return std::string{} + file + "(" + std::to_string(line) + "): [" +
function + "] " + msg;
}
#define SOURCE_ERROR(...) make_source_error(__VA_ARGS__, __FILE__, __func__, __LINE__ )
which places flow control outside of macros, but does the string building with the tokens inside the macro, and builds the string inside a normal function.
Only the things that must be done in a macro (or copy/pasted everywhere we use it) are done in a macro here. Which is how it should be.
live example
... and __VA_ARGS__ are there because the macro language doesn't understand some uses of , in C++.
I would suggest looking into Boost.Exception which does this and more (it's one of the most lightweight Boost libraries consisting only of a few headers).
I've been doing that by using a couple of macros (so that it would reduce the hassle of typing the whole thing each time, plus it adds consistency), and then creating temporary std::strings to concatenate them easily. There might be a simpler way, but it works well and you only type it once.
// Helper macros to convert a macro string constant to an actual string in another macro.
#define STRINGIFY2(x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define CURRENT_LOCATION std::string("At "STRINGIFY(__FILE__)":") + __func__ + std::string("(" STRINGIFY(__LINE__) "): ")
You can then use it and add some info afterwards that way:
throw std::logic_error(CURRENT_LOCATION + "Description here");
Watch it live here
Okay, after some trying I got an "easy" solution which doesn't even need the use of macros, only an inline function. It does compile with g++ 6.1.1 and also "work" es expected (throwing the exception).
#include <iostream>
#include <stdexcept>
inline const std::string
Exception_helper( const std::string msg,
const char * const func_name,
const char * const file_name,
const std::size_t line_number) {
return msg + " " + func_name + "() in " + file_name + ":" +
std::to_string(line_number);
}
void Foo() {
throw std::logic_error(Exception_helper("Whoops! Error in",
__func__,
__FILE__,
__LINE__));
}
int main() {
try { Foo(); }
catch (std::exception & e) {
std::cerr << e.what() << std::endl;
exit(1); }
return 0;
}
I could try to even implement Exception_helper as constexpr function, but no time for that at the moment.
Again, thanks to all who helped me find an answer. Stackoverflow is the best.

How to print C-preprocessor variables like __LINE__ with mexErrMsgTxt() In Matlab MEX

For debugging Matlab-MEX, which can be quite a hassle, it would be nice to have better assertion capabilities. Following this question about mex-assertions, it is possible to define a preprocessor makro, that throws an error to Matlab and prints a string (can mostly replace mxAssert, which unfortunately crashes Matlab2011b).
#define myassert( isOK,astr ) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(astr) )
It would be much nicer to print the file, line number and caller function, from where following example assertion myassert(A=B,"A not B") is raised! This answer to the initial question states that they are the preprocessor variables:
__LINE__,__PRETTY_FUNCTION__, __FILE__
How can we print these preprocessor variables with mexErrMsgTxt?
The problem is, that mexErrMsgTxt() takes a char* argument and not multiple inputs like for example printf(const char *format, ...).
My thinking goes only so far at the moment:
It's not possible to build a function, because the preprocessor variables will have the values (e.g. line number) from the function.
It was not possible for me to write a working multiline preprocessor makro that creates a char from the passed string astr and passes it to mexErrMsgTxt(). Maybe a solution is along these lines.
A hybrid solution with a char creating preprocessor makro and a function that passes it to mexErrMsgTxt() doesn't feel like good coding practice.
It would be really nice to make the specified error string optional.
Concatenating preprocessor tokens works as long as you only use __FILE__, __LINE__ and a string literal as message. Then you can write something like
#define STRINGIZE_I(x) #x
#define STRINGIZE(x) STRINGIZE_I(x)
#define myassert(isOK, astr) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(__FILE__ ":" STRINGIZE(__LINE__) ": " astr) )
Unfortunately, __PRETTY_FUNCTION__ is not a string literal even for those compilers who support it. If you want to use it (or less fixed error messages), you'll have to assemble the string dynamically, which means something along the lines of
#define myassert(isOK, astr) \
do { \
if(!(isOk)) { \
std::ostringstream fmt; \
fmt << "In " << __PRETTY_FUNCTION__ << ", " \
<< __FILE__ << ":" << __LINE__ << ": " << (astr); \
(void) mexErrMsgTxt(fmt.str().c_str()); \
} \
} while(false)
For C, do the same with snprintf. (Or asprintf. It avoids problems with fixed buffer lengths and long error messages, and it is about as portable as __PRETTY_FUNCTION__). Either way, roughly like
#define myassert(isOK, astr) \
do { \
if(!(isOk)) { \
char buf[ENOUGH_SPACE]; \
snprintf(buf, ENOUGH_SPACE, "In %s, %s:%d: %s", \
__PRETTY_FUNCTION__, __FILE__, __LINE__, (astr)); \
buf[ENOUGH_SPACE - 1] = '\0'; \
(void) mexErrMsgTxt(buf); \
} \
} while(0)
...where ENOUGH_SPACE would have to be defined appropriately (in the snprintf case).

Understanding a C++ Macro that uses #

I have a C++ macro with a syntax that I have never seen before:
#define ASSERT(a) \
if (! (a)) \
{ \
std::string c; \
c += " test(" #a ")";
}
Couold you please explain me the use of # in here?
I wanted to put the macro in a static function but before I would like to fully understand what it does.
Thanks
The use of # in a macro means that the macro argument will be wrapped in quotes "":
#define FOOBAR(x) #x
int main (int argc, char *argv[])
{
std::cout << FOOBAR(hello world what's up?) << std::endl;
}
output
hello world what's up?
Another example
In the below we display the contents of foo.cpp, and then what the file will look like after the pre-processor has run:
:/tmp% cat foo.cpp
#define STR(X) #X
STR (hello world);
...
:/tmp% g++ -E foo.cpp # only run the preprocessor
# 1 "foo.cpp"
# 1 "<command-line>"
# 1 "foo.cpp"
"hello world";
Where can I read more?
Check out the following link to a entry in the cpp (C Pre Processor) documentation:
Stringification - The C Preprocessor
Within a macro the # "stringifies" the variable name. By "stringify" I mean, the variable name is transformed into a string literal.
For example when you have the following macro:
#define PRINT_VARIABLE_NAME(var) printf(#var);
And use it like that:
int i;
PRINT_VARIABLE_NAME(i);
It would print "i".
In your case the string would get concatenated with "test".
#a is a string containing the literal a. See Stringfication for more.