wasCSharpSQLite – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System.Diagnostics;
2  
3  
4 namespace Community.CsharpSqlite
5 {
6 #if TCLSH
7 using tcl.lang;
8 using Tcl_Interp = tcl.lang.Interp;
9 using Tcl_Obj = tcl.lang.TclObject;
10  
11 public partial class Sqlite3
12 {
13  
14 /*
15 ** 2007 August 15
16 **
17 ** The author disclaims copyright to this source code. In place of
18 ** a legal notice, here is a blessing:
19 **
20 ** May you do good and not evil.
21 ** May you find forgiveness for yourself and forgive others.
22 ** May you share freely, never taking more than you give.
23 **
24 *************************************************************************
25 **
26 ** This file contains code used to implement test interfaces to the
27 ** memory allocation subsystem.
28 *************************************************************************
29 ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
30 ** C#-SQLite is an independent reimplementation of the SQLite software library
31 **
32 ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2
33 **
34 *************************************************************************
35 */
36 //#include "sqliteInt.h"
37 //#include "tcl.h"
38 //#include <stdlib.h>
39 //#include <string.h>
40 //#include <assert.h>
41  
42 /*
43 ** This structure is used to encapsulate the global state variables used
44 ** by malloc() fault simulation.
45 */
46 struct MemFault
47 {
48 public int iCountdown; /* Number of pending successes before a failure */
49 public int nRepeat; /* Number of times to repeat the failure */
50 public int nBenign; /* Number of benign failures seen since last config */
51 public int nFail; /* Number of failures seen since last config */
52 public int enable; /* True if enabled */
53 public int isInstalled; /* True if the fault simulation layer is installed */
54 public int isBenignMode; /* True if malloc failures are considered benign */
55 public sqlite3_mem_methods m; /* 'Real' malloc implementation */
56 }
57 static MemFault memfault;
58  
59 /*
60 ** This routine exists as a place to set a breakpoint that will
61 ** fire on any simulated malloc() failure.
62 */
63 static int cnt = 0;
64 static void sqlite3Fault()
65 {
66 cnt++;
67 }
68  
69 /*
70 ** Check to see if a fault should be simulated. Return true to simulate
71 ** the fault. Return false if the fault should not be simulated.
72 */
73 static int faultsimStep()
74 {
75 if ( likely( memfault.enable != 0 ) )
76 {
77 return 0;
78 }
79 if ( memfault.iCountdown > 0 )
80 {
81 memfault.iCountdown--;
82 return 0;
83 }
84 sqlite3Fault();
85 memfault.nFail++;
86 if ( memfault.isBenignMode > 0 )
87 {
88 memfault.nBenign++;
89 }
90 memfault.nRepeat--;
91 if ( memfault.nRepeat <= 0 )
92 {
93 memfault.enable = 0;
94 }
95 return 1;
96 }
97  
98 /*
99 ** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation
100 ** logic.
101 */
102 static byte[] faultsimMalloc( int n )
103 {
104 byte[] p = null;
105 if ( faultsimStep() != 0 )
106 {
107 p = memfault.m.xMalloc( n );
108 }
109 return p;
110 }
111 static int[] faultsimMallocInt( int n )
112 {
113 int[] p = null;
114 if ( faultsimStep() != 0 )
115 {
116 p = memfault.m.xMallocInt( n );
117 }
118 return p;
119 }
120 static Mem faultsimMallocMem( Mem n )
121 {
122 Mem p = null;
123 if ( faultsimStep() != 0 )
124 {
125 p = memfault.m.xMallocMem( n );
126 }
127 return p;
128 }
129 /*
130 ** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation
131 ** logic.
132 */
133 static byte[] faultsimRealloc( byte[] pOld, int n )
134 {
135 byte[] p = null;
136 if ( faultsimStep() != 0 )
137 {
138 p = memfault.m.xRealloc( pOld, n );
139 }
140 return p;
141 }
142  
143 /*
144 ** The following method calls are passed directly through to the underlying
145 ** malloc system:
146 **
147 ** xFree
148 ** xSize
149 ** xRoundup
150 ** xInit
151 ** xShutdown
152 */
153 static void faultsimFree( ref byte[] p )
154 {
155 memfault.m.xFree( ref p );
156 }
157 static void faultsimFreeInt( ref int[] p )
158 {
159 memfault.m.xFreeInt( ref p );
160 }
161 static void faultsimFreeMem( ref Mem p )
162 {
163 memfault.m.xFreeMem( ref p );
164 }
165 static int faultsimSize( byte[] p )
166 {
167 return memfault.m.xSize( p );
168 }
169 static int faultsimRoundup( int n )
170 {
171 return memfault.m.xRoundup( n );
172 }
173 static int faultsimInit( object p )
174 {
175 return memfault.m.xInit( memfault.m.pAppData );
176 }
177 static void faultsimShutdown( object p )
178 {
179 memfault.m.xShutdown( memfault.m.pAppData );
180 }
181  
182 /*
183 ** This routine configures the malloc failure simulation. After
184 ** calling this routine, the next nDelay mallocs will succeed, followed
185 ** by a block of nRepeat failures, after which malloc() calls will begin
186 ** to succeed again.
187 */
188 static void faultsimConfig( int nDelay, int nRepeat )
189 {
190 memfault.iCountdown = nDelay;
191 memfault.nRepeat = nRepeat;
192 memfault.nBenign = 0;
193 memfault.nFail = 0;
194 memfault.enable = ( nDelay >= 0 ) ? 1 : 0;
195  
196 /* Sometimes, when running multi-threaded tests, the isBenignMode
197 ** variable is not properly incremented/decremented so that it is
198 ** 0 when not inside a benign malloc block. This doesn't affect
199 ** the multi-threaded tests, as they do not use this system. But
200 ** it does affect OOM tests run later in the same process. So
201 ** zero the variable here, just to be sure.
202 */
203 memfault.isBenignMode = 0;
204 }
205  
206 /*
207 ** Return the number of faults (both hard and benign faults) that have
208 ** occurred since the injector was last configured.
209 */
210 static int faultsimFailures()
211 {
212 return memfault.nFail;
213 }
214  
215 /*
216 ** Return the number of benign faults that have occurred since the
217 ** injector was last configured.
218 */
219 static int faultsimBenignFailures()
220 {
221 return memfault.nBenign;
222 }
223  
224 /*
225 ** Return the number of successes that will occur before the next failure.
226 ** If no failures are scheduled, return -1.
227 */
228 static int faultsimPending()
229 {
230 if ( memfault.enable != 0 )
231 {
232 return memfault.iCountdown;
233 }
234 else
235 {
236 return -1;
237 }
238 }
239  
240  
241 static void faultsimBeginBenign()
242 {
243 memfault.isBenignMode++;
244 }
245 static void faultsimEndBenign()
246 {
247 memfault.isBenignMode--;
248 }
249  
250 /*
251 ** Add or remove the fault-simulation layer using sqlite3_config(). If
252 ** the argument is non-zero, the
253 */
254 static int faultsimInstall( int install )
255 {
256 sqlite3_mem_methods m = new sqlite3_mem_methods(
257 (dxMalloc)faultsimMalloc, /* xMalloc */
258 (dxMallocInt)faultsimMallocInt, /* xMalloc */
259 (dxMallocMem)faultsimMallocMem, /* xMalloc */
260 (dxFree)faultsimFree, /* xFree */
261 (dxFreeInt)faultsimFreeInt, /* xFree */
262 (dxFreeMem)faultsimFreeMem,
263 (dxRealloc)faultsimRealloc, /* xRealloc */
264 (dxSize)faultsimSize, /* xSize */
265 (dxRoundup)faultsimRoundup, /* xRoundup */
266 (dxMemInit)faultsimInit, /* xInit */
267 (dxMemShutdown)faultsimShutdown, /* xShutdown */
268 null /* pAppData */
269 );
270 int rc;
271  
272 //install = ( install != 0 ? 1 : 0 );
273 Debug.Assert( memfault.isInstalled == 1 || memfault.isInstalled == 0 );
274  
275 if ( install == memfault.isInstalled )
276 {
277 return SQLITE_ERROR;
278 }
279  
280 if ( install != 0 )
281 {
282 rc = sqlite3_config( SQLITE_CONFIG_GETMALLOC, ref memfault.m );
283 Debug.Assert( memfault.m.xMalloc != null );
284 if ( rc == SQLITE_OK )
285 {
286 rc = sqlite3_config( SQLITE_CONFIG_MALLOC, m );
287 }
288 sqlite3_test_control( SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
289 (void_function)faultsimBeginBenign, (void_function)faultsimEndBenign
290 );
291 }
292 else
293 {
294 //sqlite3_mem_methods m;
295 Debug.Assert( memfault.m.xMalloc != null );
296  
297 /* One should be able to reset the default memory allocator by storing
298 ** a zeroed allocator then calling GETMALLOC. */
299 m = new sqlite3_mem_methods();// memset( &m, 0, sizeof( m ) );
300 sqlite3_config( SQLITE_CONFIG_MALLOC, m );
301 sqlite3_config( SQLITE_CONFIG_GETMALLOC, ref m );
302 Debug.Assert( m.GetHashCode() == memfault.m.GetHashCode() );//memcmp(&m, &memfault.m, sizeof(m))==0 );
303  
304 rc = sqlite3_config( SQLITE_CONFIG_MALLOC, ref memfault.m );
305 sqlite3_test_control( SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0 );
306 }
307  
308 if ( rc == SQLITE_OK )
309 {
310 memfault.isInstalled = 1;
311 }
312 return rc;
313 }
314  
315 #if SQLITE_TEST
316  
317 /*
318 ** This function is implemented in test1.c. Returns a pointer to a static
319 ** buffer containing the symbolic SQLite error code that corresponds to
320 ** the least-significant 8-bits of the integer passed as an argument.
321 ** For example:
322 **
323 ** sqlite3TestErrorName(1) -> "SQLITE_ERROR"
324 */
325 //string sqlite3TestErrorName(int);
326  
327  
328 /*
329 ** Transform pointers to text and back again
330 */
331 //static void pointerToText(object p, string z){
332 // static const char zHex[] = "0123456789abcdef";
333 // int i, k;
334 // unsigned int u;
335 // sqlite3_u3264 n;
336 // if( p==0 ){
337 // strcpy(z, "0");
338 // return;
339 //}
340 // if( sizeof(n)==sizeof(p) ){
341 // memcpy(&n, ref p, sizeof(p));
342 // }else if( sizeof(u)==sizeof(p) ){
343 // memcpy(&u, ref p, sizeof(u));
344 // n = u;
345 // }else{
346 // Debug.Assert( 0 );
347 // }
348 // for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){
349 // z[k] = zHex[n&0xf];
350 // n >>= 4;
351 // }
352 // z[sizeof(p)*2] = 0;
353 //}
354 //static int hexToInt(int h){
355 // if( h>='0' && h<='9' ){
356 // return h - '0';
357 // }else if( h>='a' && h<='f' ){
358 // return h - 'a' + 10;
359 // }else{
360 // return -1;
361 // }
362 //}
363 //static int textToPointer(string z, object **pp){
364 // sqlite3_u3264 n = 0;
365 // int i;
366 // unsigned int u;
367 // for(i=0; i<sizeof(void)*2 && z[0]; i++){
368 // int v;
369 // v = hexToInt(*z++);
370 // if( v<0 ) return TCL.TCL_ERROR;
371 // n = n*16 + v;
372 // }
373 // if( *z!=0 ) return TCL.TCL_ERROR;
374 // if( sizeof(n)==sizeof(*pp) ){
375 // memcpy(pp, ref n, sizeof(n));
376 // }else if( sizeof(u)==sizeof(*pp) ){
377 // u = (unsigned int)n;
378 // memcpy(pp, ref u, sizeof(u));
379 // }else{
380 // Debug.Assert( 0 );
381 // }
382 // return TCL.TCL_OK;
383 //}
384  
385 /*
386 ** Usage: sqlite3Malloc NBYTES
387 **
388 ** Raw test interface for sqlite3Malloc().
389 */
390 //static int test_malloc(
391 // object clientdata,
392 // Tcl_Interp interp,
393 // int objc,
394 // Tcl_Obj[] objv
395 //){
396 // int nByte;
397 // object p;
398 // char zOut[100];
399 // if( objc!=2 ){
400 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");
401 // return TCL.TCL_ERROR;
402 // }
403 // if( TCL.Tcl_GetIntFromObj(interp, objv[1], out nByte) ) return TCL.TCL_ERROR;
404 // p = sqlite3Malloc((unsigned)nByte);
405 // pointerToText(p, zOut);
406 // TCL.TCL_AppendResult(interp, zOut, NULL);
407 // return TCL.TCL_OK;
408 //}
409  
410 /*
411 ** Usage: sqlite3_realloc PRIOR NBYTES
412 **
413 ** Raw test interface for sqlite3_realloc().
414 */
415 //static int test_realloc(
416 // object clientdata,
417 // Tcl_Interp interp,
418 // int objc,
419 // Tcl_Obj[] objv
420 //){
421 // int nByte;
422 // void pPrior, p;
423 // char zOut[100];
424 // if( objc!=3 ){
425 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");
426 // return TCL.TCL_ERROR;
427 // }
428 // if( TCL.Tcl_GetIntFromObj(interp, objv[2], out nByte) ) return TCL.TCL_ERROR;
429 // if( textToPointer(Tcl_GetString(objv[1]), out pPrior) ){
430 // TCL.TCL_AppendResult(interp, "bad pointer: ", TCL.Tcl_GetString(objv[1]));
431 // return TCL.TCL_ERROR;
432 // }
433 // p = sqlite3_realloc(pPrior, (unsigned)nByte);
434 // pointerToText(p, zOut);
435 // TCL.TCL_AppendResult(interp, zOut, NULL);
436 // return TCL.TCL_OK;
437 //}
438  
439 /*
440 ** tclcmd: sqlite3_config_uri BOOLEAN
441 **
442 ** Invoke sqlite3_config() or sqlite3_db_config() with invalid
443 ** opcodes and verify that they return errors.
444 */
445 static int test_config_uri(
446 object clientData,
447 Tcl_Interp interp,
448 int objc,
449 Tcl_Obj[] objv
450 ){
451 int rc;
452 bool bOpenUri = false;
453  
454 if( objc!=2 ){
455 TCL.Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
456 return TCL.TCL_ERROR;
457 }
458 if ( TCL.Tcl_GetBooleanFromObj( interp, objv[1], out bOpenUri ) )
459 {
460 return TCL.TCL_ERROR;
461 }
462  
463 rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
464 TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_VOLATILE );
465  
466 return TCL.TCL_OK;
467 }
468  
469 /*
470 ** Usage: sqlite3_free PRIOR
471 **
472 ** Raw test interface for sqlite3DbFree(db,).
473 */
474 //static int test_free(
475 // object clientdata,
476 // Tcl_Interp interp,
477 // int objc,
478 // Tcl_Obj[] objv
479 //){
480 // void pPrior;
481 // if( objc!=2 ){
482 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");
483 // return TCL.TCL_ERROR;
484 // }
485 // if( textToPointer(Tcl_GetString(objv[1]), out pPrior) ){
486 // TCL.TCL_AppendResult(interp, "bad pointer: ", TCL.Tcl_GetString(objv[1]));
487 // return TCL.TCL_ERROR;
488 // }
489 // sqlite3DbFree(db,pPrior);
490 // return TCL.TCL_OK;
491 //}
492  
493 /*
494 ** These routines are in test_hexio.c
495 */
496 //int sqlite3TestHexToBin(string , int, char );
497 //int sqlite3TestBinToHex(char*,int);
498  
499 /*
500 ** Usage: memset ADDRESS SIZE HEX
501 **
502 ** Set a chunk of memory (obtained from malloc, probably) to a
503 ** specified hex pattern.
504 */
505 //static int test_memset(
506 // object clientdata,
507 // Tcl_Interp interp,
508 // int objc,
509 // Tcl_Obj[] objv
510 //){
511 // object p;
512 // int size, n, i;
513 // string zHex;
514 // string zOut;
515 // char zBin[100];
516  
517 // if( objc!=4 ){
518 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");
519 // return TCL.TCL_ERROR;
520 // }
521 // if( textToPointer(Tcl_GetString(objv[1]), out p) ){
522 // TCL.TCL_AppendResult(interp, "bad pointer: ", TCL.Tcl_GetString(objv[1]));
523 // return TCL.TCL_ERROR;
524 // }
525 // if( TCL.Tcl_GetIntFromObj(interp, objv[2], out size) ){
526 // return TCL.TCL_ERROR;
527 // }
528 // if( size<=0 ){
529 // TCL.TCL_AppendResult(interp, "size must be positive");
530 // return TCL.TCL_ERROR;
531 // }
532 // zHex = TCL.Tcl_GetStringFromObj(objv[3], out n);
533 // if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
534 // n = sqlite3TestHexToBin(zHex, n, zBin);
535 // if( n==0 ){
536 // TCL.TCL_AppendResult(interp, "no data");
537 // return TCL.TCL_ERROR;
538 // }
539 // zOut = p;
540 // for(i=0; i<size; i++){
541 // zOut[i] = zBin[i%n];
542 // }
543 // return TCL.TCL_OK;
544 //}
545  
546 /*
547 ** Usage: memget ADDRESS SIZE
548 **
549 ** Return memory as hexadecimal text.
550 */
551 //static int test_memget(
552 // object clientdata,
553 // Tcl_Interp interp,
554 // int objc,
555 // Tcl_Obj[] objv
556 //){
557 // object p;
558 // int size, n;
559 // string zBin;
560 // char zHex[100];
561  
562 // if( objc!=3 ){
563 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");
564 // return TCL.TCL_ERROR;
565 // }
566 // if( textToPointer(Tcl_GetString(objv[1]), out p) ){
567 // TCL.TCL_AppendResult(interp, "bad pointer: ", TCL.Tcl_GetString(objv[1]));
568 // return TCL.TCL_ERROR;
569 // }
570 // if( TCL.Tcl_GetIntFromObj(interp, objv[2], out size) ){
571 // return TCL.TCL_ERROR;
572 // }
573 // if( size<=0 ){
574 // TCL.TCL_AppendResult(interp, "size must be positive");
575 // return TCL.TCL_ERROR;
576 // }
577 // zBin = p;
578 // while( size>0 ){
579 // if( size>(sizeof(zHex)-1)/2 ){
580 // n = (sizeof(zHex)-1)/2;
581 // }else{
582 // n = size;
583 // }
584 // memcpy(zHex, zBin, n);
585 // zBin += n;
586 // size -= n;
587 // sqlite3TestBinToHex(zHex, n);
588 // TCL.TCL_AppendResult(interp, zHex);
589 // }
590 // return TCL.TCL_OK;
591 //}
592 #if FALSE
593 /*
594 ** Usage: sqlite3_memory_used
595 **
596 ** Raw test interface for sqlite3_memory_used().
597 */
598 static int test_memory_used(
599 object clientdata,
600 Tcl_Interp interp,
601 int objc,
602 Tcl_Obj[] objv
603 )
604 {
605 TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewWideIntObj( sqlite3_memory_used() ) );
606 return TCL.TCL_OK;
607 }
608  
609 /*
610 ** Usage: sqlite3_memory_highwater ?RESETFLAG?
611 **
612 ** Raw test interface for sqlite3_memory_highwater().
613 */
614 static int test_memory_highwater(
615 object clientdata,
616 Tcl_Interp interp,
617 int objc,
618 Tcl_Obj[] objv
619 )
620 {
621 bool resetFlag = false;
622 if ( objc != 1 && objc != 2 )
623 {
624 TCL.Tcl_WrongNumArgs( interp, 1, objv, "?RESET?" );
625 return TCL.TCL_ERROR;
626 }
627 if ( objc == 2 )
628 {
629 if ( TCL.Tcl_GetBooleanFromObj( interp, objv[1], out resetFlag ) ) return TCL.TCL_ERROR;
630 }
631 TCL.Tcl_SetObjResult( interp,
632 TCL.Tcl_NewWideIntObj( sqlite3_memory_highwater( resetFlag ? 1 : 0 ) ) );
633 return TCL.TCL_OK;
634 }
635 #endif
636  
637 /*
638 ** Usage: sqlite3_memdebug_backtrace DEPTH
639 **
640 ** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined
641 ** then this routine is a no-op.
642 */
643 //static int test_memdebug_backtrace(
644 // object clientdata,
645 // Tcl_Interp interp,
646 // int objc,
647 // Tcl_Obj[] objv
648 //){
649 // int depth;
650 // if( objc!=2 ){
651 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "DEPT");
652 // return TCL.TCL_ERROR;
653 // }
654 // if( TCL.Tcl_GetIntFromObj(interp, objv[1], out depth) ) return TCL.TCL_ERROR;
655 //#if SQLITE_MEMDEBUG
656 // {
657 // extern void sqlite3MemdebugBacktrace(int);
658 // sqlite3MemdebugBacktrace(depth);
659 // }
660 //#endif
661 // return TCL.TCL_OK;
662 //}
663  
664 /*
665 ** Usage: sqlite3_memdebug_dump FILENAME
666 **
667 ** Write a summary of unfreed memory to FILENAME.
668 */
669 static int test_memdebug_dump(
670 object clientdata,
671 Tcl_Interp interp,
672 int objc,
673 Tcl_Obj[] objv
674 )
675 {
676 if ( objc != 2 )
677 {
678 TCL.Tcl_WrongNumArgs( interp, 1, objv, "FILENAME" );
679 return TCL.TCL_ERROR;
680 }
681 #if (SQLITE_MEMDEBUG) || (SQLITE_MEMORY_SIZE) || (SQLITE_POW2_MEMORY_SIZE)
682 {
683 extern void sqlite3MemdebugDump(const char);
684 sqlite3MemdebugDump(Tcl_GetString(objv[1]));
685 }
686 #endif
687 return TCL.TCL_OK;
688 }
689  
690 /*
691 ** Usage: sqlite3_memdebug_malloc_count
692 **
693 ** Return the total number of times malloc() has been called.
694 */
695 static int test_memdebug_malloc_count(
696 object clientdata,
697 Tcl_Interp interp,
698 int objc,
699 Tcl_Obj[] objv
700 )
701 {
702 int nMalloc = -1;
703 if ( objc != 1 )
704 {
705 TCL.Tcl_WrongNumArgs( interp, 1, objv, "" );
706 return TCL.TCL_ERROR;
707 }
708 #if SQLITE_MEMDEBUG
709 {
710 extern int sqlite3MemdebugMallocCount();
711 nMalloc = sqlite3MemdebugMallocCount();
712 }
713 #endif
714 TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( nMalloc ) );
715 return TCL.TCL_OK;
716 }
717  
718  
719 /*
720 ** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?
721 **
722 ** where options are:
723 **
724 ** -repeat <count>
725 ** -benigncnt <varname>
726 **
727 ** Arrange for a simulated malloc() failure after COUNTER successes.
728 ** If a repeat count is specified, the fault is repeated that many
729 ** times.
730 **
731 ** Each call to this routine overrides the prior counter value.
732 ** This routine returns the number of simulated failures that have
733 ** happened since the previous call to this routine.
734 **
735 ** To disable simulated failures, use a COUNTER of -1.
736 */
737 static int test_memdebug_fail(
738 object clientdata,
739 Tcl_Interp interp,
740 int objc,
741 Tcl_Obj[] objv
742 )
743 {
744 int ii;
745 int iFail = 0;
746 int nRepeat = 1;
747 Tcl_Obj pBenignCnt = null;
748 int nBenign;
749 int nFail = 0;
750  
751 if ( objc < 2 )
752 {
753 TCL.Tcl_WrongNumArgs( interp, 1, objv, "COUNTER ?OPTIONS?" );
754 return TCL.TCL_ERROR;
755 }
756 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out iFail ) )
757 return TCL.TCL_ERROR;
758  
759 for ( ii = 2; ii < objc; ii += 2 )
760 {
761 int nOption = 0;
762 string zOption = TCL.Tcl_GetStringFromObj( objv[ii], out nOption );
763 string zErr = "";
764  
765 if ( nOption > 1 && zOption == "-repeat" )
766 {
767 if ( ii == ( objc - 1 ) )
768 {
769 zErr = "option requires an argument: ";
770 }
771 else
772 {
773 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[ii + 1], out nRepeat ) )
774 {
775 return TCL.TCL_ERROR;
776 }
777 }
778 }
779 else if ( nOption > 1 && zOption == "-benigncnt" )
780 {
781 if ( ii == ( objc - 1 ) )
782 {
783 zErr = "option requires an argument: ";
784 }
785 else
786 {
787 pBenignCnt = objv[ii + 1];
788 }
789 }
790 else
791 {
792 zErr = "unknown option: ";
793 }
794  
795 if ( zErr != "" )
796 {
797 TCL.Tcl_AppendResult( interp, zErr, zOption );
798 return TCL.TCL_ERROR;
799 }
800 }
801  
802 nBenign = faultsimBenignFailures();
803 nFail = faultsimFailures();
804 faultsimConfig( iFail, nRepeat );
805 if ( pBenignCnt != null )
806 {
807 TCL.Tcl_ObjSetVar2( interp, pBenignCnt, null, TCL.Tcl_NewIntObj( nBenign ), 0 );
808 }
809 TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( nFail ) );
810 return TCL.TCL_OK;
811 }
812  
813 /*
814 ** Usage: sqlite3_memdebug_pending
815 **
816 ** Return the number of malloc() calls that will succeed before a
817 ** simulated failure occurs. A negative return value indicates that
818 ** no malloc() failure is scheduled.
819 */
820 // static int test_memdebug_pending(
821 // object clientData,
822 // Tcl_Interp interp,
823 // int objc,
824 // Tcl_Obj[] objv
825 //){
826 // int nPending;
827 // if( objc!=1 ){
828 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "");
829 // return TCL.TCL_ERROR;
830 // }
831 // nPending = faultsimPending();
832 // TCL.Tcl_SetObjResult(interp, TCL.Tcl_NewIntObj(nPending));
833 // return TCL.TCL_OK;
834 //}
835  
836 /*
837 ** Usage: sqlite3_memdebug_settitle TITLE
838 **
839 ** Set a title string stored with each allocation. The TITLE is
840 ** typically the name of the test that was running when the
841 ** allocation occurred. The TITLE is stored with the allocation
842 ** and can be used to figure out which tests are leaking memory.
843 **
844 ** Each title overwrite the previous.
845 */
846 static int test_memdebug_settitle(
847 object clientdata,
848 Tcl_Interp interp,
849 int objc,
850 Tcl_Obj[] objv
851 )
852 {
853 string zTitle;
854 if ( objc != 2 )
855 {
856 TCL.Tcl_WrongNumArgs( interp, 1, objv, "TITLE" );
857 return TCL.TCL_ERROR;
858 }
859 zTitle = TCL.Tcl_GetString( objv[1] );
860 #if SQLITE_MEMDEBUG
861 {
862 extern int sqlite3MemdebugSettitle(const char);
863 sqlite3MemdebugSettitle(zTitle);
864 }
865 #endif
866 return TCL.TCL_OK;
867 }
868  
869 //#define MALLOC_LOG_FRAMES 10
870 //static TCL.Tcl_HashTable aMallocLog;
871 //static int mallocLogEnabled = 0;
872  
873 //typedef struct MallocLog MallocLog;
874 //struct MallocLog {
875 // int nCall;
876 // int nByte;
877 //};
878  
879 //#if SQLITE_MEMDEBUG
880 //static void test_memdebug_callback(int nByte, int nFrame, object **aFrame){
881 // if( mallocLogEnabled ){
882 // MallocLog pLog;
883 // TCL.Tcl_HashEntry pEntry;
884 // int isNew;
885  
886 // int aKey[MALLOC_LOG_FRAMES];
887 // int nKey = sizeof(int)*MALLOC_LOG_FRAMES;
888  
889 // memset(aKey, 0, nKey);
890 // if( (sizeof(void)*nFrame)<nKey ){
891 // nKey = nFrame*sizeof(void);
892 // }
893 // memcpy(aKey, aFrame, nKey);
894  
895 // pEntry = TCL.Tcl_CreateHashEntry(&aMallocLog, (string )aKey, ref isNew);
896 // if( isNew ){
897 // pLog = (MallocLog )Tcl_Alloc(sizeof(MallocLog));
898 // memset(pLog, 0, sizeof(MallocLog));
899 // TCL.Tcl_SetHashValue(pEntry, (ClientData)pLog);
900 // }else{
901 // pLog = (MallocLog )Tcl_GetHashValue(pEntry);
902 // }
903  
904 // pLog->nCall++;
905 // pLog->nByte += nByte;
906 // }
907 //}
908 //#endif //* SQLITE_MEMDEBUG */
909  
910 //static void test_memdebug_log_clear(){
911 // TCL.Tcl_HashSearch search;
912 // TCL.Tcl_HashEntry pEntry;
913 // for(
914 // pEntry=Tcl_FirstHashEntry(&aMallocLog, ref search);
915 // pEntry;
916 // pEntry=Tcl_NextHashEntry(&search)
917 // ){
918 // MallocLog pLog = (MallocLog )Tcl_GetHashValue(pEntry);
919 // TCL.Tcl_Free((char )pLog);
920 // }
921 // TCL.Tcl_DeleteHashTable(&aMallocLog);
922 // TCL.Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES);
923 //}
924  
925 //static int test_memdebug_log(
926 // object clientData,
927 // Tcl_Interp interp,
928 // int objc,
929 // Tcl_Obj[] objv
930 //){
931 // static int isInit = 0;
932 // int iSub;
933  
934 // static string MB_strs[] = { "start", "stop", "dump", "clear", "sync" };
935 // enum MB_enum {
936 // MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC
937 // };
938  
939 // if( null==isInit ){
940 //#if SQLITE_MEMDEBUG
941 // extern void sqlite3MemdebugBacktraceCallback(
942 // void (*xBacktrace)(int, int, object *));
943 // sqlite3MemdebugBacktraceCallback(test_memdebug_callback);
944 //#endif
945 // TCL.Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES);
946 // isInit = 1;
947 // }
948  
949 // if( objc<2 ){
950 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
951 // }
952 // if( TCL.Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, out iSub) ){
953 // return TCL.TCL_ERROR;
954 // }
955  
956 // switch( (enum MB_enum)iSub ){
957 // case MB_LOG_START:
958 // mallocLogEnabled = 1;
959 // break;
960 // case MB_LOG_STOP:
961 // mallocLogEnabled = 0;
962 // break;
963 // case MB_LOG_DUMP: {
964 // TCL.Tcl_HashSearch search;
965 // TCL.Tcl_HashEntry pEntry;
966 // Tcl_Obj pRet = TCL.Tcl_NewObj();
967  
968 // Debug.Assert(sizeof(int)==sizeof(void));
969  
970 // for(
971 // pEntry=Tcl_FirstHashEntry(&aMallocLog, ref search);
972 // pEntry;
973 // pEntry=Tcl_NextHashEntry(&search)
974 // ){
975 // Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];
976 // MallocLog pLog = (MallocLog )Tcl_GetHashValue(pEntry);
977 // int *aKey = (int )Tcl_GetHashKey(&aMallocLog, pEntry);
978 // int ii;
979  
980 // apElem[0] = TCL.Tcl_NewIntObj(pLog->nCall);
981 // apElem[1] = TCL.Tcl_NewIntObj(pLog->nByte);
982 // for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){
983 // apElem[ii+2] = TCL.Tcl_NewIntObj(aKey[ii]);
984 // }
985  
986 // TCL.Tcl_ListObjAppendElement(interp, pRet,
987 // TCL.Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem)
988 // );
989 // }
990  
991 // TCL.Tcl_SetObjResult(interp, pRet);
992 // break;
993 // }
994 // case MB_LOG_CLEAR: {
995 // test_memdebug_log_clear();
996 // break;
997 // }
998  
999 // case MB_LOG_SYNC: {
1000 //#if SQLITE_MEMDEBUG
1001 // extern void sqlite3MemdebugSync();
1002 // test_memdebug_log_clear();
1003 // mallocLogEnabled = 1;
1004 // sqlite3MemdebugSync();
1005 //#endif
1006 // break;
1007 // }
1008 // }
1009  
1010 // return TCL.TCL_OK;
1011 //}
1012  
1013 /*
1014 ** Usage: sqlite3_config_scratch SIZE N
1015 **
1016 ** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH.
1017 ** The buffer is static and is of limited size. N might be
1018 ** adjusted downward as needed to accomodate the requested size.
1019 ** The revised value of N is returned.
1020 **
1021 ** A negative SIZE causes the buffer pointer to be NULL.
1022 */
1023 static int test_config_scratch(
1024 object clientData,
1025 Tcl_Interp interp,
1026 int objc,
1027 Tcl_Obj[] objv
1028 )
1029 {
1030 int sz = 0, N = 0, rc;
1031 Tcl_Obj pResult;
1032 byte[][] buf = null;
1033 if ( objc != 3 )
1034 {
1035 TCL.Tcl_WrongNumArgs( interp, 1, objv, "SIZE N" );
1036 return TCL.TCL_ERROR;
1037 }
1038 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out sz ) )
1039 return TCL.TCL_ERROR;
1040 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out N ) )
1041 return TCL.TCL_ERROR;
1042 //free(buf);
1043 if ( sz < 0 )
1044 {
1045 buf = null;
1046 rc = sqlite3_config( SQLITE_CONFIG_SCRATCH, 0, 0, 0 );
1047 }
1048 else
1049 {
1050 buf = new byte[2][];//// malloc( sz * N + 1 );
1051 rc = sqlite3_config( SQLITE_CONFIG_SCRATCH, buf, sz, N );
1052 }
1053 pResult = TCL.Tcl_NewObj();
1054 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( rc ) );
1055 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( N ) );
1056 TCL.Tcl_SetObjResult( interp, pResult );
1057 return TCL.TCL_OK;
1058 }
1059  
1060  
1061 /*
1062 ** Usage: sqlite3_config_pagecache SIZE N
1063 **
1064 ** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
1065 ** The buffer is static and is of limited size. N might be
1066 ** adjusted downward as needed to accomodate the requested size.
1067 ** The revised value of N is returned.
1068 **
1069 ** A negative SIZE causes the buffer pointer to be NULL.
1070 */
1071 static int test_config_pagecache(
1072 object clientData,
1073 Tcl_Interp interp,
1074 int objc,
1075 Tcl_Obj[] objv
1076 )
1077 {
1078 int sz = 0, N = 0, rc;
1079 Tcl_Obj pResult;
1080 MemPage buf; // byte[] buf = null;
1081 if ( objc != 3 )
1082 {
1083 TCL.Tcl_WrongNumArgs( interp, 1, objv, "SIZE N" );
1084 return TCL.TCL_ERROR;
1085 }
1086 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out sz ) )
1087 return TCL.TCL_ERROR;
1088 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out N ) )
1089 return TCL.TCL_ERROR;
1090 //free(buf);
1091 if ( sz < 0 )
1092 {
1093 buf = null;
1094 rc = sqlite3_config( SQLITE_CONFIG_PAGECACHE, 0, 0, 0 );
1095 }
1096 else
1097 {
1098 buf = new MemPage();// new byte[sz * N]; //malloc( sz * N );
1099 rc = sqlite3_config( SQLITE_CONFIG_PAGECACHE, buf, sz, N );
1100 }
1101 pResult = TCL.Tcl_NewObj();
1102 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( rc ) );
1103 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( N ) );
1104 TCL.Tcl_SetObjResult( interp, pResult );
1105 return TCL.TCL_OK;
1106 }
1107  
1108 /*
1109 ** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED
1110 **
1111 ** Set up the alternative test page cache. Install if INSTALL_FLAG is
1112 ** true and uninstall (reverting to the default page cache) if INSTALL_FLAG
1113 ** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive
1114 ** which determines the chance of discarding a page when unpinned. 100
1115 ** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator
1116 ** seed.
1117 */
1118 //static int test_alt_pcache(
1119 // object clientData,
1120 // Tcl_Interp interp,
1121 // int objc,
1122 // Tcl_Obj[] objv
1123 //){
1124 // int installFlag;
1125 // int discardChance = 0;
1126 // int prngSeed = 0;
1127 // int highStress = 0;
1128 // extern void installTestPCache(int,unsigned,unsigned,unsigned);
1129 // if( objc<2 || objc>5 ){
1130 // TCL.Tcl_WrongNumArgs(interp, 1, objv,
1131 // "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS");
1132 // return TCL.TCL_ERROR;
1133 // }
1134 // if( TCL.Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL.TCL_ERROR;
1135 // if( objc>=3 && TCL.Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){
1136 // return TCL.TCL_ERROR;
1137 // }
1138 // if( objc>=4 && TCL.Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){
1139 // return TCL.TCL_ERROR;
1140 // }
1141 // if( objc>=5 && TCL.Tcl_GetIntFromObj(interp, objv[4], &highStress) ){
1142 // return TCL.TCL_ERROR;
1143 // }
1144 // if( discardChance<0 || discardChance>100 ){
1145 // TCL.Tcl_AppendResult(interp, "discard-chance should be between 0 and 100",
1146 // (char)0);
1147 // return TCL.TCL_ERROR;
1148 // }
1149 // installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed,
1150 // (unsigned)highStress);
1151 // return TCL.TCL_OK;
1152 //}
1153  
1154 /*
1155 ** Usage: sqlite3_config_memstatus BOOLEAN
1156 **
1157 ** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS.
1158 */
1159 static int test_config_memstatus(
1160 object clientData,
1161 Tcl_Interp interp,
1162 int objc,
1163 Tcl_Obj[] objv
1164 )
1165 {
1166 bool enable = false;
1167 int rc;
1168 if ( objc != 2 )
1169 {
1170 TCL.Tcl_WrongNumArgs( interp, 1, objv, "BOOLEAN" );
1171 return TCL.TCL_ERROR;
1172 }
1173 if ( TCL.Tcl_GetBooleanFromObj( interp, objv[1], out enable ) )
1174 return TCL.TCL_ERROR;
1175 rc = sqlite3_config( SQLITE_CONFIG_MEMSTATUS, enable );
1176 TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( rc ) );
1177 return TCL.TCL_OK;
1178 }
1179  
1180 /*
1181 ** Usage: sqlite3_config_lookaside SIZE COUNT
1182 **
1183 */
1184 static int test_config_lookaside(
1185 object clientData,
1186 Tcl_Interp interp,
1187 int objc,
1188 Tcl_Obj[] objv
1189 )
1190 {
1191 int rc;
1192 int sz = 0, cnt = 0;
1193 Tcl_Obj pRet;
1194 if ( objc != 3 )
1195 {
1196 TCL.Tcl_WrongNumArgs( interp, 1, objv, "SIZE COUNT" );
1197 return TCL.TCL_ERROR;
1198 }
1199 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out sz ) )
1200 return TCL.TCL_ERROR;
1201 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out cnt ) )
1202 return TCL.TCL_ERROR;
1203 pRet = TCL.Tcl_NewObj();
1204 TCL.Tcl_ListObjAppendElement(
1205 interp, pRet, TCL.Tcl_NewIntObj( sqlite3GlobalConfig.szLookaside )
1206 );
1207 TCL.Tcl_ListObjAppendElement(
1208 interp, pRet, TCL.Tcl_NewIntObj( sqlite3GlobalConfig.nLookaside )
1209 );
1210 rc = sqlite3_config( SQLITE_CONFIG_LOOKASIDE, sz, cnt );
1211 TCL.Tcl_SetObjResult( interp, pRet );
1212 return TCL.TCL_OK;
1213 }
1214  
1215 /*
1216 ** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT
1217 **
1218 ** There are two static buffers with BUFID 1 and 2. Each static buffer
1219 ** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL
1220 ** which will cause sqlite3_db_config() to allocate space on its own.
1221 */
1222 static int test_db_config_lookaside(
1223 object clientData,
1224 Tcl_Interp interp,
1225 int objc,
1226 Tcl_Obj[] objv
1227 )
1228 {
1229 int rc;
1230 int sz = 0, cnt = 0;
1231 sqlite3 db = new sqlite3();
1232 int bufid = 0;
1233 byte[][] azBuf = new byte[2][];
1234 //int getDbPointer(Tcl_Interp*, const char*, sqlite3*);
1235 if ( objc != 5 )
1236 {
1237 TCL.Tcl_WrongNumArgs( interp, 1, objv, "BUFID SIZE COUNT" );
1238 return TCL.TCL_ERROR;
1239 }
1240 if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 )
1241 return TCL.TCL_ERROR;
1242 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out bufid ) )
1243 return TCL.TCL_ERROR;
1244 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[3], out sz ) )
1245 return TCL.TCL_ERROR;
1246 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[4], out cnt ) )
1247 return TCL.TCL_ERROR;
1248 if ( bufid == 0 )
1249 {
1250 rc = sqlite3_db_config( db, SQLITE_DBCONFIG_LOOKASIDE, null, sz, cnt );
1251 }
1252 else if ( bufid >= 1 && bufid <= 2 && sz * cnt <= azBuf[0].Length )
1253 {
1254 rc = sqlite3_db_config( db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz, cnt );
1255 }
1256 else
1257 {
1258 TCL.Tcl_AppendResult( interp, "illegal arguments - see documentation" );
1259 return TCL.TCL_ERROR;
1260 }
1261 TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( rc ) );
1262 return TCL.TCL_OK;
1263 }
1264  
1265 /*
1266 ** Usage:
1267 **
1268 ** sqlite3_config_heap NBYTE NMINALLOC
1269 */
1270 //static int test_config_heap(
1271 // object clientData,
1272 // Tcl_Interp interp,
1273 // int objc,
1274 // Tcl_Obj[] objv
1275 //){
1276 // static string zBuf; /* Use this memory */
1277 // static int szBuf; /* Bytes allocated for zBuf */
1278 // int nByte; /* Size of buffer to pass to sqlite3_config() */
1279 // int nMinAlloc; /* Size of minimum allocation */
1280 // int rc; /* Return code of sqlite3_config() */
1281  
1282 // Tcl_Obj * CONST *aArg = objv[1];
1283 // int nArg = objc-1;
1284  
1285 // if( nArg!=2 ){
1286 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC");
1287 // return TCL.TCL_ERROR;
1288 // }
1289 // if( TCL.Tcl_GetIntFromObj(interp, aArg[0], out nByte) ) return TCL.TCL_ERROR;
1290 // if( TCL.Tcl_GetIntFromObj(interp, aArg[1], out nMinAlloc) ) return TCL.TCL_ERROR;
1291  
1292 // if( nByte==0 ){
1293 // free( zBuf );
1294 // zBuf = 0;
1295 // szBuf = 0;
1296 // rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void)0, 0, 0);
1297 // }else{
1298 // zBuf = realloc(zBuf, nByte);
1299 // szBuf = nByte;
1300 // rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc);
1301 // }
1302  
1303 // TCL.Tcl_SetResult(interp, (char )sqlite3TestErrorName(rc), TCL.Tcl_VOLATILE);
1304 // return TCL.TCL_OK;
1305 //}
1306  
1307 /*
1308 ** tclcmd: sqlite3_config_error [DB]
1309 **
1310 ** Invoke sqlite3_config() or sqlite3_db_config() with invalid
1311 ** opcodes and verify that they return errors.
1312 */
1313 //static int test_config_error(
1314 // object clientData,
1315 // Tcl_Interp interp,
1316 // int objc,
1317 // Tcl_Obj[] objv
1318 //){
1319 // sqlite3 db;
1320 // int getDbPointer(Tcl_Interp*, const char*, sqlite3*);
1321  
1322 // if( objc!=2 && objc!=1 ){
1323 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "[DB]");
1324 // return TCL.TCL_ERROR;
1325 // }
1326 // if( objc==2 ){
1327 // if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) ) return TCL.TCL_ERROR;
1328 // if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){
1329 // TCL.Tcl_AppendResult(interp,
1330 // "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR",
1331 // (char)0);
1332 // return TCL.TCL_ERROR;
1333 // }
1334 // }else{
1335 // if( sqlite3_config(99999)!=SQLITE_ERROR ){
1336 // TCL.Tcl_AppendResult(interp,
1337 // "sqlite3_config(99999) does not return SQLITE_ERROR",
1338 // (char)0);
1339 // return TCL.TCL_ERROR;
1340 // }
1341 // }
1342 // return TCL.TCL_OK;
1343 //}
1344  
1345 /*
1346 ** Usage:
1347 **
1348 ** sqlite3_dump_memsys3 FILENAME
1349 ** sqlite3_dump_memsys5 FILENAME
1350 **
1351 ** Write a summary of unfreed memsys3 allocations to FILENAME.
1352 */
1353 //static int test_dump_memsys3(
1354 // object clientData,
1355 // Tcl_Interp interp,
1356 // int objc,
1357 // Tcl_Obj[] objv
1358 //){
1359 // if( objc!=2 ){
1360 // TCL.Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
1361 // return TCL.TCL_ERROR;
1362 // }
1363  
1364 // switch( (int)clientData ){
1365 // case 3: {
1366 //#if SQLITE_ENABLE_MEMSYS3
1367 // extern void sqlite3Memsys3Dump(const char);
1368 // sqlite3Memsys3Dump(Tcl_GetString(objv[1]));
1369 // break;
1370 //#endif
1371 // }
1372 // case 5: {
1373 //#if SQLITE_ENABLE_MEMSYS5
1374 // extern void sqlite3Memsys5Dump(const char);
1375 // sqlite3Memsys5Dump(Tcl_GetString(objv[1]));
1376 // break;
1377 //#endif
1378 // }
1379 // }
1380 // return TCL.TCL_OK;
1381 //}
1382  
1383 /*
1384 ** Usage: sqlite3_status OPCODE RESETFLAG
1385 **
1386 ** Return a list of three elements which are the sqlite3_status() return
1387 ** code, the current value, and the high-water mark value.
1388 */
1389 class _aOp
1390 {
1391 public string zName;
1392 public int op;
1393 public _aOp( string zName, int op )
1394 {
1395 this.zName = zName;
1396 this.op = op;
1397 }
1398 }
1399  
1400 static int test_status(
1401 object clientdata,
1402 Tcl_Interp interp,
1403 int objc,
1404 Tcl_Obj[] objv
1405 )
1406 {
1407 int rc, iValue, mxValue;
1408 int i, op = 0;
1409 bool resetFlag = false;
1410 string zOpName;
1411  
1412 _aOp[] aOp = new _aOp[] {
1413 new _aOp( "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED ),
1414 new _aOp( "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE ),
1415 new _aOp( "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED ),
1416 new _aOp( "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW ),
1417 new _aOp( "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE ),
1418 new _aOp( "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED ),
1419 new _aOp( "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW ),
1420 new _aOp( "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE ),
1421 new _aOp( "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK ),
1422 new _aOp("SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT ),
1423 };
1424 Tcl_Obj pResult;
1425 if ( objc != 3 )
1426 {
1427 TCL.Tcl_WrongNumArgs( interp, 1, objv, "PARAMETER RESETFLAG" );
1428 return TCL.TCL_ERROR;
1429 }
1430 zOpName = TCL.Tcl_GetString( objv[1] );
1431 for ( i = 0; i < ArraySize( aOp ); i++ )
1432 {
1433 if ( aOp[i].zName == zOpName )
1434 {//strcmp(aOp[i].zName, zOpName)==0 ){
1435 op = aOp[i].op;
1436 break;
1437 }
1438 }
1439 if ( i >= ArraySize( aOp ) )
1440 {
1441 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out op ) )
1442 return TCL.TCL_ERROR;
1443 }
1444 if ( TCL.Tcl_GetBooleanFromObj( interp, objv[2], out resetFlag ) )
1445 return TCL.TCL_ERROR;
1446 iValue = 0;
1447 mxValue = 0;
1448 rc = sqlite3_status( op, ref iValue, ref mxValue, resetFlag ? 1 : 0 );
1449 pResult = TCL.Tcl_NewObj();
1450 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( rc ) );
1451 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( iValue ) );
1452 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( mxValue ) );
1453 TCL.Tcl_SetObjResult( interp, pResult );
1454 return TCL.TCL_OK;
1455 }
1456 /*
1457 ** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG
1458 **
1459 ** Return a list of three elements which are the sqlite3_db_status() return
1460 ** code, the current value, and the high-water mark value.
1461 */
1462 static int test_db_status(
1463 object clientData,
1464 Tcl_Interp interp,
1465 int objc,
1466 Tcl_Obj[] objv
1467 )
1468 {
1469 int rc, iValue, mxValue;
1470 int i, op = 0;
1471 bool resetFlag = false;
1472 string zOpName;
1473 sqlite3 db = null;
1474 //int getDbPointer (Tcl_Interp*, const char*, sqlite3*);
1475 //static const struct {
1476 //string zName;
1477 //int op;
1478 //}
1479 _aOp[] aOp = {
1480 new _aOp( "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED ),
1481 new _aOp( "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED ),
1482 new _aOp( "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED ),
1483 new _aOp( "STMT_USED", SQLITE_DBSTATUS_STMT_USED ),
1484 new _aOp( "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT ),
1485 new _aOp( "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE ),
1486 new _aOp( "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL )
1487 };
1488 Tcl_Obj pResult;
1489 if ( objc != 4 )
1490 {
1491 TCL.Tcl_WrongNumArgs( interp, 1, objv, "PARAMETER RESETFLAG" );
1492 return TCL.TCL_ERROR;
1493 }
1494 if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 )
1495 return TCL.TCL_ERROR;
1496 zOpName = TCL.Tcl_GetString( objv[2] );
1497 if ( zOpName.StartsWith( "SQLITE_" ) )
1498 zOpName = zOpName.Remove( 0, 7 ); //zOpName += 7;
1499 if ( zOpName.StartsWith( "DBSTATUS_" ) )
1500 zOpName = zOpName.Remove( 0, 9 ); //zOpName += 9;
1501 for ( i = 0; i < ArraySize( aOp ); i++ )
1502 {
1503 if ( aOp[i].zName == zOpName )
1504 {
1505 op = aOp[i].op;
1506 break;
1507 }
1508 }
1509 if ( i >= ArraySize( aOp ) )
1510 {
1511 if ( TCL.Tcl_GetIntFromObj( interp, objv[2], out op ) != 0 )
1512 return TCL.TCL_ERROR;
1513 }
1514 if ( TCL.Tcl_GetBooleanFromObj( interp, objv[3], out resetFlag ) )
1515 return TCL.TCL_ERROR;
1516 iValue = 0;
1517 mxValue = 0;
1518 rc = sqlite3_db_status( db, op, ref iValue, ref mxValue, resetFlag ? 1 : 0 );
1519 pResult = TCL.Tcl_NewObj();
1520 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( rc ) );
1521 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( iValue ) );
1522 TCL.Tcl_ListObjAppendElement( null, pResult, TCL.Tcl_NewIntObj( mxValue ) );
1523 TCL.Tcl_SetObjResult( interp, pResult );
1524 return TCL.TCL_OK;
1525 }
1526  
1527 /*
1528 ** install_malloc_faultsim BOOLEAN
1529 */
1530 static int test_install_malloc_faultsim(
1531 object clientData,
1532 Tcl_Interp interp,
1533 int objc,
1534 Tcl_Obj[] objv
1535 )
1536 {
1537 int rc;
1538 int isInstall;
1539 bool bisInstall = false;
1540  
1541 if ( objc != 2 )
1542 {
1543 TCL.Tcl_WrongNumArgs( interp, 1, objv, "BOOLEAN" );
1544 return TCL.TCL_ERROR;
1545 }
1546 if ( TCL.Tcl_GetBooleanFromObj( interp, objv[1], out bisInstall ) )
1547 {
1548 return TCL.TCL_ERROR;
1549 }
1550 isInstall = bisInstall ? 1 : 0;
1551 rc = faultsimInstall( isInstall );
1552 TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_VOLATILE );
1553 return TCL.TCL_OK;
1554 }
1555  
1556 static int test_vfs_oom_test(
1557 object clientData,
1558 Tcl_Interp interp,
1559 int objc,
1560 Tcl_Obj[] objv
1561 )
1562 {
1563 //extern int sqlite3_memdebug_vfs_oom_test;
1564 if ( objc > 2 )
1565 {
1566 TCL.Tcl_WrongNumArgs( interp, 1, objv, "?INTEGER?" );
1567 return TCL.TCL_ERROR;
1568 }
1569 else if ( objc == 2 )
1570 {
1571 int iNew = 0;
1572 if ( TCL.Tcl_GetIntFromObj( interp, objv[1], out iNew ) != 0 )
1573 return TCL.TCL_ERROR;
1574 sqlite3_memdebug_vfs_oom_test = iNew;
1575 }
1576 TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_memdebug_vfs_oom_test ) );
1577 return TCL.TCL_OK;
1578 }
1579  
1580 /*
1581 ** Register commands with the TCL interpreter.
1582 */
1583 static public int Sqlitetest_malloc_Init( Tcl_Interp interp )
1584 {
1585 //static struct {
1586 // string zName;
1587 // Tcl_ObjCmdProc *xProc;
1588 // int clientData;
1589 //} aObjCmd[] = {
1590 _aObjCmd[] aObjCmd = new _aObjCmd[] {
1591 //{ "sqlite3_malloc", test_malloc ,0 },
1592 //{ "sqlite3_realloc", test_realloc ,0 },
1593 //{ "sqlite3_free", test_free ,0 },
1594 //{ "memset", test_memset ,0 },
1595 //{ "memget", test_memget ,0 },
1596 //{ "sqlite3_memory_used", test_memory_used ,0 },
1597 #if FALSE
1598 new _aObjCmd( "sqlite3_memory_used", test_memory_used ,0 ),
1599 new _aObjCmd( "sqlite3_memory_highwater", test_memory_highwater ,0),
1600 #endif
1601 //{ "sqlite3_memory_highwater", test_memory_highwater ,0 },
1602 //{ "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 },
1603 new _aObjCmd( "sqlite3_memdebug_dump", test_memdebug_dump ,0 ),
1604 new _aObjCmd( "sqlite3_memdebug_fail", test_memdebug_fail ,0 ),
1605 //{ "sqlite3_memdebug_pending", test_memdebug_pending ,0 },
1606 new _aObjCmd( "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 ),
1607 new _aObjCmd( "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0),
1608 //{ "sqlite3_memdebug_log", test_memdebug_log ,0 },
1609 new _aObjCmd( "sqlite3_config_scratch", test_config_scratch ,0 ),
1610 new _aObjCmd("sqlite3_config_pagecache", test_config_pagecache ,0 ),
1611 //{ "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
1612 new _aObjCmd( "sqlite3_status", test_status,0 ),
1613 new _aObjCmd( "sqlite3_db_status", test_db_status, 0 ),
1614 new _aObjCmd( "install_malloc_faultsim", test_install_malloc_faultsim ,0),
1615 //{ "sqlite3_config_heap", test_config_heap ,0 },
1616 new _aObjCmd( "sqlite3_config_memstatus", test_config_memstatus ,0 ),
1617 new _aObjCmd( "sqlite3_config_lookaside", test_config_lookaside ,0 ),
1618 //{ "sqlite3_config_error", test_config_error ,0 },
1619 new _aObjCmd( "sqlite3_config_uri",test_config_uri ,0 ),
1620 new _aObjCmd( "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 ),
1621 //{ "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
1622 //{ "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
1623 //{ "sqlite3_install_memsys3", test_install_memsys3 ,0 },
1624 //{ "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 },
1625 };
1626 int i;
1627 for ( i = 0; i < aObjCmd.Length; i++ )
1628 {//<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
1629 object c = (object)aObjCmd[i].clientData;
1630 TCL.Tcl_CreateObjCommand( interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, null );
1631 }
1632 return TCL.TCL_OK;
1633 }
1634 #endif
1635 }
1636 #endif
1637 }