/ Check-in [ccab94c1]
Login

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

Overview
Comment:Enhancements to test scripts. No code changes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | incr-vacuum-opt
Files: files | file ages | folders
SHA1: ccab94c10d54e585de918bbf82dec188287d93b2
User & Date: dan 2013-02-23 18:58:11
Context
2013-02-23
19:11
Fix a cut-and-paste bug causing the library to fail to report database corruption in a few cases. check-in: f921df59 user: dan tags: incr-vacuum-opt
18:58
Enhancements to test scripts. No code changes. check-in: ccab94c1 user: dan tags: incr-vacuum-opt
17:49
Fix off-by-one bug in [c3939d2491] uncovered by th3. check-in: 66f9faa9 user: dan tags: incr-vacuum-opt
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/test_vfs.c.

   261    261   
   262    262   
   263    263   static void tvfsExecTcl(
   264    264     Testvfs *p, 
   265    265     const char *zMethod,
   266    266     Tcl_Obj *arg1,
   267    267     Tcl_Obj *arg2,
   268         -  Tcl_Obj *arg3
          268  +  Tcl_Obj *arg3,
          269  +  Tcl_Obj *arg4
   269    270   ){
   270    271     int rc;                         /* Return code from Tcl_EvalObj() */
   271    272     Tcl_Obj *pEval;
   272    273     assert( p->pScript );
   273    274   
   274    275     assert( zMethod );
   275    276     assert( p );
................................................................................
   278    279   
   279    280     pEval = Tcl_DuplicateObj(p->pScript);
   280    281     Tcl_IncrRefCount(p->pScript);
   281    282     Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1));
   282    283     if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1);
   283    284     if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2);
   284    285     if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3);
          286  +  if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4);
   285    287   
   286    288     rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
   287    289     if( rc!=TCL_OK ){
   288    290       Tcl_BackgroundError(p->interp);
   289    291       Tcl_ResetResult(p->interp);
   290    292     }
   291    293   }
................................................................................
   298    300     int rc;
   299    301     TestvfsFile *pTestfile = (TestvfsFile *)pFile;
   300    302     TestvfsFd *pFd = pTestfile->pFd;
   301    303     Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
   302    304   
   303    305     if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){
   304    306       tvfsExecTcl(p, "xClose", 
   305         -        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
          307  +        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
   306    308       );
   307    309     }
   308    310   
   309    311     if( pFd->pShmId ){
   310    312       Tcl_DecrRefCount(pFd->pShmId);
   311    313       pFd->pShmId = 0;
   312    314     }
................................................................................
   329    331     sqlite_int64 iOfst
   330    332   ){
   331    333     int rc = SQLITE_OK;
   332    334     TestvfsFd *pFd = tvfsGetFd(pFile);
   333    335     Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
   334    336     if( p->pScript && p->mask&TESTVFS_READ_MASK ){
   335    337       tvfsExecTcl(p, "xRead", 
   336         -        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
          338  +        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
   337    339       );
   338    340       tvfsResultCode(p, &rc);
   339    341     }
   340    342     if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){
   341    343       rc = SQLITE_IOERR;
   342    344     }
   343    345     if( rc==SQLITE_OK ){
................................................................................
   358    360     int rc = SQLITE_OK;
   359    361     TestvfsFd *pFd = tvfsGetFd(pFile);
   360    362     Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
   361    363   
   362    364     if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
   363    365       tvfsExecTcl(p, "xWrite", 
   364    366           Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 
   365         -        Tcl_NewWideIntObj(iOfst)
          367  +        Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt)
   366    368       );
   367    369       tvfsResultCode(p, &rc);
   368    370     }
   369    371   
   370    372     if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){
   371    373       rc = SQLITE_FULL;
   372    374     }
................................................................................
   386    388   static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
   387    389     int rc = SQLITE_OK;
   388    390     TestvfsFd *pFd = tvfsGetFd(pFile);
   389    391     Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
   390    392   
   391    393     if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){
   392    394       tvfsExecTcl(p, "xTruncate", 
   393         -        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
          395  +        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
   394    396       );
   395    397       tvfsResultCode(p, &rc);
   396    398     }
   397    399     
   398    400     if( rc==SQLITE_OK ){
   399    401       rc = sqlite3OsTruncate(pFd->pReal, size);
   400    402     }
