|
1 # 2008 January 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 # |
|
12 # This file contains additional tests to verify that SQLite database |
|
13 # file survive a power loss or OS crash. |
|
14 # |
|
15 # $Id: crash4.test,v 1.3 2008/01/16 17:46:38 drh Exp $ |
|
16 |
|
17 set testdir [file dirname $argv0] |
|
18 source $testdir/tester.tcl |
|
19 |
|
20 ifcapable !crashtest { |
|
21 finish_test |
|
22 return |
|
23 } |
|
24 |
|
25 |
|
26 # A sequence of SQL commands: |
|
27 # |
|
28 set sql_cmd_list { |
|
29 {CREATE TABLE a(id INTEGER, name CHAR(50))} |
|
30 {INSERT INTO a(id,name) VALUES(1,'one')} |
|
31 {INSERT INTO a(id,name) VALUES(2,'two')} |
|
32 {INSERT INTO a(id,name) VALUES(3,'three')} |
|
33 {INSERT INTO a(id,name) VALUES(4,'four')} |
|
34 {INSERT INTO a(id,name) VALUES(5,'five')} |
|
35 {INSERT INTO a(id,name) VALUES(6,'six')} |
|
36 {INSERT INTO a(id,name) VALUES(7,'seven')} |
|
37 {INSERT INTO a(id,name) VALUES(8,'eight')} |
|
38 {INSERT INTO a(id,name) VALUES(9,'nine')} |
|
39 {INSERT INTO a(id,name) VALUES(10,'ten')} |
|
40 {UPDATE A SET name='new text for row 3' WHERE id=3} |
|
41 } |
|
42 |
|
43 # Assume that a database is created by evaluating the SQL statements |
|
44 # in $sql_cmd_list. Compute a set of checksums that capture the state |
|
45 # of the database after each statement. Also include a checksum for |
|
46 # the state of the database prior to any of these statements. |
|
47 # |
|
48 set crash4_cksum_set {} |
|
49 lappend crash4_cksum_set [allcksum db] |
|
50 foreach cmd $sql_cmd_list { |
|
51 db eval $cmd |
|
52 lappend crash4_cksum_set [allcksum db] |
|
53 } |
|
54 |
|
55 # Run the sequence of SQL statements shown above repeatedly. |
|
56 # Close and reopen the database right before the UPDATE statement. |
|
57 # On each repetition, introduce database corruption typical of |
|
58 # what might be seen in a power loss or OS crash. |
|
59 # |
|
60 # Slowly increase the delay before the crash, repeating the test |
|
61 # over and over. Stop testing when the entire sequence of SQL |
|
62 # statements runs to completing without hitting the crash. |
|
63 # |
|
64 for {set cnt 1; set fin 0} {!$fin} {incr cnt} { |
|
65 db close |
|
66 file delete -force test.db test.db-journal |
|
67 do_test crash4-1.$cnt.1 { |
|
68 set seed [expr {int(abs(rand()*10000))}] |
|
69 set delay [expr {int($cnt/50)+1}] |
|
70 set file [expr {($cnt&1)?"test.db":"test.db-journal"}] |
|
71 set c [crashsql -delay $delay -file $file -seed $seed -tclbody { |
|
72 db eval {CREATE TABLE a(id INTEGER, name CHAR(50))} |
|
73 db eval {INSERT INTO a(id,name) VALUES(1,'one')} |
|
74 db eval {INSERT INTO a(id,name) VALUES(2,'two')} |
|
75 db eval {INSERT INTO a(id,name) VALUES(3,'three')} |
|
76 db eval {INSERT INTO a(id,name) VALUES(4,'four')} |
|
77 db eval {INSERT INTO a(id,name) VALUES(5,'five')} |
|
78 db eval {INSERT INTO a(id,name) VALUES(6,'six')} |
|
79 db eval {INSERT INTO a(id,name) VALUES(7,'seven')} |
|
80 db eval {INSERT INTO a(id,name) VALUES(8,'eight')} |
|
81 db eval {INSERT INTO a(id,name) VALUES(9,'nine')} |
|
82 db eval {INSERT INTO a(id,name) VALUES(10,'ten')} |
|
83 db close |
|
84 sqlite3 db test.db |
|
85 db eval {UPDATE A SET name='new text for row 3' WHERE id=3} |
|
86 db close |
|
87 } {}] |
|
88 if {$c==[list 0 {}]} { |
|
89 set ::fin 1 |
|
90 set c [list 1 {child process exited abnormally}] |
|
91 } |
|
92 set c |
|
93 } {1 {child process exited abnormally}} |
|
94 sqlite3 db test.db |
|
95 integrity_check crash4-1.$cnt.2 |
|
96 do_test crash4-1.$cnt.3 { |
|
97 set x [lsearch $::crash4_cksum_set [allcksum db]] |
|
98 expr {$x>=0} |
|
99 } {1} |
|
100 } |
|
101 |
|
102 finish_test |