1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
# 2010 March 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL" mode. The tests in this file use
# brute force methods, so may take a while to run.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/wal_common.tcl
source $testdir/lock_common.tcl
ifcapable !wal {finish_test ; return }
set testprefix walslow
proc reopen_db {} {
catch { db close }
forcedelete test.db test.db-wal
sqlite3 db test.db
execsql { PRAGMA journal_mode = wal }
}
db close
save_prng_state
for {set seed 1} {$seed<10} {incr seed} {
expr srand($seed)
restore_prng_state
reopen_db
do_test walslow-1.seed=$seed.0 {
execsql { CREATE TABLE t1(a, b) }
execsql { CREATE INDEX i1 ON t1(a) }
execsql { CREATE INDEX i2 ON t1(b) }
} {}
for {set iTest 1} {$iTest < 100} {incr iTest} {
do_test walslow-1.seed=$seed.$iTest.1 {
set w [expr int(rand()*2000)]
set x [expr int(rand()*2000)]
execsql { INSERT INTO t1 VALUES(randomblob($w), randomblob($x)) }
execsql { PRAGMA integrity_check }
} {ok}
do_test walslow-1.seed=$seed.$iTest.2 {
execsql "PRAGMA wal_checkpoint;"
execsql { PRAGMA integrity_check }
} {ok}
do_test walslow-1.seed=$seed.$iTest.3 {
forcedelete testX.db testX.db-wal
copy_file test.db testX.db
copy_file test.db-wal testX.db-wal
sqlite3 db2 testX.db
execsql { PRAGMA journal_mode = WAL } db2
execsql { PRAGMA integrity_check } db2
} {ok}
do_test walslow-1.seed=$seed.$iTest.4 {
execsql { SELECT count(*) FROM t1 WHERE a!=b } db2
} [execsql { SELECT count(*) FROM t1 WHERE a!=b }]
db2 close
}
}
#-------------------------------------------------------------------------
# Test case walslow-3.* tests that the checksum calculation detects single
# byte changes to frame or frame-header data and considers the frame
# invalid as a result.
#
reset_db
do_test 3.1 {
execsql {
PRAGMA synchronous = NORMAL;
PRAGMA page_size = 1024;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, randomblob(300));
INSERT INTO t1 VALUES(2, randomblob(300));
PRAGMA journal_mode = WAL;
INSERT INTO t1 VALUES(3, randomblob(300));
}
file size test.db-wal
} [wal_file_size 1 1024]
do_test 3.2 {
forcecopy test.db-wal test2.db-wal
forcecopy test.db test2.db
sqlite3 db2 test2.db
execsql { SELECT a FROM t1 } db2
} {1 2 3}
db2 close
forcecopy test.db test2.db
foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
do_test 3.3.$incr {
set FAIL 0
for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} {
forcecopy test.db-wal test2.db-wal
set fd [open test2.db-wal r+]
fconfigure $fd -encoding binary
fconfigure $fd -translation binary
seek $fd $iOff
binary scan [read $fd 1] c x
seek $fd $iOff
puts -nonewline $fd [binary format c [expr {($x+$incr)&0xFF}]]
close $fd
sqlite3 db2 test2.db
if { [execsql { SELECT a FROM t1 } db2] != "1 2" } {set FAIL 1}
db2 close
}
set FAIL
} {0}
}
#-------------------------------------------------------------------------
# Test large log summaries.
#
# In this case "large" usually means a log file that requires a wal-index
# mapping larger than 64KB (the default initial allocation). A 64KB wal-index
# is large enough for a log file that contains approximately 13100 frames.
# So the following tests create logs containing at least this many frames.
#
# 4.1.*: This test case creates a very large log file within the
# file-system (around 200MB). The log file does not contain
# any valid frames. Test that the database file can still be
# opened and queried, and that the invalid log file causes no
# problems.
#
# 4.2.*: Test that a process may create a large log file and query
# the database (including the log file that it itself created).
#
# 4.3.*: Test that if a very large log file is created, and then a
# second connection is opened on the database file, it is possible
# to query the database (and the very large log) using the
# second connection.
#
# 4.4.*: Same test as wal-13.3.*. Except in this case the second
# connection is opened by an external process.
#
set ::blobcnt 0
proc blob {nByte} {
incr ::blobcnt
return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte]
}
reset_db
do_execsql_test 4.1 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(x, y);
INSERT INTO "t1" VALUES('A',0);
CREATE TABLE t2(x, y);
INSERT INTO "t2" VALUES('B',2);
} {wal}
db close
do_test 4.1.1 {
list [file exists test.db] [file exists test.db-wal]
} {1 0}
do_test 4.1.2 {
set fd [open test.db-wal w]
seek $fd [expr 200*1024*1024]
puts $fd ""
close $fd
sqlite3 db test.db
execsql { SELECT * FROM t2 }
} {B 2}
do_test 4.1.3 {
db close
file exists test.db-wal
} {0}
do_test 4.2.1 {
sqlite3 db test.db
execsql { SELECT count(*) FROM t2 }
} {1}
do_test 4.2.2 {
db function blob blob
for {set i 0} {$i < 16} {incr i} {
execsql { INSERT INTO t2 SELECT blob(400), blob(400) FROM t2 }
}
execsql { SELECT count(*) FROM t2 }
} [expr int(pow(2, 16))]
do_test 4.2.3 {
expr [file size test.db-wal] > [wal_file_size 33000 1024]
} 1
do_multiclient_test tn {
incr tn 2
do_test 4.$tn.0 {
sql1 {
PRAGMA journal_mode = WAL;
CREATE TABLE t1(x);
INSERT INTO t1 SELECT randomblob(800);
}
sql1 { SELECT count(*) FROM t1 }
} {1}
for {set ii 1} {$ii<16} {incr ii} {
do_test 4.$tn.$ii.a {
sql2 { INSERT INTO t1 SELECT randomblob(800) FROM t1 }
sql2 { SELECT count(*) FROM t1 }
} [expr (1<<$ii)]
do_test 4.$tn.$ii.b {
sql1 { SELECT count(*) FROM t1 }
} [expr (1<<$ii)]
do_test 4.$tn.$ii.c {
sql1 { SELECT count(*) FROM t1 }
} [expr (1<<$ii)]
do_test 4.$tn.$ii.d {
sql1 { PRAGMA integrity_check }
} {ok}
}
}
finish_test
|