]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add further test cases and minor fixes for the fuzzer.
authordan <dan@noemail.net>
Tue, 21 Feb 2012 10:36:27 +0000 (10:36 +0000)
committerdan <dan@noemail.net>
Tue, 21 Feb 2012 10:36:27 +0000 (10:36 +0000)
FossilOrigin-Name: 583dde93a9176ba4fff85241bafbbe4e5a6cc95f

manifest
manifest.uuid
src/test_fuzzer.c
test/fuzzer1.test

index c8032d0fb9fb2f95334155661ce1d21f5eacb177..b5477ec6ed53a749938602f0ad29a4d131f00512 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Updates\sto\sthe\sinstructions\sin\sthe\sheader\scomment\sof\sthe\sfuzzer\simplementation.\nNew\stest\scases\sfor\sthe\sfuzzer.
-D 2012-02-20T22:44:12.628
+C Add\sfurther\stest\scases\sand\sminor\sfixes\sfor\sthe\sfuzzer.
+D 2012-02-21T10:36:27.146
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -206,7 +206,7 @@ F src/test_config.c a036a69b550ebc477ab9ca2b37269201f888436e
 F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
 F src/test_func.c 6232d722a4ddb193035aa13a03796bf57d6c12fd
-F src/test_fuzzer.c 2c0d96f94fdf7bfc2458dac9835c87b2086fdb67
+F src/test_fuzzer.c d557ab99e9f1c0d8ae7ac639b4c3d4babd279f90
 F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
 F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a
 F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
@@ -504,7 +504,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
 F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
-F test/fuzzer1.test 830e260b10213d5dc6aadccc1fc4b0c7fefce7b8
+F test/fuzzer1.test 098fc6dc6edcc8430d8e29a27eae6b9825d35470
 F test/hook.test 5f3749de6462a6b87b4209b74adf7df5ac2df639
 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
 F test/in.test a7b8a0f43da81cd08645b7a710099ffe9ad1126b
@@ -989,7 +989,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 90b7b957f8933047fd2878048dfa3ec4891988b8
-R e208940f645a7d6e8e24937143961be4
-U drh
-Z c02d350749266fd28db3de432a6902e8
+P bf1dc7907cf1a5c7e19b04fa1278b2089316c30a
+R e5d50c19b0286a351f7b9b6f103c6c32
+U dan
+Z 5de28f986fce8d4352f35f6c3b70b1eb
index 6ba7c0f0ec57b63e3ec2e0bf0fe4fa111db8c96a..fd44690269bf94795a12c1b8737d831a36aaf271 100644 (file)
@@ -1 +1 @@
-bf1dc7907cf1a5c7e19b04fa1278b2089316c30a
\ No newline at end of file
+583dde93a9176ba4fff85241bafbbe4e5a6cc95f
\ No newline at end of file
index bfc5b7a2cf9cc7010ff2175f5e571bb939d3b0d8..eecea140e081b5e6297a59b4f0a518ec2c6d71dd 100644 (file)
 ** of the strings in the second or third column of the fuzzer data table
 ** is 50 bytes.  The maximum cost on a rule is 1000.
 */
+
+/* If SQLITE_DEBUG is not defined, disable assert statements. */
+#ifndef SQLITE_DEBUG
+# define NDEBUG
+#endif
+
 #include "sqlite3.h"
 #include <stdlib.h>
 #include <string.h>
