diff --git a/ext/ota/ota3.test b/ext/ota/ota3.test index 0dae31c190..24d5ffde32 100644 --- a/ext/ota/ota3.test +++ b/ext/ota/ota3.test @@ -200,6 +200,8 @@ do_test 5.3 { expr {[file size test.db-wal] > (1024 * 1200)} } 1 +do_test 6.1 { sqlite3ota_internal_test } {} + finish_test diff --git a/ext/ota/otafault2.test b/ext/ota/otafault2.test new file mode 100644 index 0000000000..659cfec1f8 --- /dev/null +++ b/ext/ota/otafault2.test @@ -0,0 +1,58 @@ +# 2014 October 22 +# +# 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. +# +#*********************************************************************** +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +set ::testprefix otafault2 + +forcedelete ota.db +do_execsql_test 1.0 { + CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y)); + INSERT INTO target VALUES(1, 2, 3); + INSERT INTO target VALUES(4, 5, 6); + + ATTACH 'ota.db' AS ota; + CREATE TABLE ota.data_target(x, y, z, ota_control); + INSERT INTO data_target VALUES(7, 8, 9, 0); + INSERT INTO data_target VALUES(1, 11, 12, 0); + DETACH ota; +} +db close + +forcecopy test.db test.db-bak +forcecopy ota.db ota.db-bak + +do_faultsim_test 1 -faults oom* -prep { + forcecopy test.db-bak test.db + forcecopy ota.db-bak ota.db + forcedelete test.db-oal test.db-wal ota.db-journal + sqlite3ota ota test.db ota.db +} -body { + while {[ota step]=="SQLITE_OK"} { } + ota close +} -test { + faultsim_test_result \ + {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: target.x}} \ + {1 SQLITE_CONSTRAINT} \ + {1 SQLITE_NOMEM} \ + {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}} \ + {1 {SQLITE_NOMEM - out of memory}} +} + + + + +finish_test + diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c index 3f67535548..ae4c9dd698 100644 --- a/ext/ota/sqlite3ota.c +++ b/ext/ota/sqlite3ota.c @@ -1930,6 +1930,11 @@ static void otaIncrSchemaCookie(sqlite3ota *p){ "PRAGMA schema_version" ); if( p->rc==SQLITE_OK ){ + /* Coverage: it may be that this sqlite3_step() cannot fail. There + ** is already a transaction open, so the prepared statement cannot + ** throw an SQLITE_SCHEMA exception. The only database page the + ** statement reads is page 1, which is guaranteed to be in the cache. + ** And no memory allocations are required. */ if( SQLITE_ROW==sqlite3_step(pStmt) ){ iCookie = sqlite3_column_int(pStmt, 0); } diff --git a/ext/ota/test_ota.c b/ext/ota/test_ota.c index e9a649b5d9..bbb52fe0d9 100644 --- a/ext/ota/test_ota.c +++ b/ext/ota/test_ota.c @@ -195,6 +195,30 @@ static int test_sqlite3ota_destroy_vfs( return TCL_OK; } +/* +** Tclcmd: sqlite3ota_internal_test +*/ +static int test_sqlite3ota_internal_test( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + db = sqlite3ota_db(0); + if( db!=0 ){ + Tcl_AppendResult(interp, "sqlite3ota_db(0)!=0", 0); + return TCL_ERROR; + } + + return TCL_OK; +} int SqliteOta_Init(Tcl_Interp *interp){ static struct { @@ -204,6 +228,7 @@ int SqliteOta_Init(Tcl_Interp *interp){ { "sqlite3ota", test_sqlite3ota }, { "sqlite3ota_create_vfs", test_sqlite3ota_create_vfs }, { "sqlite3ota_destroy_vfs", test_sqlite3ota_destroy_vfs }, + { "sqlite3ota_internal_test", test_sqlite3ota_internal_test }, }; int i; for(i=0; i