/trunk/test/trans2.test |
@@ -0,0 +1,232 @@ |
# 2008 August 27 |
# |
# 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 regression tests for SQLite library. The |
# focus of this script is transactions |
# |
# $Id: trans2.test,v 1.1 2008/08/27 18:56:36 drh Exp $ |
# |
set testdir [file dirname $argv0] |
source $testdir/tester.tcl |
|
# A procedure to scramble the elements of list $inlist into a random order. |
# |
proc scramble {inlist} { |
set y {} |
foreach x $inlist { |
lappend y [list [expr {rand()}] $x] |
} |
set y [lsort $y] |
set outlist {} |
foreach x $y { |
lappend outlist [lindex $x 1] |
} |
return $outlist |
} |
|
# Generate a UUID using randomness. |
# |
expr srand(1) |
proc random_uuid {} { |
set u {} |
for {set i 0} {$i<5} {incr i} { |
append u [format %06x [expr {int(rand()*16777216)}]] |
} |
return $u |
} |
|
# Compute hashes on the u1 and u2 fields of the sample data. |
# |
proc hash1 {} { |
global data |
set x "" |
foreach rec [lsort -integer -index 0 $data] { |
append x [lindex $rec 1] |
} |
return [md5 $x] |
} |
proc hash2 {} { |
global data |
set x "" |
foreach rec [lsort -integer -index 0 $data] { |
append x [lindex $rec 3] |
} |
return [md5 $x] |
} |
|
# Create the initial data set |
# |
unset -nocomplain data i max_rowid todel n rec max1 id origres newres |
unset -nocomplain inssql modsql s j z |
set data {} |
for {set i 0} {$i<400} {incr i} { |
set rec [list $i [random_uuid] [expr {int(rand()*5000)+1000}] [random_uuid]] |
lappend data $rec |
} |
set max_rowid [expr {$i-1}] |
|
# Create the T1 table used to hold test data. Populate that table with |
# the initial data set and check hashes to make sure everything is correct. |
# |
do_test trans2-1.1 { |
execsql { |
PRAGMA cache_size=100; |
CREATE TABLE t1( |
id INTEGER PRIMARY KEY, |
u1 TEXT UNIQUE, |
z BLOB NOT NULL, |
u2 TEXT UNIQUE |
); |
} |
foreach rec [scramble $data] { |
foreach {id u1 z u2} $rec break |
db eval {INSERT INTO t1 VALUES($id,$u1,zeroblob($z),$u2)} |
} |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} [list [hash1] [hash2]] |
|
# Repeat the main test loop multiple times. |
# |
for {set i 2} {$i<=30} {incr i} { |
# Delete one row out of every 10 in the database. This will add |
# many pages to the freelist. |
# |
set todel {} |
set n [expr {[llength $data]/10}] |
set data [scramble $data] |
foreach rec [lrange $data 0 $n] { |
lappend todel [lindex $rec 0] |
} |
set data [lrange $data [expr {$n+1}] end] |
set max1 [lindex [lindex $data 0] 0] |
foreach rec $data { |
set id [lindex $rec 0] |
if {$id>$max1} {set max1 $id} |
} |
set origres [list [hash1] [hash2]] |
do_test trans2-$i.1 { |
db eval "DELETE FROM t1 WHERE id IN ([join $todel ,])" |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $origres |
integrity_check trans2-$i.2 |
|
# Begin a transaction and insert many new records. |
# |
set newdata {} |
foreach id $todel { |
set rec [list $id [random_uuid] \ |
[expr {int(rand()*5000)+1000}] [random_uuid]] |
lappend newdata $rec |
lappend data $rec |
} |
for {set j 1} {$j<50} {incr j} { |
set id [expr {$max_rowid+$j}] |
lappend todel $id |
set rec [list $id [random_uuid] \ |
[expr {int(rand()*5000)+1000}] [random_uuid]] |
lappend newdata $rec |
lappend data $rec |
} |
set max_rowid [expr {$max_rowid+$j-1}] |
set modsql {} |
set inssql {} |
set newres [list [hash1] [hash2]] |
do_test trans2-$i.3 { |
db eval BEGIN |
foreach rec [scramble $newdata] { |
foreach {id u1 z u2} $rec break |
set s "INSERT INTO t1 VALUES($id,'$u1',zeroblob($z),'$u2');" |
append modsql $s\n |
append inssql $s\n |
db eval $s |
} |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $newres |
integrity_check trans2-$i.4 |
|
# Do a large update that aborts do to a constraint failure near |
# the end. This stresses the statement journal mechanism. |
# |
do_test trans2-$i.10 { |
catchsql { |
UPDATE t1 SET u1=u1||'x', |
z = CASE WHEN id<$max_rowid |
THEN zeroblob((random()&65535)%5000 + 1000) END; |
} |
} {1 {t1.z may not be NULL}} |
do_test trans2-$i.11 { |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $newres |
|
# Delete all of the newly inserted records. Verify that the database |
# is back to its original state. |
# |
do_test trans2-$i.20 { |
set s "DELETE FROM t1 WHERE id IN ([join $todel ,]);" |
append modsql $s\n |
db eval $s |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $origres |
|
# Do another large update that aborts do to a constraint failure near |
# the end. This stresses the statement journal mechanism. |
# |
do_test trans2-$i.30 { |
catchsql { |
UPDATE t1 SET u1=u1||'x', |
z = CASE WHEN id<$max1 |
THEN zeroblob((random()&65535)%5000 + 1000) END; |
} |
} {1 {t1.z may not be NULL}} |
do_test trans2-$i.31 { |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $origres |
|
# Redo the inserts |
# |
do_test trans2-$i.40 { |
db eval $inssql |
append modsql $inssql |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $newres |
|
# Rollback the transaction. Verify that the content is restored. |
# |
do_test trans2-$i.90 { |
db eval ROLLBACK |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $origres |
integrity_check trans2-$i.91 |
|
# Repeat all the changes, but this time commit. |
# |
do_test trans2-$i.92 { |
db eval BEGIN |
catchsql { |
UPDATE t1 SET u1=u1||'x', |
z = CASE WHEN id<$max1 |
THEN zeroblob((random()&65535)%5000 + 1000) END; |
} |
db eval $modsql |
catchsql { |
UPDATE t1 SET u1=u1||'x', |
z = CASE WHEN id<$max1 |
THEN zeroblob((random()&65535)%5000 + 1000) END; |
} |
db eval COMMIT |
db eval {SELECT md5sum(u1), md5sum(u2) FROM t1 ORDER BY id} |
} $newres |
integrity_check trans2-$i.93 |
} |
|
unset -nocomplain data i max_rowid todel n rec max1 id origres newres |
unset -nocomplain inssql modsql s j z |
finish_test |