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

     1  # 2007 August 23
     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 file contains tests that verify that SQLite can correctly rollback
    13  # databases after crashes when using the special IO modes triggered 
    14  # by device IOCAP flags.
    15  #
    16  # $Id: crash3.test,v 1.4 2008/07/12 14:52:20 drh Exp $
    17  
    18  set testdir [file dirname $argv0]
    19  source $testdir/tester.tcl
    20  
    21  ifcapable !crashtest {
    22    finish_test
    23    return
    24  }
    25  
    26  proc do_test2 {name tcl res1 res2} {
    27    set script [subst -nocommands {
    28      do_test $name {
    29        set res1 {$res1}
    30        set res2 {$res2}
    31        set res [eval {$tcl}]
    32        if {[set res] eq [set res1] || [set res] eq [set res2]} {
    33          set res "{[set res1]} or {[set res2]}"
    34        }
    35        set res
    36      } {{$res1} or {$res2}}
    37    }]
    38    uplevel $script
    39  }
    40  
    41  # This block tests crash-recovery when the IOCAP_ATOMIC flags is set.
    42  #
    43  # Each iteration of the following loop sets up the database to contain
    44  # the following schema and data:
    45  #
    46  #    CREATE TABLE abc(a, b, c);
    47  #    INSERT INTO abc VALUES(1, 2, 3);
    48  #
    49  # Then execute the SQL statement, scheduling a crash for part-way through
    50  # the first sync() of either the database file or the journal file (often
    51  # the journal file is not required - meaning no crash occurs).
    52  #
    53  # After the crash (or absence of a crash), open the database and 
    54  # verify that:
    55  #
    56  #   * The integrity check passes, and
    57  #   * The contents of table abc is either {1 2 3} or the value specified
    58  #     to the right of the SQL statement below.
    59  #
    60  # The procedure is repeated 10 times for each SQL statement. Five times
    61  # with the crash scheduled for midway through the first journal sync (if 
    62  # any), and five times with the crash midway through the database sync.
    63  #
    64  set tn 1
    65  foreach {sql res2} [list \
    66    {INSERT INTO abc VALUES(4, 5, 6)}                    {1 2 3 4 5 6} \
    67    {DELETE FROM abc}                                    {}    \
    68    {INSERT INTO abc SELECT * FROM abc}                  {1 2 3 1 2 3} \
    69    {UPDATE abc SET a = 2}                               {2 2 3}       \
    70    {INSERT INTO abc VALUES(4, 5, randstr(1000,1000))}   {n/a} \
    71    {CREATE TABLE def(d, e, f)}                          {n/a} \
    72  ] {
    73    for {set ii 0} {$ii < 10} {incr ii} {
    74  
    75      db close
    76      forcedelete test.db test.db-journal
    77      sqlite3 db test.db
    78      do_test crash3-1.$tn.1 {
    79        execsql {
    80          PRAGMA page_size = 1024;
    81          BEGIN;
    82          CREATE TABLE abc(a, b, c);
    83          INSERT INTO abc VALUES(1, 2, 3);
    84          COMMIT;
    85        }
    86      } {}
    87      db close
    88    
    89      set crashfile test.db
    90      if {($ii%2)==0} { append crashfile -journal }
    91      set rand "SELECT randstr($tn,$tn);"
    92      do_test crash3-1.$tn.2 [subst {
    93        crashsql -file $crashfile -char atomic {$rand $sql}
    94        sqlite3 db test.db
    95        execsql { PRAGMA integrity_check; }
    96      }] {ok}
    97    
    98      do_test2 crash3-1.$tn.3 {
    99        execsql { SELECT * FROM abc }
   100      } {1 2 3} $res2
   101  
   102      incr tn
   103    }
   104  }
   105  
   106  # This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags.
   107  #
   108  db close
   109  forcedelete test.db test.db-journal
   110  sqlite3 db test.db
   111  do_test crash3-2.0 {
   112    execsql {
   113      BEGIN;
   114      CREATE TABLE abc(a PRIMARY KEY, b, c);
   115      CREATE TABLE def(d PRIMARY KEY, e, f);
   116      PRAGMA default_cache_size = 10;
   117      INSERT INTO abc VALUES(randstr(10,1000),randstr(10,1000),randstr(10,1000));
   118      INSERT INTO abc 
   119        SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
   120      INSERT INTO abc 
   121        SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
   122      INSERT INTO abc 
   123        SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
   124      INSERT INTO abc 
   125        SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
   126      INSERT INTO abc 
   127        SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
   128      INSERT INTO abc 
   129        SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
   130      COMMIT;
   131    }
   132  } {}
   133  
   134  set tn 1
   135  foreach {::crashfile ::delay ::char} {
   136    test.db         1 sequential
   137    test.db         1 safe_append
   138    test.db-journal 1 sequential
   139    test.db-journal 1 safe_append
   140    test.db-journal 2 safe_append
   141    test.db-journal 2 sequential
   142    test.db-journal 3 sequential
   143    test.db-journal 3 safe_append
   144  } {
   145    for {set ii 0} {$ii < 100} {incr ii} {
   146      set ::SQL [subst {
   147        SELECT randstr($ii,$ii+10);
   148        BEGIN;
   149        DELETE FROM abc WHERE random()%5;
   150        INSERT INTO abc 
   151          SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) 
   152          FROM abc
   153          WHERE (random()%5)==0;
   154        DELETE FROM def WHERE random()%5;
   155        INSERT INTO def 
   156          SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) 
   157          FROM def
   158          WHERE (random()%5)==0;
   159        COMMIT;
   160      }]
   161  
   162      do_test crash3-2.$tn.$ii {
   163        crashsql -file $::crashfile -delay $::delay -char $::char $::SQL
   164        db close
   165        sqlite3 db test.db
   166        execsql {PRAGMA integrity_check}
   167      } {ok}
   168    }
   169    incr tn
   170  }
   171  
   172  # The following block tests an interaction between IOCAP_ATOMIC and
   173  # IOCAP_SEQUENTIAL. At one point, if both flags were set, small
   174  # journal files that contained only a single page, but were required 
   175  # for some other reason (i.e. nTrunk) were not being written to
   176  # disk.
   177  #
   178  for {set ii 0} {$ii < 10} {incr ii} {
   179    db close
   180    forcedelete test.db test.db-journal
   181    crashsql -file test.db -char {sequential atomic} {
   182      CREATE TABLE abc(a, b, c);
   183    }
   184    sqlite3 db test.db
   185    do_test crash3-3.$ii {
   186      execsql {PRAGMA integrity_check}
   187    } {ok}
   188  }
   189  
   190  finish_test