modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/lsm1/lsm-test/lsmtest6.c (about)

     1  
     2  #include "lsmtest.h"
     3  
     4  typedef struct OomTest OomTest;
     5  struct OomTest {
     6    lsm_env *pEnv;
     7    int iNext;                      /* Next value to pass to testMallocOom() */
     8    int nFail;                      /* Number of OOM events injected */
     9    int bEnable;
    10    int rc;                         /* Test case error code */
    11  };
    12  
    13  static void testOomStart(OomTest *p){
    14    memset(p, 0, sizeof(OomTest));
    15    p->iNext = 1;
    16    p->bEnable = 1;
    17    p->nFail = 1;
    18    p->pEnv = tdb_lsm_env();
    19  }
    20  
    21  static void xOomHook(OomTest *p){
    22    p->nFail++;
    23  }
    24  
    25  static int testOomContinue(OomTest *p){
    26    if( p->rc!=0 || (p->iNext>1 && p->nFail==0) ){
    27      return 0;
    28    }
    29    p->nFail = 0;
    30    testMallocOom(p->pEnv, p->iNext, 0, (void (*)(void*))xOomHook, (void *)p);
    31    return 1;
    32  }
    33  
    34  static void testOomEnable(OomTest *p, int bEnable){
    35    p->bEnable = bEnable;
    36    testMallocOomEnable(p->pEnv, bEnable);
    37  }
    38  
    39  static void testOomNext(OomTest *p){
    40    p->iNext++;
    41  }
    42  
    43  static int testOomHit(OomTest *p){
    44    return (p->nFail>0);
    45  }
    46  
    47  static int testOomFinish(OomTest *p){
    48    return p->rc;
    49  }
    50  
    51  static void testOomAssert(OomTest *p, int bVal){
    52    if( bVal==0 ){
    53      test_failed();
    54      p->rc = 1;
    55    }
    56  }
    57  
    58  /*
    59  ** Test that the error code matches the state of the OomTest object passed
    60  ** as the first argument. Specifically, check that rc is LSM_NOMEM if an 
    61  ** OOM error has already been injected, or LSM_OK if not.
    62  */
    63  static void testOomAssertRc(OomTest *p, int rc){
    64    testOomAssert(p, rc==LSM_OK || rc==LSM_NOMEM);
    65    testOomAssert(p, testOomHit(p)==(rc==LSM_NOMEM) || p->bEnable==0 );
    66  }
    67  
    68  static void testOomOpen(
    69    OomTest *pOom,
    70    const char *zName,
    71    lsm_db **ppDb,
    72    int *pRc
    73  ){
    74    if( *pRc==LSM_OK ){
    75      int rc;
    76      rc = lsm_new(tdb_lsm_env(), ppDb);
    77      if( rc==LSM_OK ) rc = lsm_open(*ppDb, zName);
    78      testOomAssertRc(pOom, rc);
    79      *pRc = rc;
    80    }
    81  }
    82  
    83  static void testOomFetch(
    84    OomTest *pOom,
    85    lsm_db *pDb,
    86    void *pKey, int nKey,
    87    void *pVal, int nVal,
    88    int *pRc
    89  ){
    90    testOomAssertRc(pOom, *pRc);
    91    if( *pRc==LSM_OK ){
    92      lsm_cursor *pCsr;
    93      int rc;
    94  
    95      rc = lsm_csr_open(pDb, &pCsr);
    96      if( rc==LSM_OK ) rc = lsm_csr_seek(pCsr, pKey, nKey, 0);
    97      testOomAssertRc(pOom, rc);
    98  
    99      if( rc==LSM_OK ){
   100        const void *p; int n;
   101        testOomAssert(pOom, lsm_csr_valid(pCsr));
   102  
   103        rc = lsm_csr_key(pCsr, &p, &n);
   104        testOomAssertRc(pOom, rc);
   105        testOomAssert(pOom, rc!=LSM_OK || (n==nKey && memcmp(pKey, p, nKey)==0) );
   106      }
   107  
   108      if( rc==LSM_OK ){
   109        const void *p; int n;
   110        testOomAssert(pOom, lsm_csr_valid(pCsr));
   111  
   112        rc = lsm_csr_value(pCsr, &p, &n);
   113        testOomAssertRc(pOom, rc);
   114        testOomAssert(pOom, rc!=LSM_OK || (n==nVal && memcmp(pVal, p, nVal)==0) );
   115      }
   116  
   117      lsm_csr_close(pCsr);
   118      *pRc = rc;
   119    }
   120  }
   121  
   122  static void testOomWrite(
   123    OomTest *pOom,
   124    lsm_db *pDb,
   125    void *pKey, int nKey,
   126    void *pVal, int nVal,
   127    int *pRc
   128  ){
   129    testOomAssertRc(pOom, *pRc);
   130    if( *pRc==LSM_OK ){
   131      int rc;
   132  
   133      rc = lsm_insert(pDb, pKey, nKey, pVal, nVal);
   134      testOomAssertRc(pOom, rc);
   135  
   136      *pRc = rc;
   137    }
   138  }
   139  
   140  
   141  static void testOomFetchStr(
   142    OomTest *pOom,
   143    lsm_db *pDb,
   144    const char *zKey,
   145    const char *zVal,
   146    int *pRc
   147  ){
   148    int nKey = strlen(zKey);
   149    int nVal = strlen(zVal);
   150    testOomFetch(pOom, pDb, (void *)zKey, nKey, (void *)zVal, nVal, pRc);
   151  }
   152  
   153  static void testOomFetchData(
   154    OomTest *pOom,
   155    lsm_db *pDb,
   156    Datasource *pData,
   157    int iKey,
   158    int *pRc
   159  ){
   160    void *pKey; int nKey;
   161    void *pVal; int nVal;
   162    testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
   163    testOomFetch(pOom, pDb, pKey, nKey, pVal, nVal, pRc);
   164  }
   165  
   166  static void testOomWriteStr(
   167    OomTest *pOom,
   168    lsm_db *pDb,
   169    const char *zKey,
   170    const char *zVal,
   171    int *pRc
   172  ){
   173    int nKey = strlen(zKey);
   174    int nVal = strlen(zVal);
   175    testOomWrite(pOom, pDb, (void *)zKey, nKey, (void *)zVal, nVal, pRc);
   176  }
   177  
   178  static void testOomWriteData(
   179    OomTest *pOom,
   180    lsm_db *pDb,
   181    Datasource *pData,
   182    int iKey,
   183    int *pRc
   184  ){
   185    void *pKey; int nKey;
   186    void *pVal; int nVal;
   187    testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
   188    testOomWrite(pOom, pDb, pKey, nKey, pVal, nVal, pRc);
   189  }
   190  
   191  static void testOomScan(
   192    OomTest *pOom, 
   193    lsm_db *pDb, 
   194    int bReverse,
   195    const void *pKey, int nKey,
   196    int nScan,
   197    int *pRc
   198  ){
   199    if( *pRc==0 ){
   200      int rc;
   201      int iScan = 0;
   202      lsm_cursor *pCsr;
   203      int (*xAdvance)(lsm_cursor *) = 0;
   204      
   205  
   206      rc = lsm_csr_open(pDb, &pCsr);
   207      testOomAssertRc(pOom, rc);
   208  
   209      if( rc==LSM_OK ){
   210        if( bReverse ){
   211          rc = lsm_csr_seek(pCsr, pKey, nKey, LSM_SEEK_LE);
   212          xAdvance = lsm_csr_prev;
   213        }else{
   214          rc = lsm_csr_seek(pCsr, pKey, nKey, LSM_SEEK_GE);
   215          xAdvance = lsm_csr_next;
   216        }
   217      }
   218      testOomAssertRc(pOom, rc);
   219  
   220      while( rc==LSM_OK && lsm_csr_valid(pCsr) && iScan<nScan ){
   221        const void *p; int n;
   222  
   223        rc = lsm_csr_key(pCsr, &p, &n);
   224        testOomAssertRc(pOom, rc);
   225        if( rc==LSM_OK ){
   226          rc = lsm_csr_value(pCsr, &p, &n);
   227          testOomAssertRc(pOom, rc);
   228        }
   229        if( rc==LSM_OK ){
   230          rc = xAdvance(pCsr);
   231          testOomAssertRc(pOom, rc);
   232        }
   233        iScan++;
   234      }
   235  
   236      lsm_csr_close(pCsr);
   237      *pRc = rc;
   238    }
   239  }
   240  
   241  #define LSMTEST6_TESTDB "testdb.lsm" 
   242  
   243  void testDeleteLsmdb(const char *zFile){
   244    char *zLog = testMallocPrintf("%s-log", zFile);
   245    char *zShm = testMallocPrintf("%s-shm", zFile);
   246    unlink(zFile);
   247    unlink(zLog);
   248    unlink(zShm);
   249    testFree(zLog);
   250    testFree(zShm);
   251  }
   252  
   253  static void copy_file(const char *zFrom, const char *zTo, int isDatabase){
   254  
   255    if( access(zFrom, F_OK) ){
   256      unlink(zTo);
   257    }else{
   258      int fd1;
   259      int fd2;
   260      off_t sz;
   261      off_t i;
   262      struct stat buf;
   263      u8 *aBuf;
   264  
   265      fd1 = open(zFrom, O_RDONLY | _O_BINARY, 0644);
   266      fd2 = open(zTo, O_RDWR | O_CREAT | _O_BINARY, 0644);
   267  
   268      fstat(fd1, &buf);
   269      sz = buf.st_size;
   270      ftruncate(fd2, sz);
   271  
   272      aBuf = testMalloc(4096);
   273      for(i=0; i<sz; i+=4096){
   274        int bLockPage = isDatabase && i == 0;
   275        int nByte = MIN((bLockPage ? 4066 : 4096), sz - i);
   276        memset(aBuf, 0, 4096);
   277        read(fd1, aBuf, nByte);
   278        write(fd2, aBuf, nByte);
   279        if( bLockPage ){
   280          lseek(fd1, 4096, SEEK_SET);
   281          lseek(fd2, 4096, SEEK_SET);
   282        }
   283      }
   284      testFree(aBuf);
   285  
   286      close(fd1);
   287      close(fd2);
   288    }
   289  }
   290  
   291  void testCopyLsmdb(const char *zFrom, const char *zTo){
   292    char *zLog1 = testMallocPrintf("%s-log", zFrom);
   293    char *zLog2 = testMallocPrintf("%s-log", zTo);
   294    char *zShm1 = testMallocPrintf("%s-shm", zFrom);
   295    char *zShm2 = testMallocPrintf("%s-shm", zTo);
   296  
   297    unlink(zShm2);
   298    unlink(zLog2);
   299    unlink(zTo);
   300    copy_file(zFrom, zTo, 1);
   301    copy_file(zLog1, zLog2, 0);
   302    copy_file(zShm1, zShm2, 0);
   303  
   304    testFree(zLog1); testFree(zLog2); testFree(zShm1); testFree(zShm2);
   305  }
   306  
   307  /*
   308  ** File zFile is the path to a database. This function makes backups
   309  ** of the database file and its log as follows:
   310  **
   311  **     cp $(zFile)         $(zFile)-save
   312  **     cp $(zFile)-$(zAux) $(zFile)-save-$(zAux)
   313  **
   314  ** Function testRestoreDb() can be used to copy the files back in the
   315  ** other direction.
   316  */
   317  void testSaveDb(const char *zFile, const char *zAux){
   318    char *zLog = testMallocPrintf("%s-%s", zFile, zAux);
   319    char *zFileSave = testMallocPrintf("%s-save", zFile);
   320    char *zLogSave = testMallocPrintf("%s-%s-save", zFile, zAux);
   321  
   322    unlink(zFileSave);
   323    unlink(zLogSave);
   324    copy_file(zFile, zFileSave, 1);
   325    copy_file(zLog, zLogSave, 0);
   326  
   327    testFree(zLog); testFree(zFileSave); testFree(zLogSave);
   328  }
   329  
   330  /*
   331  ** File zFile is the path to a database. This function restores
   332  ** a backup of the database made by a previous call to testSaveDb().
   333  ** Specifically, it does the equivalent of:
   334  **
   335  **     cp $(zFile)-save         $(zFile)
   336  **     cp $(zFile)-save-$(zAux) $(zFile)-$(zAux)
   337  */
   338  void testRestoreDb(const char *zFile, const char *zAux){
   339    char *zLog = testMallocPrintf("%s-%s", zFile, zAux);
   340    char *zFileSave = testMallocPrintf("%s-save", zFile);
   341    char *zLogSave = testMallocPrintf("%s-%s-save", zFile, zAux);
   342  
   343    copy_file(zFileSave, zFile, 1);
   344    copy_file(zLogSave, zLog, 0);
   345  
   346    testFree(zLog); testFree(zFileSave); testFree(zLogSave);
   347  }
   348  
   349  
   350  static int lsmWriteStr(lsm_db *pDb, const char *zKey, const char *zVal){
   351    int nKey = strlen(zKey);
   352    int nVal = strlen(zVal);
   353    return lsm_insert(pDb, (void *)zKey, nKey, (void *)zVal, nVal);
   354  }
   355  
   356  static void setup_delete_db(void){
   357    testDeleteLsmdb(LSMTEST6_TESTDB);
   358  }
   359  
   360  /*
   361  ** Create a small database. With the following content:
   362  **
   363  **    "one"   -> "one"
   364  **    "two"   -> "four"
   365  **    "three" -> "nine"
   366  **    "four"  -> "sixteen"
   367  **    "five"  -> "twentyfive"
   368  **    "six"   -> "thirtysix"
   369  **    "seven" -> "fourtynine"
   370  **    "eight" -> "sixtyfour"
   371  */
   372  static void setup_populate_db(void){
   373    const char *azStr[] = {
   374      "one",   "one",
   375      "two",   "four",
   376      "three", "nine",
   377      "four",  "sixteen",
   378      "five",  "twentyfive",
   379      "six",   "thirtysix",
   380      "seven", "fourtynine",
   381      "eight", "sixtyfour",
   382    };
   383    int rc;
   384    int ii;
   385    lsm_db *pDb;
   386  
   387    testDeleteLsmdb(LSMTEST6_TESTDB);
   388  
   389    rc = lsm_new(tdb_lsm_env(), &pDb);
   390    if( rc==LSM_OK ) rc = lsm_open(pDb, LSMTEST6_TESTDB);
   391  
   392    for(ii=0; rc==LSM_OK && ii<ArraySize(azStr); ii+=2){
   393      rc = lsmWriteStr(pDb, azStr[ii], azStr[ii+1]);
   394    }
   395    lsm_close(pDb);
   396  
   397    testSaveDb(LSMTEST6_TESTDB, "log");
   398    assert( rc==LSM_OK );
   399  }
   400  
   401  static Datasource *getDatasource(void){
   402    const DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 10, 15, 200, 250 };
   403    return testDatasourceNew(&defn);
   404  }
   405  
   406  /*
   407  ** Set up a database file with the following properties:
   408  **
   409  **   * Page size is 1024 bytes.
   410  **   * Block size is 64 KB.
   411  **   * Contains 5000 key-value pairs starting at 0 from the
   412  **     datasource returned getDatasource().
   413  */
   414  static void setup_populate_db2(void){
   415    Datasource *pData;
   416    int ii;
   417    int rc;
   418    int nBlocksize = 64*1024;
   419    int nPagesize = 1024;
   420    int nWritebuffer = 4*1024;
   421    lsm_db *pDb;
   422  
   423    testDeleteLsmdb(LSMTEST6_TESTDB);
   424    rc = lsm_new(tdb_lsm_env(), &pDb);
   425    if( rc==LSM_OK ) rc = lsm_open(pDb, LSMTEST6_TESTDB);
   426  
   427    lsm_config(pDb, LSM_CONFIG_BLOCK_SIZE, &nBlocksize); 
   428    lsm_config(pDb, LSM_CONFIG_PAGE_SIZE, &nPagesize); 
   429    lsm_config(pDb, LSM_CONFIG_AUTOFLUSH, &nWritebuffer); 
   430  
   431    pData = getDatasource();
   432    for(ii=0; rc==LSM_OK && ii<5000; ii++){
   433      void *pKey; int nKey;
   434      void *pVal; int nVal;
   435      testDatasourceEntry(pData, ii, &pKey, &nKey, &pVal, &nVal);
   436      lsm_insert(pDb, pKey, nKey, pVal, nVal);
   437    }
   438    testDatasourceFree(pData);
   439    lsm_close(pDb);
   440  
   441    testSaveDb(LSMTEST6_TESTDB, "log");
   442    assert( rc==LSM_OK );
   443  }
   444  
   445  /*
   446  ** Test the results of OOM conditions in lsm_new().
   447  */
   448  static void simple_oom_1(OomTest *pOom){
   449    int rc;
   450    lsm_db *pDb;
   451  
   452    rc = lsm_new(tdb_lsm_env(), &pDb);
   453    testOomAssertRc(pOom, rc);
   454  
   455    lsm_close(pDb);
   456  }
   457  
   458  /*
   459  ** Test the results of OOM conditions in lsm_open().
   460  */
   461  static void simple_oom_2(OomTest *pOom){
   462    int rc;
   463    lsm_db *pDb;
   464  
   465    rc = lsm_new(tdb_lsm_env(), &pDb);
   466    if( rc==LSM_OK ){
   467      rc = lsm_open(pDb, "testdb.lsm");
   468    }
   469    testOomAssertRc(pOom, rc);
   470  
   471    lsm_close(pDb);
   472  }
   473  
   474  /*
   475  ** Test the results of OOM conditions in simple fetch operations.
   476  */
   477  static void simple_oom_3(OomTest *pOom){
   478    int rc = LSM_OK;
   479    lsm_db *pDb;
   480  
   481    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
   482  
   483    testOomFetchStr(pOom, pDb, "four",  "sixteen",    &rc);
   484    testOomFetchStr(pOom, pDb, "seven", "fourtynine", &rc);
   485    testOomFetchStr(pOom, pDb, "one",   "one",        &rc);
   486    testOomFetchStr(pOom, pDb, "eight", "sixtyfour",  &rc);
   487  
   488    lsm_close(pDb);
   489  }
   490  
   491  /*
   492  ** Test the results of OOM conditions in simple write operations.
   493  */
   494  static void simple_oom_4(OomTest *pOom){
   495    int rc = LSM_OK;
   496    lsm_db *pDb;
   497  
   498    testDeleteLsmdb(LSMTEST6_TESTDB);
   499    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
   500  
   501    testOomWriteStr(pOom, pDb, "123", "onetwothree", &rc);
   502    testOomWriteStr(pOom, pDb, "456", "fourfivesix", &rc);
   503    testOomWriteStr(pOom, pDb, "789", "seveneightnine", &rc);
   504    testOomWriteStr(pOom, pDb, "123", "teneleventwelve", &rc);
   505    testOomWriteStr(pOom, pDb, "456", "fourteenfifteensixteen", &rc);
   506  
   507    lsm_close(pDb);
   508  }
   509  
   510  static void simple_oom_5(OomTest *pOom){
   511    Datasource *pData = getDatasource();
   512    int rc = LSM_OK;
   513    lsm_db *pDb;
   514  
   515    testRestoreDb(LSMTEST6_TESTDB, "log");
   516    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
   517  
   518    testOomFetchData(pOom, pDb, pData, 3333, &rc);
   519    testOomFetchData(pOom, pDb, pData, 0, &rc);
   520    testOomFetchData(pOom, pDb, pData, 4999, &rc);
   521  
   522    lsm_close(pDb);
   523    testDatasourceFree(pData);
   524  }
   525  
   526  static void simple_oom_6(OomTest *pOom){
   527    Datasource *pData = getDatasource();
   528    int rc = LSM_OK;
   529    lsm_db *pDb;
   530  
   531    testRestoreDb(LSMTEST6_TESTDB, "log");
   532    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
   533  
   534    testOomWriteData(pOom, pDb, pData, 5000, &rc);
   535    testOomWriteData(pOom, pDb, pData, 5001, &rc);
   536    testOomWriteData(pOom, pDb, pData, 5002, &rc);
   537    testOomFetchData(pOom, pDb, pData, 5001, &rc);
   538    testOomFetchData(pOom, pDb, pData, 1234, &rc);
   539  
   540    lsm_close(pDb);
   541    testDatasourceFree(pData);
   542  }
   543  
   544  static void simple_oom_7(OomTest *pOom){
   545    Datasource *pData = getDatasource();
   546    int rc = LSM_OK;
   547    lsm_db *pDb;
   548  
   549    testRestoreDb(LSMTEST6_TESTDB, "log");
   550    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
   551    testOomScan(pOom, pDb, 0, "abc", 3, 20, &rc);
   552    lsm_close(pDb);
   553    testDatasourceFree(pData);
   554  }
   555  
   556  static void simple_oom_8(OomTest *pOom){
   557    Datasource *pData = getDatasource();
   558    int rc = LSM_OK;
   559    lsm_db *pDb;
   560    testRestoreDb(LSMTEST6_TESTDB, "log");
   561    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
   562    testOomScan(pOom, pDb, 1, "xyz", 3, 20, &rc);
   563    lsm_close(pDb);
   564    testDatasourceFree(pData);
   565  }
   566  
   567  /*
   568  ** This test case has two clients connected to a database. The first client
   569  ** hits an OOM while writing to the database. Check that the second 
   570  ** connection is still able to query the db following the OOM.
   571  */
   572  static void simple_oom2_1(OomTest *pOom){
   573    const int nRecord = 100;        /* Number of records initially in db */
   574    const int nIns = 10;            /* Number of records inserted with OOM */
   575  
   576    Datasource *pData = getDatasource();
   577    int rc = LSM_OK;
   578    lsm_db *pDb1;
   579    lsm_db *pDb2;
   580    int i;
   581  
   582    testDeleteLsmdb(LSMTEST6_TESTDB);
   583  
   584    /* Open the two connections. Initialize the in-memory tree so that it
   585    ** contains 100 records. Do all this with OOM injection disabled. */
   586    testOomEnable(pOom, 0);
   587    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb1, &rc);
   588    testOomOpen(pOom, LSMTEST6_TESTDB, &pDb2, &rc);
   589    for(i=0; i<nRecord; i++){
   590      testOomWriteData(pOom, pDb1, pData, i, &rc);
   591    }
   592    testOomEnable(pOom, 1);
   593    assert( rc==0 );
   594  
   595    /* Insert 10 more records using pDb1. Stop when an OOM is encountered. */
   596    for(i=nRecord; i<nRecord+nIns; i++){
   597      testOomWriteData(pOom, pDb1, pData, i, &rc);
   598      if( rc ) break;
   599    }
   600    testOomAssertRc(pOom, rc);
   601  
   602    /* Switch off OOM injection. Write a few rows using pDb2. Then check
   603    ** that the database may be successfully queried.  */
   604    testOomEnable(pOom, 0);
   605    rc = 0;
   606    for(; i<nRecord+nIns && rc==0; i++){
   607      testOomWriteData(pOom, pDb2, pData, i, &rc);
   608    }
   609    for(i=0; i<nRecord+nIns; i++) testOomFetchData(pOom, pDb2, pData, i, &rc);
   610    testOomEnable(pOom, 1);
   611  
   612    lsm_close(pDb1);
   613    lsm_close(pDb2);
   614    testDatasourceFree(pData);
   615  }
   616  
   617  
   618  static void do_test_oom1(const char *zPattern, int *pRc){
   619    struct SimpleOom {
   620      const char *zName;
   621      void (*xSetup)(void);
   622      void (*xFunc)(OomTest *);
   623    } aSimple[] = {
   624      { "oom1.lsm.1", setup_delete_db,    simple_oom_1 },
   625      { "oom1.lsm.2", setup_delete_db,    simple_oom_2 },
   626      { "oom1.lsm.3", setup_populate_db,  simple_oom_3 },
   627      { "oom1.lsm.4", setup_delete_db,    simple_oom_4 },
   628      { "oom1.lsm.5", setup_populate_db2, simple_oom_5 },
   629      { "oom1.lsm.6", setup_populate_db2, simple_oom_6 },
   630      { "oom1.lsm.7", setup_populate_db2, simple_oom_7 },
   631      { "oom1.lsm.8", setup_populate_db2, simple_oom_8 },
   632  
   633      { "oom2.lsm.1", setup_delete_db,    simple_oom2_1 },
   634    };
   635    int i;
   636  
   637    for(i=0; i<ArraySize(aSimple); i++){
   638      if( *pRc==0 && testCaseBegin(pRc, zPattern, "%s", aSimple[i].zName) ){
   639        OomTest t;
   640  
   641        if( aSimple[i].xSetup ){
   642          aSimple[i].xSetup();
   643        }
   644  
   645        for(testOomStart(&t); testOomContinue(&t); testOomNext(&t)){
   646          aSimple[i].xFunc(&t);
   647        }
   648  
   649        printf("(%d injections).", t.iNext-2);
   650        testCaseFinish( (*pRc = testOomFinish(&t)) );
   651        testMallocOom(tdb_lsm_env(), 0, 0, 0, 0);
   652      }
   653    }
   654  }
   655  
   656  void test_oom(
   657    const char *zPattern,           /* Run test cases that match this pattern */
   658    int *pRc                        /* IN/OUT: Error code */
   659  ){
   660    do_test_oom1(zPattern, pRc);
   661  }