SQLite

Check-in [bfd563c471]
Login

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

Overview
Comment:Further test cases for pager1.test and pagerfault.test.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: bfd563c4714d86805fa09ce9f4f807e5d502a99b
User & Date: dan 2010-06-25 19:09:48.000
Context
2010-06-26
15:42
When synchronous=NORMAL, use the same journal file format as with synchronous=FULL (i.e. multiple journal headers within the one journal). Fix for [d11f09d36e]. (check-in: 2eaf5ee0d9 user: dan tags: trunk)
2010-06-25
19:09
Further test cases for pager1.test and pagerfault.test. (check-in: bfd563c471 user: dan tags: trunk)
16:34
Reduce the average (but not maximum) size of the allocations made as part of a checkpoint. (check-in: 4a7fd91b7a user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/test_vfs.c.
33
34
35
36
37
38
39










40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57





58
59
60
61
62
63
64

65
66
67
68
69
70
71

  TestvfsBuffer *pShm;            /* Shared memory buffer */
  u32 excllock;                   /* Mask of exclusive locks */
  u32 sharedlock;                 /* Mask of shared locks */
  TestvfsFile *pNext;             /* Next handle opened on the same file */
};












/*
** An instance of this structure is allocated for each VFS created. The
** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
** is set to point to it.
*/
struct Testvfs {
  char *zName;                    /* Name of this VFS */
  sqlite3_vfs *pParent;           /* The VFS to use for file IO */
  sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
  Tcl_Interp *interp;             /* Interpreter to run script in */
  Tcl_Obj *pScript;               /* Script to execute */
  int nScript;                    /* Number of elements in array apScript */
  Tcl_Obj **apScript;             /* Array version of pScript */
  TestvfsBuffer *pBuffer;         /* List of shared buffers */
  int isNoshm;


  int mask;





  int iIoerrCnt;
  int ioerr;
  int nIoerrFail;

  int iFullCnt;
  int fullerr;
  int nFullFail;


  int iDevchar;
  int iSectorsize;
};

/*
** The Testvfs.mask variable is set to a combination of the following.







>
>
>
>
>
>
>
>
>
>

















>
|
>
>
>
>
>



<



>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86
87

  TestvfsBuffer *pShm;            /* Shared memory buffer */
  u32 excllock;                   /* Mask of exclusive locks */
  u32 sharedlock;                 /* Mask of shared locks */
  TestvfsFile *pNext;             /* Next handle opened on the same file */
};

#define FAULT_INJECT_NONE       0
#define FAULT_INJECT_TRANSIENT  1
#define FAULT_INJECT_PERSISTENT 2

typedef struct TestFaultInject TestFaultInject;
struct TestFaultInject {
  int iCnt;                       /* Remaining calls before fault injection */
  int eFault;                     /* A FAULT_INJECT_* value */
  int nFail;                      /* Number of faults injected */
};

/*
** An instance of this structure is allocated for each VFS created. The
** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
** is set to point to it.
*/
struct Testvfs {
  char *zName;                    /* Name of this VFS */
  sqlite3_vfs *pParent;           /* The VFS to use for file IO */
  sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
  Tcl_Interp *interp;             /* Interpreter to run script in */
  Tcl_Obj *pScript;               /* Script to execute */
  int nScript;                    /* Number of elements in array apScript */
  Tcl_Obj **apScript;             /* Array version of pScript */
  TestvfsBuffer *pBuffer;         /* List of shared buffers */
  int isNoshm;

  int mask;                       /* Mask controlling [script] and [ioerr] */

  TestFaultInject ioerr_err;
  TestFaultInject full_err;
  TestFaultInject cantopen_err;

#if 0
  int iIoerrCnt;
  int ioerr;
  int nIoerrFail;

  int iFullCnt;
  int fullerr;
  int nFullFail;
#endif

  int iDevchar;
  int iSectorsize;
};

