SQLite

Check-in [c415bb7bbf]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the --result-trace option to fuzzcheck, and other interface enhancements.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c415bb7bbfd531b138462589cdd58fa0204804e8
User & Date: drh 2015-05-26 00:28:08.697
Context
2015-05-26
03:24
Add fuzzcheck to makefile clean targets. Also, for consistency, replace a few tabs with spaces. (check-in: eda2a43750 user: mistachkin tags: trunk)
00:28
Add the --result-trace option to fuzzcheck, and other interface enhancements. (check-in: c415bb7bbf user: drh tags: trunk)
2015-05-25
23:14
Fix an important bug in the xRead method of the in-memory VFS for fuzzcheck. (check-in: 58cd40e89f user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to test/fuzzcheck.c.
62
63
64
65
66
67
68

69
70
71
72
73
74
75
/*
** The value of a database file template, or of an SQL script
*/
typedef struct Blob Blob;
struct Blob {
  Blob *pNext;            /* Next in a list */
  int id;                 /* Id of this Blob */

  int sz;                 /* Size of this Blob in bytes */
  unsigned char a[1];     /* Blob content.  Extra space allocated as needed. */
};

/*
** Maximum number of files in the in-memory virtual filesystem.
*/







>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
** The value of a database file template, or of an SQL script
*/
typedef struct Blob Blob;
struct Blob {
  Blob *pNext;            /* Next in a list */
  int id;                 /* Id of this Blob */
  int seq;                /* Sequence number */
  int sz;                 /* Size of this Blob in bytes */
  unsigned char a[1];     /* Blob content.  Extra space allocated as needed. */
};

/*
** Maximum number of files in the in-memory virtual filesystem.
*/
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
268
269
270
271
272
  head.pNext = 0;
  p = &head;
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    int sz = sqlite3_column_bytes(pStmt, 1);
    Blob *pNew = safe_realloc(0, sizeof(*pNew)+sz );
    pNew->id = sqlite3_column_int(pStmt, 0);
    pNew->sz = sz;

    pNew->pNext = 0;
    memcpy(pNew->a, sqlite3_column_blob(pStmt,1), sz);
    pNew->a[sz] = 0;
    p->pNext = pNew;
    p = pNew;
    n++;
  }
  sqlite3_finalize(pStmt);
  *pN = n;
  *ppList = head.pNext;
}

/*







>





<







254
255
256
257
258
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
  head.pNext = 0;
  p = &head;
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    int sz = sqlite3_column_bytes(pStmt, 1);
    Blob *pNew = safe_realloc(0, sizeof(*pNew)+sz );
    pNew->id = sqlite3_column_int(pStmt, 0);
    pNew->sz = sz;
    pNew->seq = n++;
    pNew->pNext = 0;
    memcpy(pNew->a, sqlite3_column_blob(pStmt,1), sz);
    pNew->a[sz] = 0;
    p->pNext = pNew;
    p = pNew;

  }
  sqlite3_finalize(pStmt);
  *pN = n;
  *ppList = head.pNext;
}

/*
502
503
504
505
506
507
508






509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

537





































538
539
540
541
542
543
544
  inmemVfs.xRandomness = pDefault->xRandomness;
  inmemVfs.xSleep = pDefault->xSleep;
  inmemVfs.xCurrentTime = pDefault->xCurrentTime;
  inmemVfs.xGetLastError = inmemGetLastError;
  sqlite3_vfs_register(&inmemVfs, 0);
};







/*
** Run multiple commands of SQL.  Similar to sqlite3_exec(), but does not
** stop if an error is encountered.
*/
static void runSql(sqlite3 *db, const char *zSql, int traceFlag){
  const char *zMore;
  sqlite3_stmt *pStmt;

  while( zSql && zSql[0] ){
    zMore = 0;
    pStmt = 0;
    sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore);
    if( zMore==zSql ) break;
    if( traceFlag ){
      const char *z = zSql;
      int n;
      while( z<zMore && isspace(z[0]) ) z++;
      n = (int)(zMore - z);
      while( n>0 && isspace(z[n-1]) ) n--;
      if( n==0 ) break;
      if( pStmt==0 ){
        printf("TRACE: %.*s (error: %s)\n", n, z, sqlite3_errmsg(db));
      }else{
        printf("TRACE: %.*s\n", n, z);
      }
    }
    zSql = zMore;
    if( pStmt ){

      while( SQLITE_ROW==sqlite3_step(pStmt) ){}





































      sqlite3_finalize(pStmt);
    }
  }
}

