Merge updates from trunk.
[sqlite.git] / test / crash3.test
blob7958af992ed76aa9053824cd64e801a85e534c9f
1 # 2007 August 23
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
12 # This file contains tests that verify that SQLite can correctly rollback
13 # databases after crashes when using the special IO modes triggered 
14 # by device IOCAP flags.
16 # $Id: crash3.test,v 1.4 2008/07/12 14:52:20 drh Exp $
18 set testdir [file dirname $argv0]
19 source $testdir/tester.tcl
21 ifcapable !crashtest {
22   finish_test
23   return
26 proc do_test2 {name tcl res1 res2} {
27   set script [subst -nocommands {
28     do_test $name {
29       set res1 {$res1}
30       set res2 {$res2}
31       set res [eval {$tcl}]
32       if {[set res] eq [set res1] || [set res] eq [set res2]} {
33         set res "{[set res1]} or {[set res2]}"
34       }
35       set res
36     } {{$res1} or {$res2}}
37   }]
38   uplevel $script
41 # This block tests crash-recovery when the IOCAP_ATOMIC flags is set.
43 # Each iteration of the following loop sets up the database to contain
44 # the following schema and data:
46 #    CREATE TABLE abc(a, b, c);
47 #    INSERT INTO abc VALUES(1, 2, 3);
49 # Then execute the SQL statement, scheduling a crash for part-way through
50 # the first sync() of either the database file or the journal file (often
51 # the journal file is not required - meaning no crash occurs).
53 # After the crash (or absence of a crash), open the database and 
54 # verify that:
56 #   * The integrity check passes, and
57 #   * The contents of table abc is either {1 2 3} or the value specified
58 #     to the right of the SQL statement below.
60 # The procedure is repeated 10 times for each SQL statement. Five times
61 # with the crash scheduled for midway through the first journal sync (if 
62 # any), and five times with the crash midway through the database sync.
64 set tn 1
65 foreach {sql res2} [list \
66   {INSERT INTO abc VALUES(4, 5, 6)}                    {1 2 3 4 5 6} \
67   {DELETE FROM abc}                                    {}    \
68   {INSERT INTO abc SELECT * FROM abc}                  {1 2 3 1 2 3} \
69   {UPDATE abc SET a = 2}                               {2 2 3}       \
70   {INSERT INTO abc VALUES(4, 5, randstr(1000,1000))}   {n/a} \
71   {CREATE TABLE def(d, e, f)}                          {n/a} \
72 ] {
73   for {set ii 0} {$ii < 10} {incr ii} {
75     db close
76     forcedelete test.db test.db-journal
77     sqlite3 db test.db
78     do_test crash3-1.$tn.1 {
79       execsql {
80         PRAGMA page_size = 1024;
81         BEGIN;
82         CREATE TABLE abc(a, b, c);
83         INSERT INTO abc VALUES(1, 2, 3);
84         COMMIT;
85       }
86     } {}
87     db close
88   
89     set crashfile test.db
90     if {($ii%2)==0} { append crashfile -journal }
91     set rand "SELECT randstr($tn,$tn);"
92     do_test crash3-1.$tn.2 [subst {
93       crashsql -file $crashfile -char atomic {$rand $sql}
94       sqlite3 db test.db
95       execsql { PRAGMA integrity_check; }
96     }] {ok}
97   
98     do_test2 crash3-1.$tn.3 {
99       execsql { SELECT * FROM abc }
100     } {1 2 3} $res2
102     incr tn
103   }
106 # This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags.
108 db close
109 forcedelete test.db test.db-journal
110 sqlite3 db test.db
111 do_test crash3-2.0 {
112   execsql {
113     BEGIN;
114     CREATE TABLE abc(a PRIMARY KEY, b, c);
115     CREATE TABLE def(d PRIMARY KEY, e, f);
116     PRAGMA default_cache_size = 10;
117     INSERT INTO abc VALUES(randstr(10,1000),randstr(10,1000),randstr(10,1000));
118     INSERT INTO abc 
119       SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
120     INSERT INTO abc 
121       SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
122     INSERT INTO abc 
123       SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
124     INSERT INTO abc 
125       SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
126     INSERT INTO abc 
127       SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
128     INSERT INTO abc 
129       SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
130     COMMIT;
131   }
132 } {}
134 set tn 1
135 foreach {::crashfile ::delay ::char} {
136   test.db         1 sequential
137   test.db         1 safe_append
138   test.db-journal 1 sequential
139   test.db-journal 1 safe_append
140   test.db-journal 2 safe_append
141   test.db-journal 2 sequential
142   test.db-journal 3 sequential
143   test.db-journal 3 safe_append
144 } {
145   for {set ii 0} {$ii < 100} {incr ii} {
146     set ::SQL [subst {
147       SELECT randstr($ii,$ii+10);
148       BEGIN;
149       DELETE FROM abc WHERE random()%5;
150       INSERT INTO abc 
151         SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) 
152         FROM abc
153         WHERE (random()%5)==0;
154       DELETE FROM def WHERE random()%5;
155       INSERT INTO def 
156         SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) 
157         FROM def
158         WHERE (random()%5)==0;
159       COMMIT;
160     }]
162     do_test crash3-2.$tn.$ii {
163       crashsql -file $::crashfile -delay $::delay -char $::char $::SQL
164       db close
165       sqlite3 db test.db
166       execsql {PRAGMA integrity_check}
167     } {ok}
168   }
169   incr tn
172 # The following block tests an interaction between IOCAP_ATOMIC and
173 # IOCAP_SEQUENTIAL. At one point, if both flags were set, small
174 # journal files that contained only a single page, but were required 
175 # for some other reason (i.e. nTrunk) were not being written to
176 # disk.
178 for {set ii 0} {$ii < 10} {incr ii} {
179   db close
180   forcedelete test.db test.db-journal
181   crashsql -file test.db -char {sequential atomic} {
182     CREATE TABLE abc(a, b, c);
183   }
184   sqlite3 db test.db
185   do_test crash3-3.$ii {
186     execsql {PRAGMA integrity_check}
187   } {ok}
190 finish_test