Annotation of embedaddon/sqlite3/test/exclusive2.test, revision 1.1
1.1 ! misho 1: # 2007 March 24
! 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: # This file implements regression tests for SQLite library.
! 12: #
! 13: # $Id: exclusive2.test,v 1.10 2008/11/27 02:22:11 drh Exp $
! 14:
! 15: set testdir [file dirname $argv0]
! 16: source $testdir/tester.tcl
! 17:
! 18: # Do not use a codec for tests in this file, as the database file is
! 19: # manipulated directly using tcl scripts (using the [hexio_write] command).
! 20: #
! 21: do_not_use_codec
! 22:
! 23: ifcapable {!pager_pragmas} {
! 24: finish_test
! 25: return
! 26: }
! 27:
! 28: # This module does not work right if the cache spills at unexpected
! 29: # moments. So disable the soft-heap-limit.
! 30: #
! 31: sqlite3_soft_heap_limit 0
! 32:
! 33: proc pagerChangeCounter {filename new {fd ""}} {
! 34: if {$fd==""} {
! 35: set fd [open $filename RDWR]
! 36: fconfigure $fd -translation binary -encoding binary
! 37: set needClose 1
! 38: } else {
! 39: set needClose 0
! 40: }
! 41: if {$new ne ""} {
! 42: seek $fd 24
! 43: set a [expr {($new&0xFF000000)>>24}]
! 44: set b [expr {($new&0x00FF0000)>>16}]
! 45: set c [expr {($new&0x0000FF00)>>8}]
! 46: set d [expr {($new&0x000000FF)}]
! 47: puts -nonewline $fd [binary format cccc $a $b $c $d]
! 48: flush $fd
! 49: }
! 50:
! 51: seek $fd 24
! 52: foreach {a b c d} [list 0 0 0 0] {}
! 53: binary scan [read $fd 4] cccc a b c d
! 54: set ret [expr ($a&0x000000FF)<<24]
! 55: incr ret [expr ($b&0x000000FF)<<16]
! 56: incr ret [expr ($c&0x000000FF)<<8]
! 57: incr ret [expr ($d&0x000000FF)<<0]
! 58:
! 59: if {$needClose} {close $fd}
! 60: return $ret
! 61: }
! 62:
! 63: proc readPagerChangeCounter {filename} {
! 64: set fd [open $filename RDONLY]
! 65: fconfigure $fd -translation binary -encoding binary
! 66:
! 67: seek $fd 24
! 68: foreach {a b c d} [list 0 0 0 0] {}
! 69: binary scan [read $fd 4] cccc a b c d
! 70: set ret [expr ($a&0x000000FF)<<24]
! 71: incr ret [expr ($b&0x000000FF)<<16]
! 72: incr ret [expr ($c&0x000000FF)<<8]
! 73: incr ret [expr ($d&0x000000FF)<<0]
! 74:
! 75: close $fd
! 76: return $ret
! 77: }
! 78:
! 79:
! 80: proc t1sig {{db db}} {
! 81: execsql {SELECT count(*), md5sum(a) FROM t1} $db
! 82: }
! 83: do_test exclusive2-1.0 {
! 84: readPagerChangeCounter test.db
! 85: } {0}
! 86:
! 87: #-----------------------------------------------------------------------
! 88: # The following tests - exclusive2-1.X - check that:
! 89: #
! 90: # 1-3: Build a database with connection 1, calculate a signature.
! 91: # 4-7: Modify the database using a second connection in a way that
! 92: # does not modify the freelist, then reset the pager change-counter
! 93: # to the value it had before the modifications.
! 94: # 8: Check that using the first connection, the database signature
! 95: # is still the same. This is because it uses the in-memory cache.
! 96: # It can't tell the db has changed because we reset the change-counter.
! 97: # 9: Increment the change-counter.
! 98: # 10: Ensure that the first connection now sees the updated database. It
! 99: # sees the change-counter has been incremented and discards the
! 100: # invalid in-memory cache.
! 101: #
! 102: # This will only work if the database cache is large enough to hold
! 103: # the entire database. In the case of 1024 byte pages, this means
! 104: # the cache size must be at least 17. Otherwise, some pages will be
! 105: # loaded from the database file in step 8.
! 106: #
! 107: # For similar reasons, this test does not work with the memsubsys1 permutation.
! 108: # Permutation memsubsys1 configures the pcache subsystem to use a static
! 109: # allocation of 24 pages (shared between all pagers). This is not enough for
! 110: # this test.
! 111: #
! 112: do_test exclusive2-1.1 {
! 113: execsql {
! 114: BEGIN;
! 115: CREATE TABLE t1(a, b);
! 116: INSERT INTO t1(a) VALUES(randstr(10, 400));
! 117: INSERT INTO t1(a) VALUES(randstr(10, 400));
! 118: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 119: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 120: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 121: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 122: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 123: COMMIT;
! 124: SELECT count(*) FROM t1;
! 125: }
! 126: } {64}
! 127: do_test exclusive2-1.2.1 {
! 128: # Make sure the pager cache is large enough to store the
! 129: # entire database.
! 130: set nPage [expr [file size test.db]/1024]
! 131: if {$::SQLITE_DEFAULT_CACHE_SIZE < $nPage} {
! 132: execsql "PRAGMA cache_size = $nPage"
! 133: }
! 134: expr {[execsql {PRAGMA cache_size}] >= $nPage}
! 135: } {1}
! 136: do_test exclusive2-1.2 {
! 137: set ::sig [t1sig]
! 138: readPagerChangeCounter test.db
! 139: } {1}
! 140: do_test exclusive2-1.3 {
! 141: t1sig
! 142: } $::sig
! 143: do_test exclusive2-1.4 {
! 144: sqlite3 db2 test.db
! 145: t1sig db2
! 146: } $::sig
! 147: do_test exclusive2-1.5 {
! 148: execsql {
! 149: UPDATE t1 SET b=a, a=NULL;
! 150: } db2
! 151: expr {[t1sig db2] eq $::sig}
! 152: } 0
! 153: do_test exclusive2-1.6 {
! 154: readPagerChangeCounter test.db
! 155: } {2}
! 156: do_test exclusive2-1.7 {
! 157: pagerChangeCounter test.db 1
! 158: } {1}
! 159: if {[permutation] != "memsubsys1"} {
! 160: do_test exclusive2-1.9 {
! 161: t1sig
! 162: expr {[t1sig] eq $::sig}
! 163: } {1}
! 164: }
! 165: do_test exclusive2-1.10 {
! 166: pagerChangeCounter test.db 2
! 167: } {2}
! 168: do_test exclusive2-1.11 {
! 169: expr {[t1sig] eq $::sig}
! 170: } {0}
! 171: db2 close
! 172:
! 173: #--------------------------------------------------------------------
! 174: # These tests - exclusive2-2.X - are similar to exclusive2-1.X,
! 175: # except that they are run with locking_mode=EXCLUSIVE.
! 176: #
! 177: # 1-3: Build a database with exclusive-access connection 1,
! 178: # calculate a signature.
! 179: # 4: Corrupt the database by writing 10000 bytes of garbage
! 180: # starting at the beginning of page 2. Check that connection 1
! 181: # still works. It should be accessing the in-memory cache.
! 182: # 5-6: Modify the dataase change-counter. Connection 1 still works
! 183: # entirely from in-memory cache, because it doesn't check the
! 184: # change-counter.
! 185: # 7-8 Set the locking-mode back to normal. After the db is unlocked,
! 186: # SQLite detects the modified change-counter and discards the
! 187: # in-memory cache. Then it finds the corruption caused in step 4....
! 188: #
! 189: # As above, this test is only applicable if the pager cache is
! 190: # large enough to hold the entire database. With 1024 byte pages,
! 191: # this means 19 pages. We also need to disable the soft-heap-limit
! 192: # to prevent memory-induced cache spills.
! 193: #
! 194: do_test exclusive2-2.1 {
! 195: execsql {PRAGMA cache_size=1000;}
! 196: execsql {PRAGMA locking_mode = exclusive;}
! 197: execsql {
! 198: BEGIN;
! 199: DELETE FROM t1;
! 200: INSERT INTO t1(a) VALUES(randstr(10, 400));
! 201: INSERT INTO t1(a) VALUES(randstr(10, 400));
! 202: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 203: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 204: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 205: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 206: INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
! 207: COMMIT;
! 208: SELECT count(*) FROM t1;
! 209: }
! 210: } {64}
! 211: do_test exclusive2-2.2.1 {
! 212: # Make sure the pager cache is large enough to store the
! 213: # entire database.
! 214: set nPage [expr [file size test.db]/1024]
! 215: if {$::SQLITE_DEFAULT_CACHE_SIZE < $nPage} {
! 216: execsql "PRAGMA cache_size = $nPage"
! 217: }
! 218: expr {[execsql {PRAGMA cache_size}] >= $nPage}
! 219: } {1}
! 220: do_test exclusive2-2.2 {
! 221: set ::sig [t1sig]
! 222: readPagerChangeCounter test.db
! 223: } {3}
! 224: do_test exclusive2-2.3 {
! 225: t1sig
! 226: } $::sig
! 227:
! 228: do_test exclusive2-2.4 {
! 229: set ::fd [open test.db RDWR]
! 230: fconfigure $::fd -translation binary
! 231: seek $::fd 1024
! 232: puts -nonewline $::fd [string repeat [binary format c 0] 10000]
! 233: flush $::fd
! 234: t1sig
! 235: } $::sig
! 236:
! 237: do_test exclusive2-2.5 {
! 238: pagerChangeCounter test.db 5 $::fd
! 239: } {5}
! 240: do_test exclusive2-2.6 {
! 241: t1sig
! 242: } $::sig
! 243: do_test exclusive2-2.7 {
! 244: execsql {PRAGMA locking_mode = normal}
! 245: t1sig
! 246: } $::sig
! 247:
! 248: do_test exclusive2-2.8 {
! 249: set rc [catch {t1sig} msg]
! 250: list $rc $msg
! 251: } {1 {database disk image is malformed}}
! 252:
! 253: #--------------------------------------------------------------------
! 254: # These tests - exclusive2-3.X - verify that the pager change-counter
! 255: # is only incremented by the first change when in exclusive access
! 256: # mode. In normal mode, the change-counter is incremented once
! 257: # per write-transaction.
! 258: #
! 259:
! 260: db close
! 261: catch {close $::fd}
! 262: forcedelete test.db
! 263: forcedelete test.db-journal
! 264:
! 265: do_test exclusive2-3.0 {
! 266: sqlite3 db test.db
! 267: execsql {
! 268: BEGIN;
! 269: CREATE TABLE t1(a UNIQUE);
! 270: INSERT INTO t1 VALUES(randstr(200, 200));
! 271: INSERT INTO t1 VALUES(randstr(200, 200));
! 272: COMMIT;
! 273: }
! 274: readPagerChangeCounter test.db
! 275: } {1}
! 276: do_test exclusive2-3.1 {
! 277: execsql {
! 278: INSERT INTO t1 VALUES(randstr(200, 200));
! 279: }
! 280: readPagerChangeCounter test.db
! 281: } {2}
! 282: do_test exclusive2-3.2 {
! 283: execsql {
! 284: INSERT INTO t1 VALUES(randstr(200, 200));
! 285: }
! 286: readPagerChangeCounter test.db
! 287: } {3}
! 288: do_test exclusive2-3.3 {
! 289: execsql {
! 290: PRAGMA locking_mode = exclusive;
! 291: INSERT INTO t1 VALUES(randstr(200, 200));
! 292: }
! 293: readPagerChangeCounter test.db
! 294: } {4}
! 295: do_test exclusive2-3.4 {
! 296: breakpoint
! 297: execsql {
! 298: INSERT INTO t1 VALUES(randstr(200, 200));
! 299: }
! 300: readPagerChangeCounter test.db
! 301: } {4}
! 302: do_test exclusive2-3.5 {
! 303: execsql {
! 304: PRAGMA locking_mode = normal;
! 305: INSERT INTO t1 VALUES(randstr(200, 200));
! 306: }
! 307: readPagerChangeCounter test.db
! 308: } {4}
! 309: do_test exclusive2-3.6 {
! 310: execsql {
! 311: INSERT INTO t1 VALUES(randstr(200, 200));
! 312: }
! 313: readPagerChangeCounter test.db
! 314: } {5}
! 315: sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
! 316:
! 317: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>