/* ** 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.6 2007/08/29 12:31:28 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include #include #include /* ** 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( 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>= 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 ** -benigncnt ** ** Arrange for a simulated malloc() failure after COUNTER successes. ** If REPEAT is 1 then all subsequent malloc()s fail. If REPEAT is ** 0 then only a single failure occurs. ** ** Each call to this routine overrides the prior counter value. ** This routine returns the number of simulated failures that have ** happened since the previous call to this routine. ** ** To disable simulated failures, use a COUNTER of -1. */ static int test_memdebug_fail( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int ii; int iFail; int iRepeat = -1; int iBenignCnt; Tcl_Obj *pBenignCnt = 0; int nFail = 0; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR; for(ii=2; ii1 && strncmp(zOption, "-repeat", nOption)==0 ){ if( ii==(objc-1) ){ zErr = "option requires an argument: "; }else{ if( Tcl_GetIntFromObj(interp, objv[ii+1], &iRepeat) ){ return TCL_ERROR; } } }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){ if( ii==(objc-1) ){ zErr = "option requires an argument: "; }else{ pBenignCnt = objv[ii+1]; } }else{ zErr = "unknown option: "; } if( zErr ){ Tcl_AppendResult(interp, zErr, zOption, 0); return TCL_ERROR; } } #ifdef SQLITE_MEMDEBUG { extern int sqlite3_memdebug_fail(int,int,int*); nFail = sqlite3_memdebug_fail(iFail, iRepeat, &iBenignCnt); if( pBenignCnt ){ Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(iBenignCnt), 0); } } #endif Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); return TCL_OK; } /* ** Usage: sqlite3_memdebug_settitle TITLE ** ** Set a title string stored with each allocation. The TITLE is ** typically the name of the test that was running when the ** allocation occurred. The TITLE is stored with the allocation ** and can be used to figure out which tests are leaking memory. ** ** Each title overwrite the previous. */ static int test_memdebug_settitle( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ const char *zTitle; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); return TCL_ERROR; } zTitle = Tcl_GetString(objv[1]); #ifdef SQLITE_MEMDEBUG { extern int sqlite3_memdebug_settitle(const char*); sqlite3_memdebug_settitle(zTitle); } #endif return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest_malloc_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aObjCmd[] = { { "sqlite3_malloc", test_malloc }, { "sqlite3_realloc", test_realloc }, { "sqlite3_free", test_free }, { "sqlite3_memory_used", test_memory_used }, { "sqlite3_memory_highwater", test_memory_highwater }, { "sqlite3_memdebug_backtrace", test_memdebug_backtrace }, { "sqlite3_memdebug_dump", test_memdebug_dump }, { "sqlite3_memdebug_fail", test_memdebug_fail }, { "sqlite3_memdebug_settitle", test_memdebug_settitle }, }; int i; for(i=0; i