File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / exclusive2.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 10 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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.1.1.1 2012/02/21 17:04:16 misho 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>