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

     1  # 2016 February 4
     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 file is testing the operation of the library in
    13  # "PRAGMA journal_mode=WAL" mode.
    14  #
    15  # More specifically, it tests "locking protocol" errors - errors that
    16  # may be caused if one or more SQLite clients does not follow the expected
    17  # locking protocol when accessing a wal-mode database. These tests take
    18  # quite a while to run.
    19  #
    20  
    21  set testdir [file dirname $argv0]
    22  source $testdir/tester.tcl
    23  source $testdir/lock_common.tcl
    24  source $testdir/wal_common.tcl
    25  ifcapable !wal {finish_test ; return }
    26  
    27  set testprefix walprotocol
    28  
    29  #-------------------------------------------------------------------------
    30  # When recovering the contents of a WAL file, a process obtains the WRITER
    31  # lock, then locks all other bytes before commencing recovery. If it fails
    32  # to lock all other bytes (because some other process is holding a read
    33  # lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the 
    34  # caller. Test this (test case 1.3).
    35  #
    36  # Also test the effect of hitting an SQLITE_BUSY while attempting to obtain
    37  # the WRITER lock (should be the same). Test case 1.4.
    38  # 
    39  do_execsql_test 1.0 {
    40    PRAGMA journal_mode = wal;
    41    CREATE TABLE x(y);
    42    INSERT INTO x VALUES('z');
    43  } {wal}
    44  
    45  proc lock_callback {method filename handle lock} {
    46    lappend ::locks $lock
    47  }
    48  do_test 1.1 {
    49    testvfs T
    50    T filter xShmLock 
    51    T script lock_callback
    52    set ::locks [list]
    53    sqlite3 db test.db -vfs T
    54    execsql { SELECT * FROM x }
    55    lrange $::locks 0 11
    56  } [list {0 1 lock exclusive} {1 2 lock exclusive}     \
    57          {4 1 lock exclusive} {4 1 unlock exclusive}   \
    58          {5 1 lock exclusive} {5 1 unlock exclusive}   \
    59          {6 1 lock exclusive} {6 1 unlock exclusive}   \
    60          {7 1 lock exclusive} {7 1 unlock exclusive}   \
    61          {1 2 unlock exclusive}   \
    62          {0 1 unlock exclusive}  \
    63  ]
    64  do_test 1.2 {
    65    db close
    66    set ::locks [list]
    67    sqlite3 db test.db -vfs T
    68    execsql { SELECT * FROM x }
    69    lrange $::locks 0 11
    70  } [list {0 1 lock exclusive} {1 2 lock exclusive}     \
    71          {4 1 lock exclusive} {4 1 unlock exclusive}   \
    72          {5 1 lock exclusive} {5 1 unlock exclusive}   \
    73          {6 1 lock exclusive} {6 1 unlock exclusive}   \
    74          {7 1 lock exclusive} {7 1 unlock exclusive}   \
    75          {1 2 unlock exclusive}   \
    76          {0 1 unlock exclusive}  \
    77  ]
    78  proc lock_callback {method filename handle lock} {
    79    if {$lock == "1 2 lock exclusive"} { return SQLITE_BUSY }
    80    return SQLITE_OK
    81  }
    82  puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
    83  puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite"
    84  puts "# is built on unix without HAVE_USLEEP defined, it may be much longer."
    85  do_test 1.3 {
    86    db close
    87    set ::locks [list]
    88    sqlite3 db test.db -vfs T
    89    catchsql { SELECT * FROM x }
    90  } {1 {locking protocol}}
    91  
    92  puts "# Warning: Same again!"
    93  proc lock_callback {method filename handle lock} {
    94    if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY }
    95    return SQLITE_OK
    96  }
    97  do_test 1.4 {
    98    db close
    99    set ::locks [list]
   100    sqlite3 db test.db -vfs T
   101    catchsql { SELECT * FROM x }
   102  } {1 {locking protocol}}
   103  
   104  puts "# Warning: Third time!"
   105  proc lock_callback {method filename handle lock} {
   106    if {$lock == "4 4 lock exclusive"} { return SQLITE_BUSY }
   107    return SQLITE_OK
   108  }
   109  do_test 1.5 {
   110    db close
   111    set ::locks [list]
   112    sqlite3 db test.db -vfs T
   113    catchsql { SELECT * FROM x }
   114  } {0 z}
   115  db close
   116  T delete
   117  
   118  #-------------------------------------------------------------------------
   119  # 
   120  do_test 2.1 {
   121    forcedelete test.db test.db-journal test.db wal
   122    sqlite3 db test.db
   123    sqlite3 db2 test.db
   124    execsql {
   125      PRAGMA auto_vacuum = off;
   126      PRAGMA journal_mode = WAL;
   127      CREATE TABLE b(c);
   128      INSERT INTO b VALUES('Tehran');
   129      INSERT INTO b VALUES('Qom');
   130      INSERT INTO b VALUES('Markazi');
   131      PRAGMA wal_checkpoint;
   132    }
   133  } {wal 0 5 5}
   134  do_test 2.2 {
   135    execsql { SELECT * FROM b }
   136  } {Tehran Qom Markazi}
   137  do_test 2.3 {
   138    db eval { SELECT * FROM b } {
   139      db eval { INSERT INTO b VALUES('Qazvin') }
   140      set r [db2 eval { SELECT * FROM b }]
   141      break
   142    }
   143    set r
   144  } {Tehran Qom Markazi Qazvin}
   145  do_test 2.4 {
   146    execsql {
   147      INSERT INTO b VALUES('Gilan');
   148      INSERT INTO b VALUES('Ardabil');
   149    }
   150  } {}
   151  db2 close
   152  
   153  faultsim_save_and_close
   154  testvfs T -default 1
   155  faultsim_restore_and_reopen
   156  T filter xShmLock
   157  T script lock_callback
   158  
   159  proc lock_callback {method file handle spec} {
   160    if {$spec == "1 2 unlock exclusive"} {
   161      T filter {}
   162      set ::r [catchsql { SELECT * FROM b } db2]
   163    }
   164  }
   165  sqlite3 db test.db
   166  sqlite3 db2 test.db
   167  puts "# Warning: Another slow test!"
   168  do_test 2.5 {
   169    execsql { SELECT * FROM b }
   170  } {Tehran Qom Markazi Qazvin Gilan Ardabil}
   171  do_test 2.6 {
   172    set ::r
   173  } {0 {Tehran Qom Markazi Qazvin Gilan Ardabil}}
   174  
   175  db close
   176  db2 close
   177  
   178  faultsim_restore_and_reopen
   179  sqlite3 db2 test.db
   180  T filter xShmLock
   181  T script lock_callback
   182  proc lock_callback {method file handle spec} {
   183    if {$spec == "1 2 unlock exclusive"} {
   184      T filter {}
   185      set ::r [catchsql { SELECT * FROM b } db2]
   186    }
   187  }
   188  unset ::r
   189  puts "# Warning: Last one!"
   190  do_test 2.7 {
   191    execsql { SELECT * FROM b }
   192  } {Tehran Qom Markazi Qazvin Gilan Ardabil}
   193  do_test 2.8 {
   194    set ::r
   195  } {0 {Tehran Qom Markazi Qazvin Gilan Ardabil}}
   196  
   197  db close
   198  db2 close
   199  T delete
   200  
   201  finish_test