mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Improved diagnostics for Bitvec: Add the sqlite3ShowBitvec() routine that
can be called from a debugger (only available with SQLITE_DEBUG). Add new output opcodes for sqlite3BitvecBuiltinTest(). FossilOrigin-Name: dea1e37fa67ada6efc1533b449d9eb22338d9e58eec8f89b48c38319c212c8f4
This commit is contained in:
76
src/bitvec.c
76
src/bitvec.c
@@ -107,6 +107,7 @@ struct Bitvec {
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Create a new bitmap object able to handle bits between 0 and iSize,
|
||||
** inclusive. Return a pointer to the new object. Return NULL if
|
||||
@@ -293,6 +294,52 @@ u32 sqlite3BitvecSize(Bitvec *p){
|
||||
return p->iSize;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Show the content of a Bitvec option and its children. Indent
|
||||
** everything by n spaces. Add x to each bitvec value.
|
||||
**
|
||||
** From a debugger such as gdb, one can type:
|
||||
**
|
||||
** call sqlite3ShowBitvec(p)
|
||||
**
|
||||
** For some Bitvec p and see a recursive view of the Bitvec's content.
|
||||
*/
|
||||
static void showBitvec(Bitvec *p, int n, unsigned x){
|
||||
int i;
|
||||
if( p==0 ){
|
||||
printf("NULL\n");
|
||||
return;
|
||||
}
|
||||
printf("Bitvec 0x%p iSize=%d", p, p->iSize);
|
||||
if( p->iSize<=BITVEC_NBIT ){
|
||||
printf(" bitmap\n");
|
||||
printf("%*s bits:", n, "");
|
||||
for(i=1; i<=BITVEC_NBIT; i++){
|
||||
if( sqlite3BitvecTest(p,i) ) printf(" %u", x+(unsigned)i);
|
||||
}
|
||||
printf("\n");
|
||||
}else if( p->iDivisor==0 ){
|
||||
printf(" hash with %d entries\n", p->nSet);
|
||||
printf("%*s bits:", n, "");
|
||||
for(i=0; i<BITVEC_NINT; i++){
|
||||
if( p->u.aHash[i] ) printf(" %u", x+(unsigned)p->u.aHash[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}else{
|
||||
printf(" sub-bitvec with iDivisor=%d\n", p->iDivisor);
|
||||
for(i=0; i<BITVEC_NPTR; i++){
|
||||
if( p->u.apSub[i]==0 ) continue;
|
||||
printf("%*s apSub[%d]=", n, "", i);
|
||||
showBitvec(p->u.apSub[i], n+4, i*p->iDivisor);
|
||||
}
|
||||
}
|
||||
}
|
||||
void sqlite3ShowBitvec(Bitvec *p){
|
||||
showBitvec(p, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
/*
|
||||
** Let V[] be an array of unsigned characters sufficient to hold
|
||||
@@ -304,6 +351,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
|
||||
#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7))
|
||||
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
|
||||
|
||||
|
||||
/*
|
||||
** This routine runs an extensive test of the Bitvec code.
|
||||
**
|
||||
@@ -312,7 +360,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
|
||||
** 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
|
||||
** There are opcodes numbered starting with 0. 0 is the
|
||||
** "halt" opcode and causes the test to end.
|
||||
**
|
||||
** 0 Halt and return the number of errors
|
||||
@@ -321,12 +369,16 @@ u32 sqlite3BitvecSize(Bitvec *p){
|
||||
** 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
|
||||
** 6 Invoice sqlite3ShowBitvec() on the Bitvec object so far
|
||||
** 7 X Show compile-time parameters and the hash of X
|
||||
**
|
||||
** 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.
|
||||
** confirm that error detection works. Opcodes 6 and greater are
|
||||
** state output opcodes. Opcodes 6 and greater are no-ops unless
|
||||
** SQLite has been compiled with SQLITE_DEBUG.
|
||||
**
|
||||
** At the conclusion of the test the linear array is compared
|
||||
** against the Bitvec object. If there are any differences,
|
||||
@@ -355,6 +407,26 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
||||
/* Run the program */
|
||||
pc = i = 0;
|
||||
while( (op = aOp[pc])!=0 ){
|
||||
if( op>=6 ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( op==6 ){
|
||||
sqlite3ShowBitvec(pBitvec);
|
||||
}else if( op==7 ){
|
||||
unsigned x = (unsigned)aOp[++pc];
|
||||
printf("BITVEC_SZ = %d (%d by sizeof)\n",
|
||||
BITVEC_SZ, (int)sizeof(Bitvec));
|
||||
printf("BITVEC_USIZE = %d\n", (int)BITVEC_USIZE);
|
||||
printf("BITVEC_NELEM = %d\n", (int)BITVEC_NELEM);
|
||||
printf("BITVEC_NBIT = %d\n", (int)BITVEC_NBIT);
|
||||
printf("BITVEC_NINT = %d\n", (int)BITVEC_NINT);
|
||||
printf("BITVEC_MXHASH = %d\n", (int)BITVEC_MXHASH);
|
||||
printf("BITVEC_NPTR = %d\n", (int)BITVEC_NPTR);
|
||||
printf("hash(%u): %u\n", x, (unsigned)BITVEC_HASH(x));
|
||||
}
|
||||
#endif
|
||||
pc++;
|
||||
continue;
|
||||
}
|
||||
switch( op ){
|
||||
case 1:
|
||||
case 2:
|
||||
|
@@ -11590,7 +11590,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
|
||||
{"assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
|
||||
/*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
|
||||
/*{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
|
||||
{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "SIZE INT-ARRAY"},
|
||||
{"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
|
||||
{"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
|
||||
{"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"args..." },
|
||||
@@ -11928,6 +11928,49 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
sqlite3_test_control(testctrl, &rc2);
|
||||
break;
|
||||
case SQLITE_TESTCTRL_BITVEC_TEST: {
|
||||
/* Examples:
|
||||
** .testctrl bitvec_test 100 6,1 -- Show BITVEC constants
|
||||
** .testctrl bitvec_test 1000 1,12,7,3 -- Simple test
|
||||
** ---- --------
|
||||
** size of Bitvec -----^ ^--- aOp array. 0 added at end.
|
||||
**
|
||||
** See comments on sqlite3BitvecBuiltinTest() for more information
|
||||
** about the aOp[] array.
|
||||
*/
|
||||
int iSize;
|
||||
const char *zTestArg;
|
||||
int nOp;
|
||||
int ii, jj, x;
|
||||
int *aOp;
|
||||
if( nArg!=4 ){
|
||||
sqlite3_fprintf(stderr,
|
||||
"ERROR - should be: \".testctrl bitvec_test SIZE INT-ARRAY\"\n"
|
||||
);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
isOk = 3;
|
||||
iSize = (int)integerValue(azArg[2]);
|
||||
zTestArg = azArg[3];
|
||||
nOp = (int)strlen(zTestArg)+1;
|
||||
aOp = malloc( sizeof(int)*(nOp+1) );
|
||||
shell_check_oom(aOp);
|
||||
memset(aOp, 0, sizeof(int)*(nOp+1) );
|
||||
for(ii = jj = x = 0; zTestArg[ii]!=0; ii++){
|
||||
if( IsDigit(zTestArg[ii]) ){
|
||||
x = x*10 + zTestArg[ii] - '0';
|
||||
}else{
|
||||
aOp[jj++] = x;
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
aOp[jj] = x;
|
||||
x = sqlite3_test_control(testctrl, iSize, aOp);
|
||||
sqlite3_fprintf(p->out, "result: %d\n", x);
|
||||
free(aOp);
|
||||
break;
|
||||
}
|
||||
case SQLITE_TESTCTRL_FAULT_INSTALL: {
|
||||
int kk;
|
||||
int bShowHelp = nArg<=2;
|
||||
|
@@ -4894,6 +4894,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
||||
void sqlite3ShowWindow(const Window*);
|
||||
void sqlite3ShowWinFunc(const Window*);
|
||||
#endif
|
||||
void sqlite3ShowBitvec(Bitvec*);
|
||||
#endif
|
||||
|
||||
void sqlite3SetString(char **, sqlite3*, const char*);
|
||||
|
Reference in New Issue
Block a user