github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/busy2.test (about)

     1  # 2020 June 30
     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 test the busy handler
    12  #
    13  
    14  
    15  set testdir [file dirname $argv0]
    16  source $testdir/tester.tcl
    17  source $testdir/lock_common.tcl
    18  set testprefix busy2
    19  
    20  do_multiclient_test tn {
    21    do_test 1.$tn.0 {
    22      sql2 {
    23        CREATE TABLE t1(a, b);
    24        PRAGMA journal_mode = wal;
    25        INSERT INTO t1 VALUES('A', 'B');
    26      }
    27    } {wal}
    28  
    29    do_test 1.$tn.1 {
    30      code1 { db timeout 1000 }
    31      sql1 { SELECT * FROM t1 }
    32    } {A B}
    33  
    34    do_test 1.$tn.2 {
    35      sql2 {
    36        BEGIN;
    37          INSERT INTO t1 VALUES('C', 'D');
    38      }
    39    } {}
    40  
    41    do_test 1.$tn.3 {
    42      set us [lindex [time { catch { sql1 { BEGIN EXCLUSIVE } } }] 0]
    43      expr {$us>950000 && $us<1500000}
    44    } {1}
    45  
    46    do_test 1.$tn.4 {
    47      sql2 {
    48        COMMIT
    49      }
    50    } {}
    51  }
    52  
    53  #-------------------------------------------------------------------------
    54  
    55  do_multiclient_test tn {
    56    # Make the db a WAL mode db. And add a table and a row to it. Then open
    57    # a second connection within process 1. Process 1 now has connections
    58    # [db] and [db1.2], process 2 has connection [db2] only.
    59    #
    60    # Configure all connections to use a 1000 ms timeout.
    61    #
    62    do_test 2.$tn.0 {
    63      code1 {
    64        sqlite3 db1.2 test.db
    65      }
    66      sql1 {
    67        PRAGMA auto_vacuum = off;
    68        PRAGMA journal_mode = wal;
    69        CREATE TABLE t1(a, b);
    70        INSERT INTO t1 VALUES(1, 2);
    71      }
    72      code2 {
    73        db2 timeout 1000
    74      }
    75      code1 {
    76        db1.2 timeout 1000
    77        db    timeout 1000
    78        db1.2 eval {SELECT * FROM t1}
    79      }
    80    } {1 2}
    81  
    82    # Take a read lock with [db] in process 1.
    83    #
    84    do_test 2.$tn.1 {
    85      sql1 {
    86        BEGIN;
    87          SELECT * FROM t1;
    88      }
    89    } {1 2}
    90  
    91    # Insert a row using [db2] in process 2. Then try a passive checkpoint.
    92    # It fails to checkpoint the final frame (due to the readlock taken by
    93    # [db]), and returns in less than 250ms.
    94    do_test 2.$tn.2 {
    95      sql2 { INSERT INTO t1 VALUES(3, 4) }
    96      set us [lindex [time {
    97        set res [code2 { db2 eval { PRAGMA wal_checkpoint } }]
    98      }] 0]
    99      list [expr $us < 250000] $res
   100    } {1 {0 4 3}}
   101  
   102    # Now try a FULL checkpoint with [db2]. It returns SQLITE_BUSY. And takes
   103    # over 950ms to do so.
   104    do_test 2.$tn.3 {
   105      set us [lindex [time {
   106        set res [code2 { db2 eval { PRAGMA wal_checkpoint = FULL } }]
   107      }] 0]
   108      list [expr $us > 950000] $res
   109    } {1 {1 4 3}}
   110  
   111    # Passive checkpoint with [db1.2] (process 1). No SQLITE_BUSY, returns
   112    # in under 250ms.
   113    do_test 2.$tn.4 {
   114      set us [lindex [time {
   115        set res [code1 { db1.2 eval { PRAGMA wal_checkpoint } }]
   116      }] 0]
   117      list [expr $us < 250000] $res
   118    } {1 {0 4 3}}
   119  
   120    # Full checkpoint with [db1.2] (process 1). SQLITE_BUSY returned in
   121    # a bit over 950ms.
   122    do_test 2.$tn.5 {
   123      set us [lindex [time {
   124        set res [code1 { db1.2 eval { PRAGMA wal_checkpoint = FULL } }]
   125      }] 0]
   126      list [expr $us > 950000] $res
   127    } {1 {1 4 3}}
   128  
   129    code1 {
   130      db1.2 close
   131    }
   132  }
   133  
   134  #-------------------------------------------------------------------------
   135  # Check that even if the busy-handler fails (returns zero) within a
   136  # call to sqlite3_prepare() (or _v2(), or _v3()), it is still invoked
   137  # the next time an SQLITE_BUSY is encountered.
   138  #
   139  do_multiclient_test tn {
   140    code1 {
   141      set ::busy_called 0
   142      proc busy {args} {
   143        if {$::busy_called} { return 1 }
   144        set ::busy_called 1
   145        return 0
   146      }
   147      db busy busy
   148    }
   149  
   150    do_test 3.$tn.1 {
   151      sql2 {
   152        CREATE TABLE t1(x);
   153        BEGIN EXCLUSIVE;
   154          INSERT INTO t1 VALUES('x');
   155      }
   156    } {}
   157  
   158    do_test 3.$tn.2 {
   159      set ::busy_called 0
   160      list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
   161    } {1 1}
   162  
   163    do_test 3.$tn.3 {
   164      set ::busy_called 0
   165      list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
   166    } {1 1}
   167  
   168  }
   169  
   170  finish_test