Annotation of embedaddon/sqlite3/test/superlock.test, revision 1.1

1.1     ! misho       1: # 2010 November 19
        !             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: #
        !            12: 
        !            13: set testdir [file dirname $argv0]
        !            14: source $testdir/tester.tcl
        !            15: source $testdir/lock_common.tcl
        !            16: 
        !            17: set testprefix superlock
        !            18: 
        !            19: # Test organization:
        !            20: #
        !            21: #   1.*: Test superlock on a rollback database. Test that once the db is
        !            22: #        superlocked, it is not possible for a second client to read from
        !            23: #        it.
        !            24: #
        !            25: #   2.*: Test superlock on a WAL database with zero frames in the WAL file.
        !            26: #        Test that once the db is superlocked, it is not possible to read,
        !            27: #        write or checkpoint the db.
        !            28: #
        !            29: #   3.*: As 2.*, for WAL databases with one or more frames in the WAL.
        !            30: #
        !            31: #   4.*: As 2.*, for WAL databases with one or more checkpointed frames 
        !            32: #        in the WAL.
        !            33: #
        !            34: #   5.*: Test that a call to sqlite3demo_superlock() uses the busy handler
        !            35: #        correctly to wait for existing clients to clear on a WAL database.
        !            36: #        And returns SQLITE_BUSY if no busy handler is defined or the busy
        !            37: #        handler returns 0 before said clients relinquish their locks.
        !            38: #
        !            39: #   6.*: Test that if a superlocked WAL database is overwritten, existing
        !            40: #        clients run the recovery to build the new wal-index after the 
        !            41: #        superlock is released.
        !            42: #        
        !            43: #
        !            44: 
        !            45: do_execsql_test 1.1 {
        !            46:   CREATE TABLE t1(a, b);
        !            47:   INSERT INTO t1 VALUES(1, 2);
        !            48:   PRAGMA journal_mode = DELETE;
        !            49: } {delete}
        !            50: 
        !            51: ifcapable !wal {
        !            52:   finish_test
        !            53:   return
        !            54: }
        !            55: 
        !            56: do_test 1.2 { sqlite3demo_superlock unlock test.db } {unlock}
        !            57: do_catchsql_test 1.3 { SELECT * FROM t1 } {1 {database is locked}}
        !            58: do_test 1.4 { unlock } {}
        !            59: 
        !            60: do_execsql_test 2.1 { 
        !            61:   INSERT INTO t1 VALUES(3, 4);
        !            62:   PRAGMA journal_mode = WAL;
        !            63: } {wal}
        !            64: 
        !            65: do_test 2.2 { sqlite3demo_superlock unlock test.db } {unlock}
        !            66: do_catchsql_test 2.3 { SELECT * FROM t1 }           {1 {database is locked}}
        !            67: do_catchsql_test 2.4 { INSERT INTO t1 VALUES(5, 6)} {1 {database is locked}}
        !            68: do_catchsql_test 2.5 { PRAGMA wal_checkpoint }      {0 {1 -1 -1}}
        !            69: do_test 2.6 { unlock } {}
        !            70: 
        !            71: do_execsql_test 3.1 { INSERT INTO t1 VALUES(3, 4) } 
        !            72: 
        !            73: do_test 3.2 { sqlite3demo_superlock unlock test.db } {unlock}
        !            74: do_catchsql_test 3.3 { SELECT * FROM t1 }           {1 {database is locked}}
        !            75: do_catchsql_test 3.4 { INSERT INTO t1 VALUES(5, 6)} {1 {database is locked}}
        !            76: do_catchsql_test 3.5 { PRAGMA wal_checkpoint }      {0 {1 -1 -1}}
        !            77: do_test 3.6 { unlock } {}
        !            78: 
        !            79: # At this point the WAL file consists of a single frame only - written
        !            80: # by test case 3.1. If the ZERO_DAMAGE flag were not set, it would consist
        !            81: # of two frames - the frame written by 3.1 and a padding frame.
        !            82: do_execsql_test 4.1 { PRAGMA wal_checkpoint } {0 1 1}
        !            83: 
        !            84: do_test 4.2 { sqlite3demo_superlock unlock test.db } {unlock}
        !            85: do_catchsql_test 4.3 { SELECT * FROM t1 }           {1 {database is locked}}
        !            86: do_catchsql_test 4.4 { INSERT INTO t1 VALUES(5, 6)} {1 {database is locked}}
        !            87: do_catchsql_test 4.5 { PRAGMA wal_checkpoint }      {0 {1 -1 -1}}
        !            88: do_test 4.6 { unlock } {}
        !            89: 
        !            90: do_multiclient_test tn {
        !            91: 
        !            92:   proc busyhandler {x} {
        !            93:     switch -- $x {
        !            94:       1 { sql1 "COMMIT" }
        !            95:       2 { sql2 "COMMIT" }
        !            96:       3 { sql3 "COMMIT" }
        !            97:     }
        !            98:     lappend ::busylist $x
        !            99:     return 1
        !           100:   }
        !           101:   set ::busylist [list]
        !           102: 
        !           103:   do_test 5.$tn.1 {
        !           104:     sql1 {
        !           105:       CREATE TABLE t1(a, b);
        !           106:       PRAGMA journal_mode = WAL;
        !           107:       INSERT INTO t1 VALUES(1, 2);
        !           108:     }
        !           109:   } {wal}
        !           110: 
        !           111:   do_test 5.$tn.2 {
        !           112:     sql1 { BEGIN ; SELECT * FROM t1 }
        !           113:     sql2 { BEGIN ; INSERT INTO t1 VALUES(3, 4) }
        !           114:     sql3 { BEGIN ; SELECT * FROM t1 }
        !           115:   } {1 2}
        !           116: 
        !           117:   do_test 5.$tn.3 {
        !           118:     set ::busylist [list]
        !           119:     sqlite3demo_superlock unlock test.db "" busyhandler
        !           120:     set ::busylist
        !           121:   } {0 1 2 3}
        !           122: 
        !           123:   do_test 5.$tn.4 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
        !           124:   do_test 5.$tn.5        !           125:     csql3 { INSERT INTO t1 VALUES(5, 6) } 
        !           126:   } {1 {database is locked}}
        !           127:   do_test 5.$tn.6 { csql1 "PRAGMA wal_checkpoint" } {0 {1 -1 -1}}
        !           128: 
        !           129:   do_test 5.$tn.7 { unlock } {}
        !           130: 
        !           131:   
        !           132:   do_test 5.$tn.8 {
        !           133:     sql1 { BEGIN ; SELECT * FROM t1 }
        !           134:     sql2 { BEGIN ; INSERT INTO t1 VALUES(5, 6) }
        !           135:     sql3 { BEGIN ; SELECT * FROM t1 }
        !           136:   } {1 2 3 4}
        !           137: 
        !           138:   do_test 5.$tn.9        !           139:     list [catch {sqlite3demo_superlock unlock test.db} msg] $msg
        !           140:   } {1 {database is locked}}
        !           141:   do_test 5.$tn.10 { 
        !           142:     sql1 COMMIT
        !           143:     list [catch {sqlite3demo_superlock unlock test.db} msg] $msg
        !           144:   } {1 {database is locked}}
        !           145:   do_test 5.$tn.11 { 
        !           146:     sql2 COMMIT
        !           147:     list [catch {sqlite3demo_superlock unlock test.db} msg] $msg
        !           148:   } {1 {database is locked}}
        !           149:   do_test 5.$tn.12 { 
        !           150:     sql3 COMMIT
        !           151:     list [catch {sqlite3demo_superlock unlock test.db} msg] $msg
        !           152:   } {0 unlock}
        !           153:   unlock
        !           154: 
        !           155: 
        !           156:   do_test 5.$tn.13 { sql1 { SELECT * FROM t1 } } {1 2 3 4 5 6}
        !           157:   do_test 5.$tn.14 { sql2 { SELECT * FROM t1 } } {1 2 3 4 5 6}
        !           158:   do_test 5.$tn.15 { sqlite3demo_superlock unlock test.db } {unlock}
        !           159:   do_test 5.$tn.16 { unlock } {}
        !           160:   do_test 5.$tn.17 { sql2 { SELECT * FROM t1 } } {1 2 3 4 5 6}
        !           161:   do_test 5.$tn.18 { sql1 { SELECT * FROM t1 } } {1 2 3 4 5 6}
        !           162:   do_test 5.$tn.19 { sql2 { SELECT * FROM t1 } } {1 2 3 4 5 6}
        !           163: }
        !           164: 
        !           165: proc read_content {file} {
        !           166:   if {[file exists $file]==0} {return ""}
        !           167:   set fd [open $file]
        !           168:   fconfigure $fd -encoding binary -translation binary
        !           169:   set content [read $fd]
        !           170:   close $fd
        !           171:   return $content
        !           172: }
        !           173: 
        !           174: proc write_content {file content} {
        !           175:   set fd [open $file w+]
        !           176:   fconfigure $fd -encoding binary -translation binary
        !           177:   puts -nonewline $fd $content
        !           178:   close $fd
        !           179: }
        !           180: 
        !           181: # Both $file1 and $file2 are database files. This function takes a 
        !           182: # superlock on each, then exchanges the content of the two files (i.e.
        !           183: # overwrites $file1 with the initial contents of $file2, and overwrites
        !           184: # $file2 with the initial contents of $file1). The contents of any WAL 
        !           185: # file is also exchanged.
        !           186: #
        !           187: proc db_swap {file1 file2} {
        !           188:   sqlite3demo_superlock unlock1 $file1
        !           189:   sqlite3demo_superlock unlock2 $file2
        !           190: 
        !           191:   set db1 [read_content $file1]
        !           192:   set db2 [read_content $file2]
        !           193:   write_content $file1 $db2
        !           194:   write_content $file2 $db1
        !           195: 
        !           196:   set wal1 [read_content ${file1}-wal]
        !           197:   set wal2 [read_content ${file2}-wal]
        !           198:   write_content ${file1}-wal $wal2
        !           199:   write_content ${file2}-wal $wal1
        !           200: 
        !           201:   unlock1
        !           202:   unlock2
        !           203: }
        !           204: 
        !           205: forcedelete test.db
        !           206: sqlite3 db  test.db
        !           207: do_execsql_test 6.1 {
        !           208:   ATTACH 'test.db2' AS aux;
        !           209:   PRAGMA aux.journal_mode = wal;
        !           210:   CREATE TABLE aux.t2(x, y);
        !           211:   INSERT INTO aux.t2 VALUES('a', 'b');
        !           212:   PRAGMA schema_version = 450;
        !           213:   DETACH aux;
        !           214: 
        !           215:   PRAGMA main.journal_mode = wal;
        !           216:   CREATE TABLE t1(a, b);
        !           217:   INSERT INTO t1 VALUES(1, 2);
        !           218:   INSERT INTO t1 VALUES(3, 4);
        !           219:   SELECT * FROM t1;
        !           220: } {wal wal 1 2 3 4}
        !           221: 
        !           222: 
        !           223: db_swap test.db2 test.db
        !           224: do_catchsql_test 6.2 { SELECT * FROM t1 } {1 {no such table: t1}}
        !           225: do_catchsql_test 6.3 { SELECT * FROM t2 } {0 {a b}}
        !           226: 
        !           227: db_swap test.db2 test.db
        !           228: do_catchsql_test 6.4 { SELECT * FROM t1 } {0 {1 2 3 4}}
        !           229: do_catchsql_test 6.5 { SELECT * FROM t2 } {1 {no such table: t2}}
        !           230: 
        !           231: do_execsql_test  6.6 { PRAGMA wal_checkpoint } {0 0 0}
        !           232: 
        !           233: db_swap test.db2 test.db
        !           234: do_catchsql_test 6.7 { SELECT * FROM t1 } {1 {no such table: t1}}
        !           235: do_catchsql_test 6.8 { SELECT * FROM t2 } {0 {a b}}
        !           236: 
        !           237: db_swap test.db2 test.db
        !           238: do_catchsql_test 6.9 { SELECT * FROM t1 } {0 {1 2 3 4}}
        !           239: do_catchsql_test 6.10 { SELECT * FROM t2 } {1 {no such table: t2}}
        !           240: 
        !           241: do_execsql_test  6.11 { 
        !           242:   PRAGMA journal_mode = delete;
        !           243:   PRAGMA page_size = 512;
        !           244:   VACUUM;
        !           245:   PRAGMA journal_mode = wal;
        !           246:   INSERT INTO t1 VALUES(5, 6);
        !           247: } {delete wal}
        !           248: 
        !           249: db_swap test.db2 test.db
        !           250: do_catchsql_test 6.12 { SELECT * FROM t1 } {1 {no such table: t1}}
        !           251: do_catchsql_test 6.13 { SELECT * FROM t2 } {0 {a b}}
        !           252: 
        !           253: db_swap test.db2 test.db
        !           254: do_catchsql_test 6.14 { SELECT * FROM t1 } {0 {1 2 3 4 5 6}}
        !           255: do_catchsql_test 6.15 { SELECT * FROM t2 } {1 {no such table: t2}}
        !           256: 
        !           257: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>