===== Test Macros ===== Gnucap supplies a set of test macros in the file gnucap/io_trace.h . This file may be included more than once, at any place in the code, to change the options. All of these macros do nothing when compiled with default settings. They exist so they can be left in the code and enabled or disabled as needed by developers without burdening end users with their clutter. === assert() === This is not Gnucap specific -- we use this macro precicely as [[https://sourceware.org/glibc/manual/latest/html_node/Consistency-Checking.html|explained]] elsewhere and to document the code. In addition, we use //commented out asserts// to guide the reader. The intent of a commented out assert is merely to emphasize the idea behind the code. The argument statement is known not to hold in a corner case such as error handling. === unreachable() === #define unreachable() (printf("@@#\n@@@unreachable:%s:%u:%s\n", \ __FILE__, __LINE__, __func__)) It prints the word "unreachable", the source file name, line number, and function name. Use this macro to identify blocks of code that are unreachable in normal use. Any output when the program is run indicates bugs in the code. It is appropriate to question why such a block of code should exist at all. Normally, it shouldn't and should be removed. However, there are cases where a function or other code must exist to satisfy a link requirement or to defeat something. One example of the link requirement is member functions in a base class that are overridden. The usual recommended style is to use a "pure virtual", but then you can't instantiate any instances unless an overriding function exists. In some cases, it is known that it is never used, but required for instantiation, hence "unreachable". Another example is overriding default and copy constructors with the purpose of preventing their use. If you don't define one, C++ will create public default and copy constructors without asking. To prevent automatic construction or copying, you could make them private, but to make it private you need to define your own. In this case, those inhibiting constructors are unreachable. Usually an "unreachable" block can be empty except for the macro call. === incomplete() === #define incomplete() (printf("@@#\n@@@incomplete:%s:%u:%s\n", \ __FILE__, __LINE__, __func__)) It prints the word "incomplete", the source file name, line number, and function name. Use this macro to identify blocks of code that are known to not function correctly. This is intended to be used as a reminder that attention is needed here, otherwise the problems could be forgotten until they show in a more unpleasant way. === untested() === #ifdef TRACE_UNTESTED #define untested() (printf("@@#\n@@@:%s:%u:%s\n", \ __FILE__, __LINE__, __func__)) #else #define untested() #endif If ''TRACE_UNTESTED'' is defined, it prints the source file name, line number, and function name. Otherwise (normally) it does nothing. It is used in code coverage testing, and to identify blocks of code for which testing is inadequate, specifically blocks of code that are not covered by the suite of test files. Such blocks of code are suspect when bugs are reported. Following our convention, it is of special importance whether or not a Block carries an initial "untested();" statement. To make this work, implicit blocks are forbidden. Do not write if(c) stuff(); but if(c) { stuff(); }else{ } Because the latter version implies reachability from our test suite. Sometimes it is advisable to rephrase ''return c;'' as if(c) { return true; }else{ return false; }. Always remember that the absence of an "untested();" statement at a test hook has a clear meaning and reasoning behind it. === hit counters === A number at a block start indicates the number of times the block is reached from executing the test suite. This number is straightforward to obtain using "untested()" statements. === itested() === #ifdef TRACE_ITESTED #define itested() (printf("@@#\n@@@:%s:%u:%s\n", \ __FILE__, __LINE__, __func__)) #else #define itested() #endif If ''TRACE_ITESTED'' is defined, it prints the source file name, line number, and function name. Otherwise (normally) it does nothing. It is used in code coverage testing, and to identify blocks of code for which only interactive informal testing was done. It was tested, but the test suite does not cover it. === trace0(), trace1(), trace2(), .... === #ifdef DO_TRACE #define trace0(s) (printf("@#@%s\n", s)) #define trace1(s,x) (printf("@#@%s %s=%g\n", s, #x, (double)(x))) #else #define trace0(s) #define trace1(s,x) #endif If ''DO_TRACE'' is defined, it prints something, otherwise (normally) it does nothing. ''trace0'' prints a string message. ''trace1'' prints a string message and one argument. trace1("hello", data); prints: hello data=329232 and so on.