1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Move (almost all) malloc failure test logic from fault.c to test_malloc.c. (CVS 5253)

FossilOrigin-Name: 4ae21e3419ad7e69dd735ca45fdc5a2de93d1840
This commit is contained in:
danielk1977
2008-06-20 11:05:37 +00:00
parent af83758645
commit ef05f2dfe3
6 changed files with 233 additions and 239 deletions

View File

@@ -13,7 +13,7 @@
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.26 2008/06/19 18:17:50 danielk1977 Exp $
** $Id: test_malloc.c,v 1.27 2008/06/20 11:05:38 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -21,6 +21,192 @@
#include <string.h>
#include <assert.h>
/*
** This structure is used to encapsulate the global state variables used
** by malloc() fault simulation.
*/
static struct MemFault {
int iCountdown; /* Number of pending successes before a failure */
int nRepeat; /* Number of times to repeat the failure */
int nBenign; /* Number of benign failures seen since last config */
int nFail; /* Number of failures seen since last config */
u8 enable; /* True if enabled */
int isInstalled; /* True if the fault simulation layer is installed */
sqlite3_mem_methods m; /* 'Real' malloc implementation */
} memfault;
/*
** This routine exists as a place to set a breakpoint that will
** fire on any simulated malloc() failure.
*/
static void sqlite3Fault(void){
static int cnt = 0;
cnt++;
}
/*
** Check to see if a fault should be simulated. Return true to simulate
** the fault. Return false if the fault should not be simulated.
*/
static int faultsimStep(){
if( likely(!memfault.enable) ){
return 0;
}
if( memfault.iCountdown>0 ){
memfault.iCountdown--;
return 0;
}
sqlite3Fault();
memfault.nFail++;
if( sqlite3FaultIsBenign()>0 ){
memfault.nBenign++;
}
memfault.nRepeat--;
if( memfault.nRepeat<=0 ){
memfault.enable = 0;
}
return 1;
}
/*
** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation
** logic.
*/
static void *faultsimMalloc(int n){
void *p = 0;
if( !faultsimStep() ){
p = memfault.m.xMalloc(n);
}
return p;
}
/*
** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation
** logic.
*/
static void *faultsimRealloc(void *pOld, int n){
void *p = 0;
if( !faultsimStep() ){
p = memfault.m.xRealloc(pOld, n);
}
return p;
}
/*
** The following method calls are passed directly through to the underlying
** malloc system:
**
** xFree
** xSize
** xRoundup
** xInit
** xShutdown
*/
static void faultsimFree(void *p){
memfault.m.xFree(p);
}
static int faultsimSize(void *p){
return memfault.m.xSize(p);
}
static int faultsimRoundup(int n){
return memfault.m.xRoundup(n);
}
static int faultsimInit(void *p){
return memfault.m.xInit(memfault.m.pAppData);
}
static void faultsimShutdown(void *p){
memfault.m.xShutdown(memfault.m.pAppData);
}
/*
** This routine configures the malloc failure simulation. After
** calling this routine, the next nDelay mallocs will succeed, followed
** by a block of nRepeat failures, after which malloc() calls will begin
** to succeed again.
*/
static void faultsimConfig(int nDelay, int nRepeat){
memfault.iCountdown = nDelay;
memfault.nRepeat = nRepeat;
memfault.nBenign = 0;
memfault.nFail = 0;
memfault.enable = nDelay>=0;
}
/*
** Return the number of faults (both hard and benign faults) that have
** occurred since the injector was last configured.
*/
static int faultsimFailures(void){
return memfault.nFail;
}
/*
** Return the number of benign faults that have occurred since the
** injector was last configured.
*/
static int faultsimBenignFailures(void){
return memfault.nBenign;
}
/*
** Return the number of successes that will occur before the next failure.
** If no failures are scheduled, return -1.
*/
static int faultsimPending(void){
if( memfault.enable ){
return memfault.iCountdown;
}else{
return -1;
}
}
/*
** Add or remove the fault-simulation layer using sqlite3_config(). If
** the argument is non-zero, the
*/
static int faultsimInstall(int install){
static struct sqlite3_mem_methods m = {
faultsimMalloc, /* xMalloc */
faultsimFree, /* xFree */
faultsimRealloc, /* xRealloc */
faultsimSize, /* xSize */
faultsimRoundup, /* xRoundup */
faultsimInit, /* xInit */
faultsimShutdown, /* xShutdown */
0 /* pAppData */
};
int rc;
install = (install ? 1 : 0);
assert(memfault.isInstalled==1 || memfault.isInstalled==0);
if( install==memfault.isInstalled ){
return SQLITE_ERROR;
}
rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
assert(memfault.m.xMalloc);
if( rc==SQLITE_OK ){
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
}
if( rc==SQLITE_OK ){
memfault.isInstalled = 1;
}
return rc;
}
#ifdef SQLITE_TEST
/*
** This function is implemented in test1.c. Returns a pointer to a static
** buffer containing the symbolic SQLite error code that corresponds to
** the least-significant 8-bits of the integer passed as an argument.
** For example:
**
** sqlite3TestErrorName(1) -> "SQLITE_ERROR"
*/
const char *sqlite3TestErrorName(int);
/*
@@ -130,7 +316,6 @@ static int test_realloc(
return TCL_OK;
}
/*
** Usage: sqlite3_free PRIOR
**
@@ -439,13 +624,10 @@ static int test_memdebug_fail(
}
}
sqlite3_test_control(-12345); /* Just to stress the test_control interface */
nBenign = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES,
SQLITE_FAULTINJECTOR_MALLOC);
nFail = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_FAILURES,
SQLITE_FAULTINJECTOR_MALLOC);
sqlite3_test_control(SQLITE_TESTCTRL_FAULT_CONFIG,
SQLITE_FAULTINJECTOR_MALLOC, iFail, nRepeat);
nBenign = faultsimBenignFailures();
nFail = faultsimFailures();
faultsimConfig(iFail, nRepeat);
if( pBenignCnt ){
Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
}
@@ -471,8 +653,7 @@ static int test_memdebug_pending(
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
nPending = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_PENDING,
SQLITE_FAULTINJECTOR_MALLOC);
nPending = faultsimPending();
Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
return TCL_OK;
}
@@ -801,7 +982,7 @@ static int test_install_malloc_faultsim(
if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
return TCL_ERROR;
}
rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, isInstall);
rc = faultsimInstall(isInstall);
Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
return TCL_OK;
}
@@ -840,3 +1021,4 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
}
return TCL_OK;
}
#endif