/ Check-in [62dc1fff]
Login

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

Overview
Comment:Add further tests and fixes for ota.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ota-update
Files: files | file ages | folders
SHA1:62dc1fffc38cb157c15105098749b6dd0198eb84
User & Date: dan 2015-02-16 11:48:34
Context
2015-02-16
21:13
Add extra tests and fixes for ota. check-in: e0b71519 user: dan tags: ota-update
11:48
Add further tests and fixes for ota. check-in: 62dc1fff user: dan tags: ota-update
06:27
Move tcl test code from sqlite3ota.c to new file ext/ota/test_ota.c. check-in: f20779a6 user: dan tags: ota-update
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Added ext/ota/ota11.test.

            1  +# 2015 February 16
            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  +
           13  +if {![info exists testdir]} {
           14  +  set testdir [file join [file dirname [info script]] .. .. test]
           15  +}
           16  +source $testdir/tester.tcl
           17  +set ::testprefix ota11
           18  +
           19  +
           20  +#--------------------------------------------------------------------
           21  +# Test that the xAccess() method of an ota vfs handles queries other
           22  +# than SQLITE_ACCESS_EXISTS correctly. The test code below causes
           23  +# SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory
           24  +# path argument passed to "PRAGMA temp_store_directory".
           25  +#
           26  +do_test 1.1 {
           27  +  sqlite3ota_create_vfs -default ota ""
           28  +  reset_db
           29  +  catchsql { PRAGMA temp_store_directory = '/no/such/directory' }
           30  +} {1 {not a writable directory}}
           31  +
           32  +do_test 1.2 {
           33  +  catchsql " PRAGMA temp_store_directory = '[pwd]' "
           34  +} {0 {}}
           35  +
           36  +do_test 1.3 {
           37  +  catchsql " PRAGMA temp_store_directory = '' "
           38  +} {0 {}}
           39  +
           40  +do_test 1.4 {
           41  +  db close
           42  +  sqlite3ota_destroy_vfs ota
           43  +} {}
           44  +
           45  +#--------------------------------------------------------------------
           46  +# Try to trick ota into operating on a database opened in wal mode.
           47  +#
           48  +reset_db
           49  +do_execsql_test 2.1 {
           50  +  CREATE TABLE t1(a PRIMARY KEY, b, c);
           51  +  INSERT INTO t1 VALUES(1, 2, 3);
           52  +  PRAGMA journal_mode = 'wal';
           53  +  CREATE TABLE t2(d PRIMARY KEY, e, f);
           54  +} {wal}
           55  +
           56  +do_test 2.2 {
           57  +  db_save 
           58  +  db close
           59  +
           60  +  forcedelete ota.db
           61  +  sqlite3 dbo ota.db
           62  +  dbo eval {
           63  +    CREATE TABLE data_t1(a, b, c, ota_control);
           64  +    INSERT INTO data_t1 VALUES(4, 5, 6, 0);
           65  +    INSERT INTO data_t1 VALUES(7, 8, 9, 0);
           66  +  }
           67  +  dbo close
           68  +
           69  +  db_restore 
           70  +  hexio_write test.db 18 0101
           71  +  file exists test.db-wal
           72  +} {1}
           73  +
           74  +breakpoint
           75  +do_test 2.3 {
           76  +  sqlite3ota ota test.db ota.db
           77  +  ota step
           78  +} {SQLITE_ERROR}
           79  +
           80  +do_test 2.4 {
           81  +  list [catch {ota close} msg] $msg
           82  +} {1 {SQLITE_ERROR - cannot update wal mode database}}
           83  +
           84  +finish_test
           85  +

Changes to ext/ota/ota3.test.

   131    131     list [catch { run_ota test.db ota.db } msg] $msg
   132    132   } {1 SQLITE_ERROR}
   133    133   
   134    134   do_execsql_test 2.5 {
   135    135     PRAGMA integrity_check;
   136    136   } {ok}
   137    137   
          138  +
          139  +#-------------------------------------------------------------------------
          140  +# Test that sqlite3ota_create_vfs() returns an error if the requested 
          141  +# parent VFS is unknown.
          142  +#
          143  +# And that nothing disasterous happens if a VFS name passed to
          144  +# sqlite3ota_destroy_vfs() is unknown or not an OTA vfs.
          145  +#
          146  +do_test 3.1 {
          147  +  list [catch {sqlite3ota_create_vfs xyz nosuchparent} msg] $msg
          148  +} {1 SQLITE_NOTFOUND}
          149  +
          150  +do_test 3.2 {
          151  +  sqlite3ota_destroy_vfs nosuchvfs
          152  +  sqlite3ota_destroy_vfs unix
          153  +  sqlite3ota_destroy_vfs win32
          154  +} {}
          155  +
   138    156   finish_test
   139    157   

Changes to ext/ota/otaA.test.

    65     65     ota close
    66     66   } {SQLITE_OK}
    67     67   
    68     68   do_test 2.1 {
    69     69     sqlite3 db test.db
    70     70     db eval {PRAGMA journal_mode = wal}
    71     71     db close
           72  +  breakpoint
    72     73     sqlite3ota ota test.db ota.db
    73     74     ota step
    74     75   } {SQLITE_ERROR}
    75     76   
    76     77   do_test 2.2 {
    77     78     list [catch { ota close } msg] $msg
    78     79   } {1 {SQLITE_ERROR - cannot update wal mode database}}
    79     80   
    80     81   
    81     82   finish_test
    82     83   

Changes to ext/ota/sqlite3ota.c.

   109    109   struct OtaState {
   110    110     int eStage;
   111    111     char *zTbl;
   112    112     char *zIdx;
   113    113     i64 iWalCksum;
   114    114     int nRow;
   115    115     i64 nProgress;
          116  +  u32 iCookie;
   116    117   };
   117    118   
   118    119   /*
   119    120   ** An iterator of this type is used to iterate through all objects in
   120    121   ** the target database that require updating. For each such table, the
   121    122   ** iterator visits, in order:
   122    123   **
................................................................................
   231    232   
   232    233     const char *zWal;               /* Wal filename for this main db file */
   233    234     ota_file *pWalFd;               /* Wal file descriptor for this main db */
   234    235     ota_file *pMainNext;            /* Next MAIN_DB file */
   235    236   };
   236    237   
   237    238   
   238         -static void otaCreateVfs(sqlite3ota*, const char*);
   239         -static void otaDeleteVfs(sqlite3ota*);
   240         -
   241    239   /*
   242    240   ** Prepare the SQL statement in buffer zSql against database handle db.
   243    241   ** If successful, set *ppStmt to point to the new statement and return
   244    242   ** SQLITE_OK. 
   245    243   **
   246    244   ** Otherwise, if an error does occur, set *ppStmt to NULL and return
   247    245   ** an SQLite error code. Additionally, set output variable *pzErrmsg to
................................................................................
  2065   2063           break;
  2066   2064   
  2067   2065         case OTA_STATE_CKPT:
  2068   2066           pRet->iWalCksum = sqlite3_column_int64(pStmt, 1);
  2069   2067           break;
  2070   2068   
  2071   2069         case OTA_STATE_COOKIE:
  2072         -        /* At this point (p->iCookie) contains the value of the change-counter
  2073         -        ** cookie (the thing that gets incremented when a transaction is 
  2074         -        ** committed in rollback mode) currently stored on page 1 of the 
  2075         -        ** database file. */
  2076         -        if( pRet->eStage==OTA_STAGE_OAL 
  2077         -         && p->pTargetFd->iCookie!=(u32)sqlite3_column_int64(pStmt, 1) 
  2078         -        ){
  2079         -          rc = SQLITE_BUSY;
  2080         -          p->zErrmsg = sqlite3_mprintf("database modified during ota update");
  2081         -        }
         2070  +        pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1);
  2082   2071           break;
  2083   2072   
  2084   2073         default:
  2085   2074           rc = SQLITE_CORRUPT;
  2086   2075           break;
  2087   2076       }
  2088   2077     }
................................................................................
  2133   2122   */
  2134   2123   static void otaDeleteOalFile(sqlite3ota *p){
  2135   2124     char *zOal = sqlite3_mprintf("%s-oal", p->zTarget);
  2136   2125     assert( p->rc==SQLITE_OK && p->zErrmsg==0 );
  2137   2126     unlink(zOal);
  2138   2127     sqlite3_free(zOal);
  2139   2128   }
         2129  +
         2130  +static void otaCreateVfs(sqlite3ota *p){
         2131  +  int rnd;
         2132  +  char zRnd[64];
         2133  +
         2134  +  assert( p->rc==SQLITE_OK );
         2135  +  sqlite3_randomness(sizeof(int), (void*)&rnd);
         2136  +  sprintf(zRnd, "ota_vfs_%d", rnd);
         2137  +  p->rc = sqlite3ota_create_vfs(zRnd, 0);
         2138  +  if( p->rc==SQLITE_OK ){
         2139  +    sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd);
         2140  +    assert( pVfs );
         2141  +    p->zVfsName = pVfs->zName;
         2142  +  }
         2143  +}
         2144  +
         2145  +static void otaDeleteVfs(sqlite3ota *p){
         2146  +  if( p->zVfsName ){
         2147  +    sqlite3ota_destroy_vfs(p->zVfsName);
         2148  +    p->zVfsName = 0;
         2149  +  }
         2150  +}
  2140   2151   
  2141   2152   /*
  2142   2153   ** Open and return a new OTA handle. 
  2143   2154   */
  2144   2155   sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta){
  2145   2156     sqlite3ota *p;
  2146   2157     int nTarget = strlen(zTarget);
................................................................................
  2148   2159   
  2149   2160     p = (sqlite3ota*)sqlite3_malloc(sizeof(sqlite3ota)+nTarget+1+nOta+1);
  2150   2161     if( p ){
  2151   2162       OtaState *pState = 0;
  2152   2163   
  2153   2164       /* Create the custom VFS. */
  2154   2165       memset(p, 0, sizeof(sqlite3ota));
  2155         -    otaCreateVfs(p, 0);
         2166  +    otaCreateVfs(p);
  2156   2167   
  2157   2168       /* Open the target database */
  2158   2169       if( p->rc==SQLITE_OK ){
  2159   2170         p->zTarget = (char*)&p[1];
  2160   2171         memcpy(p->zTarget, zTarget, nTarget+1);
  2161   2172         p->zOta = &p->zTarget[nTarget+1];
  2162   2173         memcpy(p->zOta, zOta, nOta+1);
................................................................................
  2169   2180       }
  2170   2181   
  2171   2182       /* Check that this is not a wal mode database. If it is, it cannot be
  2172   2183       ** updated. There is also a check for a live *-wal file in otaVfsAccess()
  2173   2184       ** function, on the off chance that the target is a wal database for
  2174   2185       ** which the first page of the db file has been overwritten by garbage
  2175   2186       ** during an earlier failed checkpoint.  */
         2187  +#if 0
  2176   2188       if( p->rc==SQLITE_OK && p->pTargetFd->iWriteVer>1 ){
  2177   2189         p->rc = SQLITE_ERROR;
  2178   2190         p->zErrmsg = sqlite3_mprintf("cannot update wal mode database");
  2179   2191       }
         2192  +#endif
  2180   2193   
  2181   2194       if( p->rc==SQLITE_OK ){
  2182   2195         pState = otaLoadState(p);
  2183   2196         assert( pState || p->rc!=SQLITE_OK );
  2184   2197         if( p->rc==SQLITE_OK ){
         2198  +
  2185   2199           if( pState->eStage==0 ){ 
  2186   2200             otaDeleteOalFile(p);
  2187   2201             p->eStage = OTA_STAGE_OAL;
  2188   2202           }else{
  2189   2203             p->eStage = pState->eStage;
  2190   2204           }
  2191   2205           p->nProgress = pState->nProgress;
  2192   2206         }
  2193   2207       }
  2194   2208       assert( p->rc!=SQLITE_OK || p->eStage!=0 );
  2195   2209   
  2196   2210       if( p->rc==SQLITE_OK ){
  2197   2211         if( p->eStage==OTA_STAGE_OAL ){
         2212  +        if( p->pTargetFd->pWalFd ){
         2213  +          p->rc = SQLITE_ERROR;
         2214  +          p->zErrmsg = sqlite3_mprintf("cannot update wal mode database");
         2215  +        }
         2216  +
         2217  +        /* At this point (pTargetFd->iCookie) contains the value of the
         2218  +        ** change-counter cookie (the thing that gets incremented when a 
         2219  +        ** transaction is committed in rollback mode) currently stored on 
         2220  +        ** page 1 of the database file. */
         2221  +        else if( pState->eStage==OTA_STAGE_OAL 
         2222  +         && p->pTargetFd->iCookie!=pState->iCookie 
         2223  +        ){
         2224  +          p->rc = SQLITE_BUSY;
         2225  +          p->zErrmsg = sqlite3_mprintf("database modified during ota update");
         2226  +        }
  2198   2227   
  2199   2228           /* Open the transaction */
  2200   2229           if( p->rc==SQLITE_OK ){
  2201   2230             p->rc = sqlite3_exec(p->db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg);
  2202   2231           }
  2203   2232     
  2204   2233           /* Point the object iterator at the first object */
................................................................................
  2353   2382   
  2354   2383     if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
  2355   2384       ota_file **pp;
  2356   2385       sqlite3_mutex_enter(p->pOtaVfs->mutex);
  2357   2386       for(pp=&p->pOtaVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext));
  2358   2387       *pp = p->pMainNext;
  2359   2388       sqlite3_mutex_leave(p->pOtaVfs->mutex);
         2389  +    p->pReal->pMethods->xShmUnmap(p->pReal, 0);
  2360   2390     }
  2361   2391   
  2362   2392     /* Close the underlying file handle */
  2363   2393     rc = p->pReal->pMethods->xClose(p->pReal);
  2364   2394     return rc;
  2365   2395   }
  2366   2396   
................................................................................
  2907   2937   
  2908   2938   static int otaVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
  2909   2939     return 0;
  2910   2940   }
  2911   2941   
  2912   2942   void sqlite3ota_destroy_vfs(const char *zName){
  2913   2943     sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
  2914         -  if( pVfs ){
         2944  +  if( pVfs && pVfs->xOpen==otaVfsOpen ){
  2915   2945       sqlite3_vfs_unregister(pVfs);
  2916   2946       sqlite3_free(pVfs);
  2917   2947     }
  2918   2948   }
  2919   2949   
  2920   2950   int sqlite3ota_create_vfs(const char *zName, const char *zParent){
  2921   2951   
................................................................................
  2941   2971       otaVfsSleep,                  /* xSleep */
  2942   2972       otaVfsCurrentTime,            /* xCurrentTime */
  2943   2973       otaVfsGetLastError,           /* xGetLastError */
  2944   2974       0,                            /* xCurrentTimeInt64 (version 2) */
  2945   2975       0, 0, 0                       /* Unimplemented version 3 methods */
  2946   2976     };
  2947   2977   
  2948         -  sqlite3_vfs *pParent;           /* Parent VFS */
  2949   2978     ota_vfs *pNew = 0;              /* Newly allocated VFS */
  2950   2979     int nName;
  2951   2980     int rc = SQLITE_OK;
  2952   2981   
         2982  +  int nByte;
  2953   2983     nName = strlen(zName);
  2954         -  pParent = sqlite3_vfs_find(zParent);
  2955         -  if( pParent==0 ){
  2956         -    rc = SQLITE_NOTFOUND;
         2984  +  nByte = sizeof(ota_vfs) + nName + 1;
         2985  +  pNew = (ota_vfs*)sqlite3_malloc(nByte);
         2986  +  if( pNew==0 ){
         2987  +    rc = SQLITE_NOMEM;
  2957   2988     }else{
  2958         -    int nByte = sizeof(ota_vfs) + nName + 1;
  2959         -    pNew = (ota_vfs*)sqlite3_malloc(nByte);
  2960         -    if( pNew==0 ){
  2961         -      rc = SQLITE_NOMEM;
         2989  +    sqlite3_vfs *pParent;           /* Parent VFS */
         2990  +    memset(pNew, 0, nByte);
         2991  +    pParent = sqlite3_vfs_find(zParent);
         2992  +    if( pParent==0 ){
         2993  +      rc = SQLITE_NOTFOUND;
  2962   2994       }else{
  2963         -      memset(pNew, 0, nByte);
  2964         -    }
  2965         -  }
         2995  +      char *zSpace;
         2996  +      memcpy(&pNew->base, &vfs_template, sizeof(sqlite3_vfs));
         2997  +      pNew->base.mxPathname = pParent->mxPathname;
         2998  +      pNew->base.szOsFile = sizeof(ota_file) + pParent->szOsFile;
         2999  +      pNew->pRealVfs = pParent;
  2966   3000   
  2967         -  if( rc==SQLITE_OK ){
  2968         -    char *zSpace;
  2969         -    memcpy(&pNew->base, &vfs_template, sizeof(sqlite3_vfs));
  2970         -    pNew->base.mxPathname = pParent->mxPathname;
  2971         -    pNew->base.szOsFile = sizeof(ota_file) + pParent->szOsFile;
  2972         -    pNew->pRealVfs = pParent;
         3001  +      pNew->base.zName = (const char*)(zSpace = (char*)&pNew[1]);
         3002  +      memcpy(zSpace, zName, nName);
  2973   3003   
  2974         -    pNew->base.zName = (const char*)(zSpace = (char*)&pNew[1]);
  2975         -    memcpy(zSpace, zName, nName);
  2976         -
  2977         -    /* Register the new VFS (not as the default) */
  2978         -    rc = sqlite3_vfs_register(&pNew->base, 0);
  2979         -    if( rc ){
  2980         -      sqlite3_free(pNew);
         3004  +      /* Register the new VFS (not as the default) */
         3005  +      rc = sqlite3_vfs_register(&pNew->base, 0);
  2981   3006       }
  2982   3007     }
  2983   3008   
  2984         -  return rc;
  2985         -}
  2986         -
  2987         -static void otaCreateVfs(sqlite3ota *p, const char *zParent){
  2988         -  int rnd;
  2989         -  char zRnd[64];
  2990         -
  2991         -  assert( p->rc==SQLITE_OK );
  2992         -  sqlite3_randomness(sizeof(int), (void*)&rnd);
  2993         -  sprintf(zRnd, "ota_vfs_%d", rnd);
  2994         -  p->rc = sqlite3ota_create_vfs(zRnd, zParent);
  2995         -  if( p->rc==SQLITE_NOTFOUND ){
  2996         -    p->zErrmsg = sqlite3_mprintf("no such vfs: %s", zParent);
  2997         -  }else if( p->rc==SQLITE_OK ){
  2998         -    sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd);
  2999         -    assert( pVfs );
  3000         -    p->zVfsName = pVfs->zName;
         3009  +  if( rc!=SQLITE_OK ){
         3010  +    sqlite3_free(pNew);
  3001   3011     }
  3002         -}
  3003         -
  3004         -static void otaDeleteVfs(sqlite3ota *p){
  3005         -  if( p->zVfsName ){
  3006         -    sqlite3ota_destroy_vfs(p->zVfsName);
  3007         -    p->zVfsName = 0;
  3008         -  }
         3012  +  return rc;
  3009   3013   }
  3010   3014   
  3011   3015   
  3012   3016   /**************************************************************************/
  3013   3017   
  3014   3018   #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) */