/*
** Print sketchy documentation for this utility program







>
>
>
>
>
>




|








|














>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  inmemVfs.xRandomness = pDefault->xRandomness;
  inmemVfs.xSleep = pDefault->xSleep;
  inmemVfs.xCurrentTime = pDefault->xCurrentTime;
  inmemVfs.xGetLastError = inmemGetLastError;
  sqlite3_vfs_register(&inmemVfs, 0);
};

/*
** Allowed values for the runFlags parameter to runSql()
*/
#define SQL_TRACE  0x0001     /* Print each SQL statement as it is prepared */
#define SQL_OUTPUT 0x0002     /* Show the SQL output */

/*
** Run multiple commands of SQL.  Similar to sqlite3_exec(), but does not
** stop if an error is encountered.
*/
static void runSql(sqlite3 *db, const char *zSql, unsigned  runFlags){
  const char *zMore;
  sqlite3_stmt *pStmt;

  while( zSql && zSql[0] ){
    zMore = 0;
    pStmt = 0;
    sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore);
    if( zMore==zSql ) break;
    if( runFlags & SQL_TRACE ){
      const char *z = zSql;
      int n;
      while( z<zMore && isspace(z[0]) ) z++;
      n = (int)(zMore - z);
      while( n>0 && isspace(z[n-1]) ) n--;
      if( n==0 ) break;
      if( pStmt==0 ){
        printf("TRACE: %.*s (error: %s)\n", n, z, sqlite3_errmsg(db));
      }else{
        printf("TRACE: %.*s\n", n, z);
      }
    }
    zSql = zMore;
    if( pStmt ){
      if( (runFlags & SQL_OUTPUT)==0 ){
        while( SQLITE_ROW==sqlite3_step(pStmt) ){}
      }else{
        int nCol = -1;
        while( SQLITE_ROW==sqlite3_step(pStmt) ){
          int i;
          if( nCol<0 ){
            nCol = sqlite3_column_count(pStmt);
          }else if( nCol>0 ){
            printf("--------------------------------------------\n");
          }
          for(i=0; i<nCol; i++){
            int eType = sqlite3_column_type(pStmt,i);
            printf("%s = ", sqlite3_column_name(pStmt,i));
            switch( eType ){
              case SQLITE_NULL: {
                printf("NULL\n");
                break;
              }
              case SQLITE_INTEGER: {
                printf("INT %s\n", sqlite3_column_text(pStmt,i));
                break;
              }
              case SQLITE_FLOAT: {
                printf("FLOAT %s\n", sqlite3_column_text(pStmt,i));
                break;
              }
              case SQLITE_TEXT: {
                printf("TEXT [%s]\n", sqlite3_column_text(pStmt,i));
                break;
              }
              case SQLITE_BLOB: {
                printf("BLOB (%d bytes)\n", sqlite3_column_bytes(pStmt,i));
                break;
              }
            }
          }
        }
      }         
      sqlite3_finalize(pStmt);
    }
  }
}