/*
** The Testvfs.mask variable is set to a combination of the following.
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97

#define TESTVFS_OPEN_MASK       0x00000100
#define TESTVFS_SYNC_MASK       0x00000200
#define TESTVFS_DELETE_MASK     0x00000400
#define TESTVFS_CLOSE_MASK      0x00000800
#define TESTVFS_WRITE_MASK      0x00001000
#define TESTVFS_TRUNCATE_MASK   0x00002000

#define TESTVFS_ALL_MASK        0x00003FFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
** memory region opened by clients. If two clients open the same file,







>
|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

#define TESTVFS_OPEN_MASK       0x00000100
#define TESTVFS_SYNC_MASK       0x00000200
#define TESTVFS_DELETE_MASK     0x00000400
#define TESTVFS_CLOSE_MASK      0x00000800
#define TESTVFS_WRITE_MASK      0x00001000
#define TESTVFS_TRUNCATE_MASK   0x00002000
#define TESTVFS_ACCESS_MASK     0x00004000
#define TESTVFS_ALL_MASK        0x00007FFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
** memory region opened by clients. If two clients open the same file,
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219
220

221



222
223
224
225
226
227
228
      return 1;
    }
  }

  return 0;
}

static int tvfsInjectIoerr(Testvfs *p){
  int ret = 0;
  if( p->ioerr ){
    p->iIoerrCnt--;
    if( p->iIoerrCnt==0 || (p->iIoerrCnt<0 && p->ioerr==2) ){
      ret = 1;
      p->nIoerrFail++;
    }
  }
  return ret;
}


static int tvfsInjectFullerr(Testvfs *p){
  int ret = 0;
  if( p->fullerr ){
    p->iFullCnt--;
    if( p->iFullCnt<=0 ){
      ret = 1;
      p->nFullFail++;
    }
  }

  return ret;



}


static void tvfsExecTcl(
  Testvfs *p, 
  const char *zMethod,
  Tcl_Obj *arg1,







|

|
|
|

|





>
|
<
<
|
<
<
<
|
|
>
|
>
>
>







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230


231



232
233
234
235
236
237
238
239
240
241
242
243
244
245
      return 1;
    }
  }

  return 0;
}

static int tvfsInjectFault(TestFaultInject *p){
  int ret = 0;
  if( p->eFault ){
    p->iCnt--;
    if( p->iCnt==0 || (p->iCnt<0 && p->eFault==FAULT_INJECT_PERSISTENT ) ){
      ret = 1;
      p->nFail++;
    }
  }
  return ret;
}


static int tvfsInjectIoerr(Testvfs *p){


  return tvfsInjectFault(&p->ioerr_err);



}

static int tvfsInjectFullerr(Testvfs *p){
  return tvfsInjectFault(&p->full_err);
}
static int tvfsInjectCantopenerr(Testvfs *p){
  return tvfsInjectFault(&p->cantopen_err);
}


static void tvfsExecTcl(
  Testvfs *p, 
  const char *zMethod,
  Tcl_Obj *arg1,
508
509
510
511
512
513
514





515
516
517
518
519
520

521
522
523
524
525
526
527
    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
    if( tvfsResultCode(p, &rc) ){
      if( rc!=SQLITE_OK ) return rc;
    }else{
      pId = Tcl_GetObjResult(p->interp);
    }
  }





  if( !pId ){
    pId = Tcl_NewStringObj("anon", -1);
  }
  Tcl_IncrRefCount(pId);
  pFd->pShmId = pId;
  Tcl_ResetResult(p->interp);


  rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags);
  if( pFd->pReal->pMethods ){
    sqlite3_io_methods *pMethods;
    pMethods = (sqlite3_io_methods *)ckalloc(sizeof(sqlite3_io_methods));
    memcpy(pMethods, &tvfs_io_methods, sizeof(sqlite3_io_methods));
    if( ((Testvfs *)pVfs->pAppData)->isNoshm ){







>
>
>
>
>






>







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
    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
    if( tvfsResultCode(p, &rc) ){
      if( rc!=SQLITE_OK ) return rc;
    }else{
      pId = Tcl_GetObjResult(p->interp);
    }
  }

  if( (p->mask&TESTVFS_OPEN_MASK) &&  tvfsInjectIoerr(p) ) return SQLITE_IOERR;
  if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN;
  if( tvfsInjectFullerr(p) ) return SQLITE_FULL;

  if( !pId ){
    pId = Tcl_NewStringObj("anon", -1);
  }
  Tcl_IncrRefCount(pId);
  pFd->pShmId = pId;
  Tcl_ResetResult(p->interp);


  rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags);
  if( pFd->pReal->pMethods ){
    sqlite3_io_methods *pMethods;
    pMethods = (sqlite3_io_methods *)ckalloc(sizeof(sqlite3_io_methods));
    memcpy(pMethods, &tvfs_io_methods, sizeof(sqlite3_io_methods));
    if( ((Testvfs *)pVfs->pAppData)->isNoshm ){
564
565
566
567
568
569
570



















571
572
573
574
575
576
577
*/
static int tvfsAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){



















  return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut);
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (DEVSYM_MAX_PATHNAME+1) bytes.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
*/
static int tvfsAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){
  Testvfs *p = (Testvfs *)pVfs->pAppData;
  if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){
    int rc;
    char *zArg = 0;
    if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS";
    if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE";
    if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ";
    tvfsExecTcl(p, "xAccess", 
        Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0
    );
    if( tvfsResultCode(p, &rc) ){
      if( rc!=SQLITE_OK ) return rc;
    }else{
      Tcl_Interp *interp = p->interp;
      if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){
        return SQLITE_OK;
      }
    }
  }
  return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut);
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

