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

     1  # 2011 December 16
     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  #
    12  # This test simulates an application crash immediately following a
    13  # system call to truncate a file. Specifically, the system call that
    14  # truncates the WAL file if "PRAGMA journal_size_limit" is configured.
    15  #
    16  
    17  set testdir [file dirname $argv0]
    18  source $testdir/tester.tcl
    19  
    20  ifcapable !wal {finish_test ; return }
    21  set testprefix walcrash3
    22  
    23  db close
    24  testvfs tvfs
    25  tvfs filter {xTruncate xWrite}
    26  tvfs script tvfs_callback
    27  proc tvfs_callback {args} {}
    28  
    29  sqlite3 db test.db -vfs tvfs
    30  do_execsql_test 1.1 {
    31    PRAGMA page_size = 1024;
    32    PRAGMA journal_mode = WAL;
    33    PRAGMA wal_autocheckpoint = 128;
    34    PRAGMA journal_size_limit = 16384;
    35  
    36    CREATE TABLE t1(a BLOB, b BLOB, UNIQUE(a, b));
    37    INSERT INTO t1 VALUES(randomblob(10), randomblob(1000));
    38  } {wal 128 16384}
    39  
    40  proc tvfs_callback {method file arglist} {
    41    if {$::state==1} {
    42      foreach f [glob -nocomplain xx_test.*] { forcedelete $f }
    43      foreach f [glob -nocomplain test.*]    { forcecopy $f "xx_$f" }
    44      set ::state 2
    45    }
    46    if {$::state==0 && $method=="xTruncate" && [file tail $file]=="test.db-wal"} {
    47      set ::state 1
    48    }
    49  }
    50  
    51  for {set i 2} {$i<1000} {incr i} {
    52  
    53    # If the WAL file is truncated within the following, within the following
    54    # xWrite call the [tvfs_callback] makes a copy of the database and WAL 
    55    # files set sets $::state to 2. So that the copied files are in the same
    56    # state as the real database and WAL files would be if an application crash 
    57    # occurred immediately following the xTruncate().
    58    # 
    59    set ::state 0
    60    do_execsql_test 1.$i.1 {
    61      INSERT INTO t1 VALUES(randomblob(10), randomblob(1000));
    62    }
    63  
    64    # If a copy was made, open it and run the integrity-check.
    65    #
    66    if {$::state==2} {
    67      sqlite3 db2 xx_test.db
    68      do_test 1.$i.2 { execsql { PRAGMA integrity_check  } db2 } "ok"
    69      do_test 1.$i.3 { execsql { SELECT count(*) FROM t1 } db2 } [expr $i-1]
    70      db2 close
    71    }
    72  }
    73  catch { db close }
    74  tvfs delete
    75  
    76  #--------------------------------------------------------------------------
    77  #
    78  catch { db close }
    79  forcedelete test.db
    80  
    81  do_test 2.1 {
    82    sqlite3 db test.db
    83    execsql {
    84      PRAGMA page_size = 512;
    85      PRAGMA journal_mode = WAL;
    86      PRAGMA wal_autocheckpoint = 128;
    87      CREATE TABLE t1(a PRIMARY KEY, b);
    88      INSERT INTO t1 VALUES(randomblob(25), randomblob(200));
    89    }
    90  
    91    for {set i 0} {$i < 1500} {incr i} {
    92      execsql { INSERT INTO t1 VALUES(randomblob(25), randomblob(200)) }
    93    }
    94  
    95    db_save
    96    db close
    97  } {}
    98  
    99  set nInitialErr [set_test_counter errors]
   100  for {set i 2} {$i<10000 && [set_test_counter errors]==$nInitialErr} {incr i} {
   101  
   102    do_test 2.$i.1 {
   103      catch { db close } 
   104      db_restore
   105      crashsql -delay 2 -file test.db-wal -seed $i {
   106        SELECT * FROM sqlite_master;
   107        PRAGMA synchronous = full;
   108        PRAGMA wal_checkpoint;
   109        BEGIN;
   110          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   111          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   112          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   113          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   114          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   115          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   116          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   117          INSERT INTO t1 VALUES(randomblob(26), randomblob(200));
   118        COMMIT;
   119      }
   120    } {1 {child process exited abnormally}}
   121  
   122    do_test 2.$i.2 {
   123      sqlite3 db test.db
   124      execsql { PRAGMA integrity_check } 
   125    } {ok}
   126  }
   127  
   128  finish_test