diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bitvec.c | 127 | ||||
-rw-r--r-- | src/fault.c | 6 | ||||
-rw-r--r-- | src/main.c | 21 | ||||
-rw-r--r-- | src/random.c | 6 | ||||
-rw-r--r-- | src/sqlite.h.in | 3 | ||||
-rw-r--r-- | src/sqliteInt.h | 5 | ||||
-rw-r--r-- | src/test2.c | 120 | ||||
-rw-r--r-- | src/test_config.c | 14 |
8 files changed, 183 insertions, 119 deletions
diff --git a/src/bitvec.c b/src/bitvec.c index 7fa8a8aec..be8f4d6d1 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -32,14 +32,14 @@ ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. ** -** @(#) $Id: bitvec.c,v 1.2 2008/03/14 13:02:08 mlcreech Exp $ +** @(#) $Id: bitvec.c,v 1.3 2008/03/21 16:45:47 drh Exp $ */ #include "sqliteInt.h" #define BITVEC_SZ 512 /* Round the union size down to the nearest pointer boundary, since that's how ** it will be aligned within the Bitvec struct. */ -#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec *))*sizeof(Bitvec *)) +#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*)) #define BITVEC_NCHAR BITVEC_USIZE #define BITVEC_NBIT (BITVEC_NCHAR*8) #define BITVEC_NINT (BITVEC_USIZE/4) @@ -101,9 +101,8 @@ Bitvec *sqlite3BitvecCreate(u32 iSize){ ** i is out of range, then return false. */ int sqlite3BitvecTest(Bitvec *p, u32 i){ - assert( i>0 ); if( p==0 ) return 0; - if( i>p->iSize ) return 0; + if( i>p->iSize || i==0 ) return 0; if( p->iSize<=BITVEC_NBIT ){ i--; return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0; @@ -130,6 +129,7 @@ int sqlite3BitvecTest(Bitvec *p, u32 i){ int sqlite3BitvecSet(Bitvec *p, u32 i){ u32 h; assert( p!=0 ); + assert( i>0 ); if( p->iSize<=BITVEC_NBIT ){ i--; p->u.aBitmap[i/8] |= 1 << (i&7); @@ -159,8 +159,8 @@ int sqlite3BitvecSet(Bitvec *p, u32 i){ memcpy(aiValues, p->u.aHash, sizeof(aiValues)); memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR); p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; - sqlite3BitvecSet(p, i); - for(rc=j=0; j<BITVEC_NINT; j++){ + rc = sqlite3BitvecSet(p, i); + for(j=0; j<BITVEC_NINT; j++){ if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]); } return rc; @@ -175,6 +175,7 @@ int sqlite3BitvecSet(Bitvec *p, u32 i){ */ void sqlite3BitvecClear(Bitvec *p, u32 i){ assert( p!=0 ); + assert( i>0 ); if( p->iSize<=BITVEC_NBIT ){ i--; p->u.aBitmap[i/8] &= ~(1 << (i&7)); @@ -191,7 +192,9 @@ void sqlite3BitvecClear(Bitvec *p, u32 i){ memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT); p->nSet = 0; for(j=0; j<BITVEC_NINT; j++){ - if( aiValues[j] && aiValues[j]!=i ) sqlite3BitvecSet(p, aiValues[j]); + if( aiValues[j] && aiValues[j]!=i ){ + sqlite3BitvecSet(p, aiValues[j]); + } } } } @@ -209,3 +212,113 @@ void sqlite3BitvecDestroy(Bitvec *p){ } sqlite3_free(p); } + +#ifndef SQLITE_OMIT_BUILTIN_TEST +/* +** Let V[] be an array of unsigned characters sufficient to hold +** up to N bits. Let I be an integer between 0 and N. 0<=I<N. +** Then the following macros can be used to set, clear, or test +** individual bits within V. +*/ +#define SETBIT(V,I) V[I>>3] |= (1<<(I&7)) +#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7)) +#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 + +/* +** This routine runs an extensive test of the Bitvec code. +** +** The input is an array of integers that acts as a program +** to test the Bitvec. The integers are opcodes followed +** by 0, 1, or 3 operands, depending on the opcode. Another +** opcode follows immediately after the last operand. +** +** There are 6 opcodes numbered from 0 through 5. 0 is the +** "halt" opcode and causes the test to end. +** +** 0 Halt and return the number of errors +** 1 N S X Set N bits beginning with S and incrementing by X +** 2 N S X Clear N bits beginning with S and incrementing by X +** 3 N Set N randomly chosen bits +** 4 N Clear N randomly chosen bits +** 5 N S X Set N bits from S increment X in array only, not in bitvec +** +** The opcodes 1 through 4 perform set and clear operations are performed +** on both a Bitvec object and on a linear array of bits obtained from malloc. +** Opcode 5 works on the linear array only, not on the Bitvec. +** Opcode 5 is used to deliberately induce a fault in order to +** confirm that error detection works. +** +** At the conclusion of the test the linear array is compared +** against the Bitvec object. If there are any differences, +** an error is returned. If they are the same, zero is returned. +** +** If a memory allocation error occurs, return -1. +*/ +int sqlite3BitvecBuiltinTest(int sz, int *aOp){ + Bitvec *pBitvec = 0; + unsigned char *pV = 0; + int rc = -1; + int i, nx, pc, op; + + /* Allocate the Bitvec to be tested and a linear array of + ** bits to act as the reference */ + pBitvec = sqlite3BitvecCreate( sz ); + pV = sqlite3_malloc( (sz+7)/8 + 1 ); + if( pBitvec==0 || pV==0 ) goto bitvec_end; + memset(pV, 0, (sz+7)/8 + 1); + + /* Run the program */ + pc = 0; + while( (op = aOp[pc])!=0 ){ + switch( op ){ + case 1: + case 2: + case 5: { + nx = 4; + i = aOp[pc+2] - 1; + aOp[pc+2] += aOp[pc+3]; + break; + } + case 3: + case 4: + default: { + nx = 2; + sqlite3_randomness(sizeof(i), &i); + break; + } + } + if( (--aOp[pc+1]) > 0 ) nx = 0; + pc += nx; + i = (i & 0x7fffffff)%sz; + if( (op & 1)!=0 ){ + SETBIT(pV, (i+1)); + if( op!=5 ){ + if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; + } + }else{ + CLEARBIT(pV, (i+1)); + sqlite3BitvecClear(pBitvec, i+1); + } + } + + /* Test to make sure the linear array exactly matches the + ** Bitvec object. Start with the assumption that they do + ** match (rc==0). Change rc to non-zero if a discrepancy + ** is found. + */ + rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) + + sqlite3BitvecTest(pBitvec, 0); + for(i=1; i<=sz; i++){ + if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ + rc = i; + break; + } + } + + /* Free allocated structure */ +bitvec_end: + sqlite3_free(pV); + sqlite3BitvecDestroy(pBitvec); + return rc; +} +#endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/src/fault.c b/src/fault.c index af7702ec9..7e183ed43 100644 --- a/src/fault.c +++ b/src/fault.c @@ -19,7 +19,7 @@ ** allocation failures or I/O errors. ** ** The fault injector is omitted from the code if SQLite is -** compiled with -DSQLITE_OMIT_TESTLOGIC=1. There is a very +** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1. There is a very ** small performance hit for leaving the fault injector in the code. ** Commerical products will probably want to omit the fault injector ** from production builds. But safety-critical systems who work @@ -28,7 +28,7 @@ */ #include "sqliteInt.h" -#ifndef SQLITE_OMIT_TESTLOGIC +#ifndef SQLITE_OMIT_BUILTIN_TEST /* ** There can be various kinds of faults. For example, there can be @@ -144,4 +144,4 @@ int sqlite3FaultStep(int id){ return 1; } -#endif /* SQLITE_OMIT_TESTLOGIC */ +#endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/src/main.c b/src/main.c index 140e64a62..41b84c094 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.428 2008/03/20 18:00:49 drh Exp $ +** $Id: main.c,v 1.429 2008/03/21 16:45:47 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1574,7 +1574,7 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ */ int sqlite3_test_control(int op, ...){ int rc = 0; -#ifndef SQLITE_OMIT_TESTLOGIC +#ifndef SQLITE_OMIT_BUILTIN_TEST va_list ap; va_start(ap, op); switch( op ){ @@ -1658,8 +1658,23 @@ int sqlite3_test_control(int op, ...){ sqlite3PrngResetState(); break; } + + /* + ** sqlite3_test_control(BITVEC_TEST, size, program) + ** + ** Run a test against a Bitvec object of size. The program argument + ** is an array of integers that defines the test. Return -1 on a + ** memory allocation error, 0 on success, or non-zero for an error. + ** See the sqlite3BitvecBuiltinTest() for additional information. + */ + case SQLITE_TESTCTRL_BITVEC_TEST: { + int sz = va_arg(ap, int); + int *aProg = va_arg(ap, int*); + rc = sqlite3BitvecBuiltinTest(sz, aProg); + break; + } } va_end(ap); -#endif /* SQLITE_OMIT_TESTLOGIC */ +#endif /* SQLITE_OMIT_BUILTIN_TEST */ return rc; } diff --git a/src/random.c b/src/random.c index 0c6591866..4b977f2b4 100644 --- a/src/random.c +++ b/src/random.c @@ -15,7 +15,7 @@ ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: random.c,v 1.22 2008/03/19 14:15:35 drh Exp $ +** $Id: random.c,v 1.23 2008/03/21 16:45:47 drh Exp $ */ #include "sqliteInt.h" @@ -103,7 +103,7 @@ void sqlite3_randomness(int N, void *pBuf){ sqlite3_mutex_leave(mutex); } -#ifndef SQLITE_OMIT_TESTLOGIC +#ifndef SQLITE_OMIT_BUILTIN_TEST /* ** For testing purposes, we sometimes want to preserve the state of ** PRNG and restore the PRNG to its saved state at a later time. @@ -120,4 +120,4 @@ void sqlite3PrngRestoreState(void){ void sqlite3PrngResetState(void){ sqlite3Prng.isInit = 0; } -#endif /* SQLITE_OMIT_TESTLOGIC */ +#endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 158c6e1e3..18d44d263 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.298 2008/03/20 18:00:49 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.299 2008/03/21 16:45:47 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -5610,6 +5610,7 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 #define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8c7173b2f..8f6b5bdd6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.678 2008/03/20 16:30:18 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.679 2008/03/21 16:45:47 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1790,6 +1790,7 @@ int sqlite3BitvecTest(Bitvec*, u32); int sqlite3BitvecSet(Bitvec*, u32); void sqlite3BitvecClear(Bitvec*, u32); void sqlite3BitvecDestroy(Bitvec*); +int sqlite3BitvecBuiltinTest(int,int*); void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); @@ -2084,7 +2085,7 @@ CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); ** mechanism is disabled at compile-time then set up macros so that no ** unnecessary code is generated. */ -#ifndef SQLITE_OMIT_TESTLOGIC +#ifndef SQLITE_OMIT_BUILTIN_TEST void sqlite3FaultConfig(int,int,int); int sqlite3FaultFailures(int); int sqlite3FaultBenignFailures(int); diff --git a/src/test2.c b/src/test2.c index a8457efb3..68e9c65c0 100644 --- a/src/test2.c +++ b/src/test2.c @@ -13,12 +13,13 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test2.c,v 1.56 2008/03/20 11:04:21 danielk1977 Exp $ +** $Id: test2.c,v 1.57 2008/03/21 16:45:48 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> +#include <ctype.h> /* ** Interpret an SQLite error number @@ -561,103 +562,40 @@ static int fake_big_file( } #endif + /* -** sqlite3BitvecCreate SIZE -** sqlite3BitvecTest POINTER N -** sqlite3BitvecSet POINTER N -** sqlite3BitvecClear POINTER N -** sqlite3BitvecDestroy POINTER +** sqlite3BitvecBuiltinTest SIZE PROGRAM +** +** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control. +** See comments on sqlite3BitvecBuiltinTest() for additional information. */ -static int testBitvecCreate( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int size; - Bitvec *p; - char zBuf[100]; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", - (void*)0); - } - if( Tcl_GetInt(interp, argv[1], &size) ) return TCL_ERROR; - p = sqlite3BitvecCreate(size); - sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",p); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} -static int testBitvecTest( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int N; - Bitvec *p; - char zBuf[100]; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR N\"", - (void*)0); - } - p = (Bitvec*)sqlite3TextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &N) ) return TCL_ERROR; - sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3BitvecTest(p,N)); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} -static int testBitvecSet( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int N; - Bitvec *p; - char zBuf[100]; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR N\"", - (void*)0); - } - p = (Bitvec*)sqlite3TextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &N) ) return TCL_ERROR; - sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3BitvecSet(p,N)); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} -static int testBitvecClear( +static int testBitvecBuiltinTest( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ - int N; - Bitvec *p; + int sz, rc; + int nProg = 0; + int aProg[100]; + const char *z; if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR N\"", - (void*)0); - } - p = (Bitvec*)sqlite3TextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &N) ) return TCL_ERROR; - sqlite3BitvecClear(p,N); - return TCL_OK; -} -static int testBitvecDestroy( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Bitvec *p; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR\"", - (void*)0); - } - p = (Bitvec*)sqlite3TextToPtr(argv[1]); - sqlite3BitvecDestroy(p); + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " SIZE PROGRAM\"", (void*)0); + } + if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR; + z = argv[2]; + while( nProg<99 && *z ){ + while( *z && !isdigit(*z) ){ z++; } + if( *z==0 ) break; + aProg[nProg++] = atoi(z); + while( isdigit(*z) ){ z++; } + } + aProg[nProg] = 0; + rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } - /* ** Register commands with the TCL interpreter. @@ -693,11 +631,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){ #ifndef SQLITE_OMIT_DISKIO { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, #endif - { "sqlite3BitvecCreate", (Tcl_CmdProc*)testBitvecCreate }, - { "sqlite3BitvecTest", (Tcl_CmdProc*)testBitvecTest }, - { "sqlite3BitvecSet", (Tcl_CmdProc*)testBitvecSet }, - { "sqlite3BitvecClear", (Tcl_CmdProc*)testBitvecClear }, - { "sqlite3BitvecDestroy", (Tcl_CmdProc*)testBitvecDestroy }, + { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest}, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ diff --git a/src/test_config.c b/src/test_config.c index adf6805e8..c396763d4 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -16,7 +16,7 @@ ** The focus of this file is providing the TCL testing layer ** access to compile-time constants. ** -** $Id: test_config.c,v 1.22 2008/03/20 14:03:29 drh Exp $ +** $Id: test_config.c,v 1.23 2008/03/21 16:45:48 drh Exp $ */ #include "sqliteLimit.h" @@ -135,6 +135,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_OMIT_BUILTIN_TEST + Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "1", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_BLOB_LITERAL Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY); #else @@ -356,12 +362,6 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double", Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY); #endif -#ifdef SQLITE_OMIT_TESTLOGIC - Tcl_SetVar2(interp, "sqlite_options", "testlogic", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "testlogic", "1", TCL_GLOBAL_ONLY); -#endif - rc = sqlite3_threadsafe(); #if SQLITE_THREADSAFE Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY); |