]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance fuzzershell to accept multiple input files. Add the test/fuzzdata2.txt
authordrh <drh@noemail.net>
Fri, 1 May 2015 19:21:12 +0000 (19:21 +0000)
committerdrh <drh@noemail.net>
Fri, 1 May 2015 19:21:12 +0000 (19:21 +0000)
fuzz test content.

FossilOrigin-Name: ab5523aafe4817232388d28ea99be0953e7dccf3

Makefile.in
Makefile.msc
main.mk
manifest
manifest.uuid
test/fuzzdata2.txt [new file with mode: 0644]
tool/fuzzershell.c

index 116f117bbb12a61ae576c8018cb5c860bd9de77c..fbf67bdf6d137b366f14ca2c888686b8374bf7b3 100644 (file)
@@ -964,7 +964,7 @@ fulltestonly:       testfixture$(TEXE) sqlite3$(TEXE)
 
 # Fuzz testing
 fuzztest:      fuzzershell$(TEXE)
-       ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt
+       ./fuzzershell$(TEXE) $(TOP)/test/fuzzdata1.txt $(TOP)/test/fuzzdata2.txt
 
 fuzzoomtest:   fuzzershell$(TEXE)
        ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt --oom
index 512de51c789bb2128e4c9f9f1314143efc299ee8..9ccc7ea5fcd57a0ae33c31da0802b298e1dd7f77 100644 (file)
@@ -1644,7 +1644,7 @@ queryplantest:    testfixture.exe sqlite3.exe
        .\testfixture.exe $(TOP)\test\permutations.test queryplanner
 
 fuzztest:      fuzzershell.exe
-       .\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt
+       .\fuzzershell.exe $(TOP)\test\fuzzdata1.txt $(TOP)\test\fuzzdata2.txt
 
 fuzzoomtest:   fuzzershell.exe
        .\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt --oom
diff --git a/main.mk b/main.mk
index 6c73fa4943d1be7188fae2820586c09061559beb..53eff03012c3dfb5763b49ed72fefea72e07c570 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -646,7 +646,7 @@ queryplantest:      testfixture$(EXE) sqlite3$(EXE)
        ./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner
 
 fuzztest:      fuzzershell$(EXE)
-       ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt
+       ./fuzzershell$(EXE) $(TOP)/test/fuzzdata1.txt $(TOP)/test/fuzzdata2.txt
 
 fuzzoomtest:   fuzzershell$(EXE)
        ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt --oom
index a069ec6ab1837d883ef42467c49131e38937b2e4..db9d4f7a21ca94c184cb64a89053f12159934e83 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Fix\san\sassert\sin\sRTREE\sthat\swould\sfire\sif\sthe\srtree\stable\sis\smisdeclared.
-D 2015-05-01T18:00:37.511
+C Enhance\sfuzzershell\sto\saccept\smultiple\sinput\sfiles.\s\sAdd\sthe\stest/fuzzdata2.txt\nfuzz\stest\scontent.
+D 2015-05-01T19:21:12.995
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
-F Makefile.in e3268d234210842b4be0a6e2e1c5990999f1d9f4
+F Makefile.in e628c50e237251fc7e768bef14ee7e822ad69e69
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
-F Makefile.msc d80278757ef0b02d797d6ab98e07baf9c608b1a2
+F Makefile.msc 4c7e6fc40c5b65134b789b18b83743abac907504
 F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
 F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
 F VERSION 2e244662b71e6e68a5c29b014ebc5b7564f4cc5a
@@ -152,7 +152,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk c0c7503b9749c1532c1e0e9501331abc1afc299d
+F main.mk 1225d45e1883000a3ed6f028893a11c04522ea6a
 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
 F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -632,6 +632,7 @@ F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
 F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
 F test/fuzzdata1.txt 9fceb50868e0b798160e83742bd7e44e457176a0
+F test/fuzzdata2.txt ba9b4467d7ec46cc85d32c0d031540cd727ae6ad
 F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -1207,7 +1208,7 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
 F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
 F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
 F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
-F tool/fuzzershell.c 2799d1e74c48a7fbbfc4889601005d42d1e237a5
+F tool/fuzzershell.c 32816d2c54e7243504ab8af6d9b4323ed1206342
 F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
@@ -1255,7 +1256,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 40db3e40126db1035fcc12989026915744dc5651
-R d52749e43e60b570f31909140ed0a510
+P 9a45409cc4078f2b6e68aa777f6ab86a14309833
+R 3a133cb00e1f62fffce773de23d1e308
 U drh
