17eb05752Sdan# 2012 October 15 27eb05752Sdan# 37eb05752Sdan# The author disclaims copyright to this source code. In place of 47eb05752Sdan# a legal notice, here is a blessing: 57eb05752Sdan# 67eb05752Sdan# May you do good and not evil. 77eb05752Sdan# May you find forgiveness for yourself and forgive others. 87eb05752Sdan# May you share freely, never taking more than you give. 97eb05752Sdan# 107eb05752Sdan#*********************************************************************** 117eb05752Sdan# 127eb05752Sdan# This test case tests that a problem causing a failing assert() has 137eb05752Sdan# been fixed. The problem occurred if a writer process with a subset 147eb05752Sdan# of the *shm file mapped rolled back a transaction begun after the 157eb05752Sdan# entire WAL file was checkpointed into the db file (i.e. a transaction 167eb05752Sdan# that would have restarted the WAL file from the beginning). 177eb05752Sdan# 187eb05752Sdan 197eb05752Sdanset testdir [file dirname $argv0] 207eb05752Sdansource $testdir/tester.tcl 217eb05752Sdanset testprefix wal9 227eb05752Sdan 237eb05752Sdansqlite3 db2 test.db 247eb05752Sdan 257eb05752Sdando_execsql_test 1.0 { 267eb05752Sdan PRAGMA page_size = 1024; 277eb05752Sdan PRAGMA journal_mode = WAL; 287eb05752Sdan PRAGMA wal_autocheckpoint = 0; 297eb05752Sdan CREATE TABLE t(x); 307eb05752Sdan} {wal 0} 317eb05752Sdan 327eb05752Sdando_test 1.1 { 337eb05752Sdan execsql "SELECT * FROM t" db2 347eb05752Sdan} {} 357eb05752Sdan 367eb05752Sdando_execsql_test 1.2 { 377eb05752Sdan BEGIN; 387eb05752Sdan INSERT INTO t VALUES(randomblob(100)); 397eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 407eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 417eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 427eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 437eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 447eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 457eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 467eb05752Sdan 477eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 487eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 497eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 507eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 517eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 527eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 537eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 547eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 557eb05752Sdan 567eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 577eb05752Sdan INSERT INTO t SELECT randomblob(100) FROM t; 587eb05752Sdan COMMIT; 597eb05752Sdan} {} 607eb05752Sdan 617eb05752Sdan# Check file sizes are as expected. The real requirement here is that 627eb05752Sdan# the *shm file is now more than one chunk (>32KiB). 63*8411b25cSdan# 64*8411b25cSdan# The sizes of various files are slightly different in normal and 65*8411b25cSdan# auto-vacuum mode. 667eb05752Sdando_test 1.3 { file size test.db } {1024} 67*8411b25cSdando_test 1.4 { expr {[file size test.db-wal]>(1500*1024)} } {1} 680fbb50eeSdrhdo_test 1.5 { expr {[file size test.db-shm]>32768} } {1} 69*8411b25cSdando_test 1.6 { 70*8411b25cSdan foreach {a b c} [db eval {PRAGMA wal_checkpoint}] break 71*8411b25cSdan list [expr {$a==0}] [expr {$b>14500}] [expr {$c>14500}] [expr {$b==$c}] 72*8411b25cSdan} {1 1 1 1} 737eb05752Sdan 747eb05752Sdan# At this point connection [db2] has mapped the first 32KB of the *shm file 757eb05752Sdan# only. Because the entire WAL file has been checkpointed, it is not 767eb05752Sdan# necessary to map any more of the *-shm file to read or write the database 777eb05752Sdan# (since all data will be read directly from the db file). 787eb05752Sdan# 797eb05752Sdan# However, at one point if a transaction that had not yet written to the 807eb05752Sdan# WAL file was rolled back an assert() attempting to verify that the entire 817eb05752Sdan# *-shm file was mapped would fail. If NDEBUG was defined (and the assert() 827eb05752Sdan# disabled) this bug caused SQLite to ignore the return code of a mmap() 837eb05752Sdan# call. 847eb05752Sdan# 857eb05752Sdando_test 1.7 { 867eb05752Sdan execsql { 877eb05752Sdan BEGIN; 887eb05752Sdan INSERT INTO t VALUES('hello'); 897eb05752Sdan ROLLBACK; 907eb05752Sdan } db2 917eb05752Sdan} {} 927eb05752Sdandb2 close 937eb05752Sdan 947eb05752Sdanfinish_test 95