]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Test cases to improve coverage of btree.c (and minor bugfixes). (CVS 2190)
authordanielk1977 <danielk1977@noemail.net>
Tue, 11 Jan 2005 10:25:06 +0000 (10:25 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 11 Jan 2005 10:25:06 +0000 (10:25 +0000)
FossilOrigin-Name: 8ced491588764b1e1066787d0abf3cde8b60970b

12 files changed:
manifest
manifest.uuid
src/btree.c
src/pager.c
src/pragma.c
src/vdbe.c
test/autovacuum_ioerr.test [new file with mode: 0644]
test/autovacuum_ioerr2.test [new file with mode: 0644]
test/btree.test
test/btree2.test
test/corrupt2.test [new file with mode: 0644]
test/ioerr.test

index 6a0c78dbcdd6180e3201f86b4880d09dc315db7d..4b8c8da745dd43302f0ac7960c8605113c0b0654 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Extra\stest\scases\sto\simprove\scoverage\sof\sbtree.c\s(CVS\s2189)
-D 2005-01-10T12:59:52
+C Test\scases\sto\simprove\scoverage\sof\sbtree.c\s(and\sminor\sbugfixes).\s(CVS\s2190)
+D 2005-01-11T10:25:07
 F Makefile.in ecf441ac5ca1ccfc8748a8a9537706e69893dfa4
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -29,7 +29,7 @@ F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863
 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
 F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689
 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
-F src/btree.c 241e27b4640519a45ab55d35ee3ae300a478eb23
+F src/btree.c 5ec669c8839d98dd9e283cc6d4547da4adb37a81
 F src/btree.h 861e40b759a195ba63819740e484390012cf81ab
 F src/build.c af1296e8a21a406b4f4c4f1e1365e075071219f3
 F src/cursor.c f883813759742068890b1f699335872bfa8fdf41
@@ -53,10 +53,10 @@ F src/os_unix.c 08340c864822115bf87c6c1735780a0996278b81
 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
 F src/os_win.c 3c0b0a3bc33318cf555a1cd130232ad1b9a5a711
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 4a14410a4e67173bb121a919c7f2033b93822186
+F src/pager.c c6b29d55c9755f35bd9d711865aaf83e410f730f
 F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
 F src/parse.y ceba179b9703657180963568f54b0e75f33e36e1
-F src/pragma.c 1b6f9f4caa2c441b18bf0c8793a4b4b8f3214d03
+F src/pragma.c ac594f74c90ffec043c43e49358719ffeb491eec
 F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c af6ffcf0201f8f4e2697eea25689077dc61c6109
@@ -76,7 +76,7 @@ F src/update.c 0979397c41ac29c54fe0cc687a356d8629a633af
 F src/utf.c e45ce11be6922408cd381561721f6cca7d3b992a
 F src/util.c 29f43c4a7b9ff29302f7899f793be6836b6cd7f9
 F src/vacuum.c 1a9db113a027461daaf44724c71dd1ebbd064203
-F src/vdbe.c 53520958a7d63eaf138fa78f69efe225d502a9bf
+F src/vdbe.c c9f00cc0298e025e61b4b65555a4a23dd13325dd
 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
 F src/vdbeInt.h 0f74561e629af86172de7cdf0ecaea014c51696c
 F src/vdbeapi.c 0cf3bdc1072616bedc8eec7fc22e3f5a169d33fd
@@ -93,12 +93,14 @@ F test/auth.test 559e0816b8100740624ebb0ab7aab05f5c92831c
 F test/autoinc.test c071e51ff167b8e889212273588d9cca71845b70
 F test/autovacuum.test a4e8da39a6268378c4f9fc17fe2df1d5be16d631
 F test/autovacuum_crash.test 2dca85cbcc497098e45e8847c86407eb3554f3d4
+F test/autovacuum_ioerr.test 55ea907df34edb9be78a910a1636c2eb3c17ecc4
+F test/autovacuum_ioerr2.test bf427c86e4daa8638a2eb849bbe1446c234c73d3
 F test/bigfile.test d3744a8821ce9abb8697f2826a3e3d22b719e89f
 F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
 F test/bind.test 3635ddfe0fb15ecfd158708feff6ef707e15c0a9
 F test/blob.test fc41fe95bdc10da51f0dee73ce86e75ce1d6eb9d
-F test/btree.test ff754a2e68af75396fbbf8dfda009b4b93f086a6
-F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635
+F test/btree.test 8aa7424aeec844df990273fe36447e5d7e407261
+F test/btree2.test dbce930b549d5ac883a7d8905c976209ea241db3
 F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4
 F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2
 F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027
@@ -114,6 +116,7 @@ F test/collate5.test 7999fb3122386bae38acd8ccd61e0b7c5a30e289
 F test/collate6.test 6c9470d1606ee3e564675b229653e320c49ec638
 F test/conflict.test c5b849b01cfbe0a4f63a90cba6f68e2fe3a75f87
 F test/corrupt.test 0080ddcece23e8ba47c44608c4fb73fd4d1d8ce2
+F test/corrupt2.test cb1f813df7559de3021e01170af0bba31507a9a5
 F test/crash.test 637479504e137d065385c5b9379680d2b5372630
 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
 F test/cursor.test d7c65ea0fc4e321e12fbcf5c7f3e2211ef45379b
@@ -134,7 +137,7 @@ F test/insert.test 56f9c20c9adc8d707490c4ffa5d4daa94826ea03
 F test/insert2.test 0bb50ff999e35a21549d8ee5dc44db8ac24d31a7
 F test/interrupt.test 0aa230f8aedec0ad7caaf5edaced337e4cfb3820
 F test/intpkey.test b57cf5236fde1bd8cbc1388fa0c91908f6fd9194
-F test/ioerr.test fd283e768301b26bc148012ea6ebea4c2295aa20
+F test/ioerr.test b37837850294c6cbafb0fd5211a4df40b10d46af
 F test/join.test ea8c77b9fbc377fe553cdb5ce5f1bd72021dca5d
 F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
 F test/join3.test 67dc0d7c8dab3fff25796d0f3c3fd9c999aeded3
@@ -263,7 +266,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746
-P 5b7a5a4d69be425163135698d889797d15f56492
-R 8f87d57733bba8a8bebba0892812901d
+P a461988661368bce799ef3d498a18e88559e14c7
+R 9631300063f5d334400b6e5706977e76
 U danielk1977
-Z 23146f967500dcd597b4ae335d7f01e0
+Z 6f3669f1f4cea6222a3e8648182fde70
index bbc8e6ad961ff38d158647daeb72a54bc03936e2..743e01d3cea75e55863497eaa6e89087fa3c3a17 100644 (file)
@@ -1 +1 @@
-a461988661368bce799ef3d498a18e88559e14c7
\ No newline at end of file
+8ced491588764b1e1066787d0abf3cde8b60970b
\ No newline at end of file
index 7fed5ee6facefa859823417ff86ffed01ff428aa..5551b0c02cf0241a8db9b2821f31b65121bf99e1 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.229 2005/01/10 12:59:52 danielk1977 Exp $
+** $Id: btree.c,v 1.230 2005/01/11 10:25:07 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -356,7 +356,6 @@ struct BtCursor {
   CellInfo info;            /* A parse of the cell we are pointing at */
   u8 wrFlag;                /* True if writable */
   u8 isValid;               /* TRUE if points to a valid entry */
-  u8 status;                /* Set to SQLITE_ABORT if cursors is invalidated */
 };
 
 /*
@@ -953,7 +952,6 @@ static int initPage(
   MemPage *pParent       /* The parent.  Might be NULL */
 ){
   int pc;            /* Address of a freeblock within pPage->aData[] */
-  int i;             /* Loop counter */
   int hdr;           /* Offset to beginning of page header */
   u8 *data;          /* Equal to pPage->aData */
   Btree *pBt;        /* The main btree structure */
@@ -997,17 +995,12 @@ static int initPage(
   /* Compute the total free space on the page */
   pc = get2byte(&data[hdr+1]);
   nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
-  i = 0;
   while( pc>0 ){
     int next, size;
     if( pc>usableSize-4 ){
       /* Free block is off the page */
       return SQLITE_CORRUPT;  /* bkpt-CORRUPT */
     }
-    if( i++>SQLITE_MAX_PAGE_SIZE/4 ){
-      /* The free block list forms an infinite loop */
-      return SQLITE_CORRUPT;  /* bkpt-CORRUPT */
-    }
     next = get2byte(&data[pc]);
     size = get2byte(&data[pc+2]);
     if( next>0 && next<=pc+size+3 ){
@@ -1295,6 +1288,9 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
 ** of the database file used for locking (beginning at PENDING_BYTE,
 ** the first byte past the 1GB boundary, 0x40000000) needs to occur
 ** at the beginning of a page.
+**
+** If parameter nReserve is less than zero, then the number of reserved
+** bytes per page is left unchanged.
 */
 int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){
   if( pBt->pageSizeFixed ){
@@ -1904,6 +1900,7 @@ static void invalidateCursors(Btree *pBt){
 ** Print debugging information about all cursors to standard output.
 */
 void sqlite3BtreeCursorList(Btree *pBt){
+#ifndef SQLITE_OMIT_CURSOR
   BtCursor *pCur;
   for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
     MemPage *pPage = pCur->pPage;
@@ -1914,6 +1911,7 @@ void sqlite3BtreeCursorList(Btree *pBt){
        pCur->isValid ? "" : " eof"
     );
   }
+#endif
 }
 #endif
 
@@ -2117,7 +2115,6 @@ int sqlite3BtreeCursor(
   pCur->pPrev = 0;
   pBt->pCursor = pCur;
   pCur->isValid = 0;
-  pCur->status = SQLITE_OK;
   *ppCur = pCur;
   return SQLITE_OK;
 
@@ -2344,9 +2341,7 @@ static int getPayload(
 ** the available payload.
 */
 int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
-  if( !pCur->isValid ){
-    return pCur->status;
-  }
+  assert( pCur->isValid );
   assert( pCur->pPage!=0 );
   assert( pCur->pPage->intKey==0 );
   assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
@@ -2363,9 +2358,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
 ** the available payload.
 */
 int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
-  if( !pCur->isValid ){
-    return pCur->status ? pCur->status : SQLITE_INTERNAL;
-  }
+  assert( pCur->isValid );
   assert( pCur->pPage!=0 );
   assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
   return getPayload(pCur, offset, amt, pBuf, 1);
@@ -2603,9 +2596,6 @@ static int moveToRightmost(BtCursor *pCur){
 */
 int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
   int rc;
-  if( pCur->status ){
-    return pCur->status;
-  }
   rc = moveToRoot(pCur);
   if( rc ) return rc;
   if( pCur->isValid==0 ){
@@ -2625,9 +2615,6 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
 */
 int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
   int rc;
-  if( pCur->status ){
-    return pCur->status;
-  }
   rc = moveToRoot(pCur);
   if( rc ) return rc;
   if( pCur->isValid==0 ){
@@ -2670,10 +2657,6 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
 */
 int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
   int rc;
-
-  if( pCur->status ){
-    return pCur->status;
-  }
   rc = moveToRoot(pCur);
   if( rc ) return rc;
   assert( pCur->pPage );
@@ -3274,7 +3257,7 @@ static int fillInCell(
 #endif
       if( rc ){
         releasePage(pToRelease);
-        clearCell(pPage, pCell);
+        /* clearCell(pPage, pCell); */
         return rc;
       }
       put4byte(pPrior, pgnoOvfl);
@@ -3873,7 +3856,8 @@ static int balance_nonroot(MemPage *pPage){
       pNew = apNew[i] = apOld[i];
       pgnoNew[i] = pgnoOld[i];
       apOld[i] = 0;
-      sqlite3pager_write(pNew->aData);
+      rc = sqlite3pager_write(pNew->aData);
+      if( rc ) goto balance_cleanup;
     }else{
       rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0);
       if( rc ) goto balance_cleanup;
@@ -4236,9 +4220,6 @@ int sqlite3BtreeInsert(
   unsigned char *oldCell;
   unsigned char *newCell = 0;
 
-  if( pCur->status ){
-    return pCur->status;  /* A rollback destroyed this cursor */
-  }
   if( pBt->inTrans!=TRANS_WRITE ){
     /* Must start a transaction before doing an insert */
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@@ -4310,9 +4291,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
   Btree *pBt = pCur->pBt;
 
   assert( pPage->isInit );
-  if( pCur->status ){
-    return pCur->status;  /* A rollback destroyed this cursor */
-  }
   if( pBt->inTrans!=TRANS_WRITE ){
     /* Must start a transaction before doing a delete */
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@@ -4338,7 +4316,8 @@ int sqlite3BtreeDelete(BtCursor *pCur){
   if( !pPage->leaf ){
     pgnoChild = get4byte(pCell);
   }
-  clearCell(pPage, pCell);
+  rc = clearCell(pPage, pCell);
+  if( rc ) return rc;
 
   if( !pPage->leaf ){
     /*
@@ -4410,9 +4389,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
     /* Must start a transaction first */
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
   }
-  if( pBt->readOnly ){
-    return SQLITE_READONLY;
-  }
+  assert( !pBt->readOnly );
 
   /* It is illegal to create a table if any cursors are open on the
   ** database. This is because in auto-vacuum mode the backend may
@@ -4771,6 +4748,7 @@ int sqlite3BtreeFlags(BtCursor *pCur){
 ** is used for debugging and testing only.
 */
 #ifdef SQLITE_TEST
+#ifndef SQLITE_OMIT_BTREEPAGEDUMP
 static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){
   int rc;
   MemPage *pPage;
@@ -4867,8 +4845,11 @@ static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){
   fflush(stdout);
   return SQLITE_OK;
 }
+#endif
 int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
+#ifndef SQLITE_OMIT_BTREEPAGEDUMP
   return btreePageDump(pBt, pgno, recursive, 0);
+#endif
 }
 #endif
 
index c59e3a8de3921d6ba23e57a960c602a84da49eea..9702f741f02ac883d56b8954689091def5c8d68c 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.180 2005/01/08 12:42:39 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.181 2005/01/11 10:25:08 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -935,12 +935,14 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
     rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize);
   }
   if( pPg ){
-    /* No page should ever be rolled back that is in use, except for page
-    ** 1 which is held in use in order to keep the lock on the database
-    ** active.
+    /* No page should ever be explicitly rolled back that is in use, except
+    ** for page 1 which is held in use in order to keep the lock on the
+    ** database active. However such a page may be rolled back as a result
+    ** of an internal error resulting in an automatic call to
+    ** sqlite3pager_rollback().
     */
     void *pData;
-    assert( pPg->nRef==0 || pPg->pgno==1 );
+    /* assert( pPg->nRef==0 || pPg->pgno==1 ); */
     pData = PGHDR_TO_DATA(pPg);
     memcpy(pData, aData, pPager->pageSize);
     if( pPager->xDestructor ){  /*** FIX ME:  Should this be xReinit? ***/
index 53cdf663f0d80f8d1a9b29ec55dfa68492f7f4fe..7b9e151ef1677ff3b0d89ee76733c5fc54843729 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.82 2005/01/08 15:44:26 drh Exp $
+** $Id: pragma.c,v 1.83 2005/01/11 10:25:08 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -285,7 +285,7 @@ void sqlite3Pragma(
       int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0;
       returnSingleInt(pParse, "page_size", size);
     }else{
-      sqlite3BtreeSetPageSize(pBt, atoi(zRight), sqlite3BtreeGetReserve(pBt));
+      sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
     }
   }else
 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
index df61740eb0519267f78aebe6f6f04f79dbab4a00..a05345203d15c739a155798ecc6c105d50504ea4 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.437 2005/01/10 12:59:53 danielk1977 Exp $
+** $Id: vdbe.c,v 1.438 2005/01/11 10:25:08 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -2565,12 +2565,18 @@ case OP_MoveGt: {
         pTos--;
         break;
       }
-      sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
+      rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
+      if( rc!=SQLITE_OK ){
+        goto abort_due_to_error;
+      }
       pC->lastRecno = pTos->i;
       pC->recnoIsValid = res==0;
     }else{
       Stringify(pTos, db->enc);
-      sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
+      rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
+      if( rc!=SQLITE_OK ){
+        goto abort_due_to_error;
+      }
       pC->recnoIsValid = 0;
     }
     pC->deferredMoveto = 0;
@@ -2579,7 +2585,10 @@ case OP_MoveGt: {
     sqlite3_search_count++;
     if( oc==OP_MoveGe || oc==OP_MoveGt ){
       if( res<0 ){
-        sqlite3BtreeNext(pC->pCursor, &res);
+        rc = sqlite3BtreeNext(pC->pCursor, &res);
+        if( rc!=SQLITE_OK ){
+          goto abort_due_to_error;
+        }
         pC->recnoIsValid = 0;
       }else{
         res = 0;
@@ -2800,12 +2809,14 @@ case OP_NotExists: {
     assert( pTos->flags & MEM_Int );
     assert( p->apCsr[i]->intKey );
     iKey = intToKey(pTos->i);
-    rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
+    // rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
+    rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
     pC->lastRecno = pTos->i;
     pC->recnoIsValid = res==0;
     pC->nullRow = 0;
     pC->cacheValid = 0;
-    if( rx!=SQLITE_OK || res!=0 ){
+    // if( rx!=SQLITE_OK || res!=0 ){
+    if( res!=0 ){
       pc = pOp->p2 - 1;
       pC->recnoIsValid = 0;
     }
diff --git a/test/autovacuum_ioerr.test b/test/autovacuum_ioerr.test
new file mode 100644 (file)
index 0000000..e758444
--- /dev/null
@@ -0,0 +1,50 @@
+# 2001 September 15
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file runs the tests in the file crash.test with auto-vacuum enabled
+# databases.
+#
+# $Id: autovacuum_ioerr.test,v 1.1 2005/01/11 10:25:07 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+rename finish_test really_finish_test2
+proc finish_test {} {}
+set ISQUICK 1
+
+rename sqlite3 real_sqlite3
+proc sqlite3 {args} {
+  set r [eval "real_sqlite3 $args"]
+  if { [llength $args] == 2 } {
+    [lindex $args 0] eval {pragma auto_vacuum = 1}
+  }
+  set r
+}
+
+rename do_test really_do_test
+proc do_test {args} {
+  set sc [concat really_do_test "autovacuum-[lindex $args 0]" \
+      [lrange $args 1 end]]
+  eval $sc
+}
+
+source $testdir/ioerr.test
+
+rename sqlite3 ""
+rename real_sqlite3 sqlite3
+rename finish_test ""
+rename really_finish_test2 finish_test
+rename do_test ""
+rename really_do_test do_test
+finish_test
+
+
+
diff --git a/test/autovacuum_ioerr2.test b/test/autovacuum_ioerr2.test
new file mode 100644 (file)
index 0000000..9817f6d
--- /dev/null
@@ -0,0 +1,189 @@
+# 2001 October 12
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.  The
+# focus of this file is testing for correct handling of I/O errors
+# such as writes failing because the disk is full.
+# 
+# The tests in this file use special facilities that are only
+# available in the SQLite test fixture.
+#
+# $Id: autovacuum_ioerr2.test,v 1.1 2005/01/11 10:25:07 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+proc opendb {} {
+  catch {file delete -force test.db}
+  catch {file delete -force test.db-journal}
+  sqlite3 db test.db
+  execsql {pragma auto_vacuum = 1}
+  execsql {SELECT * FROM sqlite_master}
+}
+
+set ::go 1
+for {set n 1} {$go} {incr n} {
+  do_test autovacuum-ioerr2-1.$n.1 {
+    set ::sqlite_io_error_pending 0
+    db close
+    opendb
+    execsql {
+      CREATE TABLE abc(a);
+      INSERT INTO abc VALUES(randstr(1500,1500));
+    }
+    expr [file size test.db]/1024
+  } {4}
+  do_test autovacuum-ioerr2-1.$n.2 [subst {
+    set ::sqlite_io_error_pending $n
+  }] $n
+  do_test autovacuum-ioerr2-1.$n.3 {
+    set r [catch {db eval {
+      CREATE TABLE abc2(a);
+      BEGIN;
+      DELETE FROM abc;
+      INSERT INTO abc VALUES(randstr(1500,1500));
+      CREATE TABLE abc3(a);
+      COMMIT;
+    }} msg]
+    set ::go [expr {$::sqlite_io_error_pending<=0}]
+    expr {$::sqlite_io_error_pending>0 || $r!=0}
+  } {1}
+}
+set ::sqlite_io_error_pending 0
+
+set ::go 1
+for {set n 1} {$go} {incr n} {
+  do_test autovacuum-ioerr2-2.$n.1 {
+    set ::sqlite_io_error_pending 0
+    db close
+    opendb
+    execsql {
+      PRAGMA cache_size = 10;
+      BEGIN;
+      CREATE TABLE abc(a);
+      INSERT INTO abc VALUES(randstr(1100,1100)); -- Page 4 is overflow
+      INSERT INTO abc VALUES(randstr(1100,1100)); -- Page 5 is overflow
+    }
+    for {set i 0} {$i<150} {incr i} {
+      execsql {
+        INSERT INTO abc VALUES(randstr(100,100)); 
+      }
+    }
+    execsql COMMIT
+    expr [file size test.db]/1024
+  } {24}
+  do_test autovacuum-ioerr2-2.$n.2 [subst {
+    set ::sqlite_io_error_pending $n
+  }] $n
+  do_test autovacuum-ioerr2-2.$n.3 {
+    set r [catch {db eval {
+      BEGIN;
+      DELETE FROM abc WHERE length(a)>100;
+      UPDATE abc SET a = randstr(90,90);
+      CREATE TABLE abc3(a);
+      COMMIT;
+    }} msg]
+    set ::go [expr {$::sqlite_io_error_pending<=0}]
+    expr {$::sqlite_io_error_pending>0 || $r!=0}
+  } {1}
+}
+set ::sqlite_io_error_pending 0
+
+set ::go 1
+for {set n 1} {$go} {incr n} {
+  do_test autovacuum-ioerr2-3.$n.1 {
+    set ::sqlite_io_error_pending 0
+    db close
+    opendb
+    execsql {
+      CREATE TABLE abc(a);
+      CREATE TABLE abc2(b);
+    }
+  } {}
+  do_test autovacuum-ioerr2-3.$n.2 [subst {
+    set ::sqlite_io_error_pending $n
+  }] $n
+  do_test autovacuum-ioerr2-3.$n.3 {
+    set r [catch {db eval {
+      BEGIN;
+      INSERT INTO abc2 VALUES(10);
+      DROP TABLE abc;
+      COMMIT;
+      DROP TABLE abc2;
+    }} msg]
+    set ::go [expr {$::sqlite_io_error_pending<=0}]
+    expr {$::sqlite_io_error_pending>0 || $r!=0}
+  } {1}
+}
+set ::sqlite_io_error_pending 0
+
+do_test autovacuum-ioerr2.4.0 {
+  db close
+  opendb
+  execsql {
+    PRAGMA cache_size = 10;
+    BEGIN;
+    CREATE TABLE abc(a);
+    INSERT INTO abc VALUES(randstr(1100,1100)); -- Page 4 is overflow
+    INSERT INTO abc VALUES(randstr(1100,1100)); -- Page 5 is overflow
+  }
+  for {set i 0} {$i<2500} {incr i} {
+    execsql {
+      INSERT INTO abc VALUES(randstr(100,100)); 
+    }
+  }
+  execsql COMMIT
+  file copy -force test.db backup.db
+} {}
+
+proc opendb2 {} {
+  catch {file delete -force test.db}
+  catch {file delete -force test.db-journal}
+  file copy backup.db test.db
+  sqlite3 db test.db
+  execsql {select * from sqlite_master}
+  execsql {PRAGMA cache_size = 10}
+  return ""
+}
+
+set ::go 1
+for {set n 1} {$go} {incr n} {
+  do_test autovacuum-ioerr2-4.$n.1 {
+    set ::sqlite_io_error_pending 0
+    db close
+    opendb2
+  } {}
+  do_test autovacuum-ioerr2-4.$n.2 [subst {
+    set ::sqlite_io_error_pending $n
+  }] $n
+  do_test autovacuum-ioerr2-4.$n.3 {
+    set r [catch {db eval {
+      BEGIN;
+      DELETE FROM abc WHERE oid < 3;
+      UPDATE abc SET a = randstr(100,100) WHERE oid > 2300;
+      UPDATE abc SET a = randstr(1100,1100) WHERE oid = 
+          (select max(oid) from abc);
+      COMMIT;
+    }} msg]
+    set ::go [expr {$::sqlite_io_error_pending<=0}]
+    expr {$::sqlite_io_error_pending>0 || $r!=0}
+  } {1}
+}
+set ::sqlite_io_error_pending 0
+
+
+rename opendb ""
+db close
+catch {file delete -force test.db}
+catch {file delete -force test.db-journal}
+
+finish_test
+
+
index ed719b687f3400c0657c80711e09720e9d131c55..8e882951d9ad7a95ce6fd012c43dc2f8f7289d75 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is btree database backend
 #
-# $Id: btree.test,v 1.34 2005/01/10 12:59:53 danielk1977 Exp $
+# $Id: btree.test,v 1.35 2005/01/11 10:25:07 danielk1977 Exp $
 
 
 set testdir [file dirname $argv0]
@@ -197,10 +197,13 @@ do_test btree-3.20.1 {
 do_test btree-3.20.2 {
   btree_eof $::c1
 } {1}
-do_test btree-3.21 {
-  set rc [catch {btree_data $::c1} res]
-  lappend rc $res
-} {1 SQLITE_INTERNAL}
+# This test case used to test that one couldn't request data from an 
+# invalid cursor. That is now an assert()ed condition.
+#
+# do_test btree-3.21 {
+#   set rc [catch {btree_data $::c1} res]
+#   lappend rc $res
+# } {1 SQLITE_INTERNAL}
 
 # Commit the changes, reopen and reread the data
 #
@@ -278,10 +281,13 @@ do_test btree-3.39 {
   btree_next $::c1
   btree_key $::c1
 } {0}
-do_test btree-3.40 {
-  set rc [catch {btree_data $::c1} res]
-  lappend rc $res
-} {1 SQLITE_INTERNAL}
+# This test case used to test that requesting data from an invalid cursor
+# returned SQLITE_INTERNAL. That is now an assert()ed condition.
+#
+# do_test btree-3.40 {
+#   set rc [catch {btree_data $::c1} res]
+#   lappend rc $res
+# } {1 SQLITE_INTERNAL}
 do_test btree-3.41 {
   lindex [btree_pager_stats $::b1] 1
 } {1}
@@ -489,10 +495,13 @@ do_test btree-6.9 {
   lindex [btree_pager_stats $::b1] 1
 } {2}
 
-do_test btree-6.9.1 {
-  btree_move_to $::c2 {}
-  btree_key $::c2
-} {}
+# This test case used to test that requesting the key from an invalid cursor
+# returned an empty string.  But that is now an assert()ed condition.
+#
+# do_test btree-6.9.1 {
+#   btree_move_to $::c2 {}
+#   btree_key $::c2
+# } {}
 
 # If we drop table 1 it just clears the table.  Table 1 always exists.
 #
@@ -1035,8 +1044,10 @@ btree_pager_ref_dump $::b1
 
 # Miscellaneous tests.
 #
-# btree-16.1 - Check that a statement cannot be started if a transaction is not
-#              active.
+# btree-16.1 - Check that a statement cannot be started if a transaction 
+#              is not active.
+# btree-16.2 - Check that it is an error to request more payload from a 
+#              btree entry than the entry contains.
 do_test btree-16.1 {
   catch {btree_begin_statement $::b1} msg
   set msg
@@ -1058,6 +1069,89 @@ do_test btree-16.4 {
   set msg
 } SQLITE_ERROR
 
+if {$tcl_platform(platform)=="unix"} {
+  do_test btree-16.5 {
+    btree_close $::b1
+    set ::origperm [file attributes test1.bt -permissions]
+    file attributes test1.bt -permissions o-w,g-w,a-w
+    set ::b1 [btree_open test1.bt 2000 0]
+    catch {btree_cursor $::b1 2 1} msg
+    file attributes test1.bt -permissions $::origperm
+    btree_close $::b1
+    set ::b1 [btree_open test1.bt 2000 0]
+    set msg
+  } {SQLITE_READONLY}
+}
+
+do_test btree-16.6 {
+  set ::c1 [btree_cursor $::b1 2 1]
+  set ::c2 [btree_cursor $::b1 2 1]
+  btree_begin_transaction $::b1
+  for {set i 0} {$i<100} {incr i} {
+    btree_insert $::c1 $i [string repeat helloworld 10]
+  }
+  btree_last $::c2
+  btree_insert $::c1 100 [string repeat helloworld 10]
+} {}
+
+do_test btree-16.7 {
+  btree_close_cursor $::c1
+  btree_close_cursor $::c2
+  btree_commit $::b1
+  set ::c1 [btree_cursor $::b1 2 1]
+  catch {btree_insert $::c1 101 helloworld} msg
+  set msg
+} {SQLITE_ERROR}
+do_test btree-16.8 {
+  btree_first $::c1
+  catch {btree_delete $::c1} msg
+  set msg
+} {SQLITE_ERROR}
+do_test btree-16.9 {
+  btree_close_cursor $::c1
+  btree_begin_transaction $::b1
+  set ::c1 [btree_cursor $::b1 2 0]
+  catch {btree_insert $::c1 101 helloworld} msg
+  set msg
+} {SQLITE_PERM}
+do_test btree-16.10 {
+  catch {btree_delete $::c1} msg
+  set msg
+} {SQLITE_PERM}
+do_test btree-16.11 {
+  btree_close_cursor $::c1
+  set ::c2 [btree_cursor $::b1 2 1]
+  set ::c1 [btree_cursor $::b1 2 0]
+  catch {btree_insert $::c2 101 helloworld} msg
+  set msg
+} {SQLITE_LOCKED}
+do_test btree-16.12 {
+  btree_first $::c2
+  catch {btree_delete $::c2} msg
+  set msg
+} {SQLITE_LOCKED}
+do_test btree-16.13 {
+  catch {btree_clear_table $::b1 2} msg
+  set msg
+} {SQLITE_LOCKED}
+do_test btree-16.14 {
+  btree_close_cursor $::c1
+  btree_close_cursor $::c2
+  btree_commit $::b1
+  catch {btree_clear_table $::b1 2} msg
+  set msg
+} {SQLITE_ERROR}
+do_test btree-16.15 {
+  catch {btree_drop_table $::b1 2} msg
+  set msg
+} {SQLITE_ERROR}
+do_test btree-16.16 {
+  btree_begin_transaction $::b1
+  set ::c1 [btree_cursor $::b1 2 0]
+  catch {btree_drop_table $::b1 2} msg
+  set msg
+} {SQLITE_LOCKED}
+
 do_test btree-99.1 {
   btree_close $::b1
 } {}
index 65d32dfc1c60166aba31f39dec637c0adfd87e6a..515ba8e76a9e491aef332dac333bdf318eac1d49 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is btree database backend
 #
-# $Id: btree2.test,v 1.13 2004/05/10 16:18:48 drh Exp $
+# $Id: btree2.test,v 1.14 2005/01/11 10:25:07 danielk1977 Exp $
 
 
 set testdir [file dirname $argv0]
@@ -143,10 +143,16 @@ proc check_invariants {} {
   set L [btree_data $::c2]
   set LM1 [expr {$L-1}]
   for {set i 1} {$i<=$N} {incr i} {
-    set key [btree_key $::c3]
+    set key {}
+    if {![btree_eof $::c3]} {
+      set key [btree_key $::c3]
+    }
     if {[scan $key %d k]<1} {set k 0}
     if {$k!=$i} {
-      set key [btree_key $::c4]
+      set key {}
+      if {![btree_eof $::c4]} {
+        set key [btree_key $::c4]
+      }
       if {[scan $key %d k]<1} {set k 0}
       if {$k!=$i} {
         return "Key $i is missing from both foreground and background"
@@ -252,19 +258,26 @@ proc random_changes {n I K D} {
       btree_delete $::c3
     } else {
       if {$c<0} {btree_next $::c3}
-      if {[string match $basekey* [btree_key $::c3]]} {
-        btree_delete $::c3
+      if {![btree_eof $::c3]} {
+        if {[string match $basekey* [btree_key $::c3]]} {
+          btree_delete $::c3
+        }
       }
     }
     if {[set c [btree_move_to $::c4 $basekey]]==0} {
       btree_delete $::c4
     } else {
       if {$c<0} {btree_next $::c4}
-      if {[string match $basekey* [btree_key $::c4]]} {
-        btree_delete $::c4
+      if {![btree_eof $::c4]} {
+        if {[string match $basekey* [btree_key $::c4]]} {
+          btree_delete $::c4
+        }
       }
     }
-    if {[scan [btree_key $::c4] %d kx]<1} {set kx -1}
+    set kx -1
+    if {![btree_eof $::c4]} {
+      if {[scan [btree_key $::c4] %d kx]<1} {set kx -1}
+    }
     if {$kx==$k} {
       btree_delete $::c4
     }
diff --git a/test/corrupt2.test b/test/corrupt2.test
new file mode 100644 (file)
index 0000000..9b17fca
--- /dev/null
@@ -0,0 +1,109 @@
+# 2004 August 30
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests to make sure SQLite does not crash or
+# segfault if it sees a corrupt database file.
+#
+# $Id: corrupt2.test,v 1.1 2005/01/11 10:25:07 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# The following tests - corrupt2-1.* - create some databases corrupted in
+# specific ways and ensure that SQLite detects them as corrupt.
+#
+do_test corrupt2-1.1 {
+  execsql {
+    CREATE TABLE abc(a, b, c);
+  }
+} {}
+
+do_test corrupt2-1.2 {
+
+  # Corrupt the 16 byte magic string at the start of the file
+  file delete -force corrupt.db
+  file delete -force corrupt.db-journal
+  file copy test.db corrupt.db
+  set f [open corrupt.db a]
+  seek $f 8 start
+  puts $f blah
+  close $f
+
+  sqlite3 db2 corrupt.db
+  catchsql {
+    SELECT * FROM sqlite_master;
+  } db2
+} {1 {file is encrypted or is not a database}}
+
+do_test corrupt2-1.3 {
+  db2 close
+
+  # Corrupt the page-size (bytes 16 and 17 of page 1).
+  file delete -force corrupt.db
+  file delete -force corrupt.db-journal
+  file copy test.db corrupt.db
+  set f [open corrupt.db a]
+  fconfigure $f -encoding binary
+  seek $f 16 start
+  puts -nonewline $f "\x00\xFF"
+  close $f
+
+  sqlite3 db2 corrupt.db
+  catchsql {
+    SELECT * FROM sqlite_master;
+  } db2
+} {1 {file is encrypted or is not a database}}
+
+do_test corrupt2-1.4 {
+  db2 close
+
+  # Corrupt the free-block list on page 1.
+  file delete -force corrupt.db
+  file delete -force corrupt.db-journal
+  file copy test.db corrupt.db
+  set f [open corrupt.db a]
+  fconfigure $f -encoding binary
+  seek $f 101 start
+  puts -nonewline $f "\xFF\xFF"
+  close $f
+
+  sqlite3 db2 corrupt.db
+  catchsql {
+    SELECT * FROM sqlite_master;
+  } db2
+} {1 {database disk image is malformed}}
+
+do_test corrupt2-1.5 {
+  db2 close
+
+  # Corrupt the free-block list on page 1.
+  file delete -force corrupt.db
+  file delete -force corrupt.db-journal
+  file copy test.db corrupt.db
+  set f [open corrupt.db a]
+  fconfigure $f -encoding binary
+  seek $f 101 start
+  puts -nonewline $f "\x00\xC8"
+  seek $f 200 start
+  puts -nonewline $f "\x00\x00"
+  puts -nonewline $f "\x10\x00"
+  close $f
+
+  sqlite3 db2 corrupt.db
+  catchsql {
+    SELECT * FROM sqlite_master;
+  } db2
+} {1 {database disk image is malformed}}
+db2 close
+
+finish_test
+
index 21e7ac4b5947c0e564abfd5a775f1430c593fb22..06a32da33e8a869caadd1c8924ccd68fb84c6e7d 100644 (file)
@@ -15,7 +15,7 @@
 # The tests in this file use special facilities that are only
 # available in the SQLite test fixture.
 #
-# $Id: ioerr.test,v 1.8 2005/01/10 12:59:53 danielk1977 Exp $
+# $Id: ioerr.test,v 1.9 2005/01/11 10:25:07 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -135,4 +135,43 @@ for {set n 1} {$go} {incr n} {
 }
 set ::sqlite_io_error_pending 0
 
+set ::go 1
+for {set n 1} {$go} {incr n} {
+  do_test ioerr-3.$n.1 {
+    set ::sqlite_io_error_pending 0
+    db close
+    catch {file delete -force test.db}
+    catch {file delete -force test.db-journal}
+    sqlite3 db test.db
+    execsql {
+      PRAGMA cache_size = 10;
+      BEGIN;
+      CREATE TABLE abc(a);
+      INSERT INTO abc VALUES(randstr(1500,1500)); -- Page 4 is overflow
+    }
+    for {set i 0} {$i<150} {incr i} {
+      execsql {
+        INSERT INTO abc VALUES(randstr(100,100)); 
+      }
+    }
+    execsql COMMIT
+  } {}
+  do_test ioerr-3.$n.2 [subst {
+    set ::sqlite_io_error_pending $n
+  }] $n
+  do_test ioerr-3.$n.3 {
+    set r [catch {db eval {
+      CREATE TABLE abc2(a);
+      BEGIN;
+      DELETE FROM abc WHERE length(a)>100;
+      UPDATE abc SET a = randstr(90,90);
+      COMMIT;
+      CREATE TABLE abc3(a);
+    }} msg]
+    set ::go [expr {$::sqlite_io_error_pending<=0}]
+    expr {$::sqlite_io_error_pending>0 || $r!=0}
+  } {1}
+}
+set ::sqlite_io_error_pending 0
+
 finish_test