drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 1 | # 2007 April 6 |
| 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 | # This file implements regression tests for SQLite library. The |
| 12 | # focus of this script is database locks. |
| 13 | # |
drh | 310bd20 | 2009-05-06 00:52:40 +0000 | [diff] [blame] | 14 | # $Id: lock4.test,v 1.10 2009/05/06 00:52:41 drh Exp $ |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 15 | |
| 16 | |
| 17 | set testdir [file dirname $argv0] |
| 18 | source $testdir/tester.tcl |
| 19 | |
dan | 69aedc8 | 2018-01-13 13:07:49 +0000 | [diff] [blame] | 20 | if {[atomic_batch_write test.db]} { |
| 21 | # This test uses two processes, one of which blocks until the other |
| 22 | # creates a *-journal file. Which doesn't work if atomic writes are |
| 23 | # available. |
| 24 | finish_test |
| 25 | return |
| 26 | } |
| 27 | |
dan | 68928b6 | 2010-06-22 13:46:43 +0000 | [diff] [blame] | 28 | do_not_use_codec |
| 29 | |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 30 | # Initialize the test.db database so that it is non-empty |
| 31 | # |
| 32 | do_test lock4-1.1 { |
drh | 1e9daa6 | 2007-04-06 21:42:22 +0000 | [diff] [blame] | 33 | db eval { |
| 34 | PRAGMA auto_vacuum=OFF; |
| 35 | CREATE TABLE t1(x); |
| 36 | } |
mistachkin | fda06be | 2011-08-02 00:57:34 +0000 | [diff] [blame] | 37 | forcedelete test2.db test2.db-journal |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 38 | sqlite3 db2 test2.db |
drh | 1e9daa6 | 2007-04-06 21:42:22 +0000 | [diff] [blame] | 39 | db2 eval { |
| 40 | PRAGMA auto_vacuum=OFF; |
| 41 | CREATE TABLE t2(x) |
| 42 | } |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 43 | db2 close |
| 44 | list [file size test.db] [file size test2.db] |
| 45 | } {2048 2048} |
| 46 | |
| 47 | # Create a script to drive a separate process that will |
| 48 | # |
| 49 | # 1. Create a second database test2.db |
| 50 | # 2. Get an exclusive lock on test2.db |
| 51 | # 3. Add an entry to test.db in table t1, waiting as necessary. |
| 52 | # 4. Commit the change to test2.db. |
| 53 | # |
| 54 | # Meanwhile, this process will: |
| 55 | # |
| 56 | # A. Get an exclusive lock on test.db |
| 57 | # B. Attempt to read from test2.db but get an SQLITE_BUSY error. |
| 58 | # C. Commit the changes to test.db thus alloing the other process |
| 59 | # to continue. |
| 60 | # |
| 61 | do_test lock4-1.2 { |
danielk1977 | d5fe8d6 | 2008-03-14 08:57:41 +0000 | [diff] [blame] | 62 | |
| 63 | # Create a script for the second process to run. |
| 64 | # |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 65 | set out [open test2-script.tcl w] |
drh | c7a3bb9 | 2009-02-05 16:31:45 +0000 | [diff] [blame] | 66 | puts $out "sqlite3_test_control_pending_byte [set sqlite_pending_byte]" |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 67 | puts $out { |
| 68 | sqlite3 db2 test2.db |
| 69 | db2 eval { |
| 70 | BEGIN; |
| 71 | INSERT INTO t2 VALUES(2); |
| 72 | } |
| 73 | sqlite3 db test.db |
| 74 | db timeout 1000000 |
| 75 | db eval { |
| 76 | INSERT INTO t1 VALUES(2); |
| 77 | } |
danielk1977 | 4ffb7b9 | 2008-03-13 04:53:52 +0000 | [diff] [blame] | 78 | db close |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 79 | db2 eval COMMIT |
| 80 | exit |
| 81 | } |
| 82 | close $out |
danielk1977 | d5fe8d6 | 2008-03-14 08:57:41 +0000 | [diff] [blame] | 83 | |
| 84 | # Begin a transaction on test.db. |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 85 | db eval { |
danielk1977 | d5fe8d6 | 2008-03-14 08:57:41 +0000 | [diff] [blame] | 86 | BEGIN EXCLUSIVE; |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 87 | INSERT INTO t1 VALUES(1); |
| 88 | } |
danielk1977 | d5fe8d6 | 2008-03-14 08:57:41 +0000 | [diff] [blame] | 89 | |
| 90 | # Kick off the second process. |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 91 | exec [info nameofexec] ./test2-script.tcl & |
danielk1977 | d5fe8d6 | 2008-03-14 08:57:41 +0000 | [diff] [blame] | 92 | |
| 93 | # Wait until the second process has started its transaction on test2.db. |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 94 | while {![file exists test2.db-journal]} { |
| 95 | after 10 |
| 96 | } |
danielk1977 | d5fe8d6 | 2008-03-14 08:57:41 +0000 | [diff] [blame] | 97 | |
| 98 | # Try to write to test2.db. We are locked out. |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 99 | sqlite3 db2 test2.db |
| 100 | catchsql { |
| 101 | INSERT INTO t2 VALUES(1) |
| 102 | } db2 |
| 103 | } {1 {database is locked}} |
| 104 | do_test lock4-1.3 { |
| 105 | db eval { |
| 106 | COMMIT; |
| 107 | } |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 108 | while {[file exists test2.db-journal]} { |
| 109 | after 10 |
| 110 | } |
danielk1977 | d5fe8d6 | 2008-03-14 08:57:41 +0000 | [diff] [blame] | 111 | # The other process has committed its transaction on test2.db by |
| 112 | # deleting the journal file. But it might retain the lock for a |
| 113 | # fraction longer |
| 114 | # |
drh | 310bd20 | 2009-05-06 00:52:40 +0000 | [diff] [blame] | 115 | after 25 |
drh | bb5f18d | 2007-04-06 18:23:17 +0000 | [diff] [blame] | 116 | db2 eval { |
| 117 | SELECT * FROM t2 |
| 118 | } |
| 119 | } {2} |
| 120 | |
| 121 | |
| 122 | do_test lock4-999.1 { |
| 123 | rename db2 {} |
| 124 | } {} |
| 125 | |
| 126 | finish_test |