Skip to content

Commit

Permalink
Add fault-injection tests for the code in test_stat.c.
Browse files Browse the repository at this point in the history
  • Loading branch information
danielk-1977 committed Apr 27, 2015
1 parent a4e8a70 commit e2eb967
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 49 deletions.
114 changes: 66 additions & 48 deletions src/test_stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,23 @@ static int statConnect(
sqlite3_vtab **ppVtab,
char **pzErr
){
StatTable *pTab;
StatTable *pTab = 0;
int rc = SQLITE_OK;

pTab = (StatTable *)sqlite3_malloc(sizeof(StatTable));
memset(pTab, 0, sizeof(StatTable));
pTab->db = db;
rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
if( rc==SQLITE_OK ){
pTab = (StatTable *)sqlite3_malloc(sizeof(StatTable));
if( pTab==0 ) rc = SQLITE_NOMEM;
}

sqlite3_declare_vtab(db, VTAB_SCHEMA);
*ppVtab = &pTab->base;
return SQLITE_OK;
assert( rc==SQLITE_OK || pTab==0 );
if( rc==SQLITE_OK ){
memset(pTab, 0, sizeof(StatTable));
pTab->db = db;
}

*ppVtab = (sqlite3_vtab*)pTab;
return rc;
}

/*
Expand Down Expand Up @@ -196,32 +204,38 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc;

pCsr = (StatCursor *)sqlite3_malloc(sizeof(StatCursor));
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;

rc = sqlite3_prepare_v2(pTab->db,
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0"
" ORDER BY name", -1,
&pCsr->pStmt, 0
);
if( rc!=SQLITE_OK ){
sqlite3_free(pCsr);
return rc;
if( pCsr==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;

rc = sqlite3_prepare_v2(pTab->db,
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0"
" ORDER BY name", -1,
&pCsr->pStmt, 0
);
if( rc!=SQLITE_OK ){
sqlite3_free(pCsr);
pCsr = 0;
}
}

*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
return rc;
}

static void statClearPage(StatPage *p){
int i;
for(i=0; i<p->nCell; i++){
sqlite3_free(p->aCell[i].aOvfl);
if( p->aCell ){
for(i=0; i<p->nCell; i++){
sqlite3_free(p->aCell[i].aOvfl);
}
sqlite3_free(p->aCell);
}
sqlite3PagerUnref(p->pPg);
sqlite3_free(p->aCell);
sqlite3_free(p->zPath);
memset(p, 0, sizeof(StatPage));
}
Expand Down Expand Up @@ -307,6 +321,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt);
sqlite3BtreeLeave(pBt);
p->aCell = sqlite3_malloc((p->nCell+1) * sizeof(StatCell));
if( p->aCell==0 ) return SQLITE_NOMEM;
memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell));

for(i=0; i<p->nCell; i++){
Expand Down Expand Up @@ -339,6 +354,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
pCell->nOvfl = nOvfl;
pCell->aOvfl = sqlite3_malloc(sizeof(u32)*nOvfl);
if( pCell->aOvfl==0 ) return SQLITE_NOMEM;
pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
for(j=1; j<nOvfl; j++){
int rc;
Expand Down Expand Up @@ -486,31 +502,33 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
pCsr->iPageno = p->iPgno;

statDecodePage(pBt, p);
statSizeAndOffset(pCsr);

switch( p->flags ){
case 0x05: /* table internal */
case 0x02: /* index internal */
pCsr->zPagetype = "internal";
break;
case 0x0D: /* table leaf */
case 0x0A: /* index leaf */
pCsr->zPagetype = "leaf";
break;
default:
pCsr->zPagetype = "corrupted";
break;
}
pCsr->nCell = p->nCell;
pCsr->nUnused = p->nUnused;
pCsr->nMxPayload = p->nMxPayload;
pCsr->zPath = sqlite3_mprintf("%s", p->zPath);
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
rc = statDecodePage(pBt, p);
if( rc==SQLITE_OK ){
statSizeAndOffset(pCsr);

switch( p->flags ){
case 0x05: /* table internal */
case 0x02: /* index internal */
pCsr->zPagetype = "internal";
break;
case 0x0D: /* table leaf */
case 0x0A: /* index leaf */
pCsr->zPagetype = "leaf";
break;
default:
pCsr->zPagetype = "corrupted";
break;
}
pCsr->nCell = p->nCell;
pCsr->nUnused = p->nUnused;
pCsr->nMxPayload = p->nMxPayload;
pCsr->zPath = sqlite3_mprintf("%s", p->zPath);
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
}
pCsr->nPayload = nPayload;
}
pCsr->nPayload = nPayload;
}

return rc;
Expand Down
3 changes: 2 additions & 1 deletion src/vdbe.c
Original file line number Diff line number Diff line change
Expand Up @@ -6107,8 +6107,9 @@ case OP_VOpen: {
pCur->pVtabCursor = pVtabCursor;
pVtab->nRef++;
}else{
db->mallocFailed = 1;
assert( db->mallocFailed );
pModule->xClose(pVtabCursor);
goto no_mem;
}
}
break;
Expand Down
45 changes: 45 additions & 0 deletions test/statfault.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# 2015 April 28
#
# 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.
#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix statfault

ifcapable !vtab||!compound {
finish_test
return
}

register_dbstat_vtab db
do_execsql_test statfault-1 {
CREATE TABLE t1(a, b UNIQUE);
INSERT INTO t1 VALUES(1, randomblob(500));
INSERT INTO t1 VALUES(randomblob(500), 1);
INSERT INTO t1 VALUES(2, randomblob(250));
INSERT INTO t1 VALUES(randomblob(250), 2);
CREATE VIRTUAL TABLE sss USING dbstat;
} {}
faultsim_save_and_close

do_faultsim_test 1 -faults * -prep {
faultsim_restore_and_reopen
register_dbstat_vtab db
execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
} -body {
execsql { SELECT count(*) FROM sss }
} -test {
faultsim_test_result {0 8}
}


finish_test

0 comments on commit e2eb967

Please sign in to comment.