Annotation of embedaddon/sqlite3/test/exclusive2.test, revision 1.1.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>