From 146ed78b7818b43845ae44d3cbb12c7c80183be5 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Jun 2010 17:26:37 +0000 Subject: [PATCH] Add tests to pager1.test and pagerfault.test. FossilOrigin-Name: f5df83fd875073eee8e2269e87e2a8c9c7abc981 --- manifest | 18 ++--- manifest.uuid | 2 +- src/test_vfs.c | 75 ++++++++++++++---- test/malloc_common.tcl | 27 +++++++ test/pager1.test | 169 +++++++++++++++++++++++++++++++++++++++++ test/pagerfault.test | 49 +++++++++++- test/permutations.test | 1 + 7 files changed, 317 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index 9af221bb21..d122597b86 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ C Add\stests\sto\spager1.test\sand\spagerfault.test. -D 2010-06-19T11:30:41 +D 2010-06-19T17:26:37 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 687ba8db7830909955896488a66d3c6b655827f0 +F src/test_vfs.c abdf6881beac76cbc54d2586cd092b2b4ed3a217 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb F src/trigger.c 8927588cb9e6d47f933b53bfe74200fbb504100d @@ -509,7 +509,7 @@ F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb F test/mallocI.test e3ea401904d010cb7c1e4b2ee8803f4a9f5b999d F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9 -F test/malloc_common.tcl fbf369eb2828825c5f319c101917aff91ea87556 +F test/malloc_common.tcl 4981dd86adf0d3f25c755ac3a425d6208fda6362 F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c F test/memdb.test 0825155b2290e900264daaaf0334b6dfe69ea498 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 @@ -534,13 +534,13 @@ F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec -F test/pager1.test d71580a4f358276520192f21fa2be4b8930bce86 -F test/pagerfault.test 424b0bbb3d458d36a94dfec89b05b0eab4d99ac8 +F test/pager1.test 2842b3567589fc4881928a7febeb9342442ea449 +F test/pagerfault.test 55c7d602eaba7c08312616a4c6482606d50eed6a F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb F test/pcache.test eebc4420b37cb07733ae9b6e99c9da7c40dd6d58 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16 -F test/permutations.test f044eaba204ff13d530ceb72a22b0ed2c43562ef +F test/permutations.test 97cfca3f7c390fa530c6f5c63d73eb67e5b0cd9d F test/pragma.test 6960f9efbce476f70ba9ee2171daf5042f9e3d8a F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea @@ -824,7 +824,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 582fca89195af54e9668af249691654cfea63d04 -R fbd44aafb92e6601ec3f8830a20d8a05 +P 58c0b5bfed8c67cc3f2f4a6784d08c14e652c265 +R 86313cbaab41f6821959bc241c636465 U dan -Z 2ad8778b11d258070a4981dade837d10 +Z a6c0e379ae1464c418b51e1bd6121ef1 diff --git a/manifest.uuid b/manifest.uuid index 9a73ee0908..8f8bbb9acb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -58c0b5bfed8c67cc3f2f4a6784d08c14e652c265 \ No newline at end of file +f5df83fd875073eee8e2269e87e2a8c9c7abc981 \ No newline at end of file diff --git a/src/test_vfs.c b/src/test_vfs.c index 8a0095d87d..2d4dad7867 100644 --- a/src/test_vfs.c +++ b/src/test_vfs.c @@ -59,6 +59,10 @@ struct Testvfs { int ioerr; int nIoerrFail; + int iFullCnt; + int fullerr; + int nFullFail; + int iDevchar; int iSectorsize; }; @@ -193,6 +197,30 @@ static int tvfsResultCode(Testvfs *p, int *pRc){ return 0; } +static int tvfsInjectIoerr(Testvfs *p){ + int ret = 0; + if( p->ioerr ){ + p->iIoerrCnt--; + if( p->iIoerrCnt==0 || (p->iIoerrCnt<0 && p->ioerr==2) ){ + ret = 1; + p->nIoerrFail++; + } + } + return ret; +} + +static int tvfsInjectFullerr(Testvfs *p){ + int ret = 0; + if( p->fullerr ){ + p->iFullCnt--; + if( p->iFullCnt<=0 ){ + ret = 1; + p->nFullFail++; + } + } + return ret; +} + static void tvfsExecTcl( Testvfs *p, @@ -302,6 +330,8 @@ static int tvfsWrite( ); tvfsResultCode(p, &rc); } + + if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL; if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst); @@ -365,6 +395,8 @@ static int tvfsSync(sqlite3_file *pFile, int flags){ tvfsResultCode(p, &rc); } + if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL; + if( rc==SQLITE_OK ){ rc = sqlite3OsSync(pFd->pReal, flags); } @@ -603,18 +635,6 @@ static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); } -static int tvfsInjectIoerr(Testvfs *p){ - int ret = 0; - if( p->ioerr ){ - p->iIoerrCnt--; - if( p->iIoerrCnt==0 || (p->iIoerrCnt<0 && p->ioerr==2) ){ - ret = 1; - p->nIoerrFail++; - } - } - return ret; -} - static int tvfsShmOpen( sqlite3_file *pFileDes ){ @@ -832,7 +852,7 @@ static int testvfs_obj_cmd( enum DB_enum { CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT, - CMD_DEVCHAR, CMD_SECTORSIZE + CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR }; struct TestvfsSubcmd { char *zName; @@ -842,6 +862,7 @@ static int testvfs_obj_cmd( { "delete", CMD_DELETE }, { "filter", CMD_FILTER }, { "ioerr", CMD_IOERR }, + { "fullerr", CMD_FULLERR }, { "script", CMD_SCRIPT }, { "devchar", CMD_DEVCHAR }, { "sectorsize", CMD_SECTORSIZE }, @@ -978,6 +999,34 @@ 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? ** diff --git a/test/malloc_common.tcl b/test/malloc_common.tcl index a24716cd4a..dc68b1b53a 100644 --- a/test/malloc_common.tcl +++ b/test/malloc_common.tcl @@ -49,6 +49,16 @@ set FAULTSIM(ioerr-persistent) [list \ -injecterrlist {{1 {disk I/O error}}} \ ] +# SQLITE_FULL errors (always persistent): +# +set FAULTSIM(full) [list \ + -injectinstall fullerr_injectinstall \ + -injectstart fullerr_injectstart \ + -injectstop fullerr_injectstop \ + -injecterrlist {{1 {database or disk is full}}} \ + -injectuninstall fullerr_injectuninstall \ +] + # Transient and persistent SHM errors: # set FAULTSIM(shmerr-transient) [list \ @@ -177,6 +187,7 @@ proc ioerr_injectstop {} { return $sv } + # The following procs are used as [do_one_faultsim_test] callbacks when # injecting shared-memory related error faults into test cases. # @@ -195,6 +206,22 @@ proc shmerr_injectstop {} { shmfault ioerr 0 0 } +proc fullerr_injectinstall {} { + testvfs shmfault -default true +} +proc fullerr_injectuninstall {} { + catch {db close} + catch {db2 close} + shmfault delete +} +proc fullerr_injectstart {iFail} { + shmfault full $iFail +} +proc fullerr_injectstop {} { + shmfault full 0 +} + + # This command is not called directly. It is used by the # [faultsim_test_result] command created by [do_faultsim_test] and used # by -test scripts. diff --git a/test/pager1.test b/test/pager1.test index 4ef921e5e4..33b5c2ae04 100644 --- a/test/pager1.test +++ b/test/pager1.test @@ -26,6 +26,8 @@ source $testdir/malloc_common.tcl # # pager1-5.*: Cases related to multi-file commits. # +# pager1-6.*: Cases related to "PRAGMA max_page_count" +# proc do_execsql_test {testname sql result} { uplevel do_test $testname [list "execsql {$sql}"] [list $result] @@ -221,6 +223,12 @@ foreach code [list { } { set s 1024 set sql { PRAGMA journal_mode = memory } +} { + set s 1024 + set sql { + PRAGMA journal_mode = memory; + PRAGMA locking_mode = exclusive; + } } { set s 2048 tv devchar safe_append @@ -449,7 +457,168 @@ foreach {tn ofst value result} { db close #------------------------------------------------------------------------- +# The following tests deal with multi-file commits. # +# pager1-5.1.*: The case where a multi-file cannot be committed because +# another connection is holding a SHARED lock on one of the +# files. After the SHARED lock is removed, the COMMIT succeeds. +# +# pager1-5.2.*: Multi-file commits with journal_mode=memory. +# +# pager1-5.3.*: Multi-file commits with journal_mode=memory. +# +# pager1-5.4.*: Check that with synchronous=normal, the master-journal file +# name is added to a journal file immediately after the last +# journal record. But with synchronous=full, extra unused space +# is allocated between the last journal record and the +# master-journal file name so that the master-journal file +# name does not lie on the same sector as the last journal file +# record. +# +# pager1-5.5.*: +# +do_test pager1-5.1.1 { + faultsim_delete_and_reopen + execsql { + ATTACH 'test.db2' AS aux; + CREATE TABLE t1(a, b); + CREATE TABLE aux.t2(a, b); + INSERT INTO t1 VALUES(17, 'Lenin'); + INSERT INTO t1 VALUES(22, 'Stalin'); + INSERT INTO t1 VALUES(53, 'Khrushchev'); + } +} {} +do_test pager1-5.1.2 { + execsql { + BEGIN; + INSERT INTO t1 VALUES(64, 'Brezhnev'); + INSERT INTO t2 SELECT * FROM t1; + } + sqlite3 db2 test.db2 + execsql { + BEGIN; + SELECT * FROM t2; + } db2 +} {} +do_test pager1-5.1.3 { + catchsql COMMIT +} {1 {database is locked}} +do_test pager1-5.1.4 { + execsql COMMIT db2 + execsql COMMIT + execsql { SELECT * FROM t2 } db2 +} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev} +do_test pager1-5.1.5 { + db2 close +} {} + +do_test pager1-5.2.1 { + execsql { + PRAGMA journal_mode = memory; + BEGIN; + INSERT INTO t1 VALUES(84, 'Andropov'); + INSERT INTO t2 VALUES(84, 'Andropov'); + COMMIT; + } +} {memory} +do_test pager1-5.3.1 { + execsql { + PRAGMA journal_mode = off; + BEGIN; + INSERT INTO t1 VALUES(85, 'Gorbachev'); + INSERT INTO t2 VALUES(85, 'Gorbachev'); + COMMIT; + } +} {off} + +do_test pager1-5.4.1 { + db close + testvfs tv + sqlite3 db test.db -vfs tv + execsql { ATTACH 'test.db2' AS aux } + + tv filter xDelete + tv script max_journal_size + tv sectorsize 512 + set ::max_journal 0 + proc max_journal_size {method args} { + set sz 0 + catch { set sz [file size test.db-journal] } + if {$sz > $::max_journal} { + set ::max_journal $sz + } + return SQLITE_OK + } + execsql { + PRAGMA journal_mode = DELETE; + PRAGMA synchronous = NORMAL; + BEGIN; + INSERT INTO t1 VALUES(85, 'Gorbachev'); + INSERT INTO t2 VALUES(85, 'Gorbachev'); + COMMIT; + } + set ::max_journal +} [expr 2615+[string length [pwd]]] +do_test pager1-5.4.2 { + set ::max_journal 0 + execsql { + PRAGMA synchronous = full; + BEGIN; + DELETE FROM t1 WHERE b = 'Lenin'; + DELETE FROM t2 WHERE b = 'Lenin'; + COMMIT; + } + set ::max_journal +} [expr 3111+[string length [pwd]]] +db close +tv delete + +do_test pager1-5.5.1 { + sqlite3 db test.db + execsql { + ATTACH 'test.db2' AS aux; + PRAGMA journal_mode = PERSIST; + CREATE TABLE t3(a, b); + INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1; + UPDATE t3 SET b = randomblob(1500); + } + expr [file size test.db-journal] > 15000 +} {1} +do_test pager1-5.5.2 { + execsql { + PRAGMA synchronous = full; + BEGIN; + DELETE FROM t1 WHERE b = 'Stalin'; + DELETE FROM t2 WHERE b = 'Stalin'; + COMMIT; + } + file size test.db-journal +} {0} + + +#------------------------------------------------------------------------- +# The following tests work with "PRAGMA max_page_count" +# +do_test pager1-6.1 { + faultsim_delete_and_reopen + execsql { + PRAGMA max_page_count = 10; + CREATE TABLE t2(a, b); + CREATE TABLE t3(a, b); + CREATE TABLE t4(a, b); + CREATE TABLE t5(a, b); + CREATE TABLE t6(a, b); + CREATE TABLE t7(a, b); + CREATE TABLE t8(a, b); + CREATE TABLE t9(a, b); + CREATE TABLE t10(a, b); + } +} {10} +do_test pager1-6.2 { + catchsql { + CREATE TABLE t11(a, b); + } +} {1 {database or disk is full}} finish_test diff --git a/test/pagerfault.test b/test/pagerfault.test index ed781b5b59..81a62ed7ea 100644 --- a/test/pagerfault.test +++ b/test/pagerfault.test @@ -179,6 +179,12 @@ do_faultsim_test pagerfault-4 -prep { #------------------------------------------------------------------------- # Test fault-injection as part of a commit when using journal_mode=PERSIST. +# Three different cases: +# +# pagerfault-5.1: With no journal_size_limit configured. +# pagerfault-5.2: With a journal_size_limit configured. +# pagerfault-5.4: Multi-file transaction. One connection has a +# journal_size_limit of 0, the other has no limit. # do_test pagerfault-5-pre1 { faultsim_delete_and_reopen @@ -214,7 +220,6 @@ do_faultsim_test pagerfault-5.2 -prep { faultsim_test_result {0 {}} faultsim_integrity_check } - do_faultsim_test pagerfault-5.3 -prep { faultsim_restore_and_reopen db func a_string a_string @@ -236,4 +241,46 @@ do_faultsim_test pagerfault-5.3 -prep { faultsim_test_result {0 {}} } +# The following was an attempt to get a bitvec malloc to fail. Didn't work. +# +# do_test pagerfault-6-pre1 { +# faultsim_delete_and_reopen +# execsql { +# CREATE TABLE t1(x, y, UNIQUE(x, y)); +# INSERT INTO t1 VALUES(1, randomblob(1501)); +# INSERT INTO t1 VALUES(2, randomblob(1502)); +# INSERT INTO t1 VALUES(3, randomblob(1503)); +# INSERT INTO t1 VALUES(4, randomblob(1504)); +# INSERT INTO t1 +# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; +# INSERT INTO t1 +# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; +# INSERT INTO t1 +# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; +# INSERT INTO t1 +# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; +# } +# faultsim_save_and_close +# } {} +# do_faultsim_test pagerfault-6 -prep { +# faultsim_restore_and_reopen +# } -body { +# execsql { +# BEGIN; +# UPDATE t1 SET x=x+4 WHERE x=1; +# SAVEPOINT one; +# UPDATE t1 SET x=x+4 WHERE x=2; +# SAVEPOINT three; +# UPDATE t1 SET x=x+4 WHERE x=3; +# SAVEPOINT four; +# UPDATE t1 SET x=x+4 WHERE x=4; +# RELEASE three; +# COMMIT; +# SELECT DISTINCT x FROM t1; +# } +# } -test { +# faultsim_test_result {0 {5 6 7 8}} +# faultsim_integrity_check +# } + finish_test diff --git a/test/permutations.test b/test/permutations.test index 921df33a47..27f795676a 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -170,6 +170,7 @@ test_suite "coverage-pager" -description { } -files { pager1.test pagerfault.test + journal2.test }