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 
testOomStart(OomTest * p)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 
xOomHook(OomTest * p)21 static void xOomHook(OomTest *p){
22   p->nFail++;
23 }
24 
testOomContinue(OomTest * p)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 
testOomEnable(OomTest * p,int bEnable)34 static void testOomEnable(OomTest *p, int bEnable){
35   p->bEnable = bEnable;
36   testMallocOomEnable(p->pEnv, bEnable);
37 }
38 
testOomNext(OomTest * p)39 static void testOomNext(OomTest *p){
40   p->iNext++;
41 }
42 
testOomHit(OomTest * p)43 static int testOomHit(OomTest *p){
44   return (p->nFail>0);
45 }
46 
testOomFinish(OomTest * p)47 static int testOomFinish(OomTest *p){
48   return p->rc;
49 }
50 
testOomAssert(OomTest * p,int bVal)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 */
testOomAssertRc(OomTest * p,int rc)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 
testOomOpen(OomTest * pOom,const char * zName,lsm_db ** ppDb,int * pRc)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 
testOomFetch(OomTest * pOom,lsm_db * pDb,void * pKey,int nKey,void * pVal,int nVal,int * pRc)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 
testOomWrite(OomTest * pOom,lsm_db * pDb,void * pKey,int nKey,void * pVal,int nVal,int * pRc)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 
testOomFetchStr(OomTest * pOom,lsm_db * pDb,const char * zKey,const char * zVal,int * pRc)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 
testOomFetchData(OomTest * pOom,lsm_db * pDb,Datasource * pData,int iKey,int * pRc)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 
testOomWriteStr(OomTest * pOom,lsm_db * pDb,const char * zKey,const char * zVal,int * pRc)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 
testOomWriteData(OomTest * pOom,lsm_db * pDb,Datasource * pData,int iKey,int * pRc)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 
testOomScan(OomTest * pOom,lsm_db * pDb,int bReverse,const void * pKey,int nKey,int nScan,int * pRc)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 
testDeleteLsmdb(const char * zFile)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 
copy_file(const char * zFrom,const char * zTo,int isDatabase)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 
testCopyLsmdb(const char * zFrom,const char * zTo)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 */
testSaveDb(const char * zFile,const char * zAux)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 */
testRestoreDb(const char * zFile,const char * zAux)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 
lsmWriteStr(lsm_db * pDb,const char * zKey,const char * zVal)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 
setup_delete_db(void)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 */
setup_populate_db(void)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 
getDatasource(void)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 */
setup_populate_db2(void)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 */
simple_oom_1(OomTest * pOom)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 */
simple_oom_2(OomTest * pOom)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 */
simple_oom_3(OomTest * pOom)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 */
simple_oom_4(OomTest * pOom)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 
simple_oom_5(OomTest * pOom)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 
simple_oom_6(OomTest * pOom)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 
simple_oom_7(OomTest * pOom)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 
simple_oom_8(OomTest * pOom)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 */
simple_oom2_1(OomTest * pOom)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 
do_test_oom1(const char * zPattern,int * pRc)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 
test_oom(const char * zPattern,int * pRc)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 }
662