1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Add support for measuring and reporting coverage of the parser state machine

using the SQLITE_TESTCTRL_PARSER_COVERAGE test-control.

FossilOrigin-Name: 1253a872dbf48656d4efd588ab61223a5ac550d9b2b932249d6ba585276ba573
This commit is contained in:
drh
2017-12-26 18:04:23 +00:00
parent 3a9d6c7156
commit 0d9de99c5c
8 changed files with 80 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
C Enhance\sLEMON\sso\sthat\sit\sgenerates\sthe\saction\stable\sin\ssuch\sa\sway\sthat\sno\nrange\scheck\sis\sneeded\son\sthe\slookahead\stable\sto\sverify\sthat\sthe\snext\sinput\ntoken\sis\svalid.\s\sThis\smakes\sthe\slookahead\stable\sslightly\slarger\s(about\s120\nbytes)\sbut\shelps\sthe\sparser\sto\srun\sfaster. C Add\ssupport\sfor\smeasuring\sand\sreporting\scoverage\sof\sthe\sparser\sstate\smachine\nusing\sthe\sSQLITE_TESTCTRL_PARSER_COVERAGE\stest-control.
D 2017-12-25T04:15:38.668 D 2017-12-26T18:04:23.951
F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69
@@ -443,7 +443,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722 F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b
F src/main.c 7ce55fa3c0bf669944de309ebab1655ed06ec67869adb0372c7a1062e461c448 F src/main.c 690c4134f944cbd5b71d59dd6e61ce4131f6a50ab774f38108e57d07d79cf876
F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6 F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -479,11 +479,11 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
F src/shell.c.in 339169a3d1307b5566ebe9ce15832d03439206106724c78cc3d9125a7b851795 F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55dc
F src/sqlite.h.in 2126192945019d4cdce335cb236b440a05ec75c93e4cd94c9c6d6e7fcc654cc4 F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
F src/sqliteInt.h 003b78433baae4e5c997f99f2f9cf98d90754f256baeacb32f8189569a48251f F src/sqliteInt.h 26bf7cc7aaa6a6eb3d3c0581f9ef5523da01babb8de1d796793d5165fea95958
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -1608,8 +1608,8 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c c8d7ce4fe7a90f7fa6a5985452aa926fcf25376cf90095c9d06c432ab0bebdbc F tool/lemon.c d92031adf63377ff5055441c9d26a41a03378e8cac8dbcc1cd6ef7190f51aa6a
F tool/lempar.c 427ee280f3c3781e82bbee21f428bc8ae18ab245d4f66d65da46b598ded81648 F tool/lempar.c 2a688bf343f21c25908cf082d0d707f45bc4416eea8550787809da4025c3d7c6
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1687,7 +1687,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 fdbb35c54f2b6cb65d04ac295f207ff3e69360e0558348c77eb5e62691807046 P 7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814
R f14cbf100834d359550a23c924f7ebaa R e80238b7e2c8eabf5efe2bfae85580fc
U drh U drh
Z bb1d7d0db816330a6f1e2b8011c2819b Z d5a5596d3c74652b6ba118722fb4ea75

View File

@@ -1 +1 @@
7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814 1253a872dbf48656d4efd588ab61223a5ac550d9b2b932249d6ba585276ba573

View File

@@ -3911,6 +3911,22 @@ int sqlite3_test_control(int op, ...){
sqlite3_mutex_leave(db->mutex); sqlite3_mutex_leave(db->mutex);
break; break;
} }
#if defined(YYCOVERAGE)
/* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out)
**
** This test control (only available when SQLite is compiled with
** -DYYCOVERAGE) writes a report onto "out" that shows all
** state/lookahead combinations in the parser state machine
** which are never exercised. If any state is missed, make the
** return code SQLITE_ERROR.
*/
case SQLITE_TESTCTRL_PARSER_COVERAGE: {
FILE *out = va_arg(ap, FILE*);
if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR;
break;
}
#endif /* defined(YYCOVERAGE) */
} }
va_end(ap); va_end(ap);
#endif /* SQLITE_UNTESTABLE */ #endif /* SQLITE_UNTESTABLE */

View File