/*
** Print sketchy documentation for this utility program
552
553
554
555
556
557
558

559
560
561
562
563
564
565
"  --dbid N              Use only the database where dbid=N\n"
"  --help                Show this help text\n"    
"  -q                    Reduced output\n"
"  --quiet               Reduced output\n"
"  --load-sql ARGS...    Load SQL scripts fro files into SOURCE-DB\n"
"  --load-db ARGS...     Load template databases from files into SOURCE_DB\n"
"  --native-vfs          Use the native VFS for initially empty database files\n"

"  --sqlid N             Use only SQL where sqlid=N\n"
"  -v                    Increased output\n"
"  --verbose             Increased output\n"
  );
}

int main(int argc, char **argv){







>







597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
"  --dbid N              Use only the database where dbid=N\n"
"  --help                Show this help text\n"    
"  -q                    Reduced output\n"
"  --quiet               Reduced output\n"
"  --load-sql ARGS...    Load SQL scripts fro files into SOURCE-DB\n"
"  --load-db ARGS...     Load template databases from files into SOURCE_DB\n"
"  --native-vfs          Use the native VFS for initially empty database files\n"
"  --result-trace        Show the results of each SQL command\n"
"  --sqlid N             Use only SQL where sqlid=N\n"
"  -v                    Increased output\n"
"  --verbose             Increased output\n"
  );
}

int main(int argc, char **argv){
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611



612
613
614
615
616
617
618
619

620
621
622
623
624
625
626
  int rc;                      /* Result code from SQLite interface calls */
  Blob *pSql;                  /* For looping over SQL scripts */
  Blob *pDb;                   /* For looping over template databases */
  int i;                       /* Loop index for the argv[] loop */
  int onlySqlid = -1;          /* --sqlid */
  int onlyDbid = -1;           /* --dbid */
  int nativeFlag = 0;          /* --native-vfs */


  iBegin = timeOfDay();
  g.zArgv0 = argv[0];
  for(i=1; i<argc; i++){
    const char *z = argv[i];
    if( z[0]=='-' ){
      z++;
      if( z[0]=='-' ) z++;
      if( strcmp(z,"dbid")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlyDbid = atoi(argv[++i]);
      }else
      if( strcmp(z,"help")==0 ){
        showHelp();
        return 0;
      }else
      if( strcmp(z,"load-sql")==0 ){
        zInsSql = "INSERT INTO xsql(sqltext) VALUES(readfile(?1))";
        iFirstInsArg = i+1;
        break;
      }else
      if( strcmp(z,"load-db")==0 ){
        zInsSql = "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
        iFirstInsArg = i+1;
        break;
      }else
      if( strcmp(z,"native-vfs")==0 ){
        nativeFlag = 1;
      }else
      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
        quietFlag = 1;
        verboseFlag = 0;



      }else
      if( strcmp(z,"sqlid")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlySqlid = atoi(argv[++i]);
      }else
      if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
        quietFlag = 0;
        verboseFlag = 1;

      }else
      {
        fatalError("unknown option: %s", argv[i]);
      }
    }else{
      if( zSourceDb ) fatalError("extra argument: %s", argv[i]);
      zSourceDb = argv[i];







>

















|














>
>
>








>







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
  int rc;                      /* Result code from SQLite interface calls */
  Blob *pSql;                  /* For looping over SQL scripts */
  Blob *pDb;                   /* For looping over template databases */
  int i;                       /* Loop index for the argv[] loop */
  int onlySqlid = -1;          /* --sqlid */
  int onlyDbid = -1;           /* --dbid */
  int nativeFlag = 0;          /* --native-vfs */
  int runFlags = 0;            /* Flags sent to runSql() */

  iBegin = timeOfDay();
  g.zArgv0 = argv[0];
  for(i=1; i<argc; i++){
    const char *z = argv[i];
    if( z[0]=='-' ){
      z++;
      if( z[0]=='-' ) z++;
      if( strcmp(z,"dbid")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlyDbid = atoi(argv[++i]);
      }else
      if( strcmp(z,"help")==0 ){
        showHelp();
        return 0;
      }else
      if( strcmp(z,"load-sql")==0 ){
        zInsSql = "INSERT INTO xsql(sqltext) VALUES(CAST(readfile(?1) AS text))";
        iFirstInsArg = i+1;
        break;
      }else
      if( strcmp(z,"load-db")==0 ){
        zInsSql = "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
        iFirstInsArg = i+1;
        break;
      }else
      if( strcmp(z,"native-vfs")==0 ){
        nativeFlag = 1;
      }else
      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
        quietFlag = 1;
        verboseFlag = 0;
      }else
      if( strcmp(z,"result-trace")==0 ){
        runFlags |= SQL_OUTPUT;
      }else
      if( strcmp(z,"sqlid")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlySqlid = atoi(argv[++i]);
      }else
      if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
        quietFlag = 0;
        verboseFlag = 1;
        runFlags |= SQL_TRACE;
      }else
      {
        fatalError("unknown option: %s", argv[i]);
      }
    }else{
      if( zSourceDb ) fatalError("extra argument: %s", argv[i]);
      zSourceDb = argv[i];
672
673
674
675
676
677
678

679
680
681
682
683
684
685
  if( g.nSql==0 ) fatalError("need at least one SQL script");
  blobListLoadFromDb(db, "SELECT dbid, dbcontent FROM db", onlyDbid,
                     &g.nDb, &g.pFirstDb);
  if( g.nDb==0 ){
    g.pFirstDb = safe_realloc(0, sizeof(Blob));
    memset(g.pFirstDb, 0, sizeof(Blob));
    g.pFirstDb->id = 1;

    g.nDb = 1;
  }
    

  /* Close the source database.  Verify that no SQLite memory allocations are
  ** outstanding.
  */







>







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
  if( g.nSql==0 ) fatalError("need at least one SQL script");
  blobListLoadFromDb(db, "SELECT dbid, dbcontent FROM db", onlyDbid,
                     &g.nDb, &g.pFirstDb);
  if( g.nDb==0 ){
    g.pFirstDb = safe_realloc(0, sizeof(Blob));
    memset(g.pFirstDb, 0, sizeof(Blob));
    g.pFirstDb->id = 1;
    g.pFirstDb->seq = 0;
    g.nDb = 1;
  }
    

  /* Close the source database.  Verify that no SQLite memory allocations are
  ** outstanding.
  */
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
      sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
                       pSql->id, pDb->id);
      if( verboseFlag ){
        printf("%s\n", g.zTestName);
        fflush(stdout);
      }else if( !quietFlag ){
        static int prevAmt = -1;
        int idx = (pSql->id-1)*g.nDb + pDb->id - 1;
        int amt = idx*10/(g.nDb*g.nSql);
        if( amt!=prevAmt ){
          printf(" %d%%", amt*10);
          fflush(stdout);
          prevAmt = amt;
        }
      }
      createVFile("main.db", pDb->sz, pDb->a);
      openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
      if( nativeFlag && pDb->sz==0 ){
        openFlags |= SQLITE_OPEN_MEMORY;
        zVfs = 0;
      }
      rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
      if( rc ) fatalError("cannot open inmem database");
      runSql(db, (char*)pSql->a, verboseFlag);
      sqlite3_close(db);
      if( sqlite3_memory_used()>0 ) fatalError("memory leak");
      reformatVfs();
      g.zTestName[0] = 0;
    }
  }

  if( !quietFlag ){
    sqlite3_int64 iElapse = timeOfDay() - iBegin;
    if( !verboseFlag ) printf("\n");
    printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\nSQLite %s %s\n",
           g.nDb*g.nSql, (int)(iElapse/1000), (int)(iElapse%1000),
           sqlite3_libversion(), sqlite3_sourceid());
  }

  /* Clean up and exit.
  */
  blobListFree(g.pFirstSql);
  blobListFree(g.pFirstDb);
  reformatVfs();
  return 0;
}







