662 lines
16 KiB
C
662 lines
16 KiB
C
|
|
#include "lsmtest.h"
|
|
|
|
typedef struct OomTest OomTest;
|
|
struct OomTest {
|
|
lsm_env *pEnv;
|
|
int iNext; /* Next value to pass to testMallocOom() */
|
|
int nFail; /* Number of OOM events injected */
|
|
int bEnable;
|
|
int rc; /* Test case error code */
|
|
};
|
|
|
|
static void testOomStart(OomTest *p){
|
|
memset(p, 0, sizeof(OomTest));
|
|
p->iNext = 1;
|
|
p->bEnable = 1;
|
|
p->nFail = 1;
|
|
p->pEnv = tdb_lsm_env();
|
|
}
|
|
|
|
static void xOomHook(OomTest *p){
|
|
p->nFail++;
|
|
}
|
|
|
|
static int testOomContinue(OomTest *p){
|
|
if( p->rc!=0 || (p->iNext>1 && p->nFail==0) ){
|
|
return 0;
|
|
}
|
|
p->nFail = 0;
|
|
testMallocOom(p->pEnv, p->iNext, 0, (void (*)(void*))xOomHook, (void *)p);
|
|
return 1;
|
|
}
|
|
|
|
static void testOomEnable(OomTest *p, int bEnable){
|
|
p->bEnable = bEnable;
|
|
testMallocOomEnable(p->pEnv, bEnable);
|
|
}
|
|
|
|
static void testOomNext(OomTest *p){
|
|
p->iNext++;
|
|
}
|
|
|
|
static int testOomHit(OomTest *p){
|
|
return (p->nFail>0);
|
|
}
|
|
|
|
static int testOomFinish(OomTest *p){
|
|
return p->rc;
|
|
}
|
|
|
|
static void testOomAssert(OomTest *p, int bVal){
|
|
if( bVal==0 ){
|
|
test_failed();
|
|
p->rc = 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Test that the error code matches the state of the OomTest object passed
|
|
** as the first argument. Specifically, check that rc is LSM_NOMEM if an
|
|
** OOM error has already been injected, or LSM_OK if not.
|
|
*/
|
|
static void testOomAssertRc(OomTest *p, int rc){
|
|
testOomAssert(p, rc==LSM_OK || rc==LSM_NOMEM);
|
|
testOomAssert(p, testOomHit(p)==(rc==LSM_NOMEM) || p->bEnable==0 );
|
|
}
|
|
|
|
static void testOomOpen(
|
|
OomTest *pOom,
|
|
const char *zName,
|
|
lsm_db **ppDb,
|
|
int *pRc
|
|
){
|
|
if( *pRc==LSM_OK ){
|
|
int rc;
|
|
rc = lsm_new(tdb_lsm_env(), ppDb);
|
|
if( rc==LSM_OK ) rc = lsm_open(*ppDb, zName);
|
|
testOomAssertRc(pOom, rc);
|
|
*pRc = rc;
|
|
}
|
|
}
|
|
|
|
static void testOomFetch(
|
|
OomTest *pOom,
|
|
lsm_db *pDb,
|
|
void *pKey, int nKey,
|
|
void *pVal, int nVal,
|
|
int *pRc
|
|
){
|
|
testOomAssertRc(pOom, *pRc);
|
|
if( *pRc==LSM_OK ){
|
|
lsm_cursor *pCsr;
|
|
int rc;
|
|
|
|
rc = lsm_csr_open(pDb, &pCsr);
|
|
if( rc==LSM_OK ) rc = lsm_csr_seek(pCsr, pKey, nKey, 0);
|
|
testOomAssertRc(pOom, rc);
|
|
|
|
if( rc==LSM_OK ){
|
|
const void *p; int n;
|
|
testOomAssert(pOom, lsm_csr_valid(pCsr));
|
|
|
|
rc = lsm_csr_key(pCsr, &p, &n);
|
|
testOomAssertRc(pOom, rc);
|
|
testOomAssert(pOom, rc!=LSM_OK || (n==nKey && memcmp(pKey, p, nKey)==0) );
|
|
}
|
|
|
|
if( rc==LSM_OK ){
|
|
const void *p; int n;
|
|
testOomAssert(pOom, lsm_csr_valid(pCsr));
|
|
|
|
rc = lsm_csr_value(pCsr, &p, &n);
|
|
testOomAssertRc(pOom, rc);
|
|
testOomAssert(pOom, rc!=LSM_OK || (n==nVal && memcmp(pVal, p, nVal)==0) );
|
|
}
|
|
|
|
lsm_csr_close(pCsr);
|
|
*pRc = rc;
|
|
}
|
|
}
|
|
|
|
static void testOomWrite(
|
|
OomTest *pOom,
|
|
lsm_db *pDb,
|
|
void *pKey, int nKey,
|
|
void *pVal, int nVal,
|
|
int *pRc
|
|
){
|
|
testOomAssertRc(pOom, *pRc);
|
|
if( *pRc==LSM_OK ){
|
|
int rc;
|
|
|
|
rc = lsm_insert(pDb, pKey, nKey, pVal, nVal);
|
|
testOomAssertRc(pOom, rc);
|
|
|
|
*pRc = rc;
|
|
}
|
|
}
|
|
|
|
|
|
static void testOomFetchStr(
|
|
OomTest *pOom,
|
|
lsm_db *pDb,
|
|
const char *zKey,
|
|
const char *zVal,
|
|
int *pRc
|
|
){
|
|
int nKey = strlen(zKey);
|
|
int nVal = strlen(zVal);
|
|
testOomFetch(pOom, pDb, (void *)zKey, nKey, (void *)zVal, nVal, pRc);
|
|
}
|
|
|
|
static void testOomFetchData(
|
|
OomTest *pOom,
|
|
lsm_db *pDb,
|
|
Datasource *pData,
|
|
int iKey,
|
|
int *pRc
|
|
){
|
|
void *pKey; int nKey;
|
|
void *pVal; int nVal;
|
|
testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
|
|
testOomFetch(pOom, pDb, pKey, nKey, pVal, nVal, pRc);
|
|
}
|
|
|
|
static void testOomWriteStr(
|
|
OomTest *pOom,
|
|
lsm_db *pDb,
|
|
const char *zKey,
|
|
const char *zVal,
|
|
int *pRc
|
|
){
|
|
int nKey = strlen(zKey);
|
|
int nVal = strlen(zVal);
|
|
testOomWrite(pOom, pDb, (void *)zKey, nKey, (void *)zVal, nVal, pRc);
|
|
}
|
|
|
|
static void testOomWriteData(
|
|
OomTest *pOom,
|
|
lsm_db *pDb,
|
|
Datasource *pData,
|
|
int iKey,
|
|
int *pRc
|
|
){
|
|
void *pKey; int nKey;
|
|
void *pVal; int nVal;
|
|
testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal);
|
|
testOomWrite(pOom, pDb, pKey, nKey, pVal, nVal, pRc);
|
|
}
|
|
|
|
static void testOomScan(
|
|
OomTest *pOom,
|
|
lsm_db *pDb,
|
|
int bReverse,
|
|
const void *pKey, int nKey,
|
|
int nScan,
|
|
int *pRc
|
|
){
|
|
if( *pRc==0 ){
|
|
int rc;
|
|
int iScan = 0;
|
|
lsm_cursor *pCsr;
|
|
int (*xAdvance)(lsm_cursor *) = 0;
|
|
|
|
|
|
rc = lsm_csr_open(pDb, &pCsr);
|
|
testOomAssertRc(pOom, rc);
|
|
|
|
if( rc==LSM_OK ){
|
|
if( bReverse ){
|
|
rc = lsm_csr_seek(pCsr, pKey, nKey, LSM_SEEK_LE);
|
|
xAdvance = lsm_csr_prev;
|
|
}else{
|
|
rc = lsm_csr_seek(pCsr, pKey, nKey, LSM_SEEK_GE);
|
|
xAdvance = lsm_csr_next;
|
|
}
|
|
}
|
|
testOomAssertRc(pOom, rc);
|
|
|
|
while( rc==LSM_OK && lsm_csr_valid(pCsr) && iScan<nScan ){
|
|
const void *p; int n;
|
|
|
|
rc = lsm_csr_key(pCsr, &p, &n);
|
|
testOomAssertRc(pOom, rc);
|
|
if( rc==LSM_OK ){
|
|
rc = lsm_csr_value(pCsr, &p, &n);
|
|
testOomAssertRc(pOom, rc);
|
|
}
|
|
if( rc==LSM_OK ){
|
|
rc = xAdvance(pCsr);
|
|
testOomAssertRc(pOom, rc);
|
|
}
|
|
iScan++;
|
|
}
|
|
|
|
lsm_csr_close(pCsr);
|
|
*pRc = rc;
|
|
}
|
|
}
|
|
|
|
#define LSMTEST6_TESTDB "testdb.lsm"
|
|
|
|
void testDeleteLsmdb(const char *zFile){
|
|
char *zLog = testMallocPrintf("%s-log", zFile);
|
|
char *zShm = testMallocPrintf("%s-shm", zFile);
|
|
unlink(zFile);
|
|
unlink(zLog);
|
|
unlink(zShm);
|
|
testFree(zLog);
|
|
testFree(zShm);
|
|
}
|
|
|
|
static void copy_file(const char *zFrom, const char *zTo, int isDatabase){
|
|
|
|
if( access(zFrom, F_OK) ){
|
|
unlink(zTo);
|
|
}else{
|
|
int fd1;
|
|
int fd2;
|
|
off_t sz;
|
|
off_t i;
|
|
struct stat buf;
|
|
u8 *aBuf;
|
|
|
|
fd1 = open(zFrom, O_RDONLY | _O_BINARY, 0644);
|
|
fd2 = open(zTo, O_RDWR | O_CREAT | _O_BINARY, 0644);
|
|
|
|
fstat(fd1, &buf);
|
|
sz = buf.st_size;
|
|
ftruncate(fd2, sz);
|
|
|
|
aBuf = testMalloc(4096);
|
|
for(i=0; i<sz; i+=4096){
|
|
int bLockPage = isDatabase && i == 0;
|
|
int nByte = MIN((bLockPage ? 4066 : 4096), sz - i);
|
|
memset(aBuf, 0, 4096);
|
|
read(fd1, aBuf, nByte);
|
|
write(fd2, aBuf, nByte);
|
|
if( bLockPage ){
|
|
lseek(fd1, 4096, SEEK_SET);
|
|
lseek(fd2, 4096, SEEK_SET);
|
|
}
|
|
}
|
|
testFree(aBuf);
|
|
|
|
close(fd1);
|
|
close(fd2);
|
|
}
|
|
}
|
|
|
|
void testCopyLsmdb(const char *zFrom, const char *zTo){
|
|
char *zLog1 = testMallocPrintf("%s-log", zFrom);
|
|
char *zLog2 = testMallocPrintf("%s-log", zTo);
|
|
char *zShm1 = testMallocPrintf("%s-shm", zFrom);
|
|
char *zShm2 = testMallocPrintf("%s-shm", zTo);
|
|
|
|
unlink(zShm2);
|
|
unlink(zLog2);
|
|
unlink(zTo);
|
|
copy_file(zFrom, zTo, 1);
|
|
copy_file(zLog1, zLog2, 0);
|
|
copy_file(zShm1, zShm2, 0);
|
|
|
|
testFree(zLog1); testFree(zLog2); testFree(zShm1); testFree(zShm2);
|
|
}
|
|
|
|
/*
|
|
** File zFile is the path to a database. This function makes backups
|
|
** of the database file and its log as follows:
|
|
**
|
|
** cp $(zFile) $(zFile)-save
|
|
** cp $(zFile)-$(zAux) $(zFile)-save-$(zAux)
|
|
**
|
|
** Function testRestoreDb() can be used to copy the files back in the
|
|
** other direction.
|
|
*/
|
|
void testSaveDb(const char *zFile, const char *zAux){
|
|
char *zLog = testMallocPrintf("%s-%s", zFile, zAux);
|
|
char *zFileSave = testMallocPrintf("%s-save", zFile);
|
|
char *zLogSave = testMallocPrintf("%s-%s-save", zFile, zAux);
|
|
|
|
unlink(zFileSave);
|
|
unlink(zLogSave);
|
|
copy_file(zFile, zFileSave, 1);
|
|
copy_file(zLog, zLogSave, 0);
|
|
|
|
testFree(zLog); testFree(zFileSave); testFree(zLogSave);
|
|
}
|
|
|
|
/*
|
|
** File zFile is the path to a database. This function restores
|
|
** a backup of the database made by a previous call to testSaveDb().
|
|
** Specifically, it does the equivalent of:
|
|
**
|
|
** cp $(zFile)-save $(zFile)
|
|
** cp $(zFile)-save-$(zAux) $(zFile)-$(zAux)
|
|
*/
|
|
void testRestoreDb(const char *zFile, const char *zAux){
|
|
char *zLog = testMallocPrintf("%s-%s", zFile, zAux);
|
|
char *zFileSave = testMallocPrintf("%s-save", zFile);
|
|
char *zLogSave = testMallocPrintf("%s-%s-save", zFile, zAux);
|
|
|
|
copy_file(zFileSave, zFile, 1);
|
|
copy_file(zLogSave, zLog, 0);
|
|
|
|
testFree(zLog); testFree(zFileSave); testFree(zLogSave);
|
|
}
|
|
|
|
|
|
static int lsmWriteStr(lsm_db *pDb, const char *zKey, const char *zVal){
|
|
int nKey = strlen(zKey);
|
|
int nVal = strlen(zVal);
|
|
return lsm_insert(pDb, (void *)zKey, nKey, (void *)zVal, nVal);
|
|
}
|
|
|
|
static void setup_delete_db(void){
|
|
testDeleteLsmdb(LSMTEST6_TESTDB);
|
|
}
|
|
|
|
/*
|
|
** Create a small database. With the following content:
|
|
**
|
|
** "one" -> "one"
|
|
** "two" -> "four"
|
|
** "three" -> "nine"
|
|
** "four" -> "sixteen"
|
|
** "five" -> "twentyfive"
|
|
** "six" -> "thirtysix"
|
|
** "seven" -> "fourtynine"
|
|
** "eight" -> "sixtyfour"
|
|
*/
|
|
static void setup_populate_db(void){
|
|
const char *azStr[] = {
|
|
"one", "one",
|
|
"two", "four",
|
|
"three", "nine",
|
|
"four", "sixteen",
|
|
"five", "twentyfive",
|
|
"six", "thirtysix",
|
|
"seven", "fourtynine",
|
|
"eight", "sixtyfour",
|
|
};
|
|
int rc;
|
|
int ii;
|
|
lsm_db *pDb;
|
|
|
|
testDeleteLsmdb(LSMTEST6_TESTDB);
|
|
|
|
rc = lsm_new(tdb_lsm_env(), &pDb);
|
|
if( rc==LSM_OK ) rc = lsm_open(pDb, LSMTEST6_TESTDB);
|
|
|
|
for(ii=0; rc==LSM_OK && ii<ArraySize(azStr); ii+=2){
|
|
rc = lsmWriteStr(pDb, azStr[ii], azStr[ii+1]);
|
|
}
|
|
lsm_close(pDb);
|
|
|
|
testSaveDb(LSMTEST6_TESTDB, "log");
|
|
assert( rc==LSM_OK );
|
|
}
|
|
|
|
static Datasource *getDatasource(void){
|
|
const DatasourceDefn defn = { TEST_DATASOURCE_RANDOM, 10, 15, 200, 250 };
|
|
return testDatasourceNew(&defn);
|
|
}
|
|
|
|
/*
|
|
** Set up a database file with the following properties:
|
|
**
|
|
** * Page size is 1024 bytes.
|
|
** * Block size is 64 KB.
|
|
** * Contains 5000 key-value pairs starting at 0 from the
|
|
** datasource returned getDatasource().
|
|
*/
|
|
static void setup_populate_db2(void){
|
|
Datasource *pData;
|
|
int ii;
|
|
int rc;
|
|
int nBlocksize = 64*1024;
|
|
int nPagesize = 1024;
|
|
int nWritebuffer = 4*1024;
|
|
lsm_db *pDb;
|
|
|
|
testDeleteLsmdb(LSMTEST6_TESTDB);
|
|
rc = lsm_new(tdb_lsm_env(), &pDb);
|
|
if( rc==LSM_OK ) rc = lsm_open(pDb, LSMTEST6_TESTDB);
|
|
|
|
lsm_config(pDb, LSM_CONFIG_BLOCK_SIZE, &nBlocksize);
|
|
lsm_config(pDb, LSM_CONFIG_PAGE_SIZE, &nPagesize);
|
|
lsm_config(pDb, LSM_CONFIG_AUTOFLUSH, &nWritebuffer);
|
|
|
|
pData = getDatasource();
|
|
for(ii=0; rc==LSM_OK && ii<5000; ii++){
|
|
void *pKey; int nKey;
|
|
void *pVal; int nVal;
|
|
testDatasourceEntry(pData, ii, &pKey, &nKey, &pVal, &nVal);
|
|
lsm_insert(pDb, pKey, nKey, pVal, nVal);
|
|
}
|
|
testDatasourceFree(pData);
|
|
lsm_close(pDb);
|
|
|
|
testSaveDb(LSMTEST6_TESTDB, "log");
|
|
assert( rc==LSM_OK );
|
|
}
|
|
|
|
/*
|
|
** Test the results of OOM conditions in lsm_new().
|
|
*/
|
|
static void simple_oom_1(OomTest *pOom){
|
|
int rc;
|
|
lsm_db *pDb;
|
|
|
|
rc = lsm_new(tdb_lsm_env(), &pDb);
|
|
testOomAssertRc(pOom, rc);
|
|
|
|
lsm_close(pDb);
|
|
}
|
|
|
|
/*
|
|
** Test the results of OOM conditions in lsm_open().
|
|
*/
|
|
static void simple_oom_2(OomTest *pOom){
|
|
int rc;
|
|
lsm_db *pDb;
|
|
|
|
rc = lsm_new(tdb_lsm_env(), &pDb);
|
|
if( rc==LSM_OK ){
|
|
rc = lsm_open(pDb, "testdb.lsm");
|
|
}
|
|
testOomAssertRc(pOom, rc);
|
|
|
|
lsm_close(pDb);
|
|
}
|
|
|
|
/*
|
|
** Test the results of OOM conditions in simple fetch operations.
|
|
*/
|
|
static void simple_oom_3(OomTest *pOom){
|
|
int rc = LSM_OK;
|
|
lsm_db *pDb;
|
|
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
|
|
|
|
testOomFetchStr(pOom, pDb, "four", "sixteen", &rc);
|
|
testOomFetchStr(pOom, pDb, "seven", "fourtynine", &rc);
|
|
testOomFetchStr(pOom, pDb, "one", "one", &rc);
|
|
testOomFetchStr(pOom, pDb, "eight", "sixtyfour", &rc);
|
|
|
|
lsm_close(pDb);
|
|
}
|
|
|
|
/*
|
|
** Test the results of OOM conditions in simple write operations.
|
|
*/
|
|
static void simple_oom_4(OomTest *pOom){
|
|
int rc = LSM_OK;
|
|
lsm_db *pDb;
|
|
|
|
testDeleteLsmdb(LSMTEST6_TESTDB);
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
|
|
|
|
testOomWriteStr(pOom, pDb, "123", "onetwothree", &rc);
|
|
testOomWriteStr(pOom, pDb, "456", "fourfivesix", &rc);
|
|
testOomWriteStr(pOom, pDb, "789", "seveneightnine", &rc);
|
|
testOomWriteStr(pOom, pDb, "123", "teneleventwelve", &rc);
|
|
testOomWriteStr(pOom, pDb, "456", "fourteenfifteensixteen", &rc);
|
|
|
|
lsm_close(pDb);
|
|
}
|
|
|
|
static void simple_oom_5(OomTest *pOom){
|
|
Datasource *pData = getDatasource();
|
|
int rc = LSM_OK;
|
|
lsm_db *pDb;
|
|
|
|
testRestoreDb(LSMTEST6_TESTDB, "log");
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
|
|
|
|
testOomFetchData(pOom, pDb, pData, 3333, &rc);
|
|
testOomFetchData(pOom, pDb, pData, 0, &rc);
|
|
testOomFetchData(pOom, pDb, pData, 4999, &rc);
|
|
|
|
lsm_close(pDb);
|
|
testDatasourceFree(pData);
|
|
}
|
|
|
|
static void simple_oom_6(OomTest *pOom){
|
|
Datasource *pData = getDatasource();
|
|
int rc = LSM_OK;
|
|
lsm_db *pDb;
|
|
|
|
testRestoreDb(LSMTEST6_TESTDB, "log");
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
|
|
|
|
testOomWriteData(pOom, pDb, pData, 5000, &rc);
|
|
testOomWriteData(pOom, pDb, pData, 5001, &rc);
|
|
testOomWriteData(pOom, pDb, pData, 5002, &rc);
|
|
testOomFetchData(pOom, pDb, pData, 5001, &rc);
|
|
testOomFetchData(pOom, pDb, pData, 1234, &rc);
|
|
|
|
lsm_close(pDb);
|
|
testDatasourceFree(pData);
|
|
}
|
|
|
|
static void simple_oom_7(OomTest *pOom){
|
|
Datasource *pData = getDatasource();
|
|
int rc = LSM_OK;
|
|
lsm_db *pDb;
|
|
|
|
testRestoreDb(LSMTEST6_TESTDB, "log");
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
|
|
testOomScan(pOom, pDb, 0, "abc", 3, 20, &rc);
|
|
lsm_close(pDb);
|
|
testDatasourceFree(pData);
|
|
}
|
|
|
|
static void simple_oom_8(OomTest *pOom){
|
|
Datasource *pData = getDatasource();
|
|
int rc = LSM_OK;
|
|
lsm_db *pDb;
|
|
testRestoreDb(LSMTEST6_TESTDB, "log");
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb, &rc);
|
|
testOomScan(pOom, pDb, 1, "xyz", 3, 20, &rc);
|
|
lsm_close(pDb);
|
|
testDatasourceFree(pData);
|
|
}
|
|
|
|
/*
|
|
** This test case has two clients connected to a database. The first client
|
|
** hits an OOM while writing to the database. Check that the second
|
|
** connection is still able to query the db following the OOM.
|
|
*/
|
|
static void simple_oom2_1(OomTest *pOom){
|
|
const int nRecord = 100; /* Number of records initially in db */
|
|
const int nIns = 10; /* Number of records inserted with OOM */
|
|
|
|
Datasource *pData = getDatasource();
|
|
int rc = LSM_OK;
|
|
lsm_db *pDb1;
|
|
lsm_db *pDb2;
|
|
int i;
|
|
|
|
testDeleteLsmdb(LSMTEST6_TESTDB);
|
|
|
|
/* Open the two connections. Initialize the in-memory tree so that it
|
|
** contains 100 records. Do all this with OOM injection disabled. */
|
|
testOomEnable(pOom, 0);
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb1, &rc);
|
|
testOomOpen(pOom, LSMTEST6_TESTDB, &pDb2, &rc);
|
|
for(i=0; i<nRecord; i++){
|
|
testOomWriteData(pOom, pDb1, pData, i, &rc);
|
|
}
|
|
testOomEnable(pOom, 1);
|
|
assert( rc==0 );
|
|
|
|
/* Insert 10 more records using pDb1. Stop when an OOM is encountered. */
|
|
for(i=nRecord; i<nRecord+nIns; i++){
|
|
testOomWriteData(pOom, pDb1, pData, i, &rc);
|
|
if( rc ) break;
|
|
}
|
|
testOomAssertRc(pOom, rc);
|
|
|
|
/* Switch off OOM injection. Write a few rows using pDb2. Then check
|
|
** that the database may be successfully queried. */
|
|
testOomEnable(pOom, 0);
|
|
rc = 0;
|
|
for(; i<nRecord+nIns && rc==0; i++){
|
|
testOomWriteData(pOom, pDb2, pData, i, &rc);
|
|
}
|
|
for(i=0; i<nRecord+nIns; i++) testOomFetchData(pOom, pDb2, pData, i, &rc);
|
|
testOomEnable(pOom, 1);
|
|
|
|
lsm_close(pDb1);
|
|
lsm_close(pDb2);
|
|
testDatasourceFree(pData);
|
|
}
|
|
|
|
|
|
static void do_test_oom1(const char *zPattern, int *pRc){
|
|
struct SimpleOom {
|
|
const char *zName;
|
|
void (*xSetup)(void);
|
|
void (*xFunc)(OomTest *);
|
|
} aSimple[] = {
|
|
{ "oom1.lsm.1", setup_delete_db, simple_oom_1 },
|
|
{ "oom1.lsm.2", setup_delete_db, simple_oom_2 },
|
|
{ "oom1.lsm.3", setup_populate_db, simple_oom_3 },
|
|
{ "oom1.lsm.4", setup_delete_db, simple_oom_4 },
|
|
{ "oom1.lsm.5", setup_populate_db2, simple_oom_5 },
|
|
{ "oom1.lsm.6", setup_populate_db2, simple_oom_6 },
|
|
{ "oom1.lsm.7", setup_populate_db2, simple_oom_7 },
|
|
{ "oom1.lsm.8", setup_populate_db2, simple_oom_8 },
|
|
|
|
{ "oom2.lsm.1", setup_delete_db, simple_oom2_1 },
|
|
};
|
|
int i;
|
|
|
|
for(i=0; i<ArraySize(aSimple); i++){
|
|
if( *pRc==0 && testCaseBegin(pRc, zPattern, "%s", aSimple[i].zName) ){
|
|
OomTest t;
|
|
|
|
if( aSimple[i].xSetup ){
|
|
aSimple[i].xSetup();
|
|
}
|
|
|
|
for(testOomStart(&t); testOomContinue(&t); testOomNext(&t)){
|
|
aSimple[i].xFunc(&t);
|
|
}
|
|
|
|
printf("(%d injections).", t.iNext-2);
|
|
testCaseFinish( (*pRc = testOomFinish(&t)) );
|
|
testMallocOom(tdb_lsm_env(), 0, 0, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void test_oom(
|
|
const char *zPattern, /* Run test cases that match this pattern */
|
|
int *pRc /* IN/OUT: Error code */
|
|
){
|
|
do_test_oom1(zPattern, pRc);
|
|
}
|