@@ -289,7 +295,7 @@ static int fuzzerLoadOneRule(
   fuzzer_rule **ppRule,           /* OUT: New rule object */
   char **pzErr                    /* OUT: Error message */
 ){
-  int iRuleset = sqlite3_column_int(pStmt, 0);
+  sqlite3_int64 iRuleset = sqlite3_column_int64(pStmt, 0);
   const char *zFrom = (const char *)sqlite3_column_text(pStmt, 1);
   const char *zTo = (const char *)sqlite3_column_text(pStmt, 2);
   int nCost = sqlite3_column_int(pStmt, 3);
@@ -311,16 +317,21 @@ static int fuzzerLoadOneRule(
   }
 
   if( nCost<=0 || nCost>FUZZER_MX_COST ){
-    *pzErr = sqlite3_mprintf("cost must be between 1 and %d", FUZZER_MX_COST);
+    *pzErr = sqlite3_mprintf("%s: cost must be between 1 and %d", 
+        p->zClassName, FUZZER_MX_COST
+    );
     rc = SQLITE_ERROR;
   }else
   if( nFrom>FUZZER_MX_LENGTH || nTo>FUZZER_MX_LENGTH ){
-    *pzErr = sqlite3_mprintf("maximum string length is %d", FUZZER_MX_LENGTH);
+    *pzErr = sqlite3_mprintf("%s: maximum string length is %d", 
+        p->zClassName, FUZZER_MX_LENGTH
+    );
     rc = SQLITE_ERROR;    
   }else
   if( iRuleset<0 || iRuleset>FUZZER_MX_RULEID ){
-    *pzErr = sqlite3_mprintf(
-        "ruleset must be between 0 and %d", FUZZER_MX_RULEID);
+    *pzErr = sqlite3_mprintf("%s: ruleset must be between 0 and %d", 
+        p->zClassName, FUZZER_MX_RULEID
+    );
     rc = SQLITE_ERROR;    
   }else{
 
@@ -335,7 +346,7 @@ static int fuzzerLoadOneRule(
       memcpy(pRule->zTo, zTo, nTo+1);
       pRule->nTo = nTo;
       pRule->rCost = nCost;
-      pRule->iRuleset = iRuleset;
+      pRule->iRuleset = (int)iRuleset;
     }
   }
 
@@ -419,6 +430,59 @@ static int fuzzerLoadRules(
   return rc;
 }
 
+/*
+** This function converts an SQL quoted string into an unquoted string
+** and returns a pointer to a buffer allocated using sqlite3_malloc() 
+** containing the result. The caller should eventually free this buffer
+** using sqlite3_free.
+**
+** Examples:
+**
+**     "abc"   becomes   abc
+**     'xyz'   becomes   xyz
+**     [pqr]   becomes   pqr
+**     `mno`   becomes   mno
+*/
+static char *fuzzerDequote(const char *zIn){
+  int nIn;                        /* Size of input string, in bytes */
+  char *zOut;                     /* Output (dequoted) string */
+
+  nIn = strlen(zIn);
+  zOut = sqlite3_malloc(nIn+1);
+  if( zOut ){
+    char q = zIn[0];              /* Quote character (if any ) */
+
+    if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
+      memcpy(zOut, zIn, nIn+1);
+    }else{
+      int iOut = 0;               /* Index of next byte to write to output */
+      int iIn;                    /* Index of next byte to read from input */
+
+      if( q=='[' ) q = ']';
+      for(iIn=1; iIn<nIn; iIn++){
+        if( zIn[iIn]==q ) iIn++;
+        zOut[iOut++] = zIn[iIn];
+      }
+    }
+    assert( strlen(zOut)<=nIn );
+  }
+  return zOut;
+}
+
+/*
+** xDisconnect/xDestroy method for the fuzzer module.
+*/
+static int fuzzerDisconnect(sqlite3_vtab *pVtab){
+  fuzzer_vtab *p = (fuzzer_vtab*)pVtab;
+  assert( p->nCursor==0 );
+  while( p->pRule ){
+    fuzzer_rule *pRule = p->pRule;
+    p->pRule = pRule->pNext;
+    sqlite3_free(pRule);
+  }
+  sqlite3_free(p);
+  return SQLITE_OK;
+}
 
 /*
 ** xConnect/xCreate method for the fuzzer module. Arguments are:
@@ -453,15 +517,24 @@ static int fuzzerConnect(
     if( pNew==0 ){
       rc = SQLITE_NOMEM;
     }else{
+      char *zTab;                 /* Dequoted name of fuzzer data table */
+
       memset(pNew, 0, sizeof(*pNew));
       pNew->zClassName = (char*)&pNew[1];
       memcpy(pNew->zClassName, zModule, nModule+1);
 
-      rc = fuzzerLoadRules(db, pNew, zDb, argv[3], pzErr);
+      zTab = fuzzerDequote(argv[3]);
+      if( zTab==0 ){
+        rc = SQLITE_NOMEM;
+      }else{
+        rc = fuzzerLoadRules(db, pNew, zDb, zTab, pzErr);
+        sqlite3_free(zTab);
+      }
+
       if( rc==SQLITE_OK ){
-        sqlite3_declare_vtab(db, "CREATE TABLE x(word, distance,ruleset)");
+        sqlite3_declare_vtab(db, "CREATE TABLE x(word, distance, ruleset)");
       }else{
-        sqlite3_free(pNew);
+        fuzzerDisconnect((sqlite3_vtab *)pNew);
         pNew = 0;
       }
     }
