| Index: third_party/sqlite/src/test/pagerfault.test | 
| diff --git a/third_party/sqlite/src/test/pagerfault.test b/third_party/sqlite/src/test/pagerfault.test | 
| index c5c7d3b33acdc4e987ac0a08f6b1928a08f4d416..c0f5de69acc0a6a0bed37bc8157e5fb4c9214e4f 100644 | 
| --- a/third_party/sqlite/src/test/pagerfault.test | 
| +++ b/third_party/sqlite/src/test/pagerfault.test | 
| @@ -20,6 +20,11 @@ if {[permutation] == "inmemory_journal"} { | 
| return | 
| } | 
|  | 
| +if {$::tcl_platform(platform)=="windows"} { | 
| +  finish_test | 
| +  return | 
| +} | 
| + | 
| set a_string_counter 1 | 
| proc a_string {n} { | 
| global a_string_counter | 
| @@ -228,7 +233,7 @@ do_faultsim_test pagerfault-5.2 -prep { | 
| do_faultsim_test pagerfault-5.3 -faults oom-transient -prep { | 
| faultsim_restore_and_reopen | 
| db func a_string a_string | 
| -  file delete -force test2.db test2.db-journal test2.db-wal | 
| +  forcedelete test2.db test2.db-journal test2.db-wal | 
| execsql { | 
| PRAGMA journal_mode = PERSIST; | 
| ATTACH 'test2.db' AS aux; | 
| @@ -636,7 +641,7 @@ do_test pagerfault-13-pre1 { | 
| COMMIT; | 
| } | 
| db close | 
| -  file delete -force test.db | 
| +  forcedelete test.db | 
| faultsim_save | 
| } {} | 
| do_faultsim_test pagerfault-13 -prep { | 
| @@ -1101,7 +1106,7 @@ do_faultsim_test pagerfault-22 -prep { | 
| # | 
| do_faultsim_test pagerfault-23 -prep { | 
| sqlite3 db :memory: | 
| -  foreach f [glob -nocomplain test.db*] { file delete -force $f } | 
| +  foreach f [glob -nocomplain test.db*] { forcedelete $f } | 
| db eval { | 
| ATTACH 'test.db2' AS aux; | 
| CREATE TABLE t1(a, b); | 
| @@ -1241,5 +1246,304 @@ do_faultsim_test pagerfault-27 -faults ioerr-persistent -prep { | 
| faultsim_integrity_check | 
| } | 
|  | 
| -finish_test | 
|  | 
| +#------------------------------------------------------------------------- | 
| +# | 
| +do_test pagerfault-28-pre { | 
| +  faultsim_delete_and_reopen | 
| +  db func a_string a_string | 
| +  execsql { | 
| +    PRAGMA page_size = 512; | 
| + | 
| +    PRAGMA journal_mode = wal; | 
| +    PRAGMA wal_autocheckpoint = 0; | 
| +    PRAGMA cache_size = 100000; | 
| + | 
| +    BEGIN; | 
| +      CREATE TABLE t2(a UNIQUE, b UNIQUE); | 
| +      INSERT INTO t2 VALUES( a_string(800), a_string(800) ); | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +    COMMIT; | 
| +    CREATE TABLE t1(a PRIMARY KEY, b); | 
| +  } | 
| +  expr {[file size test.db-shm] >= 96*1024} | 
| +} {1} | 
| +faultsim_save_and_close | 
| + | 
| +do_faultsim_test pagerfault-28a -faults oom* -prep { | 
| +  faultsim_restore_and_reopen | 
| +  execsql { PRAGMA mmap_size=0 } | 
| + | 
| +  sqlite3 db2 test.db | 
| +  db2 eval { SELECT count(*) FROM t2 } | 
| + | 
| +  db func a_string a_string | 
| +  execsql { | 
| +    BEGIN; | 
| +      INSERT INTO t1 VALUES(a_string(2000), a_string(2000)); | 
| +      INSERT INTO t1 VALUES(a_string(2000), a_string(2000)); | 
| +  } | 
| +  set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY a" -1 DUMMY] | 
| +  sqlite3_step $::STMT | 
| +} -body { | 
| +  execsql { ROLLBACK } | 
| +} -test { | 
| +  db2 close | 
| +  sqlite3_finalize $::STMT | 
| +  catchsql { ROLLBACK } | 
| +  faultsim_integrity_check | 
| +} | 
| + | 
| +faultsim_restore_and_reopen | 
| +sqlite3 db2 test.db | 
| +db2 eval {SELECT count(*) FROM t2} | 
| +db close | 
| + | 
| +do_faultsim_test pagerfault-28b -faults oom* -prep { | 
| +  sqlite3 db test.db | 
| +} -body { | 
| +  execsql { SELECT count(*) FROM t2 } | 
| +} -test { | 
| +  faultsim_test_result {0 2048} | 
| +  db close | 
| +} | 
| + | 
| +db2 close | 
| + | 
| +#------------------------------------------------------------------------- | 
| +# Try this: | 
| +# | 
| +#    1) Put the pager in ERROR state (error during rollback) | 
| +# | 
| +#    2) Next time the connection is used inject errors into all xWrite() and | 
| +#       xUnlock() calls. This causes the hot-journal rollback to fail and | 
| +#       the pager to declare its locking state UNKNOWN. | 
| +# | 
| +#    3) Same again. | 
| +# | 
| +#    4a) Stop injecting errors. Allow the rollback to succeed. Check that | 
| +#        the database is Ok. Or, | 
| +# | 
| +#    4b) Close and reopen the db. Check that the db is Ok. | 
| +# | 
| +proc custom_injectinstall {} { | 
| +  testvfs custom -default true | 
| +  custom filter {xWrite xUnlock} | 
| +} | 
| +proc custom_injectuninstall {} { | 
| +  catch {db  close} | 
| +  catch {db2 close} | 
| +  custom delete | 
| +} | 
| +proc custom_injectstart {iFail} { | 
| +  custom ioerr $iFail 1 | 
| +} | 
| +proc custom_injectstop {} { | 
| +  custom ioerr | 
| +} | 
| +set ::FAULTSIM(custom)          [list      \ | 
| +  -injectinstall   custom_injectinstall    \ | 
| +  -injectstart     custom_injectstart      \ | 
| +  -injectstop      custom_injectstop       \ | 
| +  -injecterrlist   {{1 {disk I/O error}}}  \ | 
| +  -injectuninstall custom_injectuninstall  \ | 
| +] | 
| + | 
| +do_test pagerfault-29-pre { | 
| +  faultsim_delete_and_reopen | 
| +  db func a_string a_string | 
| +  execsql { | 
| +    PRAGMA page_size = 1024; | 
| +    PRAGMA cache_size = 5; | 
| + | 
| +    BEGIN; | 
| +      CREATE TABLE t2(a UNIQUE, b UNIQUE); | 
| +      INSERT INTO t2 VALUES( a_string(800), a_string(800) ); | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | 
| +    COMMIT; | 
| +  } | 
| +  expr {[file size test.db] >= 50*1024} | 
| +} {1} | 
| +faultsim_save_and_close | 
| +foreach {tn tt} { | 
| +  29 { catchsql ROLLBACK } | 
| +  30 { db close ; sqlite3 db test.db } | 
| +} { | 
| +  do_faultsim_test pagerfault-$tn -faults custom -prep { | 
| +    faultsim_restore_and_reopen | 
| +      db func a_string a_string | 
| +      execsql { | 
| +        PRAGMA cache_size = 5; | 
| +        BEGIN; | 
| +        UPDATE t2 SET a = a_string(799); | 
| +      } | 
| +  } -body { | 
| +    catchsql ROLLBACK | 
| +    catchsql ROLLBACK | 
| +    catchsql ROLLBACK | 
| +  } -test { | 
| +    eval $::tt | 
| +    if {"ok" != [db one {PRAGMA integrity_check}]} { | 
| +      error "integrity check failed" | 
| +    } | 
| +  } | 
| +} | 
| + | 
| +do_test pagerfault-31-pre { | 
| +  sqlite3_shutdown | 
| +  sqlite3_config_uri 1 | 
| +} {SQLITE_OK} | 
| +do_faultsim_test pagerfault-31 -faults oom* -body { | 
| +  sqlite3 db {file:one?mode=memory&cache=shared} | 
| +  db eval { | 
| +    CREATE TABLE t1(x); | 
| +    INSERT INTO t1 VALUES(1); | 
| +    SELECT * FROM t1; | 
| +  } | 
| +} -test { | 
| +  faultsim_test_result {0 1} {1 {}} | 
| +  catch { db close } | 
| +} | 
| +sqlite3_shutdown | 
| +sqlite3_config_uri 0 | 
| + | 
| +do_test pagerfault-32-pre { | 
| +  reset_db | 
| +  execsql { | 
| +    CREATE TABLE t1(x); | 
| +    INSERT INTO t1 VALUES('one'); | 
| +  } | 
| +} {} | 
| +faultsim_save_and_close | 
| + | 
| +do_faultsim_test pagerfault-32 -prep { | 
| +  faultsim_restore_and_reopen | 
| +  db eval { SELECT * FROM t1; } | 
| +} -body { | 
| +  execsql { SELECT * FROM t1; } | 
| +} -test { | 
| +  faultsim_test_result {0 one} | 
| +} | 
| +sqlite3_shutdown | 
| +sqlite3_config_uri 0 | 
| + | 
| +do_faultsim_test pagerfault-33a -prep { | 
| +  sqlite3 db :memory: | 
| +  execsql { | 
| +    CREATE TABLE t1(a, b); | 
| +    INSERT INTO t1 VALUES(1, 2); | 
| +  } | 
| +} -body { | 
| +  execsql { VACUUM } | 
| +} -test { | 
| +  faultsim_test_result {0 {}} | 
| +} | 
| +do_faultsim_test pagerfault-33b -prep { | 
| +  sqlite3 db "" | 
| +  execsql { | 
| +    CREATE TABLE t1(a, b); | 
| +    INSERT INTO t1 VALUES(1, 2); | 
| +  } | 
| +} -body { | 
| +  execsql { VACUUM } | 
| +} -test { | 
| +  faultsim_test_result {0 {}} | 
| +} | 
| + | 
| +do_test pagerfault-34-pre { | 
| +  reset_db | 
| +  execsql { | 
| +    CREATE TABLE t1(x PRIMARY KEY); | 
| +  } | 
| +} {} | 
| +faultsim_save_and_close | 
| +do_faultsim_test pagerfault-34 -prep { | 
| +  faultsim_restore_and_reopen | 
| +  execsql { | 
| +    BEGIN; | 
| +      INSERT INTO t1 VALUES( randomblob(4000) ); | 
| +      DELETE FROM t1; | 
| +  } | 
| +} -body { | 
| +  execsql COMMIT | 
| +} -test { | 
| +  faultsim_test_result {0 {}} | 
| +} | 
| + | 
| +do_test pagerfault-35-pre { | 
| +  faultsim_delete_and_reopen | 
| +  execsql { | 
| +    CREATE TABLE t1(x PRIMARY KEY, y); | 
| +    INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); | 
| +    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | 
| +    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | 
| +    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | 
| +  } | 
| +  faultsim_save_and_close | 
| +} {} | 
| +testvfs tv -default 1 | 
| +tv sectorsize 8192; | 
| +tv devchar [list] | 
| +do_faultsim_test pagerfault-35 -prep { | 
| +  faultsim_restore_and_reopen | 
| +} -body { | 
| +  execsql { UPDATE t1 SET x=randomblob(200) } | 
| +} -test { | 
| +  faultsim_test_result {0 {}} | 
| +} | 
| +catch {db close} | 
| +tv delete | 
| + | 
| +sqlite3_shutdown | 
| +sqlite3_config_uri 1 | 
| +do_test pagerfault-36-pre { | 
| +  faultsim_delete_and_reopen | 
| +  execsql { | 
| +    CREATE TABLE t1(x PRIMARY KEY, y); | 
| +    INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); | 
| +    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | 
| +    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | 
| +    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | 
| +  } | 
| +  faultsim_save_and_close | 
| +} {} | 
| +do_faultsim_test pagerfault-36 -prep { | 
| +  faultsim_restore | 
| +  sqlite3 db file:test.db?cache=shared | 
| +  sqlite3 db2 file:test.db?cache=shared | 
| +  db2 eval { | 
| +    BEGIN; | 
| +    SELECT count(*) FROM sqlite_master; | 
| +  } | 
| +  db eval { | 
| +    PRAGMA cache_size = 1; | 
| +    BEGIN; | 
| +      UPDATE t1 SET x = randomblob(200); | 
| +  } | 
| +} -body { | 
| +  execsql ROLLBACK db | 
| +} -test { | 
| +  catch { db eval {UPDATE t1 SET x = randomblob(200)} } | 
| +  faultsim_test_result {0 {}} | 
| +  catch { db close } | 
| +  catch { db2 close } | 
| +} | 
| + | 
| +sqlite3_shutdown | 
| +sqlite3_config_uri 0 | 
| +sqlite3_initialize | 
| + | 
| +finish_test | 
|  |