871
872
873
874
875
876
877
878
879
880
  int objc,
  Tcl_Obj *CONST objv[]
){
  Testvfs *p = (Testvfs *)cd;

  enum DB_enum { 
    CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT, 
    CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR
  };
  struct TestvfsSubcmd {
    char *zName;
    enum DB_enum eCmd;
  } aSubcmd[] = {
    { "shm",        CMD_SHM        },
    { "delete",     CMD_DELETE     },
    { "filter",     CMD_FILTER     },
    { "ioerr",      CMD_IOERR      },
    { "fullerr",    CMD_FULLERR    },

    { "script",     CMD_SCRIPT     },
    { "devchar",    CMD_DEVCHAR    },
    { "sectorsize", CMD_SECTORSIZE },
    { 0, 0 }
  };
  int i;
  
  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;







|





|
|
|
|
|
>
|
|
|







895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
  int objc,
  Tcl_Obj *CONST objv[]
){
  Testvfs *p = (Testvfs *)cd;

  enum DB_enum { 
    CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT, 
    CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR, CMD_CANTOPENERR
  };
  struct TestvfsSubcmd {
    char *zName;
    enum DB_enum eCmd;
  } aSubcmd[] = {
    { "shm",         CMD_SHM         },
    { "delete",      CMD_DELETE      },
    { "filter",      CMD_FILTER      },
    { "ioerr",       CMD_IOERR       },
    { "fullerr",     CMD_FULLERR     },
    { "cantopenerr", CMD_CANTOPENERR },
    { "script",      CMD_SCRIPT      },
    { "devchar",     CMD_DEVCHAR     },
    { "sectorsize",  CMD_SECTORSIZE  },
    { 0, 0 }
  };
  int i;
  
  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
946
947
948
949
950
951
952

953
954
955
956
957
958
959
        { "xShmMap",     TESTVFS_SHMMAP_MASK },
        { "xSync",       TESTVFS_SYNC_MASK },
        { "xDelete",     TESTVFS_DELETE_MASK },
        { "xWrite",      TESTVFS_WRITE_MASK },
        { "xTruncate",   TESTVFS_TRUNCATE_MASK },
        { "xOpen",       TESTVFS_OPEN_MASK },
        { "xClose",      TESTVFS_CLOSE_MASK },

      };
      Tcl_Obj **apElem = 0;
      int nElem = 0;
      int i;
      int mask = 0;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "LIST");







>







989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
        { "xShmMap",     TESTVFS_SHMMAP_MASK },
        { "xSync",       TESTVFS_SYNC_MASK },
        { "xDelete",     TESTVFS_DELETE_MASK },
        { "xWrite",      TESTVFS_WRITE_MASK },
        { "xTruncate",   TESTVFS_TRUNCATE_MASK },
        { "xOpen",       TESTVFS_OPEN_MASK },
        { "xClose",      TESTVFS_CLOSE_MASK },
        { "xAccess",     TESTVFS_ACCESS_MASK },
      };
      Tcl_Obj **apElem = 0;
      int nElem = 0;
      int i;
      int mask = 0;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "LIST");
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042

1043


1044
1045







