1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/exclusive2.test Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,303 @@
1.4 +# 2007 March 24
1.5 +#
1.6 +# The author disclaims copyright to this source code. In place of
1.7 +# a legal notice, here is a blessing:
1.8 +#
1.9 +# May you do good and not evil.
1.10 +# May you find forgiveness for yourself and forgive others.
1.11 +# May you share freely, never taking more than you give.
1.12 +#
1.13 +#***********************************************************************
1.14 +# This file implements regression tests for SQLite library.
1.15 +#
1.16 +# $Id: exclusive2.test,v 1.9 2008/08/22 00:25:53 aswift Exp $
1.17 +
1.18 +set testdir [file dirname $argv0]
1.19 +source $testdir/tester.tcl
1.20 +
1.21 +ifcapable {!pager_pragmas} {
1.22 + finish_test
1.23 + return
1.24 +}
1.25 +
1.26 +# This module does not work right if the cache spills at unexpected
1.27 +# moments. So disable the soft-heap-limit.
1.28 +#
1.29 +sqlite3_soft_heap_limit 0
1.30 +
1.31 +proc pagerChangeCounter {filename new {fd ""}} {
1.32 + if {$fd==""} {
1.33 + set fd [open $filename RDWR]
1.34 + fconfigure $fd -translation binary -encoding binary
1.35 + set needClose 1
1.36 + } else {
1.37 + set needClose 0
1.38 + }
1.39 + if {$new ne ""} {
1.40 + seek $fd 24
1.41 + set a [expr {($new&0xFF000000)>>24}]
1.42 + set b [expr {($new&0x00FF0000)>>16}]
1.43 + set c [expr {($new&0x0000FF00)>>8}]
1.44 + set d [expr {($new&0x000000FF)}]
1.45 + puts -nonewline $fd [binary format cccc $a $b $c $d]
1.46 + flush $fd
1.47 + }
1.48 +
1.49 + seek $fd 24
1.50 + foreach {a b c d} [list 0 0 0 0] {}
1.51 + binary scan [read $fd 4] cccc a b c d
1.52 + set ret [expr ($a&0x000000FF)<<24]
1.53 + incr ret [expr ($b&0x000000FF)<<16]
1.54 + incr ret [expr ($c&0x000000FF)<<8]
1.55 + incr ret [expr ($d&0x000000FF)<<0]
1.56 +
1.57 + if {$needClose} {close $fd}
1.58 + return $ret
1.59 +}
1.60 +
1.61 +proc readPagerChangeCounter {filename} {
1.62 + set fd [open $filename RDONLY]
1.63 + fconfigure $fd -translation binary -encoding binary
1.64 +
1.65 + seek $fd 24
1.66 + foreach {a b c d} [list 0 0 0 0] {}
1.67 + binary scan [read $fd 4] cccc a b c d
1.68 + set ret [expr ($a&0x000000FF)<<24]
1.69 + incr ret [expr ($b&0x000000FF)<<16]
1.70 + incr ret [expr ($c&0x000000FF)<<8]
1.71 + incr ret [expr ($d&0x000000FF)<<0]
1.72 +
1.73 + close $fd
1.74 + return $ret
1.75 +}
1.76 +
1.77 +
1.78 +proc t1sig {{db db}} {
1.79 + execsql {SELECT count(*), md5sum(a) FROM t1} $db
1.80 +}
1.81 +do_test exclusive2-1.0 {
1.82 + readPagerChangeCounter test.db
1.83 +} {0}
1.84 +
1.85 +#-----------------------------------------------------------------------
1.86 +# The following tests - exclusive2-1.X - check that:
1.87 +#
1.88 +# 1-3: Build a database with connection 1, calculate a signature.
1.89 +# 4-9: Modify the database using a second connection in a way that
1.90 +# does not modify the freelist, then reset the pager change-counter
1.91 +# to the value it had before the modifications.
1.92 +# 8: Check that using the first connection, the database signature
1.93 +# is still the same. This is because it uses the in-memory cache.
1.94 +# It can't tell the db has changed because we reset the change-counter.
1.95 +# 9: Increment the change-counter.
1.96 +# 10: Ensure that the first connection now sees the updated database. It
1.97 +# sees the change-counter has been incremented and discards the
1.98 +# invalid in-memory cache.
1.99 +#
1.100 +# This will only work if the database cache is large enough to hold
1.101 +# the entire database. In the case of 1024 byte pages, this means
1.102 +# the cache size must be at least 17. Otherwise, some pages will be
1.103 +# loaded from the database file in step 8.
1.104 +#
1.105 +do_test exclusive2-1.1 {
1.106 + execsql {
1.107 + BEGIN;
1.108 + CREATE TABLE t1(a, b);
1.109 + INSERT INTO t1(a) VALUES(randstr(10, 400));
1.110 + INSERT INTO t1(a) VALUES(randstr(10, 400));
1.111 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.112 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.113 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.114 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.115 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.116 + COMMIT;
1.117 + SELECT count(*) FROM t1;
1.118 + }
1.119 +} {64}
1.120 +do_test exclusive2-1.2.1 {
1.121 + # Make sure the pager cache is large enough to store the
1.122 + # entire database.
1.123 + set nPage [expr [file size test.db]/1024]
1.124 + if {$::SQLITE_DEFAULT_CACHE_SIZE < $nPage} {
1.125 + execsql "PRAGMA cache_size = $nPage"
1.126 + }
1.127 + expr {[execsql {PRAGMA cache_size}] >= $nPage}
1.128 +} {1}
1.129 +do_test exclusive2-1.2 {
1.130 + set ::sig [t1sig]
1.131 + readPagerChangeCounter test.db
1.132 +} {1}
1.133 +do_test exclusive2-1.3 {
1.134 + t1sig
1.135 +} $::sig
1.136 +do_test exclusive2-1.4 {
1.137 + sqlite3 db2 test.db
1.138 + t1sig db2
1.139 +} $::sig
1.140 +do_test exclusive2-1.5 {
1.141 + execsql {
1.142 + UPDATE t1 SET b=a, a=NULL;
1.143 + } db2
1.144 + expr {[t1sig db2] eq $::sig}
1.145 +} 0
1.146 +do_test exclusive2-1.6 {
1.147 + readPagerChangeCounter test.db
1.148 +} {2}
1.149 +do_test exclusive2-1.7 {
1.150 + pagerChangeCounter test.db 1
1.151 +} {1}
1.152 +do_test exclusive2-1.9 {
1.153 + t1sig
1.154 + expr {[t1sig] eq $::sig}
1.155 +} {1}
1.156 +do_test exclusive2-1.10 {
1.157 + pagerChangeCounter test.db 2
1.158 +} {2}
1.159 +do_test exclusive2-1.11 {
1.160 + expr {[t1sig] eq $::sig}
1.161 +} {0}
1.162 +
1.163 +#--------------------------------------------------------------------
1.164 +# These tests - exclusive2-2.X - are similar to exclusive2-1.X,
1.165 +# except that they are run with locking_mode=EXCLUSIVE.
1.166 +#
1.167 +# 1-3: Build a database with exclusive-access connection 1,
1.168 +# calculate a signature.
1.169 +# 4: Corrupt the database by writing 10000 bytes of garbage
1.170 +# starting at the beginning of page 2. Check that connection 1
1.171 +# still works. It should be accessing the in-memory cache.
1.172 +# 5-6: Modify the dataase change-counter. Connection 1 still works
1.173 +# entirely from in-memory cache, because it doesn't check the
1.174 +# change-counter.
1.175 +# 7-8 Set the locking-mode back to normal. After the db is unlocked,
1.176 +# SQLite detects the modified change-counter and discards the
1.177 +# in-memory cache. Then it finds the corruption caused in step 4....
1.178 +#
1.179 +# As above, this test is only applicable if the pager cache is
1.180 +# large enough to hold the entire database. With 1024 byte pages,
1.181 +# this means 19 pages. We also need to disable the soft-heap-limit
1.182 +# to prevent memory-induced cache spills.
1.183 +#
1.184 +do_test exclusive2-2.1 {
1.185 + execsql {PRAGMA locking_mode = exclusive;}
1.186 + execsql {
1.187 + BEGIN;
1.188 + DELETE FROM t1;
1.189 + INSERT INTO t1(a) VALUES(randstr(10, 400));
1.190 + INSERT INTO t1(a) VALUES(randstr(10, 400));
1.191 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.192 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.193 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.194 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.195 + INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
1.196 + COMMIT;
1.197 + SELECT count(*) FROM t1;
1.198 + }
1.199 +} {64}
1.200 +do_test exclusive2-2.2.1 {
1.201 + # Make sure the pager cache is large enough to store the
1.202 + # entire database.
1.203 + set nPage [expr [file size test.db]/1024]
1.204 + if {$::SQLITE_DEFAULT_CACHE_SIZE < $nPage} {
1.205 + execsql "PRAGMA cache_size = $nPage"
1.206 + }
1.207 + expr {[execsql {PRAGMA cache_size}] >= $nPage}
1.208 +} {1}
1.209 +do_test exclusive2-2.2 {
1.210 + set ::sig [t1sig]
1.211 + readPagerChangeCounter test.db
1.212 +} {3}
1.213 +do_test exclusive2-2.3 {
1.214 + t1sig
1.215 +} $::sig
1.216 +
1.217 +do_test exclusive2-2.4 {
1.218 + set ::fd [open test.db RDWR]
1.219 + fconfigure $::fd -translation binary
1.220 + seek $::fd 1024
1.221 + puts -nonewline $::fd [string repeat [binary format c 0] 10000]
1.222 + flush $::fd
1.223 + t1sig
1.224 +} $::sig
1.225 +
1.226 +do_test exclusive2-2.5 {
1.227 + pagerChangeCounter test.db 5 $::fd
1.228 +} {5}
1.229 +do_test exclusive2-2.6 {
1.230 + t1sig
1.231 +} $::sig
1.232 +do_test exclusive2-2.7 {
1.233 + execsql {PRAGMA locking_mode = normal}
1.234 + t1sig
1.235 +} $::sig
1.236 +
1.237 +do_test exclusive2-2.8 {
1.238 + set rc [catch {t1sig} msg]
1.239 + list $rc $msg
1.240 +} {1 {database disk image is malformed}}
1.241 +
1.242 +#--------------------------------------------------------------------
1.243 +# These tests - exclusive2-3.X - verify that the pager change-counter
1.244 +# is only incremented by the first change when in exclusive access
1.245 +# mode. In normal mode, the change-counter is incremented once
1.246 +# per write-transaction.
1.247 +#
1.248 +
1.249 +db close
1.250 +db2 close
1.251 +catch {close $::fd}
1.252 +file delete -force test.db
1.253 +file delete -force test.db-journal
1.254 +
1.255 +do_test exclusive2-3.0 {
1.256 + sqlite3 db test.db
1.257 + execsql {
1.258 + BEGIN;
1.259 + CREATE TABLE t1(a UNIQUE);
1.260 + INSERT INTO t1 VALUES(randstr(10, 400));
1.261 + INSERT INTO t1 VALUES(randstr(10, 400));
1.262 + COMMIT;
1.263 + }
1.264 + readPagerChangeCounter test.db
1.265 +} {1}
1.266 +do_test exclusive2-3.1 {
1.267 + execsql {
1.268 + INSERT INTO t1 VALUES(randstr(10, 400));
1.269 + }
1.270 + readPagerChangeCounter test.db
1.271 +} {2}
1.272 +do_test exclusive2-3.2 {
1.273 + execsql {
1.274 + INSERT INTO t1 VALUES(randstr(10, 400));
1.275 + }
1.276 + readPagerChangeCounter test.db
1.277 +} {3}
1.278 +do_test exclusive2-3.3 {
1.279 + execsql {
1.280 + PRAGMA locking_mode = exclusive;
1.281 + INSERT INTO t1 VALUES(randstr(10, 400));
1.282 + }
1.283 + readPagerChangeCounter test.db
1.284 +} {4}
1.285 +do_test exclusive2-3.4 {
1.286 + execsql {
1.287 + INSERT INTO t1 VALUES(randstr(10, 400));
1.288 + }
1.289 + readPagerChangeCounter test.db
1.290 +} {4}
1.291 +do_test exclusive2-3.5 {
1.292 + execsql {
1.293 + PRAGMA locking_mode = normal;
1.294 + INSERT INTO t1 VALUES(randstr(10, 400));
1.295 + }
1.296 + readPagerChangeCounter test.db
1.297 +} {4}
1.298 +do_test exclusive2-3.6 {
1.299 + execsql {
1.300 + INSERT INTO t1 VALUES(randstr(10, 400));
1.301 + }
1.302 + readPagerChangeCounter test.db
1.303 +} {5}
1.304 +sqlite3_soft_heap_limit $soft_limit
1.305 +
1.306 +finish_test