mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Enhancements and improved documentation to the byte-code branch coverage
testing logic. Provide new macros that allow the code to specify that some branch instructions can never take the NULL path and that the OP_Jump opcode is only interested in equal/not-equal. The SQLITE_TESTCTRL_VDBE_COVERAGE file control callback now works slightly differently (it provides the callback with a bitmask of the branch action, rather than an integer). FossilOrigin-Name: cd2da7e1ba4e78e68ccf65d4969df963c1e3085930e74419450bda2799381e05
This commit is contained in:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\sa\sharmless\swarning\sabout\scomment\sformatting\sin\sthe\sprevious\ncheck-in.\s\sSimplify\sthe\sORDER\sBY\sdereferencing\slogic\sso\sthat\sit\savoids\nunreachable\sbranches.
|
C Enhancements\sand\simproved\sdocumentation\sto\sthe\sbyte-code\sbranch\scoverage\ntesting\slogic.\s\sProvide\snew\smacros\sthat\sallow\sthe\scode\sto\sspecify\sthat\nsome\sbranch\sinstructions\scan\snever\stake\sthe\sNULL\spath\sand\sthat\sthe\sOP_Jump\nopcode\sis\sonly\sinterested\sin\sequal/not-equal.\s\sThe\nSQLITE_TESTCTRL_VDBE_COVERAGE\sfile\scontrol\scallback\snow\sworks\sslightly\ndifferently\s(it\sprovides\sthe\scallback\swith\sa\sbitmask\sof\sthe\sbranch\saction,\nrather\sthan\san\sinteger).
|
||||||
D 2018-07-10T07:39:23.889
|
D 2018-07-10T16:04:04.503
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
|
F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
|
||||||
@@ -459,7 +459,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
|||||||
F src/insert.c bcacf6a0d277f8fa0e4f9ffecda544a2330ca4478f904cd89564c2dd86d0b16b
|
F src/insert.c bcacf6a0d277f8fa0e4f9ffecda544a2330ca4478f904cd89564c2dd86d0b16b
|
||||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||||
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
|
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
|
||||||
F src/main.c db7d550fad3a95403f50d25cbdd8ec33037ed100e676f2481d58e0d9cf0f15dc
|
F src/main.c fa70bde00ebe7865cfa3fe1e2de87a003d575c1ec4598ff0a1f414ecb1404928
|
||||||
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
||||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||||
@@ -500,7 +500,7 @@ F src/shell.c.in f1c79c537117ee61317a5ed85cdbcb854998cd690eb34ab803779358a2ace78
|
|||||||
F src/sqlite.h.in 36f0b3f88241863530f4b7e57e673e19311dd609ec4edad83b23291928cdf853
|
F src/sqlite.h.in 36f0b3f88241863530f4b7e57e673e19311dd609ec4edad83b23291928cdf853
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
|
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
|
||||||
F src/sqliteInt.h 7e24bfe3bf22df5516062f229fe181f9532ff44335d702c525420e060aad78da
|
F src/sqliteInt.h 7e32765449d103b6b68f6d64a54add80c82e94cd8661afe34c9657b0c0e61512
|
||||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||||
@@ -566,8 +566,8 @@ F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
|
|||||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||||
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
|
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
|
||||||
F src/vdbe.c 800c69a80609b4837d3403e15092e585f356711823529ad1c04fe5ca8e9f9aec
|
F src/vdbe.c d8b06bfad9a1da50a53489f95758c68535fbc7aecd1b2c17820a1f35f066fadb
|
||||||
F src/vdbe.h 9c8c245fa3785266c269ab02c135c836ff49a307612186686bcdae500f409945
|
F src/vdbe.h 5ec6ab3ed6316fd55215a2425334c790a6246be1a54aca1dd70b64ea01aabaef
|
||||||
F src/vdbeInt.h 6b5cbd338dc9aaad343fb11b455e47463b0474d9f79710f50e647158941146e0
|
F src/vdbeInt.h 6b5cbd338dc9aaad343fb11b455e47463b0474d9f79710f50e647158941146e0
|
||||||
F src/vdbeapi.c af4a3de00d1851bcbc55b85dfbe52849aa2b1e17b4a5a1f3d9c257df7af361ff
|
F src/vdbeapi.c af4a3de00d1851bcbc55b85dfbe52849aa2b1e17b4a5a1f3d9c257df7af361ff
|
||||||
F src/vdbeaux.c c2d65c763b0811afe409e02e9d0d1f300c6e97892474fc94eec3da71955cd418
|
F src/vdbeaux.c c2d65c763b0811afe409e02e9d0d1f300c6e97892474fc94eec3da71955cd418
|
||||||
@@ -1746,7 +1746,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 52559ad58ce412af40f1f34e80bfe9fadc6a93f3ca0cfaf69f94d615bbb99831
|
P 0f6ec605e131ab3d53b9df32af0a3207146a9abbd22dcabd6ef050b92f96735d
|
||||||
R af867e8f2830341644b32312137b8d37
|
R b470ad8653de43144ab67291d89ba06d
|
||||||
U drh
|
U drh
|
||||||
Z 9b7ea72c6158564396d1f1dc7cb1a0c3
|
Z a362372ff34491594b26fb7a228e2946
|
||||||
|
@@ -1 +1 @@
|
|||||||
0f6ec605e131ab3d53b9df32af0a3207146a9abbd22dcabd6ef050b92f96735d
|
cd2da7e1ba4e78e68ccf65d4969df963c1e3085930e74419450bda2799381e05
|
@@ -3974,7 +3974,8 @@ int sqlite3_test_control(int op, ...){
|
|||||||
*/
|
*/
|
||||||
case SQLITE_TESTCTRL_VDBE_COVERAGE: {
|
case SQLITE_TESTCTRL_VDBE_COVERAGE: {
|
||||||
#ifdef SQLITE_VDBE_COVERAGE
|
#ifdef SQLITE_VDBE_COVERAGE
|
||||||
typedef void (*branch_callback)(void*,int,u8,u8);
|
typedef void (*branch_callback)(void*,unsigned int,
|
||||||
|
unsigned char,unsigned char);
|
||||||
sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback);
|
sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback);
|
||||||
sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
|
sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -3387,7 +3387,7 @@ struct Sqlite3Config {
|
|||||||
/* The following callback (if not NULL) is invoked on every VDBE branch
|
/* The following callback (if not NULL) is invoked on every VDBE branch
|
||||||
** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
|
** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
|
||||||
*/
|
*/
|
||||||
void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
|
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
|
||||||
void *pVdbeBranchArg; /* 1st argument */
|
void *pVdbeBranchArg; /* 1st argument */
|
||||||
#endif
|
#endif
|
||||||
#ifndef SQLITE_UNTESTABLE
|
#ifndef SQLITE_UNTESTABLE
|
||||||
|
66
src/vdbe.c
66
src/vdbe.c
@@ -134,32 +134,56 @@ int sqlite3_found_count = 0;
|
|||||||
** feature is used for test suite validation only and does not appear an
|
** feature is used for test suite validation only and does not appear an
|
||||||
** production builds.
|
** production builds.
|
||||||
**
|
**
|
||||||
** M is an integer, 2 or 3, that indices how many different ways the
|
** M is an integer between 2 and 4. 2 indicates a ordinary two-way
|
||||||
** branch can go. It is usually 2. "I" is the direction the branch
|
** branch (I=0 means fall through and I=1 means taken). 3 indicates
|
||||||
** goes. 0 means falls through. 1 means branch is taken. 2 means the
|
** a 3-way branch where the third way is when one of the operands is
|
||||||
** second alternative branch is taken.
|
** NULL. 4 indicates the OP_Jump instruction which has three destinations
|
||||||
|
** depending on whether the first operand is less than, equal to, or greater
|
||||||
|
** than the second.
|
||||||
**
|
**
|
||||||
** iSrcLine is the source code line (from the __LINE__ macro) that
|
** iSrcLine is the source code line (from the __LINE__ macro) that
|
||||||
** generated the VDBE instruction. This instrumentation assumes that all
|
** generated the VDBE instruction combined with flag bits. The source
|
||||||
** source code is in a single file (the amalgamation). Special values 1
|
** code line number is in the lower 24 bits of iSrcLine and the upper
|
||||||
** and 2 for the iSrcLine parameter mean that this particular branch is
|
** 8 bytes are flags. The lower three bits of the flags indicate
|
||||||
** always taken or never taken, respectively.
|
** values for I that should never occur. For example, if the branch is
|
||||||
|
** always taken, the flags should be 0x05 since the fall-through and
|
||||||
|
** alternate branch are never taken. If a branch is never taken then
|
||||||
|
** flags should be 0x06 since only the fall-through approach is allowed.
|
||||||
|
**
|
||||||
|
** Bit 0x04 of the flags indicates an OP_Jump opcode that is only
|
||||||
|
** interested in equal or not-equal. In other words, I==0 and I==2
|
||||||
|
** should be treated the same.
|
||||||
|
**
|
||||||
|
** Since only a line number is retained, not the filename, this macro
|
||||||
|
** only works for amalgamation builds. But that is ok, since these macros
|
||||||
|
** should be no-ops except for special builds used to measure test coverage.
|
||||||
*/
|
*/
|
||||||
#if !defined(SQLITE_VDBE_COVERAGE)
|
#if !defined(SQLITE_VDBE_COVERAGE)
|
||||||
# define VdbeBranchTaken(I,M)
|
# define VdbeBranchTaken(I,M)
|
||||||
#else
|
#else
|
||||||
# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
|
# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
|
||||||
static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){
|
static void vdbeTakeBranch(u32 iSrcLine, u8 I, u8 M){
|
||||||
if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){
|
u8 mNever;
|
||||||
M = iSrcLine;
|
assert( I<=2 ); /* 0: fall through, 1: taken, 2: alternate taken */
|
||||||
/* Assert the truth of VdbeCoverageAlwaysTaken() and
|
assert( M<=4 ); /* 2: two-way branch, 3: three-way branch, 4: OP_Jump */
|
||||||
** VdbeCoverageNeverTaken() */
|
assert( I<M ); /* I can only be 2 if M is 3 or 4 */
|
||||||
assert( (M & I)==I );
|
/* Transform I from a integer [0,1,2] into a bitmask of [1,2,4] */
|
||||||
}else{
|
I = 1<<I;
|
||||||
if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
|
/* The upper 8 bits of iSrcLine are flags. The lower three bits of
|
||||||
sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
|
** the flags indicate directions that the branch can never go. If
|
||||||
iSrcLine,I,M);
|
** a branch really does go in one of those directions, assert right
|
||||||
|
** away. */
|
||||||
|
mNever = iSrcLine >> 24;
|
||||||
|
assert( (I & mNever)==0 );
|
||||||
|
if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
|
||||||
|
I |= mNever;
|
||||||
|
if( M==2 ) I |= 0x04;
|
||||||
|
if( M==4 ){
|
||||||
|
I |= 0x08;
|
||||||
|
if( (I&0x05)!=0 ) I |= 0x05;
|
||||||
}
|
}
|
||||||
|
sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
|
||||||
|
iSrcLine&0xffffff, I, M);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2162,11 +2186,11 @@ case OP_Compare: {
|
|||||||
*/
|
*/
|
||||||
case OP_Jump: { /* jump */
|
case OP_Jump: { /* jump */
|
||||||
if( iCompare<0 ){
|
if( iCompare<0 ){
|
||||||
VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1];
|
VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1];
|
||||||
}else if( iCompare==0 ){
|
}else if( iCompare==0 ){
|
||||||
VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1];
|
VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1];
|
||||||
}else{
|
}else{
|
||||||
VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1];
|
VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
33
src/vdbe.h
33
src/vdbe.h
@@ -73,7 +73,8 @@ struct VdbeOp {
|
|||||||
u64 cycles; /* Total time spent executing this instruction */
|
u64 cycles; /* Total time spent executing this instruction */
|
||||||
#endif
|
#endif
|
||||||
#ifdef SQLITE_VDBE_COVERAGE
|
#ifdef SQLITE_VDBE_COVERAGE
|
||||||
int iSrcLine; /* Source-code line that generated this opcode */
|
u32 iSrcLine; /* Source-code line that generated this opcode
|
||||||
|
** with flags in the upper 8 bits */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
typedef struct VdbeOp VdbeOp;
|
typedef struct VdbeOp VdbeOp;
|
||||||
@@ -317,23 +318,49 @@ int sqlite3NotPureFunc(sqlite3_context*);
|
|||||||
**
|
**
|
||||||
** VdbeCoverageNeverTaken(v) // Previous branch is never taken
|
** VdbeCoverageNeverTaken(v) // Previous branch is never taken
|
||||||
**
|
**
|
||||||
|
** VdbeCoverageNeverNull(v) // Previous three-way branch is only
|
||||||
|
** // taken on the first two ways. The
|
||||||
|
** // NULL option is not possible
|
||||||
|
**
|
||||||
|
** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested
|
||||||
|
** // in distingishing equal and not-equal.
|
||||||
|
**
|
||||||
** Every VDBE branch operation must be tagged with one of the macros above.
|
** Every VDBE branch operation must be tagged with one of the macros above.
|
||||||
** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
|
** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
|
||||||
** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
|
** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
|
||||||
** routine in vdbe.c, alerting the developer to the missed tag.
|
** routine in vdbe.c, alerting the developer to the missed tag.
|
||||||
|
**
|
||||||
|
** During testing, the test application will invoke
|
||||||
|
** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback
|
||||||
|
** routine that is invoked as each bytecode branch is taken. The callback
|
||||||
|
** contains the sqlite3.c source line number ov the VdbeCoverage macro and
|
||||||
|
** flags to indicate whether or not the branch was taken. The test application
|
||||||
|
** is responsible for keeping track of this and reporting byte-code branches
|
||||||
|
** that are never taken.
|
||||||
|
**
|
||||||
|
** See the VdbeBranchTaken() macro and vdbeTakeBranch() function in the
|
||||||
|
** vdbe.c source file for additional information.
|
||||||
*/
|
*/
|
||||||
#ifdef SQLITE_VDBE_COVERAGE
|
#ifdef SQLITE_VDBE_COVERAGE
|
||||||
void sqlite3VdbeSetLineNumber(Vdbe*,int);
|
void sqlite3VdbeSetLineNumber(Vdbe*,int);
|
||||||
# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
|
# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
|
||||||
# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
|
# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
|
||||||
# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2);
|
# define VdbeCoverageAlwaysTaken(v) \
|
||||||
# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1);
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000);
|
||||||
|
# define VdbeCoverageNeverTaken(v) \
|
||||||
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000);
|
||||||
|
# define VdbeCoverageNeverNull(v) \
|
||||||
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000);
|
||||||
|
# define VdbeCoverageEqNe(v) \
|
||||||
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000);
|
||||||
# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
|
# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
|
||||||
#else
|
#else
|
||||||
# define VdbeCoverage(v)
|
# define VdbeCoverage(v)
|
||||||
# define VdbeCoverageIf(v,x)
|
# define VdbeCoverageIf(v,x)
|
||||||
# define VdbeCoverageAlwaysTaken(v)
|
# define VdbeCoverageAlwaysTaken(v)
|
||||||
# define VdbeCoverageNeverTaken(v)
|
# define VdbeCoverageNeverTaken(v)
|
||||||
|
# define VdbeCoverageNeverNull(v)
|
||||||
|
# define VdbeCoverageEqNe(v)
|
||||||
# define VDBE_OFFSET_LINENO(x) 0
|
# define VDBE_OFFSET_LINENO(x) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user