1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067

      Tcl_ResetResult(interp);
      if( p->pScript ) Tcl_SetObjResult(interp, p->pScript);

      break;
    }

    /*
    ** TESTVFS fullerr ?IFAIL?
    **
    **   Where IFAIL is an integer.
    */
    case CMD_FULLERR: {
      int iRet = p->nFullFail;

      p->nFullFail = 0;
      p->fullerr = 0;
      p->iFullCnt = 0;

      if( objc==3 ){
        int iCnt;
        if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iCnt) ){
          return TCL_ERROR;
        }
        p->fullerr = (iCnt>0);
        p->iFullCnt = iCnt;
      }else if( objc!=2 ){
        Tcl_AppendResult(interp, "Bad args", 0);
        return TCL_ERROR;
      }

      Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet));
      break;
    }

    /*
    ** TESTVFS ioerr ?IFAIL PERSIST?
    **
    **   Where IFAIL is an integer and PERSIST is boolean.
    */

    case CMD_IOERR: {


      int iRet = p->nIoerrFail;








      p->nIoerrFail = 0;
      p->ioerr = 0;
      p->iIoerrCnt = 0;

      if( objc==4 ){
        int iCnt, iPersist;
        if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iCnt)
         || TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &iPersist)
        ){
          return TCL_ERROR;
        }
        p->ioerr = (iCnt>0) + iPersist;
        p->iIoerrCnt = iCnt;
      }else if( objc!=2 ){
        Tcl_AppendResult(interp, "Bad args", 0);
        return TCL_ERROR;
      }
      Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet));
      break;
    }

    case CMD_DELETE: {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





>
|
>
>
|

>
>
>
>
>
>
>
|
|
|








|
|

|







1047
1048
1049
1050
1051
1052
1053




























1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093

      Tcl_ResetResult(interp);
      if( p->pScript ) Tcl_SetObjResult(interp, p->pScript);

      break;
    }





























    /*
    ** TESTVFS ioerr ?IFAIL PERSIST?
    **
    **   Where IFAIL is an integer and PERSIST is boolean.
    */
    case CMD_CANTOPENERR:
    case CMD_IOERR:
    case CMD_FULLERR: {
      TestFaultInject *pTest;
      int iRet;

      switch( aSubcmd[i].eCmd ){
        case CMD_IOERR: pTest = &p->ioerr_err; break;
        case CMD_FULLERR: pTest = &p->full_err; break;
        case CMD_CANTOPENERR: pTest = &p->cantopen_err; break;
        default: assert(0);
      }
      iRet = pTest->nFail;
      pTest->nFail = 0;
      pTest->eFault = 0;
      pTest->iCnt = 0;

      if( objc==4 ){
        int iCnt, iPersist;
        if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iCnt)
         || TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &iPersist)
        ){
          return TCL_ERROR;
        }
        pTest->eFault = iPersist?FAULT_INJECT_PERSISTENT:FAULT_INJECT_TRANSIENT;
        pTest->iCnt = iCnt;
      }else if( objc!=2 ){
        Tcl_WrongNumArgs(interp, 2, objv, "?CNT PERSIST?");
        return TCL_ERROR;
      }
      Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet));
      break;
    }

    case CMD_DELETE: {
Changes to test/malloc_common.tcl.
72
73
74
75
76
77
78

















79
80
81
82
83
84
85
  -injectinstall   shmerr_injectinstall    \
  -injectstart     {shmerr_injectstart 1}  \
  -injectstop      shmerr_injectstop       \
  -injecterrlist   {{1 {disk I/O error}}}  \
  -injectuninstall shmerr_injectuninstall  \
]




















#--------------------------------------------------------------------------
# Usage do_faultsim_test NAME ?OPTIONS...? 
#
#     -faults           List of fault types to simulate.
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  -injectinstall   shmerr_injectinstall    \
  -injectstart     {shmerr_injectstart 1}  \
  -injectstop      shmerr_injectstop       \
  -injecterrlist   {{1 {disk I/O error}}}  \
  -injectuninstall shmerr_injectuninstall  \
]

# Transient and persistent CANTOPEN errors:
#
set FAULTSIM(cantopen-transient) [list       \
  -injectinstall   cantopen_injectinstall    \
  -injectstart     {cantopen_injectstart 0}  \
  -injectstop      cantopen_injectstop       \
  -injecterrlist   {{1 {unable to open database file}}}  \
  -injectuninstall cantopen_injectuninstall  \
]
set FAULTSIM(cantopen-persistent) [list      \
  -injectinstall   cantopen_injectinstall    \
  -injectstart     {cantopen_injectstart 1}  \
  -injectstop      cantopen_injectstop       \
  -injecterrlist   {{1 {unable to open database file}}}  \
  -injectuninstall cantopen_injectuninstall  \
]



#--------------------------------------------------------------------------
# Usage do_faultsim_test NAME ?OPTIONS...? 
#
#     -faults           List of fault types to simulate.
#
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223












224






225
226
227
228
229
230
231
  catch {db2 close}
  shmfault delete
}
proc shmerr_injectstart {persist iFail} {
  shmfault ioerr $iFail $persist
}
proc shmerr_injectstop {} {
  shmfault ioerr 0 0
}

# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting SQLITE_FULL error faults into test cases.
#
proc fullerr_injectinstall {} {
  testvfs shmfault -default true
}
proc fullerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
proc fullerr_injectstart {iFail} {
  shmfault full $iFail
}
proc fullerr_injectstop {} {












  shmfault full 0






}

