Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -11,11 +11,11 @@ ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.117 2004/11/22 19:12:21 drh Exp $ +** $Id: test1.c,v 1.118 2005/01/11 15:28:33 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include @@ -2471,10 +2471,42 @@ return TCL_ERROR; } Tcl_AppendResult(interp, zFile, 0); return TCL_OK; } + +/* +** Usage: sqlite_set_magic DB MAGIC-NUMBER +** +** Set the db->magic value. This is used to test error recovery logic. +*/ +static int sqlite_set_magic( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + sqlite3 *db; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB MAGIC", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){ + db->magic = SQLITE_MAGIC_OPEN; + }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){ + db->magic = SQLITE_MAGIC_CLOSED; + }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){ + db->magic = SQLITE_MAGIC_BUSY; + }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){ + db->magic = SQLITE_MAGIC_ERROR; + }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){ + return TCL_ERROR; + } + return TCL_OK; +} /* ** Usage: tcl_variable_type VARIABLENAME ** ** Return the name of the internal representation for the @@ -2702,10 +2734,11 @@ #endif { "sqlite_bind", (Tcl_CmdProc*)test_bind }, { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, { "sqlite3_key", (Tcl_CmdProc*)test_key }, { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, + { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, }; static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -12,11 +12,11 @@ ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.123 2004/12/25 01:03:14 drh Exp $ +** $Id: util.c,v 1.124 2005/01/11 15:28:33 drh Exp $ */ #include "sqliteInt.h" #include #include @@ -924,14 +924,13 @@ static int hexToInt(int h){ if( h>='0' && h<='9' ){ return h - '0'; }else if( h>='a' && h<='f' ){ return h - 'a' + 10; - }else if( h>='A' && h<='F' ){ - return h - 'A' + 10; }else{ - return 0; + assert( h>='A' && h<='F' ); + return h - 'A' + 10; } } #endif /* (!SQLITE_OMIT_BLOB_LITERAL && !SQLITE_HAS_CODEC) || SQLITE_TEST */ #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) Index: test/misc4.test ================================================================== --- test/misc4.test +++ test/misc4.test @@ -11,11 +11,11 @@ # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # -# $Id: misc4.test,v 1.8 2004/11/22 13:35:42 danielk1977 Exp $ +# $Id: misc4.test,v 1.9 2005/01/11 15:28:33 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Prepare a statement that will create a temporary table. Then do @@ -96,8 +96,7 @@ UNION SELECT ID, max(Value) FROM Table2 GROUP BY 1,2 ORDER BY 1, 2; } } {{} {} 1 x 1 z} } ;# ifcapable compound - finish_test ADDED test/safety.test Index: test/safety.test ================================================================== --- /dev/null +++ test/safety.test @@ -0,0 +1,69 @@ +# 2005 January 11 +# +# 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 implements regression tests for SQLite library. The +# focus of this file is testing the sqlite3SafetyOn and sqlite3SafetyOff +# functions. Those routines are not strictly necessary - they are +# designed to detect misuse of the library. +# +# $Id: safety.test,v 1.1 2005/01/11 15:28:33 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_test safety-1.1 { + db close + set DB [sqlite3 db test.db] + db eval {CREATE TABLE t1(a)} + sqlite_set_magic $DB SQLITE_MAGIC_BUSY + catchsql { + SELECT name FROM sqlite_master; + } +} {1 {library routine called out of sequence}} +do_test safety-1.2 { + sqlite_set_magic $DB SQLITE_MAGIC_OPEN + catchsql { + SELECT name FROM sqlite_master + } +} {0 t1} + +do_test safety-2.1 { + proc safety_on {} "sqlite_set_magic $DB SQLITE_MAGIC_BUSY" + db function safety_on safety_on + catchsql { + SELECT safety_on(), name FROM sqlite_master + } +} {1 {library routine called out of sequence}} +do_test safety-2.2 { + catchsql { + SELECT 'hello' + } +} {1 {library routine called out of sequence}} +do_test safety-2.3 { + sqlite3_close $DB +} {SQLITE_MISUSE} +do_test safety-2.4 { + sqlite_set_magic $DB SQLITE_MAGIC_OPEN + execsql { + SELECT name FROM sqlite_master + } +} {t1} + +do_test safety-3.1 { + set rc [catch { + db eval {SELECT name FROM sqlite_master} { + sqlite_set_magic $DB SQLITE_MAGIC_BUSY + } + } msg] + lappend rc $msg +} {1 {library routine called out of sequence}} +sqlite_set_magic $DB SQLITE_MAGIC_OPEN + +finish_test