-Z 292f5446ecb0ed9f640d81ad4e3c067d
+Z 8894bd22b6f91dc8094aac398d313abb
index 8283d0b2ef075ac2163944cfd46707ef47267b2f..2765b25987c01c0bb8db6406fb6b3610ef618557 100644 (file)
@@ -1 +1 @@
-9a45409cc4078f2b6e68aa777f6ab86a14309833
\ No newline at end of file
+ab5523aafe4817232388d28ea99be0953e7dccf3
\ No newline at end of file
diff --git a/test/fuzzdata2.txt b/test/fuzzdata2.txt
new file mode 100644 (file)
index 0000000..b1d4bb7
Binary files /dev/null and b/test/fuzzdata2.txt differ
index a464e6873ac3086e40c3cf775897418930e6208b..546458a73102223687fa4f58b044faff4f95b4d7 100644 (file)
@@ -315,15 +315,14 @@ static void sqlEvalFunc(
 ** Print sketchy documentation for this utility program
 */
 static void showHelp(void){
-  printf("Usage: %s [options]\n", g.zArgv0);
+  printf("Usage: %s [options] ?FILE...?\n", g.zArgv0);
   printf(
-"Read SQL text from standard input and evaluate it.\n"
+"Read SQL text from FILE... (or from standard input if FILE... is omitted)\n"
+"and then evaluate each block of SQL contained therein.\n"
 "Options:\n"
 "  --autovacuum          Enable AUTOVACUUM mode\n"
-"  -f FILE               Read SQL text from FILE instead of standard input\n"
 "  --heap SZ MIN         Memory allocator uses SZ bytes & min allocation MIN\n"
 "  --help                Show this help text\n"    
-"  --initdb DBFILE       Initialize the in-memory database using template DBFILE\n"
 "  --lookaside N SZ      Configure lookaside for N slots of SZ bytes each\n"
 "  --oom                 Run each test multiple times in a simulated OOM loop\n"
 "  --pagesize N          Set the page size to N\n"
@@ -397,28 +396,17 @@ static int integerValue(const char *zArg){
   return (int)(isNeg? -v : v);
 }
 
-/*
-** Various operating modes
-*/
-#define FZMODE_Generic   1
-#define FZMODE_Strftime  2
-#define FZMODE_Printf    3
-#define FZMODE_Glob      4
-
 
 int main(int argc, char **argv){
-  char *zIn = 0;          /* Input text */
-  int nAlloc = 0;         /* Number of bytes allocated for zIn[] */
-  int nIn = 0;            /* Number of bytes of zIn[] used */
-  size_t got;             /* Bytes read from input */
-  FILE *in = stdin;       /* Where to read SQL text from */
-  int rc = SQLITE_OK;     /* Result codes from API functions */
-  int i;                  /* Loop counter */
-  int iNext;              /* Next block of SQL */
-  sqlite3 *db;            /* Open database */
-  sqlite3 *dbInit = 0;    /* On-disk database used to initialize the in-memory db */
-  const char *zInitDb = 0;/* Name of the initialization database file */
-  char *zErrMsg = 0;      /* Error message returned from sqlite3_exec() */
+  char *zIn = 0;                /* Input text */
+  int nAlloc = 0;               /* Number of bytes allocated for zIn[] */
+  int nIn = 0;                  /* Number of bytes of zIn[] used */
+  size_t got;                   /* Bytes read from input */
+  int rc = SQLITE_OK;           /* Result codes from API functions */
+  int i;                        /* Loop counter */
+  int iNext;                    /* Next block of SQL */
+  sqlite3 *db;                  /* Open database */
+  char *zErrMsg = 0;            /* Error message returned from sqlite3_exec() */
   const char *zEncoding = 0;    /* --utf16be or --utf16le */
   int nHeap = 0, mnHeap = 0;    /* Heap size from --heap */
   int nLook = 0, szLook = 0;    /* --lookaside configuration */
@@ -432,7 +420,6 @@ int main(int argc, char **argv){
   int doAutovac = 0;            /* True for --autovacuum */
   char *zSql;                   /* SQL to run */
   char *zToFree = 0;            /* Call sqlite3_free() on this afte running zSql */
-  int iMode = FZMODE_Generic;   /* Operating mode */
   const char *zCkGlob = 0;      /* Inputs must match this glob */
   int verboseFlag = 0;          /* --verbose or -v flag */
   int quietFlag = 0;            /* --quiet or -q flag */
@@ -447,10 +434,15 @@ int main(int argc, char **argv){
   int oomCnt = 0;               /* Counter for the OOM loop */
   char zErrBuf[200];            /* Space for the error message */
   const char *zFailCode;        /* Value of the TEST_FAILURE environment var */
+  const char *zPrompt;          /* Initial prompt when large-file fuzzing */
+  int nInFile = 0;              /* Number of input files to read */
+  char **azInFile = 0;          /* Array of input file names */
+  int jj;                       /* Loop counter for azInFile[] */
 
 
   zFailCode = getenv("TEST_FAILURE");
   g.zArgv0 = argv[0];
+  zPrompt = "<stdin>";
   for(i=1; i<argc; i++){
     const char *z = argv[i];
     if( z[0]=='-' ){
@@ -460,9 +452,8 @@ int main(int argc, char **argv){
         doAutovac = 1;
       }else
       if( strcmp(z, "f")==0 && i+1<argc ){
-        if( in!=stdin ) abendError("only one -f allowed");
-        in = fopen(argv[++i],"rb");
-        if( in==0 )  abendError("cannot open input file \"%s\"", argv[i]);
+        i++;
+        goto addNewInFile;
       }else
       if( strcmp(z,"heap")==0 ){
         if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
@@ -474,35 +465,12 @@ int main(int argc, char **argv){
         showHelp();
         return 0;
       }else
-      if( strcmp(z, "initdb")==0 && i+1<argc ){
-        if( zInitDb!=0 ) abendError("only one --initdb allowed");
-        zInitDb = argv[++i];
-      }else
       if( strcmp(z,"lookaside")==0 ){
         if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
         nLook = integerValue(argv[i+1]);
         szLook = integerValue(argv[i+2]);
         i += 2;
       }else
-      if( strcmp(z,"mode")==0 ){
-        if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
-        z = argv[++i];
-        if( strcmp(z,"generic")==0 ){
-          iMode = FZMODE_Printf;
-          zCkGlob = 0;
-        }else if( strcmp(z, "glob")==0 ){
-          iMode = FZMODE_Glob;
-          zCkGlob = "'*','*'";
-        }else if( strcmp(z, "printf")==0 ){
-          iMode = FZMODE_Printf;
-          zCkGlob = "'*',*";
-        }else if( strcmp(z, "strftime")==0 ){
-          iMode = FZMODE_Strftime;
-          zCkGlob = "'*',*";
-        }else{
-          abendError("unknown --mode: %s", z);
-        }
-      }else
       if( strcmp(z,"oom")==0 ){
         oomFlag = 1;
       }else
@@ -545,9 +513,15 @@ int main(int argc, char **argv){
         abendError("unknown option: %s", argv[i]);
       }
     }else{
-      abendError("unknown argument: %s", argv[i]);
+      addNewInFile:
+      nInFile++;
+      azInFile = realloc(azInFile, sizeof(azInFile[0])*nInFile);
+      if( azInFile==0 ) abendError("out of memory");
+      azInFile[nInFile-1] = argv[i];
     }
   }
+
+  /* Do global SQLite initialization */
   sqlite3_config(SQLITE_CONFIG_LOG, verboseFlag ? shellLog : shellLogNoop, 0);
   if( nHeap>0 ){
     pHeap = malloc( nHeap );
@@ -583,209 +557,245 @@ int main(int argc, char **argv){
     rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
     if( rc ) abendError("pcache configuration failed: %d", rc);
   }
-  while( !feof(in) ){
-    nAlloc += nAlloc+1000;
-    zIn = realloc(zIn, nAlloc);
-    if( zIn==0 ) fatalError("out of memory");
-    got = fread(zIn+nIn, 1, nAlloc-nIn-1, in); 
-    nIn += (int)got;
-    zIn[nIn] = 0;
-    if( got==0 ) break;
-  }
-  if( in!=stdin ) fclose(in);
+
+  /* If the --unique-cases option was supplied, open the database that will
+  ** be used to gather unique test cases.
+  */
   if( zDataOut ){
     rc = sqlite3_open(":memory:", &dataDb);
     if( rc ) abendError("cannot open :memory: database");
     rc = sqlite3_exec(dataDb,
           "CREATE TABLE testcase(sql BLOB PRIMARY KEY) WITHOUT ROWID;",0,0,0);
     if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
-    rc = sqlite3_prepare_v2(dataDb, "INSERT OR IGNORE INTO testcase(sql)VALUES(?1)",
-                            -1, &pStmt, 0);
+    rc = sqlite3_prepare_v2(dataDb,
+          "INSERT OR IGNORE INTO testcase(sql)VALUES(?1)",
+          -1, &pStmt, 0);
     if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
   }
-  if( zInitDb ){
-    rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
-    if( rc!=SQLITE_OK ){
-      abendError("unable to open initialization database \"%s\"", zInitDb);
-    }
-  }
-  for(i=0; i<nIn; i=iNext+1){   /* Skip initial lines beginning with '#' */
-    if( zIn[i]!='#' ) break;
-    for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
-  }
-  nHeader = i;
-  for(nTest=0; i<nIn; i=iNext, nTest++, g.zTestName[0]=0){
-    char cSaved;
-    if( strncmp(&zIn[i], "/****<",6)==0 ){
-      char *z = strstr(&zIn[i], ">****/");
-      if( z ){
-        z += 6;
-        sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s", 
-                         (int)(z-&zIn[i]) - 12, &zIn[i+6]);
-        if( verboseFlag ){
-          printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
-          fflush(stdout);
-        }
-        i += (int)(z-&zIn[i]);
-        multiTest = 1;
+
+  /* Initialize the input buffer used to hold SQL text */
+  if( nInFile==0 ) nInFile = 1;
+  nAlloc = 1000;
+  zIn = malloc(nAlloc);
+  if( zIn==0 ) fatalError("out of memory");
+
+  /* Loop over all input files */
+  for(jj=0; jj<nInFile; jj++){
+
+    /* Read the complete content of the next input file into zIn[] */
+    FILE *in;
+    if( azInFile ){
+      int j, k;
+      in = fopen(azInFile[jj],"rb");
+      if( in==0 ){
+        abendError("cannot open %s for reading", azInFile[jj]);
       }
+      zPrompt = azInFile[jj];
+      for(j=k=0; zPrompt[j]; j++) if( zPrompt[j]=='/' ) k = j+1;
+      zPrompt += k;
+    }else{
+      in = stdin;
+      zPrompt = "<stdin>";
     }
-    for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
-    if( zDataOut ){
-      sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
-      rc = sqlite3_step(pStmt);
-      if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
-      sqlite3_reset(pStmt);
-      continue;
+    while( !feof(in) ){
+      zIn = realloc(zIn, nAlloc);
+      if( zIn==0 ) fatalError("out of memory");
+      got = fread(zIn+nIn, 1, nAlloc-nIn-1, in); 
+      nIn += (int)got;
+      zIn[nIn] = 0;
+      if( got==0 ) break;
+      nAlloc += nAlloc+1000;
     }
-    cSaved = zIn[iNext];
-    zIn[iNext] = 0;
-    if( zCkGlob && sqlite3_strglob(zCkGlob,&zIn[i])!=0 ){
-      zIn[iNext] = cSaved;
-      continue;
+    if( in!=stdin ) fclose(in);
+    lastPct = -1;
+
+    /* Skip initial lines of the input file that begin with "#" */
+    for(i=0; i<nIn; i=iNext+1){
+      if( zIn[i]!='#' ) break;
+      for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
     }
-    zSql = &zIn[i];
-    if( verboseFlag ){
-      printf("INPUT (offset: %d, size: %d): [%s]\n",
-              i, (int)strlen(&zIn[i]), &zIn[i]);
-    }else if( multiTest && !quietFlag ){
-      if( oomFlag ){
-        printf("%s\n", g.zTestName);
-      }else{
-        int pct = (10*iNext)/nIn;
-        if( pct!=lastPct ){
-          if( lastPct<0 ) printf("fuzz test:");
-          printf(" %d%%", pct*10);
-          lastPct = pct;
+    nHeader = i;
+
+    /* Process all test cases contained within the input file.
+    */
+    for(; i<nIn; i=iNext, nTest++, g.zTestName[0]=0){
+      char cSaved;
+      if( strncmp(&zIn[i], "/****<",6)==0 ){
+        char *z = strstr(&zIn[i], ">****/");
+        if( z ){
+          z += 6;
+          sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s", 
+                           (int)(z-&zIn[i]) - 12, &zIn[i+6]);
+          if( verboseFlag ){
+            printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
+            fflush(stdout);
+          }
+          i += (int)(z-&zIn[i]);
+          multiTest = 1;
         }
       }
-    }
-    fflush(stdout);
-    switch( iMode ){
-      case FZMODE_Glob:
-        zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
-        break;
-      case FZMODE_Printf:
-        zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
-        break;
-      case FZMODE_Strftime:
-        zSql = zToFree = sqlite3_mprintf("SELECT strftime(%s);", zSql);
-        break;
-    }
-    if( oomFlag ){
-      oomCnt = g.iOomCntdown = 1;
-      g.nOomFault = 0;
-      g.bOomOnce = 1;
-      if( verboseFlag ){
-        printf("Once.%d\n", oomCnt);
-        fflush(stdout);
+      for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
+
+      /* Store unique test cases in the in the dataDb database if the
+      ** --unique-cases flag is present
+      */
+      if( zDataOut ){
+        sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
+        rc = sqlite3_step(pStmt);
+        if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
+        sqlite3_reset(pStmt);
+        continue;
       }
-    }else{
-      oomCnt = 0;
-    }
-    do{
-      rc = sqlite3_open_v2(
-        "main.db", &db,
-        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
-        0);
-      if( rc!=SQLITE_OK ){
-        abendError("Unable to open the in-memory database");
+      cSaved = zIn[iNext];
+      zIn[iNext] = 0;
+      if( zCkGlob && sqlite3_strglob(zCkGlob,&zIn[i])!=0 ){
+        zIn[iNext] = cSaved;
+        continue;
       }
-      if( pLook ){
-        rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook, nLook);
-        if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
+
+      /* Print out the SQL of the next test case is --verbose is enabled
+      */
+      zSql = &zIn[i];
+      if( verboseFlag ){
+        printf("INPUT (offset: %d, size: %d): [%s]\n",
+                i, (int)strlen(&zIn[i]), &zIn[i]);
+      }else if( multiTest && !quietFlag ){
+        if( oomFlag ){
+          printf("%s\n", g.zTestName);
+        }else{
+          int pct = (10*iNext)/nIn;
+          if( pct!=lastPct ){
+            if( lastPct<0 ) printf("%s:", zPrompt);
+            printf(" %d%%", pct*10);
+            lastPct = pct;
+          }
+        }
       }
-      if( zInitDb ){
-        sqlite3_backup *pBackup;
-        pBackup = sqlite3_backup_init(db, "main", dbInit, "main");
-        rc = sqlite3_backup_step(pBackup, -1);
-        if( rc!=SQLITE_DONE ){
-          abendError("attempt to initialize the in-memory database failed (rc=%d)",
-                     rc);
+      fflush(stdout);
+
+      /* Run the next test case.  Run it multiple times in --oom mode
+      */
+      if( oomFlag ){
+        oomCnt = g.iOomCntdown = 1;
+        g.nOomFault = 0;
+        g.bOomOnce = 1;
+        if( verboseFlag ){
+          printf("Once.%d\n", oomCnt);
+          fflush(stdout);
         }
-        sqlite3_backup_finish(pBackup);
+      }else{
+        oomCnt = 0;
       }
-  #ifndef SQLITE_OMIT_TRACE
-      sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
-  #endif
-      sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
-      sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
-      sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
-      if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
-      if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
-      if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
-      g.bOomEnable = 1;
-      if( verboseFlag ){
-        zErrMsg = 0;
-        rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
-        if( zErrMsg ){
-          sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg);
+      do{
+        rc = sqlite3_open_v2(
+          "main.db", &db,
+          SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
+          0);
+        if( rc!=SQLITE_OK ){
+          abendError("Unable to open the in-memory database");
+        }
+        if( pLook ){
+          rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
+          if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
+        }
+    #ifndef SQLITE_OMIT_TRACE
+        sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
+    #endif
+        sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
+        sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
+        sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
+        if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
+        if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
+        if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
+        g.bOomEnable = 1;
+        if( verboseFlag ){
           zErrMsg = 0;
+          rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
+          if( zErrMsg ){
+            sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg);
+            zErrMsg = 0;
+          }
+        }else {
+          rc = sqlite3_exec(db, zSql, execNoop, 0, 0);
         }
-      }else {
-        rc = sqlite3_exec(db, zSql, execNoop, 0, 0);
-      }
-      g.bOomEnable = 0;
-      rc = sqlite3_close(db);
-      if( rc ){
-        abendError("sqlite3_close() failed with rc=%d", rc);
-      }
-      if( sqlite3_memory_used()>0 ){
-        abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
-      }
-      if( oomFlag ){
-        /* Limit the number of iterations of the OOM loop to OOM_MAX.  If the
-        ** first pass (single failure) exceeds 2/3rds of OOM_MAX this skip the
-        ** second pass (continuous failure after first) completely. */
-        if( g.nOomFault==0 || oomCnt>OOM_MAX ){
-          if( g.bOomOnce && oomCnt<=(OOM_MAX*2/3) ){
-            oomCnt = g.iOomCntdown = 1;
-            g.bOomOnce = 0;
+        g.bOomEnable = 0;
+        rc = sqlite3_close(db);
+        if( rc ){
+          abendError("sqlite3_close() failed with rc=%d", rc);
+        }
+        if( sqlite3_memory_used()>0 ){
+          abendError("memory in use after close: %lld bytes",sqlite3_memory_used());
+        }
+        if( oomFlag ){
+          /* Limit the number of iterations of the OOM loop to OOM_MAX.  If the
+          ** first pass (single failure) exceeds 2/3rds of OOM_MAX this skip the
+          ** second pass (continuous failure after first) completely. */
+          if( g.nOomFault==0 || oomCnt>OOM_MAX ){
+            if( g.bOomOnce && oomCnt<=(OOM_MAX*2/3) ){
+              oomCnt = g.iOomCntdown = 1;
+              g.bOomOnce = 0;
+            }else{
+              oomCnt = 0;
+            }
           }else{
-            oomCnt = 0;
+            g.iOomCntdown = ++oomCnt;
+            g.nOomFault = 0;
           }
-        }else{
-          g.iOomCntdown = ++oomCnt;
-          g.nOomFault = 0;
-        }
-        if( oomCnt ){
-          if( verboseFlag ){
-            printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt);
-            fflush(stdout);
+          if( oomCnt ){
+            if( verboseFlag ){
+              printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt);
+              fflush(stdout);
+            }
+            nTest++;
           }
-          nTest++;
         }
+      }while( oomCnt>0 );
+
+      /* Free the SQL from the current test case
+      */
+      if( zToFree ){
+        sqlite3_free(zToFree);
+        zToFree = 0;
       }
-    }while( oomCnt>0 );
-    if( zToFree ){
-      sqlite3_free(zToFree);
-      zToFree = 0;
-    }
-    zIn[iNext] = cSaved;
-    if( verboseFlag ){
-      printf("RESULT-CODE: %d\n", rc);
-      if( zErrMsg ){
-        printf("ERROR-MSG: [%s]\n", zErrBuf);
+      zIn[iNext] = cSaved;
+
+      /* Show test-case results in --verbose mode
+      */
+      if( verboseFlag ){
+        printf("RESULT-CODE: %d\n", rc);
+        if( zErrMsg ){
+          printf("ERROR-MSG: [%s]\n", zErrBuf);
+        }
+        fflush(stdout);
       }
-      fflush(stdout);
-    }
-    /* Simulate an error if the TEST_FAILURE environment variable is "5" */
-    if( zFailCode ){
-      if( zFailCode[0]=='5' && zFailCode[1]==0 ){
-        abendError("simulated failure");
-      }else if( zFailCode[0]!=0 ){
-        /* If TEST_FAILURE is something other than 5, just exit the test
-        ** early */
-        printf("\nExit early due to TEST_FAILURE being set");
-        break;
+
+      /* Simulate an error if the TEST_FAILURE environment variable is "5".
+      ** This is used to verify that automated test script really do spot
+      ** errors that occur in this test program.
+      */
+      if( zFailCode ){
+        if( zFailCode[0]=='5' && zFailCode[1]==0 ){
+          abendError("simulated failure");
+        }else if( zFailCode[0]!=0 ){
+          /* If TEST_FAILURE is something other than 5, just exit the test
+          ** early */
+          printf("\nExit early due to TEST_FAILURE being set");
+          break;
+        }
       }
     }
+    if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n");
   }
-  if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n");
+
+  /* Report total number of tests run
+  */
   if( nTest>1 && !quietFlag ){
     printf("%s: 0 errors out of %d tests\nSQLite %s %s\n",
            g.zArgv0, nTest, sqlite3_libversion(), sqlite3_sourceid());
   }
+
+  /* Write the unique test cases if the --unique-cases flag was used
+  */
   if( zDataOut ){
     int n = 0;
     FILE *out = fopen(zDataOut, "wb");
@@ -802,6 +812,10 @@ int main(int argc, char **argv){
     sqlite3_finalize(pStmt);
     sqlite3_close(dataDb);
   }
+
+  /* Clean up and exit.
+  */
+  free(azInFile);
   free(zIn);
   free(pHeap);
   free(pLook);