# This command is not called directly. It is used by the 
# [faultsim_test_result] command created by [do_faultsim_test] and used
# by -test scripts.
#
proc faultsim_test_result_int {args} {







|














|


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







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  catch {db2 close}
  shmfault delete
}
proc shmerr_injectstart {persist iFail} {
  shmfault ioerr $iFail $persist
}
proc shmerr_injectstop {} {
  shmfault ioerr
}

# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting SQLITE_FULL error faults into test cases.
#
proc fullerr_injectinstall {} {
  testvfs shmfault -default true
}
proc fullerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
proc fullerr_injectstart {iFail} {
  shmfault full $iFail 1
}
proc fullerr_injectstop {} {
  shmfault full
}

# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting SQLITE_CANTOPEN error faults into test cases.
#
proc cantopen_injectinstall {} {
  testvfs shmfault -default true
}
proc cantopen_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
proc cantopen_injectstart {persist iFail} {
  shmfault cantopen $iFail $persist
}
proc cantopen_injectstop {} {
  shmfault cantopen
}

# This command is not called directly. It is used by the 
# [faultsim_test_result] command created by [do_faultsim_test] and used
# by -test scripts.
#
proc faultsim_test_result_int {args} {
Changes to test/pager1.test.
1121
1122
1123
1124
1125
1126
1127


1128































1129
1130
1131
} {truncate ok}
do_test pager1-11.4 {
  db2 close
  file size test.db-journal
} {0}
breakpoint
do_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32}


  
































finish_test








>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
} {truncate ok}
do_test pager1-11.4 {
  db2 close
  file size test.db-journal
} {0}
breakpoint
do_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32}
db close
tv delete
  
#-------------------------------------------------------------------------
# Test "PRAGMA page_size"
#
foreach pagesize {
    512   1024   2048 4096 8192 16384 32768 
} {
  faultsim_delete_and_reopen

  do_test pager1-12.$pagesize.1 {
    sqlite3 db2 test.db
    execsql "
      PRAGMA page_size = $pagesize;
      CREATE VIEW v AS SELECT * FROM sqlite_master;
    " db2
    file size test.db
  } $pagesize
  do_test pager1-12.$pagesize.2 {
    sqlite3 db2 test.db
    execsql { 
      SELECT count(*) FROM v;
      PRAGMA main.page_size;
    } db2
  } [list 1 $pagesize]
  do_test pager1-12.$pagesize.3 {
    execsql { 
      SELECT count(*) FROM v;
      PRAGMA main.page_size;
    }
  } [list 1 $pagesize]
  db2 close
}

finish_test

Changes to test/pagerfault.test.
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
























268
269
270
271
272
273
274
  faultsim_integrity_check

  set res ""
  set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }]
  if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"}
}


#-------------------------------------------------------------------------
# Test fault-injection as part of a commit when using 
# journal_mode=TRUNCATE.
#
do_test pagerfault-6-pre1 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    CREATE TABLE t1(a UNIQUE, b UNIQUE);
    INSERT INTO t1 VALUES(a_string(200), a_string(300));
  }
  faultsim_save_and_close
} {}

do_faultsim_test pagerfault-6.1 -prep {
  faultsim_restore_and_reopen
  db func a_string a_string
  execsql { PRAGMA journal_mode = TRUNCATE }
} -body {
























  execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

# The following was an attempt to get a bitvec malloc to fail. Didn't work.







<













>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  faultsim_integrity_check

  set res ""
  set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }]
  if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"}
}


#-------------------------------------------------------------------------
# Test fault-injection as part of a commit when using 
# journal_mode=TRUNCATE.
#
do_test pagerfault-6-pre1 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    CREATE TABLE t1(a UNIQUE, b UNIQUE);
    INSERT INTO t1 VALUES(a_string(200), a_string(300));
  }
  faultsim_save_and_close
} {}

do_faultsim_test pagerfault-6.1 -prep {
  faultsim_restore_and_reopen
  db func a_string a_string
  execsql { PRAGMA journal_mode = TRUNCATE }
} -body {
  execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

# The unix vfs xAccess() method considers a file zero bytes in size to
# "not exist". This proc overrides that behaviour so that a zero length
# file is considered to exist.
#
proc xAccess {method filename op args} {
  if {$op != "SQLITE_ACCESS_EXISTS"} { return "" }
  return [file exists $filename]
}
do_faultsim_test pagerfault-6.2 -faults cantopen-* -prep {
  shmfault filter xAccess
  shmfault script xAccess

  faultsim_restore_and_reopen
  db func a_string a_string
  execsql { PRAGMA journal_mode = TRUNCATE }
} -body {
  execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
  execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

# The following was an attempt to get a bitvec malloc to fail. Didn't work.