1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-01 06:27:03 +03:00

Tests to improve coverage of vdbeaux.c. (CVS 2201)

FossilOrigin-Name: 2b3e21ce2e8126ec2851751546094c3a2c831942
This commit is contained in:
danielk1977
2005-01-12 09:10:39 +00:00
parent b5402fbf05
commit 8b60e0f142
7 changed files with 198 additions and 143 deletions

View File

@ -1,5 +1,5 @@
C Tests\sto\simprove\scoverage\sof\svdbemem.c.\s(CVS\s2200) C Tests\sto\simprove\scoverage\sof\svdbeaux.c.\s(CVS\s2201)
D 2005-01-12T07:15:05 D 2005-01-12T09:10:40
F Makefile.in ecf441ac5ca1ccfc8748a8a9537706e69893dfa4 F Makefile.in ecf441ac5ca1ccfc8748a8a9537706e69893dfa4
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@ -76,11 +76,11 @@ F src/update.c 0979397c41ac29c54fe0cc687a356d8629a633af
F src/utf.c 9bece2c7b94d9002ab1bb900a7658c6f826b0f74 F src/utf.c 9bece2c7b94d9002ab1bb900a7658c6f826b0f74
F src/util.c 4511559caf83e70a036deb5c56f10ddf35a688fb F src/util.c 4511559caf83e70a036deb5c56f10ddf35a688fb
F src/vacuum.c 1a9db113a027461daaf44724c71dd1ebbd064203 F src/vacuum.c 1a9db113a027461daaf44724c71dd1ebbd064203
F src/vdbe.c b8e619fbaa59be3e537804469d8cedd4a98d3c2e F src/vdbe.c a89bb4eefa60226ddfdf8e708ea9352c0a124da3
F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
F src/vdbeInt.h 0f74561e629af86172de7cdf0ecaea014c51696c F src/vdbeInt.h f2b5f54d9881bbc89fff02d95f3f825ade68bce2
F src/vdbeapi.c 0cf3bdc1072616bedc8eec7fc22e3f5a169d33fd F src/vdbeapi.c 0cf3bdc1072616bedc8eec7fc22e3f5a169d33fd
F src/vdbeaux.c 60c24559b458d4da368694c0d322326b22edffd1 F src/vdbeaux.c 0675db9f7f801b36e2e71504f5380feeadba56bc
F src/vdbemem.c 5d9fd8de5d4f5d1f3446c9a90a7b3f8c38557821 F src/vdbemem.c 5d9fd8de5d4f5d1f3446c9a90a7b3f8c38557821
F src/where.c 3a0d08505e298242f6f151f019a05129a4f8704c F src/where.c 3a0d08505e298242f6f151f019a05129a4f8704c
F tclinstaller.tcl 36478c3bbfc5b93ceac42d94e3c736937b808432 F tclinstaller.tcl 36478c3bbfc5b93ceac42d94e3c736937b808432
@ -138,7 +138,7 @@ F test/insert.test 56f9c20c9adc8d707490c4ffa5d4daa94826ea03
F test/insert2.test 0bb50ff999e35a21549d8ee5dc44db8ac24d31a7 F test/insert2.test 0bb50ff999e35a21549d8ee5dc44db8ac24d31a7
F test/interrupt.test 5b4d8389e6cf2d01b94f87cfd02d9df1073bfb2d F test/interrupt.test 5b4d8389e6cf2d01b94f87cfd02d9df1073bfb2d
F test/intpkey.test b57cf5236fde1bd8cbc1388fa0c91908f6fd9194 F test/intpkey.test b57cf5236fde1bd8cbc1388fa0c91908f6fd9194
F test/ioerr.test 01ac547c4a6fc53fcd9fe7ecc9698ab5d827093a F test/ioerr.test 0563e3eace01d94661899a90e5888b7817fb57e0
F test/join.test ea8c77b9fbc377fe553cdb5ce5f1bd72021dca5d F test/join.test ea8c77b9fbc377fe553cdb5ce5f1bd72021dca5d
F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8 F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
F test/join3.test 67dc0d7c8dab3fff25796d0f3c3fd9c999aeded3 F test/join3.test 67dc0d7c8dab3fff25796d0f3c3fd9c999aeded3
@ -150,7 +150,7 @@ F test/lock.test 32fe28e5030f25f23bcf6beef440675b0d848413
F test/lock2.test 59c3dd7d9b24d1bf7ec91b2d1541c37e97939d5f F test/lock2.test 59c3dd7d9b24d1bf7ec91b2d1541c37e97939d5f
F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9 F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
F test/main.test a60a1d234b5f5784097973bd395514ca56003ef1 F test/main.test a60a1d234b5f5784097973bd395514ca56003ef1
F test/malloc.test 79c5e0676a8346884b3197c811f2eac60b0521cc F test/malloc.test c3985c0a5a2f28dbfdb68a4e07886f9090feeda1
F test/memdb.test 532aac7128a3da494cddc4461d76c6e3988f771b F test/memdb.test 532aac7128a3da494cddc4461d76c6e3988f771b
F test/memleak.test f1fa233f8295dd1d955a00d5e5ee857850f27f29 F test/memleak.test f1fa233f8295dd1d955a00d5e5ee857850f27f29
F test/minmax.test e7048476940df0af11d0f2cf687572f557cd0b29 F test/minmax.test e7048476940df0af11d0f2cf687572f557cd0b29
@ -268,7 +268,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746 F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746
P 50f1e229652610b386745bb39fed45549cc74aa7 P 319bb4a9064deb062a888fdc31067619c9b749bb
R bf4878fa2c84d42762e103055cb55fd1 R eca04ac646dc0adf8b62dade6edd7859
U danielk1977 U danielk1977
Z 3c12901d279d54cf5f64fafd62ec59a5 Z bac0bd5515f392b48e8053527f28ff2a

View File

@ -1 +1 @@
319bb4a9064deb062a888fdc31067619c9b749bb 2b3e21ce2e8126ec2851751546094c3a2c831942

View File

@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** commenting and indentation practices when changing or adding code.
** **
** $Id: vdbe.c,v 1.441 2005/01/12 07:15:06 danielk1977 Exp $ ** $Id: vdbe.c,v 1.442 2005/01/12 09:10:40 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "os.h" #include "os.h"
@ -477,9 +477,9 @@ int sqlite3VdbeExec(
#endif #endif
pOp = &p->aOp[pc]; pOp = &p->aOp[pc];
/* Only allow tracing if NDEBUG is not defined. /* Only allow tracing if SQLITE_DEBUG is defined.
*/ */
#ifndef NDEBUG #ifdef SQLITE_DEBUG
if( p->trace ){ if( p->trace ){
if( pc==0 ){ if( pc==0 ){
printf("VDBE Execution Trace:\n"); printf("VDBE Execution Trace:\n");
@ -487,8 +487,6 @@ int sqlite3VdbeExec(
} }
sqlite3VdbePrintOp(p->trace, pc, pOp); sqlite3VdbePrintOp(p->trace, pc, pOp);
} }
#endif
#ifdef SQLITE_TEST
if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){ if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){
sqlite3VdbePrintSql(p); sqlite3VdbePrintSql(p);
} }

View File

@ -362,10 +362,12 @@ int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *);
void sqlite3VdbeKeylistFree(Keylist*); void sqlite3VdbeKeylistFree(Keylist*);
void sqliteVdbePopStack(Vdbe*,int); void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(Cursor*); int sqlite3VdbeCursorMoveto(Cursor*);
#if !defined(NDEBUG) || defined(VDBE_PROFILE) #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, Op*); void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif #endif
#ifdef SQLITE_DEBUG
void sqlite3VdbePrintSql(Vdbe*); void sqlite3VdbePrintSql(Vdbe*);
#endif
int sqlite3VdbeSerialTypeLen(u32); int sqlite3VdbeSerialTypeLen(u32);
u32 sqlite3VdbeSerialType(Mem*); u32 sqlite3VdbeSerialType(Mem*);
int sqlite3VdbeSerialPut(unsigned char*, Mem*); int sqlite3VdbeSerialPut(unsigned char*, Mem*);

View File

