xref: /sqlite-3.40.0/test/lock4.test (revision 69aedc8d)
1bb5f18d2Sdrh# 2007 April 6
2bb5f18d2Sdrh#
3bb5f18d2Sdrh# The author disclaims copyright to this source code.  In place of
4bb5f18d2Sdrh# a legal notice, here is a blessing:
5bb5f18d2Sdrh#
6bb5f18d2Sdrh#    May you do good and not evil.
7bb5f18d2Sdrh#    May you find forgiveness for yourself and forgive others.
8bb5f18d2Sdrh#    May you share freely, never taking more than you give.
9bb5f18d2Sdrh#
10bb5f18d2Sdrh#***********************************************************************
11bb5f18d2Sdrh# This file implements regression tests for SQLite library.  The
12bb5f18d2Sdrh# focus of this script is database locks.
13bb5f18d2Sdrh#
14310bd20aSdrh# $Id: lock4.test,v 1.10 2009/05/06 00:52:41 drh Exp $
15bb5f18d2Sdrh
16bb5f18d2Sdrh
17bb5f18d2Sdrhset testdir [file dirname $argv0]
18bb5f18d2Sdrhsource $testdir/tester.tcl
19bb5f18d2Sdrh
20*69aedc8dSdanif {[atomic_batch_write test.db]} {
21*69aedc8dSdan  # This test uses two processes, one of which blocks until the other
22*69aedc8dSdan  # creates a *-journal file. Which doesn't work if atomic writes are
23*69aedc8dSdan  # available.
24*69aedc8dSdan  finish_test
25*69aedc8dSdan  return
26*69aedc8dSdan}
27*69aedc8dSdan
2868928b6cSdando_not_use_codec
2968928b6cSdan
30bb5f18d2Sdrh# Initialize the test.db database so that it is non-empty
31bb5f18d2Sdrh#
32bb5f18d2Sdrhdo_test lock4-1.1 {
331e9daa6aSdrh  db eval {
341e9daa6aSdrh     PRAGMA auto_vacuum=OFF;
351e9daa6aSdrh     CREATE TABLE t1(x);
361e9daa6aSdrh  }
37fda06befSmistachkin  forcedelete test2.db test2.db-journal
38bb5f18d2Sdrh  sqlite3 db2 test2.db
391e9daa6aSdrh  db2 eval {
401e9daa6aSdrh     PRAGMA auto_vacuum=OFF;
411e9daa6aSdrh     CREATE TABLE t2(x)
421e9daa6aSdrh  }
43bb5f18d2Sdrh  db2 close
44bb5f18d2Sdrh  list [file size test.db] [file size test2.db]
45bb5f18d2Sdrh} {2048 2048}
46bb5f18d2Sdrh
47bb5f18d2Sdrh# Create a script to drive a separate process that will
48bb5f18d2Sdrh#
49bb5f18d2Sdrh#     1.  Create a second database test2.db
50bb5f18d2Sdrh#     2.  Get an exclusive lock on test2.db
51bb5f18d2Sdrh#     3.  Add an entry to test.db in table t1, waiting as necessary.
52bb5f18d2Sdrh#     4.  Commit the change to test2.db.
53bb5f18d2Sdrh#
54bb5f18d2Sdrh# Meanwhile, this process will:
55bb5f18d2Sdrh#
56bb5f18d2Sdrh#     A.  Get an exclusive lock on test.db
57bb5f18d2Sdrh#     B.  Attempt to read from test2.db but get an SQLITE_BUSY error.
58bb5f18d2Sdrh#     C.  Commit the changes to test.db thus alloing the other process
59bb5f18d2Sdrh#         to continue.
60bb5f18d2Sdrh#
61bb5f18d2Sdrhdo_test lock4-1.2 {
62d5fe8d6cSdanielk1977
63d5fe8d6cSdanielk1977  # Create a script for the second process to run.
64d5fe8d6cSdanielk1977  #
65bb5f18d2Sdrh  set out [open test2-script.tcl w]
66c7a3bb94Sdrh  puts $out "sqlite3_test_control_pending_byte [set sqlite_pending_byte]"
67bb5f18d2Sdrh  puts $out {
68bb5f18d2Sdrh     sqlite3 db2 test2.db
69bb5f18d2Sdrh     db2 eval {
70bb5f18d2Sdrh        BEGIN;
71bb5f18d2Sdrh        INSERT INTO t2 VALUES(2);
72bb5f18d2Sdrh     }
73bb5f18d2Sdrh     sqlite3 db test.db
74bb5f18d2Sdrh     db timeout 1000000
75bb5f18d2Sdrh     db eval {
76bb5f18d2Sdrh        INSERT INTO t1 VALUES(2);
77bb5f18d2Sdrh     }
784ffb7b9aSdanielk1977     db close
79bb5f18d2Sdrh     db2 eval COMMIT
80bb5f18d2Sdrh     exit
81bb5f18d2Sdrh  }
82bb5f18d2Sdrh  close $out
83d5fe8d6cSdanielk1977
84d5fe8d6cSdanielk1977  # Begin a transaction on test.db.
85bb5f18d2Sdrh  db eval {
86d5fe8d6cSdanielk1977     BEGIN EXCLUSIVE;
87bb5f18d2Sdrh     INSERT INTO t1 VALUES(1);
88bb5f18d2Sdrh  }
89d5fe8d6cSdanielk1977
90d5fe8d6cSdanielk1977  # Kick off the second process.
91bb5f18d2Sdrh  exec [info nameofexec] ./test2-script.tcl &
92d5fe8d6cSdanielk1977
93d5fe8d6cSdanielk1977  # Wait until the second process has started its transaction on test2.db.
94bb5f18d2Sdrh  while {![file exists test2.db-journal]} {
95bb5f18d2Sdrh    after 10
96bb5f18d2Sdrh  }
97d5fe8d6cSdanielk1977
98d5fe8d6cSdanielk1977  # Try to write to test2.db. We are locked out.
99bb5f18d2Sdrh  sqlite3 db2 test2.db
100bb5f18d2Sdrh  catchsql {
101bb5f18d2Sdrh    INSERT INTO t2 VALUES(1)
102bb5f18d2Sdrh  } db2
103bb5f18d2Sdrh} {1 {database is locked}}
104bb5f18d2Sdrhdo_test lock4-1.3 {
105bb5f18d2Sdrh  db eval {
106bb5f18d2Sdrh     COMMIT;
107bb5f18d2Sdrh  }
108bb5f18d2Sdrh  while {[file exists test2.db-journal]} {
109bb5f18d2Sdrh    after 10
110bb5f18d2Sdrh  }
111d5fe8d6cSdanielk1977  # The other process has committed its transaction on test2.db by
112d5fe8d6cSdanielk1977  # deleting the journal file. But it might retain the lock for a
113d5fe8d6cSdanielk1977  # fraction longer
114d5fe8d6cSdanielk1977  #
115310bd20aSdrh  after 25
116bb5f18d2Sdrh  db2 eval {
117bb5f18d2Sdrh     SELECT * FROM t2
118bb5f18d2Sdrh  }
119bb5f18d2Sdrh} {2}
120bb5f18d2Sdrh
121bb5f18d2Sdrh
122bb5f18d2Sdrhdo_test lock4-999.1 {
123bb5f18d2Sdrh  rename db2 {}
124bb5f18d2Sdrh} {}
125bb5f18d2Sdrh
126bb5f18d2Sdrhfinish_test
127