blob: 0fe0220eac08226d6798a61fc584a9354a39fa86 [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#
danielk19778d34dfd2006-01-24 16:37:57 +000016# $Id: shared_err.test,v 1.9 2006/01/24 16:37:59 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
32# Todo: This is a copy of the [do_malloc_test] proc in malloc.test
33# It would be better if these were consolidated.
34
35# Usage: do_malloc_test <test number> <options...>
36#
37# The first argument, <test number>, is an integer used to name the
38# tests executed by this proc. Options are as follows:
39#
40# -tclprep TCL script to run to prepare test.
41# -sqlprep SQL script to run to prepare test.
42# -tclbody TCL script to run with malloc failure simulation.
43# -sqlbody TCL script to run with malloc failure simulation.
44# -cleanup TCL script to run after the test.
45#
46# This command runs a series of tests to verify SQLite's ability
47# to handle an out-of-memory condition gracefully. It is assumed
48# that if this condition occurs a malloc() call will return a
49# NULL pointer. Linux, for example, doesn't do that by default. See
50# the "BUGS" section of malloc(3).
51#
52# Each iteration of a loop, the TCL commands in any argument passed
53# to the -tclbody switch, followed by the SQL commands in any argument
54# passed to the -sqlbody switch are executed. Each iteration the
55# Nth call to sqliteMalloc() is made to fail, where N is increased
56# each time the loop runs starting from 1. When all commands execute
57# successfully, the loop ends.
58#
59proc do_malloc_test {tn args} {
60 array unset ::mallocopts
61 array set ::mallocopts $args
62
63 set ::go 1
64 for {set ::n 1} {$::go && $::n < 50000} {incr ::n} {
65 do_test shared_malloc-$tn.$::n {
66
67 # Remove all traces of database files test.db and test2.db from the files
68 # system. Then open (empty database) "test.db" with the handle [db].
69 #
70 sqlite_malloc_fail 0
71 catch {db close}
72 catch {file delete -force test.db}
73 catch {file delete -force test.db-journal}
74 catch {file delete -force test2.db}
75 catch {file delete -force test2.db-journal}
76 catch {sqlite3 db test.db}
77 set ::DB [sqlite3_connection_pointer db]
78
79 # Execute any -tclprep and -sqlprep scripts.
80 #
81 if {[info exists ::mallocopts(-tclprep)]} {
82 eval $::mallocopts(-tclprep)
83 }
84 if {[info exists ::mallocopts(-sqlprep)]} {
85 execsql $::mallocopts(-sqlprep)
86 }
87
88 # Now set the ${::n}th malloc() to fail and execute the -tclbody and
89 # -sqlbody scripts.
90 #
91 sqlite_malloc_fail $::n
92 set ::mallocbody {}
93 if {[info exists ::mallocopts(-tclbody)]} {
94 append ::mallocbody "$::mallocopts(-tclbody)\n"
95 }
96 if {[info exists ::mallocopts(-sqlbody)]} {
97 append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
98 }
99 set v [catch $::mallocbody msg]
100
101 set leftover [lindex [sqlite_malloc_stat] 2]
102 if {$leftover>0} {
103 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
104 set ::go 0
105 if {$v} {
106 puts "\nError message returned: $msg"
107 } else {
108 set v {1 1}
109 }
110 } else {
111 set v2 [expr {$msg=="" || $msg=="out of memory"}]
112 if {!$v2} {puts "\nError message returned: $msg"}
113 lappend v $v2
114 }
115 } {1 1}
116
117 sqlite_malloc_fail 0
118 if {[info exists ::mallocopts(-cleanup)]} {
119 catch [list uplevel #0 $::mallocopts(-cleanup)] msg
120 }
121 }
122 unset ::mallocopts
123}
124
125
danielk197707cb5602006-01-20 10:55:05 +0000126do_ioerr_test shared_ioerr-1 -tclprep {
127 sqlite3 db2 test.db
128 execsql {
129 PRAGMA read_uncommitted = 1;
130 CREATE TABLE t1(a,b,c);
131 BEGIN;
132 SELECT * FROM sqlite_master;
133 } db2
134} -sqlbody {
135 SELECT * FROM sqlite_master;
136 INSERT INTO t1 VALUES(1,2,3);
137 BEGIN TRANSACTION;
138 INSERT INTO t1 VALUES(1,2,3);
139 INSERT INTO t1 VALUES(4,5,6);
140 ROLLBACK;
141 SELECT * FROM t1;
142 BEGIN TRANSACTION;
143 INSERT INTO t1 VALUES(1,2,3);
144 INSERT INTO t1 VALUES(4,5,6);
145 COMMIT;
146 SELECT * FROM t1;
147 DELETE FROM t1 WHERE a<100;
148} -cleanup {
danielk197797a227c2006-01-20 16:32:04 +0000149 do_test shared_ioerr-1.$n.cleanup.1 {
danielk197707cb5602006-01-20 10:55:05 +0000150 set res [catchsql {
151 SELECT * FROM t1;
152 } db2]
153 set possible_results [list \
154 "1 {disk I/O error}" \
155 "0 {1 2 3}" \
156 "0 {1 2 3 1 2 3 4 5 6}" \
157 "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}" \
158 "0 {}" \
159 ]
160 set rc [expr [lsearch -exact $possible_results $res] >= 0]
161 if {$rc != 1} {
162 puts ""
163 puts "Result: $res"
164 }
165 set rc
166 } {1}
167 db2 close
168}
169
170do_ioerr_test shared_ioerr-2 -tclprep {
171 sqlite3 db2 test.db
172 execsql {
173 PRAGMA read_uncommitted = 1;
174 BEGIN;
175 CREATE TABLE t1(a, b);
176 INSERT INTO t1(oid) VALUES(NULL);
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 INSERT INTO t1(oid) SELECT NULL FROM t1;
187 UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789';
188 CREATE INDEX i1 ON t1(a);
189 COMMIT;
190 BEGIN;
191 SELECT * FROM sqlite_master;
192 } db2
193} -tclbody {
194 set ::residx 0
195 execsql {DELETE FROM t1 WHERE 0 = (a % 2);}
196 incr ::residx
197
198 # When this transaction begins the table contains 512 entries. The
199 # two statements together add 512+146 more if it succeeds.
200 # (1024/7==146)
201 execsql {BEGIN;}
202 execsql {INSERT INTO t1 SELECT a+1, b FROM t1;}
203 execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);}
204 execsql {COMMIT;}
205
206 incr ::residx
207} -cleanup {
208 do_test shared_ioerr-2.$n.cleanup.1 {
209 set res [catchsql {
210 SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a);
211 } db2]
212 set possible_results [list \
213 {0 {1024 1 1024}} \
214 {0 {1023 1 512}} \
215 {0 {string994 1 1170}} \
216 ]
217 set idx [lsearch -exact $possible_results $res]
218 set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}]
219 if {!$success} {
220 puts ""
221 puts "Result: \"$res\" ($::residx)"
222 }
223 set success
224 } {1}
225 db2 close
226}
227
danielk197797a227c2006-01-20 16:32:04 +0000228# This test is designed to provoke an IO error when a cursor position is
229# "saved" (because another cursor is going to modify the underlying table).
230#
231do_ioerr_test shared_ioerr-3 -tclprep {
232 sqlite3 db2 test.db
233 execsql {
234 PRAGMA read_uncommitted = 1;
danielk1977c4da5b92006-01-21 12:08:54 +0000235 PRAGMA cache_size = 10;
236 BEGIN;
237 CREATE TABLE t1(a, b, UNIQUE(a, b));
238 } db2
239 for {set i 0} {$i < 200} {incr i} {
240 set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
241
242 set b [string repeat $i 2000]
243 execsql {INSERT INTO t1 VALUES($a, $b)} db2
244 }
245 execsql {COMMIT} db2
246 set ::DB2 [sqlite3_connection_pointer db2]
247 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
248 sqlite3_step $::STMT ;# Cursor points at 000.000.000.000
249 sqlite3_step $::STMT ;# Cursor points at 001.001.001.001
250
251} -tclbody {
252 execsql {
danielk197775bab7d2006-01-23 13:09:45 +0000253 BEGIN;
danielk1977c4da5b92006-01-21 12:08:54 +0000254 INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
danielk197775bab7d2006-01-23 13:09:45 +0000255 UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
256 COMMIT;
danielk1977c4da5b92006-01-21 12:08:54 +0000257 }
258} -cleanup {
259 do_test shared_ioerr-3.$n.cleanup.1 {
260 sqlite3_step $::STMT
261 } {SQLITE_ROW}
262 do_test shared_ioerr-3.$n.cleanup.2 {
263 sqlite3_column_text $::STMT 0
264 } {002.002.002.002.002}
265 do_test shared_ioerr-3.$n.cleanup.3 {
266 sqlite3_finalize $::STMT
267 } {SQLITE_OK}
268# db2 eval {select * from sqlite_master}
269 db2 close
270}
271
drh7b3822b2006-01-23 23:49:34 +0000272# Only run these tests if memory debugging is turned on.
273#
274if {[info command sqlite_malloc_stat]==""} {
275 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
drh80d56822006-01-24 00:15:15 +0000276 db close
277 sqlite3_enable_shared_cache $::enable_shared_cache
drh7b3822b2006-01-23 23:49:34 +0000278 finish_test
279 return
280}
281
danielk1977c4da5b92006-01-21 12:08:54 +0000282# Provoke a malloc() failure when a cursor position is being saved. This
283# only happens with index cursors (because they malloc() space to save the
284# current key value). It does not happen with tables, because an integer
285# key does not require a malloc() to store.
286#
287# The library should return an SQLITE_NOMEM to the caller. The query that
288# owns the cursor (the one for which the position is not saved) should
289# continue unaffected.
290#
291do_malloc_test 4 -tclprep {
292 sqlite3 db2 test.db
293 execsql {
294 PRAGMA read_uncommitted = 1;
danielk197797a227c2006-01-20 16:32:04 +0000295 BEGIN;
296 CREATE TABLE t1(a, b, UNIQUE(a, b));
297 } db2
298 for {set i 0} {$i < 5} {incr i} {
299 set a [string repeat $i 10]
300 set b [string repeat $i 2000]
301 execsql {INSERT INTO t1 VALUES($a, $b)} db2
302 }
303 execsql {COMMIT} db2
304 set ::DB2 [sqlite3_connection_pointer db2]
305 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
306 sqlite3_step $::STMT ;# Cursor points at 0000000000
307 sqlite3_step $::STMT ;# Cursor points at 1111111111
308} -tclbody {
309 execsql {
310 INSERT INTO t1 VALUES(6, NULL);
311 }
312} -cleanup {
danielk1977c4da5b92006-01-21 12:08:54 +0000313 do_test shared_malloc-4.$::n.cleanup.1 {
danielk19778d34dfd2006-01-24 16:37:57 +0000314 set ::rc [sqlite3_step $::STMT]
315 expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ABORT"}
316 } {1}
317 if {$::rc=="SQLITE_ROW"} {
318 do_test shared_malloc-4.$::n.cleanup.2 {
319 sqlite3_column_text $::STMT 0
320 } {2222222222}
321 }
danielk1977c4da5b92006-01-21 12:08:54 +0000322 do_test shared_malloc-4.$::n.cleanup.3 {
danielk197797a227c2006-01-20 16:32:04 +0000323 sqlite3_finalize $::STMT
324 } {SQLITE_OK}
325# db2 eval {select * from sqlite_master}
326 db2 close
327}
328
danielk19774b202ae2006-01-23 05:50:58 +0000329do_malloc_test 5 -tclbody {
330 sqlite3 dbX test.db
331 sqlite3 dbY test.db
332 dbX close
333 dbY close
334} -cleanup {
335 catch {dbX close}
336 catch {dbY close}
337}
338
danielk19777246f5b2006-01-24 11:30:27 +0000339do_malloc_test 6 -tclbody {
340 catch {db close}
341 sqlite3_thread_cleanup
342 sqlite3_enable_shared_cache 0
343} -cleanup {
344 sqlite3_enable_shared_cache 1
345}
346
347do_test shared_misuse-7.1 {
348 sqlite3 db test.db
349 catch {
350 sqlite3_enable_shared_cache 0
351 } msg
352 set msg
353} {library routine called out of sequence}
354
danielk19778d34dfd2006-01-24 16:37:57 +0000355# Again provoke a malloc() failure when a cursor position is being saved,
356# this time during a ROLLBACK operation by some other handle.
357#
358# The library should return an SQLITE_NOMEM to the caller. The query that
359# owns the cursor (the one for which the position is not saved) should
360# be aborted.
361#
362set ::aborted 0
363do_malloc_test 8 -tclprep {
364 sqlite3 db2 test.db
365 execsql {
366 PRAGMA read_uncommitted = 1;
367 BEGIN;
368 CREATE TABLE t1(a, b, UNIQUE(a, b));
369 } db2
370 for {set i 0} {$i < 2} {incr i} {
371 set a [string repeat $i 10]
372 set b [string repeat $i 2000]
373 execsql {INSERT INTO t1 VALUES($a, $b)} db2
374 }
375 execsql {COMMIT} db2
376 set ::DB2 [sqlite3_connection_pointer db2]
377 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
378 sqlite3_step $::STMT ;# Cursor points at 0000000000
379 sqlite3_step $::STMT ;# Cursor points at 1111111111
380} -tclbody {
381 execsql {
382 BEGIN;
383 INSERT INTO t1 VALUES(6, NULL);
384 ROLLBACK;
385 }
386} -cleanup {
387 do_test shared_malloc-8.$::n.cleanup.1 {
388 lrange [execsql {
389 SELECT a FROM t1;
390 } db2] 0 1
391 } {0000000000 1111111111}
392 do_test shared_malloc-8.$::n.cleanup.2 {
393 set rc1 [sqlite3_step $::STMT]
394 set rc2 [sqlite3_finalize $::STMT]
395 if {$rc1=="SQLITE_ABORT"} {
396 incr ::aborted
397 }
398 expr {
399 ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") ||
400 ($rc1=="SQLITE_ABORT" && $rc2=="SQLITE_OK")
401 }
402 } {1}
403 db2 close
404}
405do_test shared_malloc-8.X {
406 # Test that one or more queries were aborted due to the malloc() failure.
407 expr $::aborted>=1
408} {1}
409
danielk197707cb5602006-01-20 10:55:05 +0000410catch {db close}
411sqlite3_enable_shared_cache $::enable_shared_cache
412finish_test