-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
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
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
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
-6b7e419ddc241f457dd69878f09f5c51c70aa379
\ No newline at end of file
+008513ee6115f8d6f4b4e1428c1c638282b971a3
\ No newline at end of file
*/
#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"
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 */
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
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 */
};
** 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 ){
if( pFile->pMethods ){
ckfree((char *)pFile->pMethods);
}
- return sqlite3OsClose(pFd->pReal);
+ rc = sqlite3OsClose(pFd->pReal);
+ ckfree((char *)pFd);
+ pTestfile->pFd = 0;
+ return rc;
}
/*
int iAmt,
sqlite_int64 iOfst
){
- TestvfsFile *p = (TestvfsFile *)pFile;
+ TestvfsFd *p = tvfsGetFd(pFile);
return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
}
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 ){
*/
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 ){
*/
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 ){
** 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);
}
** 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);
}
** 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);
}
** 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);
}
** 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);
}
** 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;
** 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;
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:
**
pFd->pShmId = pId;
Tcl_ResetResult(p->interp);
-
rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags);
if( pFd->pReal->pMethods ){
sqlite3_io_methods *pMethods;
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 );
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 ){
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];
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) ){
}
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 ){
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 );
){
static sqlite3_vfs tvfs_vfs = {
2, /* iVersion */
- sizeof(TestvfsFile), /* szOsFile */
+ 0, /* szOsFile */
0, /* mxPathname */
0, /* pNext */
0, /* zName */
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;
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);
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;
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;
}
#
# 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} {
# 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
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
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.
#
db close
sqlite3 db $filename
execsql {
+ PRAGMA auto_vacuum = 1;
CREATE TABLE x1(x);
INSERT INTO x1 VALUES('Charles');
INSERT INTO x1 VALUES('James');
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
+
#-------------------------------------------------------------------------
# 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
}
#-------------------------------------------------------------------------
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
}
+#-------------------------------------------------------------------------
+#
+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