drh | f858740 | 2008-01-08 16:03:49 +0000 | [diff] [blame] | 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 | # |
drh | 93aed5a | 2008-01-16 17:46:38 +0000 | [diff] [blame] | 15 | # $Id: crash4.test,v 1.3 2008/01/16 17:46:38 drh Exp $ |
drh | f858740 | 2008-01-08 16:03:49 +0000 | [diff] [blame] | 16 | |
| 17 | set testdir [file dirname $argv0] |
| 18 | source $testdir/tester.tcl |
| 19 | |
| 20 | ifcapable !crashtest { |
| 21 | finish_test |
| 22 | return |
| 23 | } |
| 24 | |
drh | f858740 | 2008-01-08 16:03:49 +0000 | [diff] [blame] | 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 {} |
drh | 93aed5a | 2008-01-16 17:46:38 +0000 | [diff] [blame] | 49 | lappend crash4_cksum_set [allcksum db] |
drh | f858740 | 2008-01-08 16:03:49 +0000 | [diff] [blame] | 50 | foreach cmd $sql_cmd_list { |
| 51 | db eval $cmd |
drh | 93aed5a | 2008-01-16 17:46:38 +0000 | [diff] [blame] | 52 | lappend crash4_cksum_set [allcksum db] |
drh | f858740 | 2008-01-08 16:03:49 +0000 | [diff] [blame] | 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 |
mistachkin | fda06be | 2011-08-02 00:57:34 +0000 | [diff] [blame] | 66 | forcedelete test.db test.db-journal |
drh | f858740 | 2008-01-08 16:03:49 +0000 | [diff] [blame] | 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 { |
drh | 93aed5a | 2008-01-16 17:46:38 +0000 | [diff] [blame] | 97 | set x [lsearch $::crash4_cksum_set [allcksum db]] |
drh | f858740 | 2008-01-08 16:03:49 +0000 | [diff] [blame] | 98 | expr {$x>=0} |
| 99 | } {1} |
| 100 | } |
| 101 | |
| 102 | finish_test |