blob: 32a03e71911e847d8a986aa762adc8952205b50c [file] [log] [blame]
drh2f999a62007-08-15 19:16:43 +00001/*
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:43 +000015*/
16#include "sqliteInt.h"
mistachkin52b1dbb2016-07-28 14:37:04 +000017#if defined(INCLUDE_SQLITE_TCL_H)
18# include "sqlite_tcl.h"
19#else
20# include "tcl.h"
21#endif
drh2f999a62007-08-15 19:16:43 +000022#include <stdlib.h>
23#include <string.h>
24#include <assert.h>
25
danielk1977ef05f2d2008-06-20 11:05:37 +000026/*
27** This structure is used to encapsulate the global state variables used
28** by malloc() fault simulation.
29*/
30static struct MemFault {
31 int iCountdown; /* Number of pending successes before a failure */
32 int nRepeat; /* Number of times to repeat the failure */
33 int nBenign; /* Number of benign failures seen since last config */
34 int nFail; /* Number of failures seen since last config */
drhb9cd2c42018-05-24 17:38:00 +000035 int nOkBefore; /* Successful allocations prior to the first fault */
36 int nOkAfter; /* Successful allocations after a fault */
danielk1977ef05f2d2008-06-20 11:05:37 +000037 u8 enable; /* True if enabled */
38 int isInstalled; /* True if the fault simulation layer is installed */
danielk19772d1d86f2008-06-20 14:59:51 +000039 int isBenignMode; /* True if malloc failures are considered benign */
danielk1977ef05f2d2008-06-20 11:05:37 +000040 sqlite3_mem_methods m; /* 'Real' malloc implementation */
41} memfault;
42
43/*
44** This routine exists as a place to set a breakpoint that will
45** fire on any simulated malloc() failure.
46*/
47static void sqlite3Fault(void){
48 static int cnt = 0;
49 cnt++;
50}
51
52/*
drhb9cd2c42018-05-24 17:38:00 +000053** This routine exists as a place to set a breakpoint that will
54** fire the first time any malloc() fails on a single test case.
55** The sqlite3Fault() routine above runs on every malloc() failure.
56** This routine only runs on the first such failure.
57*/
58static void sqlite3FirstFault(void){
59 static int cnt2 = 0;
60 cnt2++;
61}
62
63/*
danielk1977ef05f2d2008-06-20 11:05:37 +000064** Check to see if a fault should be simulated. Return true to simulate
65** the fault. Return false if the fault should not be simulated.
66*/
danielk197764aca192009-04-07 11:21:28 +000067static int faultsimStep(void){
danielk1977ef05f2d2008-06-20 11:05:37 +000068 if( likely(!memfault.enable) ){
drhb9cd2c42018-05-24 17:38:00 +000069 memfault.nOkAfter++;
danielk1977ef05f2d2008-06-20 11:05:37 +000070 return 0;
71 }
72 if( memfault.iCountdown>0 ){
73 memfault.iCountdown--;
drhb9cd2c42018-05-24 17:38:00 +000074 memfault.nOkBefore++;
danielk1977ef05f2d2008-06-20 11:05:37 +000075 return 0;
76 }
drhb9cd2c42018-05-24 17:38:00 +000077 if( memfault.nFail==0 ) sqlite3FirstFault();
danielk1977ef05f2d2008-06-20 11:05:37 +000078 sqlite3Fault();
79 memfault.nFail++;
danielk19772d1d86f2008-06-20 14:59:51 +000080 if( memfault.isBenignMode>0 ){
danielk1977ef05f2d2008-06-20 11:05:37 +000081 memfault.nBenign++;
82 }
83 memfault.nRepeat--;
84 if( memfault.nRepeat<=0 ){
85 memfault.enable = 0;
86 }
87 return 1;
88}
89
90/*
91** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation
92** logic.
93*/
94static void *faultsimMalloc(int n){
95 void *p = 0;
96 if( !faultsimStep() ){
97 p = memfault.m.xMalloc(n);
98 }
99 return p;
100}
101
102
103/*
104** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation
105** logic.
106*/
107static void *faultsimRealloc(void *pOld, int n){
108 void *p = 0;
109 if( !faultsimStep() ){
110 p = memfault.m.xRealloc(pOld, n);
111 }
112 return p;
113}
114
115/*
116** The following method calls are passed directly through to the underlying
117** malloc system:
118**
119** xFree
120** xSize
121** xRoundup
122** xInit
123** xShutdown
124*/
125static void faultsimFree(void *p){
126 memfault.m.xFree(p);
127}
128static int faultsimSize(void *p){
129 return memfault.m.xSize(p);
130}
131static int faultsimRoundup(int n){
132 return memfault.m.xRoundup(n);
133}
134static int faultsimInit(void *p){
135 return memfault.m.xInit(memfault.m.pAppData);
136}
137static void faultsimShutdown(void *p){
138 memfault.m.xShutdown(memfault.m.pAppData);
139}
140
141/*
142** This routine configures the malloc failure simulation. After
143** calling this routine, the next nDelay mallocs will succeed, followed
144** by a block of nRepeat failures, after which malloc() calls will begin
145** to succeed again.
146*/
147static void faultsimConfig(int nDelay, int nRepeat){
148 memfault.iCountdown = nDelay;
149 memfault.nRepeat = nRepeat;
150 memfault.nBenign = 0;
151 memfault.nFail = 0;
drhb9cd2c42018-05-24 17:38:00 +0000152 memfault.nOkBefore = 0;
153 memfault.nOkAfter = 0;
danielk1977ef05f2d2008-06-20 11:05:37 +0000154 memfault.enable = nDelay>=0;
danielk1977b48c1f12009-02-04 15:27:40 +0000155
156 /* Sometimes, when running multi-threaded tests, the isBenignMode
157 ** variable is not properly incremented/decremented so that it is
158 ** 0 when not inside a benign malloc block. This doesn't affect
159 ** the multi-threaded tests, as they do not use this system. But
160 ** it does affect OOM tests run later in the same process. So
161 ** zero the variable here, just to be sure.
162 */
163 memfault.isBenignMode = 0;
danielk1977ef05f2d2008-06-20 11:05:37 +0000164}
165
166/*
167** Return the number of faults (both hard and benign faults) that have
168** occurred since the injector was last configured.
169*/
170static int faultsimFailures(void){
171 return memfault.nFail;
172}
173
174/*
175** Return the number of benign faults that have occurred since the
176** injector was last configured.
177*/
178static int faultsimBenignFailures(void){
179 return memfault.nBenign;
180}
181
182/*
183** Return the number of successes that will occur before the next failure.
184** If no failures are scheduled, return -1.
185*/
186static int faultsimPending(void){
187 if( memfault.enable ){
188 return memfault.iCountdown;
189 }else{
190 return -1;
191 }
192}
193
danielk19772d1d86f2008-06-20 14:59:51 +0000194
195static void faultsimBeginBenign(void){
196 memfault.isBenignMode++;
197}
198static void faultsimEndBenign(void){
199 memfault.isBenignMode--;
200}
201
danielk1977ef05f2d2008-06-20 11:05:37 +0000202/*
203** Add or remove the fault-simulation layer using sqlite3_config(). If
204** the argument is non-zero, the
205*/
206static int faultsimInstall(int install){
207 static struct sqlite3_mem_methods m = {
208 faultsimMalloc, /* xMalloc */
209 faultsimFree, /* xFree */
210 faultsimRealloc, /* xRealloc */
211 faultsimSize, /* xSize */
212 faultsimRoundup, /* xRoundup */
213 faultsimInit, /* xInit */
214 faultsimShutdown, /* xShutdown */
215 0 /* pAppData */
216 };
217 int rc;
218
219 install = (install ? 1 : 0);
220 assert(memfault.isInstalled==1 || memfault.isInstalled==0);
221
222 if( install==memfault.isInstalled ){
223 return SQLITE_ERROR;
224 }
225
danielk19772d1d86f2008-06-20 14:59:51 +0000226 if( install ){
227 rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
228 assert(memfault.m.xMalloc);
229 if( rc==SQLITE_OK ){
230 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
231 }
232 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
233 faultsimBeginBenign, faultsimEndBenign
234 );
235 }else{
mistachkin8e189222015-04-19 21:43:16 +0000236 sqlite3_mem_methods m2;
danielk19772d1d86f2008-06-20 14:59:51 +0000237 assert(memfault.m.xMalloc);
drh1b67f3c2008-10-10 17:41:28 +0000238
239 /* One should be able to reset the default memory allocator by storing
240 ** a zeroed allocator then calling GETMALLOC. */
mistachkin8e189222015-04-19 21:43:16 +0000241 memset(&m2, 0, sizeof(m2));
242 sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
243 sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
244 assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
drh1b67f3c2008-10-10 17:41:28 +0000245
danielk19772d1d86f2008-06-20 14:59:51 +0000246 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
drhd797a9b2015-12-07 16:43:44 +0000247 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
248 (void*)0, (void*)0);
danielk1977ef05f2d2008-06-20 11:05:37 +0000249 }
250
251 if( rc==SQLITE_OK ){
252 memfault.isInstalled = 1;
253 }
254 return rc;
255}
256
257#ifdef SQLITE_TEST
258
259/*
mistachkine84d8d32013-04-29 03:09:10 +0000260** This function is implemented in main.c. Returns a pointer to a static
danielk1977ef05f2d2008-06-20 11:05:37 +0000261** buffer containing the symbolic SQLite error code that corresponds to
262** the least-significant 8-bits of the integer passed as an argument.
263** For example:
264**
mistachkine84d8d32013-04-29 03:09:10 +0000265** sqlite3ErrName(1) -> "SQLITE_ERROR"
danielk1977ef05f2d2008-06-20 11:05:37 +0000266*/
mistachkine84d8d32013-04-29 03:09:10 +0000267extern const char *sqlite3ErrName(int);
danielk1977d09414c2008-06-19 18:17:49 +0000268
drh2f999a62007-08-15 19:16:43 +0000269/*
270** Transform pointers to text and back again
271*/
272static void pointerToText(void *p, char *z){
273 static const char zHex[] = "0123456789abcdef";
274 int i, k;
drh4a50aac2007-08-23 02:47:53 +0000275 unsigned int u;
276 sqlite3_uint64 n;
drh8a42cbd2008-07-10 18:13:42 +0000277 if( p==0 ){
278 strcpy(z, "0");
279 return;
280 }
drh4a50aac2007-08-23 02:47:53 +0000281 if( sizeof(n)==sizeof(p) ){
282 memcpy(&n, &p, sizeof(p));
283 }else if( sizeof(u)==sizeof(p) ){
284 memcpy(&u, &p, sizeof(u));
285 n = u;
286 }else{
287 assert( 0 );
288 }
drh2f999a62007-08-15 19:16:43 +0000289 for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){
290 z[k] = zHex[n&0xf];
291 n >>= 4;
292 }
293 z[sizeof(p)*2] = 0;
294}
295static int hexToInt(int h){
296 if( h>='0' && h<='9' ){
297 return h - '0';
298 }else if( h>='a' && h<='f' ){
299 return h - 'a' + 10;
300 }else{
301 return -1;
302 }
303}
304static int textToPointer(const char *z, void **pp){
305 sqlite3_uint64 n = 0;
306 int i;
drh4a50aac2007-08-23 02:47:53 +0000307 unsigned int u;
drh2f999a62007-08-15 19:16:43 +0000308 for(i=0; i<sizeof(void*)*2 && z[0]; i++){
309 int v;
310 v = hexToInt(*z++);
311 if( v<0 ) return TCL_ERROR;
312 n = n*16 + v;
313 }
314 if( *z!=0 ) return TCL_ERROR;
drh4a50aac2007-08-23 02:47:53 +0000315 if( sizeof(n)==sizeof(*pp) ){
316 memcpy(pp, &n, sizeof(n));
317 }else if( sizeof(u)==sizeof(*pp) ){
318 u = (unsigned int)n;
319 memcpy(pp, &u, sizeof(u));
320 }else{
321 assert( 0 );
322 }
drh2f999a62007-08-15 19:16:43 +0000323 return TCL_OK;
324}
325
326/*
327** Usage: sqlite3_malloc NBYTES
328**
329** Raw test interface for sqlite3_malloc().
330*/
mistachkin7617e4a2016-07-28 17:11:20 +0000331static int SQLITE_TCLAPI test_malloc(
drh2f999a62007-08-15 19:16:43 +0000332 void * clientData,
333 Tcl_Interp *interp,
334 int objc,
335 Tcl_Obj *CONST objv[]
336){
337 int nByte;
338 void *p;
339 char zOut[100];
340 if( objc!=2 ){
341 Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");
342 return TCL_ERROR;
343 }
344 if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR;
345 p = sqlite3_malloc((unsigned)nByte);
346 pointerToText(p, zOut);
347 Tcl_AppendResult(interp, zOut, NULL);
348 return TCL_OK;
349}
350
351/*
352** Usage: sqlite3_realloc PRIOR NBYTES
353**
354** Raw test interface for sqlite3_realloc().
355*/
mistachkin7617e4a2016-07-28 17:11:20 +0000356static int SQLITE_TCLAPI test_realloc(
drh2f999a62007-08-15 19:16:43 +0000357 void * clientData,
358 Tcl_Interp *interp,
359 int objc,
360 Tcl_Obj *CONST objv[]
361){
362 int nByte;
363 void *pPrior, *p;
364 char zOut[100];
365 if( objc!=3 ){
366 Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");
367 return TCL_ERROR;
368 }
369 if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR;
370 if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
371 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
372 return TCL_ERROR;
373 }
374 p = sqlite3_realloc(pPrior, (unsigned)nByte);
375 pointerToText(p, zOut);
376 Tcl_AppendResult(interp, zOut, NULL);
377 return TCL_OK;
378}
379
drh2f999a62007-08-15 19:16:43 +0000380/*
381** Usage: sqlite3_free PRIOR
382**
383** Raw test interface for sqlite3_free().
384*/
mistachkin7617e4a2016-07-28 17:11:20 +0000385static int SQLITE_TCLAPI test_free(
drh2f999a62007-08-15 19:16:43 +0000386 void * clientData,
387 Tcl_Interp *interp,
388 int objc,
389 Tcl_Obj *CONST objv[]
390){
391 void *pPrior;
392 if( objc!=2 ){
393 Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");
394 return TCL_ERROR;
395 }
396 if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
397 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
398 return TCL_ERROR;
399 }
400 sqlite3_free(pPrior);
401 return TCL_OK;
402}
403
404/*
drh9c7a60d2007-10-19 17:47:24 +0000405** These routines are in test_hexio.c
406*/
407int sqlite3TestHexToBin(const char *, int, char *);
408int sqlite3TestBinToHex(char*,int);
409
410/*
411** Usage: memset ADDRESS SIZE HEX
412**
413** Set a chunk of memory (obtained from malloc, probably) to a
414** specified hex pattern.
415*/
mistachkin7617e4a2016-07-28 17:11:20 +0000416static int SQLITE_TCLAPI test_memset(
drh9c7a60d2007-10-19 17:47:24 +0000417 void * clientData,
418 Tcl_Interp *interp,
419 int objc,
420 Tcl_Obj *CONST objv[]
421){
422 void *p;
423 int size, n, i;
424 char *zHex;
425 char *zOut;
426 char zBin[100];
427
428 if( objc!=4 ){
429 Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");
430 return TCL_ERROR;
431 }
432 if( textToPointer(Tcl_GetString(objv[1]), &p) ){
433 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
434 return TCL_ERROR;
435 }
436 if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
437 return TCL_ERROR;
438 }
439 if( size<=0 ){
440 Tcl_AppendResult(interp, "size must be positive", (char*)0);
441 return TCL_ERROR;
442 }
443 zHex = Tcl_GetStringFromObj(objv[3], &n);
444 if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
445 n = sqlite3TestHexToBin(zHex, n, zBin);
446 if( n==0 ){
447 Tcl_AppendResult(interp, "no data", (char*)0);
448 return TCL_ERROR;
449 }
450 zOut = p;
451 for(i=0; i<size; i++){
452 zOut[i] = zBin[i%n];
453 }
454 return TCL_OK;
455}
456
457/*
458** Usage: memget ADDRESS SIZE
459**
460** Return memory as hexadecimal text.
461*/
mistachkin7617e4a2016-07-28 17:11:20 +0000462static int SQLITE_TCLAPI test_memget(
drh9c7a60d2007-10-19 17:47:24 +0000463 void * clientData,
464 Tcl_Interp *interp,
465 int objc,
466 Tcl_Obj *CONST objv[]
467){
468 void *p;
469 int size, n;
470 char *zBin;
471 char zHex[100];
472
473 if( objc!=3 ){
474 Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");
475 return TCL_ERROR;
476 }
477 if( textToPointer(Tcl_GetString(objv[1]), &p) ){
478 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
479 return TCL_ERROR;
480 }
481 if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
482 return TCL_ERROR;
483 }
484 if( size<=0 ){
485 Tcl_AppendResult(interp, "size must be positive", (char*)0);
486 return TCL_ERROR;
487 }
488 zBin = p;
489 while( size>0 ){
490 if( size>(sizeof(zHex)-1)/2 ){
491 n = (sizeof(zHex)-1)/2;
492 }else{
493 n = size;
494 }
495 memcpy(zHex, zBin, n);
496 zBin += n;
497 size -= n;
498 sqlite3TestBinToHex(zHex, n);
499 Tcl_AppendResult(interp, zHex, (char*)0);
500 }
501 return TCL_OK;
502}
503
504/*
drh2f999a62007-08-15 19:16:43 +0000505** Usage: sqlite3_memory_used
506**
507** Raw test interface for sqlite3_memory_used().
508*/
mistachkin7617e4a2016-07-28 17:11:20 +0000509static int SQLITE_TCLAPI test_memory_used(
drh2f999a62007-08-15 19:16:43 +0000510 void * clientData,
511 Tcl_Interp *interp,
512 int objc,
513 Tcl_Obj *CONST objv[]
514){
515 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used()));
516 return TCL_OK;
517}
518
519/*
520** Usage: sqlite3_memory_highwater ?RESETFLAG?
521**
522** Raw test interface for sqlite3_memory_highwater().
523*/
mistachkin7617e4a2016-07-28 17:11:20 +0000524static int SQLITE_TCLAPI test_memory_highwater(
drh2f999a62007-08-15 19:16:43 +0000525 void * clientData,
526 Tcl_Interp *interp,
527 int objc,
528 Tcl_Obj *CONST objv[]
529){
530 int resetFlag = 0;
531 if( objc!=1 && objc!=2 ){
532 Tcl_WrongNumArgs(interp, 1, objv, "?RESET?");
533 return TCL_ERROR;
534 }
535 if( objc==2 ){
536 if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR;
537 }
538 Tcl_SetObjResult(interp,
539 Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag)));
540 return TCL_OK;
541}
542
543/*
544** Usage: sqlite3_memdebug_backtrace DEPTH
545**
546** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined
547** then this routine is a no-op.
548*/
mistachkin7617e4a2016-07-28 17:11:20 +0000549static int SQLITE_TCLAPI test_memdebug_backtrace(
drh2f999a62007-08-15 19:16:43 +0000550 void * clientData,
551 Tcl_Interp *interp,
552 int objc,
553 Tcl_Obj *CONST objv[]
554){
555 int depth;
556 if( objc!=2 ){
557 Tcl_WrongNumArgs(interp, 1, objv, "DEPT");
558 return TCL_ERROR;
559 }
560 if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;
561#ifdef SQLITE_MEMDEBUG
562 {
drh49e4fd72008-02-19 15:15:15 +0000563 extern void sqlite3MemdebugBacktrace(int);
564 sqlite3MemdebugBacktrace(depth);
drh2f999a62007-08-15 19:16:43 +0000565 }
566#endif
567 return TCL_OK;
568}
569
570/*
571** Usage: sqlite3_memdebug_dump FILENAME
572**
573** Write a summary of unfreed memory to FILENAME.
574*/
mistachkin7617e4a2016-07-28 17:11:20 +0000575static int SQLITE_TCLAPI test_memdebug_dump(
drh2f999a62007-08-15 19:16:43 +0000576 void * clientData,
577 Tcl_Interp *interp,
578 int objc,
579 Tcl_Obj *CONST objv[]
580){
581 if( objc!=2 ){
582 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
583 return TCL_ERROR;
584 }
drh2d7636e2008-02-16 16:21:45 +0000585#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \
586 || defined(SQLITE_POW2_MEMORY_SIZE)
drh2f999a62007-08-15 19:16:43 +0000587 {
drh49e4fd72008-02-19 15:15:15 +0000588 extern void sqlite3MemdebugDump(const char*);
589 sqlite3MemdebugDump(Tcl_GetString(objv[1]));
drh2f999a62007-08-15 19:16:43 +0000590 }
591#endif
592 return TCL_OK;
593}
594
danielk1977a7a8e142008-02-13 18:25:27 +0000595/*
596** Usage: sqlite3_memdebug_malloc_count
597**
598** Return the total number of times malloc() has been called.
599*/
mistachkin7617e4a2016-07-28 17:11:20 +0000600static int SQLITE_TCLAPI test_memdebug_malloc_count(
danielk1977a7a8e142008-02-13 18:25:27 +0000601 void * clientData,
602 Tcl_Interp *interp,
603 int objc,
604 Tcl_Obj *CONST objv[]
605){
606 int nMalloc = -1;
607 if( objc!=1 ){
608 Tcl_WrongNumArgs(interp, 1, objv, "");
609 return TCL_ERROR;
610 }
611#if defined(SQLITE_MEMDEBUG)
612 {
drh49e4fd72008-02-19 15:15:15 +0000613 extern int sqlite3MemdebugMallocCount();
614 nMalloc = sqlite3MemdebugMallocCount();
danielk1977a7a8e142008-02-13 18:25:27 +0000615 }
616#endif
617 Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc));
618 return TCL_OK;
619}
620
drh2f999a62007-08-15 19:16:43 +0000621
622/*
danielk1977a1644fd2007-08-29 12:31:25 +0000623** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?
624**
625** where options are:
626**
drh643167f2008-01-22 21:30:53 +0000627** -repeat <count>
danielk1977a1644fd2007-08-29 12:31:25 +0000628** -benigncnt <varname>
drh0e6f1542007-08-15 20:41:28 +0000629**
630** Arrange for a simulated malloc() failure after COUNTER successes.
drh643167f2008-01-22 21:30:53 +0000631** If a repeat count is specified, the fault is repeated that many
632** times.
drh0e6f1542007-08-15 20:41:28 +0000633**
634** Each call to this routine overrides the prior counter value.
635** This routine returns the number of simulated failures that have
636** happened since the previous call to this routine.
637**
638** To disable simulated failures, use a COUNTER of -1.
639*/
mistachkin7617e4a2016-07-28 17:11:20 +0000640static int SQLITE_TCLAPI test_memdebug_fail(
drh0e6f1542007-08-15 20:41:28 +0000641 void * clientData,
642 Tcl_Interp *interp,
643 int objc,
644 Tcl_Obj *CONST objv[]
645){
danielk1977a1644fd2007-08-29 12:31:25 +0000646 int ii;
drh0e6f1542007-08-15 20:41:28 +0000647 int iFail;
drh643167f2008-01-22 21:30:53 +0000648 int nRepeat = 1;
danielk1977a1644fd2007-08-29 12:31:25 +0000649 Tcl_Obj *pBenignCnt = 0;
drh643167f2008-01-22 21:30:53 +0000650 int nBenign;
drh0e6f1542007-08-15 20:41:28 +0000651 int nFail = 0;
danielk1977a1644fd2007-08-29 12:31:25 +0000652
653 if( objc<2 ){
654 Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?");
drh0e6f1542007-08-15 20:41:28 +0000655 return TCL_ERROR;
656 }
657 if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;
danielk1977a1644fd2007-08-29 12:31:25 +0000658
659 for(ii=2; ii<objc; ii+=2){
660 int nOption;
661 char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);
662 char *zErr = 0;
663
664 if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){
665 if( ii==(objc-1) ){
666 zErr = "option requires an argument: ";
667 }else{
drh643167f2008-01-22 21:30:53 +0000668 if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){
danielk1977a1644fd2007-08-29 12:31:25 +0000669 return TCL_ERROR;
670 }
671 }
672 }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){
673 if( ii==(objc-1) ){
674 zErr = "option requires an argument: ";
675 }else{
676 pBenignCnt = objv[ii+1];
677 }
678 }else{
679 zErr = "unknown option: ";
680 }
681
682 if( zErr ){
683 Tcl_AppendResult(interp, zErr, zOption, 0);
684 return TCL_ERROR;
685 }
drhed138fb2007-08-22 22:04:37 +0000686 }
danielk1977a1644fd2007-08-29 12:31:25 +0000687
danielk1977ef05f2d2008-06-20 11:05:37 +0000688 nBenign = faultsimBenignFailures();
689 nFail = faultsimFailures();
690 faultsimConfig(iFail, nRepeat);
691
drh643167f2008-01-22 21:30:53 +0000692 if( pBenignCnt ){
693 Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
drh0e6f1542007-08-15 20:41:28 +0000694 }
drh0e6f1542007-08-15 20:41:28 +0000695 Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
696 return TCL_OK;
697}
698
danielk1977cd037242007-08-30 15:46:06 +0000699/*
700** Usage: sqlite3_memdebug_pending
701**
702** Return the number of malloc() calls that will succeed before a
703** simulated failure occurs. A negative return value indicates that
704** no malloc() failure is scheduled.
705*/
mistachkin7617e4a2016-07-28 17:11:20 +0000706static int SQLITE_TCLAPI test_memdebug_pending(
danielk1977cd037242007-08-30 15:46:06 +0000707 void * clientData,
708 Tcl_Interp *interp,
709 int objc,
710 Tcl_Obj *CONST objv[]
711){
drh5efaf072008-03-18 00:07:10 +0000712 int nPending;
danielk1977cd037242007-08-30 15:46:06 +0000713 if( objc!=1 ){
714 Tcl_WrongNumArgs(interp, 1, objv, "");
715 return TCL_ERROR;
716 }
danielk1977ef05f2d2008-06-20 11:05:37 +0000717 nPending = faultsimPending();
drh5efaf072008-03-18 00:07:10 +0000718 Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
danielk1977cd037242007-08-30 15:46:06 +0000719 return TCL_OK;
720}
721
drh44ee1dc2014-09-06 03:16:28 +0000722/*
723** The following global variable keeps track of the number of tests
724** that have run. This variable is only useful when running in the
725** debugger.
726*/
727static int sqlite3_memdebug_title_count = 0;
drh0e6f1542007-08-15 20:41:28 +0000728
729/*
drh4a50aac2007-08-23 02:47:53 +0000730** Usage: sqlite3_memdebug_settitle TITLE
731**
732** Set a title string stored with each allocation. The TITLE is
733** typically the name of the test that was running when the
734** allocation occurred. The TITLE is stored with the allocation
735** and can be used to figure out which tests are leaking memory.
736**
737** Each title overwrite the previous.
738*/
mistachkin7617e4a2016-07-28 17:11:20 +0000739static int SQLITE_TCLAPI test_memdebug_settitle(
drh4a50aac2007-08-23 02:47:53 +0000740 void * clientData,
741 Tcl_Interp *interp,
742 int objc,
743 Tcl_Obj *CONST objv[]
744){
drh44ee1dc2014-09-06 03:16:28 +0000745 sqlite3_memdebug_title_count++;
drh4a50aac2007-08-23 02:47:53 +0000746 if( objc!=2 ){
747 Tcl_WrongNumArgs(interp, 1, objv, "TITLE");
748 return TCL_ERROR;
749 }
drh4a50aac2007-08-23 02:47:53 +0000750#ifdef SQLITE_MEMDEBUG
751 {
drhcaffb1a2012-01-30 18:00:31 +0000752 const char *zTitle;
drh49e4fd72008-02-19 15:15:15 +0000753 extern int sqlite3MemdebugSettitle(const char*);
mistachkina359b5e2012-12-04 00:37:58 +0000754 zTitle = Tcl_GetString(objv[1]);
drh49e4fd72008-02-19 15:15:15 +0000755 sqlite3MemdebugSettitle(zTitle);
drh4a50aac2007-08-23 02:47:53 +0000756 }
757#endif
758 return TCL_OK;
759}
760
danec561a32010-08-09 14:47:50 +0000761#define MALLOC_LOG_FRAMES 10
762#define MALLOC_LOG_KEYINTS ( \
763 10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \
764)
danielk19776f332c12008-03-21 14:22:44 +0000765static Tcl_HashTable aMallocLog;
766static int mallocLogEnabled = 0;
767
768typedef struct MallocLog MallocLog;
769struct MallocLog {
770 int nCall;
771 int nByte;
772};
773
shaneafdd23a2008-05-29 02:57:47 +0000774#ifdef SQLITE_MEMDEBUG
danielk19776f332c12008-03-21 14:22:44 +0000775static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){
776 if( mallocLogEnabled ){
777 MallocLog *pLog;
778 Tcl_HashEntry *pEntry;
779 int isNew;
780
danec561a32010-08-09 14:47:50 +0000781 int aKey[MALLOC_LOG_KEYINTS];
mistachkinf6418892013-08-28 01:54:12 +0000782 unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS;
danielk19776f332c12008-03-21 14:22:44 +0000783
784 memset(aKey, 0, nKey);
785 if( (sizeof(void*)*nFrame)<nKey ){
786 nKey = nFrame*sizeof(void*);
787 }
788 memcpy(aKey, aFrame, nKey);
789
790 pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew);
791 if( isNew ){
792 pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog));
793 memset(pLog, 0, sizeof(MallocLog));
794 Tcl_SetHashValue(pEntry, (ClientData)pLog);
795 }else{
796 pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
797 }
798
799 pLog->nCall++;
800 pLog->nByte += nByte;
801 }
802}
shaneafdd23a2008-05-29 02:57:47 +0000803#endif /* SQLITE_MEMDEBUG */
danielk19776f332c12008-03-21 14:22:44 +0000804
danielk197764aca192009-04-07 11:21:28 +0000805static void test_memdebug_log_clear(void){
danielk1977dbdc4d42008-03-28 07:42:53 +0000806 Tcl_HashSearch search;
807 Tcl_HashEntry *pEntry;
808 for(
809 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
810 pEntry;
811 pEntry=Tcl_NextHashEntry(&search)
812 ){
813 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
814 Tcl_Free((char *)pLog);
815 }
816 Tcl_DeleteHashTable(&aMallocLog);
danec561a32010-08-09 14:47:50 +0000817 Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
danielk1977dbdc4d42008-03-28 07:42:53 +0000818}
819
mistachkin7617e4a2016-07-28 17:11:20 +0000820static int SQLITE_TCLAPI test_memdebug_log(
danielk19776f332c12008-03-21 14:22:44 +0000821 void * clientData,
822 Tcl_Interp *interp,
823 int objc,
824 Tcl_Obj *CONST objv[]
825){
826 static int isInit = 0;
827 int iSub;
828
danielk1977dbdc4d42008-03-28 07:42:53 +0000829 static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" };
830 enum MB_enum {
831 MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC
832 };
danielk19776f332c12008-03-21 14:22:44 +0000833
834 if( !isInit ){
835#ifdef SQLITE_MEMDEBUG
836 extern void sqlite3MemdebugBacktraceCallback(
837 void (*xBacktrace)(int, int, void **));
838 sqlite3MemdebugBacktraceCallback(test_memdebug_callback);
839#endif
danec561a32010-08-09 14:47:50 +0000840 Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
danielk19776f332c12008-03-21 14:22:44 +0000841 isInit = 1;
842 }
843
844 if( objc<2 ){
845 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
846 }
847 if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){
848 return TCL_ERROR;
849 }
850
851 switch( (enum MB_enum)iSub ){
852 case MB_LOG_START:
853 mallocLogEnabled = 1;
854 break;
855 case MB_LOG_STOP:
856 mallocLogEnabled = 0;
857 break;
858 case MB_LOG_DUMP: {
859 Tcl_HashSearch search;
860 Tcl_HashEntry *pEntry;
861 Tcl_Obj *pRet = Tcl_NewObj();
862
danec561a32010-08-09 14:47:50 +0000863 assert(sizeof(Tcl_WideInt)>=sizeof(void*));
danielk19776f332c12008-03-21 14:22:44 +0000864
865 for(
866 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
867 pEntry;
868 pEntry=Tcl_NextHashEntry(&search)
869 ){
870 Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];
871 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
danec561a32010-08-09 14:47:50 +0000872 Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry);
danielk19776f332c12008-03-21 14:22:44 +0000873 int ii;
874
875 apElem[0] = Tcl_NewIntObj(pLog->nCall);
876 apElem[1] = Tcl_NewIntObj(pLog->nByte);
877 for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){
danec561a32010-08-09 14:47:50 +0000878 apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]);
danielk19776f332c12008-03-21 14:22:44 +0000879 }
880
881 Tcl_ListObjAppendElement(interp, pRet,
882 Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem)
883 );
884 }
885
886 Tcl_SetObjResult(interp, pRet);
887 break;
888 }
889 case MB_LOG_CLEAR: {
danielk1977dbdc4d42008-03-28 07:42:53 +0000890 test_memdebug_log_clear();
891 break;
892 }
893
894 case MB_LOG_SYNC: {
drhb9404922008-03-28 12:53:38 +0000895#ifdef SQLITE_MEMDEBUG
danielk1977dbdc4d42008-03-28 07:42:53 +0000896 extern void sqlite3MemdebugSync();
897 test_memdebug_log_clear();
898 mallocLogEnabled = 1;
899 sqlite3MemdebugSync();
drhb9404922008-03-28 12:53:38 +0000900#endif
danielk1977dbdc4d42008-03-28 07:42:53 +0000901 break;
danielk19776f332c12008-03-21 14:22:44 +0000902 }
903 }
904
905 return TCL_OK;
906}
drh4a50aac2007-08-23 02:47:53 +0000907
908/*
drh9ac3fe92008-06-18 18:12:04 +0000909** Usage: sqlite3_config_pagecache SIZE N
910**
911** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
912** The buffer is static and is of limited size. N might be
peter.d.reid60ec9142014-09-06 16:39:46 +0000913** adjusted downward as needed to accommodate the requested size.
drh9ac3fe92008-06-18 18:12:04 +0000914** The revised value of N is returned.
915**
916** A negative SIZE causes the buffer pointer to be NULL.
917*/
mistachkin7617e4a2016-07-28 17:11:20 +0000918static int SQLITE_TCLAPI test_config_pagecache(
drh9ac3fe92008-06-18 18:12:04 +0000919 void * clientData,
920 Tcl_Interp *interp,
921 int objc,
922 Tcl_Obj *CONST objv[]
923){
drh6bacdc22015-07-24 17:14:03 +0000924 int sz, N;
dan03bc5252015-07-24 14:17:17 +0000925 Tcl_Obj *pRes;
drh5f4bcf12008-07-29 14:29:06 +0000926 static char *buf = 0;
drh9ac3fe92008-06-18 18:12:04 +0000927 if( objc!=3 ){
928 Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
929 return TCL_ERROR;
930 }
drhf7141992008-06-19 00:16:08 +0000931 if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
932 if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
drh5f4bcf12008-07-29 14:29:06 +0000933 free(buf);
dan03bc5252015-07-24 14:17:17 +0000934 buf = 0;
935
936 /* Set the return value */
937 pRes = Tcl_NewObj();
938 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.szPage));
939 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.nPage));
940 Tcl_SetObjResult(interp, pRes);
941
drh9ac3fe92008-06-18 18:12:04 +0000942 if( sz<0 ){
drha6082f62015-11-26 22:12:41 +0000943 sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, 0);
drhf7141992008-06-19 00:16:08 +0000944 }else{
drh0a60a382008-07-31 17:16:05 +0000945 buf = malloc( sz*N );
drh6bacdc22015-07-24 17:14:03 +0000946 sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
drh9ac3fe92008-06-18 18:12:04 +0000947 }
drh9ac3fe92008-06-18 18:12:04 +0000948 return TCL_OK;
949}
950
drhf7141992008-06-19 00:16:08 +0000951/*
drhb232c232008-11-19 01:20:26 +0000952** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED
953**
954** Set up the alternative test page cache. Install if INSTALL_FLAG is
955** true and uninstall (reverting to the default page cache) if INSTALL_FLAG
956** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive
957** which determines the chance of discarding a page when unpinned. 100
958** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator
959** seed.
960*/
mistachkin7617e4a2016-07-28 17:11:20 +0000961static int SQLITE_TCLAPI test_alt_pcache(
drhb232c232008-11-19 01:20:26 +0000962 void * clientData,
963 Tcl_Interp *interp,
964 int objc,
965 Tcl_Obj *CONST objv[]
966){
967 int installFlag;
drhf2a84e32009-01-07 03:59:47 +0000968 int discardChance = 0;
969 int prngSeed = 0;
970 int highStress = 0;
971 extern void installTestPCache(int,unsigned,unsigned,unsigned);
972 if( objc<2 || objc>5 ){
973 Tcl_WrongNumArgs(interp, 1, objv,
974 "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS");
drhb232c232008-11-19 01:20:26 +0000975 return TCL_ERROR;
976 }
977 if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR;
drhf2a84e32009-01-07 03:59:47 +0000978 if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){
979 return TCL_ERROR;
980 }
981 if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){
982 return TCL_ERROR;
983 }
984 if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){
985 return TCL_ERROR;
986 }
drhb232c232008-11-19 01:20:26 +0000987 if( discardChance<0 || discardChance>100 ){
988 Tcl_AppendResult(interp, "discard-chance should be between 0 and 100",
989 (char*)0);
990 return TCL_ERROR;
991 }
drhf2a84e32009-01-07 03:59:47 +0000992 installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed,
993 (unsigned)highStress);
drhb232c232008-11-19 01:20:26 +0000994 return TCL_OK;
995}
996
997/*
drh8a42cbd2008-07-10 18:13:42 +0000998** Usage: sqlite3_config_memstatus BOOLEAN
999**
1000** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS.
1001*/
mistachkin7617e4a2016-07-28 17:11:20 +00001002static int SQLITE_TCLAPI test_config_memstatus(
drh8a42cbd2008-07-10 18:13:42 +00001003 void * clientData,
1004 Tcl_Interp *interp,
1005 int objc,
1006 Tcl_Obj *CONST objv[]
1007){
1008 int enable, rc;
1009 if( objc!=2 ){
1010 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1011 return TCL_ERROR;
1012 }
1013 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;
1014 rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);
1015 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
1016 return TCL_OK;
1017}
1018
1019/*
drh633e6d52008-07-28 19:34:53 +00001020** Usage: sqlite3_config_lookaside SIZE COUNT
1021**
1022*/
mistachkin7617e4a2016-07-28 17:11:20 +00001023static int SQLITE_TCLAPI test_config_lookaside(
drh633e6d52008-07-28 19:34:53 +00001024 void * clientData,
1025 Tcl_Interp *interp,
1026 int objc,
1027 Tcl_Obj *CONST objv[]
1028){
drh633e6d52008-07-28 19:34:53 +00001029 int sz, cnt;
danielk1977ab7bee82008-10-15 11:43:55 +00001030 Tcl_Obj *pRet;
drh633e6d52008-07-28 19:34:53 +00001031 if( objc!=3 ){
1032 Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");
1033 return TCL_ERROR;
1034 }
1035 if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
1036 if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR;
danielk1977ab7bee82008-10-15 11:43:55 +00001037 pRet = Tcl_NewObj();
1038 Tcl_ListObjAppendElement(
1039 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside)
1040 );
1041 Tcl_ListObjAppendElement(
1042 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside)
1043 );
drhcaffb1a2012-01-30 18:00:31 +00001044 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);
danielk1977ab7bee82008-10-15 11:43:55 +00001045 Tcl_SetObjResult(interp, pRet);
drh633e6d52008-07-28 19:34:53 +00001046 return TCL_OK;
1047}
1048
1049
1050/*
drhe9d1c722008-08-04 20:13:26 +00001051** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT
drh633e6d52008-07-28 19:34:53 +00001052**
drhe9d1c722008-08-04 20:13:26 +00001053** There are two static buffers with BUFID 1 and 2. Each static buffer
1054** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL
1055** which will cause sqlite3_db_config() to allocate space on its own.
drh633e6d52008-07-28 19:34:53 +00001056*/
mistachkin7617e4a2016-07-28 17:11:20 +00001057static int SQLITE_TCLAPI test_db_config_lookaside(
drh633e6d52008-07-28 19:34:53 +00001058 void * clientData,
1059 Tcl_Interp *interp,
1060 int objc,
1061 Tcl_Obj *CONST objv[]
1062){
1063 int rc;
1064 int sz, cnt;
1065 sqlite3 *db;
drhe9d1c722008-08-04 20:13:26 +00001066 int bufid;
1067 static char azBuf[2][10000];
mistachkine84d8d32013-04-29 03:09:10 +00001068 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
drhe9d1c722008-08-04 20:13:26 +00001069 if( objc!=5 ){
1070 Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT");
drh633e6d52008-07-28 19:34:53 +00001071 return TCL_ERROR;
1072 }
1073 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhe9d1c722008-08-04 20:13:26 +00001074 if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR;
1075 if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR;
1076 if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR;
1077 if( bufid==0 ){
drhaed11f22016-04-05 14:02:16 +00001078 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt);
drhe9d1c722008-08-04 20:13:26 +00001079 }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){
1080 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt);
1081 }else{
1082 Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0);
1083 return TCL_ERROR;
1084 }
drh633e6d52008-07-28 19:34:53 +00001085 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
1086 return TCL_OK;
1087}
1088
1089/*
mistachkin8765b462012-09-10 08:48:05 +00001090** Usage: sqlite3_config_heap NBYTE NMINALLOC
danielk19775099be52008-06-27 13:27:03 +00001091*/
mistachkin7617e4a2016-07-28 17:11:20 +00001092static int SQLITE_TCLAPI test_config_heap(
danielk19775099be52008-06-27 13:27:03 +00001093 void * clientData,
1094 Tcl_Interp *interp,
1095 int objc,
1096 Tcl_Obj *CONST objv[]
1097){
drh7830cd42008-07-16 12:25:32 +00001098 static char *zBuf; /* Use this memory */
danielk19775099be52008-06-27 13:27:03 +00001099 int nByte; /* Size of buffer to pass to sqlite3_config() */
1100 int nMinAlloc; /* Size of minimum allocation */
1101 int rc; /* Return code of sqlite3_config() */
danielk19775099be52008-06-27 13:27:03 +00001102
1103 Tcl_Obj * CONST *aArg = &objv[1];
1104 int nArg = objc-1;
1105
danielk19775099be52008-06-27 13:27:03 +00001106 if( nArg!=2 ){
drh8a42cbd2008-07-10 18:13:42 +00001107 Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC");
danielk19775099be52008-06-27 13:27:03 +00001108 return TCL_ERROR;
1109 }
1110 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
1111 if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR;
1112
danielk19770d84e5b2008-06-27 14:05:24 +00001113 if( nByte==0 ){
drh7830cd42008-07-16 12:25:32 +00001114 free( zBuf );
1115 zBuf = 0;
drh8a42cbd2008-07-10 18:13:42 +00001116 rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0);
danielk19770d84e5b2008-06-27 14:05:24 +00001117 }else{
drh7830cd42008-07-16 12:25:32 +00001118 zBuf = realloc(zBuf, nByte);
danielk19770d84e5b2008-06-27 14:05:24 +00001119 rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc);
danielk19775099be52008-06-27 13:27:03 +00001120 }
danielk19775099be52008-06-27 13:27:03 +00001121
mistachkine84d8d32013-04-29 03:09:10 +00001122 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
danielk19775099be52008-06-27 13:27:03 +00001123 return TCL_OK;
1124}
1125
1126/*
mistachkinac1f1042013-11-23 00:27:29 +00001127** Usage: sqlite3_config_heap_size NBYTE
1128*/
mistachkin7617e4a2016-07-28 17:11:20 +00001129static int SQLITE_TCLAPI test_config_heap_size(
mistachkinac1f1042013-11-23 00:27:29 +00001130 void * clientData,
1131 Tcl_Interp *interp,
1132 int objc,
1133 Tcl_Obj *CONST objv[]
1134){
1135 int nByte; /* Size to pass to sqlite3_config() */
1136 int rc; /* Return code of sqlite3_config() */
1137
1138 Tcl_Obj * CONST *aArg = &objv[1];
1139 int nArg = objc-1;
1140
1141 if( nArg!=1 ){
1142 Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
1143 return TCL_ERROR;
1144 }
1145 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
1146
mistachkinaf8641b2013-11-25 21:49:04 +00001147 rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte);
mistachkinac1f1042013-11-23 00:27:29 +00001148
1149 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1150 return TCL_OK;
1151}
1152
1153/*
mistachkin8765b462012-09-10 08:48:05 +00001154** Usage: sqlite3_config_error [DB]
drh6480aad2008-08-01 16:31:14 +00001155**
1156** Invoke sqlite3_config() or sqlite3_db_config() with invalid
1157** opcodes and verify that they return errors.
1158*/
mistachkin7617e4a2016-07-28 17:11:20 +00001159static int SQLITE_TCLAPI test_config_error(
drh6480aad2008-08-01 16:31:14 +00001160 void * clientData,
1161 Tcl_Interp *interp,
1162 int objc,
1163 Tcl_Obj *CONST objv[]
1164){
1165 sqlite3 *db;
mistachkine84d8d32013-04-29 03:09:10 +00001166 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
drh6480aad2008-08-01 16:31:14 +00001167
1168 if( objc!=2 && objc!=1 ){
1169 Tcl_WrongNumArgs(interp, 1, objv, "[DB]");
1170 return TCL_ERROR;
1171 }
1172 if( objc==2 ){
1173 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1174 if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){
1175 Tcl_AppendResult(interp,
1176 "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR",
1177 (char*)0);
1178 return TCL_ERROR;
1179 }
1180 }else{
1181 if( sqlite3_config(99999)!=SQLITE_ERROR ){
1182 Tcl_AppendResult(interp,
1183 "sqlite3_config(99999) does not return SQLITE_ERROR",
1184 (char*)0);
1185 return TCL_ERROR;
1186 }
1187 }
1188 return TCL_OK;
1189}
1190
1191/*
mistachkin8765b462012-09-10 08:48:05 +00001192** Usage: sqlite3_config_uri BOOLEAN
dancd74b612011-04-22 19:37:32 +00001193**
mistachkin8765b462012-09-10 08:48:05 +00001194** Enables or disables interpretation of URI parameters by default using
1195** SQLITE_CONFIG_URI.
dancd74b612011-04-22 19:37:32 +00001196*/
mistachkin7617e4a2016-07-28 17:11:20 +00001197static int SQLITE_TCLAPI test_config_uri(
dancd74b612011-04-22 19:37:32 +00001198 void * clientData,
1199 Tcl_Interp *interp,
1200 int objc,
1201 Tcl_Obj *CONST objv[]
1202){
1203 int rc;
1204 int bOpenUri;
1205
1206 if( objc!=2 ){
1207 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1208 return TCL_ERROR;
1209 }
1210 if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
1211 return TCL_ERROR;
1212 }
1213
1214 rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
mistachkine84d8d32013-04-29 03:09:10 +00001215 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
dancd74b612011-04-22 19:37:32 +00001216
1217 return TCL_OK;
1218}
1219
1220/*
drhde9a7b82012-09-17 20:44:46 +00001221** Usage: sqlite3_config_cis BOOLEAN
1222**
1223** Enables or disables the use of the covering-index scan optimization.
1224** SQLITE_CONFIG_COVERING_INDEX_SCAN.
1225*/
mistachkin7617e4a2016-07-28 17:11:20 +00001226static int SQLITE_TCLAPI test_config_cis(
drhde9a7b82012-09-17 20:44:46 +00001227 void * clientData,
1228 Tcl_Interp *interp,
1229 int objc,
1230 Tcl_Obj *CONST objv[]
1231){
1232 int rc;
1233 int bUseCis;
1234
1235 if( objc!=2 ){
1236 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1237 return TCL_ERROR;
1238 }
1239 if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){
1240 return TCL_ERROR;
1241 }
1242
1243 rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
mistachkine84d8d32013-04-29 03:09:10 +00001244 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
drhde9a7b82012-09-17 20:44:46 +00001245
1246 return TCL_OK;
1247}
1248
drh3bd17912015-01-02 15:55:29 +00001249/*
1250** Usage: sqlite3_config_pmasz INTEGER
1251**
1252** Set the minimum PMA size.
1253*/
mistachkin7617e4a2016-07-28 17:11:20 +00001254static int SQLITE_TCLAPI test_config_pmasz(
drh3bd17912015-01-02 15:55:29 +00001255 void * clientData,
1256 Tcl_Interp *interp,
1257 int objc,
1258 Tcl_Obj *CONST objv[]
1259){
1260 int rc;
1261 int iPmaSz;
1262
1263 if( objc!=2 ){
1264 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1265 return TCL_ERROR;
1266 }
1267 if( Tcl_GetIntFromObj(interp, objv[1], &iPmaSz) ){
1268 return TCL_ERROR;
1269 }
1270
1271 rc = sqlite3_config(SQLITE_CONFIG_PMASZ, iPmaSz);
1272 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1273
1274 return TCL_OK;
1275}
1276
dan578e1ca2014-04-01 15:38:44 +00001277
1278/*
mistachkin8765b462012-09-10 08:48:05 +00001279** Usage: sqlite3_dump_memsys3 FILENAME
1280** sqlite3_dump_memsys5 FILENAME
danielk197732155ef2008-06-25 10:34:34 +00001281**
1282** Write a summary of unfreed memsys3 allocations to FILENAME.
1283*/
mistachkin7617e4a2016-07-28 17:11:20 +00001284static int SQLITE_TCLAPI test_dump_memsys3(
danielk197732155ef2008-06-25 10:34:34 +00001285 void * clientData,
1286 Tcl_Interp *interp,
1287 int objc,
1288 Tcl_Obj *CONST objv[]
1289){
1290 if( objc!=2 ){
1291 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
1292 return TCL_ERROR;
1293 }
danielk1977c66c0e12008-06-25 14:26:07 +00001294
drh860e3322011-08-25 18:54:46 +00001295 switch( SQLITE_PTR_TO_INT(clientData) ){
danielk19770d84e5b2008-06-27 14:05:24 +00001296 case 3: {
danielk1977c66c0e12008-06-25 14:26:07 +00001297#ifdef SQLITE_ENABLE_MEMSYS3
1298 extern void sqlite3Memsys3Dump(const char*);
1299 sqlite3Memsys3Dump(Tcl_GetString(objv[1]));
1300 break;
danielk197732155ef2008-06-25 10:34:34 +00001301#endif
danielk1977c66c0e12008-06-25 14:26:07 +00001302 }
danielk19770d84e5b2008-06-27 14:05:24 +00001303 case 5: {
danielk1977c66c0e12008-06-25 14:26:07 +00001304#ifdef SQLITE_ENABLE_MEMSYS5
1305 extern void sqlite3Memsys5Dump(const char*);
1306 sqlite3Memsys5Dump(Tcl_GetString(objv[1]));
1307 break;
1308#endif
1309 }
1310 }
danielk197732155ef2008-06-25 10:34:34 +00001311 return TCL_OK;
1312}
1313
1314/*
drhf7141992008-06-19 00:16:08 +00001315** Usage: sqlite3_status OPCODE RESETFLAG
1316**
1317** Return a list of three elements which are the sqlite3_status() return
1318** code, the current value, and the high-water mark value.
1319*/
mistachkin7617e4a2016-07-28 17:11:20 +00001320static int SQLITE_TCLAPI test_status(
drhf7141992008-06-19 00:16:08 +00001321 void * clientData,
1322 Tcl_Interp *interp,
1323 int objc,
1324 Tcl_Obj *CONST objv[]
1325){
1326 int rc, iValue, mxValue;
mistachkin7bb22ac2015-01-12 19:59:12 +00001327 int i, op = 0, resetFlag;
drhf7141992008-06-19 00:16:08 +00001328 const char *zOpName;
1329 static const struct {
1330 const char *zName;
1331 int op;
1332 } aOp[] = {
1333 { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED },
drhe50135e2008-08-05 17:53:22 +00001334 { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE },
drhf7141992008-06-19 00:16:08 +00001335 { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED },
1336 { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW },
drhe50135e2008-08-05 17:53:22 +00001337 { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE },
drhf7141992008-06-19 00:16:08 +00001338 { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED },
1339 { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
drhe50135e2008-08-05 17:53:22 +00001340 { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE },
drhec424a52008-07-25 15:39:03 +00001341 { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK },
drheafc43b2010-07-26 18:43:40 +00001342 { "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT },
drhf7141992008-06-19 00:16:08 +00001343 };
1344 Tcl_Obj *pResult;
1345 if( objc!=3 ){
1346 Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
1347 return TCL_ERROR;
1348 }
1349 zOpName = Tcl_GetString(objv[1]);
1350 for(i=0; i<ArraySize(aOp); i++){
1351 if( strcmp(aOp[i].zName, zOpName)==0 ){
1352 op = aOp[i].op;
1353 break;
1354 }
1355 }
1356 if( i>=ArraySize(aOp) ){
1357 if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR;
1358 }
1359 if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR;
drhaf005fb2008-07-09 16:51:51 +00001360 iValue = 0;
1361 mxValue = 0;
drhf7141992008-06-19 00:16:08 +00001362 rc = sqlite3_status(op, &iValue, &mxValue, resetFlag);
1363 pResult = Tcl_NewObj();
1364 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1365 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1366 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1367 Tcl_SetObjResult(interp, pResult);
1368 return TCL_OK;
1369}
drh9ac3fe92008-06-18 18:12:04 +00001370
1371/*
drh633e6d52008-07-28 19:34:53 +00001372** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG
1373**
1374** Return a list of three elements which are the sqlite3_db_status() return
1375** code, the current value, and the high-water mark value.
1376*/
mistachkin7617e4a2016-07-28 17:11:20 +00001377static int SQLITE_TCLAPI test_db_status(
drh633e6d52008-07-28 19:34:53 +00001378 void * clientData,
1379 Tcl_Interp *interp,
1380 int objc,
1381 Tcl_Obj *CONST objv[]
1382){
1383 int rc, iValue, mxValue;
mistachkin7bb22ac2015-01-12 19:59:12 +00001384 int i, op = 0, resetFlag;
drh633e6d52008-07-28 19:34:53 +00001385 const char *zOpName;
1386 sqlite3 *db;
mistachkine84d8d32013-04-29 03:09:10 +00001387 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
drh633e6d52008-07-28 19:34:53 +00001388 static const struct {
1389 const char *zName;
1390 int op;
1391 } aOp[] = {
drh2a58e9c2010-12-21 21:28:38 +00001392 { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
1393 { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
1394 { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
1395 { "STMT_USED", SQLITE_DBSTATUS_STMT_USED },
1396 { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT },
1397 { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
dan58ca31c2011-09-22 14:41:16 +00001398 { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL },
1399 { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT },
drh9ad3ee42012-03-24 20:06:14 +00001400 { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS },
drh648e2642013-07-11 15:03:32 +00001401 { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE },
dan272989b2016-07-06 10:12:02 +00001402 { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS },
dan9c106082016-07-06 18:12:54 +00001403 { "CACHE_USED_SHARED", SQLITE_DBSTATUS_CACHE_USED_SHARED },
drhffc78a42018-03-14 14:53:50 +00001404 { "CACHE_SPILL", SQLITE_DBSTATUS_CACHE_SPILL },
drh633e6d52008-07-28 19:34:53 +00001405 };
1406 Tcl_Obj *pResult;
1407 if( objc!=4 ){
dan58ca31c2011-09-22 14:41:16 +00001408 Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG");
drh633e6d52008-07-28 19:34:53 +00001409 return TCL_ERROR;
1410 }
1411 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1412 zOpName = Tcl_GetString(objv[2]);
drh2a58e9c2010-12-21 21:28:38 +00001413 if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7;
1414 if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9;
drh633e6d52008-07-28 19:34:53 +00001415 for(i=0; i<ArraySize(aOp); i++){
1416 if( strcmp(aOp[i].zName, zOpName)==0 ){
1417 op = aOp[i].op;
1418 break;
1419 }
1420 }
1421 if( i>=ArraySize(aOp) ){
1422 if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
1423 }
1424 if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
1425 iValue = 0;
1426 mxValue = 0;
1427 rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag);
1428 pResult = Tcl_NewObj();
1429 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1430 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1431 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1432 Tcl_SetObjResult(interp, pResult);
1433 return TCL_OK;
1434}
1435
1436/*
danielk1977d09414c2008-06-19 18:17:49 +00001437** install_malloc_faultsim BOOLEAN
1438*/
mistachkin7617e4a2016-07-28 17:11:20 +00001439static int SQLITE_TCLAPI test_install_malloc_faultsim(
danielk1977d09414c2008-06-19 18:17:49 +00001440 void * clientData,
1441 Tcl_Interp *interp,
1442 int objc,
1443 Tcl_Obj *CONST objv[]
1444){
1445 int rc;
1446 int isInstall;
1447
1448 if( objc!=2 ){
1449 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1450 return TCL_ERROR;
1451 }
1452 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
1453 return TCL_ERROR;
1454 }
danielk1977ef05f2d2008-06-20 11:05:37 +00001455 rc = faultsimInstall(isInstall);
mistachkine84d8d32013-04-29 03:09:10 +00001456 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
danielk1977d09414c2008-06-19 18:17:49 +00001457 return TCL_OK;
1458}
1459
1460/*
danielk19778b322822009-07-01 18:09:01 +00001461** sqlite3_install_memsys3
1462*/
mistachkin7617e4a2016-07-28 17:11:20 +00001463static int SQLITE_TCLAPI test_install_memsys3(
danielk19778b322822009-07-01 18:09:01 +00001464 void * clientData,
1465 Tcl_Interp *interp,
1466 int objc,
1467 Tcl_Obj *CONST objv[]
1468){
1469 int rc = SQLITE_MISUSE;
1470#ifdef SQLITE_ENABLE_MEMSYS3
1471 const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
1472 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetMemsys3());
1473#endif
mistachkine84d8d32013-04-29 03:09:10 +00001474 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
danielk19778b322822009-07-01 18:09:01 +00001475 return TCL_OK;
1476}
1477
mistachkin7617e4a2016-07-28 17:11:20 +00001478static int SQLITE_TCLAPI test_vfs_oom_test(
danc396d4a2010-07-02 11:27:43 +00001479 void * clientData,
1480 Tcl_Interp *interp,
1481 int objc,
1482 Tcl_Obj *CONST objv[]
1483){
1484 extern int sqlite3_memdebug_vfs_oom_test;
1485 if( objc>2 ){
1486 Tcl_WrongNumArgs(interp, 1, objv, "?INTEGER?");
1487 return TCL_ERROR;
1488 }else if( objc==2 ){
1489 int iNew;
1490 if( Tcl_GetIntFromObj(interp, objv[1], &iNew) ) return TCL_ERROR;
1491 sqlite3_memdebug_vfs_oom_test = iNew;
1492 }
1493 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_vfs_oom_test));
1494 return TCL_OK;
1495}
1496
danielk19778b322822009-07-01 18:09:01 +00001497/*
drh2f999a62007-08-15 19:16:43 +00001498** Register commands with the TCL interpreter.
1499*/
1500int Sqlitetest_malloc_Init(Tcl_Interp *interp){
1501 static struct {
1502 char *zName;
1503 Tcl_ObjCmdProc *xProc;
danielk1977c66c0e12008-06-25 14:26:07 +00001504 int clientData;
drh2f999a62007-08-15 19:16:43 +00001505 } aObjCmd[] = {
drh8a42cbd2008-07-10 18:13:42 +00001506 { "sqlite3_malloc", test_malloc ,0 },
1507 { "sqlite3_realloc", test_realloc ,0 },
1508 { "sqlite3_free", test_free ,0 },
1509 { "memset", test_memset ,0 },
1510 { "memget", test_memget ,0 },
1511 { "sqlite3_memory_used", test_memory_used ,0 },
1512 { "sqlite3_memory_highwater", test_memory_highwater ,0 },
1513 { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 },
1514 { "sqlite3_memdebug_dump", test_memdebug_dump ,0 },
1515 { "sqlite3_memdebug_fail", test_memdebug_fail ,0 },
1516 { "sqlite3_memdebug_pending", test_memdebug_pending ,0 },
1517 { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 },
1518 { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 },
1519 { "sqlite3_memdebug_log", test_memdebug_log ,0 },
drh8a42cbd2008-07-10 18:13:42 +00001520 { "sqlite3_config_pagecache", test_config_pagecache ,0 },
drhb232c232008-11-19 01:20:26 +00001521 { "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
drh8a42cbd2008-07-10 18:13:42 +00001522 { "sqlite3_status", test_status ,0 },
drh633e6d52008-07-28 19:34:53 +00001523 { "sqlite3_db_status", test_db_status ,0 },
drh8a42cbd2008-07-10 18:13:42 +00001524 { "install_malloc_faultsim", test_install_malloc_faultsim ,0 },
danielk19770d84e5b2008-06-27 14:05:24 +00001525 { "sqlite3_config_heap", test_config_heap ,0 },
mistachkinac1f1042013-11-23 00:27:29 +00001526 { "sqlite3_config_heap_size", test_config_heap_size ,0 },
drh8a42cbd2008-07-10 18:13:42 +00001527 { "sqlite3_config_memstatus", test_config_memstatus ,0 },
drh633e6d52008-07-28 19:34:53 +00001528 { "sqlite3_config_lookaside", test_config_lookaside ,0 },
drh6480aad2008-08-01 16:31:14 +00001529 { "sqlite3_config_error", test_config_error ,0 },
dancd74b612011-04-22 19:37:32 +00001530 { "sqlite3_config_uri", test_config_uri ,0 },
drhde9a7b82012-09-17 20:44:46 +00001531 { "sqlite3_config_cis", test_config_cis ,0 },
drh3bd17912015-01-02 15:55:29 +00001532 { "sqlite3_config_pmasz", test_config_pmasz ,0 },
drh633e6d52008-07-28 19:34:53 +00001533 { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
danielk19770d84e5b2008-06-27 14:05:24 +00001534 { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
drhb232c232008-11-19 01:20:26 +00001535 { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
danielk19778b322822009-07-01 18:09:01 +00001536 { "sqlite3_install_memsys3", test_install_memsys3 ,0 },
danc396d4a2010-07-02 11:27:43 +00001537 { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 },
drh2f999a62007-08-15 19:16:43 +00001538 };
1539 int i;
1540 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
drh860e3322011-08-25 18:54:46 +00001541 ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData);
danielk1977c66c0e12008-06-25 14:26:07 +00001542 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
drh2f999a62007-08-15 19:16:43 +00001543 }
1544 return TCL_OK;
1545}
danielk1977ef05f2d2008-06-20 11:05:37 +00001546#endif