📄 test_malloc.c
字号:
/*** 2007 August 15**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.******************************************************************************* This file contains code used to implement test interfaces to the** memory allocation subsystem.**** $Id: test_malloc.c,v 1.47 2008/08/05 17:53:24 drh Exp $*/#include "sqliteInt.h"#include "tcl.h"#include <stdlib.h>#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 */ int isBenignMode; /* True if malloc failures are considered benign */ 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( memfault.isBenignMode>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; }}static void faultsimBeginBenign(void){ memfault.isBenignMode++;}static void faultsimEndBenign(void){ memfault.isBenignMode--;}/*** 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; } if( install ){ rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m); assert(memfault.m.xMalloc); if( rc==SQLITE_OK ){ rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m); } sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, faultsimBeginBenign, faultsimEndBenign ); }else{ assert(memfault.m.xMalloc); rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m); sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0); } 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);/*** Transform pointers to text and back again*/static void pointerToText(void *p, char *z){ static const char zHex[] = "0123456789abcdef"; int i, k; unsigned int u; sqlite3_uint64 n; if( p==0 ){ strcpy(z, "0"); return; } if( sizeof(n)==sizeof(p) ){ memcpy(&n, &p, sizeof(p)); }else if( sizeof(u)==sizeof(p) ){ memcpy(&u, &p, sizeof(u)); n = u; }else{ assert( 0 ); } for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){ z[k] = zHex[n&0xf]; n >>= 4; } z[sizeof(p)*2] = 0;}static int hexToInt(int h){ if( h>='0' && h<='9' ){ return h - '0'; }else if( h>='a' && h<='f' ){ return h - 'a' + 10; }else{ return -1; }}static int textToPointer(const char *z, void **pp){ sqlite3_uint64 n = 0; int i; unsigned int u; for(i=0; i<sizeof(void*)*2 && z[0]; i++){ int v; v = hexToInt(*z++); if( v<0 ) return TCL_ERROR; n = n*16 + v; } if( *z!=0 ) return TCL_ERROR; if( sizeof(n)==sizeof(*pp) ){ memcpy(pp, &n, sizeof(n)); }else if( sizeof(u)==sizeof(*pp) ){ u = (unsigned int)n; memcpy(pp, &u, sizeof(u)); }else{ assert( 0 ); } return TCL_OK;}/*** Usage: sqlite3_malloc NBYTES**** Raw test interface for sqlite3_malloc().*/static int test_malloc( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int nByte; void *p; char zOut[100]; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "NBYTES"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR; p = sqlite3_malloc((unsigned)nByte); pointerToText(p, zOut); Tcl_AppendResult(interp, zOut, NULL); return TCL_OK;}/*** Usage: sqlite3_realloc PRIOR NBYTES**** Raw test interface for sqlite3_realloc().*/static int test_realloc( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ int nByte; void *pPrior, *p; char zOut[100]; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR; if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); return TCL_ERROR; } p = sqlite3_realloc(pPrior, (unsigned)nByte); pointerToText(p, zOut); Tcl_AppendResult(interp, zOut, NULL); return TCL_OK;}/*** Usage: sqlite3_free PRIOR**** Raw test interface for sqlite3_free().*/static int test_free( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ void *pPrior; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "PRIOR"); return TCL_ERROR; } if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); return TCL_ERROR; } sqlite3_free(pPrior); return TCL_OK;}/*** These routines are in test_hexio.c*/int sqlite3TestHexToBin(const char *, int, char *);int sqlite3TestBinToHex(char*,int);/*** Usage: memset ADDRESS SIZE HEX**** Set a chunk of memory (obtained from malloc, probably) to a** specified hex pattern.*/static int test_memset( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ void *p; int size, n, i; char *zHex; char *zOut; char zBin[100]; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX"); return TCL_ERROR; } if( textToPointer(Tcl_GetString(objv[1]), &p) ){ Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ return TCL_ERROR; } if( size<=0 ){ Tcl_AppendResult(interp, "size must be positive", (char*)0); return TCL_ERROR; } zHex = Tcl_GetStringFromObj(objv[3], &n); if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2; n = sqlite3TestHexToBin(zHex, n, zBin); if( n==0 ){ Tcl_AppendResult(interp, "no data", (char*)0); return TCL_ERROR; } zOut = p; for(i=0; i<size; i++){ zOut[i] = zBin[i%n]; } return TCL_OK;}/*** Usage: memget ADDRESS SIZE**** Return memory as hexadecimal text.*/static int test_memget( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){ void *p; int size, n; char *zBin; char zHex[100]; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE"); return TCL_ERROR; } if( textToPointer(Tcl_GetString(objv[1]), &p) ){ Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ return TCL_ERROR; } if( size<=0 ){ Tcl_AppendResult(interp, "size must be positive", (char*)0); return TCL_ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -