Test cases and corrections to IO and malloc() error handling in incremental blob IO functions. (CVS 3915)
FossilOrigin-Name: 641e55284e1ba6070073c83ac6ed78ffb29f7e60
This commit is contained in:
parent
126afe6b59
commit
92d4d7a92e
23
manifest
23
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\sformatting\serrror\sin\sI/O\slogging.\s(CVS\s3914)
|
||||
D 2007-05-04T12:01:03
|
||||
C Test\scases\sand\scorrections\sto\sIO\sand\smalloc()\serror\shandling\sin\sincremental\sblob\sIO\sfunctions.\s(CVS\s3915)
|
||||
D 2007-05-04T12:05:56
|
||||
F Makefile.in 8cab54f7c9f5af8f22fd97ddf1ecfd1e1860de62
|
||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -59,7 +59,7 @@ F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3
|
||||
F src/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651
|
||||
F src/attach.c a16ada4a4654a0d126b8223ec9494ebb81bc5c3c
|
||||
F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
|
||||
F src/btree.c b88c9265e323b9a55290c39f9712e44050a6162c
|
||||
F src/btree.c a47fe8172eb62468f78a2fe4904d2e6b050038fb
|
||||
F src/btree.h 2c187d60cf76d74c2b4767294d6b5fa267037ff0
|
||||
F src/build.c 02e01ec7907c7d947ab3041fda0e81eaed05db42
|
||||
F src/callback.c 6414ed32d55859d0f65067aa5b88d2da27b3af9e
|
||||
@ -101,7 +101,7 @@ F src/sqlite.h.in a666300976897eced975b448f722a722b362c6b1
|
||||
F src/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890
|
||||
F src/sqliteInt.h 5a8c0221a4f11998f46aa76364a9559af8d7c1f7
|
||||
F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06
|
||||
F src/tclsqlite.c dde509871614d17f8ab5f3b4bc496b0af07280c7
|
||||
F src/tclsqlite.c 0906902b96e4b292ba98499dd380e22d3322f817
|
||||
F src/test1.c 29a39fdde51f4612082ecf3f5af54dac93766f87
|
||||
F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
|
||||
F src/test3.c 946ea9d1a8c928656e3c70f0a2fcb8e733a15e86
|
||||
@ -129,8 +129,8 @@ F src/vdbe.c a4abf744b5376372a9be30f02ab4b231f353cab1
|
||||
F src/vdbe.h 0025259af1939fb264a545816c69e4b5b8d52691
|
||||
F src/vdbeInt.h cb02cbbceddf3b40d49012e9f41576f17bcbec97
|
||||
F src/vdbeapi.c 37d793559390bec8a00c556f651f21b5f9e589af
|
||||
F src/vdbeaux.c 51acaab4275b5fddc7af5e7d1d2594044216ac46
|
||||
F src/vdbeblob.c ed2f9b46cc2de8de97d2a4a4ec466c5914d68333
|
||||
F src/vdbeaux.c 966d166f9d4079552c7cb48855afe8c1aa331556
|
||||
F src/vdbeblob.c 58b3f68f6bc18b58aeab3a31cff083cb4127292f
|
||||
F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
|
||||
F src/vdbemem.c ba98f8572ec4609846b368fa7580db178022f1bb
|
||||
F src/vtab.c 89a0d5f39c1beba65a77fdb4d507b831fc5e6baf
|
||||
@ -243,6 +243,7 @@ F test/func.test 6727c7729472ae52b5acd86e802f89aa350ba50f
|
||||
F test/hook.test 7e7645fd9a033f79cce8fdff151e32715e7ec50a
|
||||
F test/in.test 369cb2aa1eab02296b4ec470732fe8c131260b1d
|
||||
F test/incrblob.test 5cf5a7693c6cde33eef361d94c00c7bdbc30f563
|
||||
F test/incrblob_err.test 9f78c159279c992fa5ce49c06f50b680fc470520
|
||||
F test/incrvacuum.test 2173bc075c7b3b96ccf228d737dd4f5c29500dc4
|
||||
F test/incrvacuum_ioerr.test 0ebc382bcc2036ec58cf49cc5ffada45f75d907b
|
||||
F test/index.test e65df12bed94b2903ee89987115e1578687e9266
|
||||
@ -336,7 +337,7 @@ F test/table.test dbdfd06aef054ad5aed8e57a782137d57d5c5528
|
||||
F test/tableapi.test 036575a98dcce7c92e9f39056839bbad8a715412
|
||||
F test/tclsqlite.test 726c301d35a2c1f4181fb772a607f785dd9e284e
|
||||
F test/temptable.test c36f3e5a94507abb64f7ba23deeb4e1a8a8c3821
|
||||
F test/tester.tcl dcebe3c5bf15f3b4ba015b4b2237030c1e384941
|
||||
F test/tester.tcl 9382df472e0e86cbfddc44ab8c8cc02497bc9c8a
|
||||
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
|
||||
F test/thread2.test 6d7b30102d600f51b4055ee3a5a19228799049fb
|
||||
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
|
||||
@ -473,7 +474,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 2a178d0c7950c9d403c0bc43c2043de945fb24e0
|
||||
R 2c92eb8d26a624968d9428e7829962d0
|
||||
U drh
|
||||
Z f76b8b0273f8e85ef3b644774d94b3bf
|
||||
P 2d37687a08a7b6b3a7f77f55a7c2e29a1f8731a8
|
||||
R 631ed7d60317b63e0f0649096fcada2a
|
||||
U danielk1977
|
||||
Z dfc7741fad7b57c2866d720631f3b47d
|
||||
|
@ -1 +1 @@
|
||||
2d37687a08a7b6b3a7f77f55a7c2e29a1f8731a8
|
||||
641e55284e1ba6070073c83ac6ed78ffb29f7e60
|
65
src/btree.c
65
src/btree.c
@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.371 2007/05/04 08:32:14 danielk1977 Exp $
|
||||
** $Id: btree.c,v 1.372 2007/05/04 12:05:56 danielk1977 Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@ -656,6 +656,30 @@ static void unlockAllTables(Btree *p){
|
||||
|
||||
static void releasePage(MemPage *pPage); /* Forward reference */
|
||||
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
/*
|
||||
** Invalidate the overflow page-list cache for cursor pCur, if any.
|
||||
*/
|
||||
static void invalidateOverflowCache(BtCursor *pCur){
|
||||
sqliteFree(pCur->aOverflow);
|
||||
pCur->aOverflow = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Invalidate the overflow page-list cache for all cursors opened
|
||||
** on the shared btree structure pBt.
|
||||
*/
|
||||
static void invalidateAllOverflowCache(BtShared *pBt){
|
||||
BtCursor *p;
|
||||
for(p=pBt->pCursor; p; p=p->pNext){
|
||||
invalidateOverflowCache(p);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define invalidateOverflowCache(x)
|
||||
#define invalidateAllOverflowCache(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Save the current cursor position in the variables BtCursor.nKey
|
||||
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
|
||||
@ -695,12 +719,7 @@ static int saveCursorPosition(BtCursor *pCur){
|
||||
pCur->eState = CURSOR_REQUIRESEEK;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
/* Delete the cache of overflow page numbers. */
|
||||
sqliteFree(pCur->aOverflow);
|
||||
pCur->aOverflow = 0;
|
||||
#endif
|
||||
|
||||
invalidateOverflowCache(pCur);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2423,19 +2442,11 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin){
|
||||
*/
|
||||
int sqlite3BtreeIncrVacuum(Btree *p){
|
||||
BtShared *pBt = p->pBt;
|
||||
BtCursor *pCur;
|
||||
|
||||
assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
|
||||
if( !pBt->autoVacuum ){
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
||||
/* Delete the cache of overflow page numbers. */
|
||||
sqliteFree(pCur->aOverflow);
|
||||
pCur->aOverflow = 0;
|
||||
}
|
||||
#endif
|
||||
invalidateAllOverflowCache(pBt);
|
||||
return incrVacuumStep(pBt, 0);
|
||||
}
|
||||
|
||||
@ -2455,15 +2466,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
|
||||
int nRef = sqlite3PagerRefcount(pPager);
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
BtCursor *pCur;
|
||||
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
||||
/* Delete the cache of overflow page numbers. */
|
||||
sqliteFree(pCur->aOverflow);
|
||||
pCur->aOverflow = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
invalidateAllOverflowCache(pBt);
|
||||
assert(pBt->autoVacuum);
|
||||
if( !pBt->incrVacuum ){
|
||||
Pgno nFin = 0;
|
||||
@ -2959,9 +2962,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
||||
}
|
||||
releasePage(pCur->pPage);
|
||||
unlockBtreeIfUnused(pBt);
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
sqliteFree(pCur->aOverflow);
|
||||
#endif
|
||||
invalidateOverflowCache(pCur);
|
||||
sqliteFree(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -5801,18 +5802,12 @@ int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
|
||||
Pgno pgnoMove; /* Move a page here to make room for the root-page */
|
||||
MemPage *pPageMove; /* The page to move to. */
|
||||
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
/* Creating a new table may probably require moving an existing database
|
||||
** to make room for the new tables root page. In case this page turns
|
||||
** out to be an overflow page, delete all overflow page-map caches
|
||||
** held by open cursors.
|
||||
*/
|
||||
BtCursor *pCur;
|
||||
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
||||
sqliteFree(pCur->aOverflow);
|
||||
pCur->aOverflow = 0;
|
||||
}
|
||||
#endif
|
||||
invalidateAllOverflowCache(pBt);
|
||||
|
||||
/* Read the value of meta[3] from the database to determine where the
|
||||
** root page of the new table should go. meta[3] is the largest root-page
|
||||
|
@ -12,7 +12,7 @@
|
||||
** A TCL Interface to SQLite. Append this file to sqlite3.c and
|
||||
** compile the whole thing to build a TCL-enabled version of SQLite.
|
||||
**
|
||||
** $Id: tclsqlite.c,v 1.182 2007/05/03 16:31:26 danielk1977 Exp $
|
||||
** $Id: tclsqlite.c,v 1.183 2007/05/04 12:05:56 danielk1977 Exp $
|
||||
*/
|
||||
#include "tcl.h"
|
||||
#include <errno.h>
|
||||
@ -153,7 +153,8 @@ static void closeIncrblobChannels(SqliteDb *pDb){
|
||||
*/
|
||||
static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
|
||||
IncrblobChannel *p = (IncrblobChannel *)instanceData;
|
||||
sqlite3_blob_close(p->pBlob);
|
||||
int rc = sqlite3_blob_close(p->pBlob);
|
||||
sqlite3 *db = p->pDb->db;
|
||||
|
||||
/* Remove the channel from the SqliteDb.pIncrblob list. */
|
||||
if( p->pNext ){
|
||||
@ -166,7 +167,13 @@ static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
|
||||
p->pDb->pIncrblob = p->pNext;
|
||||
}
|
||||
|
||||
/* Free the IncrblobChannel structure */
|
||||
Tcl_Free((char *)p);
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
@ -464,6 +464,7 @@ static void freeP3(int p3type, void *p3){
|
||||
** Change N opcodes starting at addr to No-ops.
|
||||
*/
|
||||
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
|
||||
if( p && p->aOp ){
|
||||
VdbeOp *pOp = &p->aOp[addr];
|
||||
while( N-- ){
|
||||
freeP3(pOp->p3type, pOp->p3);
|
||||
@ -472,6 +473,7 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
|
||||
pOp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the value of the P3 operand for a specific instruction.
|
||||
|
@ -10,7 +10,7 @@
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** $Id: vdbeblob.c,v 1.5 2007/05/03 18:14:10 danielk1977 Exp $
|
||||
** $Id: vdbeblob.c,v 1.6 2007/05/04 12:05:56 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
@ -170,12 +170,14 @@ int sqlite3_blob_open(
|
||||
** and offset cache without causing any IO.
|
||||
*/
|
||||
sqlite3VdbeChangeP2(v, 5, pTab->nCol+1);
|
||||
if( !sqlite3MallocFailed() ){
|
||||
sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
rc = sqlite3SafetyOff(db);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
if( rc!=SQLITE_OK || sqlite3MallocFailed() ){
|
||||
goto blob_open_out;
|
||||
}
|
||||
|
||||
sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow);
|
||||
@ -222,11 +224,11 @@ int sqlite3_blob_open(
|
||||
}
|
||||
|
||||
blob_open_out:
|
||||
zErr[sizeof(zErr)-1] = '\0';
|
||||
if( rc!=SQLITE_OK || sqlite3MallocFailed() ){
|
||||
sqlite3_finalize((sqlite3_stmt *)v);
|
||||
}
|
||||
zErr[sizeof(zErr)-1] = '\0';
|
||||
sqlite3Error(db, rc, zErr);
|
||||
sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr));
|
||||
return sqlite3ApiExit(db, rc);
|
||||
}
|
||||
|
||||
@ -235,31 +237,37 @@ blob_open_out:
|
||||
*/
|
||||
int sqlite3_blob_close(sqlite3_blob *pBlob){
|
||||
Incrblob *p = (Incrblob *)pBlob;
|
||||
sqlite3_finalize(p->pStmt);
|
||||
sqlite3_stmt *pStmt = p->pStmt;
|
||||
sqliteFree(p);
|
||||
return SQLITE_OK;
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read data from a blob handle.
|
||||
*/
|
||||
int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
|
||||
int rc = SQLITE_ERROR;
|
||||
Incrblob *p = (Incrblob *)pBlob;
|
||||
if( (iOffset+n)>p->nByte ){
|
||||
return SQLITE_ERROR;
|
||||
Vdbe *v = (Vdbe *)(p->pStmt);
|
||||
if( (iOffset+n)<=p->nByte ){
|
||||
rc = sqlite3BtreeData(p->pCsr, iOffset+p->iOffset, n, z);
|
||||
}
|
||||
return sqlite3BtreeData(p->pCsr, iOffset+p->iOffset, n, z);
|
||||
v->rc = rc;
|
||||
return sqlite3ApiExit(v->db, v->rc);
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data to a blob handle.
|
||||
*/
|
||||
int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
|
||||
int rc = SQLITE_ERROR;
|
||||
Incrblob *p = (Incrblob *)pBlob;
|
||||
if( (iOffset+n)>p->nByte ){
|
||||
return SQLITE_ERROR;
|
||||
Vdbe *v = (Vdbe *)(p->pStmt);
|
||||
if( (iOffset+n)<=p->nByte ){
|
||||
rc = sqlite3BtreePutData(p->pCsr, iOffset+p->iOffset, n, z);
|
||||
}
|
||||
return sqlite3BtreePutData(p->pCsr, iOffset+p->iOffset, n, z);
|
||||
v->rc = rc;
|
||||
return sqlite3ApiExit(v->db, v->rc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
192
test/incrblob_err.test
Normal file
192
test/incrblob_err.test
Normal file
@ -0,0 +1,192 @@
|
||||
# 2007 May 1
|
||||
#
|
||||
# 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: incrblob_err.test,v 1.1 2007/05/04 12:05:56 danielk1977 Exp $
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Usage: do_malloc_test <test number> <options...>
|
||||
#
|
||||
# The first argument, <test number>, is an integer used to name the
|
||||
# tests executed by this proc. Options are as follows:
|
||||
#
|
||||
# -tclprep TCL script to run to prepare test.
|
||||
# -sqlprep SQL script to run to prepare test.
|
||||
# -tclbody TCL script to run with malloc failure simulation.
|
||||
# -sqlbody TCL script to run with malloc failure simulation.
|
||||
# -cleanup TCL script to run after the test.
|
||||
#
|
||||
# This command runs a series of tests to verify SQLite's ability
|
||||
# to handle an out-of-memory condition gracefully. It is assumed
|
||||
# that if this condition occurs a malloc() call will return a
|
||||
# NULL pointer. Linux, for example, doesn't do that by default. See
|
||||
# the "BUGS" section of malloc(3).
|
||||
#
|
||||
# Each iteration of a loop, the TCL commands in any argument passed
|
||||
# to the -tclbody switch, followed by the SQL commands in any argument
|
||||
# passed to the -sqlbody switch are executed. Each iteration the
|
||||
# Nth call to sqliteMalloc() is made to fail, where N is increased
|
||||
# each time the loop runs starting from 1. When all commands execute
|
||||
# successfully, the loop ends.
|
||||
#
|
||||
proc do_malloc_test {tn args} {
|
||||
array unset ::mallocopts
|
||||
array set ::mallocopts $args
|
||||
|
||||
set ::go 1
|
||||
for {set ::n 1} {$::go && $::n < 50000} {incr ::n} {
|
||||
do_test incrblob_err-$tn.$::n {
|
||||
|
||||
# Remove all traces of database files test.db and test2.db from the files
|
||||
# system. Then open (empty database) "test.db" with the handle [db].
|
||||
#
|
||||
sqlite_malloc_fail 0
|
||||
catch {db close}
|
||||
catch {file delete -force test.db}
|
||||
catch {file delete -force test.db-journal}
|
||||
catch {file delete -force test2.db}
|
||||
catch {file delete -force test2.db-journal}
|
||||
catch {sqlite3 db test.db}
|
||||
set ::DB [sqlite3_connection_pointer db]
|
||||
|
||||
# Execute any -tclprep and -sqlprep scripts.
|
||||
#
|
||||
if {[info exists ::mallocopts(-tclprep)]} {
|
||||
eval $::mallocopts(-tclprep)
|
||||
}
|
||||
if {[info exists ::mallocopts(-sqlprep)]} {
|
||||
execsql $::mallocopts(-sqlprep)
|
||||
}
|
||||
|
||||
# Now set the ${::n}th malloc() to fail and execute the -tclbody and
|
||||
# -sqlbody scripts.
|
||||
#
|
||||
sqlite_malloc_fail $::n
|
||||
set ::mallocbody {}
|
||||
if {[info exists ::mallocopts(-tclbody)]} {
|
||||
append ::mallocbody "$::mallocopts(-tclbody)\n"
|
||||
}
|
||||
if {[info exists ::mallocopts(-sqlbody)]} {
|
||||
append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
|
||||
}
|
||||
set v [catch $::mallocbody msg]
|
||||
|
||||
# If the test fails (if $v!=0) and the database connection actually
|
||||
# exists, make sure the failure code is SQLITE_NOMEM.
|
||||
if {$v && [info command db]=="db" && [info exists ::mallocopts(-sqlbody)]
|
||||
&& [db errorcode]!=7} {
|
||||
set v 999
|
||||
}
|
||||
|
||||
set leftover [lindex [sqlite_malloc_stat] 2]
|
||||
if {$leftover>0} {
|
||||
if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
|
||||
set ::go 0
|
||||
if {$v} {
|
||||
puts "\nError message returned: $msg"
|
||||
} else {
|
||||
set v {1 1}
|
||||
}
|
||||
} else {
|
||||
set v2 [expr {$msg=="" || $msg=="out of memory"}]
|
||||
if {!$v2} {puts "\nError message returned: $msg"}
|
||||
lappend v $v2
|
||||
}
|
||||
} {1 1}
|
||||
|
||||
if {[info exists ::mallocopts(-cleanup)]} {
|
||||
catch [list uplevel #0 $::mallocopts(-cleanup)] msg
|
||||
}
|
||||
}
|
||||
unset ::mallocopts
|
||||
}
|
||||
|
||||
set ::fd [open [info script]]
|
||||
set ::data [read $::fd]
|
||||
close $::fd
|
||||
|
||||
do_malloc_test 1 -tclprep {
|
||||
set bytes [file size [info script]]
|
||||
execsql {
|
||||
CREATE TABLE blobs(k, v BLOB);
|
||||
INSERT INTO blobs VALUES(1, zeroblob($::bytes));
|
||||
}
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
set rc [catch {puts -nonewline $::blob $::data}]
|
||||
if {$rc} { error "out of memory" }
|
||||
}
|
||||
|
||||
do_malloc_test 2 -tclprep {
|
||||
execsql {
|
||||
CREATE TABLE blobs(k, v BLOB);
|
||||
INSERT INTO blobs VALUES(1, $::data);
|
||||
}
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
set rc [catch {set ::r [read $::blob]}]
|
||||
if {$rc} {
|
||||
error "out of memory"
|
||||
} elseif {$::r ne $::data} {
|
||||
error "Bad data read..."
|
||||
}
|
||||
}
|
||||
|
||||
do_malloc_test 3 -tclprep {
|
||||
execsql {
|
||||
CREATE TABLE blobs(k, v BLOB);
|
||||
INSERT INTO blobs VALUES(1, $::data);
|
||||
}
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
set rc [catch {set ::r [read $::blob]}]
|
||||
if {$rc} {
|
||||
error "out of memory"
|
||||
} elseif {$::r ne $::data} {
|
||||
error "Bad data read..."
|
||||
}
|
||||
set rc [catch {close $::blob}]
|
||||
if {$rc} {
|
||||
error "out of memory"
|
||||
}
|
||||
}
|
||||
sqlite_malloc_fail 0
|
||||
|
||||
do_ioerr_test incrblob_err-4 -cksum 1 -sqlprep {
|
||||
CREATE TABLE blobs(k, v BLOB);
|
||||
INSERT INTO blobs VALUES(1, $::data);
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
read $::blob
|
||||
}
|
||||
|
||||
do_ioerr_test incrblob_err-5 -cksum 1 -sqlprep {
|
||||
CREATE TABLE blobs(k, v BLOB);
|
||||
INSERT INTO blobs VALUES(1, zeroblob(length(CAST($::data AS BLOB))));
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
puts -nonewline $::blob $::data
|
||||
close $::blob
|
||||
}
|
||||
|
||||
do_ioerr_test incrblob_err-6 -cksum 1 -sqlprep {
|
||||
CREATE TABLE blobs(k, v BLOB);
|
||||
INSERT INTO blobs VALUES(1, $::data || $::data || $::data);
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
seek $::blob -20 end
|
||||
puts -nonewline $::blob "12345678900987654321"
|
||||
close $::blob
|
||||
}
|
||||
|
||||
finish_test
|
@ -11,7 +11,7 @@
|
||||
# This file implements some common TCL routines used for regression
|
||||
# testing the SQLite library
|
||||
#
|
||||
# $Id: tester.tcl,v 1.80 2007/04/28 15:47:45 danielk1977 Exp $
|
||||
# $Id: tester.tcl,v 1.81 2007/05/04 12:05:56 danielk1977 Exp $
|
||||
|
||||
# Make sure tclsqlite3 was compiled correctly. Abort now with an
|
||||
# error message if not.
|
||||
@ -480,6 +480,7 @@ set ::TN $n
|
||||
# 1. We never hit the IO error and the SQL returned OK
|
||||
# 2. An IO error was hit and the SQL failed
|
||||
#
|
||||
#puts "$s $r $::go - $msg"
|
||||
expr { ($s && !$r && !$::go) || (!$s && $r && $::go) }
|
||||
} {1}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user