................................................................................
   427    429           break;
   428    430         default:
   429    431           assert(0);
   430    432       }
   431    433   
   432    434       tvfsExecTcl(p, "xSync", 
   433    435           Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
   434         -        Tcl_NewStringObj(zFlags, -1)
          436  +        Tcl_NewStringObj(zFlags, -1), 0
   435    437       );
   436    438       tvfsResultCode(p, &rc);
   437    439     }
   438    440   
   439    441     if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL;
   440    442   
   441    443     if( rc==SQLITE_OK ){
................................................................................
   574    576         while( *z ){
   575    577           Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
   576    578           z += strlen(z) + 1;
   577    579           Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
   578    580           z += strlen(z) + 1;
   579    581         }
   580    582       }
   581         -    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0);
          583  +    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0);
   582    584       Tcl_DecrRefCount(pArg);
   583    585       if( tvfsResultCode(p, &rc) ){
   584    586         if( rc!=SQLITE_OK ) return rc;
   585    587       }else{
   586    588         pId = Tcl_GetObjResult(p->interp);
   587    589       }
   588    590     }
................................................................................
   631    633   */
   632    634   static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
   633    635     int rc = SQLITE_OK;
   634    636     Testvfs *p = (Testvfs *)pVfs->pAppData;
   635    637   
   636    638     if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){
   637    639       tvfsExecTcl(p, "xDelete", 
   638         -        Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0
          640  +        Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0
   639    641       );
   640    642       tvfsResultCode(p, &rc);
   641    643     }
   642    644     if( rc==SQLITE_OK ){
   643    645       rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync);
   644    646     }
   645    647     return rc;
................................................................................
   659    661     if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){
   660    662       int rc;
   661    663       char *zArg = 0;
   662    664       if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS";
   663    665       if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE";
   664    666       if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ";
   665    667       tvfsExecTcl(p, "xAccess", 
   666         -        Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0
          668  +        Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0
   667    669       );
   668    670       if( tvfsResultCode(p, &rc) ){
   669    671         if( rc!=SQLITE_OK ) return rc;
   670    672       }else{
   671    673         Tcl_Interp *interp = p->interp;
   672    674         if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){
   673    675           return SQLITE_OK;
................................................................................
   687    689     const char *zPath, 
   688    690     int nOut, 
   689    691     char *zOut
   690    692   ){
   691    693     Testvfs *p = (Testvfs *)pVfs->pAppData;
   692    694     if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
   693    695       int rc;
   694         -    tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0);
          696  +    tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0);
   695    697       if( tvfsResultCode(p, &rc) ){
   696    698         if( rc!=SQLITE_OK ) return rc;
   697    699       }
   698    700     }
   699    701     return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
   700    702   }
   701    703   
................................................................................
   767    769   
   768    770     /* Evaluate the Tcl script: 
   769    771     **
   770    772     **   SCRIPT xShmOpen FILENAME
   771    773     */
   772    774     Tcl_ResetResult(p->interp);
   773    775     if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){
   774         -    tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
          776  +    tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0);
   775    777       if( tvfsResultCode(p, &rc) ){
   776    778         if( rc!=SQLITE_OK ) return rc;
   777    779       }
   778    780     }
   779    781   
   780    782     assert( rc==SQLITE_OK );
   781    783     if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){
................................................................................
   837    839     if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){
   838    840       Tcl_Obj *pArg = Tcl_NewObj();
   839    841       Tcl_IncrRefCount(pArg);
   840    842       Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage));
   841    843       Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
   842    844       Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
   843    845       tvfsExecTcl(p, "xShmMap", 
   844         -        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg
          846  +        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0
   845    847       );
   846    848       tvfsResultCode(p, &rc);
   847    849       Tcl_DecrRefCount(pArg);
   848    850     }
   849    851     if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){
   850    852       rc = SQLITE_IOERR;
   851    853     }
................................................................................
   887    889       if( flags & SQLITE_SHM_SHARED ){
   888    890         strcpy(&zLock[nLock], " shared");
   889    891       }else{
   890    892         strcpy(&zLock[nLock], " exclusive");
   891    893       }
   892    894       tvfsExecTcl(p, "xShmLock", 
   893    895           Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
   894         -        Tcl_NewStringObj(zLock, -1)
          896  +        Tcl_NewStringObj(zLock, -1), 0
   895    897       );
   896    898       tvfsResultCode(p, &rc);
   897    899     }
   898    900   
   899    901     if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){
   900    902       rc = SQLITE_IOERR;
   901    903     }
................................................................................
   933    935     if( p->isFullshm ){
   934    936       sqlite3OsShmBarrier(pFd->pReal);
   935    937       return;
   936    938     }
   937    939   
   938    940     if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
   939    941       tvfsExecTcl(p, "xShmBarrier", 
   940         -        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
          942  +        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
   941    943       );
   942    944     }
   943    945   }
   944    946   
   945    947   static int tvfsShmUnmap(
   946    948     sqlite3_file *pFile,
   947    949     int deleteFlag
................................................................................
   957    959     }
   958    960   
   959    961     if( !pBuffer ) return SQLITE_OK;
   960    962     assert( pFd->pShmId && pFd->pShm );
   961    963   
   962    964     if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){
   963    965       tvfsExecTcl(p, "xShmUnmap", 
   964         -        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
          966  +        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
   965    967       );
   966    968       tvfsResultCode(p, &rc);
   967    969     }
   968    970   
   969    971     for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext));
   970    972     assert( (*ppFd)==pFd );
   971    973     *ppFd = pFd->pNext;

