# 2018 December 13 # # 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=WAL2" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl set testprefix wal2recover ifcapable !wal {finish_test ; return } proc db_copy {from to} { forcecopy $from $to forcecopy ${from}-wal ${to}-wal forcecopy ${from}-wal2 ${to}-wal2 } do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); CREATE INDEX t1a ON t1(a); CREATE INDEX t1b ON t1(b); CREATE INDEX t1c ON t1(c); PRAGMA journal_mode = wal2; PRAGMA journal_size_limit = 15000; PRAGMA wal_autocheckpoint = 0; } {wal2 15000 0} do_test 1.1 { for {set i 1} {$i <= 1000} {incr i} { execsql { INSERT INTO t1 VALUES(random(), random(), random()) } db_copy test.db test.db2 sqlite3 db2 test.db set res [execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } db2] db2 close if {$res != [list $i ok]} { error "failure on iteration $i" } } set {} {} } {} #-------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { CREATE TABLE t1(x UNIQUE); CREATE TABLE t2(x UNIQUE); PRAGMA journal_mode = wal2; PRAGMA journal_size_limit = 10000; PRAGMA wal_autocheckpoint = 0; BEGIN; INSERT INTO t1 VALUES(randomblob(4000)); INSERT INTO t1 VALUES(randomblob(4000)); INSERT INTO t1 VALUES(randomblob(4000)); COMMIT; BEGIN; INSERT INTO t2 VALUES(randomblob(4000)); INSERT INTO t2 VALUES(randomblob(4000)); INSERT INTO t2 VALUES(randomblob(4000)); COMMIT; } {wal2 10000 0} do_test 2.0.1 { list [file size test.db] [file size test.db-wal] [file size test.db-wal2] } {5120 28328 28328} # Test recovery with both wal files intact. # do_test 2.1 { db_copy test.db test.db2 sqlite3 db2 test.db2 execsql { SELECT count(*) FROM t1; SELECT count(*) FROM t2; PRAGMA integrity_check; } db2 } {3 3 ok} do_test 2.2 { db2 close db_copy test.db test.db2 hexio_write test.db2-wal 16 12345678 sqlite3 db2 test.db2 execsql { SELECT count(*) FROM t1; SELECT count(*) FROM t2; } db2 } {0 3} do_test 2.3 { db2 close db_copy test.db test.db2 hexio_write test.db2-wal2 16 12345678 sqlite3 db2 test.db2 execsql { SELECT count(*) FROM t1; SELECT count(*) FROM t2; PRAGMA integrity_check; } db2 } {3 0 ok} do_test 2.4 { db2 close db_copy test.db test.db2 forcecopy test.db-wal test.db2-wal2 sqlite3 db2 test.db2 execsql { SELECT count(*) FROM t1; SELECT count(*) FROM t2; PRAGMA integrity_check; } db2 } {3 0 ok} do_test 2.5 { db2 close db_copy test.db test.db2 forcecopy test.db-wal test.db2-wal2 forcecopy test.db-wal2 test.db2-wal sqlite3 db2 test.db2 execsql { SELECT count(*) FROM t1; SELECT count(*) FROM t2; PRAGMA integrity_check; } db2 } {3 3 ok} do_test 2.6 { db2 close db_copy test.db test.db2 forcecopy test.db-wal test.db2-wal2 close [open test.db-wal w] sqlite3 db2 test.db2 execsql { SELECT count(*) FROM t1; SELECT count(*) FROM t2; PRAGMA integrity_check; } db2 } {3 0 ok} do_test 2.7 { db2 close db_copy test.db test.db2 forcedelete test.db2-wal sqlite3 db2 test.db2 execsql { SELECT count(*) FROM t1; SELECT count(*) FROM t2; PRAGMA integrity_check; } db2 } {0 0 ok} db2 close #------------------------------------------------------------------------- # reset_db do_execsql_test 3.0 { CREATE TABLE t1(a TEXT, b TEXT, c TEXT); CREATE INDEX t1a ON t1(a); CREATE INDEX t1b ON t1(b); CREATE INDEX t1c ON t1(c); PRAGMA journal_mode = wal2; PRAGMA journal_size_limit = 10000; PRAGMA wal_autocheckpoint = 0; PRAGMA cache_size = 5; } {wal2 10000 0} do_execsql_test 3.1 { WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200) INSERT INTO t1 SELECT i, i, i FROM s; INSERT INTO t1 VALUES(201, 201, 201); } {} do_test 3.2 { list [file size test.db] [file size test.db-wal] [file size test.db-wal2] } {5120 15752 4224} do_test 3.3 { forcecopy test.db test.db2 forcecopy test.db-wal test.db2-wal forcecopy test.db-wal2 test.db2-wal2 sqlite3 db2 test.db2 execsql { PRAGMA journal_size_limit = 10000; PRAGMA wal_autocheckpoint = 0; PRAGMA cache_size = 5; BEGIN; WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200) INSERT INTO t1 SELECT i, i, i FROM s; } db2 list [file size test.db2] [file size test.db2-wal] [file size test.db2-wal2] } {5120 15752 23088} if {$tcl_platform(platform)!="windows"} { # These cannot be run under windows, as the *-shm file may not be read # while it is locked by the database connection. do_test 3.4 { set fd [open test.db2-shm] fconfigure $fd -translation binary set data [read $fd] close $fd set fd [open test.db-shm w] fconfigure $fd -translation binary puts -nonewline $fd $data close $fd execsql { WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10) INSERT INTO t1 SELECT i, i, i FROM s; SELECT count(*) FROM t1; PRAGMA integrity_check; } } {211 ok} do_test 3.5 { list [file size test.db] [file size test.db-wal] [file size test.db-wal2] } {5120 15752 18896} } #------------------------------------------------------------------------- # reset_db do_execsql_test 4.0 { PRAGMA journal_mode = wal2; CREATE TABLE xyz(x, y, z); INSERT INTO xyz VALUES('x', 'y', 'z'); } {wal2} db close do_test 4.1 { close [open test.db-wal w] file mkdir test.db-wal2 sqlite3 db test.db catchsql { SELECT * FROM xyz } } {1 {unable to open database file}} db close file delete test.db-wal2 db2 close do_test 4.2 { sqlite3 db test.db execsql { INSERT INTO xyz VALUES('a', 'b', 'c'); } forcecopy test.db test.db2 forcecopy test.db-wal test.db2-wal forcedelete test.db2-wal2 file mkdir test.db2-wal2 sqlite3 db2 test.db2 catchsql { SELECT * FROM xyz } db2 } {1 {unable to open database file}} db2 close file delete test.db2-wal2 finish_test