1# 2010 October 29 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 13set testdir [file dirname $argv0] 14source $testdir/tester.tcl 15source $testdir/malloc_common.tcl 16 17set g_chunk_size 2147483648 18set g_max_chunks 32 19 20# This handles appending the chunk number 21# to the end of the filename. if 22# SQLITE_MULTIPLEX_EXT_OVWR is defined, then 23# it overwrites the last 2 bytes of the 24# file name with the chunk number. 25proc multiplex_name {name chunk} { 26 if {$chunk==0} { return $name } 27 set num [format "%02d" $chunk] 28 ifcapable {multiplex_ext_overwrite} { 29 set name [string range $name 0 [expr [string length $name]-2-1]] 30 } 31 return $name$num 32} 33 34# This saves off the parameters and calls the 35# underlying sqlite3_multiplex_set() API. 36proc multiplex_set {chunk_size max_chunks} { 37 global g_chunk_size 38 global g_max_chunks 39 set g_chunk_size $chunk_size 40 set g_max_chunks $max_chunks 41 sqlite3_multiplex_set $chunk_size $max_chunks 42} 43 44# This attempts to delete the base file and 45# and files with the chunk extension. 46proc multiplex_delete {name} { 47 global g_max_chunks 48 for {set i 0} {$i<$g_max_chunks} {incr i} { 49 forcedelete [multiplex_name $name $i] 50 forcedelete [multiplex_name $name-journal $i] 51 forcedelete [multiplex_name $name-wal $i] 52 } 53} 54 55db close 56 57#------------------------------------------------------------------------- 58# multiplex-1.1.*: Test initialize and shutdown. 59 60do_test multiplex-1.1 { sqlite3_multiplex_initialize nosuchvfs 1 } {SQLITE_ERROR} 61do_test multiplex-1.2 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} 62do_test multiplex-1.3 { sqlite3_multiplex_initialize "" 1 } {SQLITE_MISUSE} 63do_test multiplex-1.4 { sqlite3_multiplex_shutdown } {SQLITE_OK} 64 65do_test multiplex-1.5 { sqlite3_multiplex_initialize "" 0 } {SQLITE_OK} 66do_test multiplex-1.6 { sqlite3_multiplex_shutdown } {SQLITE_OK} 67do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} 68do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK} 69 70do_test multiplex-1.9 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} 71do_test multiplex-1.10.1 { multiplex_set 32768 16 } {SQLITE_OK} 72do_test multiplex-1.10.2 { multiplex_set 32768 -1 } {SQLITE_MISUSE} 73do_test multiplex-1.10.3 { multiplex_set -1 16 } {SQLITE_MISUSE} 74do_test multiplex-1.10.4 { multiplex_set 31 16 } {SQLITE_MISUSE} 75do_test multiplex-1.10.5 { multiplex_set 32768 100 } {SQLITE_MISUSE} 76do_test multiplex-1.11 { sqlite3_multiplex_shutdown } {SQLITE_OK} 77 78 79#------------------------------------------------------------------------- 80# Some simple warm-body tests with a single database file in rollback 81# mode: 82# 83# multiplex-2.1.*: Test simple writing to a multiplex file. 84# 85# multiplex-2.2.*: More writing. 86# 87# multiplex-2.3.*: Open and close a second db. 88# 89# multiplex-2.4.*: Try to shutdown the multiplex system before closing the db 90# file. Check that this fails and the multiplex system still works 91# afterwards. Then close the database and successfully shut 92# down the multiplex system. 93# 94# multiplex-2.5.*: More reading/writing. 95# 96# multiplex-2.6.*: More reading/writing with varying small chunk sizes, as 97# well as varying journal mode. 98 99sqlite3_multiplex_initialize "" 1 100multiplex_set 32768 16 101 102do_test multiplex-2.1.2 { 103 sqlite3 db test.db 104 execsql { 105 PRAGMA page_size=1024; 106 PRAGMA auto_vacuum=OFF; 107 PRAGMA journal_mode=DELETE; 108 } 109 execsql { 110 CREATE TABLE t1(a, b); 111 INSERT INTO t1 VALUES(1, randomblob(1100)); 112 INSERT INTO t1 VALUES(2, randomblob(1100)); 113 } 114} {} 115do_test multiplex-2.1.3 { file size [multiplex_name test.db 0] } {4096} 116do_test multiplex-2.1.4 { 117 execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } 118} {} 119 120do_test multiplex-2.2.1 { 121 execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } 122} {} 123do_test multiplex-2.2.3 { file size [multiplex_name test.db 0] } {6144} 124 125do_test multiplex-2.3.1 { 126 sqlite3 db2 bak.db 127 db2 close 128} {} 129 130do_test multiplex-2.4.1 { 131 sqlite3_multiplex_shutdown 132} {SQLITE_MISUSE} 133do_test multiplex-2.4.2 { 134 execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } 135} {} 136do_test multiplex-2.4.4 { file size [multiplex_name test.db 0] } {7168} 137do_test multiplex-2.4.99 { 138 db close 139 sqlite3_multiplex_shutdown 140} {SQLITE_OK} 141 142 143do_test multiplex-2.5.1 { 144 multiplex_delete test.db 145 sqlite3_multiplex_initialize "" 1 146 multiplex_set 4096 16 147} {SQLITE_OK} 148 149do_test multiplex-2.5.2 { 150 sqlite3 db test.db 151 execsql { 152 PRAGMA page_size = 1024; 153 PRAGMA journal_mode = delete; 154 PRAGMA auto_vacuum = off; 155 CREATE TABLE t1(a PRIMARY KEY, b); 156 } 157} {delete} 158 159do_test multiplex-2.5.3 { 160 execsql { 161 INSERT INTO t1 VALUES(1, 'one'); 162 INSERT INTO t1 VALUES(2, randomblob(4000)); 163 INSERT INTO t1 VALUES(3, 'three'); 164 INSERT INTO t1 VALUES(4, randomblob(4000)); 165 INSERT INTO t1 VALUES(5, 'five') 166 } 167} {} 168 169do_test multiplex-2.5.4 { 170 db eval {SELECT * FROM t1 WHERE a=1} 171} {1 one} 172 173do_test multiplex-2.5.5 { 174 db eval {SELECT * FROM t1 WHERE a=3} 175} {3 three} 176 177do_test multiplex-2.5.6 { 178 db eval {SELECT * FROM t1 WHERE a=5} 179} {5 five} 180 181do_test multiplex-2.5.7 { 182 db eval {SELECT a,length(b) FROM t1 WHERE a=2} 183} {2 4000} 184 185do_test multiplex-2.5.8 { 186 db eval {SELECT a,length(b) FROM t1 WHERE a=4} 187} {4 4000} 188 189do_test multiplex-2.5.9 { file size [multiplex_name test.db 0] } [list $g_chunk_size] 190do_test multiplex-2.5.10 { file size [multiplex_name test.db 1] } [list $g_chunk_size] 191 192do_test multiplex-2.5.99 { 193 db close 194 sqlite3_multiplex_shutdown 195} {SQLITE_OK} 196 197 198set all_journal_modes {delete persist truncate memory off} 199foreach jmode $all_journal_modes { 200 for {set sz 151} {$sz<8000} {set sz [expr $sz+419]} { 201 202 do_test multiplex-2.6.1.$sz.$jmode { 203 multiplex_delete test.db 204 sqlite3_multiplex_initialize "" 1 205 multiplex_set $sz 32 206 } {SQLITE_OK} 207 208 do_test multiplex-2.6.2.$sz.$jmode { 209 sqlite3 db test.db 210 db eval { 211 PRAGMA page_size = 1024; 212 PRAGMA auto_vacuum = off; 213 } 214 db eval "PRAGMA journal_mode = $jmode;" 215 } $jmode 216 217 do_test multiplex-2.6.3.$sz.$jmode { 218 execsql { 219 CREATE TABLE t1(a PRIMARY KEY, b); 220 INSERT INTO t1 VALUES(1, 'one'); 221 INSERT INTO t1 VALUES(2, randomblob($g_chunk_size)); 222 } 223 } {} 224 225 do_test multiplex-2.6.4.$sz.$jmode { 226 db eval {SELECT b FROM t1 WHERE a=1} 227 } {one} 228 229 do_test multiplex-2.6.5.$sz.$jmode { 230 db eval {SELECT length(b) FROM t1 WHERE a=2} 231 } [list $g_chunk_size] 232 233 do_test multiplex-2.6.6.$sz.$jmode { file size [multiplex_name test.db 0] } [list $g_chunk_size] 234 235 do_test multiplex-2.6.99.$sz.$jmode { 236 db close 237 sqlite3_multiplex_shutdown 238 } {SQLITE_OK} 239 240 } 241} 242 243#------------------------------------------------------------------------- 244# Try some tests with more than one connection to a database file. Still 245# in rollback mode. 246# 247# multiplex-3.1.*: Two connections to a single database file. 248# 249# multiplex-3.2.*: Two connections to each of several database files (that 250# are in the same multiplex group). 251# 252do_test multiplex-3.1.1 { 253 multiplex_delete test.db 254 sqlite3_multiplex_initialize "" 1 255 multiplex_set 32768 16 256} {SQLITE_OK} 257do_test multiplex-3.1.2 { 258 sqlite3 db test.db 259 execsql { 260 PRAGMA page_size = 1024; 261 PRAGMA journal_mode = delete; 262 PRAGMA auto_vacuum = off; 263 CREATE TABLE t1(a PRIMARY KEY, b); 264 INSERT INTO t1 VALUES(1, 'one'); 265 } 266 file size [multiplex_name test.db 0] 267} {3072} 268do_test multiplex-3.1.3 { 269 sqlite3 db2 test.db 270 execsql { CREATE TABLE t2(a, b) } db2 271} {} 272do_test multiplex-3.1.4 { 273 execsql { CREATE TABLE t3(a, b) } 274} {} 275do_test multiplex-3.1.5 { 276 catchsql { CREATE TABLE t3(a, b) } 277} {1 {table t3 already exists}} 278do_test multiplex-3.1.6 { 279 db close 280 db2 close 281} {} 282 283do_test multiplex-3.2.1a { 284 285 multiplex_delete test.db 286 multiplex_delete test2.db 287 288 sqlite3 db1a test.db 289 sqlite3 db2a test2.db 290 291 foreach db {db1a db2a} { 292 execsql { 293 PRAGMA page_size = 1024; 294 PRAGMA journal_mode = delete; 295 PRAGMA auto_vacuum = off; 296 CREATE TABLE t1(a, b); 297 } $db 298 } 299 300 list [file size [multiplex_name test.db 0]] [file size [multiplex_name test2.db 0]] 301} {2048 2048} 302 303do_test multiplex-3.2.1b { 304 sqlite3 db1b test.db 305 sqlite3 db2b test2.db 306} {} 307 308do_test multiplex-3.2.2 { execsql { INSERT INTO t1 VALUES('x', 'y') } db1a } {} 309do_test multiplex-3.2.3 { execsql { INSERT INTO t1 VALUES('v', 'w') } db1b } {} 310do_test multiplex-3.2.4 { execsql { INSERT INTO t1 VALUES('t', 'u') } db2a } {} 311do_test multiplex-3.2.5 { execsql { INSERT INTO t1 VALUES('r', 's') } db2b } {} 312 313do_test multiplex-3.2.6 { 314 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a 315} {} 316do_test multiplex-3.2.7 { 317 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b 318} {} 319do_test multiplex-3.2.8 { 320 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a 321} {} 322do_test multiplex-3.2.9 { 323 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b 324} {} 325 326do_test multiplex-3.3.1 { 327 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a 328 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b 329 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a 330 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b 331} {} 332 333do_test multiplex-3.2.X { 334 foreach db {db1a db2a db2b db1b} { catch { $db close } } 335} {} 336 337#------------------------------------------------------------------------- 338# 339 340sqlite3_multiplex_initialize "" 1 341multiplex_set 32768 16 342 343# Return a list of all currently defined multiplexs. 344proc multiplex_list {} { 345 set allq {} 346 foreach q [sqlite3_multiplex_dump] { 347 lappend allq [lindex $q 0] 348 } 349 return [lsort $allq] 350} 351 352do_test multiplex-4.1.6 { 353 multiplex_delete test2.db 354 sqlite3 db test2.db 355 db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');} 356 set res [multiplex_list] 357 list [regexp {test2.db} $res] 358} {1} 359do_test multiplex-4.1.6a { 360 sqlite3 db2 test2.db 361 db2 eval {SELECT * FROM t2} 362} {tab-t2} 363do_test multiplex-4.1.7 { 364 execsql {INSERT INTO t2 VALUES(zeroblob(200000))} 365} {} 366do_test multiplex-4.1.8 { 367 sqlite3 db2 test2.db 368 db2 eval {SELECT count(*) FROM t2} 369} {2} 370do_test multiplex-4.1.8a { 371 db2 eval { DELETE FROM t2 WHERE x = 'tab-t2' } 372} {} 373do_test multiplex-4.1.8b { 374 sqlite3 db2 test2.db 375 db2 eval {SELECT count(*) FROM t2} 376} {1} 377 378 379do_test multiplex-4.1.9 { 380 execsql {INSERT INTO t2 VALUES(zeroblob(200000))} 381} {} 382do_test multiplex-4.1.10 { 383 set res [multiplex_list] 384 list [regexp {test2.db} $res] 385} {1} 386do_test multiplex-4.1.11 { 387 db2 close 388 set res [multiplex_list] 389 list [regexp {test2.db} $res] 390} {1} 391do_test multiplex-4.1.12 { 392 db close 393 multiplex_list 394} {} 395 396 397#------------------------------------------------------------------------- 398# The following tests test that the multiplex VFS handles malloc and IO 399# errors. 400# 401 402sqlite3_multiplex_initialize "" 1 403multiplex_set 32768 16 404 405do_faultsim_test multiplex-5.1 -prep { 406 catch {db close} 407} -body { 408 sqlite3 db test2.db 409} 410do_faultsim_test multiplex-5.2 -prep { 411 catch {db close} 412} -body { 413 sqlite3 db test.db 414} 415 416catch { db close } 417multiplex_delete test.db 418multiplex_delete test2.db 419 420do_test multiplex-5.3.prep { 421 sqlite3 db test.db 422 execsql { 423 PRAGMA auto_vacuum = 1; 424 PRAGMA page_size = 1024; 425 CREATE TABLE t1(a, b); 426 INSERT INTO t1 VALUES(10, zeroblob(1200)); 427 } 428 faultsim_save_and_close 429} {} 430do_faultsim_test multiplex-5.3 -prep { 431 faultsim_restore_and_reopen 432} -body { 433 execsql { DELETE FROM t1 } 434} 435 436do_test multiplex-5.4.1 { 437 catch { db close } 438 multiplex_delete test.db 439 file mkdir test.db 440 list [catch { sqlite3 db test.db } msg] $msg 441} {1 {unable to open database file}} 442catch { file delete test.db } 443 444do_faultsim_test multiplex-5.5 -prep { 445 catch { sqlite3_multiplex_shutdown } 446} -body { 447 sqlite3_multiplex_initialize "" 1 448 multiplex_set 32768 16 449} 450 451catch { sqlite3_multiplex_shutdown } 452finish_test 453