Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fixed several more crashes due to corrupt db files. Added corruptC.test to soak.test. (CVS 5905) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9b7a52e952c81e50611e04d2d79003b0 |
User & Date: | shane 2008-11-13 18:29:51.000 |
Context
2008-11-13
| ||
19:12 | Fix a couple of memory leaks that may follow malloc failures. (CVS 5906) (check-in: 4cf8a8e1bf user: danielk1977 tags: trunk) | |
18:29 | Fixed several more crashes due to corrupt db files. Added corruptC.test to soak.test. (CVS 5905) (check-in: 9b7a52e952 user: shane tags: trunk) | |
18:20 | Added support for -DSQLITE_NO_SYNC to os_win.c. (CVS 5904) (check-in: 2649337937 user: shane tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.536 2008/11/13 18:29:51 shane Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" |
︙ | ︙ | |||
730 731 732 733 734 735 736 | cbrk = get2byte(&data[hdr+5]); memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk); cbrk = usableSize; for(i=0; i<nCell; i++){ u8 *pAddr; /* The i-th cell pointer */ pAddr = &data[cellOffset + i*2]; pc = get2byte(pAddr); | | | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 | cbrk = get2byte(&data[hdr+5]); memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk); cbrk = usableSize; for(i=0; i<nCell; i++){ u8 *pAddr; /* The i-th cell pointer */ pAddr = &data[cellOffset + i*2]; pc = get2byte(pAddr); if( pc>=usableSize ){ return SQLITE_CORRUPT_BKPT; } size = cellSizePtr(pPage, &temp[pc]); cbrk -= size; if( cbrk<cellOffset+2*nCell || pc+size>usableSize ){ return SQLITE_CORRUPT_BKPT; } |
︙ | ︙ | |||
831 832 833 834 835 836 837 | ** Return a section of the pPage->aData to the freelist. ** The first byte of the new free block is pPage->aDisk[start] ** and the size of the block is "size" bytes. ** ** Most of the effort here is involved in coalesing adjacent ** free blocks into a single big free block. */ | | | 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | ** Return a section of the pPage->aData to the freelist. ** The first byte of the new free block is pPage->aDisk[start] ** and the size of the block is "size" bytes. ** ** Most of the effort here is involved in coalesing adjacent ** free blocks into a single big free block. */ static int freeSpace(MemPage *pPage, int start, int size){ int addr, pbegin, hdr; unsigned char *data = pPage->aData; assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); assert( (start + size)<=pPage->pBt->usableSize ); |
︙ | ︙ | |||
853 854 855 856 857 858 859 | #endif /* Add the space back into the linked list of freeblocks */ hdr = pPage->hdrOffset; addr = hdr + 1; while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){ assert( pbegin<=pPage->pBt->usableSize-4 ); | | > > | > > | > > > | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 | #endif /* Add the space back into the linked list of freeblocks */ hdr = pPage->hdrOffset; addr = hdr + 1; while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){ assert( pbegin<=pPage->pBt->usableSize-4 ); if( pbegin<=addr ) { return SQLITE_CORRUPT_BKPT; } addr = pbegin; } if ( pbegin>pPage->pBt->usableSize-4 ) { return SQLITE_CORRUPT_BKPT; } assert( pbegin>addr || pbegin==0 ); put2byte(&data[addr], start); put2byte(&data[start], pbegin); put2byte(&data[start+2], size); pPage->nFree += size; /* Coalesce adjacent free blocks */ addr = pPage->hdrOffset + 1; while( (pbegin = get2byte(&data[addr]))>0 ){ int pnext, psize; assert( pbegin>addr ); assert( pbegin<=pPage->pBt->usableSize-4 ); pnext = get2byte(&data[pbegin]); psize = get2byte(&data[pbegin+2]); if( pbegin + psize + 3 >= pnext && pnext>0 ){ int frag = pnext - (pbegin+psize); if( (frag<0) || (frag>data[pPage->hdrOffset+7]) ){ return SQLITE_CORRUPT_BKPT; } data[pPage->hdrOffset+7] -= frag; put2byte(&data[pbegin], get2byte(&data[pnext])); put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin); }else{ addr = pbegin; } } /* If the cell content area begins with a freeblock, remove it. */ if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ int top; pbegin = get2byte(&data[hdr+1]); memcpy(&data[hdr+1], &data[pbegin], 2); top = get2byte(&data[hdr+5]); put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2])); } return SQLITE_OK; } /* ** Decode the flags byte (the first byte of the header) for a page ** and initialize fields of the MemPage structure accordingly. ** ** Only the following combinations are supported. Anything different |
︙ | ︙ | |||
4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 | ** "sz" must be the number of bytes in the cell. */ static int dropCell(MemPage *pPage, int idx, int sz){ int i; /* Loop counter */ int pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ assert( idx>=0 && idx<pPage->nCell ); assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); data = pPage->aData; ptr = &data[pPage->cellOffset + 2*idx]; pc = get2byte(ptr); | > | | > > > | 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 | ** "sz" must be the number of bytes in the cell. */ static int dropCell(MemPage *pPage, int idx, int sz){ int i; /* Loop counter */ int pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ int rc; /* The return code */ assert( idx>=0 && idx<pPage->nCell ); assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); data = pPage->aData; ptr = &data[pPage->cellOffset + 2*idx]; pc = get2byte(ptr); if ( (pc<pPage->hdrOffset+6+(pPage->leaf?0:4)) || (pc+sz>pPage->pBt->usableSize) ) { return SQLITE_CORRUPT_BKPT; } rc = freeSpace(pPage, pc, sz); if( rc!=SQLITE_OK ){ return rc; } for(i=idx+1; i<pPage->nCell; i++, ptr+=2){ ptr[0] = ptr[2]; ptr[1] = ptr[3]; } pPage->nCell--; put2byte(&data[pPage->hdrOffset+3], pPage->nCell); pPage->nFree += 2; |
︙ | ︙ | |||
6047 6048 6049 6050 6051 6052 6053 | || !pCur->pagesShuffled ); } } sqlite3BtreeReleaseTempCursor(&leafCur); }else{ TRACE(("DELETE: table=%d delete from leaf %d\n", pCur->pgnoRoot, pPage->pgno)); | | > | > | 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 | || !pCur->pagesShuffled ); } } sqlite3BtreeReleaseTempCursor(&leafCur); }else{ TRACE(("DELETE: table=%d delete from leaf %d\n", pCur->pgnoRoot, pPage->pgno)); rc = dropCell(pPage, idx, cellSizePtr(pPage, pCell)); if( rc==SQLITE_OK ){ rc = balance(pCur, 0); } } if( rc==SQLITE_OK ){ moveToRoot(pCur); } return rc; } |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.502 2008/11/13 18:29:51 shane Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
666 667 668 669 670 671 672 | Token *pName2, /* The "yyy" in the name "xxx.yyy" */ Token **pUnqual /* Write the unqualified object name here */ ){ int iDb; /* Database holding the object */ sqlite3 *db = pParse->db; if( pName2 && pName2->n>0 ){ | | > > > > | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 | Token *pName2, /* The "yyy" in the name "xxx.yyy" */ Token **pUnqual /* Write the unqualified object name here */ ){ int iDb; /* Database holding the object */ sqlite3 *db = pParse->db; if( pName2 && pName2->n>0 ){ if( db->init.busy ) { sqlite3ErrorMsg(pParse, "corrupt database"); pParse->nErr++; return -1; } *pUnqual = pName2; iDb = sqlite3FindDb(db, pName1); if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); pParse->nErr++; return -1; } |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.787 2008/11/13 18:29:51 shane Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor |
︙ | ︙ | |||
2694 2695 2696 2697 2698 2699 2700 | } if( pOp->p5 ){ assert( p2>0 ); assert( p2<=p->nMem ); pIn2 = &p->aMem[p2]; sqlite3VdbeMemIntegerify(pIn2); p2 = pIn2->u.i; | | > > > | 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 | } if( pOp->p5 ){ assert( p2>0 ); assert( p2<=p->nMem ); pIn2 = &p->aMem[p2]; sqlite3VdbeMemIntegerify(pIn2); p2 = pIn2->u.i; if( p2<2 ) { rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } } assert( i>=0 ); pCur = allocateCursor(p, i, &pOp[-1], iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor); if( pOp->p4type==P4_KEYINFO ){ |
︙ | ︙ |
Changes to test/corruptC.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # This file implements regression tests for SQLite library. # # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. It creates a base # data base file, then tests that single byte corruptions in # increasingly larger quantities are handled gracefully. # | | < < < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # This file implements regression tests for SQLite library. # # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. It creates a base # data base file, then tests that single byte corruptions in # increasingly larger quantities are handled gracefully. # # $Id: corruptC.test,v 1.9 2008/11/13 18:29:51 shane Exp $ catch {file delete -force test.db test.db-journal test.bu} set testdir [file dirname $argv0] source $testdir/tester.tcl # Construct a compact, dense database for testing. # do_test corruptC-1.1 { execsql { PRAGMA auto_vacuum = 0; BEGIN; CREATE TABLE t1(x,y); |
︙ | ︙ | |||
48 49 50 51 52 53 54 | ifcapable {integrityck} { integrity_check corruptC-1.2 } # Generate random integer # proc random {range} { | | < < < < < < | > > > > > > > > > > > > | > | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | ifcapable {integrityck} { integrity_check corruptC-1.2 } # Generate random integer # proc random {range} { return [expr {round(rand()*$range)}] } # Copy file $from into $to # proc copy_file {from to} { file copy -force $from $to } # Setup for the tests. Make a backup copy of the good database in test.bu. # db close copy_file test.db test.bu sqlite3 db test.db set fsize [file size test.db] # Set a quasi-random random seed. if {[info exists SOAKTEST]} { # If we are doing SOAK tests, we want a different # random seed for each run. Ideally we would like # to use [clock clicks] or something like that here. set qseed [file mtime test.db] } else { # If we are not doing soak tests, # make it repeatable. set qseed 0 } expr srand($qseed) # # First test some specific corruption tests found from earlier runs # with specific seeds. # # test that a corrupt content offset size is handled (seed 5577) do_test corruptC-2.1 { db close copy_file test.bu test.db |
︙ | ︙ | |||
161 162 163 164 165 166 167 168 | # insert corrupt byte(s) hexio_write test.db 619 [format %02x 0xe2] hexio_write test.db 3150 [format %02x 0xa8] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} } {1 {database disk image is malformed}} | > > > > | > > | > > > | > > > > | > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | | | | | | | | > > > > > > > > > > > > | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | # insert corrupt byte(s) hexio_write test.db 619 [format %02x 0xe2] hexio_write test.db 3150 [format %02x 0xa8] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 178692) do_test corruptC-2.7 { db close copy_file test.bu test.db # insert corrupt byte(s) hexio_write test.db 3074 [format %02x 0xa0] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 179069) do_test corruptC-2.8 { db close copy_file test.bu test.db # insert corrupt byte(s) hexio_write test.db 1393 [format %02x 0x7d] hexio_write test.db 84 [format %02x 0x19] hexio_write test.db 3287 [format %02x 0x3b] hexio_write test.db 2564 [format %02x 0xed] hexio_write test.db 2139 [format %02x 0x55] sqlite3 db test.db catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 170434) do_test corruptC-2.9 { db close copy_file test.bu test.db # insert corrupt byte(s) hexio_write test.db 2095 [format %02x 0xd6] sqlite3 db test.db catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 186504) do_test corruptC-2.10 { db close copy_file test.bu test.db # insert corrupt byte(s) hexio_write test.db 3130 [format %02x 0x02] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 1589) do_test corruptC-2.11 { db close copy_file test.bu test.db # insert corrupt byte(s) hexio_write test.db 55 [format %02x 0xa7] sqlite3 db test.db catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 14166) do_test corruptC-2.12 { db close copy_file test.bu test.db # insert corrupt byte(s) hexio_write test.db 974 [format %02x 0x2e] sqlite3 db test.db catchsql {SELECT count(*) FROM sqlite_master;} } {1 {malformed database schema (t1i1) - corrupt database}} # corruption (seed 218803) do_test corruptC-2.13 { db close copy_file test.bu test.db # insert corrupt byte(s) hexio_write test.db 102 [format %02x 0x12] sqlite3 db test.db catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;} } {1 {database disk image is malformed}} # # now test for a series of quasi-random seeds for {set tn 0} {$tn<1024} {incr tn 1} { # setup for test db close copy_file test.bu test.db sqlite3 db test.db # Seek to a random location in the file, and write a random single byte # value. Then do various operations on the file to make sure that # the database engine can handle the corruption gracefully. # set last 0 for {set i 1} {$i<=512 && !$last} {incr i 1} { # insert random byte at random location db close set roffset [random $fsize] set rbyte [format %02x [random 255]] # You can uncomment the following to have it trace # exactly how it's corrupting the file. This is # useful for generating the "seed specific" tests # above. # set rline "$roffset $rbyte" # puts stdout $rline hexio_write test.db $roffset $rbyte sqlite3 db test.db # do a few random operations to make sure that if # they error, they error gracefully instead of crashing. do_test corruptC-3.$tn.($qseed).$i.1 { catchsql {SELECT count(*) FROM sqlite_master} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.2 { catchsql {SELECT count(*) FROM t1} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.3 { catchsql {SELECT count(*) FROM t1 WHERE x>13} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.4 { catchsql {SELECT count(*) FROM t2} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.5 { catchsql {SELECT count(*) FROM t2 WHERE x<13} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.6 { catchsql {BEGIN; UPDATE t1 SET y=1; ROLLBACK;} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.7 { catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.8 { catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.9 { catchsql {BEGIN; DELETE FROM t2 WHERE x<13; ROLLBACK;} set x {} } {} do_test corruptC-3.$tn.($qseed).$i.10 { catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;} set x {} } {} # check the integrity of the database. # once the corruption is detected, we can stop. ifcapable {integrityck} { set res [ catchsql {PRAGMA integrity_check} ] set ans [lindex $res 1] |
︙ | ︙ | |||
239 240 241 242 243 244 245 | } } # Check that no page references were leaked. # TBD: need to figure out why this doesn't work # work with ROLLBACKs... if {0} { | | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | } } # Check that no page references were leaked. # TBD: need to figure out why this doesn't work # work with ROLLBACKs... if {0} { do_test corruptC-3.$tn.($qseed).$i.11 { set bt [btree_from_db db] db_enter db array set stats [btree_pager_stats $bt] db_leave db set stats(ref) } {0} } |
︙ | ︙ |
Changes to test/soak.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2007 May 24 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file is the driver for the "soak" tests. It is a peer of the # quick.test and all.test scripts. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2007 May 24 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file is the driver for the "soak" tests. It is a peer of the # quick.test and all.test scripts. # # $Id: soak.test,v 1.4 2008/11/13 18:29:51 shane Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl rename finish_test really_finish_test proc finish_test {} {} # By default, guarantee that the tests will run for at least 1 hour. |
︙ | ︙ | |||
43 44 45 46 47 48 49 | # # The general principle is to run those SQLite tests that use # pseudo-random data in some way over and over again for a very # long time. The number of tests run depends on the value of # global variable $TIMEOUT - tests are run for at least $TIMEOUT # seconds. # | | | < | > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | # # The general principle is to run those SQLite tests that use # pseudo-random data in some way over and over again for a very # long time. The number of tests run depends on the value of # global variable $TIMEOUT - tests are run for at least $TIMEOUT # seconds. # # fuzz.test (pseudo-random SQL statements) # trans.test (pseudo-random changes to a database followed by rollbacks) # fuzz_malloc.test # corruptC.test (pseudo-random corruption to a database) # # Many database changes maintaining some kind of invariant. # Storing checksums etc. # # List of test files that are run by this file. # set SOAKTESTS { fuzz.test fuzz_malloc.test trans.test corruptC.test } set ISQUICK 1 set soak_starttime [clock seconds] set soak_finishtime [expr {$soak_starttime + $TIMEOUT}] |
︙ | ︙ |