@ -103,7 +103,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
pOp->p2 = p2; pOp->p2 = p2;
pOp->p3 = 0; pOp->p3 = 0;
pOp->p3type = P3_NOTUSED; pOp->p3type = P3_NOTUSED;
#ifndef NDEBUG #ifdef SQLITE_DEBUG
if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
#endif #endif
return i; return i;
@ -212,7 +212,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
pOut->p2 = p2<0 ? addr + ADDR(p2) : p2; pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;
pOut->p3 = pIn->p3; pOut->p3 = pIn->p3;
pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED; pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;
#ifndef NDEBUG #ifdef SQLITE_DEBUG
if( sqlite3_vdbe_addop_trace ){ if( sqlite3_vdbe_addop_trace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
} }
@ -449,7 +449,7 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
#endif #endif
#if !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/* /*
** Print a single opcode. This routine is used for debugging only. ** Print a single opcode. This routine is used for debugging only.
*/ */
@ -689,7 +689,7 @@ void sqlite3VdbeSorterReset(Vdbe *p){
** Free all resources allociated with AggElem pElem, an element of ** Free all resources allociated with AggElem pElem, an element of
** aggregate pAgg. ** aggregate pAgg.
*/ */
void freeAggElem(AggElem *pElem, Agg *pAgg){ static void freeAggElem(AggElem *pElem, Agg *pAgg){
int i; int i;
for(i=0; i<pAgg->nMem; i++){ for(i=0; i<pAgg->nMem; i++){
Mem *pMem = &pElem->aMem[i]; Mem *pMem = &pElem->aMem[i];
@ -752,7 +752,7 @@ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
while( res==0 && rc==SQLITE_OK ){ while( res==0 && rc==SQLITE_OK ){
AggElem *pElem; AggElem *pElem;
rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem); rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem);
if( res!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
return rc; return rc;
} }
assert( pAgg->apFunc!=0 ); assert( pAgg->apFunc!=0 );
@ -1058,18 +1058,12 @@ static int vdbeCommit(sqlite3 *db){
*/ */
zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt); zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
rc = sqlite3OsOpenDirectory(zMainFile, &master); rc = sqlite3OsOpenDirectory(zMainFile, &master);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK || (rc = sqlite3OsSync(&master))!=SQLITE_OK ){
sqlite3OsClose(&master); sqlite3OsClose(&master);
sqlite3OsDelete(zMaster); sqlite3OsDelete(zMaster);
sqliteFree(zMaster); sqliteFree(zMaster);
return rc; return rc;
} }
rc = sqlite3OsSync(&master);
if( rc!=SQLITE_OK ){
sqlite3OsClose(&master);
sqliteFree(zMaster);
return rc;
}
/* Sync all the db files involved in the transaction. The same call /* Sync all the db files involved in the transaction. The same call
** sets the master journal pointer in each individual journal. If ** sets the master journal pointer in each individual journal. If
@ -1111,8 +1105,6 @@ static int vdbeCommit(sqlite3 *db){
** master journal exists now or if it will exist after the operating ** master journal exists now or if it will exist after the operating
** system crash that may follow the fsync() failure. ** system crash that may follow the fsync() failure.
*/ */
assert(0);
sqliteFree(zMaster);
return rc; return rc;
} }

View File

