SQLite

Check-in [87b4ac4b73]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add crash4.test with additional crash testing. (CVS 4695)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 87b4ac4b73fb84411ced9e9a859dd0e2d211c4b3
User & Date: drh 2008-01-08 16:03:50.000
Context
2008-01-08
18:57
Finish registerizing the core logic of INSERT and UPDATE. (CVS 4696) (check-in: 5fd1036788 user: drh tags: trunk)
16:03
Add crash4.test with additional crash testing. (CVS 4695) (check-in: 87b4ac4b73 user: drh tags: trunk)
15:18
Add additional randomness to crash tests. (CVS 4694) (check-in: 3ccce1f58b user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Added test/crash4.test.
































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# 2008 January 8
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains additional tests to verify that SQLite database
# file survive a power loss or OS crash.
#
# $Id: crash4.test,v 1.1 2008/01/08 16:03:50 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !crashtest {
  finish_test
  return
}

# Generate a checksum based on the contents of the database. If the
# checksum of two databases is the same, and the integrity-check passes
# for both, the two databases are identical.
#
proc cksum {db} {
  set ret [list]
  ifcapable tempdb {
    set sql {
      SELECT name FROM sqlite_master WHERE type = 'table' UNION
      SELECT name FROM sqlite_temp_master WHERE type = 'table' UNION
      SELECT 'sqlite_master' UNION
      SELECT 'sqlite_temp_master'
    }
  } else {
    set sql {
      SELECT name FROM sqlite_master WHERE type = 'table' UNION
      SELECT 'sqlite_master'
    }
  }
  set tbllist [$db eval $sql]
  set txt {}
  foreach tbl $tbllist {
    append txt [$db eval "SELECT * FROM $tbl"]
  }
  return [md5 $txt]
}

# A sequence of SQL commands:
#
set sql_cmd_list {
  {CREATE TABLE a(id INTEGER, name CHAR(50))}
  {INSERT INTO a(id,name) VALUES(1,'one')}
  {INSERT INTO a(id,name) VALUES(2,'two')}
  {INSERT INTO a(id,name) VALUES(3,'three')}
  {INSERT INTO a(id,name) VALUES(4,'four')}
  {INSERT INTO a(id,name) VALUES(5,'five')}
  {INSERT INTO a(id,name) VALUES(6,'six')}
  {INSERT INTO a(id,name) VALUES(7,'seven')}
  {INSERT INTO a(id,name) VALUES(8,'eight')}
  {INSERT INTO a(id,name) VALUES(9,'nine')}
  {INSERT INTO a(id,name) VALUES(10,'ten')}
  {UPDATE A SET name='new text for row 3' WHERE id=3}
}

# Assume that a database is created by evaluating the SQL statements
# in $sql_cmd_list.  Compute a set of checksums that capture the state
# of the database after each statement.  Also include a checksum for
# the state of the database prior to any of these statements.
#
set crash4_cksum_set {}
lappend crash4_cksum_set [cksum db]
foreach cmd $sql_cmd_list {
  db eval $cmd
  lappend crash4_cksum_set [cksum db]
}

# Run the sequence of SQL statements shown above repeatedly.
# Close and reopen the database right before the UPDATE statement.
# On each repetition, introduce database corruption typical of
# what might be seen in a power loss or OS crash.  
#
# Slowly increase the delay before the crash, repeating the test
# over and over.  Stop testing when the entire sequence of SQL
# statements runs to completing without hitting the crash.
#
for {set cnt 1; set fin 0} {!$fin} {incr cnt} {
  db close
  file delete -force test.db test.db-journal
  do_test crash4-1.$cnt.1 {
    set seed [expr {int(abs(rand()*10000))}]
    set delay [expr {int($cnt/50)+1}]
    set file [expr {($cnt&1)?"test.db":"test.db-journal"}]
    set c [crashsql -delay $delay -file $file -seed $seed -tclbody {
      db eval {CREATE TABLE a(id INTEGER, name CHAR(50))}
      db eval {INSERT INTO a(id,name) VALUES(1,'one')}
      db eval {INSERT INTO a(id,name) VALUES(2,'two')}
      db eval {INSERT INTO a(id,name) VALUES(3,'three')}
      db eval {INSERT INTO a(id,name) VALUES(4,'four')}
      db eval {INSERT INTO a(id,name) VALUES(5,'five')}
      db eval {INSERT INTO a(id,name) VALUES(6,'six')}
      db eval {INSERT INTO a(id,name) VALUES(7,'seven')}
      db eval {INSERT INTO a(id,name) VALUES(8,'eight')}
      db eval {INSERT INTO a(id,name) VALUES(9,'nine')}
      db eval {INSERT INTO a(id,name) VALUES(10,'ten')}
      db close
      sqlite3 db test.db
      db eval {UPDATE A SET name='new text for row 3' WHERE id=3}
      db close
    } {}]
    if {$c==[list 0 {}]} {
      set ::fin 1
      set c [list 1 {child process exited abnormally}]
    }
    set c
  } {1 {child process exited abnormally}}
  sqlite3 db test.db
  integrity_check crash4-1.$cnt.2
  do_test crash4-1.$cnt.3 {
    set x [lsearch $::crash4_cksum_set [cksum db]]
    expr {$x>=0}
  } {1}
}

