Add tests to pager1.test and pagerfault.test.
FossilOrigin-Name: 008513ee6115f8d6f4b4e1428c1c638282b971a3
This commit is contained in:
parent
d353331aba
commit
c8ce39723d
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Add\sextra\spager\stests.
|
||||
D 2010-06-28T19:04:02
|
||||
C Add\stests\sto\spager1.test\sand\spagerfault.test.
|
||||
D 2010-06-29T10:30:24
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -209,7 +209,7 @@ F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c aa9919c885a1fe53eafc73492f0898ee6c0a0726
|
||||
F src/test_vfs.c 90d51963dfe2aa28a9408b461cb06f48921be8e8
|
||||
F src/test_vfs.c 2291fd22726e499830e9958563e760effaf9e9af
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb
|
||||
F src/trigger.c 67e95c76d625b92d43409ace771c8e0d02a09ac2
|
||||
@ -534,9 +534,9 @@ F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
|
||||
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
|
||||
F test/pager1.test 634c62f8c321fb5b72b4c8fa27340bd8e9db9089
|
||||
F test/pager1.test 28709653e83ce9557a983cce251ff02112d5ecca
|
||||
F test/pager2.test f5c757c271ce642d36a393ecbfb3aef1c240dcef
|
||||
F test/pagerfault.test 210fae669249a06ef0c08da1e75b9bda7e9bf66b
|
||||
F test/pagerfault.test e7fd4e54fb362ec16ce3474842ed7af390d88de0
|
||||
F test/pagerfault2.test 1287f123bd5d20452113739ed7755fd254e502f1
|
||||
F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
|
||||
F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
|
||||
@ -828,7 +828,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 3b68cb9c656db8c5c481199919a98f5764f7ebfa
|
||||
R 3cf749e0c461e6688a0dd44d86bc37c3
|
||||
P 6b7e419ddc241f457dd69878f09f5c51c70aa379
|
||||
R d8452c9c3029633c6ea47d4358dc9dd2
|
||||
U dan
|
||||
Z cd8f9170613084e79dc0108e44d902f9
|
||||
Z 673ae6c021fa890a23c09b0dc8b30087
|
||||
|
@ -1 +1 @@
|
||||
6b7e419ddc241f457dd69878f09f5c51c70aa379
|
||||
008513ee6115f8d6f4b4e1428c1c638282b971a3
|
111
src/test_vfs.c
111
src/test_vfs.c
@ -13,6 +13,21 @@
|
||||
*/
|
||||
#if SQLITE_TEST /* This file is used for testing only */
|
||||
|
||||
/*
|
||||
** This file contains the implementation of the Tcl [testvfs] command,
|
||||
** used to create SQLite VFS implementations with various properties and
|
||||
** instrumentation to support testing SQLite.
|
||||
**
|
||||
** testvfs VFSNAME ?OPTIONS?
|
||||
**
|
||||
** Available options are:
|
||||
**
|
||||
** -noshm BOOLEAN (True to omit shm methods. Default false)
|
||||
** -default BOOLEAN (True to make the vfs default. Default false)
|
||||
** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile)
|
||||
** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname)
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -20,12 +35,18 @@ typedef struct Testvfs Testvfs;
|
||||
typedef struct TestvfsShm TestvfsShm;
|
||||
typedef struct TestvfsBuffer TestvfsBuffer;
|
||||
typedef struct TestvfsFile TestvfsFile;
|
||||
typedef struct TestvfsFd TestvfsFd;
|
||||
|
||||
/*
|
||||
** An open file handle.
|
||||
*/
|
||||
struct TestvfsFile {
|
||||
sqlite3_file base; /* Base class. Must be first */
|
||||
TestvfsFd *pFd; /* File data */
|
||||
};
|
||||
#define tvfsGetFd(pFile) (((TestvfsFile *)pFile)->pFd)
|
||||
|
||||
struct TestvfsFd {
|
||||
sqlite3_vfs *pVfs; /* The VFS */
|
||||
const char *zFilename; /* Filename as passed to xOpen() */
|
||||
sqlite3_file *pReal; /* The real, underlying file descriptor */
|
||||
@ -34,9 +55,10 @@ struct TestvfsFile {
|
||||
TestvfsBuffer *pShm; /* Shared memory buffer */
|
||||
u32 excllock; /* Mask of exclusive locks */
|
||||
u32 sharedlock; /* Mask of shared locks */
|
||||
TestvfsFile *pNext; /* Next handle opened on the same file */
|
||||
TestvfsFd *pNext; /* Next handle opened on the same file */
|
||||
};
|
||||
|
||||
|
||||
#define FAULT_INJECT_NONE 0
|
||||
#define FAULT_INJECT_TRANSIENT 1
|
||||
#define FAULT_INJECT_PERSISTENT 2
|
||||
@ -118,7 +140,7 @@ struct TestvfsBuffer {
|
||||
char *zFile; /* Associated file name */
|
||||
int pgsz; /* Page size */
|
||||
u8 *aPage[TESTVFS_MAX_PAGES]; /* Array of ckalloc'd pages */
|
||||
TestvfsFile *pFile; /* List of open handles */
|
||||
TestvfsFd *pFile; /* List of open handles */
|
||||
TestvfsBuffer *pNext; /* Next in linked list of all buffers */
|
||||
};
|
||||
|
||||
@ -296,7 +318,9 @@ static void tvfsExecTcl(
|
||||
** Close an tvfs-file.
|
||||
*/
|
||||
static int tvfsClose(sqlite3_file *pFile){
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
int rc;
|
||||
TestvfsFile *pTestfile = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = pTestfile->pFd;
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){
|
||||
@ -312,7 +336,10 @@ static int tvfsClose(sqlite3_file *pFile){
|
||||
if( pFile->pMethods ){
|
||||
ckfree((char *)pFile->pMethods);
|
||||
}
|
||||
return sqlite3OsClose(pFd->pReal);
|
||||
rc = sqlite3OsClose(pFd->pReal);
|
||||
ckfree((char *)pFd);
|
||||
pTestfile->pFd = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -324,7 +351,7 @@ static int tvfsRead(
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
TestvfsFile *p = (TestvfsFile *)pFile;
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
|
||||
}
|
||||
|
||||
@ -338,7 +365,7 @@ static int tvfsWrite(
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
|
||||
@ -366,7 +393,7 @@ static int tvfsWrite(
|
||||
*/
|
||||
static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
int rc = SQLITE_OK;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){
|
||||
@ -387,7 +414,7 @@ static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
*/
|
||||
static int tvfsSync(sqlite3_file *pFile, int flags){
|
||||
int rc = SQLITE_OK;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SYNC_MASK ){
|
||||
@ -430,7 +457,7 @@ static int tvfsSync(sqlite3_file *pFile, int flags){
|
||||
** Return the current file-size of an tvfs-file.
|
||||
*/
|
||||
static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
TestvfsFile *p = (TestvfsFile *)pFile;
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsFileSize(p->pReal, pSize);
|
||||
}
|
||||
|
||||
@ -438,7 +465,7 @@ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
** Lock an tvfs-file.
|
||||
*/
|
||||
static int tvfsLock(sqlite3_file *pFile, int eLock){
|
||||
TestvfsFile *p = (TestvfsFile *)pFile;
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsLock(p->pReal, eLock);
|
||||
}
|
||||
|
||||
@ -446,7 +473,7 @@ static int tvfsLock(sqlite3_file *pFile, int eLock){
|
||||
** Unlock an tvfs-file.
|
||||
*/
|
||||
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
|
||||
TestvfsFile *p = (TestvfsFile *)pFile;
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsUnlock(p->pReal, eLock);
|
||||
}
|
||||
|
||||
@ -454,7 +481,7 @@ static int tvfsUnlock(sqlite3_file *pFile, int eLock){
|
||||
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
|
||||
*/
|
||||
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
TestvfsFile *p = (TestvfsFile *)pFile;
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsCheckReservedLock(p->pReal, pResOut);
|
||||
}
|
||||
|
||||
@ -462,7 +489,7 @@ static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
** File control method. For custom operations on an tvfs-file.
|
||||
*/
|
||||
static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
TestvfsFile *p = (TestvfsFile *)pFile;
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsFileControl(p->pReal, op, pArg);
|
||||
}
|
||||
|
||||
@ -470,7 +497,7 @@ static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
** Return the sector-size in bytes for an tvfs-file.
|
||||
*/
|
||||
static int tvfsSectorSize(sqlite3_file *pFile){
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
if( p->iSectorsize>=0 ){
|
||||
return p->iSectorsize;
|
||||
@ -482,7 +509,7 @@ static int tvfsSectorSize(sqlite3_file *pFile){
|
||||
** Return the device characteristic flags supported by an tvfs-file.
|
||||
*/
|
||||
static int tvfsDeviceCharacteristics(sqlite3_file *pFile){
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
if( p->iDevchar>=0 ){
|
||||
return p->iDevchar;
|
||||
@ -501,15 +528,19 @@ static int tvfsOpen(
|
||||
int *pOutFlags
|
||||
){
|
||||
int rc;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFile *pTestfile = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd;
|
||||
Tcl_Obj *pId = 0;
|
||||
Testvfs *p = (Testvfs *)pVfs->pAppData;
|
||||
|
||||
pFd = (TestvfsFd *)ckalloc(sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile);
|
||||
memset(pFd, 0, sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile);
|
||||
pFd->pShm = 0;
|
||||
pFd->pShmId = 0;
|
||||
pFd->zFilename = zName;
|
||||
pFd->pVfs = pVfs;
|
||||
pFd->pReal = (sqlite3_file *)&pFd[1];
|
||||
pTestfile->pFd = pFd;
|
||||
|
||||
/* Evaluate the Tcl script:
|
||||
**
|
||||
@ -541,7 +572,6 @@ 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;
|
||||
@ -682,15 +712,13 @@ static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut);
|
||||
}
|
||||
|
||||
static int tvfsShmOpen(
|
||||
sqlite3_file *pFileDes
|
||||
){
|
||||
static int tvfsShmOpen(sqlite3_file *pFile){
|
||||
Testvfs *p;
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
TestvfsBuffer *pBuffer; /* Buffer to open connection to */
|
||||
TestvfsFile *pFd; /* The testvfs file structure */
|
||||
TestvfsFd *pFd; /* The testvfs file structure */
|
||||
|
||||
pFd = (TestvfsFile*)pFileDes;
|
||||
pFd = tvfsGetFd(pFile);
|
||||
p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 );
|
||||
|
||||
@ -749,7 +777,7 @@ static int tvfsShmMap(
|
||||
void volatile **pp /* OUT: Mapped memory */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){
|
||||
@ -784,7 +812,7 @@ static int tvfsShmLock(
|
||||
int flags
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
int nLock;
|
||||
char zLock[80];
|
||||
@ -819,7 +847,7 @@ static int tvfsShmLock(
|
||||
int isExcl = (flags & SQLITE_SHM_EXCLUSIVE);
|
||||
u32 mask = (((1<<n)-1) << ofst);
|
||||
if( isLock ){
|
||||
TestvfsFile *p2;
|
||||
TestvfsFd *p2;
|
||||
for(p2=pFd->pShm->pFile; p2; p2=p2->pNext){
|
||||
if( p2==pFd ) continue;
|
||||
if( (p2->excllock&mask) || (isExcl && p2->sharedlock&mask) ){
|
||||
@ -841,7 +869,7 @@ static int tvfsShmLock(
|
||||
}
|
||||
|
||||
static void tvfsShmBarrier(sqlite3_file *pFile){
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
|
||||
@ -856,10 +884,10 @@ static int tvfsShmClose(
|
||||
int deleteFlag
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
TestvfsFile *pFd = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
TestvfsBuffer *pBuffer = pFd->pShm;
|
||||
TestvfsFile **ppFd;
|
||||
TestvfsFd **ppFd;
|
||||
|
||||
assert( pFd->pShmId && pFd->pShm );
|
||||
|
||||
@ -1234,7 +1262,7 @@ static int testvfs_cmd(
|
||||
){
|
||||
static sqlite3_vfs tvfs_vfs = {
|
||||
2, /* iVersion */
|
||||
sizeof(TestvfsFile), /* szOsFile */
|
||||
0, /* szOsFile */
|
||||
0, /* mxPathname */
|
||||
0, /* pNext */
|
||||
0, /* zName */
|
||||
@ -1270,13 +1298,15 @@ static int testvfs_cmd(
|
||||
int i;
|
||||
int isNoshm = 0; /* True if -noshm is passed */
|
||||
int isDefault = 0; /* True if -default is passed */
|
||||
int szOsFile = 0; /* Value passed to -szosfile */
|
||||
int mxPathname = -1; /* Value passed to -mxpathname */
|
||||
|
||||
if( objc<2 || 0!=(objc%2) ) goto bad_args;
|
||||
for(i=2; i<objc; i += 2){
|
||||
int nSwitch;
|
||||
char *zSwitch;
|
||||
|
||||
zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch);
|
||||
|
||||
if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){
|
||||
return TCL_ERROR;
|
||||
@ -1287,11 +1317,25 @@ static int testvfs_cmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){
|
||||
if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){
|
||||
if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
else{
|
||||
goto bad_args;
|
||||
}
|
||||
}
|
||||
|
||||
if( szOsFile<sizeof(TestvfsFile) ){
|
||||
szOsFile = sizeof(TestvfsFile);
|
||||
}
|
||||
|
||||
zVfs = Tcl_GetString(objv[1]);
|
||||
nByte = sizeof(Testvfs) + strlen(zVfs)+1;
|
||||
p = (Testvfs *)ckalloc(nByte);
|
||||
@ -1317,7 +1361,10 @@ static int testvfs_cmd(
|
||||
pVfs->pAppData = (void *)p;
|
||||
pVfs->zName = p->zName;
|
||||
pVfs->mxPathname = p->pParent->mxPathname;
|
||||
pVfs->szOsFile += p->pParent->szOsFile;
|
||||
if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){
|
||||
pVfs->mxPathname = mxPathname;
|
||||
}
|
||||
pVfs->szOsFile = szOsFile;
|
||||
p->pVfs = pVfs;
|
||||
p->isNoshm = isNoshm;
|
||||
p->mask = TESTVFS_ALL_MASK;
|
||||
@ -1327,7 +1374,7 @@ static int testvfs_cmd(
|
||||
return TCL_OK;
|
||||
|
||||
bad_args:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL?");
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
245
test/pager1.test
245
test/pager1.test
@ -49,6 +49,15 @@ do_not_use_codec
|
||||
#
|
||||
# pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF"
|
||||
#
|
||||
# pager1-15.*: Varying sqlite3_vfs.szOsFile
|
||||
#
|
||||
# pager1-16.*: Varying sqlite3_vfs.mxPathname
|
||||
#
|
||||
# pager1-17.*: Tests related to "PRAGMA omit_readlock"
|
||||
#
|
||||
# pager1-18.*: Test that the pager layer responds correctly if the b-tree
|
||||
# requests an invalid page number (due to db corruption).
|
||||
#
|
||||
|
||||
set a_string_counter 1
|
||||
proc a_string {n} {
|
||||
@ -358,6 +367,10 @@ foreach {tn sql tcl} {
|
||||
# pager1.4.6.*: Test that when rolling back a hot-journal that contains a
|
||||
# master journal pointer, the master journal file is deleted
|
||||
# after all the hot-journals that refer to it are deleted.
|
||||
#
|
||||
# pager1.4.7.*: Test that if a hot-journal file exists but a client can
|
||||
# open it for reading only, the database cannot be accessed and
|
||||
# SQLITE_CANTOPEN is returned.
|
||||
#
|
||||
do_test pager1.4.1.1 {
|
||||
faultsim_delete_and_reopen
|
||||
@ -635,7 +648,6 @@ testvfs tv -default 1
|
||||
tv sectorsize 512
|
||||
tv script copy_on_journal_delete
|
||||
tv filter xDelete
|
||||
set ::mj_filename_length 0
|
||||
proc copy_on_journal_delete {method filename args} {
|
||||
if {[string match *journal $filename]} faultsim_save
|
||||
return SQLITE_OK
|
||||
@ -806,6 +818,43 @@ do_test pager1.4.6.15 { file exists $::mj_filename } {0}
|
||||
db close
|
||||
tv delete
|
||||
|
||||
testvfs tv -default 1
|
||||
tv sectorsize 512
|
||||
tv script copy_on_journal_delete
|
||||
tv filter xDelete
|
||||
proc copy_on_journal_delete {method filename args} {
|
||||
if {[string match *journal $filename]} faultsim_save
|
||||
return SQLITE_OK
|
||||
}
|
||||
faultsim_delete_and_reopen
|
||||
do_execsql_test pager1.4.7.1 {
|
||||
CREATE TABLE t1(x PRIMARY KEY, y);
|
||||
CREATE INDEX i1 ON t1(y);
|
||||
INSERT INTO t1 VALUES('I', 'one');
|
||||
INSERT INTO t1 VALUES('II', 'four');
|
||||
INSERT INTO t1 VALUES('III', 'nine');
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES('IV', 'sixteen');
|
||||
INSERT INTO t1 VALUES('V' , 'twentyfive');
|
||||
COMMIT;
|
||||
} {}
|
||||
tv filter {}
|
||||
db close
|
||||
tv delete
|
||||
do_test pager1.4.7.2 {
|
||||
faultsim_restore_and_reopen
|
||||
catch {file attributes test.db-journal -permissions r--------}
|
||||
catch {file attributes test.db-journal -readonly 1}
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} {1 {unable to open database file}}
|
||||
do_test pager1.4.7.3 {
|
||||
db close
|
||||
catch {file attributes test.db-journal -permissions rw-rw-rw-}
|
||||
catch {file attributes test.db-journal -readonly 0}
|
||||
file delete test.db-journal
|
||||
file exists test.db-journal
|
||||
} {0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests deal with multi-file commits.
|
||||
#
|
||||
@ -1055,6 +1104,7 @@ foreach {tn filename} {
|
||||
db close
|
||||
sqlite3 db $filename
|
||||
execsql {
|
||||
PRAGMA auto_vacuum = 1;
|
||||
CREATE TABLE x1(x);
|
||||
INSERT INTO x1 VALUES('Charles');
|
||||
INSERT INTO x1 VALUES('James');
|
||||
@ -1378,4 +1428,197 @@ do_execsql_test pager1-14.1.5 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2 3 4 2 2 4 4}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test opening and closing the pager sub-system with different values
|
||||
# for the sqlite3_vfs.szOsFile variable.
|
||||
#
|
||||
faultsim_delete_and_reopen
|
||||
do_execsql_test pager1-15.0 {
|
||||
CREATE TABLE tx(y, z);
|
||||
INSERT INTO tx VALUES('Ayutthaya', 'Beijing');
|
||||
INSERT INTO tx VALUES('London', 'Tokyo');
|
||||
} {}
|
||||
db close
|
||||
for {set i 0} {$i<513} {incr i 3} {
|
||||
testvfs tv -default 1 -szosfile $i
|
||||
sqlite3 db test.db
|
||||
do_execsql_test pager1-15.$i.1 {
|
||||
SELECT * FROM tx;
|
||||
} {Ayutthaya Beijing London Tokyo}
|
||||
db close
|
||||
tv delete
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that it is not possible to open a database file if the full path
|
||||
# to the associated journal file will be longer than sqlite3_vfs.mxPathname.
|
||||
#
|
||||
testvfs tv -default 1
|
||||
tv script xOpenCb
|
||||
tv filter xOpen
|
||||
proc xOpenCb {method filename} {
|
||||
set ::file_len [string length $filename]
|
||||
}
|
||||
sqlite3 db test.db
|
||||
db close
|
||||
tv delete
|
||||
|
||||
for {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} {
|
||||
testvfs tv -default 1 -mxpathname $ii
|
||||
|
||||
# The length of the full path to file "test.db-journal" is ($::file_len+8).
|
||||
# If the configured sqlite3_vfs.mxPathname value greater than or equal to
|
||||
# this, then the file can be opened. Otherwise, it cannot.
|
||||
#
|
||||
if {$ii >= [expr $::file_len+8]} {
|
||||
set res {0 {}}
|
||||
} else {
|
||||
set res {1 {unable to open database file}}
|
||||
}
|
||||
|
||||
do_test pager1-16.1.$ii {
|
||||
list [catch { sqlite3 db test.db } msg] $msg
|
||||
} $res
|
||||
|
||||
catch {db close}
|
||||
tv delete
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test "PRAGMA omit_readlock".
|
||||
#
|
||||
# pager1-17.$tn.1.*: Test that if a second connection has an open
|
||||
# read-transaction, it is not usually possible to write
|
||||
# the database.
|
||||
#
|
||||
# pager1-17.$tn.2.*: Test that if the second connection was opened with
|
||||
# the SQLITE_OPEN_READONLY flag, and
|
||||
# "PRAGMA omit_readlock = 1" is executed before attaching
|
||||
# the database and opening a read-transaction on it, it is
|
||||
# possible to write the db.
|
||||
#
|
||||
# pager1-17.$tn.3.*: Test that if the second connection was *not* opened with
|
||||
# the SQLITE_OPEN_READONLY flag, executing
|
||||
# "PRAGMA omit_readlock = 1" has no effect.
|
||||
#
|
||||
do_multiclient_test tn {
|
||||
do_test pager1-17.$tn.1.1 {
|
||||
sql1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
sql2 {
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2}
|
||||
do_test pager1-17.$tn.1.2 {
|
||||
csql1 { INSERT INTO t1 VALUES(3, 4) }
|
||||
} {1 {database is locked}}
|
||||
do_test pager1-17.$tn.1.3 {
|
||||
sql2 { COMMIT }
|
||||
sql1 { INSERT INTO t1 VALUES(3, 4) }
|
||||
} {}
|
||||
|
||||
do_test pager1-17.$tn.2.1 {
|
||||
code2 {
|
||||
db2 close
|
||||
sqlite3 db2 :memory: -readonly 1
|
||||
}
|
||||
sql2 {
|
||||
PRAGMA omit_readlock = 1;
|
||||
ATTACH 'test.db' AS two;
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4}
|
||||
do_test pager1-17.$tn.2.2 { sql1 "INSERT INTO t1 VALUES(5, 6)" } {}
|
||||
do_test pager1-17.$tn.2.3 { sql2 "SELECT * FROM t1" } {1 2 3 4}
|
||||
do_test pager1-17.$tn.2.4 { sql2 "COMMIT ; SELECT * FROM t1" } {1 2 3 4 5 6}
|
||||
|
||||
do_test pager1-17.$tn.3.1 {
|
||||
code2 {
|
||||
db2 close
|
||||
sqlite3 db2 :memory:
|
||||
}
|
||||
sql2 {
|
||||
PRAGMA omit_readlock = 1;
|
||||
ATTACH 'test.db' AS two;
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6}
|
||||
do_test pager1-17.$tn.3.2 {
|
||||
csql1 { INSERT INTO t1 VALUES(3, 4) }
|
||||
} {1 {database is locked}}
|
||||
do_test pager1-17.$tn.3.3 { sql2 COMMIT } {}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test the pagers response to the b-tree layer requesting illegal page
|
||||
# numbers:
|
||||
#
|
||||
# + The locking page,
|
||||
# + Page 0,
|
||||
# + A page with a page number greater than (2^31-1).
|
||||
#
|
||||
do_test pager1-18.1 {
|
||||
faultsim_delete_and_reopen
|
||||
db func a_string a_string
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(a_string(500), a_string(200));
|
||||
INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
|
||||
INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
|
||||
INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
|
||||
INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
|
||||
INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
|
||||
INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
|
||||
INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
|
||||
}
|
||||
} {}
|
||||
do_test pager1-18.2 {
|
||||
set root [db one "SELECT rootpage FROM sqlite_master"]
|
||||
set lockingpage [expr (0x10000/1024) + 1]
|
||||
execsql {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET rootpage = $lockingpage;
|
||||
}
|
||||
sqlite3 db2 test.db
|
||||
catchsql { SELECT count(*) FROM t1 } db2
|
||||
} {1 {database disk image is malformed}}
|
||||
db2 close
|
||||
do_test pager1-18.3 {
|
||||
execsql {
|
||||
CREATE TABLE t2(x);
|
||||
INSERT INTO t2 VALUES(a_string(5000));
|
||||
}
|
||||
set pgno [expr ([file size test.db] / 1024)-2]
|
||||
hexio_write test.db [expr ($pgno-1)*1024] 00000000
|
||||
sqlite3 db2 test.db
|
||||
catchsql { SELECT length(x) FROM t2 } db2
|
||||
} {1 {database disk image is malformed}}
|
||||
db2 close
|
||||
do_test pager1-18.4 {
|
||||
hexio_write test.db [expr ($pgno-1)*1024] 90000000
|
||||
sqlite3 db2 test.db
|
||||
catchsql { SELECT length(x) FROM t2 } db2
|
||||
} {1 {database disk image is malformed}}
|
||||
db2 close
|
||||
do_test pager1-18.5 {
|
||||
sqlite3 db ""
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1';
|
||||
PRAGMA writable_schema = 0;
|
||||
ALTER TABLE t1 RENAME TO x1;
|
||||
}
|
||||
catchsql { SELECT * FROM x1 }
|
||||
} {}
|
||||
db close
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -473,26 +473,29 @@ do_faultsim_test pagerfault-9.1 -prep {
|
||||
#-------------------------------------------------------------------------
|
||||
# Test fault injection with a temporary database file.
|
||||
#
|
||||
do_faultsim_test pagerfault-10 -prep {
|
||||
sqlite3 db ""
|
||||
db func a_string a_string;
|
||||
execsql {
|
||||
PRAGMA cache_size = 10;
|
||||
BEGIN;
|
||||
CREATE TABLE xx(a, b, UNIQUE(a, b));
|
||||
INSERT INTO xx VALUES(a_string(200), a_string(200));
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
COMMIT;
|
||||
foreach v {a b} {
|
||||
do_faultsim_test pagerfault-10$v -prep {
|
||||
sqlite3 db ""
|
||||
db func a_string a_string;
|
||||
execsql {
|
||||
PRAGMA cache_size = 10;
|
||||
BEGIN;
|
||||
CREATE TABLE xx(a, b, UNIQUE(a, b));
|
||||
INSERT INTO xx VALUES(a_string(200), a_string(200));
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
|
||||
COMMIT;
|
||||
}
|
||||
} -body {
|
||||
execsql { UPDATE xx SET a = a_string(300) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
if {$::v == "b"} { execsql { PRAGMA journal_mode = TRUNCATE } }
|
||||
faultsim_integrity_check
|
||||
faultsim_integrity_check
|
||||
}
|
||||
} -body {
|
||||
execsql { UPDATE xx SET a = a_string(300) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
faultsim_integrity_check
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -542,8 +545,10 @@ do_faultsim_test pagerfault-11 -prep {
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test fault injection when writing to a database file that resides on
|
||||
# a file-system with a sector-size larger than the database page-size.
|
||||
#
|
||||
do_test pagerfault-12-pre1 {
|
||||
testvfs ss_layer -default 1
|
||||
ss_layer sectorsize 4096
|
||||
@ -580,5 +585,31 @@ do_faultsim_test pagerfault-12 -prep {
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_test pagerfault-13-pre1 {
|
||||
faultsim_delete_and_reopen
|
||||
db func a_string a_string;
|
||||
execsql {
|
||||
PRAGMA journal_mode = PERSIST;
|
||||
BEGIN;
|
||||
CREATE TABLE t1(x, y UNIQUE);
|
||||
INSERT INTO t1 VALUES(a_string(333), a_string(444));
|
||||
COMMIT;
|
||||
}
|
||||
db close
|
||||
file delete -force test.db
|
||||
faultsim_save
|
||||
} {}
|
||||
do_faultsim_test pagerfault-13 -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql { CREATE TABLE xx(a, b) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
Loading…
x
Reference in New Issue
Block a user