Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: 1c19d896f2e7a3abefddfc8a6f252e04b085b9d3 [file] [log] [blame]
drh2f999a62007-08-15 19:16:431/*
2** 2007 August 15
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11*************************************************************************
12**
13** This file contains code used to implement test interfaces to the
14** memory allocation subsystem.
drh2f999a62007-08-15 19:16:4315*/
16#include "sqliteInt.h"
drh064b6812024-07-30 15:49:0217#include "tclsqlite.h"
drh2f999a62007-08-15 19:16:4318#include <stdlib.h>
19#include <string.h>
20#include <assert.h>
21
danielk1977ef05f2d2008-06-20 11:05:3722/*
23** This structure is used to encapsulate the global state variables used
24** by malloc() fault simulation.
25*/
26static struct MemFault {
27 int iCountdown; /* Number of pending successes before a failure */
28 int nRepeat; /* Number of times to repeat the failure */
29 int nBenign; /* Number of benign failures seen since last config */
30 int nFail; /* Number of failures seen since last config */
drhb9cd2c42018-05-24 17:38:0031 int nOkBefore; /* Successful allocations prior to the first fault */
32 int nOkAfter; /* Successful allocations after a fault */
danielk1977ef05f2d2008-06-20 11:05:3733 u8 enable; /* True if enabled */
34 int isInstalled; /* True if the fault simulation layer is installed */
danielk19772d1d86f2008-06-20 14:59:5135 int isBenignMode; /* True if malloc failures are considered benign */
danielk1977ef05f2d2008-06-20 11:05:3736 sqlite3_mem_methods m; /* 'Real' malloc implementation */
37} memfault;
38
39/*
40** This routine exists as a place to set a breakpoint that will
41** fire on any simulated malloc() failure.
42*/
43static void sqlite3Fault(void){
drh43afab22025-01-13 11:28:3444 static u64 cnt = 0;
danielk1977ef05f2d2008-06-20 11:05:3745 cnt++;
drh43afab22025-01-13 11:28:3446 if( cnt>((u64)1<<63) ) abort();
danielk1977ef05f2d2008-06-20 11:05:3747}
48
49/*
drhb9cd2c42018-05-24 17:38:0050** This routine exists as a place to set a breakpoint that will
51** fire the first time any malloc() fails on a single test case.
52** The sqlite3Fault() routine above runs on every malloc() failure.
53** This routine only runs on the first such failure.
54*/
55static void sqlite3FirstFault(void){
drh43afab22025-01-13 11:28:3456 static u64 cnt2 = 0;
drhb9cd2c42018-05-24 17:38:0057 cnt2++;
drh43afab22025-01-13 11:28:3458 if( cnt2>((u64)1<<63) ) abort();
drhb9cd2c42018-05-24 17:38:0059}
60
61/*
danielk1977ef05f2d2008-06-20 11:05:3762** Check to see if a fault should be simulated. Return true to simulate
63** the fault. Return false if the fault should not be simulated.
64*/
danielk197764aca192009-04-07 11:21:2865static int faultsimStep(void){
danielk1977ef05f2d2008-06-20 11:05:3766 if( likely(!memfault.enable) ){
drhb9cd2c42018-05-24 17:38:0067 memfault.nOkAfter++;
danielk1977ef05f2d2008-06-20 11:05:3768 return 0;
69 }
70 if( memfault.iCountdown>0 ){
71 memfault.iCountdown--;
drhb9cd2c42018-05-24 17:38:0072 memfault.nOkBefore++;
danielk1977ef05f2d2008-06-20 11:05:3773 return 0;
74 }
drhb9cd2c42018-05-24 17:38:0075 if( memfault.nFail==0 ) sqlite3FirstFault();
danielk1977ef05f2d2008-06-20 11:05:3776 sqlite3Fault();
77 memfault.nFail++;
danielk19772d1d86f2008-06-20 14:59:5178 if( memfault.isBenignMode>0 ){
danielk1977ef05f2d2008-06-20 11:05:3779 memfault.nBenign++;
80 }
81 memfault.nRepeat--;
82 if( memfault.nRepeat<=0 ){
83 memfault.enable = 0;
84 }
85 return 1;
86}
87
88/*
89** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation
90** logic.
91*/
92static void *faultsimMalloc(int n){
93 void *p = 0;
94 if( !faultsimStep() ){
95 p = memfault.m.xMalloc(n);
96 }
97 return p;
98}
99
100
101/*
102** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation
103** logic.
104*/
105static void *faultsimRealloc(void *pOld, int n){
106 void *p = 0;
107 if( !faultsimStep() ){
108 p = memfault.m.xRealloc(pOld, n);
109 }
110 return p;
111}
112
danielk1977ef05f2d2008-06-20 11:05:37113/*
114** This routine configures the malloc failure simulation. After
115** calling this routine, the next nDelay mallocs will succeed, followed
116** by a block of nRepeat failures, after which malloc() calls will begin
117** to succeed again.
118*/
119static void faultsimConfig(int nDelay, int nRepeat){
120 memfault.iCountdown = nDelay;
121 memfault.nRepeat = nRepeat;
122 memfault.nBenign = 0;
123 memfault.nFail = 0;
drhb9cd2c42018-05-24 17:38:00124 memfault.nOkBefore = 0;
125 memfault.nOkAfter = 0;
danielk1977ef05f2d2008-06-20 11:05:37126 memfault.enable = nDelay>=0;
danielk1977b48c1f12009-02-04 15:27:40127
128 /* Sometimes, when running multi-threaded tests, the isBenignMode
129 ** variable is not properly incremented/decremented so that it is
130 ** 0 when not inside a benign malloc block. This doesn't affect
131 ** the multi-threaded tests, as they do not use this system. But
132 ** it does affect OOM tests run later in the same process. So
133 ** zero the variable here, just to be sure.
134 */
135 memfault.isBenignMode = 0;
danielk1977ef05f2d2008-06-20 11:05:37136}
137
138/*
139** Return the number of faults (both hard and benign faults) that have
140** occurred since the injector was last configured.
141*/
142static int faultsimFailures(void){
143 return memfault.nFail;
144}
145
146/*
147** Return the number of benign faults that have occurred since the
148** injector was last configured.
149*/
150static int faultsimBenignFailures(void){
151 return memfault.nBenign;
152}
153
154/*
155** Return the number of successes that will occur before the next failure.
156** If no failures are scheduled, return -1.
157*/
158static int faultsimPending(void){
159 if( memfault.enable ){
160 return memfault.iCountdown;
161 }else{
162 return -1;
163 }
164}
165
danielk19772d1d86f2008-06-20 14:59:51166
167static void faultsimBeginBenign(void){
168 memfault.isBenignMode++;
169}
170static void faultsimEndBenign(void){
171 memfault.isBenignMode--;
172}
173
danielk1977ef05f2d2008-06-20 11:05:37174/*
175** Add or remove the fault-simulation layer using sqlite3_config(). If
176** the argument is non-zero, the
177*/
178static int faultsimInstall(int install){
danielk1977ef05f2d2008-06-20 11:05:37179 int rc;
180
181 install = (install ? 1 : 0);
182 assert(memfault.isInstalled==1 || memfault.isInstalled==0);
183
184 if( install==memfault.isInstalled ){
185 return SQLITE_ERROR;
186 }
187
danielk19772d1d86f2008-06-20 14:59:51188 if( install ){
189 rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
190 assert(memfault.m.xMalloc);
191 if( rc==SQLITE_OK ){
dan9a23d262020-07-16 14:52:24192 sqlite3_mem_methods m = memfault.m;
193 m.xMalloc = faultsimMalloc;
194 m.xRealloc = faultsimRealloc;
danielk19772d1d86f2008-06-20 14:59:51195 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
196 }
197 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
198 faultsimBeginBenign, faultsimEndBenign
199 );
200 }else{
mistachkin8e189222015-04-19 21:43:16201 sqlite3_mem_methods m2;
danielk19772d1d86f2008-06-20 14:59:51202 assert(memfault.m.xMalloc);
drh1b67f3c2008-10-10 17:41:28203
204 /* One should be able to reset the default memory allocator by storing
205 ** a zeroed allocator then calling GETMALLOC. */
mistachkin8e189222015-04-19 21:43:16206 memset(&m2, 0, sizeof(m2));
207 sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
208 sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
209 assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
drh1b67f3c2008-10-10 17:41:28210
danielk19772d1d86f2008-06-20 14:59:51211 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
drhd797a9b2015-12-07 16:43:44212 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
213 (void*)0, (void*)0);
danielk1977ef05f2d2008-06-20 11:05:37214 }
215
216 if( rc==SQLITE_OK ){
217 memfault.isInstalled = 1;
218 }
219 return rc;
220}
221
222#ifdef SQLITE_TEST
223
224/*
mistachkine84d8d32013-04-29 03:09:10225** This function is implemented in main.c. Returns a pointer to a static
danielk1977ef05f2d2008-06-20 11:05:37226** buffer containing the symbolic SQLite error code that corresponds to
227** the least-significant 8-bits of the integer passed as an argument.
228** For example:
229**
mistachkine84d8d32013-04-29 03:09:10230** sqlite3ErrName(1) -> "SQLITE_ERROR"
danielk1977ef05f2d2008-06-20 11:05:37231*/
mistachkine84d8d32013-04-29 03:09:10232extern const char *sqlite3ErrName(int);
danielk1977d09414c2008-06-19 18:17:49233
drh2f999a62007-08-15 19:16:43234/*
235** Transform pointers to text and back again
236*/
237static void pointerToText(void *p, char *z){
238 static const char zHex[] = "0123456789abcdef";
239 int i, k;
drh4a50aac2007-08-23 02:47:53240 unsigned int u;
241 sqlite3_uint64 n;
drh8a42cbd2008-07-10 18:13:42242 if( p==0 ){
243 strcpy(z, "0");
244 return;
245 }
drh4a50aac2007-08-23 02:47:53246 if( sizeof(n)==sizeof(p) ){
247 memcpy(&n, &p, sizeof(p));
248 }else if( sizeof(u)==sizeof(p) ){
249 memcpy(&u, &p, sizeof(u));
250 n = u;
251 }else{
252 assert( 0 );
253 }
drh2f999a62007-08-15 19:16:43254 for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){
255 z[k] = zHex[n&0xf];
256 n >>= 4;
257 }
258 z[sizeof(p)*2] = 0;
259}
260static int hexToInt(int h){
261 if( h>='0' && h<='9' ){
262 return h - '0';
263 }else if( h>='a' && h<='f' ){
264 return h - 'a' + 10;
265 }else{
266 return -1;
267 }
268}
269static int textToPointer(const char *z, void **pp){
270 sqlite3_uint64 n = 0;
271 int i;
drh4a50aac2007-08-23 02:47:53272 unsigned int u;
drh2f999a62007-08-15 19:16:43273 for(i=0; i<sizeof(void*)*2 && z[0]; i++){
274 int v;
275 v = hexToInt(*z++);
276 if( v<0 ) return TCL_ERROR;
277 n = n*16 + v;
278 }
279 if( *z!=0 ) return TCL_ERROR;
drh4a50aac2007-08-23 02:47:53280 if( sizeof(n)==sizeof(*pp) ){
281 memcpy(pp, &n, sizeof(n));
282 }else if( sizeof(u)==sizeof(*pp) ){
283 u = (unsigned int)n;
284 memcpy(pp, &u, sizeof(u));
285 }else{
286 assert( 0 );
287 }
drh2f999a62007-08-15 19:16:43288 return TCL_OK;
289}
290
291/*
292** Usage: sqlite3_malloc NBYTES
293**
294** Raw test interface for sqlite3_malloc().
295*/
mistachkin7617e4a2016-07-28 17:11:20296static int SQLITE_TCLAPI test_malloc(
drh2f999a62007-08-15 19:16:43297 void * clientData,
298 Tcl_Interp *interp,
299 int objc,
300 Tcl_Obj *CONST objv[]
301){
302 int nByte;
303 void *p;
304 char zOut[100];
305 if( objc!=2 ){
306 Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");
307 return TCL_ERROR;
308 }
309 if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR;
310 p = sqlite3_malloc((unsigned)nByte);
311 pointerToText(p, zOut);
312 Tcl_AppendResult(interp, zOut, NULL);
313 return TCL_OK;
314}
315
316/*
317** Usage: sqlite3_realloc PRIOR NBYTES
318**
319** Raw test interface for sqlite3_realloc().
320*/
mistachkin7617e4a2016-07-28 17:11:20321static int SQLITE_TCLAPI test_realloc(
drh2f999a62007-08-15 19:16:43322 void * clientData,
323 Tcl_Interp *interp,
324 int objc,
325 Tcl_Obj *CONST objv[]
326){
327 int nByte;
328 void *pPrior, *p;
329 char zOut[100];
330 if( objc!=3 ){
331 Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");
332 return TCL_ERROR;
333 }
334 if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR;
335 if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
336 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
337 return TCL_ERROR;
338 }
339 p = sqlite3_realloc(pPrior, (unsigned)nByte);
340 pointerToText(p, zOut);
341 Tcl_AppendResult(interp, zOut, NULL);
342 return TCL_OK;
343}
344
drh2f999a62007-08-15 19:16:43345/*
346** Usage: sqlite3_free PRIOR
347**
348** Raw test interface for sqlite3_free().
349*/
mistachkin7617e4a2016-07-28 17:11:20350static int SQLITE_TCLAPI test_free(
drh2f999a62007-08-15 19:16:43351 void * clientData,
352 Tcl_Interp *interp,
353 int objc,
354 Tcl_Obj *CONST objv[]
355){
356 void *pPrior;
357 if( objc!=2 ){
358 Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");
359 return TCL_ERROR;
360 }
361 if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
362 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
363 return TCL_ERROR;
364 }
365 sqlite3_free(pPrior);
366 return TCL_OK;
367}
368
369/*
drh9c7a60d2007-10-19 17:47:24370** These routines are in test_hexio.c
371*/
372int sqlite3TestHexToBin(const char *, int, char *);
373int sqlite3TestBinToHex(char*,int);
374
375/*
376** Usage: memset ADDRESS SIZE HEX
377**
378** Set a chunk of memory (obtained from malloc, probably) to a
379** specified hex pattern.
380*/
mistachkin7617e4a2016-07-28 17:11:20381static int SQLITE_TCLAPI test_memset(
drh9c7a60d2007-10-19 17:47:24382 void * clientData,
383 Tcl_Interp *interp,
384 int objc,
385 Tcl_Obj *CONST objv[]
386){
387 void *p;
drh064b6812024-07-30 15:49:02388 int size, i;
389 Tcl_Size n;
drh9c7a60d2007-10-19 17:47:24390 char *zHex;
391 char *zOut;
392 char zBin[100];
393
394 if( objc!=4 ){
395 Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");
396 return TCL_ERROR;
397 }
398 if( textToPointer(Tcl_GetString(objv[1]), &p) ){
399 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
400 return TCL_ERROR;
401 }
402 if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
403 return TCL_ERROR;
404 }
405 if( size<=0 ){
406 Tcl_AppendResult(interp, "size must be positive", (char*)0);
407 return TCL_ERROR;
408 }
409 zHex = Tcl_GetStringFromObj(objv[3], &n);
410 if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
drh064b6812024-07-30 15:49:02411 n = sqlite3TestHexToBin(zHex, (int)n, zBin);
drh9c7a60d2007-10-19 17:47:24412 if( n==0 ){
413 Tcl_AppendResult(interp, "no data", (char*)0);
414 return TCL_ERROR;
415 }
416 zOut = p;
417 for(i=0; i<size; i++){
418 zOut[i] = zBin[i%n];
419 }
420 return TCL_OK;
421}
422
423/*
424** Usage: memget ADDRESS SIZE
425**
426** Return memory as hexadecimal text.
427*/
mistachkin7617e4a2016-07-28 17:11:20428static int SQLITE_TCLAPI test_memget(
drh9c7a60d2007-10-19 17:47:24429 void * clientData,
430 Tcl_Interp *interp,
431 int objc,
432 Tcl_Obj *CONST objv[]
433){
434 void *p;
435 int size, n;
436 char *zBin;
437 char zHex[100];
438
439 if( objc!=3 ){
440 Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");
441 return TCL_ERROR;
442 }
443 if( textToPointer(Tcl_GetString(objv[1]), &p) ){
444 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
445 return TCL_ERROR;
446 }
447 if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
448 return TCL_ERROR;
449 }
450 if( size<=0 ){
451 Tcl_AppendResult(interp, "size must be positive", (char*)0);
452 return TCL_ERROR;
453 }
454 zBin = p;
455 while( size>0 ){
456 if( size>(sizeof(zHex)-1)/2 ){
457 n = (sizeof(zHex)-1)/2;
458 }else{
459 n = size;
460 }
461 memcpy(zHex, zBin, n);
462 zBin += n;
463 size -= n;
464 sqlite3TestBinToHex(zHex, n);
465 Tcl_AppendResult(interp, zHex, (char*)0);
466 }
467 return TCL_OK;
468}
469
470/*
drh2f999a62007-08-15 19:16:43471** Usage: sqlite3_memory_used
472**
473** Raw test interface for sqlite3_memory_used().
474*/
mistachkin7617e4a2016-07-28 17:11:20475static int SQLITE_TCLAPI test_memory_used(
drh2f999a62007-08-15 19:16:43476 void * clientData,
477 Tcl_Interp *interp,
478 int objc,
479 Tcl_Obj *CONST objv[]
480){
481 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used()));
482 return TCL_OK;
483}
484
485/*
486** Usage: sqlite3_memory_highwater ?RESETFLAG?
487**
488** Raw test interface for sqlite3_memory_highwater().
489*/
mistachkin7617e4a2016-07-28 17:11:20490static int SQLITE_TCLAPI test_memory_highwater(
drh2f999a62007-08-15 19:16:43491 void * clientData,
492 Tcl_Interp *interp,
493 int objc,
494 Tcl_Obj *CONST objv[]
495){
496 int resetFlag = 0;
497 if( objc!=1 && objc!=2 ){
498 Tcl_WrongNumArgs(interp, 1, objv, "?RESET?");
499 return TCL_ERROR;
500 }
501 if( objc==2 ){
502 if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR;
503 }
504 Tcl_SetObjResult(interp,
505 Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag)));
506 return TCL_OK;
507}
508
509/*
510** Usage: sqlite3_memdebug_backtrace DEPTH
511**
512** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined
513** then this routine is a no-op.
514*/
mistachkin7617e4a2016-07-28 17:11:20515static int SQLITE_TCLAPI test_memdebug_backtrace(
drh2f999a62007-08-15 19:16:43516 void * clientData,
517 Tcl_Interp *interp,
518 int objc,
519 Tcl_Obj *CONST objv[]
520){
521 int depth;
522 if( objc!=2 ){
523 Tcl_WrongNumArgs(interp, 1, objv, "DEPT");
524 return TCL_ERROR;
525 }
526 if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;
527#ifdef SQLITE_MEMDEBUG
528 {
drh49e4fd72008-02-19 15:15:15529 extern void sqlite3MemdebugBacktrace(int);
530 sqlite3MemdebugBacktrace(depth);
drh2f999a62007-08-15 19:16:43531 }
532#endif
533 return TCL_OK;
534}
535
536/*
537** Usage: sqlite3_memdebug_dump FILENAME
538**
539** Write a summary of unfreed memory to FILENAME.
540*/
mistachkin7617e4a2016-07-28 17:11:20541static int SQLITE_TCLAPI test_memdebug_dump(
drh2f999a62007-08-15 19:16:43542 void * clientData,
543 Tcl_Interp *interp,
544 int objc,
545 Tcl_Obj *CONST objv[]
546){
547 if( objc!=2 ){
548 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
549 return TCL_ERROR;
550 }
drh2d7636e2008-02-16 16:21:45551#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \
552 || defined(SQLITE_POW2_MEMORY_SIZE)
drh2f999a62007-08-15 19:16:43553 {
drh49e4fd72008-02-19 15:15:15554 extern void sqlite3MemdebugDump(const char*);
555 sqlite3MemdebugDump(Tcl_GetString(objv[1]));
drh2f999a62007-08-15 19:16:43556 }
557#endif
558 return TCL_OK;
559}
560
danielk1977a7a8e142008-02-13 18:25:27561/*
562** Usage: sqlite3_memdebug_malloc_count
563**
564** Return the total number of times malloc() has been called.
565*/
mistachkin7617e4a2016-07-28 17:11:20566static int SQLITE_TCLAPI test_memdebug_malloc_count(
danielk1977a7a8e142008-02-13 18:25:27567 void * clientData,
568 Tcl_Interp *interp,
569 int objc,
570 Tcl_Obj *CONST objv[]
571){
572 int nMalloc = -1;
573 if( objc!=1 ){
574 Tcl_WrongNumArgs(interp, 1, objv, "");
575 return TCL_ERROR;
576 }
577#if defined(SQLITE_MEMDEBUG)
578 {
drh49e4fd72008-02-19 15:15:15579 extern int sqlite3MemdebugMallocCount();
580 nMalloc = sqlite3MemdebugMallocCount();
danielk1977a7a8e142008-02-13 18:25:27581 }
582#endif
583 Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc));
584 return TCL_OK;
585}
586
drh2f999a62007-08-15 19:16:43587
588/*
danielk1977a1644fd2007-08-29 12:31:25589** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?
590**
591** where options are:
592**
drh643167f2008-01-22 21:30:53593** -repeat <count>
danielk1977a1644fd2007-08-29 12:31:25594** -benigncnt <varname>
drh0e6f1542007-08-15 20:41:28595**
596** Arrange for a simulated malloc() failure after COUNTER successes.
drh643167f2008-01-22 21:30:53597** If a repeat count is specified, the fault is repeated that many
598** times.
drh0e6f1542007-08-15 20:41:28599**
600** Each call to this routine overrides the prior counter value.
601** This routine returns the number of simulated failures that have
602** happened since the previous call to this routine.
603**
604** To disable simulated failures, use a COUNTER of -1.
605*/
mistachkin7617e4a2016-07-28 17:11:20606static int SQLITE_TCLAPI test_memdebug_fail(
drh0e6f1542007-08-15 20:41:28607 void * clientData,
608 Tcl_Interp *interp,
609 int objc,
610 Tcl_Obj *CONST objv[]
611){
danielk1977a1644fd2007-08-29 12:31:25612 int ii;
drh0e6f1542007-08-15 20:41:28613 int iFail;
drh643167f2008-01-22 21:30:53614 int nRepeat = 1;
danielk1977a1644fd2007-08-29 12:31:25615 Tcl_Obj *pBenignCnt = 0;
drh643167f2008-01-22 21:30:53616 int nBenign;
drh0e6f1542007-08-15 20:41:28617 int nFail = 0;
danielk1977a1644fd2007-08-29 12:31:25618
619 if( objc<2 ){
620 Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?");
drh0e6f1542007-08-15 20:41:28621 return TCL_ERROR;
622 }
623 if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;
danielk1977a1644fd2007-08-29 12:31:25624
625 for(ii=2; ii<objc; ii+=2){
drh064b6812024-07-30 15:49:02626 Tcl_Size nOption;
danielk1977a1644fd2007-08-29 12:31:25627 char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);
628 char *zErr = 0;
629
630 if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){
631 if( ii==(objc-1) ){
632 zErr = "option requires an argument: ";
633 }else{
drh643167f2008-01-22 21:30:53634 if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){
danielk1977a1644fd2007-08-29 12:31:25635 return TCL_ERROR;
636 }
637 }
638 }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){
639 if( ii==(objc-1) ){
640 zErr = "option requires an argument: ";
641 }else{
642 pBenignCnt = objv[ii+1];
643 }
644 }else{
645 zErr = "unknown option: ";
646 }
647
648 if( zErr ){
stephanb6503f12025-03-06 13:38:07649 Tcl_AppendResult(interp, zErr, zOption, NULL);
danielk1977a1644fd2007-08-29 12:31:25650 return TCL_ERROR;
651 }
drhed138fb2007-08-22 22:04:37652 }
danielk1977a1644fd2007-08-29 12:31:25653
danielk1977ef05f2d2008-06-20 11:05:37654 nBenign = faultsimBenignFailures();
655 nFail = faultsimFailures();
656 faultsimConfig(iFail, nRepeat);
657
drh643167f2008-01-22 21:30:53658 if( pBenignCnt ){
659 Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
drh0e6f1542007-08-15 20:41:28660 }
drh0e6f1542007-08-15 20:41:28661 Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
662 return TCL_OK;
663}
664
danielk1977cd037242007-08-30 15:46:06665/*
666** Usage: sqlite3_memdebug_pending
667**
668** Return the number of malloc() calls that will succeed before a
669** simulated failure occurs. A negative return value indicates that
670** no malloc() failure is scheduled.
671*/
mistachkin7617e4a2016-07-28 17:11:20672static int SQLITE_TCLAPI test_memdebug_pending(
danielk1977cd037242007-08-30 15:46:06673 void * clientData,
674 Tcl_Interp *interp,
675 int objc,
676 Tcl_Obj *CONST objv[]
677){
drh5efaf072008-03-18 00:07:10678 int nPending;
danielk1977cd037242007-08-30 15:46:06679 if( objc!=1 ){
680 Tcl_WrongNumArgs(interp, 1, objv, "");
681 return TCL_ERROR;
682 }
danielk1977ef05f2d2008-06-20 11:05:37683 nPending = faultsimPending();
drh5efaf072008-03-18 00:07:10684 Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
danielk1977cd037242007-08-30 15:46:06685 return TCL_OK;
686}
687
drh44ee1dc2014-09-06 03:16:28688/*
689** The following global variable keeps track of the number of tests
690** that have run. This variable is only useful when running in the
691** debugger.
692*/
693static int sqlite3_memdebug_title_count = 0;
drh0e6f1542007-08-15 20:41:28694
695/*
drh4a50aac2007-08-23 02:47:53696** Usage: sqlite3_memdebug_settitle TITLE
697**
698** Set a title string stored with each allocation. The TITLE is
699** typically the name of the test that was running when the
700** allocation occurred. The TITLE is stored with the allocation
701** and can be used to figure out which tests are leaking memory.
702**
703** Each title overwrite the previous.
704*/
mistachkin7617e4a2016-07-28 17:11:20705static int SQLITE_TCLAPI test_memdebug_settitle(
drh4a50aac2007-08-23 02:47:53706 void * clientData,
707 Tcl_Interp *interp,
708 int objc,
709 Tcl_Obj *CONST objv[]
710){
drh44ee1dc2014-09-06 03:16:28711 sqlite3_memdebug_title_count++;
drh4a50aac2007-08-23 02:47:53712 if( objc!=2 ){
713 Tcl_WrongNumArgs(interp, 1, objv, "TITLE");
714 return TCL_ERROR;
715 }
drh4a50aac2007-08-23 02:47:53716#ifdef SQLITE_MEMDEBUG
717 {
drhcaffb1a2012-01-30 18:00:31718 const char *zTitle;
drh49e4fd72008-02-19 15:15:15719 extern int sqlite3MemdebugSettitle(const char*);
mistachkina359b5e2012-12-04 00:37:58720 zTitle = Tcl_GetString(objv[1]);
drh49e4fd72008-02-19 15:15:15721 sqlite3MemdebugSettitle(zTitle);
drh4a50aac2007-08-23 02:47:53722 }
723#endif
724 return TCL_OK;
725}
726
danec561a32010-08-09 14:47:50727#define MALLOC_LOG_FRAMES 10
728#define MALLOC_LOG_KEYINTS ( \
729 10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \
730)
danielk19776f332c12008-03-21 14:22:44731static Tcl_HashTable aMallocLog;
732static int mallocLogEnabled = 0;
733
734typedef struct MallocLog MallocLog;
735struct MallocLog {
736 int nCall;
737 int nByte;
738};
739
shaneafdd23a2008-05-29 02:57:47740#ifdef SQLITE_MEMDEBUG
danielk19776f332c12008-03-21 14:22:44741static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){
742 if( mallocLogEnabled ){
743 MallocLog *pLog;
744 Tcl_HashEntry *pEntry;
745 int isNew;
746
danec561a32010-08-09 14:47:50747 int aKey[MALLOC_LOG_KEYINTS];
mistachkinf6418892013-08-28 01:54:12748 unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS;
danielk19776f332c12008-03-21 14:22:44749
750 memset(aKey, 0, nKey);
751 if( (sizeof(void*)*nFrame)<nKey ){
752 nKey = nFrame*sizeof(void*);
753 }
754 memcpy(aKey, aFrame, nKey);
755
756 pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew);
757 if( isNew ){
758 pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog));
759 memset(pLog, 0, sizeof(MallocLog));
760 Tcl_SetHashValue(pEntry, (ClientData)pLog);
761 }else{
762 pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
763 }
764
765 pLog->nCall++;
766 pLog->nByte += nByte;
767 }
768}
shaneafdd23a2008-05-29 02:57:47769#endif /* SQLITE_MEMDEBUG */
danielk19776f332c12008-03-21 14:22:44770
danielk197764aca192009-04-07 11:21:28771static void test_memdebug_log_clear(void){
danielk1977dbdc4d42008-03-28 07:42:53772 Tcl_HashSearch search;
773 Tcl_HashEntry *pEntry;
774 for(
775 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
776 pEntry;
777 pEntry=Tcl_NextHashEntry(&search)
778 ){
779 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
780 Tcl_Free((char *)pLog);
781 }
782 Tcl_DeleteHashTable(&aMallocLog);
danec561a32010-08-09 14:47:50783 Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
danielk1977dbdc4d42008-03-28 07:42:53784}
785
mistachkin7617e4a2016-07-28 17:11:20786static int SQLITE_TCLAPI test_memdebug_log(
danielk19776f332c12008-03-21 14:22:44787 void * clientData,
788 Tcl_Interp *interp,
789 int objc,
790 Tcl_Obj *CONST objv[]
791){
792 static int isInit = 0;
793 int iSub;
794
danielk1977dbdc4d42008-03-28 07:42:53795 static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" };
796 enum MB_enum {
797 MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC
798 };
danielk19776f332c12008-03-21 14:22:44799
800 if( !isInit ){
801#ifdef SQLITE_MEMDEBUG
802 extern void sqlite3MemdebugBacktraceCallback(
803 void (*xBacktrace)(int, int, void **));
804 sqlite3MemdebugBacktraceCallback(test_memdebug_callback);
805#endif
danec561a32010-08-09 14:47:50806 Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
danielk19776f332c12008-03-21 14:22:44807 isInit = 1;
808 }
809
810 if( objc<2 ){
811 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
812 }
813 if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){
814 return TCL_ERROR;
815 }
816
817 switch( (enum MB_enum)iSub ){
818 case MB_LOG_START:
819 mallocLogEnabled = 1;
820 break;
821 case MB_LOG_STOP:
822 mallocLogEnabled = 0;
823 break;
824 case MB_LOG_DUMP: {
825 Tcl_HashSearch search;
826 Tcl_HashEntry *pEntry;
827 Tcl_Obj *pRet = Tcl_NewObj();
828
danec561a32010-08-09 14:47:50829 assert(sizeof(Tcl_WideInt)>=sizeof(void*));
danielk19776f332c12008-03-21 14:22:44830
831 for(
832 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
833 pEntry;
834 pEntry=Tcl_NextHashEntry(&search)
835 ){
836 Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];
837 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
danec561a32010-08-09 14:47:50838 Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry);
danielk19776f332c12008-03-21 14:22:44839 int ii;
840
841 apElem[0] = Tcl_NewIntObj(pLog->nCall);
842 apElem[1] = Tcl_NewIntObj(pLog->nByte);
843 for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){
danec561a32010-08-09 14:47:50844 apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]);
danielk19776f332c12008-03-21 14:22:44845 }
846
847 Tcl_ListObjAppendElement(interp, pRet,
848 Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem)
849 );
850 }
851
852 Tcl_SetObjResult(interp, pRet);
853 break;
854 }
855 case MB_LOG_CLEAR: {
danielk1977dbdc4d42008-03-28 07:42:53856 test_memdebug_log_clear();
857 break;
858 }
859
860 case MB_LOG_SYNC: {
drhb9404922008-03-28 12:53:38861#ifdef SQLITE_MEMDEBUG
danielk1977dbdc4d42008-03-28 07:42:53862 extern void sqlite3MemdebugSync();
863 test_memdebug_log_clear();
864 mallocLogEnabled = 1;
865 sqlite3MemdebugSync();
drhb9404922008-03-28 12:53:38866#endif
danielk1977dbdc4d42008-03-28 07:42:53867 break;
danielk19776f332c12008-03-21 14:22:44868 }
869 }
870
871 return TCL_OK;
872}
drh4a50aac2007-08-23 02:47:53873
874/*
drh9ac3fe92008-06-18 18:12:04875** Usage: sqlite3_config_pagecache SIZE N
876**
877** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
878** The buffer is static and is of limited size. N might be
peter.d.reid60ec9142014-09-06 16:39:46879** adjusted downward as needed to accommodate the requested size.
drh9ac3fe92008-06-18 18:12:04880** The revised value of N is returned.
881**
882** A negative SIZE causes the buffer pointer to be NULL.
883*/
mistachkin7617e4a2016-07-28 17:11:20884static int SQLITE_TCLAPI test_config_pagecache(
drh9ac3fe92008-06-18 18:12:04885 void * clientData,
886 Tcl_Interp *interp,
887 int objc,
888 Tcl_Obj *CONST objv[]
889){
drh6bacdc22015-07-24 17:14:03890 int sz, N;
dan03bc5252015-07-24 14:17:17891 Tcl_Obj *pRes;
drh5f4bcf12008-07-29 14:29:06892 static char *buf = 0;
drh9ac3fe92008-06-18 18:12:04893 if( objc!=3 ){
894 Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
895 return TCL_ERROR;
896 }
drhf7141992008-06-19 00:16:08897 if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
898 if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
drh5f4bcf12008-07-29 14:29:06899 free(buf);
dan03bc5252015-07-24 14:17:17900 buf = 0;
901
902 /* Set the return value */
903 pRes = Tcl_NewObj();
904 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.szPage));
905 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.nPage));
906 Tcl_SetObjResult(interp, pRes);
907
drh9ac3fe92008-06-18 18:12:04908 if( sz<0 ){
drha6082f62015-11-26 22:12:41909 sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, 0);
drhf7141992008-06-19 00:16:08910 }else{
drh0a60a382008-07-31 17:16:05911 buf = malloc( sz*N );
drh6bacdc22015-07-24 17:14:03912 sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
drh9ac3fe92008-06-18 18:12:04913 }
drh9ac3fe92008-06-18 18:12:04914 return TCL_OK;
915}
916
drhf7141992008-06-19 00:16:08917/*
drhb232c232008-11-19 01:20:26918** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED
919**
920** Set up the alternative test page cache. Install if INSTALL_FLAG is
921** true and uninstall (reverting to the default page cache) if INSTALL_FLAG
922** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive
923** which determines the chance of discarding a page when unpinned. 100
924** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator
925** seed.
926*/
mistachkin7617e4a2016-07-28 17:11:20927static int SQLITE_TCLAPI test_alt_pcache(
drhb232c232008-11-19 01:20:26928 void * clientData,
929 Tcl_Interp *interp,
930 int objc,
931 Tcl_Obj *CONST objv[]
932){
933 int installFlag;
drhf2a84e32009-01-07 03:59:47934 int discardChance = 0;
935 int prngSeed = 0;
936 int highStress = 0;
937 extern void installTestPCache(int,unsigned,unsigned,unsigned);
938 if( objc<2 || objc>5 ){
939 Tcl_WrongNumArgs(interp, 1, objv,
940 "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS");
drhb232c232008-11-19 01:20:26941 return TCL_ERROR;
942 }
943 if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR;
drhf2a84e32009-01-07 03:59:47944 if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){
945 return TCL_ERROR;
946 }
947 if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){
948 return TCL_ERROR;
949 }
950 if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){
951 return TCL_ERROR;
952 }
drhb232c232008-11-19 01:20:26953 if( discardChance<0 || discardChance>100 ){
954 Tcl_AppendResult(interp, "discard-chance should be between 0 and 100",
955 (char*)0);
956 return TCL_ERROR;
957 }
drhf2a84e32009-01-07 03:59:47958 installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed,
959 (unsigned)highStress);
drhb232c232008-11-19 01:20:26960 return TCL_OK;
961}
962
963/*
drh8a42cbd2008-07-10 18:13:42964** Usage: sqlite3_config_memstatus BOOLEAN
965**
966** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS.
967*/
mistachkin7617e4a2016-07-28 17:11:20968static int SQLITE_TCLAPI test_config_memstatus(
drh8a42cbd2008-07-10 18:13:42969 void * clientData,
970 Tcl_Interp *interp,
971 int objc,
972 Tcl_Obj *CONST objv[]
973){
974 int enable, rc;
975 if( objc!=2 ){
976 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
977 return TCL_ERROR;
978 }
979 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;
980 rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);
981 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
982 return TCL_OK;
983}
984
985/*
drh633e6d52008-07-28 19:34:53986** Usage: sqlite3_config_lookaside SIZE COUNT
987**
988*/
mistachkin7617e4a2016-07-28 17:11:20989static int SQLITE_TCLAPI test_config_lookaside(
drh633e6d52008-07-28 19:34:53990 void * clientData,
991 Tcl_Interp *interp,
992 int objc,
993 Tcl_Obj *CONST objv[]
994){
drh633e6d52008-07-28 19:34:53995 int sz, cnt;
danielk1977ab7bee82008-10-15 11:43:55996 Tcl_Obj *pRet;
drh633e6d52008-07-28 19:34:53997 if( objc!=3 ){
998 Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");
999 return TCL_ERROR;
1000 }
1001 if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
1002 if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR;
danielk1977ab7bee82008-10-15 11:43:551003 pRet = Tcl_NewObj();
1004 Tcl_ListObjAppendElement(
1005 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside)
1006 );
1007 Tcl_ListObjAppendElement(
1008 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside)
1009 );
drhcaffb1a2012-01-30 18:00:311010 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);
danielk1977ab7bee82008-10-15 11:43:551011 Tcl_SetObjResult(interp, pRet);
drh633e6d52008-07-28 19:34:531012 return TCL_OK;
1013}
1014
1015
1016/*
drhe9d1c722008-08-04 20:13:261017** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT
drh633e6d52008-07-28 19:34:531018**
drhe9d1c722008-08-04 20:13:261019** There are two static buffers with BUFID 1 and 2. Each static buffer
1020** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL
1021** which will cause sqlite3_db_config() to allocate space on its own.
drh633e6d52008-07-28 19:34:531022*/
mistachkin7617e4a2016-07-28 17:11:201023static int SQLITE_TCLAPI test_db_config_lookaside(
drh633e6d52008-07-28 19:34:531024 void * clientData,
1025 Tcl_Interp *interp,
1026 int objc,
1027 Tcl_Obj *CONST objv[]
1028){
1029 int rc;
1030 int sz, cnt;
1031 sqlite3 *db;
drhe9d1c722008-08-04 20:13:261032 int bufid;
1033 static char azBuf[2][10000];
mistachkine84d8d32013-04-29 03:09:101034 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
drhe9d1c722008-08-04 20:13:261035 if( objc!=5 ){
1036 Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT");
drh633e6d52008-07-28 19:34:531037 return TCL_ERROR;
1038 }
1039 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhe9d1c722008-08-04 20:13:261040 if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR;
1041 if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR;
1042 if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR;
1043 if( bufid==0 ){
drhaed11f22016-04-05 14:02:161044 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt);
drhe9d1c722008-08-04 20:13:261045 }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){
1046 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt);
1047 }else{
1048 Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0);
1049 return TCL_ERROR;
1050 }
drh633e6d52008-07-28 19:34:531051 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
1052 return TCL_OK;
1053}
1054
1055/*
mistachkin8765b462012-09-10 08:48:051056** Usage: sqlite3_config_heap NBYTE NMINALLOC
danielk19775099be52008-06-27 13:27:031057*/
mistachkin7617e4a2016-07-28 17:11:201058static int SQLITE_TCLAPI test_config_heap(
danielk19775099be52008-06-27 13:27:031059 void * clientData,
1060 Tcl_Interp *interp,
1061 int objc,
1062 Tcl_Obj *CONST objv[]
1063){
drh7830cd42008-07-16 12:25:321064 static char *zBuf; /* Use this memory */
danielk19775099be52008-06-27 13:27:031065 int nByte; /* Size of buffer to pass to sqlite3_config() */
1066 int nMinAlloc; /* Size of minimum allocation */
1067 int rc; /* Return code of sqlite3_config() */
danielk19775099be52008-06-27 13:27:031068
1069 Tcl_Obj * CONST *aArg = &objv[1];
1070 int nArg = objc-1;
1071
danielk19775099be52008-06-27 13:27:031072 if( nArg!=2 ){
drh8a42cbd2008-07-10 18:13:421073 Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC");
danielk19775099be52008-06-27 13:27:031074 return TCL_ERROR;
1075 }
1076 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
1077 if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR;
1078
danielk19770d84e5b2008-06-27 14:05:241079 if( nByte==0 ){
drh7830cd42008-07-16 12:25:321080 free( zBuf );
1081 zBuf = 0;
drh8a42cbd2008-07-10 18:13:421082 rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0);
danielk19770d84e5b2008-06-27 14:05:241083 }else{
drh7830cd42008-07-16 12:25:321084 zBuf = realloc(zBuf, nByte);
danielk19770d84e5b2008-06-27 14:05:241085 rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc);
danielk19775099be52008-06-27 13:27:031086 }
danielk19775099be52008-06-27 13:27:031087
mistachkine84d8d32013-04-29 03:09:101088 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
danielk19775099be52008-06-27 13:27:031089 return TCL_OK;
1090}
1091
1092/*
mistachkinac1f1042013-11-23 00:27:291093** Usage: sqlite3_config_heap_size NBYTE
1094*/
mistachkin7617e4a2016-07-28 17:11:201095static int SQLITE_TCLAPI test_config_heap_size(
mistachkinac1f1042013-11-23 00:27:291096 void * clientData,
1097 Tcl_Interp *interp,
1098 int objc,
1099 Tcl_Obj *CONST objv[]
1100){
1101 int nByte; /* Size to pass to sqlite3_config() */
1102 int rc; /* Return code of sqlite3_config() */
1103
1104 Tcl_Obj * CONST *aArg = &objv[1];
1105 int nArg = objc-1;
1106
1107 if( nArg!=1 ){
1108 Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
1109 return TCL_ERROR;
1110 }
1111 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
1112
mistachkinaf8641b2013-11-25 21:49:041113 rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte);
mistachkinac1f1042013-11-23 00:27:291114
1115 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1116 return TCL_OK;
1117}
1118
1119/*
mistachkin8765b462012-09-10 08:48:051120** Usage: sqlite3_config_error [DB]
drh6480aad2008-08-01 16:31:141121**
1122** Invoke sqlite3_config() or sqlite3_db_config() with invalid
1123** opcodes and verify that they return errors.
1124*/
mistachkin7617e4a2016-07-28 17:11:201125static int SQLITE_TCLAPI test_config_error(
drh6480aad2008-08-01 16:31:141126 void * clientData,
1127 Tcl_Interp *interp,
1128 int objc,
1129 Tcl_Obj *CONST objv[]
1130){
1131 sqlite3 *db;
mistachkine84d8d32013-04-29 03:09:101132 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
drh6480aad2008-08-01 16:31:141133
1134 if( objc!=2 && objc!=1 ){
1135 Tcl_WrongNumArgs(interp, 1, objv, "[DB]");
1136 return TCL_ERROR;
1137 }
1138 if( objc==2 ){
1139 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1140 if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){
1141 Tcl_AppendResult(interp,
1142 "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR",
1143 (char*)0);
1144 return TCL_ERROR;
1145 }
1146 }else{
1147 if( sqlite3_config(99999)!=SQLITE_ERROR ){
1148 Tcl_AppendResult(interp,
1149 "sqlite3_config(99999) does not return SQLITE_ERROR",
1150 (char*)0);
1151 return TCL_ERROR;
1152 }
1153 }
1154 return TCL_OK;
1155}
1156
1157/*
mistachkin8765b462012-09-10 08:48:051158** Usage: sqlite3_config_uri BOOLEAN
dancd74b612011-04-22 19:37:321159**
mistachkin8765b462012-09-10 08:48:051160** Enables or disables interpretation of URI parameters by default using
1161** SQLITE_CONFIG_URI.
dancd74b612011-04-22 19:37:321162*/
mistachkin7617e4a2016-07-28 17:11:201163static int SQLITE_TCLAPI test_config_uri(
dancd74b612011-04-22 19:37:321164 void * clientData,
1165 Tcl_Interp *interp,
1166 int objc,
1167 Tcl_Obj *CONST objv[]
1168){
1169 int rc;
1170 int bOpenUri;
1171
1172 if( objc!=2 ){
1173 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1174 return TCL_ERROR;
1175 }
1176 if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
1177 return TCL_ERROR;
1178 }
1179
1180 rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
mistachkine84d8d32013-04-29 03:09:101181 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
dancd74b612011-04-22 19:37:321182
1183 return TCL_OK;
1184}
1185
1186/*
drhde9a7b82012-09-17 20:44:461187** Usage: sqlite3_config_cis BOOLEAN
1188**
1189** Enables or disables the use of the covering-index scan optimization.
1190** SQLITE_CONFIG_COVERING_INDEX_SCAN.
1191*/
mistachkin7617e4a2016-07-28 17:11:201192static int SQLITE_TCLAPI test_config_cis(
drhde9a7b82012-09-17 20:44:461193 void * clientData,
1194 Tcl_Interp *interp,
1195 int objc,
1196 Tcl_Obj *CONST objv[]
1197){
1198 int rc;
1199 int bUseCis;
1200
1201 if( objc!=2 ){
1202 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1203 return TCL_ERROR;
1204 }
1205 if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){
1206 return TCL_ERROR;
1207 }
1208
1209 rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
mistachkine84d8d32013-04-29 03:09:101210 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
drhde9a7b82012-09-17 20:44:461211
1212 return TCL_OK;
1213}
1214
drh3bd17912015-01-02 15:55:291215/*
1216** Usage: sqlite3_config_pmasz INTEGER
1217**
1218** Set the minimum PMA size.
1219*/
mistachkin7617e4a2016-07-28 17:11:201220static int SQLITE_TCLAPI test_config_pmasz(
drh3bd17912015-01-02 15:55:291221 void * clientData,
1222 Tcl_Interp *interp,
1223 int objc,
1224 Tcl_Obj *CONST objv[]
1225){
1226 int rc;
1227 int iPmaSz;
1228
1229 if( objc!=2 ){
1230 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1231 return TCL_ERROR;
1232 }
1233 if( Tcl_GetIntFromObj(interp, objv[1], &iPmaSz) ){
1234 return TCL_ERROR;
1235 }
1236
1237 rc = sqlite3_config(SQLITE_CONFIG_PMASZ, iPmaSz);
1238 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1239
1240 return TCL_OK;
1241}
1242
dan578e1ca2014-04-01 15:38:441243
1244/*
mistachkin8765b462012-09-10 08:48:051245** Usage: sqlite3_dump_memsys3 FILENAME
1246** sqlite3_dump_memsys5 FILENAME
danielk197732155ef2008-06-25 10:34:341247**
1248** Write a summary of unfreed memsys3 allocations to FILENAME.
1249*/
mistachkin7617e4a2016-07-28 17:11:201250static int SQLITE_TCLAPI test_dump_memsys3(
danielk197732155ef2008-06-25 10:34:341251 void * clientData,
1252 Tcl_Interp *interp,
1253 int objc,
1254 Tcl_Obj *CONST objv[]
1255){
1256 if( objc!=2 ){
1257 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
1258 return TCL_ERROR;
1259 }
danielk1977c66c0e12008-06-25 14:26:071260
drh860e3322011-08-25 18:54:461261 switch( SQLITE_PTR_TO_INT(clientData) ){
danielk19770d84e5b2008-06-27 14:05:241262 case 3: {
danielk1977c66c0e12008-06-25 14:26:071263#ifdef SQLITE_ENABLE_MEMSYS3
1264 extern void sqlite3Memsys3Dump(const char*);
1265 sqlite3Memsys3Dump(Tcl_GetString(objv[1]));
1266 break;
danielk197732155ef2008-06-25 10:34:341267#endif
danielk1977c66c0e12008-06-25 14:26:071268 }
danielk19770d84e5b2008-06-27 14:05:241269 case 5: {
danielk1977c66c0e12008-06-25 14:26:071270#ifdef SQLITE_ENABLE_MEMSYS5
1271 extern void sqlite3Memsys5Dump(const char*);
1272 sqlite3Memsys5Dump(Tcl_GetString(objv[1]));
1273 break;
1274#endif
1275 }
1276 }
danielk197732155ef2008-06-25 10:34:341277 return TCL_OK;
1278}
1279
1280/*
drhf7141992008-06-19 00:16:081281** Usage: sqlite3_status OPCODE RESETFLAG
1282**
1283** Return a list of three elements which are the sqlite3_status() return
1284** code, the current value, and the high-water mark value.
1285*/
mistachkin7617e4a2016-07-28 17:11:201286static int SQLITE_TCLAPI test_status(
drhf7141992008-06-19 00:16:081287 void * clientData,
1288 Tcl_Interp *interp,
1289 int objc,
1290 Tcl_Obj *CONST objv[]
1291){
1292 int rc, iValue, mxValue;
mistachkin7bb22ac2015-01-12 19:59:121293 int i, op = 0, resetFlag;
drhf7141992008-06-19 00:16:081294 const char *zOpName;
1295 static const struct {
1296 const char *zName;
1297 int op;
1298 } aOp[] = {
1299 { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED },
drhe50135e2008-08-05 17:53:221300 { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE },
drhf7141992008-06-19 00:16:081301 { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED },
1302 { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW },
drhe50135e2008-08-05 17:53:221303 { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE },
drhf7141992008-06-19 00:16:081304 { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED },
1305 { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
drhe50135e2008-08-05 17:53:221306 { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE },
drhec424a52008-07-25 15:39:031307 { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK },
drheafc43b2010-07-26 18:43:401308 { "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT },
drhf7141992008-06-19 00:16:081309 };
1310 Tcl_Obj *pResult;
1311 if( objc!=3 ){
1312 Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
1313 return TCL_ERROR;
1314 }
1315 zOpName = Tcl_GetString(objv[1]);
1316 for(i=0; i<ArraySize(aOp); i++){
1317 if( strcmp(aOp[i].zName, zOpName)==0 ){
1318 op = aOp[i].op;
1319 break;
1320 }
1321 }
1322 if( i>=ArraySize(aOp) ){
1323 if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR;
1324 }
1325 if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR;
drhaf005fb2008-07-09 16:51:511326 iValue = 0;
1327 mxValue = 0;
drhf7141992008-06-19 00:16:081328 rc = sqlite3_status(op, &iValue, &mxValue, resetFlag);
1329 pResult = Tcl_NewObj();
1330 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1331 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1332 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1333 Tcl_SetObjResult(interp, pResult);
1334 return TCL_OK;
1335}
drh9ac3fe92008-06-18 18:12:041336
1337/*
drh633e6d52008-07-28 19:34:531338** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG
1339**
1340** Return a list of three elements which are the sqlite3_db_status() return
1341** code, the current value, and the high-water mark value.
1342*/
mistachkin7617e4a2016-07-28 17:11:201343static int SQLITE_TCLAPI test_db_status(
drh633e6d52008-07-28 19:34:531344 void * clientData,
1345 Tcl_Interp *interp,
1346 int objc,
1347 Tcl_Obj *CONST objv[]
1348){
1349 int rc, iValue, mxValue;
mistachkin7bb22ac2015-01-12 19:59:121350 int i, op = 0, resetFlag;
drh633e6d52008-07-28 19:34:531351 const char *zOpName;
1352 sqlite3 *db;
mistachkine84d8d32013-04-29 03:09:101353 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
drh633e6d52008-07-28 19:34:531354 static const struct {
1355 const char *zName;
1356 int op;
1357 } aOp[] = {
drh2a58e9c2010-12-21 21:28:381358 { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
1359 { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
1360 { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
1361 { "STMT_USED", SQLITE_DBSTATUS_STMT_USED },
1362 { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT },
1363 { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
dan58ca31c2011-09-22 14:41:161364 { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL },
1365 { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT },
drh9ad3ee42012-03-24 20:06:141366 { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS },
drh648e2642013-07-11 15:03:321367 { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE },
dan272989b2016-07-06 10:12:021368 { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS },
dan9c106082016-07-06 18:12:541369 { "CACHE_USED_SHARED", SQLITE_DBSTATUS_CACHE_USED_SHARED },
drhffc78a42018-03-14 14:53:501370 { "CACHE_SPILL", SQLITE_DBSTATUS_CACHE_SPILL },
drh633e6d52008-07-28 19:34:531371 };
1372 Tcl_Obj *pResult;
1373 if( objc!=4 ){
dan58ca31c2011-09-22 14:41:161374 Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG");
drh633e6d52008-07-28 19:34:531375 return TCL_ERROR;
1376 }
1377 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1378 zOpName = Tcl_GetString(objv[2]);
drh2a58e9c2010-12-21 21:28:381379 if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7;
1380 if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9;
drh633e6d52008-07-28 19:34:531381 for(i=0; i<ArraySize(aOp); i++){
1382 if( strcmp(aOp[i].zName, zOpName)==0 ){
1383 op = aOp[i].op;
1384 break;
1385 }
1386 }
1387 if( i>=ArraySize(aOp) ){
1388 if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
1389 }
1390 if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
1391 iValue = 0;
1392 mxValue = 0;
1393 rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag);
1394 pResult = Tcl_NewObj();
1395 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1396 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1397 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1398 Tcl_SetObjResult(interp, pResult);
1399 return TCL_OK;
1400}
1401
1402/*
danielk1977d09414c2008-06-19 18:17:491403** install_malloc_faultsim BOOLEAN
1404*/
mistachkin7617e4a2016-07-28 17:11:201405static int SQLITE_TCLAPI test_install_malloc_faultsim(
danielk1977d09414c2008-06-19 18:17:491406 void * clientData,
1407 Tcl_Interp *interp,
1408 int objc,
1409 Tcl_Obj *CONST objv[]
1410){
1411 int rc;
1412 int isInstall;
1413
1414 if( objc!=2 ){
1415 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1416 return TCL_ERROR;
1417 }
1418 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
1419 return TCL_ERROR;
1420 }
danielk1977ef05f2d2008-06-20 11:05:371421 rc = faultsimInstall(isInstall);
mistachkine84d8d32013-04-29 03:09:101422 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
danielk1977d09414c2008-06-19 18:17:491423 return TCL_OK;
1424}
1425
1426/*
danielk19778b322822009-07-01 18:09:011427** sqlite3_install_memsys3
1428*/
mistachkin7617e4a2016-07-28 17:11:201429static int SQLITE_TCLAPI test_install_memsys3(
danielk19778b322822009-07-01 18:09:011430 void * clientData,
1431 Tcl_Interp *interp,
1432 int objc,
1433 Tcl_Obj *CONST objv[]
1434){
1435 int rc = SQLITE_MISUSE;
1436#ifdef SQLITE_ENABLE_MEMSYS3
1437 const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
1438 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetMemsys3());
1439#endif
mistachkine84d8d32013-04-29 03:09:101440 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
danielk19778b322822009-07-01 18:09:011441 return TCL_OK;
1442}
1443
mistachkin7617e4a2016-07-28 17:11:201444static int SQLITE_TCLAPI test_vfs_oom_test(
danc396d4a2010-07-02 11:27:431445 void * clientData,
1446 Tcl_Interp *interp,
1447 int objc,
1448 Tcl_Obj *CONST objv[]
1449){
1450 extern int sqlite3_memdebug_vfs_oom_test;
1451 if( objc>2 ){
1452 Tcl_WrongNumArgs(interp, 1, objv, "?INTEGER?");
1453 return TCL_ERROR;
1454 }else if( objc==2 ){
1455 int iNew;
1456 if( Tcl_GetIntFromObj(interp, objv[1], &iNew) ) return TCL_ERROR;
1457 sqlite3_memdebug_vfs_oom_test = iNew;
1458 }
1459 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_vfs_oom_test));
1460 return TCL_OK;
1461}
1462
danielk19778b322822009-07-01 18:09:011463/*
drh2f999a62007-08-15 19:16:431464** Register commands with the TCL interpreter.
1465*/
1466int Sqlitetest_malloc_Init(Tcl_Interp *interp){
1467 static struct {
1468 char *zName;
1469 Tcl_ObjCmdProc *xProc;
danielk1977c66c0e12008-06-25 14:26:071470 int clientData;
drh2f999a62007-08-15 19:16:431471 } aObjCmd[] = {
drh8a42cbd2008-07-10 18:13:421472 { "sqlite3_malloc", test_malloc ,0 },
1473 { "sqlite3_realloc", test_realloc ,0 },
1474 { "sqlite3_free", test_free ,0 },
1475 { "memset", test_memset ,0 },
1476 { "memget", test_memget ,0 },
1477 { "sqlite3_memory_used", test_memory_used ,0 },
1478 { "sqlite3_memory_highwater", test_memory_highwater ,0 },
1479 { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 },
1480 { "sqlite3_memdebug_dump", test_memdebug_dump ,0 },
1481 { "sqlite3_memdebug_fail", test_memdebug_fail ,0 },
1482 { "sqlite3_memdebug_pending", test_memdebug_pending ,0 },
1483 { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 },
1484 { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 },
1485 { "sqlite3_memdebug_log", test_memdebug_log ,0 },
drh8a42cbd2008-07-10 18:13:421486 { "sqlite3_config_pagecache", test_config_pagecache ,0 },
drhb232c232008-11-19 01:20:261487 { "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
drh8a42cbd2008-07-10 18:13:421488 { "sqlite3_status", test_status ,0 },
drh633e6d52008-07-28 19:34:531489 { "sqlite3_db_status", test_db_status ,0 },
drh8a42cbd2008-07-10 18:13:421490 { "install_malloc_faultsim", test_install_malloc_faultsim ,0 },
danielk19770d84e5b2008-06-27 14:05:241491 { "sqlite3_config_heap", test_config_heap ,0 },
mistachkinac1f1042013-11-23 00:27:291492 { "sqlite3_config_heap_size", test_config_heap_size ,0 },
drh8a42cbd2008-07-10 18:13:421493 { "sqlite3_config_memstatus", test_config_memstatus ,0 },
drh633e6d52008-07-28 19:34:531494 { "sqlite3_config_lookaside", test_config_lookaside ,0 },
drh6480aad2008-08-01 16:31:141495 { "sqlite3_config_error", test_config_error ,0 },
dancd74b612011-04-22 19:37:321496 { "sqlite3_config_uri", test_config_uri ,0 },
drhde9a7b82012-09-17 20:44:461497 { "sqlite3_config_cis", test_config_cis ,0 },
drh3bd17912015-01-02 15:55:291498 { "sqlite3_config_pmasz", test_config_pmasz ,0 },
drh633e6d52008-07-28 19:34:531499 { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
danielk19770d84e5b2008-06-27 14:05:241500 { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
drhb232c232008-11-19 01:20:261501 { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
danielk19778b322822009-07-01 18:09:011502 { "sqlite3_install_memsys3", test_install_memsys3 ,0 },
danc396d4a2010-07-02 11:27:431503 { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 },
drh2f999a62007-08-15 19:16:431504 };
1505 int i;
1506 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
drh860e3322011-08-25 18:54:461507 ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData);
danielk1977c66c0e12008-06-25 14:26:071508 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
drh2f999a62007-08-15 19:16:431509 }
1510 return TCL_OK;
1511}
danielk1977ef05f2d2008-06-20 11:05:371512#endif