You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-07-03 00:26:59 +02:00
Use __noreturn_ on error functions when coverage testing.
The errorInternalThrowSys*() functions were marked as returning during coverage testing even when they had no possibility to return, i.e. the error parameter was set to constant true. This meant the compiler would treat the functions as returning even when they would not. Instead create completely separate functions for coverage to use for THROW_ON_SYS_ERROR*() that can return and leave the regular functions marked __noreturn__.
This commit is contained in:
@ -41,6 +41,14 @@
|
|||||||
|
|
||||||
<p>Split session functionality of <code>SocketClient</code> out into <code>SocketSession</code>.</p>
|
<p>Split session functionality of <code>SocketClient</code> out into <code>SocketSession</code>.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<release-item-contributor-list>
|
||||||
|
<release-item-reviewer id="cynthia.shang"/>
|
||||||
|
</release-item-contributor-list>
|
||||||
|
|
||||||
|
<p>Use <code>__noreturn_</code> on error functions when coverage testing.</p>
|
||||||
|
</release-item>
|
||||||
</release-development-list>
|
</release-development-list>
|
||||||
</release-core-list>
|
</release-core-list>
|
||||||
</release>
|
</release>
|
||||||
|
@ -386,16 +386,8 @@ errorInternalThrowFmt(
|
|||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
void
|
void
|
||||||
errorInternalThrowSys(
|
errorInternalThrowSys(
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
bool error,
|
|
||||||
#endif
|
|
||||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Format message with system message appended
|
// Format message with system message appended
|
||||||
if (errNo == 0)
|
if (errNo == 0)
|
||||||
{
|
{
|
||||||
@ -406,24 +398,23 @@ errorInternalThrowSys(
|
|||||||
snprintf(messageBufferTemp, ERROR_MESSAGE_BUFFER_SIZE - 1, "%s: [%d] %s", message, errNo, strerror(errNo));
|
snprintf(messageBufferTemp, ERROR_MESSAGE_BUFFER_SIZE - 1, "%s: [%d] %s", message, errNo, strerror(errNo));
|
||||||
|
|
||||||
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_COVERAGE
|
#ifdef DEBUG_COVERAGE
|
||||||
}
|
void
|
||||||
#endif
|
errorInternalThrowOnSys(
|
||||||
|
bool error, int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine,
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
errorInternalThrowSys(errNo, errorType, fileName, functionName, fileLine, message);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
errorInternalThrowSysFmt(
|
errorInternalThrowSysFmt(
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
bool error,
|
|
||||||
#endif
|
|
||||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Format message
|
// Format message
|
||||||
va_list argument;
|
va_list argument;
|
||||||
va_start(argument, format);
|
va_start(argument, format);
|
||||||
@ -435,8 +426,30 @@ errorInternalThrowSysFmt(
|
|||||||
snprintf(messageBufferTemp + messageSize, ERROR_MESSAGE_BUFFER_SIZE - 1 - messageSize, ": [%d] %s", errNo, strerror(errNo));
|
snprintf(messageBufferTemp + messageSize, ERROR_MESSAGE_BUFFER_SIZE - 1 - messageSize, ": [%d] %s", errNo, strerror(errNo));
|
||||||
|
|
||||||
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_COVERAGE
|
#ifdef DEBUG_COVERAGE
|
||||||
|
void
|
||||||
|
errorInternalThrowOnSysFmt(
|
||||||
|
bool error, int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
// Format message
|
||||||
|
va_list argument;
|
||||||
|
va_start(argument, format);
|
||||||
|
size_t messageSize = (size_t)vsnprintf(messageBufferTemp, ERROR_MESSAGE_BUFFER_SIZE - 1, format, argument);
|
||||||
|
va_end(argument);
|
||||||
|
|
||||||
|
// Append the system message
|
||||||
|
if (errNo != 0)
|
||||||
|
{
|
||||||
|
snprintf(
|
||||||
|
messageBufferTemp + messageSize, ERROR_MESSAGE_BUFFER_SIZE - 1 - messageSize, ": [%d] %s", errNo, strerror(errNo));
|
||||||
|
}
|
||||||
|
|
||||||
|
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -175,18 +175,28 @@ The seldom used "THROWP" variants allow an error to be thrown with a pointer to
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Throw an error when a system call fails
|
Throw an error when a system call fails
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
// When coverage testing define special versions of the macros that don't contain branches. These macros are less efficient because
|
#define THROW_SYS_ERROR(errorType, message) \
|
||||||
// they need to call errorInternalThrowSys*() before determining if there is an error or not, but they allow coverage testing for
|
errorInternalThrowSys(errno, &errorType, __FILE__, __func__, __LINE__, message)
|
||||||
|
#define THROW_SYS_ERROR_FMT(errorType, ...) \
|
||||||
|
errorInternalThrowSysFmt(errno, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||||
|
#define THROWP_SYS_ERROR(errorType, message) \
|
||||||
|
errorInternalThrowSys(errno, errorType, __FILE__, __func__, __LINE__, message)
|
||||||
|
#define THROWP_SYS_ERROR_FMT(errorType, ...) \
|
||||||
|
errorInternalThrowSysFmt(errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define THROW_SYS_ERROR_CODE(errNo, errorType, message) \
|
||||||
|
errorInternalThrowSys(errNo, &errorType, __FILE__, __func__, __LINE__, message)
|
||||||
|
#define THROW_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
||||||
|
errorInternalThrowSysFmt(errNo, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||||
|
#define THROWP_SYS_ERROR_CODE(errNo, errorType, message) \
|
||||||
|
errorInternalThrowSys(errNo, errorType, __FILE__, __func__, __LINE__, message)
|
||||||
|
#define THROWP_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
||||||
|
errorInternalThrowSysFmt(errNo, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
|
// When coverage testing, define special versions of the macros that don't contain branches. These macros are less efficient because
|
||||||
|
// they need to call errorInternalThrowOnSys*() before determining if there is an error or not, but they allow coverage testing for
|
||||||
// THROW*_ON*() calls that contain conditionals.
|
// THROW*_ON*() calls that contain conditionals.
|
||||||
#ifdef DEBUG_COVERAGE
|
#ifdef DEBUG_COVERAGE
|
||||||
#define THROW_SYS_ERROR(errorType, message) \
|
|
||||||
errorInternalThrowSys(true, errno, &errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROW_SYS_ERROR_FMT(errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(true, errno, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
#define THROWP_SYS_ERROR(errorType, message) \
|
|
||||||
errorInternalThrowSys(true, errno, errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROWP_SYS_ERROR_FMT(errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(true, errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
|
|
||||||
// The expression can't be passed directly to errorInternalThrowSys*() because we need to be sure it is evaluated before passing
|
// The expression can't be passed directly to errorInternalThrowSys*() because we need to be sure it is evaluated before passing
|
||||||
// errno. Depending on optimization that might not happen.
|
// errno. Depending on optimization that might not happen.
|
||||||
@ -194,50 +204,32 @@ Throw an error when a system call fails
|
|||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
bool error = expression; \
|
bool error = expression; \
|
||||||
errorInternalThrowSys(error, errno, &errorType, __FILE__, __func__, __LINE__, message); \
|
errorInternalThrowOnSys(error, errno, &errorType, __FILE__, __func__, __LINE__, message); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define THROW_ON_SYS_ERROR_FMT(expression, errorType, ...) \
|
#define THROW_ON_SYS_ERROR_FMT(expression, errorType, ...) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
bool error = expression; \
|
bool error = expression; \
|
||||||
errorInternalThrowSysFmt(error, errno, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__); \
|
errorInternalThrowOnSysFmt(error, errno, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define THROWP_ON_SYS_ERROR(expression, errorType, message) \
|
#define THROWP_ON_SYS_ERROR(expression, errorType, message) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
bool error = expression; \
|
bool error = expression; \
|
||||||
errorInternalThrowSys(error, errno, errorType, __FILE__, __func__, __LINE__, message); \
|
errorInternalThrowOnSys(error, errno, errorType, __FILE__, __func__, __LINE__, message); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define THROWP_ON_SYS_ERROR_FMT(expression, errorType, ...) \
|
#define THROWP_ON_SYS_ERROR_FMT(expression, errorType, ...) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
bool error = expression; \
|
bool error = expression; \
|
||||||
errorInternalThrowSysFmt(error, errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__); \
|
errorInternalThrowOnSysFmt(error, errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define THROW_SYS_ERROR_CODE(errNo, errorType, message) \
|
|
||||||
errorInternalThrowSys(true, errNo, &errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROW_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(true, errNo, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
#define THROWP_SYS_ERROR_CODE(errNo, errorType, message) \
|
|
||||||
errorInternalThrowSys(true, errNo, errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROWP_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(true, errNo, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
|
|
||||||
// Else define the normal macros which check for an error first
|
// Else define the normal macros which check for an error first
|
||||||
#else
|
#else
|
||||||
#define THROW_SYS_ERROR(errorType, message) \
|
|
||||||
errorInternalThrowSys(errno, &errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROW_SYS_ERROR_FMT(errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(errno, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
#define THROWP_SYS_ERROR(errorType, message) \
|
|
||||||
errorInternalThrowSys(errno, errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROWP_SYS_ERROR_FMT(errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
|
|
||||||
#define THROW_ON_SYS_ERROR(expression, errorType, message) \
|
#define THROW_ON_SYS_ERROR(expression, errorType, message) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
@ -265,15 +257,6 @@ Throw an error when a system call fails
|
|||||||
if (expression) \
|
if (expression) \
|
||||||
errorInternalThrowSysFmt(errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__); \
|
errorInternalThrowSysFmt(errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define THROW_SYS_ERROR_CODE(errNo, errorType, message) \
|
|
||||||
errorInternalThrowSys(errNo, &errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROW_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(errNo, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
#define THROWP_SYS_ERROR_CODE(errNo, errorType, message) \
|
|
||||||
errorInternalThrowSys(errNo, errorType, __FILE__, __func__, __LINE__, message)
|
|
||||||
#define THROWP_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
|
||||||
errorInternalThrowSysFmt(errNo, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
@ -318,25 +301,23 @@ void errorInternalThrowFmt(
|
|||||||
|
|
||||||
// Throw a system error
|
// Throw a system error
|
||||||
void errorInternalThrowSys(
|
void errorInternalThrowSys(
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
bool error,
|
|
||||||
#endif
|
|
||||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
;
|
|
||||||
#else
|
|
||||||
__attribute__((__noreturn__));
|
__attribute__((__noreturn__));
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// Throw a formatted system error
|
||||||
void errorInternalThrowSysFmt(
|
void errorInternalThrowSysFmt(
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
bool error,
|
|
||||||
#endif
|
|
||||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
||||||
#ifdef DEBUG_COVERAGE
|
|
||||||
__attribute__((format(printf, 7, 8)));
|
|
||||||
#else
|
|
||||||
__attribute__((format(printf, 6, 7))) __attribute__((__noreturn__));
|
__attribute__((format(printf, 6, 7))) __attribute__((__noreturn__));
|
||||||
|
|
||||||
|
// Versions of the above for coverage testing which checks the error condition inside the function
|
||||||
|
#ifdef DEBUG_COVERAGE
|
||||||
|
void errorInternalThrowOnSys(
|
||||||
|
bool error, int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine,
|
||||||
|
const char *message);
|
||||||
|
|
||||||
|
void errorInternalThrowOnSysFmt(
|
||||||
|
bool error, int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine,
|
||||||
|
const char *format, ...) __attribute__((format(printf, 7, 8)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
|
@ -261,7 +261,7 @@ testRun(void)
|
|||||||
TRY_BEGIN()
|
TRY_BEGIN()
|
||||||
{
|
{
|
||||||
errno = E2BIG;
|
errno = E2BIG;
|
||||||
THROW_SYS_ERROR(AssertError, "message");
|
THROW_ON_SYS_ERROR(true, AssertError, "message");
|
||||||
}
|
}
|
||||||
CATCH_ANY()
|
CATCH_ANY()
|
||||||
{
|
{
|
||||||
@ -271,6 +271,34 @@ testRun(void)
|
|||||||
}
|
}
|
||||||
TRY_END();
|
TRY_END();
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
TRY_BEGIN()
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
THROW_ON_SYS_ERROR_FMT(true, AssertError, "message %d", 77);
|
||||||
|
}
|
||||||
|
CATCH_ANY()
|
||||||
|
{
|
||||||
|
printf("%s\n", errorMessage());
|
||||||
|
assert(errorCode() == AssertError.code);
|
||||||
|
assert(strcmp(errorMessage(), "message 77") == 0);
|
||||||
|
}
|
||||||
|
TRY_END();
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
TRY_BEGIN()
|
||||||
|
{
|
||||||
|
errno = E2BIG;
|
||||||
|
THROW_ON_SYS_ERROR_FMT(true, AssertError, "message %d", 77);
|
||||||
|
}
|
||||||
|
CATCH_ANY()
|
||||||
|
{
|
||||||
|
printf("%s\n", errorMessage());
|
||||||
|
assert(errorCode() == AssertError.code);
|
||||||
|
assert(strcmp(errorMessage(), "message 77: [7] Argument list too long") == 0);
|
||||||
|
}
|
||||||
|
TRY_END();
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
TRY_BEGIN()
|
TRY_BEGIN()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user