]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add support for measuring and reporting coverage of the parser state machine
authordrh <drh@noemail.net>
Tue, 26 Dec 2017 18:04:23 +0000 (18:04 +0000)
committerdrh <drh@noemail.net>
Tue, 26 Dec 2017 18:04:23 +0000 (18:04 +0000)
using the SQLITE_TESTCTRL_PARSER_COVERAGE test-control.

FossilOrigin-Name: 1253a872dbf48656d4efd588ab61223a5ac550d9b2b932249d6ba585276ba573

manifest
manifest.uuid
src/main.c
src/shell.c.in
src/sqlite.h.in
src/sqliteInt.h
tool/lemon.c
tool/lempar.c

index d9f3940ae050f20b1deb4c2b8a0b13959a8bd243..7f1e56cfbd21a917955da8997f1ba35374f765cd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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.
-D 2017-12-25T04:15:38.668
+C Add\ssupport\sfor\smeasuring\sand\sreporting\scoverage\sof\sthe\sparser\sstate\smachine\nusing\sthe\sSQLITE_TESTCTRL_PARSER_COVERAGE\stest-control.
+D 2017-12-26T18:04:23.951
 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69
@@ -443,7 +443,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722
 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
 F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b
-F src/main.c 7ce55fa3c0bf669944de309ebab1655ed06ec67869adb0372c7a1062e461c448
+F src/main.c 690c4134f944cbd5b71d59dd6e61ce4131f6a50ab774f38108e57d07d79cf876
 F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -479,11 +479,11 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
-F src/shell.c.in 339169a3d1307b5566ebe9ce15832d03439206106724c78cc3d9125a7b851795
-F src/sqlite.h.in 2126192945019d4cdce335cb236b440a05ec75c93e4cd94c9c6d6e7fcc654cc4
+F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55dc
+F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
-F src/sqliteInt.h 003b78433baae4e5c997f99f2f9cf98d90754f256baeacb32f8189569a48251f
+F src/sqliteInt.h 26bf7cc7aaa6a6eb3d3c0581f9ef5523da01babb8de1d796793d5165fea95958
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -1608,8 +1608,8 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
 F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c c8d7ce4fe7a90f7fa6a5985452aa926fcf25376cf90095c9d06c432ab0bebdbc
-F tool/lempar.c 427ee280f3c3781e82bbee21f428bc8ae18ab245d4f66d65da46b598ded81648
+F tool/lemon.c d92031adf63377ff5055441c9d26a41a03378e8cac8dbcc1cd6ef7190f51aa6a
+F tool/lempar.c 2a688bf343f21c25908cf082d0d707f45bc4416eea8550787809da4025c3d7c6
 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P fdbb35c54f2b6cb65d04ac295f207ff3e69360e0558348c77eb5e62691807046
-R f14cbf100834d359550a23c924f7ebaa
+P 7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814
+R e80238b7e2c8eabf5efe2bfae85580fc
 U drh
-Z bb1d7d0db816330a6f1e2b8011c2819b
+Z d5a5596d3c74652b6ba118722fb4ea75
index b69ed5a1cc950bff707ee8f1d0b2ec97f44db2a2..dce691ea27d5bb3cd9cf0eec01f48543b23cf341 100644 (file)
@@ -1 +1 @@
-7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814
\ No newline at end of file
+1253a872dbf48656d4efd588ab61223a5ac550d9b2b932249d6ba585276ba573
\ No newline at end of file
index 32ce1889f6bbc3d037b7e19fae4ebce08f406b70..3c8035c120ce960c8139a22f0270d1583cad3a0f 100644 (file)
@@ -3911,6 +3911,22 @@ int sqlite3_test_control(int op, ...){
       sqlite3_mutex_leave(db->mutex);
       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);
 #endif /* SQLITE_UNTESTABLE */
index 13b1fcde396fafc2a2ac18650b16093393b569b8..155ca708a59ba12a430ead10339394785d41c0a8 100644 (file)
@@ -6108,6 +6108,9 @@ static int do_meta_command(char *zLine, ShellState *p){
       { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"           },
       { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"            },
       { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"       },
+#ifdef YYCOVERAGE
+      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""                 },
+#endif
       { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "           },
       { "prng_reset",         SQLITE_TESTCTRL_PRNG_RESET,    ""                   },
       { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""                   },
@@ -6233,6 +6236,14 @@ static int do_meta_command(char *zLine, ShellState *p){
             isOk = 3;
           }
           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 ){
index f161eea6f2aa09b04327eda01f4a746a5076efbd..7e5fccdae6d37ae6ac8226335777370c56d725af 100644 (file)
@@ -7042,7 +7042,8 @@ int sqlite3_test_control(int op, ...);
 #define SQLITE_TESTCTRL_ISINIT                  23
 #define SQLITE_TESTCTRL_SORTER_MMAP             24
 #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
index b0c4711b0348b4d9456493d2eedebcbc9cebc571..074d363d48f3030983ccf29abe79a45955965688 100644 (file)
@@ -4348,6 +4348,9 @@ void sqlite3Put4byte(u8*, u32);
 #ifdef SQLITE_DEBUG
   void sqlite3ParserTrace(FILE*, char *);
 #endif
+#if defined(YYCOVERAGE)
+  int sqlite3ParserCoverage(FILE*);
+#endif
 
 /*
 ** If the SQLITE_ENABLE IOTRACE exists then the global variable
index 96dc756d1b3711367536d559b47a0481d06a7d83..111082c72ab51279df18ab91380f51ca728c42a7 100644 (file)
@@ -4257,6 +4257,7 @@ void ReportTable(
   ** been computed */
   fprintf(out,"#define YYNSTATE             %d\n",lemp->nxstate);  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++;
   i = lemp->minShiftReduce;
   fprintf(out,"#define YY_MIN_SHIFTREDUCE   %d\n",i); lineno++;
index 7ceaaa62072922d052a741d7969d13a6635455ff..29dc15d03d5b5a64ed253b054f0762700cf961cc 100644 (file)
@@ -72,6 +72,7 @@
 **                       defined, then do no error processing.
 **    YYNSTATE           the combined number of states.
 **    YYNRULE            the number of rules in the grammar
+**    YYNTOKEN           Number of terminal symbols
 **    YY_MAX_SHIFT       Maximum value for shift actions
 **    YY_MIN_SHIFTREDUCE Minimum 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 */
 
-#ifndef NDEBUG
+#if defined(YYCOVERAGE) || !defined(NDEBUG)
 /* For tracing shifts, the names of all terminals and nonterminals
 ** are required.  The following table supplies these names */
 static const char *const yyTokenName[] = { 
 %%
 };
-#endif /* NDEBUG */
+#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
 
 #ifndef NDEBUG
 /* For tracing reduce actions, the names of all rules are required.
@@ -455,6 +456,35 @@ int ParseStackPeak(void *p){
 }
 #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
 ** look-ahead token iLookAhead.
@@ -468,6 +498,9 @@ static unsigned int yy_find_shift_action(
  
   if( stateno>YY_MAX_SHIFT ) return stateno;
   assert( stateno <= YY_SHIFT_COUNT );
+#if defined(YYCOVERAGE)
+  yycoverage[stateno][iLookAhead] = 1;
+#endif
   do{
     i = yy_shift_ofst[stateno];
     assert( iLookAhead!=YYNOCODE );