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 */
35b9cd2c45Sdrh int nOkBefore; /* Successful allocations prior to the first fault */
36b9cd2c45Sdrh 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 */
sqlite3Fault(void)47ef05f2dfSdanielk1977 static void sqlite3Fault(void){
48ef05f2dfSdanielk1977 static int cnt = 0;
49ef05f2dfSdanielk1977 cnt++;
50ef05f2dfSdanielk1977 }
51ef05f2dfSdanielk1977
52ef05f2dfSdanielk1977 /*
53b9cd2c45Sdrh ** This routine exists as a place to set a breakpoint that will
54b9cd2c45Sdrh ** fire the first time any malloc() fails on a single test case.
55b9cd2c45Sdrh ** The sqlite3Fault() routine above runs on every malloc() failure.
56b9cd2c45Sdrh ** This routine only runs on the first such failure.
57b9cd2c45Sdrh */
sqlite3FirstFault(void)58b9cd2c45Sdrh static void sqlite3FirstFault(void){
59b9cd2c45Sdrh static int cnt2 = 0;
60b9cd2c45Sdrh cnt2++;
61b9cd2c45Sdrh }
62b9cd2c45Sdrh
63b9cd2c45Sdrh /*
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 */
faultsimStep(void)6764aca191Sdanielk1977 static int faultsimStep(void){
68ef05f2dfSdanielk1977 if( likely(!memfault.enable) ){
69b9cd2c45Sdrh memfault.nOkAfter++;
70ef05f2dfSdanielk1977 return 0;
71ef05f2dfSdanielk1977 }
72ef05f2dfSdanielk1977 if( memfault.iCountdown>0 ){
73ef05f2dfSdanielk1977 memfault.iCountdown--;
74b9cd2c45Sdrh memfault.nOkBefore++;
75ef05f2dfSdanielk1977 return 0;
76ef05f2dfSdanielk1977 }
77b9cd2c45Sdrh 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 */
faultsimMalloc(int n)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 */
faultsimRealloc(void * pOld,int n)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 ** This routine configures the malloc failure simulation. After
117ef05f2dfSdanielk1977 ** calling this routine, the next nDelay mallocs will succeed, followed
118ef05f2dfSdanielk1977 ** by a block of nRepeat failures, after which malloc() calls will begin
119ef05f2dfSdanielk1977 ** to succeed again.
120ef05f2dfSdanielk1977 */
faultsimConfig(int nDelay,int nRepeat)121ef05f2dfSdanielk1977 static void faultsimConfig(int nDelay, int nRepeat){
122ef05f2dfSdanielk1977 memfault.iCountdown = nDelay;
123ef05f2dfSdanielk1977 memfault.nRepeat = nRepeat;
124ef05f2dfSdanielk1977 memfault.nBenign = 0;
125ef05f2dfSdanielk1977 memfault.nFail = 0;
126b9cd2c45Sdrh memfault.nOkBefore = 0;
127b9cd2c45Sdrh memfault.nOkAfter = 0;
128ef05f2dfSdanielk1977 memfault.enable = nDelay>=0;
129b48c1f19Sdanielk1977
130b48c1f19Sdanielk1977 /* Sometimes, when running multi-threaded tests, the isBenignMode
131b48c1f19Sdanielk1977 ** variable is not properly incremented/decremented so that it is
132b48c1f19Sdanielk1977 ** 0 when not inside a benign malloc block. This doesn't affect
133b48c1f19Sdanielk1977 ** the multi-threaded tests, as they do not use this system. But
134b48c1f19Sdanielk1977 ** it does affect OOM tests run later in the same process. So
135b48c1f19Sdanielk1977 ** zero the variable here, just to be sure.
136b48c1f19Sdanielk1977 */
137b48c1f19Sdanielk1977 memfault.isBenignMode = 0;
138ef05f2dfSdanielk1977 }
139ef05f2dfSdanielk1977
140ef05f2dfSdanielk1977 /*
141ef05f2dfSdanielk1977 ** Return the number of faults (both hard and benign faults) that have
142ef05f2dfSdanielk1977 ** occurred since the injector was last configured.
143ef05f2dfSdanielk1977 */
faultsimFailures(void)144ef05f2dfSdanielk1977 static int faultsimFailures(void){
145ef05f2dfSdanielk1977 return memfault.nFail;
146ef05f2dfSdanielk1977 }
147ef05f2dfSdanielk1977
148ef05f2dfSdanielk1977 /*
149ef05f2dfSdanielk1977 ** Return the number of benign faults that have occurred since the
150ef05f2dfSdanielk1977 ** injector was last configured.
151ef05f2dfSdanielk1977 */
faultsimBenignFailures(void)152ef05f2dfSdanielk1977 static int faultsimBenignFailures(void){
153ef05f2dfSdanielk1977 return memfault.nBenign;
154ef05f2dfSdanielk1977 }
155ef05f2dfSdanielk1977
156ef05f2dfSdanielk1977 /*
157ef05f2dfSdanielk1977 ** Return the number of successes that will occur before the next failure.
158ef05f2dfSdanielk1977 ** If no failures are scheduled, return -1.
159ef05f2dfSdanielk1977 */
faultsimPending(void)160ef05f2dfSdanielk1977 static int faultsimPending(void){
161ef05f2dfSdanielk1977 if( memfault.enable ){
162ef05f2dfSdanielk1977 return memfault.iCountdown;
163ef05f2dfSdanielk1977 }else{
164ef05f2dfSdanielk1977 return -1;
165ef05f2dfSdanielk1977 }
166ef05f2dfSdanielk1977 }
167ef05f2dfSdanielk1977
1682d1d86fbSdanielk1977
faultsimBeginBenign(void)1692d1d86fbSdanielk1977 static void faultsimBeginBenign(void){
1702d1d86fbSdanielk1977 memfault.isBenignMode++;
1712d1d86fbSdanielk1977 }
faultsimEndBenign(void)1722d1d86fbSdanielk1977 static void faultsimEndBenign(void){
1732d1d86fbSdanielk1977 memfault.isBenignMode--;
1742d1d86fbSdanielk1977 }
1752d1d86fbSdanielk1977
176ef05f2dfSdanielk1977 /*
177ef05f2dfSdanielk1977 ** Add or remove the fault-simulation layer using sqlite3_config(). If
178ef05f2dfSdanielk1977 ** the argument is non-zero, the
179ef05f2dfSdanielk1977 */
faultsimInstall(int install)180ef05f2dfSdanielk1977 static int faultsimInstall(int install){
181ef05f2dfSdanielk1977 int rc;
182ef05f2dfSdanielk1977
183ef05f2dfSdanielk1977 install = (install ? 1 : 0);
184ef05f2dfSdanielk1977 assert(memfault.isInstalled==1 || memfault.isInstalled==0);
185ef05f2dfSdanielk1977
186ef05f2dfSdanielk1977 if( install==memfault.isInstalled ){
187ef05f2dfSdanielk1977 return SQLITE_ERROR;
188ef05f2dfSdanielk1977 }
189ef05f2dfSdanielk1977
1902d1d86fbSdanielk1977 if( install ){
191ef05f2dfSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
192ef05f2dfSdanielk1977 assert(memfault.m.xMalloc);
193ef05f2dfSdanielk1977 if( rc==SQLITE_OK ){
194*9a23d26cSdan sqlite3_mem_methods m = memfault.m;
195*9a23d26cSdan m.xMalloc = faultsimMalloc;
196*9a23d26cSdan m.xRealloc = faultsimRealloc;
197ef05f2dfSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
198ef05f2dfSdanielk1977 }
1992d1d86fbSdanielk1977 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
2002d1d86fbSdanielk1977 faultsimBeginBenign, faultsimEndBenign
2012d1d86fbSdanielk1977 );
2022d1d86fbSdanielk1977 }else{
2038e18922fSmistachkin sqlite3_mem_methods m2;
2042d1d86fbSdanielk1977 assert(memfault.m.xMalloc);
2051b67f3caSdrh
2061b67f3caSdrh /* One should be able to reset the default memory allocator by storing
2071b67f3caSdrh ** a zeroed allocator then calling GETMALLOC. */
2088e18922fSmistachkin memset(&m2, 0, sizeof(m2));
2098e18922fSmistachkin sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
2108e18922fSmistachkin sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
2118e18922fSmistachkin assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
2121b67f3caSdrh
2132d1d86fbSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
214d797a9b5Sdrh sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
215d797a9b5Sdrh (void*)0, (void*)0);
2162d1d86fbSdanielk1977 }
217ef05f2dfSdanielk1977
218ef05f2dfSdanielk1977 if( rc==SQLITE_OK ){
219ef05f2dfSdanielk1977 memfault.isInstalled = 1;
220ef05f2dfSdanielk1977 }
221ef05f2dfSdanielk1977 return rc;
222ef05f2dfSdanielk1977 }
223ef05f2dfSdanielk1977
224ef05f2dfSdanielk1977 #ifdef SQLITE_TEST
225ef05f2dfSdanielk1977
226ef05f2dfSdanielk1977 /*
227e84d8d32Smistachkin ** This function is implemented in main.c. Returns a pointer to a static
228ef05f2dfSdanielk1977 ** buffer containing the symbolic SQLite error code that corresponds to
229ef05f2dfSdanielk1977 ** the least-significant 8-bits of the integer passed as an argument.
230ef05f2dfSdanielk1977 ** For example:
231ef05f2dfSdanielk1977 **
232e84d8d32Smistachkin ** sqlite3ErrName(1) -> "SQLITE_ERROR"
233ef05f2dfSdanielk1977 */
234e84d8d32Smistachkin extern const char *sqlite3ErrName(int);
235d09414cdSdanielk1977
2362f999a67Sdrh /*
2372f999a67Sdrh ** Transform pointers to text and back again
2382f999a67Sdrh */
pointerToText(void * p,char * z)2392f999a67Sdrh static void pointerToText(void *p, char *z){
2402f999a67Sdrh static const char zHex[] = "0123456789abcdef";
2412f999a67Sdrh int i, k;
2424a50aac5Sdrh unsigned int u;
2434a50aac5Sdrh sqlite3_uint64 n;
2448a42cbd3Sdrh if( p==0 ){
2458a42cbd3Sdrh strcpy(z, "0");
2468a42cbd3Sdrh return;
2478a42cbd3Sdrh }
2484a50aac5Sdrh if( sizeof(n)==sizeof(p) ){
2494a50aac5Sdrh memcpy(&n, &p, sizeof(p));
2504a50aac5Sdrh }else if( sizeof(u)==sizeof(p) ){
2514a50aac5Sdrh memcpy(&u, &p, sizeof(u));
2524a50aac5Sdrh n = u;
2534a50aac5Sdrh }else{
2544a50aac5Sdrh assert( 0 );
2554a50aac5Sdrh }
2562f999a67Sdrh for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){
2572f999a67Sdrh z[k] = zHex[n&0xf];
2582f999a67Sdrh n >>= 4;
2592f999a67Sdrh }
2602f999a67Sdrh z[sizeof(p)*2] = 0;
2612f999a67Sdrh }
hexToInt(int h)2622f999a67Sdrh static int hexToInt(int h){
2632f999a67Sdrh if( h>='0' && h<='9' ){
2642f999a67Sdrh return h - '0';
2652f999a67Sdrh }else if( h>='a' && h<='f' ){
2662f999a67Sdrh return h - 'a' + 10;
2672f999a67Sdrh }else{
2682f999a67Sdrh return -1;
2692f999a67Sdrh }
2702f999a67Sdrh }
textToPointer(const char * z,void ** pp)2712f999a67Sdrh static int textToPointer(const char *z, void **pp){
2722f999a67Sdrh sqlite3_uint64 n = 0;
2732f999a67Sdrh int i;
2744a50aac5Sdrh unsigned int u;
2752f999a67Sdrh for(i=0; i<sizeof(void*)*2 && z[0]; i++){
2762f999a67Sdrh int v;
2772f999a67Sdrh v = hexToInt(*z++);
2782f999a67Sdrh if( v<0 ) return TCL_ERROR;
2792f999a67Sdrh n = n*16 + v;
2802f999a67Sdrh }
2812f999a67Sdrh if( *z!=0 ) return TCL_ERROR;
2824a50aac5Sdrh if( sizeof(n)==sizeof(*pp) ){
2834a50aac5Sdrh memcpy(pp, &n, sizeof(n));
2844a50aac5Sdrh }else if( sizeof(u)==sizeof(*pp) ){
2854a50aac5Sdrh u = (unsigned int)n;
2864a50aac5Sdrh memcpy(pp, &u, sizeof(u));
2874a50aac5Sdrh }else{
2884a50aac5Sdrh assert( 0 );
2894a50aac5Sdrh }
2902f999a67Sdrh return TCL_OK;
2912f999a67Sdrh }
2922f999a67Sdrh
2932f999a67Sdrh /*
2942f999a67Sdrh ** Usage: sqlite3_malloc NBYTES
2952f999a67Sdrh **
2962f999a67Sdrh ** Raw test interface for sqlite3_malloc().
2972f999a67Sdrh */
test_malloc(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])2987617e4a8Smistachkin static int SQLITE_TCLAPI test_malloc(
2992f999a67Sdrh void * clientData,
3002f999a67Sdrh Tcl_Interp *interp,
3012f999a67Sdrh int objc,
3022f999a67Sdrh Tcl_Obj *CONST objv[]
3032f999a67Sdrh ){
3042f999a67Sdrh int nByte;
3052f999a67Sdrh void *p;
3062f999a67Sdrh char zOut[100];
3072f999a67Sdrh if( objc!=2 ){
3082f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");
3092f999a67Sdrh return TCL_ERROR;
3102f999a67Sdrh }
3112f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR;
3122f999a67Sdrh p = sqlite3_malloc((unsigned)nByte);
3132f999a67Sdrh pointerToText(p, zOut);
3142f999a67Sdrh Tcl_AppendResult(interp, zOut, NULL);
3152f999a67Sdrh return TCL_OK;
3162f999a67Sdrh }
3172f999a67Sdrh
3182f999a67Sdrh /*
3192f999a67Sdrh ** Usage: sqlite3_realloc PRIOR NBYTES
3202f999a67Sdrh **
3212f999a67Sdrh ** Raw test interface for sqlite3_realloc().
3222f999a67Sdrh */
test_realloc(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])3237617e4a8Smistachkin static int SQLITE_TCLAPI test_realloc(
3242f999a67Sdrh void * clientData,
3252f999a67Sdrh Tcl_Interp *interp,
3262f999a67Sdrh int objc,
3272f999a67Sdrh Tcl_Obj *CONST objv[]
3282f999a67Sdrh ){
3292f999a67Sdrh int nByte;
3302f999a67Sdrh void *pPrior, *p;
3312f999a67Sdrh char zOut[100];
3322f999a67Sdrh if( objc!=3 ){
3332f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");
3342f999a67Sdrh return TCL_ERROR;
3352f999a67Sdrh }
3362f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR;
3372f999a67Sdrh if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
3382f999a67Sdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
3392f999a67Sdrh return TCL_ERROR;
3402f999a67Sdrh }
3412f999a67Sdrh p = sqlite3_realloc(pPrior, (unsigned)nByte);
3422f999a67Sdrh pointerToText(p, zOut);
3432f999a67Sdrh Tcl_AppendResult(interp, zOut, NULL);
3442f999a67Sdrh return TCL_OK;
3452f999a67Sdrh }
3462f999a67Sdrh
3472f999a67Sdrh /*
3482f999a67Sdrh ** Usage: sqlite3_free PRIOR
3492f999a67Sdrh **
3502f999a67Sdrh ** Raw test interface for sqlite3_free().
3512f999a67Sdrh */
test_free(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])3527617e4a8Smistachkin static int SQLITE_TCLAPI test_free(
3532f999a67Sdrh void * clientData,
3542f999a67Sdrh Tcl_Interp *interp,
3552f999a67Sdrh int objc,
3562f999a67Sdrh Tcl_Obj *CONST objv[]
3572f999a67Sdrh ){
3582f999a67Sdrh void *pPrior;
3592f999a67Sdrh if( objc!=2 ){
3602f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");
3612f999a67Sdrh return TCL_ERROR;
3622f999a67Sdrh }
3632f999a67Sdrh if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
3642f999a67Sdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
3652f999a67Sdrh return TCL_ERROR;
3662f999a67Sdrh }
3672f999a67Sdrh sqlite3_free(pPrior);
3682f999a67Sdrh return TCL_OK;
3692f999a67Sdrh }
3702f999a67Sdrh
3712f999a67Sdrh /*
3729c7a60dfSdrh ** These routines are in test_hexio.c
3739c7a60dfSdrh */
3749c7a60dfSdrh int sqlite3TestHexToBin(const char *, int, char *);
3759c7a60dfSdrh int sqlite3TestBinToHex(char*,int);
3769c7a60dfSdrh
3779c7a60dfSdrh /*
3789c7a60dfSdrh ** Usage: memset ADDRESS SIZE HEX
3799c7a60dfSdrh **
3809c7a60dfSdrh ** Set a chunk of memory (obtained from malloc, probably) to a
3819c7a60dfSdrh ** specified hex pattern.
3829c7a60dfSdrh */
test_memset(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])3837617e4a8Smistachkin static int SQLITE_TCLAPI test_memset(
3849c7a60dfSdrh void * clientData,
3859c7a60dfSdrh Tcl_Interp *interp,
3869c7a60dfSdrh int objc,
3879c7a60dfSdrh Tcl_Obj *CONST objv[]
3889c7a60dfSdrh ){
3899c7a60dfSdrh void *p;
3909c7a60dfSdrh int size, n, i;
3919c7a60dfSdrh char *zHex;
3929c7a60dfSdrh char *zOut;
3939c7a60dfSdrh char zBin[100];
3949c7a60dfSdrh
3959c7a60dfSdrh if( objc!=4 ){
3969c7a60dfSdrh Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");
3979c7a60dfSdrh return TCL_ERROR;
3989c7a60dfSdrh }
3999c7a60dfSdrh if( textToPointer(Tcl_GetString(objv[1]), &p) ){
4009c7a60dfSdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
4019c7a60dfSdrh return TCL_ERROR;
4029c7a60dfSdrh }
4039c7a60dfSdrh if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
4049c7a60dfSdrh return TCL_ERROR;
4059c7a60dfSdrh }
4069c7a60dfSdrh if( size<=0 ){
4079c7a60dfSdrh Tcl_AppendResult(interp, "size must be positive", (char*)0);
4089c7a60dfSdrh return TCL_ERROR;
4099c7a60dfSdrh }
4109c7a60dfSdrh zHex = Tcl_GetStringFromObj(objv[3], &n);
4119c7a60dfSdrh if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
4129c7a60dfSdrh n = sqlite3TestHexToBin(zHex, n, zBin);
4139c7a60dfSdrh if( n==0 ){
4149c7a60dfSdrh Tcl_AppendResult(interp, "no data", (char*)0);
4159c7a60dfSdrh return TCL_ERROR;
4169c7a60dfSdrh }
4179c7a60dfSdrh zOut = p;
4189c7a60dfSdrh for(i=0; i<size; i++){
4199c7a60dfSdrh zOut[i] = zBin[i%n];
4209c7a60dfSdrh }
4219c7a60dfSdrh return TCL_OK;
4229c7a60dfSdrh }
4239c7a60dfSdrh
4249c7a60dfSdrh /*
4259c7a60dfSdrh ** Usage: memget ADDRESS SIZE
4269c7a60dfSdrh **
4279c7a60dfSdrh ** Return memory as hexadecimal text.
4289c7a60dfSdrh */
test_memget(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4297617e4a8Smistachkin static int SQLITE_TCLAPI test_memget(
4309c7a60dfSdrh void * clientData,
4319c7a60dfSdrh Tcl_Interp *interp,
4329c7a60dfSdrh int objc,
4339c7a60dfSdrh Tcl_Obj *CONST objv[]
4349c7a60dfSdrh ){
4359c7a60dfSdrh void *p;
4369c7a60dfSdrh int size, n;
4379c7a60dfSdrh char *zBin;
4389c7a60dfSdrh char zHex[100];
4399c7a60dfSdrh
4409c7a60dfSdrh if( objc!=3 ){
4419c7a60dfSdrh Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");
4429c7a60dfSdrh return TCL_ERROR;
4439c7a60dfSdrh }
4449c7a60dfSdrh if( textToPointer(Tcl_GetString(objv[1]), &p) ){
4459c7a60dfSdrh Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
4469c7a60dfSdrh return TCL_ERROR;
4479c7a60dfSdrh }
4489c7a60dfSdrh if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
4499c7a60dfSdrh return TCL_ERROR;
4509c7a60dfSdrh }
4519c7a60dfSdrh if( size<=0 ){
4529c7a60dfSdrh Tcl_AppendResult(interp, "size must be positive", (char*)0);
4539c7a60dfSdrh return TCL_ERROR;
4549c7a60dfSdrh }
4559c7a60dfSdrh zBin = p;
4569c7a60dfSdrh while( size>0 ){
4579c7a60dfSdrh if( size>(sizeof(zHex)-1)/2 ){
4589c7a60dfSdrh n = (sizeof(zHex)-1)/2;
4599c7a60dfSdrh }else{
4609c7a60dfSdrh n = size;
4619c7a60dfSdrh }
4629c7a60dfSdrh memcpy(zHex, zBin, n);
4639c7a60dfSdrh zBin += n;
4649c7a60dfSdrh size -= n;
4659c7a60dfSdrh sqlite3TestBinToHex(zHex, n);
4669c7a60dfSdrh Tcl_AppendResult(interp, zHex, (char*)0);
4679c7a60dfSdrh }
4689c7a60dfSdrh return TCL_OK;
4699c7a60dfSdrh }
4709c7a60dfSdrh
4719c7a60dfSdrh /*
4722f999a67Sdrh ** Usage: sqlite3_memory_used
4732f999a67Sdrh **
4742f999a67Sdrh ** Raw test interface for sqlite3_memory_used().
4752f999a67Sdrh */
test_memory_used(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4767617e4a8Smistachkin static int SQLITE_TCLAPI test_memory_used(
4772f999a67Sdrh void * clientData,
4782f999a67Sdrh Tcl_Interp *interp,
4792f999a67Sdrh int objc,
4802f999a67Sdrh Tcl_Obj *CONST objv[]
4812f999a67Sdrh ){
4822f999a67Sdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used()));
4832f999a67Sdrh return TCL_OK;
4842f999a67Sdrh }
4852f999a67Sdrh
4862f999a67Sdrh /*
4872f999a67Sdrh ** Usage: sqlite3_memory_highwater ?RESETFLAG?
4882f999a67Sdrh **
4892f999a67Sdrh ** Raw test interface for sqlite3_memory_highwater().
4902f999a67Sdrh */
test_memory_highwater(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4917617e4a8Smistachkin static int SQLITE_TCLAPI test_memory_highwater(
4922f999a67Sdrh void * clientData,
4932f999a67Sdrh Tcl_Interp *interp,
4942f999a67Sdrh int objc,
4952f999a67Sdrh Tcl_Obj *CONST objv[]
4962f999a67Sdrh ){
4972f999a67Sdrh int resetFlag = 0;
4982f999a67Sdrh if( objc!=1 && objc!=2 ){
4992f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "?RESET?");
5002f999a67Sdrh return TCL_ERROR;
5012f999a67Sdrh }
5022f999a67Sdrh if( objc==2 ){
5032f999a67Sdrh if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR;
5042f999a67Sdrh }
5052f999a67Sdrh Tcl_SetObjResult(interp,
5062f999a67Sdrh Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag)));
5072f999a67Sdrh return TCL_OK;
5082f999a67Sdrh }
5092f999a67Sdrh
5102f999a67Sdrh /*
5112f999a67Sdrh ** Usage: sqlite3_memdebug_backtrace DEPTH
5122f999a67Sdrh **
5132f999a67Sdrh ** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined
5142f999a67Sdrh ** then this routine is a no-op.
5152f999a67Sdrh */
test_memdebug_backtrace(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])5167617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_backtrace(
5172f999a67Sdrh void * clientData,
5182f999a67Sdrh Tcl_Interp *interp,
5192f999a67Sdrh int objc,
5202f999a67Sdrh Tcl_Obj *CONST objv[]
5212f999a67Sdrh ){
5222f999a67Sdrh int depth;
5232f999a67Sdrh if( objc!=2 ){
5242f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DEPT");
5252f999a67Sdrh return TCL_ERROR;
5262f999a67Sdrh }
5272f999a67Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;
5282f999a67Sdrh #ifdef SQLITE_MEMDEBUG
5292f999a67Sdrh {
53049e4fd71Sdrh extern void sqlite3MemdebugBacktrace(int);
53149e4fd71Sdrh sqlite3MemdebugBacktrace(depth);
5322f999a67Sdrh }
5332f999a67Sdrh #endif
5342f999a67Sdrh return TCL_OK;
5352f999a67Sdrh }
5362f999a67Sdrh
5372f999a67Sdrh /*
5382f999a67Sdrh ** Usage: sqlite3_memdebug_dump FILENAME
5392f999a67Sdrh **
5402f999a67Sdrh ** Write a summary of unfreed memory to FILENAME.
5412f999a67Sdrh */
test_memdebug_dump(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])5427617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_dump(
5432f999a67Sdrh void * clientData,
5442f999a67Sdrh Tcl_Interp *interp,
5452f999a67Sdrh int objc,
5462f999a67Sdrh Tcl_Obj *CONST objv[]
5472f999a67Sdrh ){
5482f999a67Sdrh if( objc!=2 ){
5492f999a67Sdrh Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
5502f999a67Sdrh return TCL_ERROR;
5512f999a67Sdrh }
5522d7636e2Sdrh #if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \
5532d7636e2Sdrh || defined(SQLITE_POW2_MEMORY_SIZE)
5542f999a67Sdrh {
55549e4fd71Sdrh extern void sqlite3MemdebugDump(const char*);
55649e4fd71Sdrh sqlite3MemdebugDump(Tcl_GetString(objv[1]));
5572f999a67Sdrh }
5582f999a67Sdrh #endif
5592f999a67Sdrh return TCL_OK;
5602f999a67Sdrh }
5612f999a67Sdrh
562a7a8e14bSdanielk1977 /*
563a7a8e14bSdanielk1977 ** Usage: sqlite3_memdebug_malloc_count
564a7a8e14bSdanielk1977 **
565a7a8e14bSdanielk1977 ** Return the total number of times malloc() has been called.
566a7a8e14bSdanielk1977 */
test_memdebug_malloc_count(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])5677617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_malloc_count(
568a7a8e14bSdanielk1977 void * clientData,
569a7a8e14bSdanielk1977 Tcl_Interp *interp,
570a7a8e14bSdanielk1977 int objc,
571a7a8e14bSdanielk1977 Tcl_Obj *CONST objv[]
572a7a8e14bSdanielk1977 ){
573a7a8e14bSdanielk1977 int nMalloc = -1;
574a7a8e14bSdanielk1977 if( objc!=1 ){
575a7a8e14bSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
576a7a8e14bSdanielk1977 return TCL_ERROR;
577a7a8e14bSdanielk1977 }
578a7a8e14bSdanielk1977 #if defined(SQLITE_MEMDEBUG)
579a7a8e14bSdanielk1977 {
58049e4fd71Sdrh extern int sqlite3MemdebugMallocCount();
58149e4fd71Sdrh nMalloc = sqlite3MemdebugMallocCount();
582a7a8e14bSdanielk1977 }
583a7a8e14bSdanielk1977 #endif
584a7a8e14bSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc));
585a7a8e14bSdanielk1977 return TCL_OK;
586a7a8e14bSdanielk1977 }
587a7a8e14bSdanielk1977
5882f999a67Sdrh
5892f999a67Sdrh /*
590a1644fd8Sdanielk1977 ** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?
591a1644fd8Sdanielk1977 **
592a1644fd8Sdanielk1977 ** where options are:
593a1644fd8Sdanielk1977 **
594643167ffSdrh ** -repeat <count>
595a1644fd8Sdanielk1977 ** -benigncnt <varname>
5960e6f1546Sdrh **
5970e6f1546Sdrh ** Arrange for a simulated malloc() failure after COUNTER successes.
598643167ffSdrh ** If a repeat count is specified, the fault is repeated that many
599643167ffSdrh ** times.
6000e6f1546Sdrh **
6010e6f1546Sdrh ** Each call to this routine overrides the prior counter value.
6020e6f1546Sdrh ** This routine returns the number of simulated failures that have
6030e6f1546Sdrh ** happened since the previous call to this routine.
6040e6f1546Sdrh **
6050e6f1546Sdrh ** To disable simulated failures, use a COUNTER of -1.
6060e6f1546Sdrh */
test_memdebug_fail(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])6077617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_fail(
6080e6f1546Sdrh void * clientData,
6090e6f1546Sdrh Tcl_Interp *interp,
6100e6f1546Sdrh int objc,
6110e6f1546Sdrh Tcl_Obj *CONST objv[]
6120e6f1546Sdrh ){
613a1644fd8Sdanielk1977 int ii;
6140e6f1546Sdrh int iFail;
615643167ffSdrh int nRepeat = 1;
616a1644fd8Sdanielk1977 Tcl_Obj *pBenignCnt = 0;
617643167ffSdrh int nBenign;
6180e6f1546Sdrh int nFail = 0;
619a1644fd8Sdanielk1977
620a1644fd8Sdanielk1977 if( objc<2 ){
621a1644fd8Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?");
6220e6f1546Sdrh return TCL_ERROR;
6230e6f1546Sdrh }
6240e6f1546Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;
625a1644fd8Sdanielk1977
626a1644fd8Sdanielk1977 for(ii=2; ii<objc; ii+=2){
627a1644fd8Sdanielk1977 int nOption;
628a1644fd8Sdanielk1977 char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);
629a1644fd8Sdanielk1977 char *zErr = 0;
630a1644fd8Sdanielk1977
631a1644fd8Sdanielk1977 if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){
632a1644fd8Sdanielk1977 if( ii==(objc-1) ){
633a1644fd8Sdanielk1977 zErr = "option requires an argument: ";
634ed138fb3Sdrh }else{
635643167ffSdrh if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){
636a1644fd8Sdanielk1977 return TCL_ERROR;
637ed138fb3Sdrh }
638a1644fd8Sdanielk1977 }
639a1644fd8Sdanielk1977 }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){
640a1644fd8Sdanielk1977 if( ii==(objc-1) ){
641a1644fd8Sdanielk1977 zErr = "option requires an argument: ";
642a1644fd8Sdanielk1977 }else{
643a1644fd8Sdanielk1977 pBenignCnt = objv[ii+1];
644a1644fd8Sdanielk1977 }
645a1644fd8Sdanielk1977 }else{
646a1644fd8Sdanielk1977 zErr = "unknown option: ";
647a1644fd8Sdanielk1977 }
648a1644fd8Sdanielk1977
649a1644fd8Sdanielk1977 if( zErr ){
650a1644fd8Sdanielk1977 Tcl_AppendResult(interp, zErr, zOption, 0);
651a1644fd8Sdanielk1977 return TCL_ERROR;
652a1644fd8Sdanielk1977 }
653a1644fd8Sdanielk1977 }
654a1644fd8Sdanielk1977
655ef05f2dfSdanielk1977 nBenign = faultsimBenignFailures();
656ef05f2dfSdanielk1977 nFail = faultsimFailures();
657ef05f2dfSdanielk1977 faultsimConfig(iFail, nRepeat);
658ef05f2dfSdanielk1977
659a1644fd8Sdanielk1977 if( pBenignCnt ){
660643167ffSdrh Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
661a1644fd8Sdanielk1977 }
6620e6f1546Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
6630e6f1546Sdrh return TCL_OK;
6640e6f1546Sdrh }
6650e6f1546Sdrh
666cd03724cSdanielk1977 /*
667cd03724cSdanielk1977 ** Usage: sqlite3_memdebug_pending
668cd03724cSdanielk1977 **
669cd03724cSdanielk1977 ** Return the number of malloc() calls that will succeed before a
670cd03724cSdanielk1977 ** simulated failure occurs. A negative return value indicates that
671cd03724cSdanielk1977 ** no malloc() failure is scheduled.
672cd03724cSdanielk1977 */
test_memdebug_pending(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])6737617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_pending(
674cd03724cSdanielk1977 void * clientData,
675cd03724cSdanielk1977 Tcl_Interp *interp,
676cd03724cSdanielk1977 int objc,
677cd03724cSdanielk1977 Tcl_Obj *CONST objv[]
678cd03724cSdanielk1977 ){
6795efaf070Sdrh int nPending;
680cd03724cSdanielk1977 if( objc!=1 ){
681cd03724cSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
682cd03724cSdanielk1977 return TCL_ERROR;
683cd03724cSdanielk1977 }
684ef05f2dfSdanielk1977 nPending = faultsimPending();
685ed13d98cSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
686cd03724cSdanielk1977 return TCL_OK;
687cd03724cSdanielk1977 }
688cd03724cSdanielk1977
68944ee1dc8Sdrh /*
69044ee1dc8Sdrh ** The following global variable keeps track of the number of tests
69144ee1dc8Sdrh ** that have run. This variable is only useful when running in the
69244ee1dc8Sdrh ** debugger.
69344ee1dc8Sdrh */
69444ee1dc8Sdrh static int sqlite3_memdebug_title_count = 0;
6950e6f1546Sdrh
6960e6f1546Sdrh /*
6974a50aac5Sdrh ** Usage: sqlite3_memdebug_settitle TITLE
6984a50aac5Sdrh **
6994a50aac5Sdrh ** Set a title string stored with each allocation. The TITLE is
7004a50aac5Sdrh ** typically the name of the test that was running when the
7014a50aac5Sdrh ** allocation occurred. The TITLE is stored with the allocation
7024a50aac5Sdrh ** and can be used to figure out which tests are leaking memory.
7034a50aac5Sdrh **
7044a50aac5Sdrh ** Each title overwrite the previous.
7054a50aac5Sdrh */
test_memdebug_settitle(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])7067617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_settitle(
7074a50aac5Sdrh void * clientData,
7084a50aac5Sdrh Tcl_Interp *interp,
7094a50aac5Sdrh int objc,
7104a50aac5Sdrh Tcl_Obj *CONST objv[]
7114a50aac5Sdrh ){
71244ee1dc8Sdrh sqlite3_memdebug_title_count++;
7134a50aac5Sdrh if( objc!=2 ){
7144a50aac5Sdrh Tcl_WrongNumArgs(interp, 1, objv, "TITLE");
7154a50aac5Sdrh return TCL_ERROR;
7164a50aac5Sdrh }
7174a50aac5Sdrh #ifdef SQLITE_MEMDEBUG
7184a50aac5Sdrh {
719caffb1a5Sdrh const char *zTitle;
72049e4fd71Sdrh extern int sqlite3MemdebugSettitle(const char*);
721a359b5eeSmistachkin zTitle = Tcl_GetString(objv[1]);
72249e4fd71Sdrh sqlite3MemdebugSettitle(zTitle);
7234a50aac5Sdrh }
7244a50aac5Sdrh #endif
7254a50aac5Sdrh return TCL_OK;
7264a50aac5Sdrh }
7274a50aac5Sdrh
728cd3e8f7cSdanielk1977 #define MALLOC_LOG_FRAMES 10
729ec561a35Sdan #define MALLOC_LOG_KEYINTS ( \
730ec561a35Sdan 10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \
731ec561a35Sdan )
7326f332c18Sdanielk1977 static Tcl_HashTable aMallocLog;
7336f332c18Sdanielk1977 static int mallocLogEnabled = 0;
7346f332c18Sdanielk1977
7356f332c18Sdanielk1977 typedef struct MallocLog MallocLog;
7366f332c18Sdanielk1977 struct MallocLog {
7376f332c18Sdanielk1977 int nCall;
7386f332c18Sdanielk1977 int nByte;
7396f332c18Sdanielk1977 };
7406f332c18Sdanielk1977
741afdd23a4Sshane #ifdef SQLITE_MEMDEBUG
test_memdebug_callback(int nByte,int nFrame,void ** aFrame)7426f332c18Sdanielk1977 static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){
7436f332c18Sdanielk1977 if( mallocLogEnabled ){
7446f332c18Sdanielk1977 MallocLog *pLog;
7456f332c18Sdanielk1977 Tcl_HashEntry *pEntry;
7466f332c18Sdanielk1977 int isNew;
7476f332c18Sdanielk1977
748ec561a35Sdan int aKey[MALLOC_LOG_KEYINTS];
749f6418891Smistachkin unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS;
7506f332c18Sdanielk1977
7516f332c18Sdanielk1977 memset(aKey, 0, nKey);
7526f332c18Sdanielk1977 if( (sizeof(void*)*nFrame)<nKey ){
7536f332c18Sdanielk1977 nKey = nFrame*sizeof(void*);
7546f332c18Sdanielk1977 }
7556f332c18Sdanielk1977 memcpy(aKey, aFrame, nKey);
7566f332c18Sdanielk1977
7576f332c18Sdanielk1977 pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew);
7586f332c18Sdanielk1977 if( isNew ){
7596f332c18Sdanielk1977 pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog));
7606f332c18Sdanielk1977 memset(pLog, 0, sizeof(MallocLog));
7616f332c18Sdanielk1977 Tcl_SetHashValue(pEntry, (ClientData)pLog);
7626f332c18Sdanielk1977 }else{
7636f332c18Sdanielk1977 pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
7646f332c18Sdanielk1977 }
7656f332c18Sdanielk1977
7666f332c18Sdanielk1977 pLog->nCall++;
7676f332c18Sdanielk1977 pLog->nByte += nByte;
7686f332c18Sdanielk1977 }
7696f332c18Sdanielk1977 }
770afdd23a4Sshane #endif /* SQLITE_MEMDEBUG */
7716f332c18Sdanielk1977
test_memdebug_log_clear(void)77264aca191Sdanielk1977 static void test_memdebug_log_clear(void){
773dbdc4d49Sdanielk1977 Tcl_HashSearch search;
774dbdc4d49Sdanielk1977 Tcl_HashEntry *pEntry;
775dbdc4d49Sdanielk1977 for(
776dbdc4d49Sdanielk1977 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
777dbdc4d49Sdanielk1977 pEntry;
778dbdc4d49Sdanielk1977 pEntry=Tcl_NextHashEntry(&search)
779dbdc4d49Sdanielk1977 ){
780dbdc4d49Sdanielk1977 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
781dbdc4d49Sdanielk1977 Tcl_Free((char *)pLog);
782dbdc4d49Sdanielk1977 }
783dbdc4d49Sdanielk1977 Tcl_DeleteHashTable(&aMallocLog);
784ec561a35Sdan Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
785dbdc4d49Sdanielk1977 }
786dbdc4d49Sdanielk1977
test_memdebug_log(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])7877617e4a8Smistachkin static int SQLITE_TCLAPI test_memdebug_log(
7886f332c18Sdanielk1977 void * clientData,
7896f332c18Sdanielk1977 Tcl_Interp *interp,
7906f332c18Sdanielk1977 int objc,
7916f332c18Sdanielk1977 Tcl_Obj *CONST objv[]
7926f332c18Sdanielk1977 ){
7936f332c18Sdanielk1977 static int isInit = 0;
7946f332c18Sdanielk1977 int iSub;
7956f332c18Sdanielk1977
796dbdc4d49Sdanielk1977 static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" };
797dbdc4d49Sdanielk1977 enum MB_enum {
798dbdc4d49Sdanielk1977 MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC
799dbdc4d49Sdanielk1977 };
8006f332c18Sdanielk1977
8016f332c18Sdanielk1977 if( !isInit ){
8026f332c18Sdanielk1977 #ifdef SQLITE_MEMDEBUG
8036f332c18Sdanielk1977 extern void sqlite3MemdebugBacktraceCallback(
8046f332c18Sdanielk1977 void (*xBacktrace)(int, int, void **));
8056f332c18Sdanielk1977 sqlite3MemdebugBacktraceCallback(test_memdebug_callback);
8066f332c18Sdanielk1977 #endif
807ec561a35Sdan Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
8086f332c18Sdanielk1977 isInit = 1;
8096f332c18Sdanielk1977 }
8106f332c18Sdanielk1977
8116f332c18Sdanielk1977 if( objc<2 ){
8126f332c18Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
8136f332c18Sdanielk1977 }
8146f332c18Sdanielk1977 if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){
8156f332c18Sdanielk1977 return TCL_ERROR;
8166f332c18Sdanielk1977 }
8176f332c18Sdanielk1977
8186f332c18Sdanielk1977 switch( (enum MB_enum)iSub ){
8196f332c18Sdanielk1977 case MB_LOG_START:
8206f332c18Sdanielk1977 mallocLogEnabled = 1;
8216f332c18Sdanielk1977 break;
8226f332c18Sdanielk1977 case MB_LOG_STOP:
8236f332c18Sdanielk1977 mallocLogEnabled = 0;
8246f332c18Sdanielk1977 break;
8256f332c18Sdanielk1977 case MB_LOG_DUMP: {
8266f332c18Sdanielk1977 Tcl_HashSearch search;
8276f332c18Sdanielk1977 Tcl_HashEntry *pEntry;
8286f332c18Sdanielk1977 Tcl_Obj *pRet = Tcl_NewObj();
8296f332c18Sdanielk1977
830ec561a35Sdan assert(sizeof(Tcl_WideInt)>=sizeof(void*));
8316f332c18Sdanielk1977
8326f332c18Sdanielk1977 for(
8336f332c18Sdanielk1977 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
8346f332c18Sdanielk1977 pEntry;
8356f332c18Sdanielk1977 pEntry=Tcl_NextHashEntry(&search)
8366f332c18Sdanielk1977 ){
8376f332c18Sdanielk1977 Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];
8386f332c18Sdanielk1977 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
839ec561a35Sdan Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry);
8406f332c18Sdanielk1977 int ii;
8416f332c18Sdanielk1977
8426f332c18Sdanielk1977 apElem[0] = Tcl_NewIntObj(pLog->nCall);
8436f332c18Sdanielk1977 apElem[1] = Tcl_NewIntObj(pLog->nByte);
8446f332c18Sdanielk1977 for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){
845ec561a35Sdan apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]);
8466f332c18Sdanielk1977 }
8476f332c18Sdanielk1977
8486f332c18Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet,
8496f332c18Sdanielk1977 Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem)
8506f332c18Sdanielk1977 );
8516f332c18Sdanielk1977 }
8526f332c18Sdanielk1977
8536f332c18Sdanielk1977 Tcl_SetObjResult(interp, pRet);
8546f332c18Sdanielk1977 break;
8556f332c18Sdanielk1977 }
8566f332c18Sdanielk1977 case MB_LOG_CLEAR: {
857dbdc4d49Sdanielk1977 test_memdebug_log_clear();
858dbdc4d49Sdanielk1977 break;
8596f332c18Sdanielk1977 }
860dbdc4d49Sdanielk1977
861dbdc4d49Sdanielk1977 case MB_LOG_SYNC: {
862b940492eSdrh #ifdef SQLITE_MEMDEBUG
863dbdc4d49Sdanielk1977 extern void sqlite3MemdebugSync();
864dbdc4d49Sdanielk1977 test_memdebug_log_clear();
865dbdc4d49Sdanielk1977 mallocLogEnabled = 1;
866dbdc4d49Sdanielk1977 sqlite3MemdebugSync();
867b940492eSdrh #endif
868dbdc4d49Sdanielk1977 break;
8696f332c18Sdanielk1977 }
8706f332c18Sdanielk1977 }
8716f332c18Sdanielk1977
8726f332c18Sdanielk1977 return TCL_OK;
8736f332c18Sdanielk1977 }
8744a50aac5Sdrh
8754a50aac5Sdrh /*
8769ac3fe97Sdrh ** Usage: sqlite3_config_pagecache SIZE N
8779ac3fe97Sdrh **
8789ac3fe97Sdrh ** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
8799ac3fe97Sdrh ** The buffer is static and is of limited size. N might be
88060ec914cSpeter.d.reid ** adjusted downward as needed to accommodate the requested size.
8819ac3fe97Sdrh ** The revised value of N is returned.
8829ac3fe97Sdrh **
8839ac3fe97Sdrh ** A negative SIZE causes the buffer pointer to be NULL.
8849ac3fe97Sdrh */
test_config_pagecache(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])8857617e4a8Smistachkin static int SQLITE_TCLAPI test_config_pagecache(
8869ac3fe97Sdrh void * clientData,
8879ac3fe97Sdrh Tcl_Interp *interp,
8889ac3fe97Sdrh int objc,
8899ac3fe97Sdrh Tcl_Obj *CONST objv[]
8909ac3fe97Sdrh ){
8916bacdc21Sdrh int sz, N;
89203bc525aSdan Tcl_Obj *pRes;
8935f4bcf15Sdrh static char *buf = 0;
8949ac3fe97Sdrh if( objc!=3 ){
8959ac3fe97Sdrh Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
8969ac3fe97Sdrh return TCL_ERROR;
8979ac3fe97Sdrh }
898f7141990Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
899f7141990Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
9005f4bcf15Sdrh free(buf);
9015f4bcf15Sdrh buf = 0;
90203bc525aSdan
90303bc525aSdan /* Set the return value */
90403bc525aSdan pRes = Tcl_NewObj();
90503bc525aSdan Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.szPage));
90603bc525aSdan Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.nPage));
90703bc525aSdan Tcl_SetObjResult(interp, pRes);
90803bc525aSdan
90903bc525aSdan if( sz<0 ){
910a6082f69Sdrh sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, 0);
911f7141990Sdrh }else{
9120a60a384Sdrh buf = malloc( sz*N );
9136bacdc21Sdrh sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
9149ac3fe97Sdrh }
9159ac3fe97Sdrh return TCL_OK;
9169ac3fe97Sdrh }
9179ac3fe97Sdrh
918f7141990Sdrh /*
919b232c232Sdrh ** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED
920b232c232Sdrh **
921b232c232Sdrh ** Set up the alternative test page cache. Install if INSTALL_FLAG is
922b232c232Sdrh ** true and uninstall (reverting to the default page cache) if INSTALL_FLAG
923b232c232Sdrh ** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive
924b232c232Sdrh ** which determines the chance of discarding a page when unpinned. 100
925b232c232Sdrh ** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator
926b232c232Sdrh ** seed.
927b232c232Sdrh */
test_alt_pcache(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])9287617e4a8Smistachkin static int SQLITE_TCLAPI test_alt_pcache(
929b232c232Sdrh void * clientData,
930b232c232Sdrh Tcl_Interp *interp,
931b232c232Sdrh int objc,
932b232c232Sdrh Tcl_Obj *CONST objv[]
933b232c232Sdrh ){
934b232c232Sdrh int installFlag;
935f2a84e3cSdrh int discardChance = 0;
936f2a84e3cSdrh int prngSeed = 0;
937f2a84e3cSdrh int highStress = 0;
938f2a84e3cSdrh extern void installTestPCache(int,unsigned,unsigned,unsigned);
939f2a84e3cSdrh if( objc<2 || objc>5 ){
940f2a84e3cSdrh Tcl_WrongNumArgs(interp, 1, objv,
941f2a84e3cSdrh "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS");
942b232c232Sdrh return TCL_ERROR;
943b232c232Sdrh }
944b232c232Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR;
945f2a84e3cSdrh if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){
946f2a84e3cSdrh return TCL_ERROR;
947f2a84e3cSdrh }
948f2a84e3cSdrh if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){
949f2a84e3cSdrh return TCL_ERROR;
950f2a84e3cSdrh }
951f2a84e3cSdrh if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){
952f2a84e3cSdrh return TCL_ERROR;
953f2a84e3cSdrh }
954b232c232Sdrh if( discardChance<0 || discardChance>100 ){
955b232c232Sdrh Tcl_AppendResult(interp, "discard-chance should be between 0 and 100",
956b232c232Sdrh (char*)0);
957b232c232Sdrh return TCL_ERROR;
958b232c232Sdrh }
959f2a84e3cSdrh installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed,
960f2a84e3cSdrh (unsigned)highStress);
961b232c232Sdrh return TCL_OK;
962b232c232Sdrh }
963b232c232Sdrh
964b232c232Sdrh /*
9658a42cbd3Sdrh ** Usage: sqlite3_config_memstatus BOOLEAN
9668a42cbd3Sdrh **
9678a42cbd3Sdrh ** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS.
9688a42cbd3Sdrh */
test_config_memstatus(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])9697617e4a8Smistachkin static int SQLITE_TCLAPI test_config_memstatus(
9708a42cbd3Sdrh void * clientData,
9718a42cbd3Sdrh Tcl_Interp *interp,
9728a42cbd3Sdrh int objc,
9738a42cbd3Sdrh Tcl_Obj *CONST objv[]
9748a42cbd3Sdrh ){
9758a42cbd3Sdrh int enable, rc;
9768a42cbd3Sdrh if( objc!=2 ){
9778a42cbd3Sdrh Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
9788a42cbd3Sdrh return TCL_ERROR;
9798a42cbd3Sdrh }
9808a42cbd3Sdrh if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;
9818a42cbd3Sdrh rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);
9828a42cbd3Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
9838a42cbd3Sdrh return TCL_OK;
9848a42cbd3Sdrh }
9858a42cbd3Sdrh
9868a42cbd3Sdrh /*
987633e6d57Sdrh ** Usage: sqlite3_config_lookaside SIZE COUNT
988633e6d57Sdrh **
989633e6d57Sdrh */
test_config_lookaside(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])9907617e4a8Smistachkin static int SQLITE_TCLAPI test_config_lookaside(
991633e6d57Sdrh void * clientData,
992633e6d57Sdrh Tcl_Interp *interp,
993633e6d57Sdrh int objc,
994633e6d57Sdrh Tcl_Obj *CONST objv[]
995633e6d57Sdrh ){
996633e6d57Sdrh int sz, cnt;
997ab7bee89Sdanielk1977 Tcl_Obj *pRet;
998633e6d57Sdrh if( objc!=3 ){
999633e6d57Sdrh Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");
1000633e6d57Sdrh return TCL_ERROR;
1001633e6d57Sdrh }
1002633e6d57Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
1003633e6d57Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR;
1004ab7bee89Sdanielk1977 pRet = Tcl_NewObj();
1005ab7bee89Sdanielk1977 Tcl_ListObjAppendElement(
1006ab7bee89Sdanielk1977 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside)
1007ab7bee89Sdanielk1977 );
1008ab7bee89Sdanielk1977 Tcl_ListObjAppendElement(
1009ab7bee89Sdanielk1977 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside)
1010ab7bee89Sdanielk1977 );
1011caffb1a5Sdrh sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);
1012ab7bee89Sdanielk1977 Tcl_SetObjResult(interp, pRet);
1013633e6d57Sdrh return TCL_OK;
1014633e6d57Sdrh }
1015633e6d57Sdrh
1016633e6d57Sdrh
1017633e6d57Sdrh /*
1018e9d1c720Sdrh ** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT
1019633e6d57Sdrh **
1020e9d1c720Sdrh ** There are two static buffers with BUFID 1 and 2. Each static buffer
1021e9d1c720Sdrh ** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL
1022e9d1c720Sdrh ** which will cause sqlite3_db_config() to allocate space on its own.
1023633e6d57Sdrh */
test_db_config_lookaside(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])10247617e4a8Smistachkin static int SQLITE_TCLAPI test_db_config_lookaside(
1025633e6d57Sdrh void * clientData,
1026633e6d57Sdrh Tcl_Interp *interp,
1027633e6d57Sdrh int objc,
1028633e6d57Sdrh Tcl_Obj *CONST objv[]
1029633e6d57Sdrh ){
1030633e6d57Sdrh int rc;
1031633e6d57Sdrh int sz, cnt;
1032633e6d57Sdrh sqlite3 *db;
1033e9d1c720Sdrh int bufid;
1034e9d1c720Sdrh static char azBuf[2][10000];
1035e84d8d32Smistachkin extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
1036e9d1c720Sdrh if( objc!=5 ){
1037e9d1c720Sdrh Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT");
1038633e6d57Sdrh return TCL_ERROR;
1039633e6d57Sdrh }
1040633e6d57Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1041e9d1c720Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR;
1042e9d1c720Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR;
1043e9d1c720Sdrh if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR;
1044e9d1c720Sdrh if( bufid==0 ){
1045aed11f20Sdrh rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt);
1046e9d1c720Sdrh }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){
1047e9d1c720Sdrh rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt);
1048e9d1c720Sdrh }else{
1049e9d1c720Sdrh Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0);
1050e9d1c720Sdrh return TCL_ERROR;
1051e9d1c720Sdrh }
1052633e6d57Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
1053633e6d57Sdrh return TCL_OK;
1054633e6d57Sdrh }
1055633e6d57Sdrh
1056633e6d57Sdrh /*
10578765b466Smistachkin ** Usage: sqlite3_config_heap NBYTE NMINALLOC
10585099be5eSdanielk1977 */
test_config_heap(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])10597617e4a8Smistachkin static int SQLITE_TCLAPI test_config_heap(
10605099be5eSdanielk1977 void * clientData,
10615099be5eSdanielk1977 Tcl_Interp *interp,
10625099be5eSdanielk1977 int objc,
10635099be5eSdanielk1977 Tcl_Obj *CONST objv[]
10645099be5eSdanielk1977 ){
10657830cd41Sdrh static char *zBuf; /* Use this memory */
10665099be5eSdanielk1977 int nByte; /* Size of buffer to pass to sqlite3_config() */
10675099be5eSdanielk1977 int nMinAlloc; /* Size of minimum allocation */
10685099be5eSdanielk1977 int rc; /* Return code of sqlite3_config() */
10695099be5eSdanielk1977
10705099be5eSdanielk1977 Tcl_Obj * CONST *aArg = &objv[1];
10715099be5eSdanielk1977 int nArg = objc-1;
10725099be5eSdanielk1977
10735099be5eSdanielk1977 if( nArg!=2 ){
10748a42cbd3Sdrh Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC");
10755099be5eSdanielk1977 return TCL_ERROR;
10765099be5eSdanielk1977 }
10775099be5eSdanielk1977 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
10785099be5eSdanielk1977 if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR;
10795099be5eSdanielk1977
10800d84e5b2Sdanielk1977 if( nByte==0 ){
10817830cd41Sdrh free( zBuf );
10827830cd41Sdrh zBuf = 0;
10838a42cbd3Sdrh rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0);
10840d84e5b2Sdanielk1977 }else{
10857830cd41Sdrh zBuf = realloc(zBuf, nByte);
10865099be5eSdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc);
10870d84e5b2Sdanielk1977 }
10885099be5eSdanielk1977
1089e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
10905099be5eSdanielk1977 return TCL_OK;
10915099be5eSdanielk1977 }
10925099be5eSdanielk1977
10935099be5eSdanielk1977 /*
1094ac1f1045Smistachkin ** Usage: sqlite3_config_heap_size NBYTE
1095ac1f1045Smistachkin */
test_config_heap_size(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])10967617e4a8Smistachkin static int SQLITE_TCLAPI test_config_heap_size(
1097ac1f1045Smistachkin void * clientData,
1098ac1f1045Smistachkin Tcl_Interp *interp,
1099ac1f1045Smistachkin int objc,
1100ac1f1045Smistachkin Tcl_Obj *CONST objv[]
1101ac1f1045Smistachkin ){
1102ac1f1045Smistachkin int nByte; /* Size to pass to sqlite3_config() */
1103ac1f1045Smistachkin int rc; /* Return code of sqlite3_config() */
1104ac1f1045Smistachkin
1105ac1f1045Smistachkin Tcl_Obj * CONST *aArg = &objv[1];
1106ac1f1045Smistachkin int nArg = objc-1;
1107ac1f1045Smistachkin
1108ac1f1045Smistachkin if( nArg!=1 ){
1109ac1f1045Smistachkin Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
1110ac1f1045Smistachkin return TCL_ERROR;
1111ac1f1045Smistachkin }
1112ac1f1045Smistachkin if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
1113ac1f1045Smistachkin
1114af8641bdSmistachkin rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte);
1115ac1f1045Smistachkin
1116ac1f1045Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1117ac1f1045Smistachkin return TCL_OK;
1118ac1f1045Smistachkin }
1119ac1f1045Smistachkin
1120ac1f1045Smistachkin /*
11218765b466Smistachkin ** Usage: sqlite3_config_error [DB]
11226480aad4Sdrh **
11236480aad4Sdrh ** Invoke sqlite3_config() or sqlite3_db_config() with invalid
11246480aad4Sdrh ** opcodes and verify that they return errors.
11256480aad4Sdrh */
test_config_error(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])11267617e4a8Smistachkin static int SQLITE_TCLAPI test_config_error(
11276480aad4Sdrh void * clientData,
11286480aad4Sdrh Tcl_Interp *interp,
11296480aad4Sdrh int objc,
11306480aad4Sdrh Tcl_Obj *CONST objv[]
11316480aad4Sdrh ){
11326480aad4Sdrh sqlite3 *db;
1133e84d8d32Smistachkin extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
11346480aad4Sdrh
11356480aad4Sdrh if( objc!=2 && objc!=1 ){
11366480aad4Sdrh Tcl_WrongNumArgs(interp, 1, objv, "[DB]");
11376480aad4Sdrh return TCL_ERROR;
11386480aad4Sdrh }
11396480aad4Sdrh if( objc==2 ){
11406480aad4Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
11416480aad4Sdrh if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){
11426480aad4Sdrh Tcl_AppendResult(interp,
11436480aad4Sdrh "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR",
11446480aad4Sdrh (char*)0);
11456480aad4Sdrh return TCL_ERROR;
11466480aad4Sdrh }
11476480aad4Sdrh }else{
11486480aad4Sdrh if( sqlite3_config(99999)!=SQLITE_ERROR ){
11496480aad4Sdrh Tcl_AppendResult(interp,
11506480aad4Sdrh "sqlite3_config(99999) does not return SQLITE_ERROR",
11516480aad4Sdrh (char*)0);
11526480aad4Sdrh return TCL_ERROR;
11536480aad4Sdrh }
11546480aad4Sdrh }
11556480aad4Sdrh return TCL_OK;
11566480aad4Sdrh }
11576480aad4Sdrh
11586480aad4Sdrh /*
11598765b466Smistachkin ** Usage: sqlite3_config_uri BOOLEAN
1160cd74b611Sdan **
11618765b466Smistachkin ** Enables or disables interpretation of URI parameters by default using
11628765b466Smistachkin ** SQLITE_CONFIG_URI.
1163cd74b611Sdan */
test_config_uri(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])11647617e4a8Smistachkin static int SQLITE_TCLAPI test_config_uri(
1165cd74b611Sdan void * clientData,
1166cd74b611Sdan Tcl_Interp *interp,
1167cd74b611Sdan int objc,
1168cd74b611Sdan Tcl_Obj *CONST objv[]
1169cd74b611Sdan ){
1170cd74b611Sdan int rc;
1171cd74b611Sdan int bOpenUri;
1172cd74b611Sdan
1173cd74b611Sdan if( objc!=2 ){
1174cd74b611Sdan Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1175cd74b611Sdan return TCL_ERROR;
1176cd74b611Sdan }
1177cd74b611Sdan if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
1178cd74b611Sdan return TCL_ERROR;
1179cd74b611Sdan }
1180cd74b611Sdan
1181cd74b611Sdan rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
1182e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1183cd74b611Sdan
1184cd74b611Sdan return TCL_OK;
1185cd74b611Sdan }
1186cd74b611Sdan
1187cd74b611Sdan /*
1188de9a7b8aSdrh ** Usage: sqlite3_config_cis BOOLEAN
1189de9a7b8aSdrh **
1190de9a7b8aSdrh ** Enables or disables the use of the covering-index scan optimization.
1191de9a7b8aSdrh ** SQLITE_CONFIG_COVERING_INDEX_SCAN.
1192de9a7b8aSdrh */
test_config_cis(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])11937617e4a8Smistachkin static int SQLITE_TCLAPI test_config_cis(
1194de9a7b8aSdrh void * clientData,
1195de9a7b8aSdrh Tcl_Interp *interp,
1196de9a7b8aSdrh int objc,
1197de9a7b8aSdrh Tcl_Obj *CONST objv[]
1198de9a7b8aSdrh ){
1199de9a7b8aSdrh int rc;
1200de9a7b8aSdrh int bUseCis;
1201de9a7b8aSdrh
1202de9a7b8aSdrh if( objc!=2 ){
1203de9a7b8aSdrh Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1204de9a7b8aSdrh return TCL_ERROR;
1205de9a7b8aSdrh }
1206de9a7b8aSdrh if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){
1207de9a7b8aSdrh return TCL_ERROR;
1208de9a7b8aSdrh }
1209de9a7b8aSdrh
1210de9a7b8aSdrh rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
1211e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1212de9a7b8aSdrh
1213de9a7b8aSdrh return TCL_OK;
1214de9a7b8aSdrh }
1215de9a7b8aSdrh
12163bd1791dSdrh /*
12173bd1791dSdrh ** Usage: sqlite3_config_pmasz INTEGER
12183bd1791dSdrh **
12193bd1791dSdrh ** Set the minimum PMA size.
12203bd1791dSdrh */
test_config_pmasz(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])12217617e4a8Smistachkin static int SQLITE_TCLAPI test_config_pmasz(
12223bd1791dSdrh void * clientData,
12233bd1791dSdrh Tcl_Interp *interp,
12243bd1791dSdrh int objc,
12253bd1791dSdrh Tcl_Obj *CONST objv[]
12263bd1791dSdrh ){
12273bd1791dSdrh int rc;
12283bd1791dSdrh int iPmaSz;
12293bd1791dSdrh
12303bd1791dSdrh if( objc!=2 ){
12313bd1791dSdrh Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
12323bd1791dSdrh return TCL_ERROR;
12333bd1791dSdrh }
12343bd1791dSdrh if( Tcl_GetIntFromObj(interp, objv[1], &iPmaSz) ){
12353bd1791dSdrh return TCL_ERROR;
12363bd1791dSdrh }
12373bd1791dSdrh
12383bd1791dSdrh rc = sqlite3_config(SQLITE_CONFIG_PMASZ, iPmaSz);
12393bd1791dSdrh Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
12403bd1791dSdrh
12413bd1791dSdrh return TCL_OK;
12423bd1791dSdrh }
12433bd1791dSdrh
1244578e1ca8Sdan
1245578e1ca8Sdan /*
12468765b466Smistachkin ** Usage: sqlite3_dump_memsys3 FILENAME
1247c66c0e14Sdanielk1977 ** sqlite3_dump_memsys5 FILENAME
124832155ef0Sdanielk1977 **
124932155ef0Sdanielk1977 ** Write a summary of unfreed memsys3 allocations to FILENAME.
125032155ef0Sdanielk1977 */
test_dump_memsys3(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])12517617e4a8Smistachkin static int SQLITE_TCLAPI test_dump_memsys3(
125232155ef0Sdanielk1977 void * clientData,
125332155ef0Sdanielk1977 Tcl_Interp *interp,
125432155ef0Sdanielk1977 int objc,
125532155ef0Sdanielk1977 Tcl_Obj *CONST objv[]
125632155ef0Sdanielk1977 ){
125732155ef0Sdanielk1977 if( objc!=2 ){
125832155ef0Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
125932155ef0Sdanielk1977 return TCL_ERROR;
126032155ef0Sdanielk1977 }
1261c66c0e14Sdanielk1977
1262860e332cSdrh switch( SQLITE_PTR_TO_INT(clientData) ){
12630d84e5b2Sdanielk1977 case 3: {
1264c66c0e14Sdanielk1977 #ifdef SQLITE_ENABLE_MEMSYS3
126532155ef0Sdanielk1977 extern void sqlite3Memsys3Dump(const char*);
126632155ef0Sdanielk1977 sqlite3Memsys3Dump(Tcl_GetString(objv[1]));
1267c66c0e14Sdanielk1977 break;
126832155ef0Sdanielk1977 #endif
1269c66c0e14Sdanielk1977 }
12700d84e5b2Sdanielk1977 case 5: {
1271c66c0e14Sdanielk1977 #ifdef SQLITE_ENABLE_MEMSYS5
1272c66c0e14Sdanielk1977 extern void sqlite3Memsys5Dump(const char*);
1273c66c0e14Sdanielk1977 sqlite3Memsys5Dump(Tcl_GetString(objv[1]));
1274c66c0e14Sdanielk1977 break;
1275c66c0e14Sdanielk1977 #endif
1276c66c0e14Sdanielk1977 }
1277c66c0e14Sdanielk1977 }
127832155ef0Sdanielk1977 return TCL_OK;
127932155ef0Sdanielk1977 }
128032155ef0Sdanielk1977
128132155ef0Sdanielk1977 /*
1282f7141990Sdrh ** Usage: sqlite3_status OPCODE RESETFLAG
1283f7141990Sdrh **
1284f7141990Sdrh ** Return a list of three elements which are the sqlite3_status() return
1285f7141990Sdrh ** code, the current value, and the high-water mark value.
1286f7141990Sdrh */
test_status(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])12877617e4a8Smistachkin static int SQLITE_TCLAPI test_status(
1288f7141990Sdrh void * clientData,
1289f7141990Sdrh Tcl_Interp *interp,
1290f7141990Sdrh int objc,
1291f7141990Sdrh Tcl_Obj *CONST objv[]
1292f7141990Sdrh ){
1293f7141990Sdrh int rc, iValue, mxValue;
12947bb22ac7Smistachkin int i, op = 0, resetFlag;
1295f7141990Sdrh const char *zOpName;
1296f7141990Sdrh static const struct {
1297f7141990Sdrh const char *zName;
1298f7141990Sdrh int op;
1299f7141990Sdrh } aOp[] = {
1300f7141990Sdrh { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED },
1301e50135e2Sdrh { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE },
1302f7141990Sdrh { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED },
1303f7141990Sdrh { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW },
1304e50135e2Sdrh { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE },
1305f7141990Sdrh { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED },
1306f7141990Sdrh { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
1307e50135e2Sdrh { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE },
1308ec424a5bSdrh { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK },
1309eafc43b1Sdrh { "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT },
1310f7141990Sdrh };
1311f7141990Sdrh Tcl_Obj *pResult;
1312f7141990Sdrh if( objc!=3 ){
1313f7141990Sdrh Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
1314f7141990Sdrh return TCL_ERROR;
1315f7141990Sdrh }
1316f7141990Sdrh zOpName = Tcl_GetString(objv[1]);
1317f7141990Sdrh for(i=0; i<ArraySize(aOp); i++){
1318f7141990Sdrh if( strcmp(aOp[i].zName, zOpName)==0 ){
1319f7141990Sdrh op = aOp[i].op;
1320f7141990Sdrh break;
1321f7141990Sdrh }
1322f7141990Sdrh }
1323f7141990Sdrh if( i>=ArraySize(aOp) ){
1324f7141990Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR;
1325f7141990Sdrh }
1326f7141990Sdrh if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR;
1327af005fbcSdrh iValue = 0;
1328af005fbcSdrh mxValue = 0;
1329f7141990Sdrh rc = sqlite3_status(op, &iValue, &mxValue, resetFlag);
1330f7141990Sdrh pResult = Tcl_NewObj();
1331f7141990Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1332f7141990Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1333f7141990Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1334f7141990Sdrh Tcl_SetObjResult(interp, pResult);
1335f7141990Sdrh return TCL_OK;
1336f7141990Sdrh }
13379ac3fe97Sdrh
13389ac3fe97Sdrh /*
1339633e6d57Sdrh ** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG
1340633e6d57Sdrh **
1341633e6d57Sdrh ** Return a list of three elements which are the sqlite3_db_status() return
1342633e6d57Sdrh ** code, the current value, and the high-water mark value.
1343633e6d57Sdrh */
test_db_status(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])13447617e4a8Smistachkin static int SQLITE_TCLAPI test_db_status(
1345633e6d57Sdrh void * clientData,
1346633e6d57Sdrh Tcl_Interp *interp,
1347633e6d57Sdrh int objc,
1348633e6d57Sdrh Tcl_Obj *CONST objv[]
1349633e6d57Sdrh ){
1350633e6d57Sdrh int rc, iValue, mxValue;
13517bb22ac7Smistachkin int i, op = 0, resetFlag;
1352633e6d57Sdrh const char *zOpName;
1353633e6d57Sdrh sqlite3 *db;
1354e84d8d32Smistachkin extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
1355633e6d57Sdrh static const struct {
1356633e6d57Sdrh const char *zName;
1357633e6d57Sdrh int op;
1358633e6d57Sdrh } aOp[] = {
13592a58e9ccSdrh { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
13602a58e9ccSdrh { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
13612a58e9ccSdrh { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
13622a58e9ccSdrh { "STMT_USED", SQLITE_DBSTATUS_STMT_USED },
13632a58e9ccSdrh { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT },
13642a58e9ccSdrh { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
136558ca31c9Sdan { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL },
136658ca31c9Sdan { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT },
13679ad3ee40Sdrh { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS },
1368648e2643Sdrh { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE },
1369272989b4Sdan { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS },
13709c10608aSdan { "CACHE_USED_SHARED", SQLITE_DBSTATUS_CACHE_USED_SHARED },
1371ffc78a41Sdrh { "CACHE_SPILL", SQLITE_DBSTATUS_CACHE_SPILL },
1372633e6d57Sdrh };
1373633e6d57Sdrh Tcl_Obj *pResult;
1374633e6d57Sdrh if( objc!=4 ){
137558ca31c9Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG");
1376633e6d57Sdrh return TCL_ERROR;
1377633e6d57Sdrh }
1378633e6d57Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1379633e6d57Sdrh zOpName = Tcl_GetString(objv[2]);
13802a58e9ccSdrh if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7;
13812a58e9ccSdrh if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9;
1382633e6d57Sdrh for(i=0; i<ArraySize(aOp); i++){
1383633e6d57Sdrh if( strcmp(aOp[i].zName, zOpName)==0 ){
1384633e6d57Sdrh op = aOp[i].op;
1385633e6d57Sdrh break;
1386633e6d57Sdrh }
1387633e6d57Sdrh }
1388633e6d57Sdrh if( i>=ArraySize(aOp) ){
1389633e6d57Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
1390633e6d57Sdrh }
1391633e6d57Sdrh if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
1392633e6d57Sdrh iValue = 0;
1393633e6d57Sdrh mxValue = 0;
1394633e6d57Sdrh rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag);
1395633e6d57Sdrh pResult = Tcl_NewObj();
1396633e6d57Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1397633e6d57Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1398633e6d57Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1399633e6d57Sdrh Tcl_SetObjResult(interp, pResult);
1400633e6d57Sdrh return TCL_OK;
1401633e6d57Sdrh }
1402633e6d57Sdrh
1403633e6d57Sdrh /*
1404d09414cdSdanielk1977 ** install_malloc_faultsim BOOLEAN
1405d09414cdSdanielk1977 */
test_install_malloc_faultsim(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])14067617e4a8Smistachkin static int SQLITE_TCLAPI test_install_malloc_faultsim(
1407d09414cdSdanielk1977 void * clientData,
1408d09414cdSdanielk1977 Tcl_Interp *interp,
1409d09414cdSdanielk1977 int objc,
1410d09414cdSdanielk1977 Tcl_Obj *CONST objv[]
1411d09414cdSdanielk1977 ){
1412d09414cdSdanielk1977 int rc;
1413d09414cdSdanielk1977 int isInstall;
1414d09414cdSdanielk1977
1415d09414cdSdanielk1977 if( objc!=2 ){
1416d09414cdSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1417d09414cdSdanielk1977 return TCL_ERROR;
1418d09414cdSdanielk1977 }
1419d09414cdSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
1420d09414cdSdanielk1977 return TCL_ERROR;
1421d09414cdSdanielk1977 }
1422ef05f2dfSdanielk1977 rc = faultsimInstall(isInstall);
1423e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1424d09414cdSdanielk1977 return TCL_OK;
1425d09414cdSdanielk1977 }
1426d09414cdSdanielk1977
1427d09414cdSdanielk1977 /*
14288b322827Sdanielk1977 ** sqlite3_install_memsys3
14298b322827Sdanielk1977 */
test_install_memsys3(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])14307617e4a8Smistachkin static int SQLITE_TCLAPI test_install_memsys3(
14318b322827Sdanielk1977 void * clientData,
14328b322827Sdanielk1977 Tcl_Interp *interp,
14338b322827Sdanielk1977 int objc,
14348b322827Sdanielk1977 Tcl_Obj *CONST objv[]
14358b322827Sdanielk1977 ){
14368b322827Sdanielk1977 int rc = SQLITE_MISUSE;
14378b322827Sdanielk1977 #ifdef SQLITE_ENABLE_MEMSYS3
14388b322827Sdanielk1977 const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
14398b322827Sdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetMemsys3());
14408b322827Sdanielk1977 #endif
1441e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
14428b322827Sdanielk1977 return TCL_OK;
14438b322827Sdanielk1977 }
14448b322827Sdanielk1977
test_vfs_oom_test(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])14457617e4a8Smistachkin static int SQLITE_TCLAPI test_vfs_oom_test(
1446c396d4afSdan void * clientData,
1447c396d4afSdan Tcl_Interp *interp,
1448c396d4afSdan int objc,
1449c396d4afSdan Tcl_Obj *CONST objv[]
1450c396d4afSdan ){
1451c396d4afSdan extern int sqlite3_memdebug_vfs_oom_test;
1452c396d4afSdan if( objc>2 ){
1453c396d4afSdan Tcl_WrongNumArgs(interp, 1, objv, "?INTEGER?");
1454c396d4afSdan return TCL_ERROR;
1455c396d4afSdan }else if( objc==2 ){
1456c396d4afSdan int iNew;
1457c396d4afSdan if( Tcl_GetIntFromObj(interp, objv[1], &iNew) ) return TCL_ERROR;
1458c396d4afSdan sqlite3_memdebug_vfs_oom_test = iNew;
1459c396d4afSdan }
1460c396d4afSdan Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_vfs_oom_test));
1461c396d4afSdan return TCL_OK;
1462c396d4afSdan }
1463c396d4afSdan
14648b322827Sdanielk1977 /*
14652f999a67Sdrh ** Register commands with the TCL interpreter.
14662f999a67Sdrh */
Sqlitetest_malloc_Init(Tcl_Interp * interp)14672f999a67Sdrh int Sqlitetest_malloc_Init(Tcl_Interp *interp){
14682f999a67Sdrh static struct {
14692f999a67Sdrh char *zName;
14702f999a67Sdrh Tcl_ObjCmdProc *xProc;
1471c66c0e14Sdanielk1977 int clientData;
14722f999a67Sdrh } aObjCmd[] = {
14738a42cbd3Sdrh { "sqlite3_malloc", test_malloc ,0 },
14748a42cbd3Sdrh { "sqlite3_realloc", test_realloc ,0 },
14758a42cbd3Sdrh { "sqlite3_free", test_free ,0 },
14768a42cbd3Sdrh { "memset", test_memset ,0 },
14778a42cbd3Sdrh { "memget", test_memget ,0 },
14788a42cbd3Sdrh { "sqlite3_memory_used", test_memory_used ,0 },
14798a42cbd3Sdrh { "sqlite3_memory_highwater", test_memory_highwater ,0 },
14808a42cbd3Sdrh { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 },
14818a42cbd3Sdrh { "sqlite3_memdebug_dump", test_memdebug_dump ,0 },
14828a42cbd3Sdrh { "sqlite3_memdebug_fail", test_memdebug_fail ,0 },
14838a42cbd3Sdrh { "sqlite3_memdebug_pending", test_memdebug_pending ,0 },
14848a42cbd3Sdrh { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 },
14858a42cbd3Sdrh { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 },
14868a42cbd3Sdrh { "sqlite3_memdebug_log", test_memdebug_log ,0 },
14878a42cbd3Sdrh { "sqlite3_config_pagecache", test_config_pagecache ,0 },
1488b232c232Sdrh { "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
14898a42cbd3Sdrh { "sqlite3_status", test_status ,0 },
1490633e6d57Sdrh { "sqlite3_db_status", test_db_status ,0 },
14918a42cbd3Sdrh { "install_malloc_faultsim", test_install_malloc_faultsim ,0 },
14925099be5eSdanielk1977 { "sqlite3_config_heap", test_config_heap ,0 },
1493ac1f1045Smistachkin { "sqlite3_config_heap_size", test_config_heap_size ,0 },
14948a42cbd3Sdrh { "sqlite3_config_memstatus", test_config_memstatus ,0 },
1495633e6d57Sdrh { "sqlite3_config_lookaside", test_config_lookaside ,0 },
14966480aad4Sdrh { "sqlite3_config_error", test_config_error ,0 },
1497cd74b611Sdan { "sqlite3_config_uri", test_config_uri ,0 },
1498de9a7b8aSdrh { "sqlite3_config_cis", test_config_cis ,0 },
14993bd1791dSdrh { "sqlite3_config_pmasz", test_config_pmasz ,0 },
1500633e6d57Sdrh { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
15010d84e5b2Sdanielk1977 { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
1502b232c232Sdrh { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
15038b322827Sdanielk1977 { "sqlite3_install_memsys3", test_install_memsys3 ,0 },
1504c396d4afSdan { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 },
15052f999a67Sdrh };
15062f999a67Sdrh int i;
15072f999a67Sdrh for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
1508860e332cSdrh ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData);
1509c66c0e14Sdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
15102f999a67Sdrh }
15112f999a67Sdrh return TCL_OK;
15122f999a67Sdrh }
1513ef05f2dfSdanielk1977 #endif
1514