@@ -6108,6 +6108,9 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
#ifdef YYCOVERAGE
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
#endif
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
{ "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" }, { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
@@ -6233,6 +6236,14 @@ static int do_meta_command(char *zLine, ShellState *p){
isOk = 3; isOk = 3;
} }
break; break;
#ifdef YYCOVERAGE
case SQLITE_TESTCTRL_PARSER_COVERAGE:
if( nArg==2 ){
sqlite3_test_control(testctrl, p->out);
isOk = 3;
}
#endif
} }
} }
if( isOk==0 && iCtrl>=0 ){ if( isOk==0 && iCtrl>=0 ){

View File

@@ -7042,7 +7042,8 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_ISINIT 23
#define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_SORTER_MMAP 24
#define SQLITE_TESTCTRL_IMPOSTER 25 #define SQLITE_TESTCTRL_IMPOSTER 25
#define SQLITE_TESTCTRL_LAST 25 /* Largest TESTCTRL */ #define SQLITE_TESTCTRL_PARSER_COVERAGE 26
#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
/* /*
** CAPI3REF: SQLite Runtime Status ** CAPI3REF: SQLite Runtime Status

View File

@@ -4348,6 +4348,9 @@ void sqlite3Put4byte(u8*, u32);
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
void sqlite3ParserTrace(FILE*, char *); void sqlite3ParserTrace(FILE*, char *);
#endif #endif
#if defined(YYCOVERAGE)
int sqlite3ParserCoverage(FILE*);
#endif
/* /*
** If the SQLITE_ENABLE IOTRACE exists then the global variable ** If the SQLITE_ENABLE IOTRACE exists then the global variable

View File

@@ -4257,6 +4257,7 @@ void ReportTable(
** been computed */ ** been computed */
fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
fprintf(out,"#define YYNTOKEN %d\n",lemp->nterminal); lineno++;
fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++; fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++;
i = lemp->minShiftReduce; i = lemp->minShiftReduce;
fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",i); lineno++; fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",i); lineno++;

View File

@@ -72,6 +72,7 @@
** defined, then do no error processing. ** defined, then do no error processing.
** YYNSTATE the combined number of states. ** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar ** YYNRULE the number of rules in the grammar
** YYNTOKEN Number of terminal symbols
** YY_MAX_SHIFT Maximum value for shift actions ** YY_MAX_SHIFT Maximum value for shift actions
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
@@ -253,13 +254,13 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
} }
#endif /* NDEBUG */ #endif /* NDEBUG */
#ifndef NDEBUG #if defined(YYCOVERAGE) || !defined(NDEBUG)
/* For tracing shifts, the names of all terminals and nonterminals /* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */ ** are required. The following table supplies these names */
static const char *const yyTokenName[] = { static const char *const yyTokenName[] = {
%% %%
}; };
#endif /* NDEBUG */ #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
#ifndef NDEBUG #ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required. /* For tracing reduce actions, the names of all rules are required.
@@ -455,6 +456,35 @@ int ParseStackPeak(void *p){
} }
#endif #endif
/* This array of booleans keeps track of the parser statement
** coverage. The element yycoverage[X][Y] is set when the parser
** is in state X and has a lookahead token Y. In a well-tested
** systems, every element of this matrix should end up being set.
*/
#if defined(YYCOVERAGE)
static unsigned char yycoverage[YYNSTATE][YYNTOKEN];
#endif
/*
** Write into out a description of every state/lookahead combination that
** has not previously been seen by the parser. Return the number of
** missed state/lookahead combinations.
*/
#if defined(YYCOVERAGE)
int ParseCoverage(FILE *out){
int i, j;
int nMissed = 0;
for(i=0; i<YYNSTATE; i++){
for(j=0; j<YYNTOKEN; j++){
if( yycoverage[i][j] ) continue;
nMissed++;
if( out ) fprintf(out,"State %d lookahead %s\n", i, yyTokenName[j]);
}
}
return nMissed;
}
#endif
/* /*
** Find the appropriate action for a parser given the terminal ** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead. ** look-ahead token iLookAhead.
@@ -468,6 +498,9 @@ static unsigned int yy_find_shift_action(
if( stateno>YY_MAX_SHIFT ) return stateno; if( stateno>YY_MAX_SHIFT ) return stateno;
assert( stateno <= YY_SHIFT_COUNT ); assert( stateno <= YY_SHIFT_COUNT );
#if defined(YYCOVERAGE)
yycoverage[stateno][iLookAhead] = 1;
#endif
do{ do{
i = yy_shift_ofst[stateno]; i = yy_shift_ofst[stateno];
assert( iLookAhead!=YYNOCODE ); assert( iLookAhead!=YYNOCODE );