1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-06-25 00:16:54 +02:00

Add ASSERT_DEBUG() macro for debugging.

Replace all current assert() calls except in tests that can't use the debug code.
This commit is contained in:
David Steele
2018-03-12 14:31:22 -04:00
parent dd31ae832d
commit cced6ec03a
17 changed files with 133 additions and 25 deletions

View File

@ -83,6 +83,10 @@
<p>Improve code documentation in <code>config</code> module.</p> <p>Improve code documentation in <code>config</code> module.</p>
</release-item> </release-item>
<release-item>
<p>Add <code>ASSERT_DEBUG()</code> macro for debugging and replace all current <code>assert()</code> calls except in tests that can't use the debug code.</p>
</release-item>
<release-item> <release-item>
<release-item-contributor-list> <release-item-contributor-list>
<release-item-contributor id="shang.cynthia"/> <release-item-contributor id="shang.cynthia"/>

View File

@ -1,22 +1,28 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Common Command Routines Common Command Routines
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
#include <string.h> #include <string.h>
#include "common/debug.h"
#include "common/log.h" #include "common/log.h"
#include "common/memContext.h" #include "common/memContext.h"
#include "config/config.h" #include "config/config.h"
#include "version.h" #include "version.h"
/***********************************************************************************************************************************
Debug Asserts
***********************************************************************************************************************************/
// The command must be set
#define ASSERT_DEBUG_COMMAND_SET() \
ASSERT_DEBUG(cfgCommand() != cfgCmdNone)
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Begin the command Begin the command
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
void void
cmdBegin() cmdBegin()
{ {
// A command must be set ASSERT_DEBUG_COMMAND_SET();
assert(cfgCommand() != cfgCmdNone);
// This is fairly expensive log message to generate so skip it if it won't be output // This is fairly expensive log message to generate so skip it if it won't be output
if (logWill(cfgLogLevelDefault())) if (logWill(cfgLogLevelDefault()))
@ -112,8 +118,7 @@ End the command
void void
cmdEnd(int code) cmdEnd(int code)
{ {
// A command must be set ASSERT_DEBUG_COMMAND_SET();
assert(cfgCommand() != cfgCmdNone);
// Skip this log message if it won't be output. It's not too expensive but since we skipped cmdBegin(), may as well. // Skip this log message if it won't be output. It's not too expensive but since we skipped cmdBegin(), may as well.
if (logWill(cfgLogLevelDefault())) if (logWill(cfgLogLevelDefault()))

29
src/common/debug.h Normal file
View File

@ -0,0 +1,29 @@
/***********************************************************************************************************************************
Debug Routines
***********************************************************************************************************************************/
#ifndef COMMON_DEBUG_H
#define COMMON_DEBUG_H
#include "common/log.h"
/***********************************************************************************************************************************
NDEBUG indicates to C library routines that debugging is off -- set a more readable flag to use when debugging is on
***********************************************************************************************************************************/
#ifndef NDEBUG
#define DEBUG
#endif
/***********************************************************************************************************************************
Assert Macros
***********************************************************************************************************************************/
#ifdef DEBUG
#define ASSERT_DEBUG(condition) \
{ \
if (!(condition)) \
THROW(AssertError, "assertion '%s' failed", #condition); \
}
#else
#define ASSERT_DEBUG(condition)
#endif
#endif

View File

@ -1,7 +1,6 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Log Handler Log Handler
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
@ -10,6 +9,7 @@ Log Handler
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "common/debug.h"
#include "common/error.h" #include "common/error.h"
#include "common/log.h" #include "common/log.h"
#include "common/time.h" #include "common/time.h"
@ -36,10 +36,8 @@ bool logTimestamp = false;
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Debug Asserts Debug Asserts
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#define ASSERT_MESSAGE_LOG_LEVEL_VALID(logLevel) \ #define ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel) \
{ \ ASSERT_DEBUG(logLevel > logLevelOff)
assert(logLevel > logLevelOff); \
}
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Log buffer Log buffer
@ -143,28 +141,28 @@ This is useful for log messages that are expensive to generate and should be ski
static bool static bool
logWillFile(LogLevel logLevel) logWillFile(LogLevel logLevel)
{ {
ASSERT_MESSAGE_LOG_LEVEL_VALID(logLevel) ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
return logLevel <= logLevelFile && logHandleFile != -1; return logLevel <= logLevelFile && logHandleFile != -1;
} }
static bool static bool
logWillStdErr(LogLevel logLevel) logWillStdErr(LogLevel logLevel)
{ {
ASSERT_MESSAGE_LOG_LEVEL_VALID(logLevel) ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
return logLevel <= logLevelStdErr; return logLevel <= logLevelStdErr;
} }
static bool static bool
logWillStdOut(LogLevel logLevel) logWillStdOut(LogLevel logLevel)
{ {
ASSERT_MESSAGE_LOG_LEVEL_VALID(logLevel) ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
return logLevel <= logLevelStdOut; return logLevel <= logLevelStdOut;
} }
bool bool
logWill(LogLevel logLevel) logWill(LogLevel logLevel)
{ {
ASSERT_MESSAGE_LOG_LEVEL_VALID(logLevel) ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
return logWillStdOut(logLevel) || logWillStdErr(logLevel) || logWillFile(logLevel); return logWillStdOut(logLevel) || logWillStdErr(logLevel) || logWillFile(logLevel);
} }
@ -174,7 +172,7 @@ General log function
void void
logInternal(LogLevel logLevel, const char *fileName, const char *functionName, int code, const char *format, ...) logInternal(LogLevel logLevel, const char *fileName, const char *functionName, int code, const char *format, ...)
{ {
ASSERT_MESSAGE_LOG_LEVEL_VALID(logLevel) ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
size_t bufferPos = 0; // Current position in the buffer size_t bufferPos = 0; // Current position in the buffer
@ -197,7 +195,7 @@ logInternal(LogLevel logLevel, const char *fileName, const char *functionName, i
size_t messageStdErrPos = bufferPos - strlen(logLevelStr(logLevel)) - 2; size_t messageStdErrPos = bufferPos - strlen(logLevelStr(logLevel)) - 2;
// Check that error code matches log level // Check that error code matches log level
assert( ASSERT_DEBUG(
code == 0 || (logLevel == logLevelError && code != errorTypeCode(&AssertError)) || code == 0 || (logLevel == logLevelError && code != errorTypeCode(&AssertError)) ||
(logLevel == logLevelAssert && code == errorTypeCode(&AssertError))); (logLevel == logLevelAssert && code == errorTypeCode(&AssertError)));

View File

@ -59,6 +59,8 @@ Only call logInternal() if the message will be logged to one of the available ou
logInternal(logLevel, __FILE__, __func__, code, __VA_ARGS__); \ logInternal(logLevel, __FILE__, __func__, code, __VA_ARGS__); \
} }
#define LOG_ASSERT(...) \
LOG_ANY(logLevelAssert, errorTypeCode(&AssertError), __VA_ARGS__)
#define LOG_ERROR(code, ...) \ #define LOG_ERROR(code, ...) \
LOG_ANY(logLevelError, code, __VA_ARGS__) LOG_ANY(logLevelError, code, __VA_ARGS__)
#define LOG_INFO(...) \ #define LOG_INFO(...) \

View File

@ -1,9 +1,9 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Command and Option Configuration Command and Option Configuration
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
#include <string.h> #include <string.h>
#include "common/debug.h"
#include "common/error.h" #include "common/error.h"
#include "common/memContext.h" #include "common/memContext.h"
#include "config/config.h" #include "config/config.h"
@ -60,6 +60,13 @@ Include the automatically generated configuration data
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include "config.auto.c" #include "config.auto.c"
/***********************************************************************************************************************************
Debug Asserts
***********************************************************************************************************************************/
// The command must be set
#define ASSERT_DEBUG_COMMAND_SET() \
ASSERT_DEBUG(cfgCommand() != cfgCmdNone)
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Store the config memory context Store the config memory context
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
@ -273,7 +280,7 @@ Does this command log to a file?
bool bool
cfgLogFile() cfgLogFile()
{ {
assert(cfgCommand() != cfgCmdNone); ASSERT_DEBUG_COMMAND_SET();
return configCommandData[cfgCommand()].logFile; return configCommandData[cfgCommand()].logFile;
} }
@ -283,7 +290,7 @@ Get default log level -- used for log messages that are common to all commands
LogLevel LogLevel
cfgLogLevelDefault() cfgLogLevelDefault()
{ {
assert(cfgCommand() != cfgCmdNone); ASSERT_DEBUG_COMMAND_SET();
return (LogLevel)configCommandData[cfgCommand()].logLevelDefault; return (LogLevel)configCommandData[cfgCommand()].logLevelDefault;
} }

View File

@ -1,11 +1,11 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Command and Option Parse Command and Option Parse
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
#include <getopt.h> #include <getopt.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include "common/debug.h"
#include "common/error.h" #include "common/error.h"
#include "common/ini.h" #include "common/ini.h"
#include "common/log.h" #include "common/log.h"
@ -165,7 +165,7 @@ configParse(unsigned int argListSize, const char *argList[])
reset = option & PARSE_RESET_FLAG; reset = option & PARSE_RESET_FLAG;
// Make sure the option id is valid // Make sure the option id is valid
assert(optionId < CFG_OPTION_TOTAL); ASSERT_DEBUG(optionId < CFG_OPTION_TOTAL);
// If the the option has not been found yet then set it // If the the option has not been found yet then set it
if (!parseOptionList[optionId].found) if (!parseOptionList[optionId].found)

View File

@ -155,6 +155,27 @@ my $oTestDef =
'common/log' => TESTDEF_COVERAGE_FULL, 'common/log' => TESTDEF_COVERAGE_FULL,
}, },
}, },
{
&TESTDEF_NAME => 'debug-on',
&TESTDEF_TOTAL => 1,
&TESTDEF_C => true,
&TESTDEF_COVERAGE =>
{
'common/debug' => TESTDEF_COVERAGE_NOCODE,
},
},
{
&TESTDEF_NAME => 'debug-off',
&TESTDEF_TOTAL => 1,
&TESTDEF_C => true,
&TESTDEF_CDEF => '-DNDEBUG -DNO_LOG',
&TESTDEF_COVERAGE =>
{
'common/debug' => TESTDEF_COVERAGE_NOCODE,
},
},
{ {
&TESTDEF_NAME => 'exit', &TESTDEF_NAME => 'exit',
&TESTDEF_TOTAL => 1, &TESTDEF_TOTAL => 1,

View File

@ -1,7 +1,6 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
C Test Harness C Test Harness
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@ -10,6 +10,8 @@ Log Test Harness
#include "common/type.h" #include "common/type.h"
#include "storage/helper.h" #include "storage/helper.h"
#ifndef NO_LOG
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Name of file where logs are stored for testing Name of file where logs are stored for testing
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
@ -81,3 +83,5 @@ testLogFinal()
if (!strEqZ(actual, "")) if (!strEqZ(actual, ""))
THROW(AssertError, "\n\nexpected error log to be empty but actual error log was:\n\n%s\n\n", strPtr(actual)); THROW(AssertError, "\n\nexpected error log to be empty but actual error log was:\n\n%s\n\n", strPtr(actual));
} }
#endif

View File

@ -7,9 +7,11 @@ Log Test Harness
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Functions Functions
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#ifndef NO_LOG
void testLogInit(); void testLogInit();
void testLogResult(const char *expected); void testLogResult(const char *expected);
void testLogErrResult(const char *expected); void testLogErrResult(const char *expected);
void testLogFinal(); void testLogFinal();
#endif
#endif #endif

View File

@ -0,0 +1,17 @@
/***********************************************************************************************************************************
Test Debug Macros and Routines when Disabled
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun()
{
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("ASSERT_DEBUG()"))
{
TEST_RESULT_VOID(ASSERT_DEBUG(true), "assert true ignored");
TEST_RESULT_VOID(ASSERT_DEBUG(false || false), "assert false ignored");
}
}

View File

@ -0,0 +1,17 @@
/***********************************************************************************************************************************
Test Debug Macros and Routines
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun()
{
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("ASSERT_DEBUG()"))
{
TEST_RESULT_VOID(ASSERT_DEBUG(true), "assert true");
TEST_ERROR(ASSERT_DEBUG(false || false), AssertError, "assertion 'false || false' failed");
}
}

View File

@ -1,6 +1,7 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Test Error Handling Test Error Handling
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
/*********************************************************************************************************************************** /***********************************************************************************************************************************
testTryRecurse - test to blow up try stack testTryRecurse - test to blow up try stack

View File

@ -1,6 +1,8 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Test Types Test Types
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
void void
testRun() testRun()
{ {

View File

@ -1,6 +1,7 @@
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Test Page Checksums Test Page Checksums
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include "common/debug.h"
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Page data for testing -- use 8192 for page size since this is the most common value Page data for testing -- use 8192 for page size since this is the most common value
@ -26,7 +27,7 @@ testRun()
// ----------------------------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("pageChecksum()")) if (testBegin("pageChecksum()"))
{ {
// Checksum for 0x00 fill, page 0x00 // Checksum for 0x00 fill, page 0x00
memset(testPage(0), 0, TEST_PAGE_SIZE); memset(testPage(0), 0, TEST_PAGE_SIZE);
TEST_RESULT_U16_HEX(pageChecksum(testPage(0), 0, TEST_PAGE_SIZE), 0xC6AA, "check for 0x00 filled page, block 0"); TEST_RESULT_U16_HEX(pageChecksum(testPage(0), 0, TEST_PAGE_SIZE), 0xC6AA, "check for 0x00 filled page, block 0");
@ -102,7 +103,7 @@ testRun()
// Break the checksum for a page and make sure it is found // Break the checksum for a page and make sure it is found
unsigned int pageInvalid = 7; unsigned int pageInvalid = 7;
assert(pageInvalid < TEST_PAGE_TOTAL); ASSERT_DEBUG(pageInvalid < TEST_PAGE_TOTAL);
((PageHeader)testPage(pageInvalid))->pd_checksum = 0xEEEE; ((PageHeader)testPage(pageInvalid))->pd_checksum = 0xEEEE;
TEST_RESULT_BOOL( TEST_RESULT_BOOL(

View File

@ -3,7 +3,6 @@ C Test Wrapper
This wrapper runs the the C unit tests. This wrapper runs the the C unit tests.
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>