Changes to test/incrvacuum_ioerr.test.

   135    135     
   136    136     set ::rc 1
   137    137     for {set iTest 1} {$::rc && $iTest<2000} {incr iTest} {
   138    138     
   139    139       # Figure out how big the database is and how many free pages it
   140    140       # has before running incremental-vacuum.
   141    141       #
   142         -    set nPage [expr {[file size test.db]/1024}]
   143    142       set nFree [execsql {pragma freelist_count} db1]
          143  +    set nPage [execsql {pragma page_count} db1]
   144    144     
   145    145       # Now run incremental-vacuum to vacuum 5 pages from the db file.
   146    146       # The iTest'th I/O call is set to fail.
   147    147       #
   148    148       set ::sqlite_io_error_pending $iTest
   149    149       set ::sqlite_io_error_persist 1
   150    150       do_test incrvacuum-ioerr-4.$iTest.1 {
................................................................................
   154    154     
   155    155       set ::sqlite_io_error_pending 0
   156    156       set ::sqlite_io_error_persist 0
   157    157       set ::sqlite_io_error_hit 0
   158    158       set ::sqlite_io_error_hardhit 0
   159    159     
   160    160       set nFree2 [execsql {pragma freelist_count} db1]
   161         -    set nPage2 [expr {[file size test.db]/1024}]
          161  +    set nPage2 [execsql {pragma page_count} db1]
   162    162     
   163    163       do_test incrvacuum-ioerr-4.$iTest.2 {
   164    164         set shrink [expr {$nPage-$nPage2}]
   165    165         expr {$shrink==0 || $shrink==5}
   166    166       } {1}
   167    167     
   168    168       do_test incrvacuum-ioerr-4.$iTest.3 {

Changes to test/tester.tcl.

  1113   1113       if {$msg=="child killed: unknown signal"} {
  1114   1114         set msg "child process exited abnormally"
  1115   1115       }
  1116   1116     }
  1117   1117     
  1118   1118     lappend r $msg
  1119   1119   }
         1120  +
         1121  +proc run_ioerr_prep {} {
         1122  +  set ::sqlite_io_error_pending 0
         1123  +  catch {db close}
         1124  +  catch {db2 close}
         1125  +  catch {forcedelete test.db}
         1126  +  catch {forcedelete test.db-journal}
         1127  +  catch {forcedelete test2.db}
         1128  +  catch {forcedelete test2.db-journal}
         1129  +  set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
         1130  +  sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
         1131  +  if {[info exists ::ioerropts(-tclprep)]} {
         1132  +    eval $::ioerropts(-tclprep)
         1133  +  }
         1134  +  if {[info exists ::ioerropts(-sqlprep)]} {
         1135  +    execsql $::ioerropts(-sqlprep)
         1136  +  }
         1137  +  expr 0
         1138  +}
  1120   1139   
  1121   1140   # Usage: do_ioerr_test <test number> <options...>
  1122   1141   #
  1123   1142   # This proc is used to implement test cases that check that IO errors
  1124   1143   # are correctly handled. The first argument, <test number>, is an integer 
  1125   1144   # used to name the tests executed by this proc. Options are as follows:
  1126   1145   #
................................................................................
  1146   1165     set ::ioerropts(-ckrefcount) 0
  1147   1166     set ::ioerropts(-restoreprng) 1
  1148   1167     array set ::ioerropts $args
  1149   1168   
  1150   1169     # TEMPORARY: For 3.5.9, disable testing of extended result codes. There are
  1151   1170     # a couple of obscure IO errors that do not return them.
  1152   1171     set ::ioerropts(-erc) 0
         1172  +  
         1173  +  # Create a single TCL script from the TCL and SQL specified
         1174  +  # as the body of the test.
         1175  +  set ::ioerrorbody {}
         1176  +  if {[info exists ::ioerropts(-tclbody)]} {
         1177  +    append ::ioerrorbody "$::ioerropts(-tclbody)\n"
         1178  +  }
         1179  +  if {[info exists ::ioerropts(-sqlbody)]} {
         1180  +    append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
         1181  +  }
         1182  +
         1183  +  save_prng_state
         1184  +  if {$::ioerropts(-cksum)} {
         1185  +    run_ioerr_prep
         1186  +    eval $::ioerrorbody
         1187  +    set ::goodcksum [cksum]
         1188  +  }
  1153   1189   
  1154   1190     set ::go 1
  1155   1191     #reset_prng_state
  1156         -  save_prng_state
  1157   1192     for {set n $::ioerropts(-start)} {$::go} {incr n} {
  1158   1193       set ::TN $n
  1159   1194       incr ::ioerropts(-count) -1
  1160   1195       if {$::ioerropts(-count)<0} break
  1161   1196    
  1162   1197       # Skip this IO error if it was specified with the "-exclude" option.
  1163   1198       if {[info exists ::ioerropts(-exclude)]} {
................................................................................
  1166   1201       if {$::ioerropts(-restoreprng)} {
  1167   1202         restore_prng_state
  1168   1203       }
  1169   1204   
  1170   1205       # Delete the files test.db and test2.db, then execute the TCL and 
  1171   1206       # SQL (in that order) to prepare for the test case.
  1172   1207       do_test $testname.$n.1 {
  1173         -      set ::sqlite_io_error_pending 0
  1174         -      catch {db close}
  1175         -      catch {db2 close}
  1176         -      catch {forcedelete test.db}
  1177         -      catch {forcedelete test.db-journal}
  1178         -      catch {forcedelete test2.db}
  1179         -      catch {forcedelete test2.db-journal}
  1180         -      set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
  1181         -      sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
  1182         -      if {[info exists ::ioerropts(-tclprep)]} {
  1183         -        eval $::ioerropts(-tclprep)
  1184         -      }
  1185         -      if {[info exists ::ioerropts(-sqlprep)]} {
  1186         -        execsql $::ioerropts(-sqlprep)
  1187         -      }
  1188         -      expr 0
         1208  +      run_ioerr_prep
  1189   1209       } {0}
  1190   1210   
  1191   1211       # Read the 'checksum' of the database.
  1192   1212       if {$::ioerropts(-cksum)} {
  1193         -      set checksum [cksum]
         1213  +      set ::checksum [cksum]
  1194   1214       }
  1195   1215   
  1196   1216       # Set the Nth IO error to fail.
  1197   1217       do_test $testname.$n.2 [subst {
  1198   1218         set ::sqlite_io_error_persist $::ioerropts(-persist)
  1199   1219         set ::sqlite_io_error_pending $n
  1200   1220       }] $n
  1201         -  
  1202         -    # Create a single TCL script from the TCL and SQL specified
  1203         -    # as the body of the test.
  1204         -    set ::ioerrorbody {}
  1205         -    if {[info exists ::ioerropts(-tclbody)]} {
  1206         -      append ::ioerrorbody "$::ioerropts(-tclbody)\n"
  1207         -    }
  1208         -    if {[info exists ::ioerropts(-sqlbody)]} {
  1209         -      append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
  1210         -    }
  1211   1221   
  1212         -    # Execute the TCL Script created in the above block. If
  1213         -    # there are at least N IO operations performed by SQLite as
  1214         -    # a result of the script, the Nth will fail.
         1222  +    # Execute the TCL script created for the body of this test. If
         1223  +    # at least N IO operations performed by SQLite as a result of 
         1224  +    # the script, the Nth will fail.
  1215   1225       do_test $testname.$n.3 {
  1216   1226         set ::sqlite_io_error_hit 0
  1217   1227         set ::sqlite_io_error_hardhit 0
  1218   1228         set r [catch $::ioerrorbody msg]
  1219   1229         set ::errseen $r
  1220   1230         set rc [sqlite3_errcode $::DB]
  1221   1231         if {$::ioerropts(-erc)} {
................................................................................
  1311   1321       # be the same as before the script that caused the IO error was run.
  1312   1322       #
  1313   1323       if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} {
  1314   1324         do_test $testname.$n.6 {
  1315   1325           catch {db close}
  1316   1326           catch {db2 close}
  1317   1327           set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
  1318         -        cksum
  1319         -      } $checksum
         1328  +        set nowcksum [cksum]
         1329  +        set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}]
         1330  +        if {$res==0} {
         1331  +          puts "now=$nowcksum"
         1332  +          puts "the=$::checksum"
         1333  +          puts "fwd=$::goodcksum"
         1334  +        }
         1335  +        set res
         1336  +      } 1
  1320   1337       }
  1321   1338   
  1322   1339       set ::sqlite_io_error_hardhit 0
  1323   1340       set ::sqlite_io_error_pending 0
  1324   1341       if {[info exists ::ioerropts(-cleanup)]} {
  1325   1342         catch $::ioerropts(-cleanup)
  1326   1343       }