sl@0: # 2007 April 6 sl@0: # sl@0: # The author disclaims copyright to this source code. In place of sl@0: # a legal notice, here is a blessing: sl@0: # sl@0: # May you do good and not evil. sl@0: # May you find forgiveness for yourself and forgive others. sl@0: # May you share freely, never taking more than you give. sl@0: # sl@0: #*********************************************************************** sl@0: # This file implements regression tests for SQLite library. The sl@0: # focus of this script is database locks. sl@0: # sl@0: # $Id: lock4.test,v 1.8 2008/03/14 08:57:42 danielk1977 Exp $ sl@0: sl@0: sl@0: set testdir [file dirname $argv0] sl@0: source $testdir/tester.tcl sl@0: sl@0: # Initialize the test.db database so that it is non-empty sl@0: # sl@0: do_test lock4-1.1 { sl@0: db eval { sl@0: PRAGMA auto_vacuum=OFF; sl@0: CREATE TABLE t1(x); sl@0: } sl@0: file delete -force test2.db test2.db-journal sl@0: sqlite3 db2 test2.db sl@0: db2 eval { sl@0: PRAGMA auto_vacuum=OFF; sl@0: CREATE TABLE t2(x) sl@0: } sl@0: db2 close sl@0: list [file size test.db] [file size test2.db] sl@0: } {2048 2048} sl@0: sl@0: # Create a script to drive a separate process that will sl@0: # sl@0: # 1. Create a second database test2.db sl@0: # 2. Get an exclusive lock on test2.db sl@0: # 3. Add an entry to test.db in table t1, waiting as necessary. sl@0: # 4. Commit the change to test2.db. sl@0: # sl@0: # Meanwhile, this process will: sl@0: # sl@0: # A. Get an exclusive lock on test.db sl@0: # B. Attempt to read from test2.db but get an SQLITE_BUSY error. sl@0: # C. Commit the changes to test.db thus alloing the other process sl@0: # to continue. sl@0: # sl@0: do_test lock4-1.2 { sl@0: sl@0: # Create a script for the second process to run. sl@0: # sl@0: set out [open test2-script.tcl w] sl@0: puts $out "set sqlite_pending_byte [set sqlite_pending_byte]" sl@0: puts $out { sl@0: sqlite3 db2 test2.db sl@0: db2 eval { sl@0: BEGIN; sl@0: INSERT INTO t2 VALUES(2); sl@0: } sl@0: sqlite3 db test.db sl@0: db timeout 1000000 sl@0: db eval { sl@0: INSERT INTO t1 VALUES(2); sl@0: } sl@0: db close sl@0: db2 eval COMMIT sl@0: exit sl@0: } sl@0: close $out sl@0: sl@0: # Begin a transaction on test.db. sl@0: db eval { sl@0: BEGIN EXCLUSIVE; sl@0: INSERT INTO t1 VALUES(1); sl@0: } sl@0: sl@0: # Kick off the second process. sl@0: exec [info nameofexec] ./test2-script.tcl & sl@0: sl@0: # Wait until the second process has started its transaction on test2.db. sl@0: while {![file exists test2.db-journal]} { sl@0: after 10 sl@0: } sl@0: sl@0: # Try to write to test2.db. We are locked out. sl@0: sqlite3 db2 test2.db sl@0: catchsql { sl@0: INSERT INTO t2 VALUES(1) sl@0: } db2 sl@0: } {1 {database is locked}} sl@0: do_test lock4-1.3 { sl@0: db eval { sl@0: COMMIT; sl@0: } sl@0: while {[file exists test2.db-journal]} { sl@0: after 10 sl@0: } sl@0: # The other process has committed its transaction on test2.db by sl@0: # deleting the journal file. But it might retain the lock for a sl@0: # fraction longer sl@0: # sl@0: db2 eval { sl@0: SELECT * FROM t2 sl@0: } sl@0: } {2} sl@0: sl@0: sl@0: do_test lock4-999.1 { sl@0: rename db2 {} sl@0: } {} sl@0: sl@0: finish_test