12f999a67Sdrh /* 22f999a67Sdrh ** 2007 August 15 32f999a67Sdrh ** 42f999a67Sdrh ** The author disclaims copyright to this source code. In place of 52f999a67Sdrh ** a legal notice, here is a blessing: 62f999a67Sdrh ** 72f999a67Sdrh ** May you do good and not evil. 82f999a67Sdrh ** May you find forgiveness for yourself and forgive others. 92f999a67Sdrh ** May you share freely, never taking more than you give. 102f999a67Sdrh ** 112f999a67Sdrh ************************************************************************* 122f999a67Sdrh ** 132f999a67Sdrh ** This file contains code used to implement test interfaces to the 142f999a67Sdrh ** memory allocation subsystem. 152f999a67Sdrh */ 162f999a67Sdrh #include "sqliteInt.h" 1752b1dbb5Smistachkin #if defined(INCLUDE_SQLITE_TCL_H) 1852b1dbb5Smistachkin # include "sqlite_tcl.h" 1952b1dbb5Smistachkin #else 202f999a67Sdrh # include "tcl.h" 2152b1dbb5Smistachkin #endif 222f999a67Sdrh #include <stdlib.h> 232f999a67Sdrh #include <string.h> 242f999a67Sdrh #include <assert.h> 252f999a67Sdrh 26ef05f2dfSdanielk1977 /* 27ef05f2dfSdanielk1977 ** This structure is used to encapsulate the global state variables used 28ef05f2dfSdanielk1977 ** by malloc() fault simulation. 29ef05f2dfSdanielk1977 */ 30ef05f2dfSdanielk1977 static struct MemFault { 31ef05f2dfSdanielk1977 int iCountdown; /* Number of pending successes before a failure */ 32ef05f2dfSdanielk1977 int nRepeat; /* Number of times to repeat the failure */ 33ef05f2dfSdanielk1977 int nBenign; /* Number of benign failures seen since last config */ 34ef05f2dfSdanielk1977 int nFail; /* Number of failures seen since last config */ 35*b9cd2c45Sdrh int nOkBefore; /* Successful allocations prior to the first fault */ 36*b9cd2c45Sdrh int nOkAfter; /* Successful allocations after a fault */ 37ef05f2dfSdanielk1977 u8 enable; /* True if enabled */ 38ef05f2dfSdanielk1977 int isInstalled; /* True if the fault simulation layer is installed */ 392d1d86fbSdanielk1977 int isBenignMode; /* True if malloc failures are considered benign */ 40ef05f2dfSdanielk1977 sqlite3_mem_methods m; /* 'Real' malloc implementation */ 41ef05f2dfSdanielk1977 } memfault; 42ef05f2dfSdanielk1977 43ef05f2dfSdanielk1977 /* 44ef05f2dfSdanielk1977 ** This routine exists as a place to set a breakpoint that will 45ef05f2dfSdanielk1977 ** fire on any simulated malloc() failure. 46ef05f2dfSdanielk1977 */ 47ef05f2dfSdanielk1977 static void sqlite3Fault(void){ 48ef05f2dfSdanielk1977 static int cnt = 0; 49ef05f2dfSdanielk1977 cnt++; 50ef05f2dfSdanielk1977 } 51ef05f2dfSdanielk1977 52ef05f2dfSdanielk1977 /* 53*b9cd2c45Sdrh ** This routine exists as a place to set a breakpoint that will 54*b9cd2c45Sdrh ** fire the first time any malloc() fails on a single test case. 55*b9cd2c45Sdrh ** The sqlite3Fault() routine above runs on every malloc() failure. 56*b9cd2c45Sdrh ** This routine only runs on the first such failure. 57*b9cd2c45Sdrh */ 58*b9cd2c45Sdrh static void sqlite3FirstFault(void){ 59*b9cd2c45Sdrh static int cnt2 = 0; 60*b9cd2c45Sdrh cnt2++; 61*b9cd2c45Sdrh } 62*b9cd2c45Sdrh 63*b9cd2c45Sdrh /* 64ef05f2dfSdanielk1977 ** Check to see if a fault should be simulated. Return true to simulate 65ef05f2dfSdanielk1977 ** the fault. Return false if the fault should not be simulated. 66ef05f2dfSdanielk1977 */ 6764aca191Sdanielk1977 static int faultsimStep(void){ 68ef05f2dfSdanielk1977 if( likely(!memfault.enable) ){ 69*b9cd2c45Sdrh memfault.nOkAfter++; 70ef05f2dfSdanielk1977 return 0; 71ef05f2dfSdanielk1977 } 72ef05f2dfSdanielk1977 if( memfault.iCountdown>0 ){ 73ef05f2dfSdanielk1977 memfault.iCountdown--; 74*b9cd2c45Sdrh memfault.nOkBefore++; 75ef05f2dfSdanielk1977 return 0; 76ef05f2dfSdanielk1977 } 77*b9cd2c45Sdrh if( memfault.nFail==0 ) sqlite3FirstFault(); 78ef05f2dfSdanielk1977 sqlite3Fault(); 79ef05f2dfSdanielk1977 memfault.nFail++; 802d1d86fbSdanielk1977 if( memfault.isBenignMode>0 ){ 81ef05f2dfSdanielk1977 memfault.nBenign++; 82ef05f2dfSdanielk1977 } 83ef05f2dfSdanielk1977 memfault.nRepeat--; 84ef05f2dfSdanielk1977 if( memfault.nRepeat<=0 ){ 85ef05f2dfSdanielk1977 memfault.enable = 0; 86ef05f2dfSdanielk1977 } 87ef05f2dfSdanielk1977 return 1; 88ef05f2dfSdanielk1977 } 89ef05f2dfSdanielk1977 90ef05f2dfSdanielk1977 /* 91ef05f2dfSdanielk1977 ** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation 92ef05f2dfSdanielk1977 ** logic. 93ef05f2dfSdanielk1977 */ 94ef05f2dfSdanielk1977 static void *faultsimMalloc(int n){ 95ef05f2dfSdanielk1977 void *p = 0; 96ef05f2dfSdanielk1977 if( !faultsimStep() ){ 97ef05f2dfSdanielk1977 p = memfault.m.xMalloc(n); 98ef05f2dfSdanielk1977 } 99ef05f2dfSdanielk1977 return p; 100ef05f2dfSdanielk1977 } 101ef05f2dfSdanielk1977 102ef05f2dfSdanielk1977 103ef05f2dfSdanielk1977 /* 104ef05f2dfSdanielk1977 ** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation 105ef05f2dfSdanielk1977 ** logic. 106ef05f2dfSdanielk1977 */ 107ef05f2dfSdanielk1977 static void *faultsimRealloc(void *pOld, int n){ 108ef05f2dfSdanielk1977 void *p = 0; 109ef05f2dfSdanielk1977 if( !faultsimStep() ){ 110ef05f2dfSdanielk1977 p = memfault.m.xRealloc(pOld, n); 111ef05f2dfSdanielk1977 } 112ef05f2dfSdanielk1977 return p; 113ef05f2dfSdanielk1977 } 114ef05f2dfSdanielk1977 115ef05f2dfSdanielk1977 /* 116ef05f2dfSdanielk1977 ** The following method calls are passed directly through to the underlying 117ef05f2dfSdanielk1977 ** malloc system: 118ef05f2dfSdanielk1977 ** 119ef05f2dfSdanielk1977 ** xFree 120ef05f2dfSdanielk1977 ** xSize 121ef05f2dfSdanielk1977 ** xRoundup 122ef05f2dfSdanielk1977 ** xInit 123ef05f2dfSdanielk1977 ** xShutdown 124ef05f2dfSdanielk1977 */ 125ef05f2dfSdanielk1977 static void faultsimFree(void *p){ 126ef05f2dfSdanielk1977 memfault.m.xFree(p); 127ef05f2dfSdanielk1977 } 128ef05f2dfSdanielk1977 static int faultsimSize(void *p){ 129ef05f2dfSdanielk1977 return memfault.m.xSize(p); 130ef05f2dfSdanielk1977 } 131ef05f2dfSdanielk1977 static int faultsimRoundup(int n){ 132ef05f2dfSdanielk1977 return memfault.m.xRoundup(n); 133ef05f2dfSdanielk1977 } 134ef05f2dfSdanielk1977 static int faultsimInit(void *p){ 135ef05f2dfSdanielk1977 return memfault.m.xInit(memfault.m.pAppData); 136ef05f2dfSdanielk1977 } 137ef05f2dfSdanielk1977 static void faultsimShutdown(void *p){ 138ef05f2dfSdanielk1977 memfault.m.xShutdown(memfault.m.pAppData); 139ef05f2dfSdanielk1977 } 140ef05f2dfSdanielk1977 141ef05f2dfSdanielk1977 /* 142ef05f2dfSdanielk1977 ** This routine configures the malloc failure simulation. After 143ef05f2dfSdanielk1977 ** calling this routine, the next nDelay mallocs will succeed, followed 144ef05f2dfSdanielk1977 ** by a block of nRepeat failures, after which malloc() calls will begin 145ef05f2dfSdanielk1977 ** to succeed again. 146ef05f2dfSdanielk1977 */ 147ef05f2dfSdanielk1977 static void faultsimConfig(int nDelay, int nRepeat){ 148ef05f2dfSdanielk1977 memfault.iCountdown = nDelay; 149ef05f2dfSdanielk1977 memfault.nRepeat = nRepeat; 150ef05f2dfSdanielk1977 memfault.nBenign = 0; 151ef05f2dfSdanielk1977 memfault.nFail = 0; 152*b9cd2c45Sdrh memfault.nOkBefore = 0; 153*b9cd2c45Sdrh memfault.nOkAfter = 0; 154ef05f2dfSdanielk1977 memfault.enable = nDelay>=0; 155b48c1f19Sdanielk1977 156b48c1f19Sdanielk1977 /* Sometimes, when running multi-threaded tests, the isBenignMode 157b48c1f19Sdanielk1977 ** variable is not properly incremented/decremented so that it is 158b48c1f19Sdanielk1977 ** 0 when not inside a benign malloc block. This doesn't affect 159b48c1f19Sdanielk1977 ** the multi-threaded tests, as they do not use this system. But 160b48c1f19Sdanielk1977 ** it does affect OOM tests run later in the same process. So 161b48c1f19Sdanielk1977 ** zero the variable here, just to be sure. 162b48c1f19Sdanielk1977 */ 163b48c1f19Sdanielk1977 memfault.isBenignMode = 0; 164ef05f2dfSdanielk1977 } 165ef05f2dfSdanielk1977 166ef05f2dfSdanielk1977 /* 167ef05f2dfSdanielk1977 ** Return the number of faults (both hard and benign faults) that have 168ef05f2dfSdanielk1977 ** occurred since the injector was last configured. 169ef05f2dfSdanielk1977 */ 170ef05f2dfSdanielk1977 static int faultsimFailures(void){ 171ef05f2dfSdanielk1977 return memfault.nFail; 172ef05f2dfSdanielk1977 } 173ef05f2dfSdanielk1977 174ef05f2dfSdanielk1977 /* 175ef05f2dfSdanielk1977 ** Return the number of benign faults that have occurred since the 176ef05f2dfSdanielk1977 ** injector was last configured. 177ef05f2dfSdanielk1977 */ 178ef05f2dfSdanielk1977 static int faultsimBenignFailures(void){ 179ef05f2dfSdanielk1977 return memfault.nBenign; 180ef05f2dfSdanielk1977 } 181ef05f2dfSdanielk1977 182ef05f2dfSdanielk1977 /* 183ef05f2dfSdanielk1977 ** Return the number of successes that will occur before the next failure. 184ef05f2dfSdanielk1977 ** If no failures are scheduled, return -1. 185ef05f2dfSdanielk1977 */ 186ef05f2dfSdanielk1977 static int faultsimPending(void){ 187ef05f2dfSdanielk1977 if( memfault.enable ){ 188ef05f2dfSdanielk1977 return memfault.iCountdown; 189ef05f2dfSdanielk1977 }else{ 190ef05f2dfSdanielk1977 return -1; 191ef05f2dfSdanielk1977 } 192ef05f2dfSdanielk1977 } 193ef05f2dfSdanielk1977 1942d1d86fbSdanielk1977 1952d1d86fbSdanielk1977 static void faultsimBeginBenign(void){ 1962d1d86fbSdanielk1977 memfault.isBenignMode++; 1972d1d86fbSdanielk1977 } 1982d1d86fbSdanielk1977 static void faultsimEndBenign(void){ 1992d1d86fbSdanielk1977 memfault.isBenignMode--; 2002d1d86fbSdanielk1977 } 2012d1d86fbSdanielk1977 202ef05f2dfSdanielk1977 /* 203ef05f2dfSdanielk1977 ** Add or remove the fault-simulation layer using sqlite3_config(). If 204ef05f2dfSdanielk1977 ** the argument is non-zero, the 205ef05f2dfSdanielk1977 */ 206ef05f2dfSdanielk1977 static int faultsimInstall(int install){ 207ef05f2dfSdanielk1977 static struct sqlite3_mem_methods m = { 208ef05f2dfSdanielk1977 faultsimMalloc, /* xMalloc */ 209ef05f2dfSdanielk1977 faultsimFree, /* xFree */ 210ef05f2dfSdanielk1977 faultsimRealloc, /* xRealloc */ 211ef05f2dfSdanielk1977 faultsimSize, /* xSize */ 212ef05f2dfSdanielk1977 faultsimRoundup, /* xRoundup */ 213ef05f2dfSdanielk1977 faultsimInit, /* xInit */ 214ef05f2dfSdanielk1977 faultsimShutdown, /* xShutdown */ 215ef05f2dfSdanielk1977 0 /* pAppData */ 216ef05f2dfSdanielk1977 }; 217ef05f2dfSdanielk1977 int rc; 218ef05f2dfSdanielk1977 219ef05f2dfSdanielk1977 install = (install ? 1 : 0); 220ef05f2dfSdanielk1977 assert(memfault.isInstalled==1 || memfault.isInstalled==0); 221ef05f2dfSdanielk1977 222ef05f2dfSdanielk1977 if( install==memfault.isInstalled ){ 223ef05f2dfSdanielk1977 return SQLITE_ERROR; 224ef05f2dfSdanielk1977 } 225ef05f2dfSdanielk1977 2262d1d86fbSdanielk1977 if( install ){ 227ef05f2dfSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m); 228ef05f2dfSdanielk1977 assert(memfault.m.xMalloc); 229ef05f2dfSdanielk1977 if( rc==SQLITE_OK ){ 230ef05f2dfSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m); 231ef05f2dfSdanielk1977 } 2322d1d86fbSdanielk1977 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 2332d1d86fbSdanielk1977 faultsimBeginBenign, faultsimEndBenign 2342d1d86fbSdanielk1977 ); 2352d1d86fbSdanielk1977 }else{ 2368e18922fSmistachkin sqlite3_mem_methods m2; 2372d1d86fbSdanielk1977 assert(memfault.m.xMalloc); 2381b67f3caSdrh 2391b67f3caSdrh /* One should be able to reset the default memory allocator by storing 2401b67f3caSdrh ** a zeroed allocator then calling GETMALLOC. */ 2418e18922fSmistachkin memset(&m2, 0, sizeof(m2)); 2428e18922fSmistachkin sqlite3_config(SQLITE_CONFIG_MALLOC, &m2); 2438e18922fSmistachkin sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2); 2448e18922fSmistachkin assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 ); 2451b67f3caSdrh 2462d1d86fbSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m); 247d797a9b5Sdrh sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 248d797a9b5Sdrh (void*)0, (void*)0); 2492d1d86fbSdanielk1977 } 250ef05f2dfSdanielk1977 251ef05f2dfSdanielk1977 if( rc==SQLITE_OK ){ 252ef05f2dfSdanielk1977 memfault.isInstalled = 1; 253ef05f2dfSdanielk1977 } 254ef05f2dfSdanielk1977 return rc; 255ef05f2dfSdanielk1977 } 256ef05f2dfSdanielk1977 257ef05f2dfSdanielk1977 #ifdef SQLITE_TEST 258ef05f2dfSdanielk1977 259ef05f2dfSdanielk1977 /* 260e84d8d32Smistachkin ** This function is implemented in main.c. Returns a pointer to a static 261ef05f2dfSdanielk1977 ** buffer containing the symbolic SQLite error code that corresponds to 262ef05f2dfSdanielk1977 ** the least-significant 8-bits of the integer passed as an argument. 263ef05f2dfSdanielk1977 ** For example: 264ef05f2dfSdanielk1977 ** 265e84d8d32Smistachkin ** sqlite3ErrName(1) -> "SQLITE_ERROR" 266ef05f2dfSdanielk1977 */ 267e84d8d32Smistachkin extern const char *sqlite3ErrName(int); 268d09414cdSdanielk1977 2692f999a67Sdrh /* 2702f999a67Sdrh ** Transform pointers to text and back again 2712f999a67Sdrh */ 2722f999a67Sdrh static void pointerToText(void *p, char *z){ 2732f999a67Sdrh static const char zHex[] = "0123456789abcdef"; 2742f999a67Sdrh int i, k; 2754a50aac5Sdrh unsigned int u; 2764a50aac5Sdrh sqlite3_uint64 n; 2778a42cbd3Sdrh if( p==0 ){ 2788a42cbd3Sdrh strcpy(z, "0"); 2798a42cbd3Sdrh return; 2808a42cbd3Sdrh } 2814a50aac5Sdrh if( sizeof(n)==sizeof(p) ){ 2824a50aac5Sdrh memcpy(&n, &p, sizeof(p)); 2834a50aac5Sdrh }else if( sizeof(u)==sizeof(p) ){ 2844a50aac5Sdrh memcpy(&u, &p, sizeof(u)); 2854a50aac5Sdrh n = u; 2864a50aac5Sdrh }else{ 2874a50aac5Sdrh assert( 0 ); 2884a50aac5Sdrh } 2892f999a67Sdrh for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){ 2902f999a67Sdrh z[k] = zHex[n&0xf]; 2912f999a67Sdrh n >>= 4; 2922f999a67Sdrh } 2932f999a67Sdrh z[sizeof(p)*2] = 0; 2942f999a67Sdrh } 2952f999a67Sdrh static int hexToInt(int h){ 2962f999a67Sdrh if( h>='0' && h<='9' ){ 2972f999a67Sdrh return h - '0'; 2982f999a67Sdrh }else if( h>='a' && h<='f' ){ 2992f999a67Sdrh return h - 'a' + 10; 3002f999a67Sdrh }else{ 3012f999a67Sdrh return -1; 3022f999a67Sdrh } 3032f999a67Sdrh } 3042f999a67Sdrh static int textToPointer(const char *z, void **pp){ 3052f999a67Sdrh sqlite3_uint64 n = 0; 3062f999a67Sdrh int i; 3074a50aac5Sdrh unsigned int u; 3082f999a67Sdrh for(i=0; i<sizeof(void*)*2 && z[0]; i++){ 3092f999a67Sdrh int v; 3102f999a67Sdrh v = hexToInt(*z++); 3112f999a67Sdrh if( v<0 ) return TCL_ERROR; 3122f999a67Sdrh n = n*16 + v; 3132f999a67Sdrh } 3142f999a67Sdrh if( *z!=0 ) return TCL_ERROR; 3154a50aac5Sdrh if( sizeof(n)==sizeof(*pp) ){ 3164a50aac5Sdrh memcpy(pp, &n, sizeof(n)); 3174a50aac5Sdrh }else if( sizeof(u)==sizeof(*pp) ){ 3184a50aac5Sdrh u = (unsigned int)n; 3194a50aac5Sdrh memcpy(pp, &u, sizeof(u)); 3204a50aac5Sdrh }else{ 3214a50aac5Sdrh assert( 0 ); 3224a50aac5Sdrh } 3232f999a67Sdrh return TCL_OK; 3242f999a67Sdrh } 3252f999a67Sdrh 3262f999a67Sdrh /* 3272f999a67Sdrh ** Usage: sqlite3_malloc NBYTES 3282f999a67Sdrh ** 3292f999a67Sdrh ** Raw test interface for sqlite3_malloc(). 3302f999a67Sdrh */ 3317617e4a8Smistachkin static int SQLITE_TCLAPI test_malloc( 3322f999a67Sdrh void * clientData, 3332f999a67Sdrh Tcl_Interp *interp, 3342f999a67Sdrh int objc, 3352f999a67Sdrh Tcl_Obj *CONST objv[] 3362f999a67Sdrh ){ 3372f999a67Sdrh int nByte; 3382f999a67Sdrh void *p; 3392f999a67Sdrh char zOut[100]; 3402f999a67Sdrh if( objc!=2 ){ 3412f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "NBYTES"); 3422f999a67Sdrh return TCL_ERROR; 3432f999a67Sdrh } 3442f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR; 3452f999a67Sdrh p = sqlite3_malloc((unsigned)nByte); 3462f999a67Sdrh pointerToText(p, zOut); 3472f999a67Sdrh Tcl_AppendResult(interp, zOut, NULL); 3482f999a67Sdrh return TCL_OK; 3492f999a67Sdrh } 3502f999a67Sdrh 3512f999a67Sdrh /* 3522f999a67Sdrh ** Usage: sqlite3_realloc PRIOR NBYTES 3532f999a67Sdrh ** 3542f999a67Sdrh ** Raw test interface for sqlite3_realloc(). 3552f999a67Sdrh */ 3567617e4a8Smistachkin static int SQLITE_TCLAPI test_realloc( 3572f999a67Sdrh void * clientData, 3582f999a67Sdrh Tcl_Interp *interp, 3592f999a67Sdrh int objc, 3602f999a67Sdrh Tcl_Obj *CONST objv[] 3612f999a67Sdrh ){ 3622f999a67Sdrh int nByte; 3632f999a67Sdrh void *pPrior, *p; 3642f999a67Sdrh char zOut[100]; 3652f999a67Sdrh if( objc!=3 ){ 3662f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES"); 3672f999a67Sdrh return TCL_ERROR; 3682f999a67Sdrh } 3692f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR; 3702f999a67Sdrh if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ 3712f999a67Sdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 3722f999a67Sdrh return TCL_ERROR; 3732f999a67Sdrh } 3742f999a67Sdrh p = sqlite3_realloc(pPrior, (unsigned)nByte); 3752f999a67Sdrh pointerToText(p, zOut); 3762f999a67Sdrh Tcl_AppendResult(interp, zOut, NULL); 3772f999a67Sdrh return TCL_OK; 3782f999a67Sdrh } 3792f999a67Sdrh 3802f999a67Sdrh /* 3812f999a67Sdrh ** Usage: sqlite3_free PRIOR 3822f999a67Sdrh ** 3832f999a67Sdrh ** Raw test interface for sqlite3_free(). 3842f999a67Sdrh */ 3857617e4a8Smistachkin static int SQLITE_TCLAPI test_free( 3862f999a67Sdrh void * clientData, 3872f999a67Sdrh Tcl_Interp *interp, 3882f999a67Sdrh int objc, 3892f999a67Sdrh Tcl_Obj *CONST objv[] 3902f999a67Sdrh ){ 3912f999a67Sdrh void *pPrior; 3922f999a67Sdrh if( objc!=2 ){ 3932f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PRIOR"); 3942f999a67Sdrh return TCL_ERROR; 3952f999a67Sdrh } 3962f999a67Sdrh if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ 3972f999a67Sdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 3982f999a67Sdrh return TCL_ERROR; 3992f999a67Sdrh } 4002f999a67Sdrh sqlite3_free(pPrior); 4012f999a67Sdrh return TCL_OK; 4022f999a67Sdrh } 4032f999a67Sdrh 4042f999a67Sdrh /* 4059c7a60dfSdrh ** These routines are in test_hexio.c 4069c7a60dfSdrh */ 4079c7a60dfSdrh int sqlite3TestHexToBin(const char *, int, char *); 4089c7a60dfSdrh int sqlite3TestBinToHex(char*,int); 4099c7a60dfSdrh 4109c7a60dfSdrh /* 4119c7a60dfSdrh ** Usage: memset ADDRESS SIZE HEX 4129c7a60dfSdrh ** 4139c7a60dfSdrh ** Set a chunk of memory (obtained from malloc, probably) to a 4149c7a60dfSdrh ** specified hex pattern. 4159c7a60dfSdrh */ 4167617e4a8Smistachkin static int SQLITE_TCLAPI test_memset( 4179c7a60dfSdrh void * clientData, 4189c7a60dfSdrh Tcl_Interp *interp, 4199c7a60dfSdrh int objc, 4209c7a60dfSdrh Tcl_Obj *CONST objv[] 4219c7a60dfSdrh ){ 4229c7a60dfSdrh void *p; 4239c7a60dfSdrh int size, n, i; 4249c7a60dfSdrh char *zHex; 4259c7a60dfSdrh char *zOut; 4269c7a60dfSdrh char zBin[100]; 4279c7a60dfSdrh 4289c7a60dfSdrh if( objc!=4 ){ 4299c7a60dfSdrh Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX"); 4309c7a60dfSdrh return TCL_ERROR; 4319c7a60dfSdrh } 4329c7a60dfSdrh if( textToPointer(Tcl_GetString(objv[1]), &p) ){ 4339c7a60dfSdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 4349c7a60dfSdrh return TCL_ERROR; 4359c7a60dfSdrh } 4369c7a60dfSdrh if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ 4379c7a60dfSdrh return TCL_ERROR; 4389c7a60dfSdrh } 4399c7a60dfSdrh if( size<=0 ){ 4409c7a60dfSdrh Tcl_AppendResult(interp, "size must be positive", (char*)0); 4419c7a60dfSdrh return TCL_ERROR; 4429c7a60dfSdrh } 4439c7a60dfSdrh zHex = Tcl_GetStringFromObj(objv[3], &n); 4449c7a60dfSdrh if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2; 4459c7a60dfSdrh n = sqlite3TestHexToBin(zHex, n, zBin); 4469c7a60dfSdrh if( n==0 ){ 4479c7a60dfSdrh Tcl_AppendResult(interp, "no data", (char*)0); 4489c7a60dfSdrh return TCL_ERROR; 4499c7a60dfSdrh } 4509c7a60dfSdrh zOut = p; 4519c7a60dfSdrh for(i=0; i<size; i++){ 4529c7a60dfSdrh zOut[i] = zBin[i%n]; 4539c7a60dfSdrh } 4549c7a60dfSdrh return TCL_OK; 4559c7a60dfSdrh } 4569c7a60dfSdrh 4579c7a60dfSdrh /* 4589c7a60dfSdrh ** Usage: memget ADDRESS SIZE 4599c7a60dfSdrh ** 4609c7a60dfSdrh ** Return memory as hexadecimal text. 4619c7a60dfSdrh */ 4627617e4a8Smistachkin static int SQLITE_TCLAPI test_memget( 4639c7a60dfSdrh void * clientData, 4649c7a60dfSdrh Tcl_Interp *interp, 4659c7a60dfSdrh int objc, 4669c7a60dfSdrh Tcl_Obj *CONST objv[] 4679c7a60dfSdrh ){ 4689c7a60dfSdrh void *p; 4699c7a60dfSdrh int size, n; 4709c7a60dfSdrh char *zBin; 4719c7a60dfSdrh char zHex[100]; 4729c7a60dfSdrh 4739c7a60dfSdrh if( objc!=3 ){ 4749c7a60dfSdrh Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE"); 4759c7a60dfSdrh return TCL_ERROR; 4769c7a60dfSdrh } 4779c7a60dfSdrh if( textToPointer(Tcl_GetString(objv[1]), &p) ){ 4789c7a60dfSdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); 4799c7a60dfSdrh return TCL_ERROR; 4809c7a60dfSdrh } 4819c7a60dfSdrh if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ 4829c7a60dfSdrh return TCL_ERROR; 4839c7a60dfSdrh } 4849c7a60dfSdrh if( size<=0 ){ 4859c7a60dfSdrh Tcl_AppendResult(interp, "size must be positive", (char*)0); 4869c7a60dfSdrh return TCL_ERROR; 4879c7a60dfSdrh } 4889c7a60dfSdrh zBin = p; 4899c7a60dfSdrh while( size>0 ){ 4909c7a60dfSdrh if( size>(sizeof(zHex)-1)/2 ){ 4919c7a60dfSdrh n = (sizeof(zHex)-1)/2; 4929c7a60dfSdrh }else{ 4939c7a60dfSdrh n = size; 4949c7a60dfSdrh } 4959c7a60dfSdrh memcpy(zHex, zBin, n); 4969c7a60dfSdrh zBin += n; 4979c7a60dfSdrh size -= n; 4989c7a60dfSdrh sqlite3TestBinToHex(zHex, n); 4999c7a60dfSdrh Tcl_AppendResult(interp, zHex, (char*)0); 5009c7a60dfSdrh } 5019c7a60dfSdrh return TCL_OK; 5029c7a60dfSdrh } 5039c7a60dfSdrh 5049c7a60dfSdrh /* 5052f999a67Sdrh ** Usage: sqlite3_memory_used 5062f999a67Sdrh ** 5072f999a67Sdrh ** Raw test interface for sqlite3_memory_used(). 5082f999a67Sdrh */ 5097617e4a8Smistachkin static int SQLITE_TCLAPI test_memory_used( 5102f999a67Sdrh void * clientData, 5112f999a67Sdrh Tcl_Interp *interp, 5122f999a67Sdrh int objc, 5132f999a67Sdrh Tcl_Obj *CONST objv[] 5142f999a67Sdrh ){ 5152f999a67Sdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used())); 5162f999a67Sdrh return TCL_OK; 5172f999a67Sdrh } 5182f999a67Sdrh 5192f999a67Sdrh /* 5202f999a67Sdrh ** Usage: sqlite3_memory_highwater ?RESETFLAG? 5212f999a67Sdrh ** 5222f999a67Sdrh ** Raw test interface for sqlite3_memory_highwater(). 5232f999a67Sdrh */ 5247617e4a8Smistachkin static int SQLITE_TCLAPI test_memory_highwater( 5252f999a67Sdrh void * clientData, 5262f999a67Sdrh Tcl_Interp *interp, 5272f999a67Sdrh int objc, 5282f999a67Sdrh Tcl_Obj *CONST objv[] 5292f999a67Sdrh ){ 5302f999a67Sdrh int resetFlag = 0; 5312f999a67Sdrh if( objc!=1 && objc!=2 ){ 5322f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "?RESET?"); 5332f999a67Sdrh return TCL_ERROR; 5342f999a67Sdrh } 5352f999a67Sdrh if( objc==2 ){ 5362f999a67Sdrh if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR; 5372f999a67Sdrh } 5382f999a67Sdrh Tcl_SetObjResult(interp, 5392f999a67Sdrh Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag))); 5402f999a67Sdrh return TCL_OK; 5412f999a67Sdrh } 5422f999a67Sdrh 5432f999a67Sdrh /* 5442f999a67Sdrh ** Usage: sqlite3_memdebug_backtrace DEPTH 5452f999a67Sdrh ** 5462f999a67Sdrh ** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined 5472f999a67Sdrh ** then this routine is a no-op. 5482f999a67Sdrh */ 5497617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_backtrace( 5502f999a67Sdrh void * clientData, 5512f999a67Sdrh Tcl_Interp *interp, 5522f999a67Sdrh int objc, 5532f999a67Sdrh Tcl_Obj *CONST objv[] 5542f999a67Sdrh ){ 5552f999a67Sdrh int depth; 5562f999a67Sdrh if( objc!=2 ){ 5572f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DEPT"); 5582f999a67Sdrh return TCL_ERROR; 5592f999a67Sdrh } 5602f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR; 5612f999a67Sdrh #ifdef SQLITE_MEMDEBUG 5622f999a67Sdrh { 56349e4fd71Sdrh extern void sqlite3MemdebugBacktrace(int); 56449e4fd71Sdrh sqlite3MemdebugBacktrace(depth); 5652f999a67Sdrh } 5662f999a67Sdrh #endif 5672f999a67Sdrh return TCL_OK; 5682f999a67Sdrh } 5692f999a67Sdrh 5702f999a67Sdrh /* 5712f999a67Sdrh ** Usage: sqlite3_memdebug_dump FILENAME 5722f999a67Sdrh ** 5732f999a67Sdrh ** Write a summary of unfreed memory to FILENAME. 5742f999a67Sdrh */ 5757617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_dump( 5762f999a67Sdrh void * clientData, 5772f999a67Sdrh Tcl_Interp *interp, 5782f999a67Sdrh int objc, 5792f999a67Sdrh Tcl_Obj *CONST objv[] 5802f999a67Sdrh ){ 5812f999a67Sdrh if( objc!=2 ){ 5822f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); 5832f999a67Sdrh return TCL_ERROR; 5842f999a67Sdrh } 5852d7636e2Sdrh #if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \ 5862d7636e2Sdrh || defined(SQLITE_POW2_MEMORY_SIZE) 5872f999a67Sdrh { 58849e4fd71Sdrh extern void sqlite3MemdebugDump(const char*); 58949e4fd71Sdrh sqlite3MemdebugDump(Tcl_GetString(objv[1])); 5902f999a67Sdrh } 5912f999a67Sdrh #endif 5922f999a67Sdrh return TCL_OK; 5932f999a67Sdrh } 5942f999a67Sdrh 595a7a8e14bSdanielk1977 /* 596a7a8e14bSdanielk1977 ** Usage: sqlite3_memdebug_malloc_count 597a7a8e14bSdanielk1977 ** 598a7a8e14bSdanielk1977 ** Return the total number of times malloc() has been called. 599a7a8e14bSdanielk1977 */ 6007617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_malloc_count( 601a7a8e14bSdanielk1977 void * clientData, 602a7a8e14bSdanielk1977 Tcl_Interp *interp, 603a7a8e14bSdanielk1977 int objc, 604a7a8e14bSdanielk1977 Tcl_Obj *CONST objv[] 605a7a8e14bSdanielk1977 ){ 606a7a8e14bSdanielk1977 int nMalloc = -1; 607a7a8e14bSdanielk1977 if( objc!=1 ){ 608a7a8e14bSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, ""); 609a7a8e14bSdanielk1977 return TCL_ERROR; 610a7a8e14bSdanielk1977 } 611a7a8e14bSdanielk1977 #if defined(SQLITE_MEMDEBUG) 612a7a8e14bSdanielk1977 { 61349e4fd71Sdrh extern int sqlite3MemdebugMallocCount(); 61449e4fd71Sdrh nMalloc = sqlite3MemdebugMallocCount(); 615a7a8e14bSdanielk1977 } 616a7a8e14bSdanielk1977 #endif 617a7a8e14bSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc)); 618a7a8e14bSdanielk1977 return TCL_OK; 619a7a8e14bSdanielk1977 } 620a7a8e14bSdanielk1977 6212f999a67Sdrh 6222f999a67Sdrh /* 623a1644fd8Sdanielk1977 ** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS? 624a1644fd8Sdanielk1977 ** 625a1644fd8Sdanielk1977 ** where options are: 626a1644fd8Sdanielk1977 ** 627643167ffSdrh ** -repeat <count> 628a1644fd8Sdanielk1977 ** -benigncnt <varname> 6290e6f1546Sdrh ** 6300e6f1546Sdrh ** Arrange for a simulated malloc() failure after COUNTER successes. 631643167ffSdrh ** If a repeat count is specified, the fault is repeated that many 632643167ffSdrh ** times. 6330e6f1546Sdrh ** 6340e6f1546Sdrh ** Each call to this routine overrides the prior counter value. 6350e6f1546Sdrh ** This routine returns the number of simulated failures that have 6360e6f1546Sdrh ** happened since the previous call to this routine. 6370e6f1546Sdrh ** 6380e6f1546Sdrh ** To disable simulated failures, use a COUNTER of -1. 6390e6f1546Sdrh */ 6407617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_fail( 6410e6f1546Sdrh void * clientData, 6420e6f1546Sdrh Tcl_Interp *interp, 6430e6f1546Sdrh int objc, 6440e6f1546Sdrh Tcl_Obj *CONST objv[] 6450e6f1546Sdrh ){ 646a1644fd8Sdanielk1977 int ii; 6470e6f1546Sdrh int iFail; 648643167ffSdrh int nRepeat = 1; 649a1644fd8Sdanielk1977 Tcl_Obj *pBenignCnt = 0; 650643167ffSdrh int nBenign; 6510e6f1546Sdrh int nFail = 0; 652a1644fd8Sdanielk1977 653a1644fd8Sdanielk1977 if( objc<2 ){ 654a1644fd8Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?"); 6550e6f1546Sdrh return TCL_ERROR; 6560e6f1546Sdrh } 6570e6f1546Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR; 658a1644fd8Sdanielk1977 659a1644fd8Sdanielk1977 for(ii=2; ii<objc; ii+=2){ 660a1644fd8Sdanielk1977 int nOption; 661a1644fd8Sdanielk1977 char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption); 662a1644fd8Sdanielk1977 char *zErr = 0; 663a1644fd8Sdanielk1977 664a1644fd8Sdanielk1977 if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){ 665a1644fd8Sdanielk1977 if( ii==(objc-1) ){ 666a1644fd8Sdanielk1977 zErr = "option requires an argument: "; 667ed138fb3Sdrh }else{ 668643167ffSdrh if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){ 669a1644fd8Sdanielk1977 return TCL_ERROR; 670ed138fb3Sdrh } 671a1644fd8Sdanielk1977 } 672a1644fd8Sdanielk1977 }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){ 673a1644fd8Sdanielk1977 if( ii==(objc-1) ){ 674a1644fd8Sdanielk1977 zErr = "option requires an argument: "; 675a1644fd8Sdanielk1977 }else{ 676a1644fd8Sdanielk1977 pBenignCnt = objv[ii+1]; 677a1644fd8Sdanielk1977 } 678a1644fd8Sdanielk1977 }else{ 679a1644fd8Sdanielk1977 zErr = "unknown option: "; 680a1644fd8Sdanielk1977 } 681a1644fd8Sdanielk1977 682a1644fd8Sdanielk1977 if( zErr ){ 683a1644fd8Sdanielk1977 Tcl_AppendResult(interp, zErr, zOption, 0); 684a1644fd8Sdanielk1977 return TCL_ERROR; 685a1644fd8Sdanielk1977 } 686a1644fd8Sdanielk1977 } 687a1644fd8Sdanielk1977 688ef05f2dfSdanielk1977 nBenign = faultsimBenignFailures(); 689ef05f2dfSdanielk1977 nFail = faultsimFailures(); 690ef05f2dfSdanielk1977 faultsimConfig(iFail, nRepeat); 691ef05f2dfSdanielk1977 692a1644fd8Sdanielk1977 if( pBenignCnt ){ 693643167ffSdrh Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0); 694a1644fd8Sdanielk1977 } 6950e6f1546Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); 6960e6f1546Sdrh return TCL_OK; 6970e6f1546Sdrh } 6980e6f1546Sdrh 699cd03724cSdanielk1977 /* 700cd03724cSdanielk1977 ** Usage: sqlite3_memdebug_pending 701cd03724cSdanielk1977 ** 702cd03724cSdanielk1977 ** Return the number of malloc() calls that will succeed before a 703cd03724cSdanielk1977 ** simulated failure occurs. A negative return value indicates that 704cd03724cSdanielk1977 ** no malloc() failure is scheduled. 705cd03724cSdanielk1977 */ 7067617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_pending( 707cd03724cSdanielk1977 void * clientData, 708cd03724cSdanielk1977 Tcl_Interp *interp, 709cd03724cSdanielk1977 int objc, 710cd03724cSdanielk1977 Tcl_Obj *CONST objv[] 711cd03724cSdanielk1977 ){ 7125efaf070Sdrh int nPending; 713cd03724cSdanielk1977 if( objc!=1 ){ 714cd03724cSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, ""); 715cd03724cSdanielk1977 return TCL_ERROR; 716cd03724cSdanielk1977 } 717ef05f2dfSdanielk1977 nPending = faultsimPending(); 718ed13d98cSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending)); 719cd03724cSdanielk1977 return TCL_OK; 720cd03724cSdanielk1977 } 721cd03724cSdanielk1977 72244ee1dc8Sdrh /* 72344ee1dc8Sdrh ** The following global variable keeps track of the number of tests 72444ee1dc8Sdrh ** that have run. This variable is only useful when running in the 72544ee1dc8Sdrh ** debugger. 72644ee1dc8Sdrh */ 72744ee1dc8Sdrh static int sqlite3_memdebug_title_count = 0; 7280e6f1546Sdrh 7290e6f1546Sdrh /* 7304a50aac5Sdrh ** Usage: sqlite3_memdebug_settitle TITLE 7314a50aac5Sdrh ** 7324a50aac5Sdrh ** Set a title string stored with each allocation. The TITLE is 7334a50aac5Sdrh ** typically the name of the test that was running when the 7344a50aac5Sdrh ** allocation occurred. The TITLE is stored with the allocation 7354a50aac5Sdrh ** and can be used to figure out which tests are leaking memory. 7364a50aac5Sdrh ** 7374a50aac5Sdrh ** Each title overwrite the previous. 7384a50aac5Sdrh */ 7397617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_settitle( 7404a50aac5Sdrh void * clientData, 7414a50aac5Sdrh Tcl_Interp *interp, 7424a50aac5Sdrh int objc, 7434a50aac5Sdrh Tcl_Obj *CONST objv[] 7444a50aac5Sdrh ){ 74544ee1dc8Sdrh sqlite3_memdebug_title_count++; 7464a50aac5Sdrh if( objc!=2 ){ 7474a50aac5Sdrh Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); 7484a50aac5Sdrh return TCL_ERROR; 7494a50aac5Sdrh } 7504a50aac5Sdrh #ifdef SQLITE_MEMDEBUG 7514a50aac5Sdrh { 752caffb1a5Sdrh const char *zTitle; 75349e4fd71Sdrh extern int sqlite3MemdebugSettitle(const char*); 754a359b5eeSmistachkin zTitle = Tcl_GetString(objv[1]); 75549e4fd71Sdrh sqlite3MemdebugSettitle(zTitle); 7564a50aac5Sdrh } 7574a50aac5Sdrh #endif 7584a50aac5Sdrh return TCL_OK; 7594a50aac5Sdrh } 7604a50aac5Sdrh 761cd3e8f7cSdanielk1977 #define MALLOC_LOG_FRAMES 10 762ec561a35Sdan #define MALLOC_LOG_KEYINTS ( \ 763ec561a35Sdan 10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \ 764ec561a35Sdan ) 7656f332c18Sdanielk1977 static Tcl_HashTable aMallocLog; 7666f332c18Sdanielk1977 static int mallocLogEnabled = 0; 7676f332c18Sdanielk1977 7686f332c18Sdanielk1977 typedef struct MallocLog MallocLog; 7696f332c18Sdanielk1977 struct MallocLog { 7706f332c18Sdanielk1977 int nCall; 7716f332c18Sdanielk1977 int nByte; 7726f332c18Sdanielk1977 }; 7736f332c18Sdanielk1977 774afdd23a4Sshane #ifdef SQLITE_MEMDEBUG 7756f332c18Sdanielk1977 static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){ 7766f332c18Sdanielk1977 if( mallocLogEnabled ){ 7776f332c18Sdanielk1977 MallocLog *pLog; 7786f332c18Sdanielk1977 Tcl_HashEntry *pEntry; 7796f332c18Sdanielk1977 int isNew; 7806f332c18Sdanielk1977 781ec561a35Sdan int aKey[MALLOC_LOG_KEYINTS]; 782f6418891Smistachkin unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS; 7836f332c18Sdanielk1977 7846f332c18Sdanielk1977 memset(aKey, 0, nKey); 7856f332c18Sdanielk1977 if( (sizeof(void*)*nFrame)<nKey ){ 7866f332c18Sdanielk1977 nKey = nFrame*sizeof(void*); 7876f332c18Sdanielk1977 } 7886f332c18Sdanielk1977 memcpy(aKey, aFrame, nKey); 7896f332c18Sdanielk1977 7906f332c18Sdanielk1977 pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew); 7916f332c18Sdanielk1977 if( isNew ){ 7926f332c18Sdanielk1977 pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog)); 7936f332c18Sdanielk1977 memset(pLog, 0, sizeof(MallocLog)); 7946f332c18Sdanielk1977 Tcl_SetHashValue(pEntry, (ClientData)pLog); 7956f332c18Sdanielk1977 }else{ 7966f332c18Sdanielk1977 pLog = (MallocLog *)Tcl_GetHashValue(pEntry); 7976f332c18Sdanielk1977 } 7986f332c18Sdanielk1977 7996f332c18Sdanielk1977 pLog->nCall++; 8006f332c18Sdanielk1977 pLog->nByte += nByte; 8016f332c18Sdanielk1977 } 8026f332c18Sdanielk1977 } 803afdd23a4Sshane #endif /* SQLITE_MEMDEBUG */ 8046f332c18Sdanielk1977 80564aca191Sdanielk1977 static void test_memdebug_log_clear(void){ 806dbdc4d49Sdanielk1977 Tcl_HashSearch search; 807dbdc4d49Sdanielk1977 Tcl_HashEntry *pEntry; 808dbdc4d49Sdanielk1977 for( 809dbdc4d49Sdanielk1977 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); 810dbdc4d49Sdanielk1977 pEntry; 811dbdc4d49Sdanielk1977 pEntry=Tcl_NextHashEntry(&search) 812dbdc4d49Sdanielk1977 ){ 813dbdc4d49Sdanielk1977 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); 814dbdc4d49Sdanielk1977 Tcl_Free((char *)pLog); 815dbdc4d49Sdanielk1977 } 816dbdc4d49Sdanielk1977 Tcl_DeleteHashTable(&aMallocLog); 817ec561a35Sdan Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS); 818dbdc4d49Sdanielk1977 } 819dbdc4d49Sdanielk1977 8207617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_log( 8216f332c18Sdanielk1977 void * clientData, 8226f332c18Sdanielk1977 Tcl_Interp *interp, 8236f332c18Sdanielk1977 int objc, 8246f332c18Sdanielk1977 Tcl_Obj *CONST objv[] 8256f332c18Sdanielk1977 ){ 8266f332c18Sdanielk1977 static int isInit = 0; 8276f332c18Sdanielk1977 int iSub; 8286f332c18Sdanielk1977 829dbdc4d49Sdanielk1977 static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" }; 830dbdc4d49Sdanielk1977 enum MB_enum { 831dbdc4d49Sdanielk1977 MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC 832dbdc4d49Sdanielk1977 }; 8336f332c18Sdanielk1977 8346f332c18Sdanielk1977 if( !isInit ){ 8356f332c18Sdanielk1977 #ifdef SQLITE_MEMDEBUG 8366f332c18Sdanielk1977 extern void sqlite3MemdebugBacktraceCallback( 8376f332c18Sdanielk1977 void (*xBacktrace)(int, int, void **)); 8386f332c18Sdanielk1977 sqlite3MemdebugBacktraceCallback(test_memdebug_callback); 8396f332c18Sdanielk1977 #endif 840ec561a35Sdan Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS); 8416f332c18Sdanielk1977 isInit = 1; 8426f332c18Sdanielk1977 } 8436f332c18Sdanielk1977 8446f332c18Sdanielk1977 if( objc<2 ){ 8456f332c18Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); 8466f332c18Sdanielk1977 } 8476f332c18Sdanielk1977 if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){ 8486f332c18Sdanielk1977 return TCL_ERROR; 8496f332c18Sdanielk1977 } 8506f332c18Sdanielk1977 8516f332c18Sdanielk1977 switch( (enum MB_enum)iSub ){ 8526f332c18Sdanielk1977 case MB_LOG_START: 8536f332c18Sdanielk1977 mallocLogEnabled = 1; 8546f332c18Sdanielk1977 break; 8556f332c18Sdanielk1977 case MB_LOG_STOP: 8566f332c18Sdanielk1977 mallocLogEnabled = 0; 8576f332c18Sdanielk1977 break; 8586f332c18Sdanielk1977 case MB_LOG_DUMP: { 8596f332c18Sdanielk1977 Tcl_HashSearch search; 8606f332c18Sdanielk1977 Tcl_HashEntry *pEntry; 8616f332c18Sdanielk1977 Tcl_Obj *pRet = Tcl_NewObj(); 8626f332c18Sdanielk1977 863ec561a35Sdan assert(sizeof(Tcl_WideInt)>=sizeof(void*)); 8646f332c18Sdanielk1977 8656f332c18Sdanielk1977 for( 8666f332c18Sdanielk1977 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); 8676f332c18Sdanielk1977 pEntry; 8686f332c18Sdanielk1977 pEntry=Tcl_NextHashEntry(&search) 8696f332c18Sdanielk1977 ){ 8706f332c18Sdanielk1977 Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2]; 8716f332c18Sdanielk1977 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); 872ec561a35Sdan Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry); 8736f332c18Sdanielk1977 int ii; 8746f332c18Sdanielk1977 8756f332c18Sdanielk1977 apElem[0] = Tcl_NewIntObj(pLog->nCall); 8766f332c18Sdanielk1977 apElem[1] = Tcl_NewIntObj(pLog->nByte); 8776f332c18Sdanielk1977 for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){ 878ec561a35Sdan apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]); 8796f332c18Sdanielk1977 } 8806f332c18Sdanielk1977 8816f332c18Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, 8826f332c18Sdanielk1977 Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem) 8836f332c18Sdanielk1977 ); 8846f332c18Sdanielk1977 } 8856f332c18Sdanielk1977 8866f332c18Sdanielk1977 Tcl_SetObjResult(interp, pRet); 8876f332c18Sdanielk1977 break; 8886f332c18Sdanielk1977 } 8896f332c18Sdanielk1977 case MB_LOG_CLEAR: { 890dbdc4d49Sdanielk1977 test_memdebug_log_clear(); 891dbdc4d49Sdanielk1977 break; 8926f332c18Sdanielk1977 } 893dbdc4d49Sdanielk1977 894dbdc4d49Sdanielk1977 case MB_LOG_SYNC: { 895b940492eSdrh #ifdef SQLITE_MEMDEBUG 896dbdc4d49Sdanielk1977 extern void sqlite3MemdebugSync(); 897dbdc4d49Sdanielk1977 test_memdebug_log_clear(); 898dbdc4d49Sdanielk1977 mallocLogEnabled = 1; 899dbdc4d49Sdanielk1977 sqlite3MemdebugSync(); 900b940492eSdrh #endif 901dbdc4d49Sdanielk1977 break; 9026f332c18Sdanielk1977 } 9036f332c18Sdanielk1977 } 9046f332c18Sdanielk1977 9056f332c18Sdanielk1977 return TCL_OK; 9066f332c18Sdanielk1977 } 9074a50aac5Sdrh 9084a50aac5Sdrh /* 9099ac3fe97Sdrh ** Usage: sqlite3_config_pagecache SIZE N 9109ac3fe97Sdrh ** 9119ac3fe97Sdrh ** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE. 9129ac3fe97Sdrh ** The buffer is static and is of limited size. N might be 91360ec914cSpeter.d.reid ** adjusted downward as needed to accommodate the requested size. 9149ac3fe97Sdrh ** The revised value of N is returned. 9159ac3fe97Sdrh ** 9169ac3fe97Sdrh ** A negative SIZE causes the buffer pointer to be NULL. 9179ac3fe97Sdrh */ 9187617e4a8Smistachkin static int SQLITE_TCLAPI test_config_pagecache( 9199ac3fe97Sdrh void * clientData, 9209ac3fe97Sdrh Tcl_Interp *interp, 9219ac3fe97Sdrh int objc, 9229ac3fe97Sdrh Tcl_Obj *CONST objv[] 9239ac3fe97Sdrh ){ 9246bacdc21Sdrh int sz, N; 92503bc525aSdan Tcl_Obj *pRes; 9265f4bcf15Sdrh static char *buf = 0; 9279ac3fe97Sdrh if( objc!=3 ){ 9289ac3fe97Sdrh Tcl_WrongNumArgs(interp, 1, objv, "SIZE N"); 9299ac3fe97Sdrh return TCL_ERROR; 9309ac3fe97Sdrh } 931f7141990Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; 932f7141990Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR; 9335f4bcf15Sdrh free(buf); 9345f4bcf15Sdrh buf = 0; 93503bc525aSdan 93603bc525aSdan /* Set the return value */ 93703bc525aSdan pRes = Tcl_NewObj(); 93803bc525aSdan Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.szPage)); 93903bc525aSdan Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.nPage)); 94003bc525aSdan Tcl_SetObjResult(interp, pRes); 94103bc525aSdan 94203bc525aSdan if( sz<0 ){ 943a6082f69Sdrh sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, 0); 944f7141990Sdrh }else{ 9450a60a384Sdrh buf = malloc( sz*N ); 9466bacdc21Sdrh sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N); 9479ac3fe97Sdrh } 9489ac3fe97Sdrh return TCL_OK; 9499ac3fe97Sdrh } 9509ac3fe97Sdrh 951f7141990Sdrh /* 952b232c232Sdrh ** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED 953b232c232Sdrh ** 954b232c232Sdrh ** Set up the alternative test page cache. Install if INSTALL_FLAG is 955b232c232Sdrh ** true and uninstall (reverting to the default page cache) if INSTALL_FLAG 956b232c232Sdrh ** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive 957b232c232Sdrh ** which determines the chance of discarding a page when unpinned. 100 958b232c232Sdrh ** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator 959b232c232Sdrh ** seed. 960b232c232Sdrh */ 9617617e4a8Smistachkin static int SQLITE_TCLAPI test_alt_pcache( 962b232c232Sdrh void * clientData, 963b232c232Sdrh Tcl_Interp *interp, 964b232c232Sdrh int objc, 965b232c232Sdrh Tcl_Obj *CONST objv[] 966b232c232Sdrh ){ 967b232c232Sdrh int installFlag; 968f2a84e3cSdrh int discardChance = 0; 969f2a84e3cSdrh int prngSeed = 0; 970f2a84e3cSdrh int highStress = 0; 971f2a84e3cSdrh extern void installTestPCache(int,unsigned,unsigned,unsigned); 972f2a84e3cSdrh if( objc<2 || objc>5 ){ 973f2a84e3cSdrh Tcl_WrongNumArgs(interp, 1, objv, 974f2a84e3cSdrh "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS"); 975b232c232Sdrh return TCL_ERROR; 976b232c232Sdrh } 977b232c232Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR; 978f2a84e3cSdrh if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){ 979f2a84e3cSdrh return TCL_ERROR; 980f2a84e3cSdrh } 981f2a84e3cSdrh if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){ 982f2a84e3cSdrh return TCL_ERROR; 983f2a84e3cSdrh } 984f2a84e3cSdrh if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){ 985f2a84e3cSdrh return TCL_ERROR; 986f2a84e3cSdrh } 987b232c232Sdrh if( discardChance<0 || discardChance>100 ){ 988b232c232Sdrh Tcl_AppendResult(interp, "discard-chance should be between 0 and 100", 989b232c232Sdrh (char*)0); 990b232c232Sdrh return TCL_ERROR; 991b232c232Sdrh } 992f2a84e3cSdrh installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed, 993f2a84e3cSdrh (unsigned)highStress); 994b232c232Sdrh return TCL_OK; 995b232c232Sdrh } 996b232c232Sdrh 997b232c232Sdrh /* 9988a42cbd3Sdrh ** Usage: sqlite3_config_memstatus BOOLEAN 9998a42cbd3Sdrh ** 10008a42cbd3Sdrh ** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS. 10018a42cbd3Sdrh */ 10027617e4a8Smistachkin static int SQLITE_TCLAPI test_config_memstatus( 10038a42cbd3Sdrh void * clientData, 10048a42cbd3Sdrh Tcl_Interp *interp, 10058a42cbd3Sdrh int objc, 10068a42cbd3Sdrh Tcl_Obj *CONST objv[] 10078a42cbd3Sdrh ){ 10088a42cbd3Sdrh int enable, rc; 10098a42cbd3Sdrh if( objc!=2 ){ 10108a42cbd3Sdrh Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); 10118a42cbd3Sdrh return TCL_ERROR; 10128a42cbd3Sdrh } 10138a42cbd3Sdrh if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR; 10148a42cbd3Sdrh rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable); 10158a42cbd3Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 10168a42cbd3Sdrh return TCL_OK; 10178a42cbd3Sdrh } 10188a42cbd3Sdrh 10198a42cbd3Sdrh /* 1020633e6d57Sdrh ** Usage: sqlite3_config_lookaside SIZE COUNT 1021633e6d57Sdrh ** 1022633e6d57Sdrh */ 10237617e4a8Smistachkin static int SQLITE_TCLAPI test_config_lookaside( 1024633e6d57Sdrh void * clientData, 1025633e6d57Sdrh Tcl_Interp *interp, 1026633e6d57Sdrh int objc, 1027633e6d57Sdrh Tcl_Obj *CONST objv[] 1028633e6d57Sdrh ){ 1029633e6d57Sdrh int sz, cnt; 1030ab7bee89Sdanielk1977 Tcl_Obj *pRet; 1031633e6d57Sdrh if( objc!=3 ){ 1032633e6d57Sdrh Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT"); 1033633e6d57Sdrh return TCL_ERROR; 1034633e6d57Sdrh } 1035633e6d57Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; 1036633e6d57Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR; 1037ab7bee89Sdanielk1977 pRet = Tcl_NewObj(); 1038ab7bee89Sdanielk1977 Tcl_ListObjAppendElement( 1039ab7bee89Sdanielk1977 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside) 1040ab7bee89Sdanielk1977 ); 1041ab7bee89Sdanielk1977 Tcl_ListObjAppendElement( 1042ab7bee89Sdanielk1977 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside) 1043ab7bee89Sdanielk1977 ); 1044caffb1a5Sdrh sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt); 1045ab7bee89Sdanielk1977 Tcl_SetObjResult(interp, pRet); 1046633e6d57Sdrh return TCL_OK; 1047633e6d57Sdrh } 1048633e6d57Sdrh 1049633e6d57Sdrh 1050633e6d57Sdrh /* 1051e9d1c720Sdrh ** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT 1052633e6d57Sdrh ** 1053e9d1c720Sdrh ** There are two static buffers with BUFID 1 and 2. Each static buffer 1054e9d1c720Sdrh ** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL 1055e9d1c720Sdrh ** which will cause sqlite3_db_config() to allocate space on its own. 1056633e6d57Sdrh */ 10577617e4a8Smistachkin static int SQLITE_TCLAPI test_db_config_lookaside( 1058633e6d57Sdrh void * clientData, 1059633e6d57Sdrh Tcl_Interp *interp, 1060633e6d57Sdrh int objc, 1061633e6d57Sdrh Tcl_Obj *CONST objv[] 1062633e6d57Sdrh ){ 1063633e6d57Sdrh int rc; 1064633e6d57Sdrh int sz, cnt; 1065633e6d57Sdrh sqlite3 *db; 1066e9d1c720Sdrh int bufid; 1067e9d1c720Sdrh static char azBuf[2][10000]; 1068e84d8d32Smistachkin extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); 1069e9d1c720Sdrh if( objc!=5 ){ 1070e9d1c720Sdrh Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT"); 1071633e6d57Sdrh return TCL_ERROR; 1072633e6d57Sdrh } 1073633e6d57Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1074e9d1c720Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR; 1075e9d1c720Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR; 1076e9d1c720Sdrh if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR; 1077e9d1c720Sdrh if( bufid==0 ){ 1078aed11f20Sdrh rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt); 1079e9d1c720Sdrh }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){ 1080e9d1c720Sdrh rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt); 1081e9d1c720Sdrh }else{ 1082e9d1c720Sdrh Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0); 1083e9d1c720Sdrh return TCL_ERROR; 1084e9d1c720Sdrh } 1085633e6d57Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 1086633e6d57Sdrh return TCL_OK; 1087633e6d57Sdrh } 1088633e6d57Sdrh 1089633e6d57Sdrh /* 10908765b466Smistachkin ** Usage: sqlite3_config_heap NBYTE NMINALLOC 10915099be5eSdanielk1977 */ 10927617e4a8Smistachkin static int SQLITE_TCLAPI test_config_heap( 10935099be5eSdanielk1977 void * clientData, 10945099be5eSdanielk1977 Tcl_Interp *interp, 10955099be5eSdanielk1977 int objc, 10965099be5eSdanielk1977 Tcl_Obj *CONST objv[] 10975099be5eSdanielk1977 ){ 10987830cd41Sdrh static char *zBuf; /* Use this memory */ 10995099be5eSdanielk1977 int nByte; /* Size of buffer to pass to sqlite3_config() */ 11005099be5eSdanielk1977 int nMinAlloc; /* Size of minimum allocation */ 11015099be5eSdanielk1977 int rc; /* Return code of sqlite3_config() */ 11025099be5eSdanielk1977 11035099be5eSdanielk1977 Tcl_Obj * CONST *aArg = &objv[1]; 11045099be5eSdanielk1977 int nArg = objc-1; 11055099be5eSdanielk1977 11065099be5eSdanielk1977 if( nArg!=2 ){ 11078a42cbd3Sdrh Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC"); 11085099be5eSdanielk1977 return TCL_ERROR; 11095099be5eSdanielk1977 } 11105099be5eSdanielk1977 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR; 11115099be5eSdanielk1977 if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR; 11125099be5eSdanielk1977 11130d84e5b2Sdanielk1977 if( nByte==0 ){ 11147830cd41Sdrh free( zBuf ); 11157830cd41Sdrh zBuf = 0; 11168a42cbd3Sdrh rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0); 11170d84e5b2Sdanielk1977 }else{ 11187830cd41Sdrh zBuf = realloc(zBuf, nByte); 11195099be5eSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc); 11200d84e5b2Sdanielk1977 } 11215099be5eSdanielk1977 1122e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 11235099be5eSdanielk1977 return TCL_OK; 11245099be5eSdanielk1977 } 11255099be5eSdanielk1977 11265099be5eSdanielk1977 /* 1127ac1f1045Smistachkin ** Usage: sqlite3_config_heap_size NBYTE 1128ac1f1045Smistachkin */ 11297617e4a8Smistachkin static int SQLITE_TCLAPI test_config_heap_size( 1130ac1f1045Smistachkin void * clientData, 1131ac1f1045Smistachkin Tcl_Interp *interp, 1132ac1f1045Smistachkin int objc, 1133ac1f1045Smistachkin Tcl_Obj *CONST objv[] 1134ac1f1045Smistachkin ){ 1135ac1f1045Smistachkin int nByte; /* Size to pass to sqlite3_config() */ 1136ac1f1045Smistachkin int rc; /* Return code of sqlite3_config() */ 1137ac1f1045Smistachkin 1138ac1f1045Smistachkin Tcl_Obj * CONST *aArg = &objv[1]; 1139ac1f1045Smistachkin int nArg = objc-1; 1140ac1f1045Smistachkin 1141ac1f1045Smistachkin if( nArg!=1 ){ 1142ac1f1045Smistachkin Tcl_WrongNumArgs(interp, 1, objv, "NBYTE"); 1143ac1f1045Smistachkin return TCL_ERROR; 1144ac1f1045Smistachkin } 1145ac1f1045Smistachkin if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR; 1146ac1f1045Smistachkin 1147af8641bdSmistachkin rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte); 1148ac1f1045Smistachkin 1149ac1f1045Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 1150ac1f1045Smistachkin return TCL_OK; 1151ac1f1045Smistachkin } 1152ac1f1045Smistachkin 1153ac1f1045Smistachkin /* 11548765b466Smistachkin ** Usage: sqlite3_config_error [DB] 11556480aad4Sdrh ** 11566480aad4Sdrh ** Invoke sqlite3_config() or sqlite3_db_config() with invalid 11576480aad4Sdrh ** opcodes and verify that they return errors. 11586480aad4Sdrh */ 11597617e4a8Smistachkin static int SQLITE_TCLAPI test_config_error( 11606480aad4Sdrh void * clientData, 11616480aad4Sdrh Tcl_Interp *interp, 11626480aad4Sdrh int objc, 11636480aad4Sdrh Tcl_Obj *CONST objv[] 11646480aad4Sdrh ){ 11656480aad4Sdrh sqlite3 *db; 1166e84d8d32Smistachkin extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); 11676480aad4Sdrh 11686480aad4Sdrh if( objc!=2 && objc!=1 ){ 11696480aad4Sdrh Tcl_WrongNumArgs(interp, 1, objv, "[DB]"); 11706480aad4Sdrh return TCL_ERROR; 11716480aad4Sdrh } 11726480aad4Sdrh if( objc==2 ){ 11736480aad4Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 11746480aad4Sdrh if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){ 11756480aad4Sdrh Tcl_AppendResult(interp, 11766480aad4Sdrh "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR", 11776480aad4Sdrh (char*)0); 11786480aad4Sdrh return TCL_ERROR; 11796480aad4Sdrh } 11806480aad4Sdrh }else{ 11816480aad4Sdrh if( sqlite3_config(99999)!=SQLITE_ERROR ){ 11826480aad4Sdrh Tcl_AppendResult(interp, 11836480aad4Sdrh "sqlite3_config(99999) does not return SQLITE_ERROR", 11846480aad4Sdrh (char*)0); 11856480aad4Sdrh return TCL_ERROR; 11866480aad4Sdrh } 11876480aad4Sdrh } 11886480aad4Sdrh return TCL_OK; 11896480aad4Sdrh } 11906480aad4Sdrh 11916480aad4Sdrh /* 11928765b466Smistachkin ** Usage: sqlite3_config_uri BOOLEAN 1193cd74b611Sdan ** 11948765b466Smistachkin ** Enables or disables interpretation of URI parameters by default using 11958765b466Smistachkin ** SQLITE_CONFIG_URI. 1196cd74b611Sdan */ 11977617e4a8Smistachkin static int SQLITE_TCLAPI test_config_uri( 1198cd74b611Sdan void * clientData, 1199cd74b611Sdan Tcl_Interp *interp, 1200cd74b611Sdan int objc, 1201cd74b611Sdan Tcl_Obj *CONST objv[] 1202cd74b611Sdan ){ 1203cd74b611Sdan int rc; 1204cd74b611Sdan int bOpenUri; 1205cd74b611Sdan 1206cd74b611Sdan if( objc!=2 ){ 1207cd74b611Sdan Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); 1208cd74b611Sdan return TCL_ERROR; 1209cd74b611Sdan } 1210cd74b611Sdan if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){ 1211cd74b611Sdan return TCL_ERROR; 1212cd74b611Sdan } 1213cd74b611Sdan 1214cd74b611Sdan rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri); 1215e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 1216cd74b611Sdan 1217cd74b611Sdan return TCL_OK; 1218cd74b611Sdan } 1219cd74b611Sdan 1220cd74b611Sdan /* 1221de9a7b8aSdrh ** Usage: sqlite3_config_cis BOOLEAN 1222de9a7b8aSdrh ** 1223de9a7b8aSdrh ** Enables or disables the use of the covering-index scan optimization. 1224de9a7b8aSdrh ** SQLITE_CONFIG_COVERING_INDEX_SCAN. 1225de9a7b8aSdrh */ 12267617e4a8Smistachkin static int SQLITE_TCLAPI test_config_cis( 1227de9a7b8aSdrh void * clientData, 1228de9a7b8aSdrh Tcl_Interp *interp, 1229de9a7b8aSdrh int objc, 1230de9a7b8aSdrh Tcl_Obj *CONST objv[] 1231de9a7b8aSdrh ){ 1232de9a7b8aSdrh int rc; 1233de9a7b8aSdrh int bUseCis; 1234de9a7b8aSdrh 1235de9a7b8aSdrh if( objc!=2 ){ 1236de9a7b8aSdrh Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); 1237de9a7b8aSdrh return TCL_ERROR; 1238de9a7b8aSdrh } 1239de9a7b8aSdrh if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){ 1240de9a7b8aSdrh return TCL_ERROR; 1241de9a7b8aSdrh } 1242de9a7b8aSdrh 1243de9a7b8aSdrh rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis); 1244e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 1245de9a7b8aSdrh 1246de9a7b8aSdrh return TCL_OK; 1247de9a7b8aSdrh } 1248de9a7b8aSdrh 12493bd1791dSdrh /* 12503bd1791dSdrh ** Usage: sqlite3_config_pmasz INTEGER 12513bd1791dSdrh ** 12523bd1791dSdrh ** Set the minimum PMA size. 12533bd1791dSdrh */ 12547617e4a8Smistachkin static int SQLITE_TCLAPI test_config_pmasz( 12553bd1791dSdrh void * clientData, 12563bd1791dSdrh Tcl_Interp *interp, 12573bd1791dSdrh int objc, 12583bd1791dSdrh Tcl_Obj *CONST objv[] 12593bd1791dSdrh ){ 12603bd1791dSdrh int rc; 12613bd1791dSdrh int iPmaSz; 12623bd1791dSdrh 12633bd1791dSdrh if( objc!=2 ){ 12643bd1791dSdrh Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); 12653bd1791dSdrh return TCL_ERROR; 12663bd1791dSdrh } 12673bd1791dSdrh if( Tcl_GetIntFromObj(interp, objv[1], &iPmaSz) ){ 12683bd1791dSdrh return TCL_ERROR; 12693bd1791dSdrh } 12703bd1791dSdrh 12713bd1791dSdrh rc = sqlite3_config(SQLITE_CONFIG_PMASZ, iPmaSz); 12723bd1791dSdrh Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 12733bd1791dSdrh 12743bd1791dSdrh return TCL_OK; 12753bd1791dSdrh } 12763bd1791dSdrh 1277578e1ca8Sdan 1278578e1ca8Sdan /* 12798765b466Smistachkin ** Usage: sqlite3_dump_memsys3 FILENAME 1280c66c0e14Sdanielk1977 ** sqlite3_dump_memsys5 FILENAME 128132155ef0Sdanielk1977 ** 128232155ef0Sdanielk1977 ** Write a summary of unfreed memsys3 allocations to FILENAME. 128332155ef0Sdanielk1977 */ 12847617e4a8Smistachkin static int SQLITE_TCLAPI test_dump_memsys3( 128532155ef0Sdanielk1977 void * clientData, 128632155ef0Sdanielk1977 Tcl_Interp *interp, 128732155ef0Sdanielk1977 int objc, 128832155ef0Sdanielk1977 Tcl_Obj *CONST objv[] 128932155ef0Sdanielk1977 ){ 129032155ef0Sdanielk1977 if( objc!=2 ){ 129132155ef0Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); 129232155ef0Sdanielk1977 return TCL_ERROR; 129332155ef0Sdanielk1977 } 1294c66c0e14Sdanielk1977 1295860e332cSdrh switch( SQLITE_PTR_TO_INT(clientData) ){ 12960d84e5b2Sdanielk1977 case 3: { 1297c66c0e14Sdanielk1977 #ifdef SQLITE_ENABLE_MEMSYS3 129832155ef0Sdanielk1977 extern void sqlite3Memsys3Dump(const char*); 129932155ef0Sdanielk1977 sqlite3Memsys3Dump(Tcl_GetString(objv[1])); 1300c66c0e14Sdanielk1977 break; 130132155ef0Sdanielk1977 #endif 1302c66c0e14Sdanielk1977 } 13030d84e5b2Sdanielk1977 case 5: { 1304c66c0e14Sdanielk1977 #ifdef SQLITE_ENABLE_MEMSYS5 1305c66c0e14Sdanielk1977 extern void sqlite3Memsys5Dump(const char*); 1306c66c0e14Sdanielk1977 sqlite3Memsys5Dump(Tcl_GetString(objv[1])); 1307c66c0e14Sdanielk1977 break; 1308c66c0e14Sdanielk1977 #endif 1309c66c0e14Sdanielk1977 } 1310c66c0e14Sdanielk1977 } 131132155ef0Sdanielk1977 return TCL_OK; 131232155ef0Sdanielk1977 } 131332155ef0Sdanielk1977 131432155ef0Sdanielk1977 /* 1315f7141990Sdrh ** Usage: sqlite3_status OPCODE RESETFLAG 1316f7141990Sdrh ** 1317f7141990Sdrh ** Return a list of three elements which are the sqlite3_status() return 1318f7141990Sdrh ** code, the current value, and the high-water mark value. 1319f7141990Sdrh */ 13207617e4a8Smistachkin static int SQLITE_TCLAPI test_status( 1321f7141990Sdrh void * clientData, 1322f7141990Sdrh Tcl_Interp *interp, 1323f7141990Sdrh int objc, 1324f7141990Sdrh Tcl_Obj *CONST objv[] 1325f7141990Sdrh ){ 1326f7141990Sdrh int rc, iValue, mxValue; 13277bb22ac7Smistachkin int i, op = 0, resetFlag; 1328f7141990Sdrh const char *zOpName; 1329f7141990Sdrh static const struct { 1330f7141990Sdrh const char *zName; 1331f7141990Sdrh int op; 1332f7141990Sdrh } aOp[] = { 1333f7141990Sdrh { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED }, 1334e50135e2Sdrh { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE }, 1335f7141990Sdrh { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED }, 1336f7141990Sdrh { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW }, 1337e50135e2Sdrh { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE }, 1338f7141990Sdrh { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED }, 1339f7141990Sdrh { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW }, 1340e50135e2Sdrh { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE }, 1341ec424a5bSdrh { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK }, 1342eafc43b1Sdrh { "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT }, 1343f7141990Sdrh }; 1344f7141990Sdrh Tcl_Obj *pResult; 1345f7141990Sdrh if( objc!=3 ){ 1346f7141990Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG"); 1347f7141990Sdrh return TCL_ERROR; 1348f7141990Sdrh } 1349f7141990Sdrh zOpName = Tcl_GetString(objv[1]); 1350f7141990Sdrh for(i=0; i<ArraySize(aOp); i++){ 1351f7141990Sdrh if( strcmp(aOp[i].zName, zOpName)==0 ){ 1352f7141990Sdrh op = aOp[i].op; 1353f7141990Sdrh break; 1354f7141990Sdrh } 1355f7141990Sdrh } 1356f7141990Sdrh if( i>=ArraySize(aOp) ){ 1357f7141990Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR; 1358f7141990Sdrh } 1359f7141990Sdrh if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR; 1360af005fbcSdrh iValue = 0; 1361af005fbcSdrh mxValue = 0; 1362f7141990Sdrh rc = sqlite3_status(op, &iValue, &mxValue, resetFlag); 1363f7141990Sdrh pResult = Tcl_NewObj(); 1364f7141990Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); 1365f7141990Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue)); 1366f7141990Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue)); 1367f7141990Sdrh Tcl_SetObjResult(interp, pResult); 1368f7141990Sdrh return TCL_OK; 1369f7141990Sdrh } 13709ac3fe97Sdrh 13719ac3fe97Sdrh /* 1372633e6d57Sdrh ** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG 1373633e6d57Sdrh ** 1374633e6d57Sdrh ** Return a list of three elements which are the sqlite3_db_status() return 1375633e6d57Sdrh ** code, the current value, and the high-water mark value. 1376633e6d57Sdrh */ 13777617e4a8Smistachkin static int SQLITE_TCLAPI test_db_status( 1378633e6d57Sdrh void * clientData, 1379633e6d57Sdrh Tcl_Interp *interp, 1380633e6d57Sdrh int objc, 1381633e6d57Sdrh Tcl_Obj *CONST objv[] 1382633e6d57Sdrh ){ 1383633e6d57Sdrh int rc, iValue, mxValue; 13847bb22ac7Smistachkin int i, op = 0, resetFlag; 1385633e6d57Sdrh const char *zOpName; 1386633e6d57Sdrh sqlite3 *db; 1387e84d8d32Smistachkin extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); 1388633e6d57Sdrh static const struct { 1389633e6d57Sdrh const char *zName; 1390633e6d57Sdrh int op; 1391633e6d57Sdrh } aOp[] = { 13922a58e9ccSdrh { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED }, 13932a58e9ccSdrh { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED }, 13942a58e9ccSdrh { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED }, 13952a58e9ccSdrh { "STMT_USED", SQLITE_DBSTATUS_STMT_USED }, 13962a58e9ccSdrh { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT }, 13972a58e9ccSdrh { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, 139858ca31c9Sdan { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, 139958ca31c9Sdan { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT }, 14009ad3ee40Sdrh { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS }, 1401648e2643Sdrh { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE }, 1402272989b4Sdan { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS }, 14039c10608aSdan { "CACHE_USED_SHARED", SQLITE_DBSTATUS_CACHE_USED_SHARED }, 1404ffc78a41Sdrh { "CACHE_SPILL", SQLITE_DBSTATUS_CACHE_SPILL }, 1405633e6d57Sdrh }; 1406633e6d57Sdrh Tcl_Obj *pResult; 1407633e6d57Sdrh if( objc!=4 ){ 140858ca31c9Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG"); 1409633e6d57Sdrh return TCL_ERROR; 1410633e6d57Sdrh } 1411633e6d57Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1412633e6d57Sdrh zOpName = Tcl_GetString(objv[2]); 14132a58e9ccSdrh if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7; 14142a58e9ccSdrh if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9; 1415633e6d57Sdrh for(i=0; i<ArraySize(aOp); i++){ 1416633e6d57Sdrh if( strcmp(aOp[i].zName, zOpName)==0 ){ 1417633e6d57Sdrh op = aOp[i].op; 1418633e6d57Sdrh break; 1419633e6d57Sdrh } 1420633e6d57Sdrh } 1421633e6d57Sdrh if( i>=ArraySize(aOp) ){ 1422633e6d57Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; 1423633e6d57Sdrh } 1424633e6d57Sdrh if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; 1425633e6d57Sdrh iValue = 0; 1426633e6d57Sdrh mxValue = 0; 1427633e6d57Sdrh rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag); 1428633e6d57Sdrh pResult = Tcl_NewObj(); 1429633e6d57Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); 1430633e6d57Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue)); 1431633e6d57Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue)); 1432633e6d57Sdrh Tcl_SetObjResult(interp, pResult); 1433633e6d57Sdrh return TCL_OK; 1434633e6d57Sdrh } 1435633e6d57Sdrh 1436633e6d57Sdrh /* 1437d09414cdSdanielk1977 ** install_malloc_faultsim BOOLEAN 1438d09414cdSdanielk1977 */ 14397617e4a8Smistachkin static int SQLITE_TCLAPI test_install_malloc_faultsim( 1440d09414cdSdanielk1977 void * clientData, 1441d09414cdSdanielk1977 Tcl_Interp *interp, 1442d09414cdSdanielk1977 int objc, 1443d09414cdSdanielk1977 Tcl_Obj *CONST objv[] 1444d09414cdSdanielk1977 ){ 1445d09414cdSdanielk1977 int rc; 1446d09414cdSdanielk1977 int isInstall; 1447d09414cdSdanielk1977 1448d09414cdSdanielk1977 if( objc!=2 ){ 1449d09414cdSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); 1450d09414cdSdanielk1977 return TCL_ERROR; 1451d09414cdSdanielk1977 } 1452d09414cdSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){ 1453d09414cdSdanielk1977 return TCL_ERROR; 1454d09414cdSdanielk1977 } 1455ef05f2dfSdanielk1977 rc = faultsimInstall(isInstall); 1456e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 1457d09414cdSdanielk1977 return TCL_OK; 1458d09414cdSdanielk1977 } 1459d09414cdSdanielk1977 1460d09414cdSdanielk1977 /* 14618b322827Sdanielk1977 ** sqlite3_install_memsys3 14628b322827Sdanielk1977 */ 14637617e4a8Smistachkin static int SQLITE_TCLAPI test_install_memsys3( 14648b322827Sdanielk1977 void * clientData, 14658b322827Sdanielk1977 Tcl_Interp *interp, 14668b322827Sdanielk1977 int objc, 14678b322827Sdanielk1977 Tcl_Obj *CONST objv[] 14688b322827Sdanielk1977 ){ 14698b322827Sdanielk1977 int rc = SQLITE_MISUSE; 14708b322827Sdanielk1977 #ifdef SQLITE_ENABLE_MEMSYS3 14718b322827Sdanielk1977 const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); 14728b322827Sdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetMemsys3()); 14738b322827Sdanielk1977 #endif 1474e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 14758b322827Sdanielk1977 return TCL_OK; 14768b322827Sdanielk1977 } 14778b322827Sdanielk1977 14787617e4a8Smistachkin static int SQLITE_TCLAPI test_vfs_oom_test( 1479c396d4afSdan void * clientData, 1480c396d4afSdan Tcl_Interp *interp, 1481c396d4afSdan int objc, 1482c396d4afSdan Tcl_Obj *CONST objv[] 1483c396d4afSdan ){ 1484c396d4afSdan extern int sqlite3_memdebug_vfs_oom_test; 1485c396d4afSdan if( objc>2 ){ 1486c396d4afSdan Tcl_WrongNumArgs(interp, 1, objv, "?INTEGER?"); 1487c396d4afSdan return TCL_ERROR; 1488c396d4afSdan }else if( objc==2 ){ 1489c396d4afSdan int iNew; 1490c396d4afSdan if( Tcl_GetIntFromObj(interp, objv[1], &iNew) ) return TCL_ERROR; 1491c396d4afSdan sqlite3_memdebug_vfs_oom_test = iNew; 1492c396d4afSdan } 1493c396d4afSdan Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_vfs_oom_test)); 1494c396d4afSdan return TCL_OK; 1495c396d4afSdan } 1496c396d4afSdan 14978b322827Sdanielk1977 /* 14982f999a67Sdrh ** Register commands with the TCL interpreter. 14992f999a67Sdrh */ 15002f999a67Sdrh int Sqlitetest_malloc_Init(Tcl_Interp *interp){ 15012f999a67Sdrh static struct { 15022f999a67Sdrh char *zName; 15032f999a67Sdrh Tcl_ObjCmdProc *xProc; 1504c66c0e14Sdanielk1977 int clientData; 15052f999a67Sdrh } aObjCmd[] = { 15068a42cbd3Sdrh { "sqlite3_malloc", test_malloc ,0 }, 15078a42cbd3Sdrh { "sqlite3_realloc", test_realloc ,0 }, 15088a42cbd3Sdrh { "sqlite3_free", test_free ,0 }, 15098a42cbd3Sdrh { "memset", test_memset ,0 }, 15108a42cbd3Sdrh { "memget", test_memget ,0 }, 15118a42cbd3Sdrh { "sqlite3_memory_used", test_memory_used ,0 }, 15128a42cbd3Sdrh { "sqlite3_memory_highwater", test_memory_highwater ,0 }, 15138a42cbd3Sdrh { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 }, 15148a42cbd3Sdrh { "sqlite3_memdebug_dump", test_memdebug_dump ,0 }, 15158a42cbd3Sdrh { "sqlite3_memdebug_fail", test_memdebug_fail ,0 }, 15168a42cbd3Sdrh { "sqlite3_memdebug_pending", test_memdebug_pending ,0 }, 15178a42cbd3Sdrh { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 }, 15188a42cbd3Sdrh { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 }, 15198a42cbd3Sdrh { "sqlite3_memdebug_log", test_memdebug_log ,0 }, 15208a42cbd3Sdrh { "sqlite3_config_pagecache", test_config_pagecache ,0 }, 1521b232c232Sdrh { "sqlite3_config_alt_pcache", test_alt_pcache ,0 }, 15228a42cbd3Sdrh { "sqlite3_status", test_status ,0 }, 1523633e6d57Sdrh { "sqlite3_db_status", test_db_status ,0 }, 15248a42cbd3Sdrh { "install_malloc_faultsim", test_install_malloc_faultsim ,0 }, 15255099be5eSdanielk1977 { "sqlite3_config_heap", test_config_heap ,0 }, 1526ac1f1045Smistachkin { "sqlite3_config_heap_size", test_config_heap_size ,0 }, 15278a42cbd3Sdrh { "sqlite3_config_memstatus", test_config_memstatus ,0 }, 1528633e6d57Sdrh { "sqlite3_config_lookaside", test_config_lookaside ,0 }, 15296480aad4Sdrh { "sqlite3_config_error", test_config_error ,0 }, 1530cd74b611Sdan { "sqlite3_config_uri", test_config_uri ,0 }, 1531de9a7b8aSdrh { "sqlite3_config_cis", test_config_cis ,0 }, 15323bd1791dSdrh { "sqlite3_config_pmasz", test_config_pmasz ,0 }, 1533633e6d57Sdrh { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 }, 15340d84e5b2Sdanielk1977 { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, 1535b232c232Sdrh { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 }, 15368b322827Sdanielk1977 { "sqlite3_install_memsys3", test_install_memsys3 ,0 }, 1537c396d4afSdan { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 }, 15382f999a67Sdrh }; 15392f999a67Sdrh int i; 15402f999a67Sdrh for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 1541860e332cSdrh ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData); 1542c66c0e14Sdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0); 15432f999a67Sdrh } 15442f999a67Sdrh return TCL_OK; 15452f999a67Sdrh } 1546ef05f2dfSdanielk1977 #endif 1547