finish_test
Changes to test/tester.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.97 2008/01/08 15:18:52 drh Exp $


set tcl_precision 15
set sqlite_pending_byte 0x0010000

# 
# Check the command-line arguments for a default soft-heap-limit.













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.98 2008/01/08 16:03:50 drh Exp $


set tcl_precision 15
set sqlite_pending_byte 0x0010000

# 
# Check the command-line arguments for a default soft-heap-limit.
349
350
351
352
353
354
355

356
357
358
359
360
361
362
363
364
365
366
367

368
369
370
371
372
373
374
  if {$::tcl_platform(platform)!="unix"} {
    error "crashsql should only be used on unix"
  }

  set blocksize ""
  set crashdelay 1
  set prngseed 0

  set crashfile ""
  set dc ""
  set sql [lindex $args end]
  
  for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} {
    set z [lindex $args $ii]
    set n [string length $z]
    set z2 [lindex $args [expr $ii+1]]

    if     {$n>1 && [string first $z -delay]==0}     {set crashdelay $z2} \
    elseif {$n>1 && [string first $z -seed]==0}      {set prngseed $z2} \
    elseif {$n>1 && [string first $z -file]==0}      {set crashfile $z2}  \

    elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \
    elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \
    else   { error "Unrecognized option: $z" }
  }

  if {$crashfile eq ""} {
    error "Compulsory option -file missing"







>












>







349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  if {$::tcl_platform(platform)!="unix"} {
    error "crashsql should only be used on unix"
  }

  set blocksize ""
  set crashdelay 1
  set prngseed 0
  set tclbody {}
  set crashfile ""
  set dc ""
  set sql [lindex $args end]
  
  for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} {
    set z [lindex $args $ii]
    set n [string length $z]
    set z2 [lindex $args [expr $ii+1]]

    if     {$n>1 && [string first $z -delay]==0}     {set crashdelay $z2} \
    elseif {$n>1 && [string first $z -seed]==0}      {set prngseed $z2} \
    elseif {$n>1 && [string first $z -file]==0}      {set crashfile $z2}  \
    elseif {$n>1 && [string first $z -tclbody]==0}   {set tclbody $z2}  \
    elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \
    elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \
    else   { error "Unrecognized option: $z" }
  }

  if {$crashfile eq ""} {
    error "Compulsory option -file missing"
390
391
392
393
394
395
396




397
398
399

400
401
402
403
404
405
406
  puts $f {btree_set_cache_size $bt 10}
  if {$prngseed} {
    set seed [expr {$prngseed%10007+1}]
    # puts seed=$seed
    puts $f "db eval {SELECT randomblob($seed)}"
  }





  puts $f "db eval {"
  puts $f   "$sql"
  puts $f "}"

  close $f

  set r [catch {
    exec [info nameofexec] crash.tcl >@stdout
  } msg]
  lappend r $msg
}







>
>
>
>
|
|
|
>







392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  puts $f {btree_set_cache_size $bt 10}
  if {$prngseed} {
    set seed [expr {$prngseed%10007+1}]
    # puts seed=$seed
    puts $f "db eval {SELECT randomblob($seed)}"
  }

  if {[string length $tclbody]>0} {
    puts $f $tclbody
  }
  if {[string length $sql]>0} {
    puts $f "db eval {"
    puts $f   "$sql"
    puts $f "}"
  }
  close $f

  set r [catch {
    exec [info nameofexec] crash.tcl >@stdout
  } msg]
  lappend r $msg
}