mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Further test cases for pager1.test and pagerfault.test.
FossilOrigin-Name: bfd563c4714d86805fa09ce9f4f807e5d502a99b
This commit is contained in:
150
src/test_vfs.c
150
src/test_vfs.c
@@ -37,6 +37,16 @@ struct TestvfsFile {
|
||||
TestvfsFile *pNext; /* Next handle opened on the same file */
|
||||
};
|
||||
|
||||
#define FAULT_INJECT_NONE 0
|
||||
#define FAULT_INJECT_TRANSIENT 1
|
||||
#define FAULT_INJECT_PERSISTENT 2
|
||||
|
||||
typedef struct TestFaultInject TestFaultInject;
|
||||
struct TestFaultInject {
|
||||
int iCnt; /* Remaining calls before fault injection */
|
||||
int eFault; /* A FAULT_INJECT_* value */
|
||||
int nFail; /* Number of faults injected */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of this structure is allocated for each VFS created. The
|
||||
@@ -54,14 +64,20 @@ struct Testvfs {
|
||||
TestvfsBuffer *pBuffer; /* List of shared buffers */
|
||||
int isNoshm;
|
||||
|
||||
int mask;
|
||||
int mask; /* Mask controlling [script] and [ioerr] */
|
||||
|
||||
TestFaultInject ioerr_err;
|
||||
TestFaultInject full_err;
|
||||
TestFaultInject cantopen_err;
|
||||
|
||||
#if 0
|
||||
int iIoerrCnt;
|
||||
int ioerr;
|
||||
int nIoerrFail;
|
||||
|
||||
int iFullCnt;
|
||||
int fullerr;
|
||||
int nFullFail;
|
||||
#endif
|
||||
|
||||
int iDevchar;
|
||||
int iSectorsize;
|
||||
@@ -87,7 +103,8 @@ struct Testvfs {
|
||||
#define TESTVFS_CLOSE_MASK 0x00000800
|
||||
#define TESTVFS_WRITE_MASK 0x00001000
|
||||
#define TESTVFS_TRUNCATE_MASK 0x00002000
|
||||
#define TESTVFS_ALL_MASK 0x00003FFF
|
||||
#define TESTVFS_ACCESS_MASK 0x00004000
|
||||
#define TESTVFS_ALL_MASK 0x00007FFF
|
||||
|
||||
|
||||
#define TESTVFS_MAX_PAGES 1024
|
||||
@@ -197,28 +214,28 @@ static int tvfsResultCode(Testvfs *p, int *pRc){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tvfsInjectIoerr(Testvfs *p){
|
||||
static int tvfsInjectFault(TestFaultInject *p){
|
||||
int ret = 0;
|
||||
if( p->ioerr ){
|
||||
p->iIoerrCnt--;
|
||||
if( p->iIoerrCnt==0 || (p->iIoerrCnt<0 && p->ioerr==2) ){
|
||||
if( p->eFault ){
|
||||
p->iCnt--;
|
||||
if( p->iCnt==0 || (p->iCnt<0 && p->eFault==FAULT_INJECT_PERSISTENT ) ){
|
||||
ret = 1;
|
||||
p->nIoerrFail++;
|
||||
p->nFail++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int tvfsInjectIoerr(Testvfs *p){
|
||||
return tvfsInjectFault(&p->ioerr_err);
|
||||
}
|
||||
|
||||
static int tvfsInjectFullerr(Testvfs *p){
|
||||
int ret = 0;
|
||||
if( p->fullerr ){
|
||||
p->iFullCnt--;
|
||||
if( p->iFullCnt<=0 ){
|
||||
ret = 1;
|
||||
p->nFullFail++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return tvfsInjectFault(&p->full_err);
|
||||
}
|
||||
static int tvfsInjectCantopenerr(Testvfs *p){
|
||||
return tvfsInjectFault(&p->cantopen_err);
|
||||
}
|
||||
|
||||
|
||||
@@ -512,6 +529,11 @@ static int tvfsOpen(
|
||||
pId = Tcl_GetObjResult(p->interp);
|
||||
}
|
||||
}
|
||||
|
||||
if( (p->mask&TESTVFS_OPEN_MASK) && tvfsInjectIoerr(p) ) return SQLITE_IOERR;
|
||||
if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN;
|
||||
if( tvfsInjectFullerr(p) ) return SQLITE_FULL;
|
||||
|
||||
if( !pId ){
|
||||
pId = Tcl_NewStringObj("anon", -1);
|
||||
}
|
||||
@@ -519,6 +541,7 @@ static int tvfsOpen(
|
||||
pFd->pShmId = pId;
|
||||
Tcl_ResetResult(p->interp);
|
||||
|
||||
|
||||
rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags);
|
||||
if( pFd->pReal->pMethods ){
|
||||
sqlite3_io_methods *pMethods;
|
||||
@@ -568,6 +591,25 @@ static int tvfsAccess(
|
||||
int flags,
|
||||
int *pResOut
|
||||
){
|
||||
Testvfs *p = (Testvfs *)pVfs->pAppData;
|
||||
if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){
|
||||
int rc;
|
||||
char *zArg = 0;
|
||||
if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS";
|
||||
if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE";
|
||||
if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ";
|
||||
tvfsExecTcl(p, "xAccess",
|
||||
Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0
|
||||
);
|
||||
if( tvfsResultCode(p, &rc) ){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}else{
|
||||
Tcl_Interp *interp = p->interp;
|
||||
if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut);
|
||||
}
|
||||
|
||||
@@ -857,20 +899,21 @@ static int testvfs_obj_cmd(
|
||||
|
||||
enum DB_enum {
|
||||
CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT,
|
||||
CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR
|
||||
CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR, CMD_CANTOPENERR
|
||||
};
|
||||
struct TestvfsSubcmd {
|
||||
char *zName;
|
||||
enum DB_enum eCmd;
|
||||
} aSubcmd[] = {
|
||||
{ "shm", CMD_SHM },
|
||||
{ "delete", CMD_DELETE },
|
||||
{ "filter", CMD_FILTER },
|
||||
{ "ioerr", CMD_IOERR },
|
||||
{ "fullerr", CMD_FULLERR },
|
||||
{ "script", CMD_SCRIPT },
|
||||
{ "devchar", CMD_DEVCHAR },
|
||||
{ "sectorsize", CMD_SECTORSIZE },
|
||||
{ "shm", CMD_SHM },
|
||||
{ "delete", CMD_DELETE },
|
||||
{ "filter", CMD_FILTER },
|
||||
{ "ioerr", CMD_IOERR },
|
||||
{ "fullerr", CMD_FULLERR },
|
||||
{ "cantopenerr", CMD_CANTOPENERR },
|
||||
{ "script", CMD_SCRIPT },
|
||||
{ "devchar", CMD_DEVCHAR },
|
||||
{ "sectorsize", CMD_SECTORSIZE },
|
||||
{ 0, 0 }
|
||||
};
|
||||
int i;
|
||||
@@ -950,6 +993,7 @@ static int testvfs_obj_cmd(
|
||||
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
|
||||
{ "xOpen", TESTVFS_OPEN_MASK },
|
||||
{ "xClose", TESTVFS_CLOSE_MASK },
|
||||
{ "xAccess", TESTVFS_ACCESS_MASK },
|
||||
};
|
||||
Tcl_Obj **apElem = 0;
|
||||
int nElem = 0;
|
||||
@@ -1007,45 +1051,27 @@ static int testvfs_obj_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** TESTVFS fullerr ?IFAIL?
|
||||
**
|
||||
** Where IFAIL is an integer.
|
||||
*/
|
||||
case CMD_FULLERR: {
|
||||
int iRet = p->nFullFail;
|
||||
|
||||
p->nFullFail = 0;
|
||||
p->fullerr = 0;
|
||||
p->iFullCnt = 0;
|
||||
|
||||
if( objc==3 ){
|
||||
int iCnt;
|
||||
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iCnt) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
p->fullerr = (iCnt>0);
|
||||
p->iFullCnt = iCnt;
|
||||
}else if( objc!=2 ){
|
||||
Tcl_AppendResult(interp, "Bad args", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** TESTVFS ioerr ?IFAIL PERSIST?
|
||||
**
|
||||
** Where IFAIL is an integer and PERSIST is boolean.
|
||||
*/
|
||||
case CMD_IOERR: {
|
||||
int iRet = p->nIoerrFail;
|
||||
case CMD_CANTOPENERR:
|
||||
case CMD_IOERR:
|
||||
case CMD_FULLERR: {
|
||||
TestFaultInject *pTest;
|
||||
int iRet;
|
||||
|
||||
p->nIoerrFail = 0;
|
||||
p->ioerr = 0;
|
||||
p->iIoerrCnt = 0;
|
||||
switch( aSubcmd[i].eCmd ){
|
||||
case CMD_IOERR: pTest = &p->ioerr_err; break;
|
||||
case CMD_FULLERR: pTest = &p->full_err; break;
|
||||
case CMD_CANTOPENERR: pTest = &p->cantopen_err; break;
|
||||
default: assert(0);
|
||||
}
|
||||
iRet = pTest->nFail;
|
||||
pTest->nFail = 0;
|
||||
pTest->eFault = 0;
|
||||
pTest->iCnt = 0;
|
||||
|
||||
if( objc==4 ){
|
||||
int iCnt, iPersist;
|
||||
@@ -1054,10 +1080,10 @@ static int testvfs_obj_cmd(
|
||||
){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
p->ioerr = (iCnt>0) + iPersist;
|
||||
p->iIoerrCnt = iCnt;
|
||||
pTest->eFault = iPersist?FAULT_INJECT_PERSISTENT:FAULT_INJECT_TRANSIENT;
|
||||
pTest->iCnt = iCnt;
|
||||
}else if( objc!=2 ){
|
||||
Tcl_AppendResult(interp, "Bad args", 0);
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?CNT PERSIST?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet));
|
||||
|
Reference in New Issue
Block a user