| OLD | NEW | 
| (Empty) |  | 
 |    1 # 2011 December 16 | 
 |    2 # | 
 |    3 # The author disclaims copyright to this source code.  In place of | 
 |    4 # a legal notice, here is a blessing: | 
 |    5 # | 
 |    6 #    May you do good and not evil. | 
 |    7 #    May you find forgiveness for yourself and forgive others. | 
 |    8 #    May you share freely, never taking more than you give. | 
 |    9 # | 
 |   10 #*********************************************************************** | 
 |   11 # | 
 |   12 # This test simulates an application crash immediately following a | 
 |   13 # system call to truncate a file. Specifically, the system call that | 
 |   14 # truncates the WAL file if "PRAGMA journal_size_limit" is configured. | 
 |   15 # | 
 |   16  | 
 |   17 set testdir [file dirname $argv0] | 
 |   18 source $testdir/tester.tcl | 
 |   19  | 
 |   20 ifcapable !wal {finish_test ; return } | 
 |   21 set testprefix walcrash3 | 
 |   22  | 
 |   23 db close | 
 |   24 testvfs tvfs | 
 |   25 tvfs filter {xTruncate xWrite} | 
 |   26 tvfs script tvfs_callback | 
 |   27 proc tvfs_callback {args} {} | 
 |   28  | 
 |   29 sqlite3 db test.db -vfs tvfs | 
 |   30 do_execsql_test 1.1 { | 
 |   31   PRAGMA page_size = 1024; | 
 |   32   PRAGMA journal_mode = WAL; | 
 |   33   PRAGMA wal_autocheckpoint = 128; | 
 |   34   PRAGMA journal_size_limit = 16384; | 
 |   35  | 
 |   36   CREATE TABLE t1(a BLOB, b BLOB, UNIQUE(a, b)); | 
 |   37   INSERT INTO t1 VALUES(randomblob(10), randomblob(1000)); | 
 |   38 } {wal 128 16384} | 
 |   39  | 
 |   40 proc tvfs_callback {method file arglist} { | 
 |   41   if {$::state==1} { | 
 |   42     foreach f [glob -nocomplain xx_test.*] { forcedelete $f } | 
 |   43     foreach f [glob -nocomplain test.*]    { forcecopy $f "xx_$f" } | 
 |   44     set ::state 2 | 
 |   45   } | 
 |   46   if {$::state==0 && $method=="xTruncate" && [file tail $file]=="test.db-wal"} { | 
 |   47     set ::state 1 | 
 |   48   } | 
 |   49 } | 
 |   50  | 
 |   51 for {set i 2} {$i<1000} {incr i} { | 
 |   52  | 
 |   53   # If the WAL file is truncated within the following, within the following | 
 |   54   # xWrite call the [tvfs_callback] makes a copy of the database and WAL  | 
 |   55   # files set sets $::state to 2. So that the copied files are in the same | 
 |   56   # state as the real database and WAL files would be if an application crash  | 
 |   57   # occurred immediately following the xTruncate(). | 
 |   58   #  | 
 |   59   set ::state 0 | 
 |   60   do_execsql_test 1.$i.1 { | 
 |   61     INSERT INTO t1 VALUES(randomblob(10), randomblob(1000)); | 
 |   62   } | 
 |   63  | 
 |   64   # If a copy was made, open it and run the integrity-check. | 
 |   65   # | 
 |   66   if {$::state==2} { | 
 |   67     sqlite3 db2 xx_test.db | 
 |   68     do_test 1.$i.2 { execsql { PRAGMA integrity_check  } db2 } "ok" | 
 |   69     do_test 1.$i.3 { execsql { SELECT count(*) FROM t1 } db2 } [expr $i-1] | 
 |   70     db2 close | 
 |   71   } | 
 |   72 } | 
 |   73 catch { db close } | 
 |   74 tvfs delete | 
 |   75  | 
 |   76 #-------------------------------------------------------------------------- | 
 |   77 # | 
 |   78 catch { db close } | 
 |   79 forcedelete test.db | 
 |   80  | 
 |   81 do_test 2.1 { | 
 |   82   sqlite3 db test.db | 
 |   83   execsql { | 
 |   84     PRAGMA page_size = 512; | 
 |   85     PRAGMA journal_mode = WAL; | 
 |   86     PRAGMA wal_autocheckpoint = 128; | 
 |   87     CREATE TABLE t1(a PRIMARY KEY, b); | 
 |   88     INSERT INTO t1 VALUES(randomblob(25), randomblob(200)); | 
 |   89   } | 
 |   90  | 
 |   91   for {set i 0} {$i < 1500} {incr i} { | 
 |   92     execsql { INSERT INTO t1 VALUES(randomblob(25), randomblob(200)) } | 
 |   93   } | 
 |   94  | 
 |   95   db_save | 
 |   96   db close | 
 |   97 } {} | 
 |   98  | 
 |   99 set nInitialErr [set_test_counter errors] | 
 |  100 for {set i 2} {$i<10000 && [set_test_counter errors]==$nInitialErr} {incr i} { | 
 |  101  | 
 |  102   do_test 2.$i.1 { | 
 |  103     catch { db close }  | 
 |  104     db_restore | 
 |  105     crashsql -delay 2 -file test.db-wal -seed $i { | 
 |  106       SELECT * FROM sqlite_master; | 
 |  107       PRAGMA synchronous = full; | 
 |  108       PRAGMA wal_checkpoint; | 
 |  109       BEGIN; | 
 |  110         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  111         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  112         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  113         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  114         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  115         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  116         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  117         INSERT INTO t1 VALUES(randomblob(26), randomblob(200)); | 
 |  118       COMMIT; | 
 |  119     } | 
 |  120   } {1 {child process exited abnormally}} | 
 |  121  | 
 |  122   do_test 2.$i.2 { | 
 |  123     sqlite3 db test.db | 
 |  124     execsql { PRAGMA integrity_check }  | 
 |  125   } {ok} | 
 |  126 } | 
 |  127  | 
 |  128 finish_test | 
| OLD | NEW |