|















|









|












760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
      sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
                       pSql->id, pDb->id);
      if( verboseFlag ){
        printf("%s\n", g.zTestName);
        fflush(stdout);
      }else if( !quietFlag ){
        static int prevAmt = -1;
        int idx = pSql->seq*g.nDb + pDb->id - 1;
        int amt = idx*10/(g.nDb*g.nSql);
        if( amt!=prevAmt ){
          printf(" %d%%", amt*10);
          fflush(stdout);
          prevAmt = amt;
        }
      }
      createVFile("main.db", pDb->sz, pDb->a);
      openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
      if( nativeFlag && pDb->sz==0 ){
        openFlags |= SQLITE_OPEN_MEMORY;
        zVfs = 0;
      }
      rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
      if( rc ) fatalError("cannot open inmem database");
      runSql(db, (char*)pSql->a, runFlags);
      sqlite3_close(db);
      if( sqlite3_memory_used()>0 ) fatalError("memory leak");
      reformatVfs();
      g.zTestName[0] = 0;
    }
  }

  if( !quietFlag ){
    sqlite3_int64 iElapse = timeOfDay() - iBegin;
    if( !verboseFlag ) printf(" 100%%\n");
    printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\nSQLite %s %s\n",
           g.nDb*g.nSql, (int)(iElapse/1000), (int)(iElapse%1000),
           sqlite3_libversion(), sqlite3_sourceid());
  }

  /* Clean up and exit.
  */
  blobListFree(g.pFirstSql);
  blobListFree(g.pFirstDb);
  reformatVfs();
  return 0;
}