xref: /sqlite-3.40.0/ext/rbu/rbufault.test (revision 6ab91a7a)
1# 2014 October 22
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
13if {![info exists testdir]} {
14  set testdir [file join [file dirname [info script]] .. .. test]
15}
16source $testdir/tester.tcl
17source $testdir/malloc_common.tcl
18set ::testprefix rbufault
19
20proc copy_if_exists {src target} {
21  if {[file exists $src]} {
22    forcecopy $src $target
23  } else {
24    forcedelete $target
25  }
26}
27
28foreach {tn2 setup sql expect} {
29  1 {
30    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
31    CREATE INDEX t1cb ON t1(c, b);
32    INSERT INTO t1 VALUES(1, 1, 1);
33    INSERT INTO t1 VALUES(2, 2, 2);
34    INSERT INTO t1 VALUES(3, 3, 3);
35
36    CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
37    INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
38    INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.');
39    INSERT INTO data_t1 VALUES(4, 4, 4, 0);
40  } {
41    SELECT * FROM t1
42  } {1 1 1   3 three 3   4 4 4}
43
44  2 {
45    CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
46    CREATE INDEX t2cb ON t2(c, b);
47    INSERT INTO t2 VALUES('a', 'a', 'a');
48    INSERT INTO t2 VALUES('b', 'b', 'b');
49    INSERT INTO t2 VALUES('c', 'c', 'c');
50
51    CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
52    INSERT INTO data_t2 VALUES('b', NULL, NULL, 1);
53    INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.');
54    INSERT INTO data_t2 VALUES('d', 'd', 'd', 0);
55  } {
56    SELECT * FROM t2
57  } {a a a   c see c     d d d}
58
59  3 {
60    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
61    CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
62    CREATE INDEX t1cb ON t1(c, b);
63    CREATE INDEX t2cb ON t2(c, b);
64
65    CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
66    CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
67    INSERT INTO data_t1 VALUES(1, 2, 3, 0);
68    INSERT INTO data_t2 VALUES(4, 5, 6, 0);
69  } {
70    SELECT * FROM t1 UNION ALL SELECT * FROM t2
71  } {1 2 3 4 5 6}
72
73  4 {
74    CREATE TABLE t1(a PRIMARY KEY, b, c);
75    CREATE INDEX t1c ON t1(c);
76    INSERT INTO t1 VALUES('A', 'B', 'C');
77    INSERT INTO t1 VALUES('D', 'E', 'F');
78
79    CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
80    INSERT INTO data_t1 VALUES('D', NULL, NULL, 1);
81    INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.');
82    INSERT INTO data_t1 VALUES('G', 'H', 'I', 0);
83  } {
84    SELECT * FROM t1 ORDER BY a;
85  } {A Z C G H I}
86
87  5 {
88    CREATE TABLE t1(a, b, c);
89    CREATE INDEX t1c ON t1(c, b);
90
91    CREATE TABLE rbu.data_t1(a, b, c, rbu_rowid, rbu_control);
92    INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0);
93    INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0);
94  } {
95    SELECT * FROM t1 ORDER BY a;
96  } {a b c d e f}
97
98} {
99  catch {db close}
100  forcedelete rbu.db test.db
101  sqlite3 db test.db
102  execsql {
103    PRAGMA encoding = utf16;
104    ATTACH 'rbu.db' AS rbu;
105  }
106  execsql $setup
107  db close
108
109  forcecopy test.db test.db.bak
110  forcecopy rbu.db rbu.db.bak
111
112  foreach {tn f reslist} {
113    1 oom-tra*  {
114      {0 SQLITE_DONE}
115      {1 {SQLITE_NOMEM - out of memory}}
116      {1 SQLITE_NOMEM}
117      {1 SQLITE_IOERR_NOMEM}
118      {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}}
119    }
120
121    2 ioerr-*  {
122      {0 SQLITE_DONE}
123      {1 {SQLITE_IOERR - disk I/O error}}
124      {1 SQLITE_IOERR}
125      {1 SQLITE_IOERR_WRITE}
126      {1 SQLITE_IOERR_READ}
127      {1 SQLITE_IOERR_FSYNC}
128      {1 {SQLITE_ERROR - SQL logic error}}
129      {1 {SQLITE_ERROR - unable to open database: rbu.db}}
130      {1 {SQLITE_IOERR - unable to open database: rbu.db}}
131    }
132
133    3 shmerr-*  {
134      {0 SQLITE_DONE}
135      {1 {SQLITE_IOERR - disk I/O error}}
136      {1 SQLITE_IOERR}
137    }
138  } {
139
140    catch {db close}
141    sqlite3_shutdown
142    set lookaside_config [sqlite3_config_lookaside 0 0]
143    sqlite3_initialize
144    autoinstall_test_functions
145
146    do_faultsim_test 2.$tn2 -faults $::f -prep {
147      catch { db close }
148      forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
149      forcecopy test.db.bak test.db
150      forcecopy rbu.db.bak  rbu.db
151    } -body {
152      sqlite3rbu rbu test.db rbu.db
153      while {[rbu step]=="SQLITE_OK"} {}
154      rbu close
155    } -test {
156      faultsim_test_result {*}$::reslist
157      if {$testrc==0} {
158        sqlite3 db test.db
159        faultsim_integrity_check
160        set res [db eval $::sql]
161        if {$res != [list {*}$::expect]} {
162          puts ""
163          puts "res: $res"
164          puts "exp: $expect"
165          error "data not as expected!"
166        }
167      }
168    }
169
170    catch {db close}
171    sqlite3_shutdown
172    sqlite3_config_lookaside {*}$lookaside_config
173    sqlite3_initialize
174    autoinstall_test_functions
175
176
177    for {set iStep 0} {$iStep<=21} {incr iStep} {
178
179      forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
180
181      copy_if_exists test.db.bak test.db
182      copy_if_exists rbu.db.bak rbu.db
183
184      sqlite3rbu rbu test.db rbu.db
185      for {set x 0} {$x < $::iStep} {incr x} { rbu step }
186      rbu close
187
188# sqlite3 x rbu.db ; puts "XYZ [x eval { SELECT * FROM rbu_state } ]" ; x close
189
190      copy_if_exists test.db     test.db.bak.2
191      copy_if_exists test.db-wal test.db.bak.2-wal
192      copy_if_exists test.db-oal test.db.bak.2-oal
193      copy_if_exists rbu.db      rbu.db.bak.2
194
195      do_faultsim_test 3.$tn.$iStep -faults $::f -prep {
196        catch { db close }
197        forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
198        copy_if_exists test.db.bak.2 test.db
199        copy_if_exists test.db.bak.2-wal test.db-wal
200        copy_if_exists test.db.bak.2-oal test.db-oal
201        copy_if_exists rbu.db.bak.2  rbu.db
202      } -body {
203        sqlite3rbu rbu test.db rbu.db
204        rbu step
205        rbu close
206      } -test {
207
208        if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"}
209        faultsim_test_result {*}$::reslist
210
211        if {$testrc==0} {
212          # No error occurred. If the RBU has not already been fully applied,
213          # apply the rest of it now. Then ensure that the final state of the
214          # target db is as expected. And that "PRAGMA integrity_check"
215          # passes.
216          sqlite3rbu rbu test.db rbu.db
217          while {[rbu step] == "SQLITE_OK"} {}
218          rbu close
219
220          sqlite3 db test.db
221          faultsim_integrity_check
222
223          set res [db eval $::sql]
224          if {$res != [list {*}$::expect]} {
225            puts ""
226            puts "res: $res"
227            puts "exp: $::expect"
228            error "data not as expected!"
229          }
230        }
231      }
232    }
233  }
234}
235
236finish_test
237