@@ -470,22 +543,6 @@ static int fuzzerConnect(
   *ppVtab = (sqlite3_vtab *)pNew;
   return rc;
 }
-/* Note that for this virtual table, the xCreate and xConnect
-** methods are identical. */
-
-static int fuzzerDisconnect(sqlite3_vtab *pVtab){
-  fuzzer_vtab *p = (fuzzer_vtab*)pVtab;
-  assert( p->nCursor==0 );
-  while( p->pRule ){
-    fuzzer_rule *pRule = p->pRule;
-    p->pRule = pRule->pNext;
-    sqlite3_free(pRule);
-  }
-  sqlite3_free(p);
-  return SQLITE_OK;
-}
-/* The xDisconnect and xDestroy methods are also the same */
-
 
 /*
 ** Open a new fuzzer cursor.
index 8e8d581a77f2de4175e92d64ca7089d223e7dd7a..89662c86fe17eb1eee30a0fec76c61098f00e0c3 100644 (file)
@@ -22,6 +22,8 @@ ifcapable !vtab {
   return
 }
 
+set ::testprefix fuzzer1
+
 register_fuzzer_module db
 
 
@@ -1538,4 +1540,182 @@ do_execsql_test fuzzer1-4.1 {
   SELECT word FROM f3 WHERE word MATCH 'ax'
 } {ax ay}
 
+#-------------------------------------------------------------------------
+#
+#  1.5.1 - Check things work with a fuzzer data table name that requires
+#          quoting. Also that NULL entries in the "from" column of the
+#          data table are treated as zero length strings ('').
+#
+#  1.5.2 - Check that no-op rules (i.e. C->C) are ignored. Test NULL in
+#          the "to" column of a fuzzer data table.
+#  
+#  1.5.3 - Test out-of-range values for the cost field of the data table.
+#
+#  1.5.4 - Test out-of-range values for the string fields of the data table.
+#
+#  1.5.5 - Test out-of-range values for the ruleset field of the data table.
+#
+do_execsql_test 5.1 {
+  CREATE TABLE "fuzzer [x] rules table"(a, b, c, d);
+  INSERT INTO "fuzzer [x] rules table" VALUES(0, NULL, 'abc', 10);
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+  SELECT word, distance FROM x WHERE word MATCH '123' LIMIT 4;
+} {123 0 abc123 10 1abc23 10 12abc3 10}
+
+do_execsql_test 5.2 {
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES(0, 'x', NULL, 20);
+  INSERT INTO "fuzzer [x] rules table" VALUES(0, NULL, NULL, 10);
+  INSERT INTO "fuzzer [x] rules table" VALUES(0, 'x', 'x', 10);
+
+  DROP TABLE x;
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+
+  SELECT word, distance FROM x WHERE word MATCH 'xx';
+} {xx 0 x 20 {} 40}
+
+do_execsql_test 5.3.1 {
+  DROP TABLE IF EXISTS x;
+  INSERT INTO "fuzzer [x] rules table" VALUES(0, 'c', 'd', 1001);
+}
+do_catchsql_test 5.3.2 {
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+} {1 {fuzzer: cost must be between 1 and 1000}}
+
+do_execsql_test 5.3.3 {
+  DROP TABLE IF EXISTS x;
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES(0, 'd', 'c', 0);
+}
+do_catchsql_test 5.3.4 {
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+} {1 {fuzzer: cost must be between 1 and 1000}}
+
+do_execsql_test 5.3.5 {
+  DROP TABLE IF EXISTS x;
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES(0, 'd', 'c', -20);
+}
+do_catchsql_test 5.3.6 {
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+} {1 {fuzzer: cost must be between 1 and 1000}}
+
+do_execsql_test 5.4.1 {
+  DROP TABLE IF EXISTS x;
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES(
+    0, 'x', '12345678901234567890123456789012345678901234567890', 2
+  );
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+  SELECT word FROM x WHERE word MATCH 'x';
+} {x 12345678901234567890123456789012345678901234567890}
+
+do_execsql_test 5.4.2 {
+  DROP TABLE IF EXISTS x;
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES(
+    0, 'x', '123456789012345678901234567890123456789012345678901', 2
+  );
+} 
+do_catchsql_test 5.4.3 {
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+} {1 {fuzzer: maximum string length is 50}}
+
+do_execsql_test 5.4.4 {
+  DROP TABLE IF EXISTS x;
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES(
+    0, '123456789012345678901234567890123456789012345678901', 'x', 2
+  );
+} 
+do_catchsql_test 5.4.5 {
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+} {1 {fuzzer: maximum string length is 50}}
+
+do_execsql_test 5.5.1 {
+  DROP TABLE IF EXISTS x;
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES(-1, 'x', 'y', 2);
+} 
+do_catchsql_test 5.5.2 {
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+} {1 {fuzzer: ruleset must be between 0 and 2147483647}}
+
+do_execsql_test 5.5.3 {
+  DROP TABLE IF EXISTS x;
+  DELETE FROM "fuzzer [x] rules table";
+  INSERT INTO "fuzzer [x] rules table" VALUES((1<<32)+100, 'x', 'y', 2);
+} 
+do_catchsql_test 5.5.4 {
+  CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
+} {1 {fuzzer: ruleset must be between 0 and 2147483647}}
+
+#-------------------------------------------------------------------------
+# This test uses a fuzzer table with many rules. There is one rule to
+# map each possible two character string, where characters are lower-case
+# letters used in the English language, to all other possible two character
+# strings. In total, (26^4)-(26^2) mappings (the subtracted term represents
+# the no-op mappings discarded automatically by the fuzzer).
+#
+#
+do_execsql_test 6.1.1 {
+  DROP TABLE IF EXISTS x1;
+  DROP TABLE IF EXISTS x1_rules;
+  CREATE TABLE x1_rules(ruleset, cFrom, cTo, cost);
+}
+puts "This test is slow - perhaps around 7 seconds on an average pc"
+do_test 6.1.2 {
+  set LETTERS {a b c d e f g h i j k l m n o p q r s t u v w x y z}
+  set cost 1
+  db transaction {
+    foreach c1 $LETTERS { 
+      foreach c2 $LETTERS { 
+        foreach c3 $LETTERS { 
+          foreach c4 $LETTERS { 
+            db eval {INSERT INTO x1_rules VALUES(0, $c1||$c2, $c3||$c4, $cost)}
+            set cost [expr ($cost%1000) + 1]
+          }
+        }
+      }
+    }
+    db eval {UPDATE x1_rules SET cost = 20 WHERE cost<20 AND cFrom!='xx'}
+  }
+} {}
+
+do_execsql_test 6.2 {
+  SELECT count(*) FROM x1_rules WHERE cTo!=cFrom;
+} [expr 26*26*26*26 - 26*26]
+
+do_execsql_test 6.2.1 {
+  CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules);
+  SELECT word FROM x1 WHERE word MATCH 'xx' LIMIT 10;
+} {xx hw hx hy hz ia ib ic id ie}
+do_execsql_test 6.2.2 {
+  SELECT cTo FROM x1_rules WHERE cFrom='xx' 
+  ORDER BY cost asc, rowid asc LIMIT 9;
+} {hw hx hy hz ia ib ic id ie}
+
+
+#-------------------------------------------------------------------------
+# Test using different types of quotes with CREATE VIRTUAL TABLE 
+# arguments.
+#
+do_execsql_test 7.1 {
+  CREATE TABLE [x2 "rules] (a, b, c, d);
+  INSERT INTO [x2 "rules] VALUES(0, 'a', 'b', 5);
+}
+foreach {tn sql} {
+  1 { CREATE VIRTUAL TABLE x2 USING fuzzer( [x2 "rules] ) }
+  2 { CREATE VIRTUAL TABLE x2 USING fuzzer( "x2 ""rules" ) }
+  3 { CREATE VIRTUAL TABLE x2 USING fuzzer( 'x2 "rules' ) }
+  4 { CREATE VIRTUAL TABLE x2 USING fuzzer( `x2 "rules` ) }
+} {
+  do_execsql_test 7.2.$tn.1 { DROP TABLE IF EXISTS x2 }
+  do_execsql_test 7.2.$tn.2 $sql
+  do_execsql_test 7.2.$tn.3 { 
+    SELECT word FROM x2 WHERE word MATCH 'aaa' 
+  } {aaa baa aba aab bab abb bba bbb}
+}
+
 finish_test
+