• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20ifcapable !crashtest {
21  finish_test
22  return
23}
24
25
26# A sequence of SQL commands:
27#
28set 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#
48set crash4_cksum_set {}
49lappend crash4_cksum_set [allcksum db]
50foreach 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#
64for {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
102finish_test
103