blob: e4ba31c3ae746ae37239af56ab52cb3cf802c9b6 [file] [log] [blame]
danielk197707cb5602006-01-20 10:55:05 +00001# 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#
danielk1977b94bf852007-03-19 13:53:37 +000016# $Id: shared_err.test,v 1.10 2007/03/19 13:53:38 danielk1977 Exp $
danielk197707cb5602006-01-20 10:55:05 +000017
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
danielk1977c4da5b92006-01-21 12:08:54 +000031# 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
danielk197707cb5602006-01-20 10:55:05 +0000125do_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 {
danielk197797a227c2006-01-20 16:32:04 +0000148 do_test shared_ioerr-1.$n.cleanup.1 {
danielk197707cb5602006-01-20 10:55:05 +0000149 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
danielk197797a227c2006-01-20 16:32:04 +0000227# 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;
danielk1977c4da5b92006-01-21 12:08:54 +0000234 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 {
danielk197775bab7d2006-01-23 13:09:45 +0000252 BEGIN;
danielk1977c4da5b92006-01-21 12:08:54 +0000253 INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
danielk197775bab7d2006-01-23 13:09:45 +0000254 UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
255 COMMIT;
danielk1977c4da5b92006-01-21 12:08:54 +0000256 }
257} -cleanup {
danielk1977b94bf852007-03-19 13:53:37 +0000258 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
danielk1977c4da5b92006-01-21 12:08:54 +0000279 do_test shared_ioerr-3.$n.cleanup.1 {
danielk1977b94bf852007-03-19 13:53:37 +0000280 expr {
281 $::steprc eq "SQLITE_ROW" ||
282 $::steprc eq "SQLITE_ERROR" ||
283 $::steprc eq "SQLITE_ABORT"
284 }
285 } {1}
danielk1977c4da5b92006-01-21 12:08:54 +0000286 do_test shared_ioerr-3.$n.cleanup.2 {
danielk1977b94bf852007-03-19 13:53:37 +0000287 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}
danielk1977c4da5b92006-01-21 12:08:54 +0000293 do_test shared_ioerr-3.$n.cleanup.3 {
danielk1977b94bf852007-03-19 13:53:37 +0000294 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
danielk1977c4da5b92006-01-21 12:08:54 +0000301# db2 eval {select * from sqlite_master}
302 db2 close
303}
304
drh7b3822b2006-01-23 23:49:34 +0000305# Only run these tests if memory debugging is turned on.
306#
307if {[info command sqlite_malloc_stat]==""} {
308 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
drh80d56822006-01-24 00:15:15 +0000309 db close
310 sqlite3_enable_shared_cache $::enable_shared_cache
drh7b3822b2006-01-23 23:49:34 +0000311 finish_test
312 return
313}
314
danielk1977c4da5b92006-01-21 12:08:54 +0000315# Provoke a malloc() failure when a cursor position is being saved. This
316# only happens with index cursors (because they malloc() space to save the
317# current key value). It does not happen with tables, because an integer
318# key does not require a malloc() to store.
319#
320# The library should return an SQLITE_NOMEM to the caller. The query that
321# owns the cursor (the one for which the position is not saved) should
322# continue unaffected.
323#
324do_malloc_test 4 -tclprep {
325 sqlite3 db2 test.db
326 execsql {
327 PRAGMA read_uncommitted = 1;
danielk197797a227c2006-01-20 16:32:04 +0000328 BEGIN;
329 CREATE TABLE t1(a, b, UNIQUE(a, b));
330 } db2
331 for {set i 0} {$i < 5} {incr i} {
332 set a [string repeat $i 10]
333 set b [string repeat $i 2000]
334 execsql {INSERT INTO t1 VALUES($a, $b)} db2
335 }
336 execsql {COMMIT} db2
337 set ::DB2 [sqlite3_connection_pointer db2]
338 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
339 sqlite3_step $::STMT ;# Cursor points at 0000000000
340 sqlite3_step $::STMT ;# Cursor points at 1111111111
341} -tclbody {
342 execsql {
343 INSERT INTO t1 VALUES(6, NULL);
344 }
345} -cleanup {
danielk1977c4da5b92006-01-21 12:08:54 +0000346 do_test shared_malloc-4.$::n.cleanup.1 {
danielk19778d34dfd2006-01-24 16:37:57 +0000347 set ::rc [sqlite3_step $::STMT]
348 expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ABORT"}
349 } {1}
350 if {$::rc=="SQLITE_ROW"} {
351 do_test shared_malloc-4.$::n.cleanup.2 {
352 sqlite3_column_text $::STMT 0
353 } {2222222222}
354 }
danielk1977c4da5b92006-01-21 12:08:54 +0000355 do_test shared_malloc-4.$::n.cleanup.3 {
danielk197797a227c2006-01-20 16:32:04 +0000356 sqlite3_finalize $::STMT
357 } {SQLITE_OK}
358# db2 eval {select * from sqlite_master}
359 db2 close
360}
361
danielk19774b202ae2006-01-23 05:50:58 +0000362do_malloc_test 5 -tclbody {
363 sqlite3 dbX test.db
364 sqlite3 dbY test.db
365 dbX close
366 dbY close
367} -cleanup {
368 catch {dbX close}
369 catch {dbY close}
370}
371
danielk19777246f5b2006-01-24 11:30:27 +0000372do_malloc_test 6 -tclbody {
373 catch {db close}
374 sqlite3_thread_cleanup
375 sqlite3_enable_shared_cache 0
376} -cleanup {
377 sqlite3_enable_shared_cache 1
378}
379
380do_test shared_misuse-7.1 {
381 sqlite3 db test.db
382 catch {
383 sqlite3_enable_shared_cache 0
384 } msg
385 set msg
386} {library routine called out of sequence}
387
danielk19778d34dfd2006-01-24 16:37:57 +0000388# Again provoke a malloc() failure when a cursor position is being saved,
389# this time during a ROLLBACK operation by some other handle.
390#
391# The library should return an SQLITE_NOMEM to the caller. The query that
392# owns the cursor (the one for which the position is not saved) should
393# be aborted.
394#
395set ::aborted 0
396do_malloc_test 8 -tclprep {
397 sqlite3 db2 test.db
398 execsql {
399 PRAGMA read_uncommitted = 1;
400 BEGIN;
401 CREATE TABLE t1(a, b, UNIQUE(a, b));
402 } db2
403 for {set i 0} {$i < 2} {incr i} {
404 set a [string repeat $i 10]
405 set b [string repeat $i 2000]
406 execsql {INSERT INTO t1 VALUES($a, $b)} db2
407 }
408 execsql {COMMIT} db2
409 set ::DB2 [sqlite3_connection_pointer db2]
410 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
411 sqlite3_step $::STMT ;# Cursor points at 0000000000
412 sqlite3_step $::STMT ;# Cursor points at 1111111111
413} -tclbody {
414 execsql {
415 BEGIN;
416 INSERT INTO t1 VALUES(6, NULL);
417 ROLLBACK;
418 }
419} -cleanup {
420 do_test shared_malloc-8.$::n.cleanup.1 {
421 lrange [execsql {
422 SELECT a FROM t1;
423 } db2] 0 1
424 } {0000000000 1111111111}
425 do_test shared_malloc-8.$::n.cleanup.2 {
426 set rc1 [sqlite3_step $::STMT]
427 set rc2 [sqlite3_finalize $::STMT]
428 if {$rc1=="SQLITE_ABORT"} {
429 incr ::aborted
430 }
431 expr {
432 ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") ||
433 ($rc1=="SQLITE_ABORT" && $rc2=="SQLITE_OK")
434 }
435 } {1}
436 db2 close
437}
438do_test shared_malloc-8.X {
439 # Test that one or more queries were aborted due to the malloc() failure.
440 expr $::aborted>=1
441} {1}
442
danielk197707cb5602006-01-20 10:55:05 +0000443catch {db close}
444sqlite3_enable_shared_cache $::enable_shared_cache
445finish_test