/ Check-in [98e02913]
Login

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

Overview
Comment:Added SQLITE_TESTCTRL_INITMODE for improved testability.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:98e029134dc1300d3ecb48b41b5107ec69ba85db
User & Date: drh 2015-01-30 15:52:26
Context
2015-01-30
20:59
Change SQLITE_TESTCTRL_INITMODE to SQLITE_TESTCTRL_IMPOSTER. Revise the order of parameters. Give it the ability to reset the schema parse table so that imposter tables can be erased. check-in: 42d56017 user: drh tags: trunk
16:36
Merge all recent trunk changes, and especially the SQLITE_TESTCTRL_INITMODE enhancement. check-in: 36436dde user: drh tags: ota-update
15:52
Added SQLITE_TESTCTRL_INITMODE for improved testability. check-in: 98e02913 user: drh tags: trunk
15:40
Add a few simple test cases for SQLITE_TESTCTRL_INITMODE - cases which also test PRAGMA integrity_check. Closed-Leaf check-in: 3a6e2afe user: drh tags: initmode-testctrl
2015-01-29
19:27
Fix some duplicated test names. check-in: 1797158d user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

  3594   3594       ** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if
  3595   3595       ** not.
  3596   3596       */
  3597   3597       case SQLITE_TESTCTRL_ISINIT: {
  3598   3598         if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
  3599   3599         break;
  3600   3600       }
         3601  +
         3602  +    /*   sqlite3_test_control(SQLITE_TESTCTRL_INITMODE, db, busy, iDb, newTnum);
         3603  +    **
         3604  +    ** Set the db->init.busy, db->init.iDb, and db->init.tnum fields.
         3605  +    */
         3606  +    case SQLITE_TESTCTRL_INITMODE: {
         3607  +      sqlite3 *db = va_arg(ap, sqlite3*);
         3608  +      db->init.busy = va_arg(ap,int);
         3609  +      db->init.iDb = va_arg(ap,int);
         3610  +      db->init.newTnum = va_arg(ap,int);
         3611  +      break;
         3612  +    }
  3601   3613     }
  3602   3614     va_end(ap);
  3603   3615   #endif /* SQLITE_OMIT_BUILTIN_TEST */
  3604   3616     return rc;
  3605   3617   }
  3606   3618   
  3607   3619   /*

Changes to src/shell.c.

  3532   3532         { "always",                SQLITE_TESTCTRL_ALWAYS                 },
  3533   3533         { "reserve",               SQLITE_TESTCTRL_RESERVE                },
  3534   3534         { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },
  3535   3535         { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },
  3536   3536         { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },
  3537   3537         { "byteorder",             SQLITE_TESTCTRL_BYTEORDER              },
  3538   3538         { "never_corrupt",         SQLITE_TESTCTRL_NEVER_CORRUPT          },
         3539  +      { "initmode",              SQLITE_TESTCTRL_INITMODE               },
  3539   3540       };
  3540   3541       int testctrl = -1;
  3541   3542       int rc = 0;
  3542   3543       int i, n;
  3543   3544       open_db(p, 0);
  3544   3545   
  3545   3546       /* convert testctrl text option to value. allow any unique prefix
................................................................................
  3623   3624               fprintf(p->out, "%d (0x%08x)\n", rc, rc);
  3624   3625             } else {
  3625   3626               fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
  3626   3627                               azArg[1]);
  3627   3628             }
  3628   3629             break;
  3629   3630   #endif
         3631  +
         3632  +        case SQLITE_TESTCTRL_INITMODE:
         3633  +          if( nArg==5 ){
         3634  +            rc = sqlite3_test_control(testctrl, p->db, 
         3635  +                          integerValue(azArg[2]),
         3636  +                          integerValue(azArg[3]),
         3637  +                          integerValue(azArg[4]));
         3638  +          }else{
         3639  +            fprintf(stderr,"Usage: .testctrl initmode fBusy iDb newTnum\n");
         3640  +            rc = 1;
         3641  +          }
         3642  +          break;
  3630   3643   
  3631   3644           case SQLITE_TESTCTRL_BITVEC_TEST:         
  3632   3645           case SQLITE_TESTCTRL_FAULT_INSTALL:       
  3633   3646           case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: 
  3634   3647           case SQLITE_TESTCTRL_SCRATCHMALLOC:       
  3635   3648           default:
  3636   3649             fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",

Changes to src/sqlite.h.in.

  6256   6256   #define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
  6257   6257   #define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
  6258   6258   #define SQLITE_TESTCTRL_NEVER_CORRUPT           20
  6259   6259   #define SQLITE_TESTCTRL_VDBE_COVERAGE           21
  6260   6260   #define SQLITE_TESTCTRL_BYTEORDER               22
  6261   6261   #define SQLITE_TESTCTRL_ISINIT                  23
  6262   6262   #define SQLITE_TESTCTRL_SORTER_MMAP             24
  6263         -#define SQLITE_TESTCTRL_LAST                    24
         6263  +#define SQLITE_TESTCTRL_INITMODE                25
         6264  +#define SQLITE_TESTCTRL_LAST                    25
  6264   6265   
  6265   6266   /*
  6266   6267   ** CAPI3REF: SQLite Runtime Status
  6267   6268   **
  6268   6269   ** ^This interface is used to retrieve runtime status information
  6269   6270   ** about the performance of SQLite, and optionally to reset various
  6270   6271   ** highwater marks.  ^The first argument is an integer code for

Changes to src/test1.c.

  5910   5910     Tcl_Obj *CONST objv[]
  5911   5911   ){
  5912   5912     struct Verb {
  5913   5913       const char *zName;
  5914   5914       int i;
  5915   5915     } aVerb[] = {
  5916   5916       { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, 
  5917         -    { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, 
         5917  +    { "SQLITE_TESTCTRL_SORTER_MMAP",     SQLITE_TESTCTRL_SORTER_MMAP     }, 
         5918  +    { "SQLITE_TESTCTRL_INITMODE",        SQLITE_TESTCTRL_INITMODE        },
  5918   5919     };
  5919   5920     int iVerb;
  5920   5921     int iFlag;
  5921   5922     int rc;
  5922   5923   
  5923   5924     if( objc<2 ){
  5924   5925       Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
................................................................................
  5951   5952           return TCL_ERROR;
  5952   5953         }
  5953   5954         if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
  5954   5955         if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
  5955   5956         sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
  5956   5957         break;
  5957   5958       }
         5959  +
         5960  +    case SQLITE_TESTCTRL_INITMODE: {
         5961  +      int fBusy, iDb, newTnum;
         5962  +      sqlite3 *db;
         5963  +      if( objc!=6 ){
         5964  +        Tcl_WrongNumArgs(interp, 2, objv, "DB fBusy iDb newTnum");
         5965  +        return TCL_ERROR;
         5966  +      }
         5967  +      if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
         5968  +      if( Tcl_GetIntFromObj(interp, objv[3], &fBusy) ) return TCL_ERROR;
         5969  +      if( Tcl_GetIntFromObj(interp, objv[4], &iDb) ) return TCL_ERROR;
         5970  +      if( Tcl_GetIntFromObj(interp, objv[5], &newTnum) ) return TCL_ERROR;
         5971  +      sqlite3_test_control(SQLITE_TESTCTRL_INITMODE, db, fBusy, iDb, newTnum);
         5972  +      break;
         5973  +    }
  5958   5974     }
  5959   5975   
  5960   5976     Tcl_ResetResult(interp);
  5961   5977     return TCL_OK;
  5962   5978   }
  5963   5979   
  5964   5980   #if SQLITE_OS_UNIX

Added test/initmode.test.

            1  +# 2015-01-30
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# This file implements tests for SQLite library.
           13  +#
           14  +# The focus of this file is adding extra entries in the symbol table
           15  +# using sqlite3_test_control(SQLITE_TESTCTRL_INITMODE) and verifying that
           16  +# SQLite handles those as expected.
           17  +#
           18  +
           19  +set testdir [file dirname $argv0]
           20  +source $testdir/tester.tcl
           21  +set testprefix initmode
           22  +
           23  +# Create a bunch of data to sort against
           24  +#
           25  +do_test initmode-1.0 {
           26  +  execsql {
           27  +    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d NOT NULL);
           28  +    CREATE INDEX t1b ON t1(b);
           29  +    CREATE UNIQUE INDEX t1c ON t1(c);
           30  +    WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<30)
           31  +      INSERT INTO t1(a,b,c,d) SELECT i,1000+i,2000+i,3000+i FROM c;
           32  +  }
           33  +  set t1_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1'}]
           34  +  set t1a_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1a'}]
           35  +  set t1b_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1b'}]
           36  +
           37  +  # Create a shadow table that uses the same b-tree as t1 but which does
           38  +  # not have the indexes
           39  +  #
           40  +  sqlite3_test_control SQLITE_TESTCTRL_INITMODE db 1 0 $t1_root
           41  +  db eval {CREATE TABLE xt1(a,b,c,d)}
           42  +  sqlite3_test_control SQLITE_TESTCTRL_INITMODE db 0 0 0
           43  +
           44  +  # Create triggers to record changes to xt1.
           45  +  #
           46  +  db eval {
           47  +    CREATE TEMP TABLE chnglog(desc TEXT);
           48  +    CREATE TEMP TRIGGER xt1_del AFTER DELETE ON xt1 BEGIN
           49  +      INSERT INTO chnglog VALUES(
           50  +           printf('DELETE t1: rowid=%d, a=%s, b=%s, c=%s, d=%s',
           51  +                  old.rowid, quote(old.a), quote(old.b), quote(old.c),
           52  +                  quote(old.d)));
           53  +    END;
           54  +    CREATE TEMP TRIGGER xt1_ins AFTER INSERT ON xt1 BEGIN
           55  +      INSERT INTO chnglog VALUES(
           56  +           printf('INSERT t1:  rowid=%d, a=%s, b=%s, c=%s, d=%s',
           57  +                  new.rowid, quote(new.a), quote(new.b), quote(new.c),
           58  +                  quote(new.d)));
           59  +    END;
           60  +  }
           61  +} {}
           62  +
           63  +# The xt1 table has separate xt1.rowid and xt1.a columns.  The xt1.rowid
           64  +# column corresponds to t1.rowid and t1.a, but the xt1.a column is always
           65  +# NULL
           66  +#
           67  +do_execsql_test initmode-1.1 {
           68  +  SELECT rowid FROM xt1 WHERE a IS NOT NULL;
           69  +} {}
           70  +do_execsql_test initmode-1.2 {
           71  +  SELECT a,b,c,d FROM t1 EXCEPT SELECT rowid,b,c,d FROM xt1;
           72  +  SELECT rowid,b,c,d FROM xt1 EXCEPT SELECT a,b,c,d FROM t1;
           73  +} {}
           74  +
           75  +
           76  +# Make changes via the xt1 shadow table.  This will not update the
           77  +# indexes on t1 nor check the uniqueness constraint on t1.c nor check
           78  +# the NOT NULL constraint on t1.d, resulting in a logically inconsistent
           79  +# database.
           80  +#
           81  +do_execsql_test initmode-1.3 {
           82  +  DELETE FROM xt1 WHERE rowid=5;
           83  +  INSERT INTO xt1(rowid,a,b,c,d) VALUES(99,'hello',1099,2022,NULL);
           84  +  SELECT * FROM chnglog ORDER BY rowid;
           85  +} [list \
           86  +  {DELETE t1: rowid=5, a=NULL, b=1005, c=2005, d=3005} \
           87  +  {INSERT t1:  rowid=99, a='hello', b=1099, c=2022, d=NULL} \
           88  +]
           89  +
           90  +do_execsql_test initmode-1.4a {
           91  +  PRAGMA integrity_check;
           92  +} {/NULL value in t1.d/}
           93  +do_execsql_test initmode-1.4b {
           94  +  PRAGMA integrity_check;
           95  +} {/row # missing from index t1b/}
           96  +do_execsql_test initmode-1.4c {
           97  +  PRAGMA integrity_check;
           98  +} {/row # missing from index t1c/}
           99  +
          100  +finish_test