persistentstorage/sqlite3api/TEST/TclScript/crash3.test
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     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     file delete -force 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 file delete -force 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   file delete -force 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