xref: /sqlite-3.40.0/test/shared_err.test (revision d230f648)
1# 2005 December 30
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# The focus of the tests in this file are IO errors that occur in a shared
13# cache context. What happens to connection B if one connection A encounters
14# an IO-error whilst reading or writing the file-system?
15#
16# $Id: shared_err.test,v 1.11 2007/04/06 01:04:40 drh Exp $
17
18proc skip {args} {}
19
20
21set testdir [file dirname $argv0]
22source $testdir/tester.tcl
23db close
24
25ifcapable !shared_cache||!subquery {
26  finish_test
27  return
28}
29set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
30
31# Todo: This is a copy of the [do_malloc_test] proc in malloc.test
32# It would be better if these were consolidated.
33
34# Usage: do_malloc_test <test number> <options...>
35#
36# The first argument, <test number>, is an integer used to name the
37# tests executed by this proc. Options are as follows:
38#
39#     -tclprep          TCL script to run to prepare test.
40#     -sqlprep          SQL script to run to prepare test.
41#     -tclbody          TCL script to run with malloc failure simulation.
42#     -sqlbody          TCL script to run with malloc failure simulation.
43#     -cleanup          TCL script to run after the test.
44#
45# This command runs a series of tests to verify SQLite's ability
46# to handle an out-of-memory condition gracefully. It is assumed
47# that if this condition occurs a malloc() call will return a
48# NULL pointer. Linux, for example, doesn't do that by default. See
49# the "BUGS" section of malloc(3).
50#
51# Each iteration of a loop, the TCL commands in any argument passed
52# to the -tclbody switch, followed by the SQL commands in any argument
53# passed to the -sqlbody switch are executed. Each iteration the
54# Nth call to sqliteMalloc() is made to fail, where N is increased
55# each time the loop runs starting from 1. When all commands execute
56# successfully, the loop ends.
57#
58proc do_malloc_test {tn args} {
59  array unset ::mallocopts
60  array set ::mallocopts $args
61
62  set ::go 1
63  for {set ::n 1} {$::go && $::n < 50000} {incr ::n} {
64    do_test shared_malloc-$tn.$::n {
65
66      # Remove all traces of database files test.db and test2.db from the files
67      # system. Then open (empty database) "test.db" with the handle [db].
68      #
69      sqlite_malloc_fail 0
70      catch {db close}
71      catch {file delete -force test.db}
72      catch {file delete -force test.db-journal}
73      catch {file delete -force test2.db}
74      catch {file delete -force test2.db-journal}
75      catch {sqlite3 db test.db}
76      set ::DB [sqlite3_connection_pointer db]
77
78      # Execute any -tclprep and -sqlprep scripts.
79      #
80      if {[info exists ::mallocopts(-tclprep)]} {
81        eval $::mallocopts(-tclprep)
82      }
83      if {[info exists ::mallocopts(-sqlprep)]} {
84        execsql $::mallocopts(-sqlprep)
85      }
86
87      # Now set the ${::n}th malloc() to fail and execute the -tclbody and
88      # -sqlbody scripts.
89      #
90      sqlite_malloc_fail $::n
91      set ::mallocbody {}
92      if {[info exists ::mallocopts(-tclbody)]} {
93        append ::mallocbody "$::mallocopts(-tclbody)\n"
94      }
95      if {[info exists ::mallocopts(-sqlbody)]} {
96        append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
97      }
98      set v [catch $::mallocbody msg]
99
100      set leftover [lindex [sqlite_malloc_stat] 2]
101      if {$leftover>0} {
102        if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
103        set ::go 0
104        if {$v} {
105          puts "\nError message returned: $msg"
106        } else {
107          set v {1 1}
108        }
109      } else {
110        set v2 [expr {$msg=="" || $msg=="out of memory"}]
111        if {!$v2} {puts "\nError message returned: $msg"}
112        lappend v $v2
113      }
114    } {1 1}
115
116    sqlite_malloc_fail 0
117    if {[info exists ::mallocopts(-cleanup)]} {
118      catch [list uplevel #0 $::mallocopts(-cleanup)] msg
119    }
120  }
121  unset ::mallocopts
122}
123
124
125do_ioerr_test shared_ioerr-1 -tclprep {
126  sqlite3 db2 test.db
127  execsql {
128    PRAGMA read_uncommitted = 1;
129    CREATE TABLE t1(a,b,c);
130    BEGIN;
131    SELECT * FROM sqlite_master;
132  } db2
133} -sqlbody {
134  SELECT * FROM sqlite_master;
135  INSERT INTO t1 VALUES(1,2,3);
136  BEGIN TRANSACTION;
137  INSERT INTO t1 VALUES(1,2,3);
138  INSERT INTO t1 VALUES(4,5,6);
139  ROLLBACK;
140  SELECT * FROM t1;
141  BEGIN TRANSACTION;
142  INSERT INTO t1 VALUES(1,2,3);
143  INSERT INTO t1 VALUES(4,5,6);
144  COMMIT;
145  SELECT * FROM t1;
146  DELETE FROM t1 WHERE a<100;
147} -cleanup {
148  do_test shared_ioerr-1.$n.cleanup.1 {
149    set res [catchsql {
150      SELECT * FROM t1;
151    } db2]
152    set possible_results [list            \
153      "1 {disk I/O error}"                \
154      "0 {1 2 3}"                         \
155      "0 {1 2 3 1 2 3 4 5 6}"             \
156      "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}" \
157      "0 {}"                              \
158    ]
159    set rc [expr [lsearch -exact $possible_results $res] >= 0]
160    if {$rc != 1} {
161      puts ""
162      puts "Result: $res"
163    }
164    set rc
165  } {1}
166  db2 close
167}
168
169do_ioerr_test shared_ioerr-2 -tclprep {
170  sqlite3 db2 test.db
171  execsql {
172    PRAGMA read_uncommitted = 1;
173    BEGIN;
174    CREATE TABLE t1(a, b);
175    INSERT INTO t1(oid) VALUES(NULL);
176    INSERT INTO t1(oid) SELECT NULL FROM t1;
177    INSERT INTO t1(oid) SELECT NULL FROM t1;
178    INSERT INTO t1(oid) SELECT NULL FROM t1;
179    INSERT INTO t1(oid) SELECT NULL FROM t1;
180    INSERT INTO t1(oid) SELECT NULL FROM t1;
181    INSERT INTO t1(oid) SELECT NULL FROM t1;
182    INSERT INTO t1(oid) SELECT NULL FROM t1;
183    INSERT INTO t1(oid) SELECT NULL FROM t1;
184    INSERT INTO t1(oid) SELECT NULL FROM t1;
185    INSERT INTO t1(oid) SELECT NULL FROM t1;
186    UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789';
187    CREATE INDEX i1 ON t1(a);
188    COMMIT;
189    BEGIN;
190    SELECT * FROM sqlite_master;
191  } db2
192} -tclbody {
193  set ::residx 0
194  execsql {DELETE FROM t1 WHERE 0 = (a % 2);}
195  incr ::residx
196
197  # When this transaction begins the table contains 512 entries. The
198  # two statements together add 512+146 more if it succeeds.
199  # (1024/7==146)
200  execsql {BEGIN;}
201  execsql {INSERT INTO t1 SELECT a+1, b FROM t1;}
202  execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);}
203  execsql {COMMIT;}
204
205  incr ::residx
206} -cleanup {
207  do_test shared_ioerr-2.$n.cleanup.1 {
208    set res [catchsql {
209      SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a);
210    } db2]
211    set possible_results [list \
212      {0 {1024 1 1024}}        \
213      {0 {1023 1 512}}         \
214      {0 {string994 1 1170}}   \
215    ]
216    set idx [lsearch -exact $possible_results $res]
217    set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}]
218    if {!$success} {
219      puts ""
220      puts "Result: \"$res\" ($::residx)"
221    }
222    set success
223  } {1}
224  db2 close
225}
226
227# This test is designed to provoke an IO error when a cursor position is
228# "saved" (because another cursor is going to modify the underlying table).
229#
230do_ioerr_test shared_ioerr-3 -tclprep {
231  sqlite3 db2 test.db
232  execsql {
233    PRAGMA read_uncommitted = 1;
234    PRAGMA cache_size = 10;
235    BEGIN;
236    CREATE TABLE t1(a, b, UNIQUE(a, b));
237  } db2
238  for {set i 0} {$i < 200} {incr i} {
239    set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
240
241    set b [string repeat $i 2000]
242    execsql {INSERT INTO t1 VALUES($a, $b)} db2
243  }
244  execsql {COMMIT} db2
245  set ::DB2 [sqlite3_connection_pointer db2]
246  set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
247  sqlite3_step $::STMT       ;# Cursor points at 000.000.000.000
248  sqlite3_step $::STMT       ;# Cursor points at 001.001.001.001
249
250} -tclbody {
251  execsql {
252    BEGIN;
253    INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
254    UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
255    COMMIT;
256  }
257} -cleanup {
258  set ::steprc  [sqlite3_step $::STMT]
259  set ::column  [sqlite3_column_text $::STMT 0]
260  set ::finalrc [sqlite3_finalize $::STMT]
261
262  # There are three possible outcomes here (assuming persistent IO errors):
263  #
264  # 1. If the [sqlite3_step] did not require any IO (required pages in
265  #    the cache), then the next row ("002...") may be retrieved
266  #    successfully.
267  #
268  # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
269  #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
270  #
271  # 3. If, after the initial IO error, SQLite tried to rollback the
272  #    active transaction and a second IO error was encountered, then
273  #    statement $::STMT will have been aborted. This means [sqlite3_stmt]
274  #    returns SQLITE_ABORT, and the statement cursor does not move. i.e.
275  #    [sqlite3_column] still returns the current row ("001...") and
276  #    [sqlite3_finalize] returns SQLITE_OK.
277  #
278
279  do_test shared_ioerr-3.$n.cleanup.1 {
280    expr {
281      $::steprc eq "SQLITE_ROW" ||
282      $::steprc eq "SQLITE_ERROR" ||
283      $::steprc eq "SQLITE_ABORT"
284    }
285  } {1}
286  do_test shared_ioerr-3.$n.cleanup.2 {
287    expr {
288      ($::steprc eq "SQLITE_ROW" && $::column eq "002.002.002.002.002") ||
289      ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
290      ($::steprc eq "SQLITE_ABORT" && $::column eq "001.001.001.001.001")
291    }
292  } {1}
293  do_test shared_ioerr-3.$n.cleanup.3 {
294    expr {
295      ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
296      ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
297      ($::steprc eq "SQLITE_ABORT" && $::finalrc eq "SQLITE_OK")
298    }
299  } {1}
300
301# db2 eval {select * from sqlite_master}
302  db2 close
303}
304
305# This is a repeat of the previous test except that this time we
306# are doing a reverse-order scan of the table when the cursor is
307# "saved".
308#
309do_ioerr_test shared_ioerr-3rev -tclprep {
310  sqlite3 db2 test.db
311  execsql {
312    PRAGMA read_uncommitted = 1;
313    PRAGMA cache_size = 10;
314    BEGIN;
315    CREATE TABLE t1(a, b, UNIQUE(a, b));
316  } db2
317  for {set i 0} {$i < 200} {incr i} {
318    set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
319
320    set b [string repeat $i 2000]
321    execsql {INSERT INTO t1 VALUES($a, $b)} db2
322  }
323  execsql {COMMIT} db2
324  set ::DB2 [sqlite3_connection_pointer db2]
325  set ::STMT [sqlite3_prepare $::DB2 \
326           "SELECT a FROM t1 ORDER BY a DESC" -1 DUMMY]
327  sqlite3_step $::STMT       ;# Cursor points at 199.199.199.199.199
328  sqlite3_step $::STMT       ;# Cursor points at 198.198.198.198.198
329
330} -tclbody {
331  execsql {
332    BEGIN;
333    INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
334    UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
335    COMMIT;
336  }
337} -cleanup {
338  set ::steprc  [sqlite3_step $::STMT]
339  set ::column  [sqlite3_column_text $::STMT 0]
340  set ::finalrc [sqlite3_finalize $::STMT]
341
342  # There are three possible outcomes here (assuming persistent IO errors):
343  #
344  # 1. If the [sqlite3_step] did not require any IO (required pages in
345  #    the cache), then the next row ("002...") may be retrieved
346  #    successfully.
347  #
348  # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
349  #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
350  #
351  # 3. If, after the initial IO error, SQLite tried to rollback the
352  #    active transaction and a second IO error was encountered, then
353  #    statement $::STMT will have been aborted. This means [sqlite3_stmt]
354  #    returns SQLITE_ABORT, and the statement cursor does not move. i.e.
355  #    [sqlite3_column] still returns the current row ("001...") and
356  #    [sqlite3_finalize] returns SQLITE_OK.
357  #
358
359  do_test shared_ioerr-3rev.$n.cleanup.1 {
360    expr {
361      $::steprc eq "SQLITE_ROW" ||
362      $::steprc eq "SQLITE_ERROR" ||
363      $::steprc eq "SQLITE_ABORT"
364    }
365  } {1}
366  do_test shared_ioerr-3rev.$n.cleanup.2 {
367    expr {
368      ($::steprc eq "SQLITE_ROW" && $::column eq "197.197.197.197.197") ||
369      ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
370      ($::steprc eq "SQLITE_ABORT" && $::column eq "198.198.198.198.198")
371    }
372  } {1}
373  do_test shared_ioerr-3rev.$n.cleanup.3 {
374    expr {
375      ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
376      ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
377      ($::steprc eq "SQLITE_ABORT" && $::finalrc eq "SQLITE_OK")
378    }
379  } {1}
380
381# db2 eval {select * from sqlite_master}
382  db2 close
383}
384
385# Only run these tests if memory debugging is turned on.
386#
387if {[info command sqlite_malloc_stat]==""} {
388   puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
389   db close
390   sqlite3_enable_shared_cache $::enable_shared_cache
391   finish_test
392   return
393}
394
395# Provoke a malloc() failure when a cursor position is being saved. This
396# only happens with index cursors (because they malloc() space to save the
397# current key value). It does not happen with tables, because an integer
398# key does not require a malloc() to store.
399#
400# The library should return an SQLITE_NOMEM to the caller. The query that
401# owns the cursor (the one for which the position is not saved) should
402# continue unaffected.
403#
404do_malloc_test 4 -tclprep {
405  sqlite3 db2 test.db
406  execsql {
407    PRAGMA read_uncommitted = 1;
408    BEGIN;
409    CREATE TABLE t1(a, b, UNIQUE(a, b));
410  } db2
411  for {set i 0} {$i < 5} {incr i} {
412    set a [string repeat $i 10]
413    set b [string repeat $i 2000]
414    execsql {INSERT INTO t1 VALUES($a, $b)} db2
415  }
416  execsql {COMMIT} db2
417  set ::DB2 [sqlite3_connection_pointer db2]
418  set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
419  sqlite3_step $::STMT       ;# Cursor points at 0000000000
420  sqlite3_step $::STMT       ;# Cursor points at 1111111111
421} -tclbody {
422  execsql {
423    INSERT INTO t1 VALUES(6, NULL);
424  }
425} -cleanup {
426  do_test shared_malloc-4.$::n.cleanup.1 {
427    set ::rc [sqlite3_step $::STMT]
428    expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ABORT"}
429  } {1}
430  if {$::rc=="SQLITE_ROW"} {
431    do_test shared_malloc-4.$::n.cleanup.2 {
432      sqlite3_column_text $::STMT 0
433    } {2222222222}
434  }
435  do_test shared_malloc-4.$::n.cleanup.3 {
436    sqlite3_finalize $::STMT
437  } {SQLITE_OK}
438# db2 eval {select * from sqlite_master}
439  db2 close
440}
441
442do_malloc_test 5 -tclbody {
443  sqlite3 dbX test.db
444  sqlite3 dbY test.db
445  dbX close
446  dbY close
447} -cleanup {
448  catch {dbX close}
449  catch {dbY close}
450}
451
452do_malloc_test 6 -tclbody {
453  catch {db close}
454  sqlite3_thread_cleanup
455  sqlite3_enable_shared_cache 0
456} -cleanup {
457  sqlite3_enable_shared_cache 1
458}
459
460do_test shared_misuse-7.1 {
461  sqlite3 db test.db
462  catch {
463    sqlite3_enable_shared_cache 0
464  } msg
465  set msg
466} {library routine called out of sequence}
467
468# Again provoke a malloc() failure when a cursor position is being saved,
469# this time during a ROLLBACK operation by some other handle.
470#
471# The library should return an SQLITE_NOMEM to the caller. The query that
472# owns the cursor (the one for which the position is not saved) should
473# be aborted.
474#
475set ::aborted 0
476do_malloc_test 8 -tclprep {
477  sqlite3 db2 test.db
478  execsql {
479    PRAGMA read_uncommitted = 1;
480    BEGIN;
481    CREATE TABLE t1(a, b, UNIQUE(a, b));
482  } db2
483  for {set i 0} {$i < 2} {incr i} {
484    set a [string repeat $i 10]
485    set b [string repeat $i 2000]
486    execsql {INSERT INTO t1 VALUES($a, $b)} db2
487  }
488  execsql {COMMIT} db2
489  set ::DB2 [sqlite3_connection_pointer db2]
490  set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
491  sqlite3_step $::STMT       ;# Cursor points at 0000000000
492  sqlite3_step $::STMT       ;# Cursor points at 1111111111
493} -tclbody {
494  execsql {
495    BEGIN;
496    INSERT INTO t1 VALUES(6, NULL);
497    ROLLBACK;
498  }
499} -cleanup {
500  do_test shared_malloc-8.$::n.cleanup.1 {
501    lrange [execsql {
502      SELECT a FROM t1;
503    } db2] 0 1
504  } {0000000000 1111111111}
505  do_test shared_malloc-8.$::n.cleanup.2 {
506    set rc1 [sqlite3_step $::STMT]
507    set rc2 [sqlite3_finalize $::STMT]
508    if {$rc1=="SQLITE_ABORT"} {
509      incr ::aborted
510    }
511    expr {
512      ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") ||
513      ($rc1=="SQLITE_ABORT" && $rc2=="SQLITE_OK")
514    }
515  } {1}
516  db2 close
517}
518do_test shared_malloc-8.X {
519  # Test that one or more queries were aborted due to the malloc() failure.
520  expr $::aborted>=1
521} {1}
522
523catch {db close}
524sqlite3_enable_shared_cache $::enable_shared_cache
525finish_test
526