@ -15,60 +15,98 @@
# The tests in this file use special facilities that are only # The tests in this file use special facilities that are only
# available in the SQLite test fixture. # available in the SQLite test fixture.
# #
# $Id: ioerr.test,v 1.10 2005/01/11 13:02:34 danielk1977 Exp $ # $Id: ioerr.test,v 1.11 2005/01/12 09:10:41 danielk1977 Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
set ::AV [execsql {pragma auto_vacuum}] set ::AV [execsql {pragma auto_vacuum}]
set ::go 1 # Usage: do_ioerr_test <test number> <options...>
for {set n 1} {$go} {incr n} { #
# 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 IO error simulation.
# -sqlbody TCL script to run with IO error simulation.
# -exclude List of 'N' values not to test.
#
proc do_ioerr_test {tn args} {
array set ::ioerropts $args
# If SQLITE_DEFAULT_AUTOVACUUM is set to true, then a simulated IO error set ::go 1
# on the 8th IO operation in the SQL script below doesn't report an error. for {set n 1} {$::go} {incr n} {
#
# This is because the 8th IO call attempts to read page 2 of the database if {[info exists ::ioerropts(-exclude)]} {
# file when the file on disk is only 1 page. The pager layer detects that if {[lsearch $::ioerropts(-exclude) $n]!=-1} continue
# this has happened and suppresses the error returned by the OS layer. }
#
if {$::AV} {
if {$n==8} continue
}
do_test ioerr-1.$n.1 { do_test ioerr-$tn.$n.1 {
set ::sqlite_io_error_pending 0 set ::sqlite_io_error_pending 0
db close db close
catch {file delete -force test.db} catch {file delete -force test.db}
catch {file delete -force test.db-journal} catch {file delete -force test.db-journal}
sqlite3 db test.db catch {file delete -force test2.db}
execsql {SELECT * FROM sqlite_master} catch {file delete -force test2.db-journal}
} {}
do_test ioerr-1.$n.2 [subst { set ::DB [sqlite3 db test.db]
set ::sqlite_io_error_pending $n
}] $n if {[info exists ::ioerropts(-tclprep)]} {
do_test ioerr-1.$n.3 { eval $::ioerropts(-tclprep)
set r [catch {db eval { }
CREATE TABLE t1(a,b,c); if {[info exists ::ioerropts(-sqlprep)]} {
SELECT * FROM sqlite_master; execsql $::ioerropts(-sqlprep)
BEGIN TRANSACTION; }
INSERT INTO t1 VALUES(1,2,3); expr 0
INSERT INTO t1 VALUES(4,5,6); } {0}
ROLLBACK;
SELECT * FROM t1; do_test ioerr-$tn.$n.2 [subst {
BEGIN TRANSACTION; set ::sqlite_io_error_pending $n
INSERT INTO t1 VALUES(1,2,3); }] $n
INSERT INTO t1 VALUES(4,5,6);
COMMIT; set ::ioerrorbody {}
SELECT * FROM t1; if {[info exists ::ioerropts(-tclbody)]} {
DELETE FROM t1 WHERE a<100; append ::ioerrorbody "$::ioerropts(-tclbody)\n"
}} msg] }
# if {$r} {puts $msg} if {[info exists ::ioerropts(-sqlbody)]} {
set ::go [expr {$::sqlite_io_error_pending<=0}] append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
expr {$::sqlite_io_error_pending>0 || $r!=0} }
} {1} do_test ioerr-$tn.$n.3 {
set r [catch $::ioerrorbody msg]
set ::go [expr {$::sqlite_io_error_pending<=0}]
expr {$::sqlite_io_error_pending>0 || $r!=0}
} {1}
}
set ::sqlite_io_error_pending 0
} }
set ::sqlite_io_error_pending 0
# If SQLITE_DEFAULT_AUTOVACUUM is set to true, then a simulated IO error
# on the 8th IO operation in the SQL script below doesn't report an error.
#
# This is because the 8th IO call attempts to read page 2 of the database
# file when the file on disk is only 1 page. The pager layer detects that
# this has happened and suppresses the error returned by the OS layer.
#
do_ioerr_test 1 -sqlprep {
SELECT * FROM sqlite_master;
} -sqlbody {
CREATE TABLE t1(a,b,c);
SELECT * FROM sqlite_master;
BEGIN TRANSACTION;
INSERT INTO t1 VALUES(1,2,3);
INSERT INTO t1 VALUES(4,5,6);
ROLLBACK;
SELECT * FROM t1;
BEGIN TRANSACTION;
INSERT INTO t1 VALUES(1,2,3);
INSERT INTO t1 VALUES(4,5,6);
COMMIT;
SELECT * FROM t1;
DELETE FROM t1 WHERE a<100;
} -exclude [expr [execsql {pragma auto_vacuum}] ? 8 : 0]
proc cksum {{db db}} { proc cksum {{db db}} {
set txt [$db eval { set txt [$db eval {
@ -95,6 +133,8 @@ for {set n 1} {$go} {incr n} {
db close db close
catch {file delete -force test.db} catch {file delete -force test.db}
catch {file delete -force test.db-journal} catch {file delete -force test.db-journal}
catch {file delete -force test2.db}
catch {file delete -force test2.db-journal}
sqlite3 db test.db sqlite3 db test.db
execsql { execsql {
BEGIN; BEGIN;
@ -135,72 +175,51 @@ for {set n 1} {$go} {incr n} {
} }
set ::sqlite_io_error_pending 0 set ::sqlite_io_error_pending 0
set ::go 1
for {set n 1} {$go} {incr n} {
do_test ioerr-3.$n.1 {
set ::sqlite_io_error_pending 0
db close
catch {file delete -force test.db}
catch {file delete -force test.db-journal}
sqlite3 db test.db
execsql {
PRAGMA cache_size = 10;
BEGIN;
CREATE TABLE abc(a);
INSERT INTO abc VALUES(randstr(1500,1500)); -- Page 4 is overflow
}
for {set i 0} {$i<150} {incr i} {
execsql {
INSERT INTO abc VALUES(randstr(100,100));
}
}
execsql COMMIT
} {}
do_test ioerr-3.$n.2 [subst {
set ::sqlite_io_error_pending $n
}] $n
do_test ioerr-3.$n.3 {
set r [catch {db eval {
CREATE TABLE abc2(a);
BEGIN;
DELETE FROM abc WHERE length(a)>100;
UPDATE abc SET a = randstr(90,90);
COMMIT;
CREATE TABLE abc3(a);
}} msg]
set ::go [expr {$::sqlite_io_error_pending<=0}]
expr {$::sqlite_io_error_pending>0 || $r!=0}
} {1}
}
set ::sqlite_io_error_pending 0
set ::go 1 do_ioerr_test 3 -tclprep {
for {set n 1} {$go} {incr n} { execsql {
do_test ioerr-4.$n.1 { PRAGMA cache_size = 10;
set ::sqlite_io_error_pending 0 BEGIN;
db close CREATE TABLE abc(a);
catch {file delete -force test.db} INSERT INTO abc VALUES(randstr(1500,1500)); -- Page 4 is overflow
catch {file delete -force test.db-journal} }
sqlite3 db test.db for {set i 0} {$i<150} {incr i} {
set sql "CREATE TABLE abc(a1" execsql {
for {set i 2} {$i<1300} {incr i} { INSERT INTO abc VALUES(randstr(100,100));
append sql ", a$i"
} }
append sql ");" }
execsql $sql execsql COMMIT
execsql {INSERT INTO abc (a1) VALUES(NULL)} } -sqlbody {
} {} CREATE TABLE abc2(a);
do_test ioerr-4.$n.2 [subst { BEGIN;
set ::sqlite_io_error_pending $n DELETE FROM abc WHERE length(a)>100;
}] $n UPDATE abc SET a = randstr(90,90);
do_test ioerr-4.$n.3 { COMMIT;
set r [catch {db eval { CREATE TABLE abc3(a);
SELECT * FROM abc; }
}} msg]
set ::go [expr {$::sqlite_io_error_pending<=0}] # Test IO errors that can occur retrieving a record header that flows over
expr {$::sqlite_io_error_pending>0 || $r!=0} # onto an overflow page.
} {1} do_ioerr_test 4 -tclprep {
set sql "CREATE TABLE abc(a1"
for {set i 2} {$i<1300} {incr i} {
append sql ", a$i"
}
append sql ");"
execsql $sql
execsql {INSERT INTO abc (a1) VALUES(NULL)}
} -sqlbody {
SELECT * FROM abc;
}
# Test IO errors that may occur during a multi-file commit.
do_ioerr_test 5 -sqlprep {
ATTACH 'test2.db' AS test2;
} -sqlbody {
BEGIN;
CREATE TABLE t1(a,b,c);
CREATE TABLE test2.t2(a,b,c);
COMMIT;
} }
set ::sqlite_io_error_pending 0
finish_test finish_test

View File

@ -14,7 +14,7 @@
# special feature is used to see what happens in the library if a malloc # special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation. # were to really fail due to an out-of-memory situation.
# #
# $Id: malloc.test,v 1.14 2005/01/12 07:15:07 danielk1977 Exp $ # $Id: malloc.test,v 1.15 2005/01/12 09:10:41 danielk1977 Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -342,8 +342,12 @@ for {set go 1; set i 1} {$go} {incr i} {
# when converting UTF-16 text to integers and real numbers is handled # when converting UTF-16 text to integers and real numbers is handled
# correctly. # correctly.
# #
# This doesn't actually return an error to the user. That could be # This is done by retrieving a string from the database engine and
# viewed as a bug. # manipulating it using the sqlite3_column_*** APIs. This doesn't
# actually return an error to the user when a malloc() fails.. That
# could be viewed as a bug.
#
# These tests only run if UTF-16 support is compiled in.
# #
for {set go 1; set i 1} {$go && $::sqlite_options(utf16)} {incr i} { for {set go 1; set i 1} {$go && $::sqlite_options(utf16)} {incr i} {
do_test malloc-8.$i { do_test malloc-8.$i {
@ -382,6 +386,46 @@ for {set go 1; set i 1} {$go && $::sqlite_options(utf16)} {incr i} {
} {0} } {0}
} }
# This block tests that malloc() failures that occur whilst commiting
# a multi-file transaction are handled correctly.
#
for {set go 1; set i 1} {$go} {incr i} {
do_test malloc-9.$i {
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}
sqlite3 db test.db
execsql {
ATTACH 'test2.db' as test2;
CREATE TABLE abc1(a, b, c);
CREATE TABLE test2.abc2(a, b, c);
}
sqlite_malloc_fail $i
set v [catch {execsql {
BEGIN;
INSERT INTO abc1 VALUES(1, 2, 3);
INSERT INTO abc2 VALUES(1, 2, 3);
COMMIT;
}} msg]
set leftover [lindex [sqlite_malloc_stat] 2]
if {$leftover>0} {
if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
set ::go 0
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}
}
# Ensure that no file descriptors were leaked. # Ensure that no file descriptors were leaked.
do_test malloc-99.X { do_test malloc-99.X {
catch {db close} catch {db close}