Annotation of embedaddon/sqlite3/src/test_malloc.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>