xref: /sqlite-3.40.0/test/busy2.test (revision cf2ad7ae)
12bfd35b8Sdan# 2020 June 30
22bfd35b8Sdan#
32bfd35b8Sdan# The author disclaims copyright to this source code.  In place of
42bfd35b8Sdan# a legal notice, here is a blessing:
52bfd35b8Sdan#
62bfd35b8Sdan#    May you do good and not evil.
72bfd35b8Sdan#    May you find forgiveness for yourself and forgive others.
82bfd35b8Sdan#    May you share freely, never taking more than you give.
92bfd35b8Sdan#
102bfd35b8Sdan#***********************************************************************
112bfd35b8Sdan# This file test the busy handler
122bfd35b8Sdan#
13*cf2ad7aeSdan# TESTRUNNER: slow
142bfd35b8Sdan
152bfd35b8Sdan
162bfd35b8Sdanset testdir [file dirname $argv0]
172bfd35b8Sdansource $testdir/tester.tcl
182bfd35b8Sdansource $testdir/lock_common.tcl
192bfd35b8Sdanset testprefix busy2
202bfd35b8Sdan
212bfd35b8Sdando_multiclient_test tn {
222bfd35b8Sdan  do_test 1.$tn.0 {
232bfd35b8Sdan    sql2 {
242bfd35b8Sdan      CREATE TABLE t1(a, b);
252bfd35b8Sdan      PRAGMA journal_mode = wal;
262bfd35b8Sdan      INSERT INTO t1 VALUES('A', 'B');
272bfd35b8Sdan    }
282bfd35b8Sdan  } {wal}
292bfd35b8Sdan
302bfd35b8Sdan  do_test 1.$tn.1 {
312bfd35b8Sdan    code1 { db timeout 1000 }
322bfd35b8Sdan    sql1 { SELECT * FROM t1 }
332bfd35b8Sdan  } {A B}
342bfd35b8Sdan
352bfd35b8Sdan  do_test 1.$tn.2 {
362bfd35b8Sdan    sql2 {
372bfd35b8Sdan      BEGIN;
382bfd35b8Sdan        INSERT INTO t1 VALUES('C', 'D');
392bfd35b8Sdan    }
402bfd35b8Sdan  } {}
412bfd35b8Sdan
422bfd35b8Sdan  do_test 1.$tn.3 {
432bfd35b8Sdan    set us [lindex [time { catch { sql1 { BEGIN EXCLUSIVE } } }] 0]
442bfd35b8Sdan    expr {$us>950000 && $us<1500000}
452bfd35b8Sdan  } {1}
462bfd35b8Sdan
472bfd35b8Sdan  do_test 1.$tn.4 {
482bfd35b8Sdan    sql2 {
492bfd35b8Sdan      COMMIT
502bfd35b8Sdan    }
512bfd35b8Sdan  } {}
522bfd35b8Sdan}
532bfd35b8Sdan
543f1d0f56Sdan#-------------------------------------------------------------------------
553f1d0f56Sdan
563f1d0f56Sdando_multiclient_test tn {
573f1d0f56Sdan  # Make the db a WAL mode db. And add a table and a row to it. Then open
583f1d0f56Sdan  # a second connection within process 1. Process 1 now has connections
593f1d0f56Sdan  # [db] and [db1.2], process 2 has connection [db2] only.
603f1d0f56Sdan  #
613f1d0f56Sdan  # Configure all connections to use a 1000 ms timeout.
623f1d0f56Sdan  #
633f1d0f56Sdan  do_test 2.$tn.0 {
6407066d90Sdan    code1 {
6507066d90Sdan      sqlite3 db1.2 test.db
6607066d90Sdan    }
673f1d0f56Sdan    sql1 {
6847d38e24Sdan      PRAGMA auto_vacuum = off;
693f1d0f56Sdan      PRAGMA journal_mode = wal;
703f1d0f56Sdan      CREATE TABLE t1(a, b);
713f1d0f56Sdan      INSERT INTO t1 VALUES(1, 2);
723f1d0f56Sdan    }
733f1d0f56Sdan    code2 {
743f1d0f56Sdan      db2 timeout 1000
753f1d0f56Sdan    }
763f1d0f56Sdan    code1 {
773f1d0f56Sdan      db1.2 timeout 1000
783f1d0f56Sdan      db    timeout 1000
793f1d0f56Sdan      db1.2 eval {SELECT * FROM t1}
803f1d0f56Sdan    }
813f1d0f56Sdan  } {1 2}
823f1d0f56Sdan
833f1d0f56Sdan  # Take a read lock with [db] in process 1.
843f1d0f56Sdan  #
853f1d0f56Sdan  do_test 2.$tn.1 {
863f1d0f56Sdan    sql1 {
873f1d0f56Sdan      BEGIN;
883f1d0f56Sdan        SELECT * FROM t1;
893f1d0f56Sdan    }
903f1d0f56Sdan  } {1 2}
913f1d0f56Sdan
923f1d0f56Sdan  # Insert a row using [db2] in process 2. Then try a passive checkpoint.
933f1d0f56Sdan  # It fails to checkpoint the final frame (due to the readlock taken by
943f1d0f56Sdan  # [db]), and returns in less than 250ms.
953f1d0f56Sdan  do_test 2.$tn.2 {
963f1d0f56Sdan    sql2 { INSERT INTO t1 VALUES(3, 4) }
973f1d0f56Sdan    set us [lindex [time {
983f1d0f56Sdan      set res [code2 { db2 eval { PRAGMA wal_checkpoint } }]
993f1d0f56Sdan    }] 0]
1003f1d0f56Sdan    list [expr $us < 250000] $res
1013f1d0f56Sdan  } {1 {0 4 3}}
1023f1d0f56Sdan
1033f1d0f56Sdan  # Now try a FULL checkpoint with [db2]. It returns SQLITE_BUSY. And takes
1043f1d0f56Sdan  # over 950ms to do so.
1053f1d0f56Sdan  do_test 2.$tn.3 {
1063f1d0f56Sdan    set us [lindex [time {
1073f1d0f56Sdan      set res [code2 { db2 eval { PRAGMA wal_checkpoint = FULL } }]
1083f1d0f56Sdan    }] 0]
1093f1d0f56Sdan    list [expr $us > 950000] $res
1103f1d0f56Sdan  } {1 {1 4 3}}
1113f1d0f56Sdan
1123f1d0f56Sdan  # Passive checkpoint with [db1.2] (process 1). No SQLITE_BUSY, returns
1133f1d0f56Sdan  # in under 250ms.
1143f1d0f56Sdan  do_test 2.$tn.4 {
1153f1d0f56Sdan    set us [lindex [time {
1163f1d0f56Sdan      set res [code1 { db1.2 eval { PRAGMA wal_checkpoint } }]
1173f1d0f56Sdan    }] 0]
1183f1d0f56Sdan    list [expr $us < 250000] $res
1193f1d0f56Sdan  } {1 {0 4 3}}
1203f1d0f56Sdan
1213f1d0f56Sdan  # Full checkpoint with [db1.2] (process 1). SQLITE_BUSY returned in
1223f1d0f56Sdan  # a bit over 950ms.
1233f1d0f56Sdan  do_test 2.$tn.5 {
1243f1d0f56Sdan    set us [lindex [time {
1253f1d0f56Sdan      set res [code1 { db1.2 eval { PRAGMA wal_checkpoint = FULL } }]
1263f1d0f56Sdan    }] 0]
1273f1d0f56Sdan    list [expr $us > 950000] $res
1283f1d0f56Sdan  } {1 {1 4 3}}
1293f1d0f56Sdan
1303f1d0f56Sdan  code1 {
1313f1d0f56Sdan    db1.2 close
1323f1d0f56Sdan  }
1333f1d0f56Sdan}
1343f1d0f56Sdan
1352b06b076Sdan#-------------------------------------------------------------------------
1362b06b076Sdan# Check that even if the busy-handler fails (returns zero) within a
1372b06b076Sdan# call to sqlite3_prepare() (or _v2(), or _v3()), it is still invoked
1382b06b076Sdan# the next time an SQLITE_BUSY is encountered.
1392b06b076Sdan#
1402b06b076Sdando_multiclient_test tn {
1412b06b076Sdan  code1 {
1422b06b076Sdan    set ::busy_called 0
1432b06b076Sdan    proc busy {args} {
1442b06b076Sdan      if {$::busy_called} { return 1 }
1452b06b076Sdan      set ::busy_called 1
1462b06b076Sdan      return 0
1472b06b076Sdan    }
1482b06b076Sdan    db busy busy
1492b06b076Sdan  }
1502b06b076Sdan
1512b06b076Sdan  do_test 3.$tn.1 {
1522b06b076Sdan    sql2 {
1532b06b076Sdan      CREATE TABLE t1(x);
1542b06b076Sdan      BEGIN EXCLUSIVE;
1552b06b076Sdan        INSERT INTO t1 VALUES('x');
1562b06b076Sdan    }
1572b06b076Sdan  } {}
1582b06b076Sdan
1592b06b076Sdan  do_test 3.$tn.2 {
1602b06b076Sdan    set ::busy_called 0
16112c99946Sdan    list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
16212c99946Sdan  } {1 1}
1632b06b076Sdan
1642b06b076Sdan  do_test 3.$tn.3 {
1652b06b076Sdan    set ::busy_called 0
16612c99946Sdan    list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
16712c99946Sdan  } {1 1}
16812c99946Sdan
1692b06b076Sdan}
1702b06b076Sdan
1712bfd35b8Sdanfinish_test
172