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