Index: third_party/sqlite/src/test/walprotocol.test |
diff --git a/third_party/sqlite/src/test/walprotocol.test b/third_party/sqlite/src/test/walprotocol.test |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ee8d0b72a555553ea56f24f67525df4d42a7cf6b |
--- /dev/null |
+++ b/third_party/sqlite/src/test/walprotocol.test |
@@ -0,0 +1,177 @@ |
+# 2016 February 4 |
+# |
+# 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. |
+# |
+# More specifically, it tests "locking protocol" errors - errors that |
+# may be caused if one or more SQLite clients does not follow the expected |
+# locking protocol when accessing a wal-mode database. These tests take |
+# quite a while to run. |
+# |
+ |
+set testdir [file dirname $argv0] |
+source $testdir/tester.tcl |
+source $testdir/lock_common.tcl |
+source $testdir/wal_common.tcl |
+ifcapable !wal {finish_test ; return } |
+ |
+set testprefix walprotocol |
+ |
+#------------------------------------------------------------------------- |
+# When recovering the contents of a WAL file, a process obtains the WRITER |
+# lock, then locks all other bytes before commencing recovery. If it fails |
+# to lock all other bytes (because some other process is holding a read |
+# lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the |
+# caller. Test this (test case 1.3). |
+# |
+# Also test the effect of hitting an SQLITE_BUSY while attempting to obtain |
+# the WRITER lock (should be the same). Test case 1.4. |
+# |
+do_execsql_test 1.0 { |
+ PRAGMA journal_mode = wal; |
+ CREATE TABLE x(y); |
+ INSERT INTO x VALUES('z'); |
+} {wal} |
+ |
+proc lock_callback {method filename handle lock} { |
+ lappend ::locks $lock |
+} |
+do_test 1.1 { |
+ testvfs T |
+ T filter xShmLock |
+ T script lock_callback |
+ set ::locks [list] |
+ sqlite3 db test.db -vfs T |
+ execsql { SELECT * FROM x } |
+ lrange $::locks 0 3 |
+} [list {0 1 lock exclusive} {1 7 lock exclusive} \ |
+ {1 7 unlock exclusive} {0 1 unlock exclusive} \ |
+] |
+do_test 1.2 { |
+ db close |
+ set ::locks [list] |
+ sqlite3 db test.db -vfs T |
+ execsql { SELECT * FROM x } |
+ lrange $::locks 0 3 |
+} [list {0 1 lock exclusive} {1 7 lock exclusive} \ |
+ {1 7 unlock exclusive} {0 1 unlock exclusive} \ |
+] |
+proc lock_callback {method filename handle lock} { |
+ if {$lock == "1 7 lock exclusive"} { return SQLITE_BUSY } |
+ return SQLITE_OK |
+} |
+puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times." |
+puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite" |
+puts "# is built on unix without HAVE_USLEEP defined, it may be much longer." |
+do_test 1.3 { |
+ db close |
+ set ::locks [list] |
+ sqlite3 db test.db -vfs T |
+ catchsql { SELECT * FROM x } |
+} {1 {locking protocol}} |
+ |
+puts "# Warning: Same again!" |
+proc lock_callback {method filename handle lock} { |
+ if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY } |
+ return SQLITE_OK |
+} |
+do_test 1.4 { |
+ db close |
+ set ::locks [list] |
+ sqlite3 db test.db -vfs T |
+ catchsql { SELECT * FROM x } |
+} {1 {locking protocol}} |
+db close |
+T delete |
+ |
+#------------------------------------------------------------------------- |
+# |
+do_test 2.1 { |
+ forcedelete test.db test.db-journal test.db wal |
+ sqlite3 db test.db |
+ sqlite3 db2 test.db |
+ execsql { |
+ PRAGMA auto_vacuum = off; |
+ PRAGMA journal_mode = WAL; |
+ CREATE TABLE b(c); |
+ INSERT INTO b VALUES('Tehran'); |
+ INSERT INTO b VALUES('Qom'); |
+ INSERT INTO b VALUES('Markazi'); |
+ PRAGMA wal_checkpoint; |
+ } |
+} {wal 0 5 5} |
+do_test 2.2 { |
+ execsql { SELECT * FROM b } |
+} {Tehran Qom Markazi} |
+do_test 2.3 { |
+ db eval { SELECT * FROM b } { |
+ db eval { INSERT INTO b VALUES('Qazvin') } |
+ set r [db2 eval { SELECT * FROM b }] |
+ break |
+ } |
+ set r |
+} {Tehran Qom Markazi Qazvin} |
+do_test 2.4 { |
+ execsql { |
+ INSERT INTO b VALUES('Gilan'); |
+ INSERT INTO b VALUES('Ardabil'); |
+ } |
+} {} |
+db2 close |
+ |
+faultsim_save_and_close |
+testvfs T -default 1 |
+faultsim_restore_and_reopen |
+T filter xShmLock |
+T script lock_callback |
+ |
+proc lock_callback {method file handle spec} { |
+ if {$spec == "1 7 unlock exclusive"} { |
+ T filter {} |
+ set ::r [catchsql { SELECT * FROM b } db2] |
+ } |
+} |
+sqlite3 db test.db |
+sqlite3 db2 test.db |
+do_test 2.5 { |
+ execsql { SELECT * FROM b } |
+} {Tehran Qom Markazi Qazvin Gilan Ardabil} |
+do_test 2.6 { |
+ set ::r |
+} {1 {locking protocol}} |
+ |
+db close |
+db2 close |
+ |
+faultsim_restore_and_reopen |
+sqlite3 db2 test.db |
+T filter xShmLock |
+T script lock_callback |
+proc lock_callback {method file handle spec} { |
+ if {$spec == "1 7 unlock exclusive"} { |
+ T filter {} |
+ set ::r [catchsql { SELECT * FROM b } db2] |
+ } |
+} |
+unset ::r |
+do_test 2.7 { |
+ execsql { SELECT * FROM b } |
+} {Tehran Qom Markazi Qazvin Gilan Ardabil} |
+do_test 2.8 { |
+ set ::r |
+} {1 {locking protocol}} |
+ |
+db close |
+db2 close |
+T delete |
+ |
+finish_test |