Annotation of embedaddon/sqlite3/test/malloc.test, revision 1.1
1.1 ! misho 1: # 2001 September 15
! 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 attempts to check the behavior of the SQLite library in
! 13: # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1,
! 14: # the SQLite library accepts a special command (sqlite3_memdebug_fail N C)
! 15: # which causes the N-th malloc to fail. This special feature is used
! 16: # to see what happens in the library if a malloc were to really fail
! 17: # due to an out-of-memory situation.
! 18: #
! 19: # $Id: malloc.test,v 1.81 2009/06/24 13:13:45 drh Exp $
! 20:
! 21: set testdir [file dirname $argv0]
! 22: source $testdir/tester.tcl
! 23:
! 24:
! 25: # Only run these tests if memory debugging is turned on.
! 26: #
! 27: source $testdir/malloc_common.tcl
! 28: if {!$MEMDEBUG} {
! 29: puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
! 30: finish_test
! 31: return
! 32: }
! 33:
! 34: # Do a couple of memory dumps just to exercise the memory dump logic
! 35: # that that we can say that we have.
! 36: #
! 37: puts stderr "This is a test. Ignore the error that follows:"
! 38: sqlite3_memdebug_dump $testdir
! 39: puts "Memory dump to file memdump.txt..."
! 40: sqlite3_memdebug_dump memdump.txt
! 41:
! 42: ifcapable bloblit&&subquery {
! 43: do_malloc_test 1 -tclprep {
! 44: db close
! 45: } -tclbody {
! 46: if {[catch {sqlite3 db test.db}]} {
! 47: error "out of memory"
! 48: }
! 49: sqlite3_extended_result_codes db 1
! 50: } -sqlbody {
! 51: DROP TABLE IF EXISTS t1;
! 52: CREATE TABLE t1(
! 53: a int, b float, c double, d text, e varchar(20),
! 54: primary key(a,b,c)
! 55: );
! 56: CREATE INDEX i1 ON t1(a,b);
! 57: INSERT INTO t1 VALUES(1,2.3,4.5,'hi',x'746865726500');
! 58: INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
! 59: SELECT * FROM t1;
! 60: SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
! 61: DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
! 62: SELECT count(*), group_concat(e) FROM t1;
! 63: SELECT b FROM t1 ORDER BY 1 COLLATE nocase;
! 64: }
! 65: }
! 66:
! 67: # Ensure that no file descriptors were leaked.
! 68: do_test malloc-1.X {
! 69: catch {db close}
! 70: set sqlite_open_file_count
! 71: } {0}
! 72:
! 73: ifcapable subquery {
! 74: do_malloc_test 2 -sqlbody {
! 75: CREATE TABLE t1(a int, b int default 'abc', c int default 1);
! 76: CREATE INDEX i1 ON t1(a,b);
! 77: INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
! 78: INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
! 79: INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
! 80: INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
! 81: INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
! 82: INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
! 83: SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
! 84: UPDATE t1 SET b=b||b||b||b;
! 85: UPDATE t1 SET b=a WHERE a in (10,12,22);
! 86: INSERT INTO t1(c,b,a) VALUES(20,10,5);
! 87: INSERT INTO t1 SELECT * FROM t1
! 88: WHERE a IN (SELECT a FROM t1 WHERE a<10);
! 89: DELETE FROM t1 WHERE a>=10;
! 90: DROP INDEX i1;
! 91: DELETE FROM t1;
! 92: }
! 93: }
! 94:
! 95: # Ensure that no file descriptors were leaked.
! 96: do_test malloc-2.X {
! 97: catch {db close}
! 98: set sqlite_open_file_count
! 99: } {0}
! 100:
! 101: do_malloc_test 3 -sqlbody {
! 102: BEGIN TRANSACTION;
! 103: CREATE TABLE t1(a int, b int, c int);
! 104: CREATE INDEX i1 ON t1(a,b);
! 105: INSERT INTO t1 VALUES(1,1,99);
! 106: INSERT INTO t1 VALUES(2,4,98);
! 107: INSERT INTO t1 VALUES(3,9,97);
! 108: INSERT INTO t1 VALUES(4,16,96);
! 109: INSERT INTO t1 VALUES(5,25,95);
! 110: INSERT INTO t1 VALUES(6,36,94);
! 111: INSERT INTO t1(c,b,a) VALUES(20,10,5);
! 112: DELETE FROM t1 WHERE a>=10;
! 113: DROP INDEX i1;
! 114: DELETE FROM t1;
! 115: ROLLBACK;
! 116: }
! 117:
! 118:
! 119: # Ensure that no file descriptors were leaked.
! 120: do_test malloc-3.X {
! 121: catch {db close}
! 122: set sqlite_open_file_count
! 123: } {0}
! 124:
! 125: ifcapable subquery {
! 126: do_malloc_test 4 -sqlbody {
! 127: BEGIN TRANSACTION;
! 128: CREATE TABLE t1(a int, b int, c int);
! 129: CREATE INDEX i1 ON t1(a,b);
! 130: INSERT INTO t1 VALUES(1,1,99);
! 131: INSERT INTO t1 VALUES(2,4,98);
! 132: INSERT INTO t1 VALUES(3,9,97);
! 133: INSERT INTO t1 VALUES(4,16,96);
! 134: INSERT INTO t1 VALUES(5,25,95);
! 135: INSERT INTO t1 VALUES(6,36,94);
! 136: UPDATE t1 SET b=a WHERE a in (10,12,22);
! 137: INSERT INTO t1 SELECT * FROM t1
! 138: WHERE a IN (SELECT a FROM t1 WHERE a<10);
! 139: DROP INDEX i1;
! 140: DELETE FROM t1;
! 141: COMMIT;
! 142: }
! 143: }
! 144:
! 145: # Ensure that no file descriptors were leaked.
! 146: do_test malloc-4.X {
! 147: catch {db close}
! 148: set sqlite_open_file_count
! 149: } {0}
! 150:
! 151: ifcapable trigger {
! 152: do_malloc_test 5 -sqlbody {
! 153: BEGIN TRANSACTION;
! 154: CREATE TABLE t1(a,b);
! 155: CREATE TABLE t2(x,y);
! 156: CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a = 2 BEGIN
! 157: INSERT INTO t2(x,y) VALUES(new.rowid,1);
! 158: INSERT INTO t2(x,y) SELECT * FROM t2;
! 159: INSERT INTO t2 SELECT * FROM t2;
! 160: UPDATE t2 SET y=y+1 WHERE x=new.rowid;
! 161: SELECT 123;
! 162: DELETE FROM t2 WHERE x=new.rowid;
! 163: END;
! 164: INSERT INTO t1(a,b) VALUES(2,3);
! 165: COMMIT;
! 166: }
! 167: }
! 168:
! 169: # Ensure that no file descriptors were leaked.
! 170: do_test malloc-5.X {
! 171: catch {db close}
! 172: set sqlite_open_file_count
! 173: } {0}
! 174:
! 175: ifcapable vacuum {
! 176: do_malloc_test 6 -sqlprep {
! 177: BEGIN TRANSACTION;
! 178: CREATE TABLE t1(a);
! 179: INSERT INTO t1 VALUES(1);
! 180: INSERT INTO t1 SELECT a*2 FROM t1;
! 181: INSERT INTO t1 SELECT a*2 FROM t1;
! 182: INSERT INTO t1 SELECT a*2 FROM t1;
! 183: INSERT INTO t1 SELECT a*2 FROM t1;
! 184: INSERT INTO t1 SELECT a*2 FROM t1;
! 185: INSERT INTO t1 SELECT a*2 FROM t1;
! 186: INSERT INTO t1 SELECT a*2 FROM t1;
! 187: INSERT INTO t1 SELECT a*2 FROM t1;
! 188: INSERT INTO t1 SELECT a*2 FROM t1;
! 189: INSERT INTO t1 SELECT a*2 FROM t1;
! 190: DELETE FROM t1 where rowid%5 = 0;
! 191: COMMIT;
! 192: } -sqlbody {
! 193: VACUUM;
! 194: }
! 195: }
! 196:
! 197: autoinstall_test_functions
! 198: do_malloc_test 7 -sqlprep {
! 199: CREATE TABLE t1(a, b);
! 200: INSERT INTO t1 VALUES(1, 2);
! 201: INSERT INTO t1 VALUES(3, 4);
! 202: INSERT INTO t1 VALUES(5, 6);
! 203: INSERT INTO t1 VALUES(7, randstr(1200,1200));
! 204: } -sqlbody {
! 205: SELECT min(a) FROM t1 WHERE a<6 GROUP BY b;
! 206: SELECT a FROM t1 WHERE a<6 ORDER BY a;
! 207: SELECT b FROM t1 WHERE a>6;
! 208: }
! 209:
! 210: # This block is designed to test that some malloc failures that may
! 211: # occur in vdbeapi.c. Specifically, if a malloc failure that occurs
! 212: # when converting UTF-16 text to integers and real numbers is handled
! 213: # correctly.
! 214: #
! 215: # This is done by retrieving a string from the database engine and
! 216: # manipulating it using the sqlite3_column_*** APIs. This doesn't
! 217: # actually return an error to the user when a malloc() fails.. That
! 218: # could be viewed as a bug.
! 219: #
! 220: # These tests only run if UTF-16 support is compiled in.
! 221: #
! 222: ifcapable utf16 {
! 223: set ::STMT {}
! 224: do_malloc_test 8 -tclprep {
! 225: set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?"
! 226: set ::STMT [sqlite3_prepare db $sql -1 X]
! 227: sqlite3_step $::STMT
! 228: if { $::tcl_platform(byteOrder)=="littleEndian" } {
! 229: set ::bomstr "\xFF\xFE"
! 230: } else {
! 231: set ::bomstr "\xFE\xFF"
! 232: }
! 233: append ::bomstr [encoding convertto unicode "123456789_123456789_123456789"]
! 234: } -tclbody {
! 235: sqlite3_column_text16 $::STMT 0
! 236: sqlite3_column_int $::STMT 0
! 237: sqlite3_column_text16 $::STMT 1
! 238: sqlite3_column_double $::STMT 1
! 239: set rc [sqlite3_reset $::STMT]
! 240: if {$rc eq "SQLITE_NOMEM"} {error "out of memory"}
! 241: sqlite3_bind_text16 $::STMT 1 $::bomstr 60
! 242: #catch {sqlite3_finalize $::STMT}
! 243: #if {[lindex [sqlite_malloc_stat] 2]<=0} {
! 244: # error "out of memory"
! 245: #}
! 246: } -cleanup {
! 247: if {$::STMT!=""} {
! 248: sqlite3_finalize $::STMT
! 249: set ::STMT {}
! 250: }
! 251: }
! 252: }
! 253:
! 254: # This block tests that malloc() failures that occur whilst commiting
! 255: # a multi-file transaction are handled correctly.
! 256: #
! 257: do_malloc_test 9 -sqlprep {
! 258: ATTACH 'test2.db' as test2;
! 259: CREATE TABLE abc1(a, b, c);
! 260: CREATE TABLE test2.abc2(a, b, c);
! 261: } -sqlbody {
! 262: BEGIN;
! 263: INSERT INTO abc1 VALUES(1, 2, 3);
! 264: INSERT INTO abc2 VALUES(1, 2, 3);
! 265: COMMIT;
! 266: }
! 267:
! 268: # This block tests malloc() failures that occur while opening a
! 269: # connection to a database.
! 270: do_malloc_test 10 -tclprep {
! 271: catch {db2 close}
! 272: db close
! 273: forcedelete test.db test.db-journal
! 274: sqlite3 db test.db
! 275: sqlite3_extended_result_codes db 1
! 276: db eval {CREATE TABLE abc(a, b, c)}
! 277: } -tclbody {
! 278: db close
! 279: sqlite3 db2 test.db
! 280: sqlite3_extended_result_codes db2 1
! 281: db2 eval {SELECT * FROM sqlite_master}
! 282: db2 close
! 283: }
! 284:
! 285: # This block tests malloc() failures that occur within calls to
! 286: # sqlite3_create_function().
! 287: do_malloc_test 11 -tclbody {
! 288: set rc [sqlite3_create_function db]
! 289: if {[string match $rc SQLITE_OK]} {
! 290: set rc [sqlite3_create_aggregate db]
! 291: }
! 292: if {[string match $rc SQLITE_NOMEM]} {
! 293: error "out of memory"
! 294: }
! 295: }
! 296:
! 297: do_malloc_test 12 -tclbody {
! 298: set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"]
! 299: append sql16 "\00\00"
! 300: set ::STMT [sqlite3_prepare16 db $sql16 -1 DUMMY]
! 301: sqlite3_finalize $::STMT
! 302: }
! 303:
! 304: # Test malloc errors when replaying two hot journals from a 2-file
! 305: # transaction.
! 306: ifcapable crashtest&&attach {
! 307: do_malloc_test 13 -tclprep {
! 308: set rc [crashsql -delay 1 -file test2.db {
! 309: ATTACH 'test2.db' as aux;
! 310: PRAGMA cache_size = 10;
! 311: BEGIN;
! 312: CREATE TABLE aux.t2(a, b, c);
! 313: CREATE TABLE t1(a, b, c);
! 314: COMMIT;
! 315: }]
! 316: if {$rc!="1 {child process exited abnormally}"} {
! 317: error "Wrong error message: $rc"
! 318: }
! 319: } -tclbody {
! 320: db eval {ATTACH 'test2.db' as aux;}
! 321: set rc [catch {db eval {
! 322: SELECT * FROM t1;
! 323: SELECT * FROM t2;
! 324: }} err]
! 325: if {$rc && $err!="no such table: t1"} {
! 326: error $err
! 327: }
! 328: }
! 329: }
! 330:
! 331: if {$tcl_platform(platform)!="windows"} {
! 332: do_malloc_test 14 -tclprep {
! 333: catch {db close}
! 334: sqlite3 db2 test2.db
! 335: sqlite3_extended_result_codes db2 1
! 336: db2 eval {
! 337: PRAGMA journal_mode = DELETE; /* For inmemory_journal permutation */
! 338: PRAGMA synchronous = 0;
! 339: CREATE TABLE t1(a, b);
! 340: INSERT INTO t1 VALUES(1, 2);
! 341: BEGIN;
! 342: INSERT INTO t1 VALUES(3, 4);
! 343: }
! 344: forcecopy test2.db test.db
! 345: forcecopy test2.db-journal test.db-journal
! 346: db2 close
! 347: } -tclbody {
! 348: sqlite3 db test.db
! 349: sqlite3_extended_result_codes db 1
! 350:
! 351: # If an out-of-memory occurs within a call to a VFS layer function during
! 352: # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit
! 353: # [5668] for details.
! 354: set rc [catch {db eval { SELECT * FROM t1 }} msg]
! 355: if {$msg eq "database disk image is malformed"} { set msg "out of memory" }
! 356: if {$rc} { error $msg }
! 357: set msg
! 358: }
! 359: }
! 360:
! 361: proc string_compare {a b} {
! 362: return [string compare $a $b]
! 363: }
! 364:
! 365: # Test for malloc() failures in sqlite3_create_collation() and
! 366: # sqlite3_create_collation16().
! 367: #
! 368: ifcapable utf16 {
! 369: do_malloc_test 15 -start 4 -tclbody {
! 370: db collate string_compare string_compare
! 371: if {[catch {add_test_collate db 1 1 1} msg]} {
! 372: if {$msg=="SQLITE_NOMEM"} {set msg "out of memory"}
! 373: error $msg
! 374: }
! 375:
! 376: db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;}
! 377: db complete {-- Useful comment}
! 378:
! 379: execsql {
! 380: CREATE TABLE t1(a, b COLLATE string_compare);
! 381: INSERT INTO t1 VALUES(10, 'string');
! 382: INSERT INTO t1 VALUES(10, 'string2');
! 383: }
! 384: }
! 385: }
! 386:
! 387: # Also test sqlite3_complete(). There are (currently) no malloc()
! 388: # calls in this function, but test anyway against future changes.
! 389: #
! 390: do_malloc_test 16 -tclbody {
! 391: db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;}
! 392: db complete {-- Useful comment}
! 393: db eval {
! 394: SELECT * FROM sqlite_master;
! 395: }
! 396: }
! 397:
! 398: # Test handling of malloc() failures in sqlite3_open16().
! 399: #
! 400: ifcapable utf16 {
! 401: do_malloc_test 17 -tclbody {
! 402: set DB2 0
! 403: set STMT 0
! 404:
! 405: # open database using sqlite3_open16()
! 406: set filename [encoding convertto unicode test.db]
! 407: append filename "\x00\x00"
! 408: set DB2 [sqlite3_open16 $filename -unused]
! 409: if {0==$DB2} {
! 410: error "out of memory"
! 411: }
! 412: sqlite3_extended_result_codes $DB2 1
! 413:
! 414: # Prepare statement
! 415: set rc [catch {sqlite3_prepare $DB2 {SELECT * FROM sqlite_master} -1 X} msg]
! 416: if {[sqlite3_errcode $DB2] eq "SQLITE_IOERR+12"} {
! 417: error "out of memory"
! 418: }
! 419: if {[regexp ".*automatic extension loading.*" [sqlite3_errmsg $DB2]]} {
! 420: error "out of memory"
! 421: }
! 422: if {$rc} {
! 423: error [string range $msg 4 end]
! 424: }
! 425: set STMT $msg
! 426:
! 427: # Finalize statement
! 428: set rc [sqlite3_finalize $STMT]
! 429: if {$rc!="SQLITE_OK"} {
! 430: error [sqlite3_errmsg $DB2]
! 431: }
! 432: set STMT 0
! 433:
! 434: # Close database
! 435: set rc [sqlite3_close $DB2]
! 436: if {$rc!="SQLITE_OK"} {
! 437: error [sqlite3_errmsg $DB2]
! 438: }
! 439: set DB2 0
! 440: } -cleanup {
! 441: if {$STMT!="0"} {
! 442: sqlite3_finalize $STMT
! 443: }
! 444: if {$DB2!="0"} {
! 445: set rc [sqlite3_close $DB2]
! 446: }
! 447: }
! 448: }
! 449:
! 450: # Test handling of malloc() failures in sqlite3_errmsg16().
! 451: #
! 452: ifcapable utf16 {
! 453: do_malloc_test 18 -tclprep {
! 454: catch {
! 455: db eval "SELECT [string repeat longcolumnname 10] FROM sqlite_master"
! 456: }
! 457: } -tclbody {
! 458: set utf16 [sqlite3_errmsg16 [sqlite3_connection_pointer db]]
! 459: binary scan $utf16 c* bytes
! 460: if {[llength $bytes]==0} {
! 461: error "out of memory"
! 462: }
! 463: }
! 464: }
! 465:
! 466: # This test is aimed at coverage testing. Specificly, it is supposed to
! 467: # cause a malloc() only used when converting between the two utf-16
! 468: # encodings to fail (i.e. little-endian->big-endian). It only actually
! 469: # hits this malloc() on little-endian hosts.
! 470: #
! 471: set static_string "\x00h\x00e\x00l\x00l\x00o"
! 472: for {set l 0} {$l<10} {incr l} {
! 473: append static_string $static_string
! 474: }
! 475: append static_string "\x00\x00"
! 476: do_malloc_test 19 -tclprep {
! 477: execsql {
! 478: PRAGMA encoding = "UTF16be";
! 479: CREATE TABLE abc(a, b, c);
! 480: }
! 481: } -tclbody {
! 482: unset -nocomplain ::STMT
! 483: set r [catch {
! 484: set ::STMT [sqlite3_prepare db {SELECT ?} -1 DUMMY]
! 485: sqlite3_bind_text16 -static $::STMT 1 $static_string 112
! 486: } msg]
! 487: if {$r} {error [string range $msg 4 end]}
! 488: set msg
! 489: } -cleanup {
! 490: if {[info exists ::STMT]} {
! 491: sqlite3_finalize $::STMT
! 492: }
! 493: }
! 494: unset static_string
! 495:
! 496: # Make sure SQLITE_NOMEM is reported out on an ATTACH failure even
! 497: # when the malloc failure occurs within the nested parse.
! 498: #
! 499: ifcapable attach {
! 500: do_malloc_test 20 -tclprep {
! 501: db close
! 502: forcedelete test2.db test2.db-journal
! 503: sqlite3 db test2.db
! 504: sqlite3_extended_result_codes db 1
! 505: db eval {CREATE TABLE t1(x);}
! 506: db close
! 507: } -tclbody {
! 508: if {[catch {sqlite3 db test.db}]} {
! 509: error "out of memory"
! 510: }
! 511: sqlite3_extended_result_codes db 1
! 512: } -sqlbody {
! 513: ATTACH DATABASE 'test2.db' AS t2;
! 514: SELECT * FROM t1;
! 515: DETACH DATABASE t2;
! 516: }
! 517: }
! 518:
! 519: # Test malloc failure whilst installing a foreign key.
! 520: #
! 521: ifcapable foreignkey {
! 522: do_malloc_test 21 -sqlbody {
! 523: CREATE TABLE abc(a, b, c, FOREIGN KEY(a) REFERENCES abc(b))
! 524: }
! 525: }
! 526:
! 527: # Test malloc failure in an sqlite3_prepare_v2() call.
! 528: #
! 529: do_malloc_test 22 -tclbody {
! 530: set ::STMT ""
! 531: set r [catch {
! 532: set ::STMT [
! 533: sqlite3_prepare_v2 db "SELECT * FROM sqlite_master" -1 DUMMY
! 534: ]
! 535: } msg]
! 536: if {$r} {error [string range $msg 4 end]}
! 537: } -cleanup {
! 538: if {$::STMT ne ""} {
! 539: sqlite3_finalize $::STMT
! 540: set ::STMT ""
! 541: }
! 542: }
! 543:
! 544: ifcapable {pager_pragmas} {
! 545: # This tests a special case - that an error that occurs while the pager
! 546: # is trying to recover from error-state in exclusive-access mode works.
! 547: #
! 548: do_malloc_test 23 -tclprep {
! 549: db eval {
! 550: PRAGMA cache_size = 10;
! 551: PRAGMA locking_mode = exclusive;
! 552: BEGIN;
! 553: CREATE TABLE abc(a, b, c);
! 554: CREATE INDEX abc_i ON abc(a, b, c);
! 555: INSERT INTO abc
! 556: VALUES(randstr(100,100), randstr(100,100), randstr(100,100));
! 557: INSERT INTO abc
! 558: SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
! 559: INSERT INTO abc
! 560: SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
! 561: INSERT INTO abc
! 562: SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
! 563: INSERT INTO abc
! 564: SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
! 565: INSERT INTO abc
! 566: SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
! 567: COMMIT;
! 568: }
! 569:
! 570: # This puts the pager into error state.
! 571: #
! 572: db eval BEGIN
! 573: db eval {UPDATE abc SET a = 0 WHERE oid%2}
! 574: set ::sqlite_io_error_pending 10
! 575: catch {db eval {ROLLBACK}} msg
! 576:
! 577: } -tclbody {
! 578: # If an out-of-memory occurs within a call to a VFS layer function during
! 579: # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit
! 580: # [5668] for details.
! 581: set rc [catch {db eval { SELECT * FROM abc LIMIT 10 }} msg]
! 582: if {$msg eq "database disk image is malformed"} { set msg "out of memory" }
! 583: if {$rc} { error $msg }
! 584: set msg
! 585: } -cleanup {
! 586: set e [db eval {PRAGMA integrity_check}]
! 587: if {$e ne "ok"} {error $e}
! 588: }
! 589: }
! 590:
! 591: ifcapable compound {
! 592: do_malloc_test 24 -sqlprep {
! 593: CREATE TABLE t1(a, b, c)
! 594: } -sqlbody {
! 595: SELECT 1 FROM t1 UNION SELECT 2 FROM t1 ORDER BY 1
! 596: }
! 597: }
! 598:
! 599: ifcapable view&&trigger {
! 600: do_malloc_test 25 -sqlprep {
! 601: CREATE TABLE t1(a, b, c);
! 602: CREATE VIEW v1 AS SELECT * FROM t1;
! 603: CREATE TRIGGER v1t1 INSTEAD OF DELETE ON v1 BEGIN SELECT 1; END;
! 604: CREATE TRIGGER v1t2 INSTEAD OF INSERT ON v1 BEGIN SELECT 1; END;
! 605: CREATE TRIGGER v1t3 INSTEAD OF UPDATE ON v1 BEGIN SELECT 1; END;
! 606: } -sqlbody {
! 607: DELETE FROM v1 WHERE a = 1;
! 608: INSERT INTO v1 VALUES(1, 2, 3);
! 609: UPDATE v1 SET a = 1 WHERE b = 2;
! 610: }
! 611: }
! 612:
! 613: do_malloc_test 25 -sqlprep {
! 614: CREATE TABLE abc(a, b, c);
! 615: CREATE INDEX i1 ON abc(a, b);
! 616: INSERT INTO abc VALUES(1, 2, 3);
! 617: INSERT INTO abc VALUES(4, 5, 6);
! 618: } -tclbody {
! 619: # For each UPDATE executed, the cursor used for the SELECT statement
! 620: # must be "saved". Because the cursor is open on an index, this requires
! 621: # a malloc() to allocate space to save the index key. This test case is
! 622: # aimed at testing the response of the library to a failure in that
! 623: # particular malloc() call.
! 624: db eval {SELECT a FROM abc ORDER BY a} {
! 625: db eval {UPDATE abc SET b = b - 1 WHERE a = $a}
! 626: }
! 627: }
! 628:
! 629: # This test is designed to test a specific juncture in the sqlite code.
! 630: # The database set up by -sqlprep script contains a single table B-Tree
! 631: # of height 2. In the -tclbody script, the existing database connection
! 632: # is closed and a new one opened and used to insert a new row into the
! 633: # table B-Tree. By using a new connection, the outcome of a malloc()
! 634: # failure while seeking to the right-hand side of the B-Tree to insert
! 635: # a new record can be tested.
! 636: #
! 637: do_malloc_test 26 -sqlprep {
! 638: BEGIN;
! 639: CREATE TABLE t1(a, b);
! 640: INSERT INTO t1 VALUES(1, randomblob(210));
! 641: INSERT INTO t1 VALUES(1, randomblob(210));
! 642: INSERT INTO t1 VALUES(1, randomblob(210));
! 643: INSERT INTO t1 VALUES(1, randomblob(210));
! 644: INSERT INTO t1 VALUES(1, randomblob(210));
! 645: COMMIT;
! 646: } -tclbody {
! 647: db close
! 648: sqlite3 db test.db
! 649: db eval { INSERT INTO t1 VALUES(1, randomblob(210)) }
! 650: }
! 651:
! 652: # Test that no memory is leaked following a malloc() failure in
! 653: # sqlite3_initialize().
! 654: #
! 655: do_malloc_test 27 -tclprep {
! 656: db close
! 657: sqlite3_shutdown
! 658: } -tclbody {
! 659: set rc [sqlite3_initialize]
! 660: if {$rc == "SQLITE_NOMEM"} {
! 661: error "out of memory"
! 662: }
! 663: }
! 664: autoinstall_test_functions
! 665:
! 666: # Test that malloc failures that occur while processing INDEXED BY
! 667: # clauses are handled correctly.
! 668: do_malloc_test 28 -sqlprep {
! 669: CREATE TABLE t1(a, b);
! 670: CREATE INDEX i1 ON t1(a);
! 671: CREATE VIEW v1 AS SELECT * FROM t1 INDEXED BY i1 WHERE a = 10;
! 672: } -sqlbody {
! 673: SELECT * FROM t1 INDEXED BY i1 ORDER BY a;
! 674: SELECT * FROM v1;
! 675: }
! 676:
! 677: do_malloc_test 29 -sqlprep {
! 678: CREATE TABLE t1(a TEXT, b TEXT);
! 679: } -sqlbody {
! 680: INSERT INTO t1 VALUES(1, -234);
! 681: INSERT INTO t1 SELECT * FROM t1 UNION ALL SELECT * FROM t1;
! 682: }
! 683:
! 684: do_malloc_test 30 -tclprep {
! 685: db eval {
! 686: CREATE TABLE t1(x PRIMARY KEY);
! 687: INSERT INTO t1 VALUES(randstr(500,500));
! 688: INSERT INTO t1 VALUES(randstr(500,500));
! 689: INSERT INTO t1 VALUES(randstr(500,500));
! 690: }
! 691: db close
! 692: sqlite3 db test.db
! 693:
! 694: # The DELETE command in the following block moves the overflow pages that
! 695: # are part of the primary key index to the free-list. But it does not
! 696: # actually load the content of the pages. This leads to the peculiar
! 697: # situation where cache entries exist, but are not populated with data.
! 698: # They are populated next time they are requested by the b-tree layer.
! 699: #
! 700: db eval {
! 701: BEGIN;
! 702: DELETE FROM t1;
! 703: ROLLBACK;
! 704: }
! 705: } -sqlbody {
! 706: -- This statement requires the 'no-content' pages loaded by the DELETE
! 707: -- statement above. When requesting the pages, the content is loaded
! 708: -- from the database file. The point of this test case is to test handling
! 709: -- of malloc errors (including SQLITE_IOERR_NOMEM errors) when loading
! 710: -- the content.
! 711: SELECT * FROM t1 ORDER BY x;
! 712: }
! 713:
! 714: # After committing a transaction in persistent-journal mode, if a journal
! 715: # size limit is configured SQLite may attempt to truncate the journal file.
! 716: # This test verifies the libraries response to a malloc() failure during
! 717: # this operation.
! 718: #
! 719: do_malloc_test 31 -sqlprep {
! 720: PRAGMA journal_mode = persist;
! 721: PRAGMA journal_size_limit = 1024;
! 722: CREATE TABLE t1(a PRIMARY KEY, b);
! 723: } -sqlbody {
! 724: INSERT INTO t1 VALUES(1, 2);
! 725: }
! 726:
! 727: # When written, this test provoked an obscure change-counter bug.
! 728: #
! 729: # If, when running in exclusive mode, a malloc() failure occurs
! 730: # after the database file change-counter has been written but
! 731: # before the transaction has been committed, then the transaction
! 732: # is automatically rolled back. However, internally the
! 733: # Pager.changeCounterDone flag was being left set. This means
! 734: # that if the same connection attempts another transaction following
! 735: # the malloc failure and rollback, the change counter will not
! 736: # be updated. This could corrupt another processes cache.
! 737: #
! 738: do_malloc_test 32 -tclprep {
! 739: # Build a small database containing an indexed table.
! 740: #
! 741: db eval {
! 742: PRAGMA locking_mode = normal;
! 743: BEGIN;
! 744: CREATE TABLE t1(a PRIMARY KEY, b);
! 745: INSERT INTO t1 VALUES(1, 'one');
! 746: INSERT INTO t1 VALUES(2, 'two');
! 747: INSERT INTO t1 VALUES(3, 'three');
! 748: COMMIT;
! 749: PRAGMA locking_mode = exclusive;
! 750: }
! 751:
! 752: # Open a second database connection. Load the table (but not index)
! 753: # into the second connections pager cache.
! 754: #
! 755: sqlite3 db2 test.db
! 756: db2 eval {
! 757: PRAGMA locking_mode = normal;
! 758: SELECT b FROM t1;
! 759: }
! 760:
! 761: } -tclbody {
! 762: # Running in exclusive mode, perform a database transaction that
! 763: # modifies both the database table and index. For iterations where
! 764: # the malloc failure occurs after updating the change counter but
! 765: # before committing the transaction, this should result in the
! 766: # transaction being rolled back but the changeCounterDone flag
! 767: # left set.
! 768: #
! 769: db eval { UPDATE t1 SET a = a + 3 }
! 770: } -cleanup {
! 771:
! 772: # Perform another transaction using the first connection. Unlock
! 773: # the database after doing so. If this is one of the right iterations,
! 774: # then this should result in the database contents being updated but
! 775: # the change-counter left as it is.
! 776: #
! 777: db eval {
! 778: PRAGMA locking_mode = normal;
! 779: UPDATE t1 SET a = a + 3;
! 780: }
! 781:
! 782: # Now do an integrity check with the second connection. The second
! 783: # connection still has the database table in its cache. If this is
! 784: # one of the magic iterations and the change counter was not modified,
! 785: # then it won't realize that the cached data is out of date. Since
! 786: # the cached data won't match the up to date index data read from
! 787: # the database file, the integrity check should fail.
! 788: #
! 789: set zRepeat "transient"
! 790: if {$::iRepeat} {set zRepeat "persistent"}
! 791: do_test malloc-32.$zRepeat.${::n}.integrity {
! 792: execsql {PRAGMA integrity_check} db2
! 793: } {ok}
! 794: db2 close
! 795: }
! 796:
! 797: # The following two OOM tests verify that OOM handling works in the
! 798: # code used to optimize "SELECT count(*) FROM <tbl>".
! 799: #
! 800: do_malloc_test 33 -tclprep {
! 801: db eval { PRAGMA cache_size = 10 }
! 802: db transaction {
! 803: db eval { CREATE TABLE abc(a, b) }
! 804: for {set i 0} {$i<500} {incr i} {
! 805: db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))}
! 806: }
! 807: }
! 808: } -sqlbody {
! 809: SELECT count(*) FROM abc;
! 810: }
! 811: do_malloc_test 34 -tclprep {
! 812: db eval { PRAGMA cache_size = 10 }
! 813: db transaction {
! 814: db eval { CREATE TABLE abc(a PRIMARY KEY, b) }
! 815: for {set i 0} {$i<500} {incr i} {
! 816: db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))}
! 817: }
! 818: }
! 819: } -sqlbody {
! 820: SELECT count(*) FROM abc;
! 821: }
! 822:
! 823: proc f {args} { error "Quite a long error!" }
! 824: do_malloc_test 35 -tclprep {
! 825: db func f f
! 826: set ::STMT [sqlite3_prepare db "SELECT f()" -1 DUMMY]
! 827: sqlite3_step $::STMT
! 828: } -tclbody {
! 829: sqlite3_finalize $::STMT
! 830: } -cleanup {
! 831: # At one point an assert( !db->mallocFailed ) could fail in the following
! 832: # call to sqlite3_errmsg(). Because sqlite3_finalize() had failed to clear
! 833: # the flag before returning.
! 834: sqlite3_errmsg16 db
! 835: }
! 836:
! 837: do_malloc_test 36 -sqlprep {
! 838: CREATE TABLE t1(a, b);
! 839: INSERT INTO t1 VALUES(1, 2);
! 840: INSERT INTO t1 VALUES(3, 4);
! 841: } -sqlbody {
! 842: SELECT test_agg_errmsg16(), group_concat(a) FROM t1
! 843: }
! 844:
! 845: # At one point, if an OOM occured immediately after obtaining a shared lock
! 846: # on the database file, the file remained locked. This test case ensures
! 847: # that bug has been fixed.i
! 848: if {[db eval {PRAGMA locking_mode}]!="exclusive"} {
! 849: do_malloc_test 37 -tclprep {
! 850: sqlite3 db2 test.db
! 851: execsql {
! 852: CREATE TABLE t1(a, b);
! 853: INSERT INTO t1 VALUES(1, 2);
! 854: } db2
! 855: } -sqlbody {
! 856: SELECT * FROM t1;
! 857: } -cleanup {
! 858: # Try to write to the database using connection [db2]. If connection [db]
! 859: # has correctly released the shared lock, this write attempt should
! 860: # succeed. If [db] has not released the lock, this should hit an
! 861: # SQLITE_BUSY error.
! 862: do_test malloc-36.$zRepeat.${::n}.unlocked {
! 863: execsql {INSERT INTO t1 VALUES(3, 4)} db2
! 864: } {}
! 865: db2 close
! 866: }
! 867: catch { db2 close }
! 868: }
! 869:
! 870:
! 871: # Test that if an OOM error occurs, aux-data is still correctly destroyed.
! 872: # This test case was causing either a memory-leak or an assert() failure
! 873: # at one point, depending on the configuration.
! 874: #
! 875: do_malloc_test 39 -tclprep {
! 876: sqlite3 db test.db
! 877: } -sqlbody {
! 878: SELECT test_auxdata('abc', 'def');
! 879: } -cleanup {
! 880: db close
! 881: }
! 882:
! 883: # Ensure that no file descriptors were leaked.
! 884: do_test malloc-99.X {
! 885: catch {db close}
! 886: set sqlite_open_file_count
! 887: } {0}
! 888:
! 889: puts open-file-count=$sqlite_open_file_count
! 890: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>