Home | History | Annotate | Download | only in test
      1 # 2010 February 8
      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 # This file implements regression tests for SQLite library.  The
     12 # focus of this file is testing the operation of the library when
     13 # recovering a database following a simulated system failure in 
     14 # "PRAGMA journal_mode=WAL" mode.
     15 #
     16 
     17 #
     18 # These are 'warm-body' tests of database recovery used while developing 
     19 # the WAL code. They serve to prove that a few really simple cases work:
     20 #
     21 # walcrash-1.*: Recover a database.
     22 # walcrash-2.*: Recover a database where the failed transaction spanned more
     23 #               than one page.
     24 # walcrash-3.*: Recover multiple databases where the failed transaction 
     25 #               was a multi-file transaction.
     26 #
     27 
     28 set testdir [file dirname $argv0]
     29 source $testdir/tester.tcl
     30 ifcapable !wal {finish_test ; return }
     31 
     32 db close
     33 
     34 set seed 0
     35 set REPEATS 100
     36 
     37 # walcrash-1.*
     38 #
     39 for {set i 1} {$i < $REPEATS} {incr i} {
     40   file delete -force test.db test.db-wal
     41   do_test walcrash-1.$i.1 {
     42     crashsql -delay 4 -file test.db-wal -seed [incr seed] {
     43       PRAGMA journal_mode = WAL;
     44       CREATE TABLE t1(a, b);
     45       INSERT INTO t1 VALUES(1, 1);
     46       INSERT INTO t1 VALUES(2, 3);
     47       INSERT INTO t1 VALUES(3, 6);
     48     }
     49   } {1 {child process exited abnormally}}
     50   do_test walcrash-1.$i.2 {
     51     sqlite3 db test.db
     52     execsql { SELECT sum(a)==max(b) FROM t1 }
     53   } {1}
     54   integrity_check walcrash-1.$i.3
     55   db close
     56   
     57   do_test walcrash-1.$i.4 {
     58     crashsql -delay 2 -file test.db-wal -seed [incr seed] {
     59       INSERT INTO t1 VALUES(4, (SELECT sum(a) FROM t1) + 4);
     60       INSERT INTO t1 VALUES(5, (SELECT sum(a) FROM t1) + 5);
     61     }
     62   } {1 {child process exited abnormally}}
     63   do_test walcrash-1.$i.5 {
     64     sqlite3 db test.db
     65     execsql { SELECT sum(a)==max(b) FROM t1 }
     66   } {1}
     67   integrity_check walcrash-1.$i.6
     68   do_test walcrash-1.$i.7 {
     69     execsql { PRAGMA main.journal_mode }
     70   } {wal}
     71   db close
     72 }
     73 
     74 # walcrash-2.*
     75 #
     76 for {set i 1} {$i < $REPEATS} {incr i} {
     77   file delete -force test.db test.db-wal
     78   do_test walcrash-2.$i.1 {
     79     crashsql -delay 4 -file test.db-wal -seed [incr seed] {
     80       PRAGMA journal_mode = WAL;
     81       CREATE TABLE t1(a PRIMARY KEY, b);
     82       INSERT INTO t1 VALUES(1, 2);
     83       INSERT INTO t1 VALUES(3, 4);
     84       INSERT INTO t1 VALUES(5, 9);
     85     }
     86   } {1 {child process exited abnormally}}
     87   do_test walcrash-2.$i.2 {
     88     sqlite3 db test.db
     89     execsql { SELECT sum(a)==max(b) FROM t1 }
     90   } {1}
     91   integrity_check walcrash-2.$i.3
     92   db close
     93   
     94   do_test walcrash-2.$i.4 {
     95     crashsql -delay 2 -file test.db-wal -seed [incr seed] {
     96       INSERT INTO t1 VALUES(6, (SELECT sum(a) FROM t1) + 6);
     97       INSERT INTO t1 VALUES(7, (SELECT sum(a) FROM t1) + 7);
     98     }
     99   } {1 {child process exited abnormally}}
    100   do_test walcrash-2.$i.5 {
    101     sqlite3 db test.db
    102     execsql { SELECT sum(a)==max(b) FROM t1 }
    103   } {1}
    104   integrity_check walcrash-2.$i.6
    105   do_test walcrash-2.$i.6 {
    106     execsql { PRAGMA main.journal_mode }
    107   } {wal}
    108   db close
    109 }
    110 
    111 # walcrash-3.*
    112 #
    113 # for {set i 1} {$i < $REPEATS} {incr i} {
    114 #   file delete -force test.db test.db-wal
    115 #   file delete -force test2.db test2.db-wal
    116 # 
    117 #   do_test walcrash-3.$i.1 {
    118 #     crashsql -delay 2 -file test2.db-wal -seed [incr seed] {
    119 #       PRAGMA journal_mode = WAL;
    120 #       ATTACH 'test2.db' AS aux;
    121 #       CREATE TABLE t1(a PRIMARY KEY, b);
    122 #       CREATE TABLE aux.t2(a PRIMARY KEY, b);
    123 #       BEGIN;
    124 #         INSERT INTO t1 VALUES(1, 2);
    125 #         INSERT INTO t2 VALUES(1, 2);
    126 #       COMMIT;
    127 #     }
    128 #   } {1 {child process exited abnormally}}
    129 # 
    130 #   do_test walcrash-3.$i.2 {
    131 #     sqlite3_wal db test.db
    132 #     execsql { 
    133 #       ATTACH 'test2.db' AS aux;
    134 #       SELECT * FROM t1 EXCEPT SELECT * FROM t2;
    135 #     }
    136 #   } {}
    137 #   do_test walcrash-3.$i.3 { execsql { PRAGMA main.integrity_check } } {ok}
    138 #   do_test walcrash-3.$i.4 { execsql { PRAGMA aux.integrity_check  } } {ok}
    139 # 
    140 #   db close
    141 # }
    142 
    143 # walcrash-4.*
    144 #
    145 for {set i 1} {$i < $REPEATS} {incr i} {
    146   file delete -force test.db test.db-wal
    147   file delete -force test2.db test2.db-wal
    148 
    149   do_test walcrash-4.$i.1 {
    150     crashsql -delay 3 -file test.db-wal -seed [incr seed] -blocksize 4096 {
    151       PRAGMA journal_mode = WAL;
    152       PRAGMA page_size = 1024;
    153       CREATE TABLE t1(a PRIMARY KEY, b);
    154       INSERT INTO t1 VALUES(1, 2);
    155       INSERT INTO t1 VALUES(3, 4);
    156     }
    157   } {1 {child process exited abnormally}}
    158 
    159   do_test walcrash-4.$i.2 {
    160     sqlite3 db test.db
    161     execsql { 
    162       SELECT * FROM t1 WHERE a = 1;
    163     }
    164   } {1 2}
    165   do_test walcrash-4.$i.3 { execsql { PRAGMA main.integrity_check } } {ok}
    166   do_test walcrash-4.$i.4 { execsql { PRAGMA main.journal_mode } } {wal}
    167 
    168   db close
    169 }
    170 
    171 # walcrash-5.*
    172 #
    173 for {set i 1} {$i < $REPEATS} {incr i} {
    174   file delete -force test.db test.db-wal
    175   file delete -force test2.db test2.db-wal
    176 
    177   do_test walcrash-5.$i.1 {
    178     crashsql -delay 11 -file test.db-wal -seed [incr seed] -blocksize 4096 {
    179       PRAGMA journal_mode = WAL;
    180       PRAGMA page_size = 1024;
    181       BEGIN;
    182         CREATE TABLE t1(x PRIMARY KEY);
    183         INSERT INTO t1 VALUES(randomblob(900));
    184         INSERT INTO t1 VALUES(randomblob(900));
    185         INSERT INTO t1 SELECT randomblob(900) FROM t1;           /* 4 */
    186       COMMIT;
    187       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 8 */
    188       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 12 */
    189       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 16 */
    190       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 20 */
    191       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 24 */
    192       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 28 */
    193       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 32 */
    194 
    195       PRAGMA wal_checkpoint;
    196       INSERT INTO t1 VALUES(randomblob(900));
    197       INSERT INTO t1 VALUES(randomblob(900));
    198       INSERT INTO t1 VALUES(randomblob(900));
    199     }
    200   } {1 {child process exited abnormally}}
    201 
    202   do_test walcrash-5.$i.2 {
    203     sqlite3 db test.db
    204     execsql { SELECT count(*)==33 OR count(*)==34 FROM t1 WHERE x != 1 }
    205   } {1}
    206   do_test walcrash-5.$i.3 { execsql { PRAGMA main.integrity_check } } {ok}
    207   do_test walcrash-5.$i.4 { execsql { PRAGMA main.journal_mode } } {wal}
    208 
    209   db close
    210 }
    211 
    212 # walcrash-6.*
    213 #
    214 for {set i 1} {$i < $REPEATS} {incr i} {
    215   file delete -force test.db test.db-wal
    216   file delete -force test2.db test2.db-wal
    217 
    218   do_test walcrash-6.$i.1 {
    219     crashsql -delay 12 -file test.db-wal -seed [incr seed] -blocksize 512 {
    220       PRAGMA journal_mode = WAL;
    221       PRAGMA page_size = 1024;
    222       BEGIN;
    223         CREATE TABLE t1(x PRIMARY KEY);
    224         INSERT INTO t1 VALUES(randomblob(900));
    225         INSERT INTO t1 VALUES(randomblob(900));
    226         INSERT INTO t1 SELECT randomblob(900) FROM t1;           /* 4 */
    227       COMMIT;
    228       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 8 */
    229       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 12 */
    230       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 16 */
    231       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 20 */
    232       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 24 */
    233       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 28 */
    234       INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4;   /* 32 */
    235 
    236       PRAGMA wal_checkpoint;
    237       INSERT INTO t1 VALUES(randomblob(900));
    238       INSERT INTO t1 VALUES(randomblob(900));
    239       INSERT INTO t1 VALUES(randomblob(900));
    240     }
    241   } {1 {child process exited abnormally}}
    242 
    243   do_test walcrash-6.$i.2 {
    244     sqlite3 db test.db
    245     execsql { SELECT count(*)==34 OR count(*)==35 FROM t1 WHERE x != 1 }
    246   } {1}
    247   do_test walcrash-6.$i.3 { execsql { PRAGMA main.integrity_check } } {ok}
    248   do_test walcrash-6.$i.4 { execsql { PRAGMA main.journal_mode } } {wal}
    249 
    250   db close
    251 }
    252 
    253 #-------------------------------------------------------------------------
    254 # This test case simulates a crash while checkpointing the database. Page
    255 # 1 is one of the pages overwritten by the checkpoint. This is a special
    256 # case because it means the content of page 1 may be damaged. SQLite will
    257 # have to determine:
    258 #
    259 #   (a) that the database is a WAL database, and 
    260 #   (b) the database page-size
    261 #
    262 # based on the log file.
    263 #
    264 for {set i 1} {$i < $REPEATS} {incr i} {
    265   file delete -force test.db test.db-wal
    266 
    267   # Select a page-size for this test.
    268   #
    269   set pgsz [lindex {512 1024 2048 4096 8192 16384} [expr $i%6]]
    270 
    271   do_test walcrash-7.$i.1 {
    272     crashsql -delay 3 -file test.db -seed [incr seed] -blocksize 512 "
    273       PRAGMA page_size = $pgsz;
    274       PRAGMA journal_mode = wal;
    275       BEGIN;
    276         CREATE TABLE t1(a, b);
    277         INSERT INTO t1 VALUES(1, 2);
    278       COMMIT;
    279       PRAGMA wal_checkpoint;
    280       CREATE INDEX i1 ON t1(a);
    281       PRAGMA wal_checkpoint;
    282     "
    283   } {1 {child process exited abnormally}}
    284 
    285   do_test walcrash-7.$i.2 {
    286     sqlite3 db test.db
    287     execsql { SELECT b FROM t1 WHERE a = 1 }
    288   } {2}
    289   do_test walcrash-7.$i.3 { execsql { PRAGMA main.integrity_check } } {ok}
    290   do_test walcrash-7.$i.4 { execsql { PRAGMA main.journal_mode } } {wal}
    291 
    292   db close
    293 }
    294 
    295 finish_test
    296 
    297