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>