Add a test for the outcome of a process crash within an xWrite VFS method
call. FossilOrigin-Name: eb8718006cb23ba9304da5c30d19863d688495f0eaae3794c5ad870e481866f8
This commit is contained in:
parent
4da30f8888
commit
33447e7793
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
|||||||
C Add\sthe\s"atomic-batch-write"\spermutation\sto\spermutations.test.\sThis\npermutation\sfails\sif\snot\srun\son\sa\sfile-system\sthat\ssupports\natomic-batch-writes.
|
C Add\sa\stest\sfor\sthe\soutcome\sof\sa\sprocess\scrash\swithin\san\sxWrite\sVFS\smethod\ncall.
|
||||||
D 2017-07-22T16:58:47.336
|
D 2017-07-22T20:12:31.931
|
||||||
F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
|
F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
|
||||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||||
F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
|
F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
|
||||||
@ -468,7 +468,7 @@ F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
|||||||
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
|
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
|
||||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||||
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
|
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
|
||||||
F src/test6.c 004ad42f121f693b8cbe060d1a330678abc61620
|
F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
|
||||||
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
|
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
|
||||||
F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86
|
F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86
|
||||||
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
|
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
|
||||||
@ -481,7 +481,7 @@ F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
|||||||
F src/test_config.c abf6fc1fe9d041b699578c42e3db81f8831c4f5b804f1927958102ee8f2b773e
|
F src/test_config.c abf6fc1fe9d041b699578c42e3db81f8831c4f5b804f1927958102ee8f2b773e
|
||||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||||
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
|
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
|
||||||
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
|
F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
|
||||||
F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
|
F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
|
||||||
F src/test_func.c a4fdab3363b436c1b12660e9362ce3f3782b7b5e
|
F src/test_func.c a4fdab3363b436c1b12660e9362ce3f3782b7b5e
|
||||||
F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
|
F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
|
||||||
@ -1246,7 +1246,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
|||||||
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
|
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
|
||||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||||
F test/tester.tcl 581f0185434daf7026ccede4c07e8d1479186ec5
|
F test/tester.tcl eb7ec55fe074a909423c1de701f7c545417b8aa96787b8c3e7a79203f2cebec8
|
||||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||||
@ -1542,6 +1542,7 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
|||||||
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
|
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
|
||||||
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
|
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
|
||||||
F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
|
F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
|
||||||
|
F test/writecrash.test e6dc9d470d43710c3f780a50d29cce1c3884ca34ff50e737bc9ab8724c7c2398
|
||||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||||
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
|
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
|
||||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||||
@ -1637,7 +1638,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 2e80e19e4faac30947ed56aa3601c45c758cafb27f84780df255fdbcdc9a6999
|
P 9f1b83fae9c973eee80eefefe7bd3a1eb7bba8af4cd919d7a2ce911900dd9087
|
||||||
R f3cc9474e40dfdafd1378160ccb50876
|
R f23da5f714bc905d7cb0056ef392fdf9
|
||||||
U dan
|
U dan
|
||||||
Z e9e3d5840c0aa48b88a9ce806cb1e69e
|
Z 063d069885d7a39f9c6cf058832bceb7
|
||||||
|
@ -1 +1 @@
|
|||||||
9f1b83fae9c973eee80eefefe7bd3a1eb7bba8af4cd919d7a2ce911900dd9087
|
eb8718006cb23ba9304da5c30d19863d688495f0eaae3794c5ad870e481866f8
|
25
src/test6.c
25
src/test6.c
@ -736,6 +736,7 @@ static int processDevSymArgs(
|
|||||||
{ "sequential", SQLITE_IOCAP_SEQUENTIAL },
|
{ "sequential", SQLITE_IOCAP_SEQUENTIAL },
|
||||||
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
|
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
|
||||||
{ "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
|
{ "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
|
||||||
|
{ "batch-atomic", SQLITE_IOCAP_BATCH_ATOMIC },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -976,7 +977,30 @@ static int SQLITE_TCLAPI devSymObjCmd(
|
|||||||
devsym_register(iDc, iSectorSize);
|
devsym_register(iDc, iSectorSize);
|
||||||
|
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** tclcmd: sqlite3_crash_on_write N
|
||||||
|
*/
|
||||||
|
static int SQLITE_TCLAPI writeCrashObjCmd(
|
||||||
|
void * clientData,
|
||||||
|
Tcl_Interp *interp,
|
||||||
|
int objc,
|
||||||
|
Tcl_Obj *CONST objv[]
|
||||||
|
){
|
||||||
|
void devsym_crash_on_write(int);
|
||||||
|
int nWrite = 0;
|
||||||
|
|
||||||
|
if( objc!=2 ){
|
||||||
|
Tcl_WrongNumArgs(interp, 1, objv, "NWRITE");
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
if( Tcl_GetIntFromObj(interp, objv[1], &nWrite) ){
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
devsym_crash_on_write(nWrite);
|
||||||
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1068,6 +1092,7 @@ int Sqlitetest6_Init(Tcl_Interp *interp){
|
|||||||
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "sqlite3_crash_now", crashNowCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "sqlite3_crash_now", crashNowCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
|
||||||
|
Tcl_CreateObjCommand(interp, "sqlite3_crash_on_write", writeCrashObjCmd,0,0);
|
||||||
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
** Name used to identify this VFS.
|
** Name used to identify this VFS.
|
||||||
*/
|
*/
|
||||||
#define DEVSYM_VFS_NAME "devsym"
|
#define DEVSYM_VFS_NAME "devsym"
|
||||||
|
#define WRITECRASH_NAME "writecrash"
|
||||||
|
|
||||||
typedef struct devsym_file devsym_file;
|
typedef struct devsym_file devsym_file;
|
||||||
struct devsym_file {
|
struct devsym_file {
|
||||||
@ -72,61 +73,13 @@ static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
|||||||
static int devsymSleep(sqlite3_vfs*, int microseconds);
|
static int devsymSleep(sqlite3_vfs*, int microseconds);
|
||||||
static int devsymCurrentTime(sqlite3_vfs*, double*);
|
static int devsymCurrentTime(sqlite3_vfs*, double*);
|
||||||
|
|
||||||
static sqlite3_vfs devsym_vfs = {
|
|
||||||
2, /* iVersion */
|
|
||||||
sizeof(devsym_file), /* szOsFile */
|
|
||||||
DEVSYM_MAX_PATHNAME, /* mxPathname */
|
|
||||||
0, /* pNext */
|
|
||||||
DEVSYM_VFS_NAME, /* zName */
|
|
||||||
0, /* pAppData */
|
|
||||||
devsymOpen, /* xOpen */
|
|
||||||
devsymDelete, /* xDelete */
|
|
||||||
devsymAccess, /* xAccess */
|
|
||||||
devsymFullPathname, /* xFullPathname */
|
|
||||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
||||||
devsymDlOpen, /* xDlOpen */
|
|
||||||
devsymDlError, /* xDlError */
|
|
||||||
devsymDlSym, /* xDlSym */
|
|
||||||
devsymDlClose, /* xDlClose */
|
|
||||||
#else
|
|
||||||
0, /* xDlOpen */
|
|
||||||
0, /* xDlError */
|
|
||||||
0, /* xDlSym */
|
|
||||||
0, /* xDlClose */
|
|
||||||
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
|
|
||||||
devsymRandomness, /* xRandomness */
|
|
||||||
devsymSleep, /* xSleep */
|
|
||||||
devsymCurrentTime, /* xCurrentTime */
|
|
||||||
0, /* xGetLastError */
|
|
||||||
0 /* xCurrentTimeInt64 */
|
|
||||||
};
|
|
||||||
|
|
||||||
static sqlite3_io_methods devsym_io_methods = {
|
|
||||||
2, /* iVersion */
|
|
||||||
devsymClose, /* xClose */
|
|
||||||
devsymRead, /* xRead */
|
|
||||||
devsymWrite, /* xWrite */
|
|
||||||
devsymTruncate, /* xTruncate */
|
|
||||||
devsymSync, /* xSync */
|
|
||||||
devsymFileSize, /* xFileSize */
|
|
||||||
devsymLock, /* xLock */
|
|
||||||
devsymUnlock, /* xUnlock */
|
|
||||||
devsymCheckReservedLock, /* xCheckReservedLock */
|
|
||||||
devsymFileControl, /* xFileControl */
|
|
||||||
devsymSectorSize, /* xSectorSize */
|
|
||||||
devsymDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
||||||
devsymShmMap, /* xShmMap */
|
|
||||||
devsymShmLock, /* xShmLock */
|
|
||||||
devsymShmBarrier, /* xShmBarrier */
|
|
||||||
devsymShmUnmap /* xShmUnmap */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DevsymGlobal {
|
struct DevsymGlobal {
|
||||||
sqlite3_vfs *pVfs;
|
sqlite3_vfs *pVfs;
|
||||||
int iDeviceChar;
|
int iDeviceChar;
|
||||||
int iSectorSize;
|
int iSectorSize;
|
||||||
|
int nWriteCrash;
|
||||||
};
|
};
|
||||||
struct DevsymGlobal g = {0, 0, 512};
|
struct DevsymGlobal g = {0, 0, 512, 0};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Close an devsym-file.
|
** Close an devsym-file.
|
||||||
@ -271,6 +224,26 @@ static int devsymOpen(
|
|||||||
int flags,
|
int flags,
|
||||||
int *pOutFlags
|
int *pOutFlags
|
||||||
){
|
){
|
||||||
|
static sqlite3_io_methods devsym_io_methods = {
|
||||||
|
2, /* iVersion */
|
||||||
|
devsymClose, /* xClose */
|
||||||
|
devsymRead, /* xRead */
|
||||||
|
devsymWrite, /* xWrite */
|
||||||
|
devsymTruncate, /* xTruncate */
|
||||||
|
devsymSync, /* xSync */
|
||||||
|
devsymFileSize, /* xFileSize */
|
||||||
|
devsymLock, /* xLock */
|
||||||
|
devsymUnlock, /* xUnlock */
|
||||||
|
devsymCheckReservedLock, /* xCheckReservedLock */
|
||||||
|
devsymFileControl, /* xFileControl */
|
||||||
|
devsymSectorSize, /* xSectorSize */
|
||||||
|
devsymDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||||
|
devsymShmMap, /* xShmMap */
|
||||||
|
devsymShmLock, /* xShmLock */
|
||||||
|
devsymShmBarrier, /* xShmBarrier */
|
||||||
|
devsymShmUnmap /* xShmUnmap */
|
||||||
|
};
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
devsym_file *p = (devsym_file *)pFile;
|
devsym_file *p = (devsym_file *)pFile;
|
||||||
p->pReal = (sqlite3_file *)&p[1];
|
p->pReal = (sqlite3_file *)&p[1];
|
||||||
@ -372,6 +345,137 @@ static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
|||||||
return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
|
return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the sector-size in bytes for an writecrash-file.
|
||||||
|
*/
|
||||||
|
static int writecrashSectorSize(sqlite3_file *pFile){
|
||||||
|
devsym_file *p = (devsym_file *)pFile;
|
||||||
|
return sqlite3OsSectorSize(p->pReal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the device characteristic flags supported by an writecrash-file.
|
||||||
|
*/
|
||||||
|
static int writecrashDeviceCharacteristics(sqlite3_file *pFile){
|
||||||
|
devsym_file *p = (devsym_file *)pFile;
|
||||||
|
return sqlite3OsDeviceCharacteristics(p->pReal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write data to an writecrash-file.
|
||||||
|
*/
|
||||||
|
static int writecrashWrite(
|
||||||
|
sqlite3_file *pFile,
|
||||||
|
const void *zBuf,
|
||||||
|
int iAmt,
|
||||||
|
sqlite_int64 iOfst
|
||||||
|
){
|
||||||
|
devsym_file *p = (devsym_file *)pFile;
|
||||||
|
if( g.nWriteCrash>0 ){
|
||||||
|
g.nWriteCrash--;
|
||||||
|
if( g.nWriteCrash==0 ) abort();
|
||||||
|
}
|
||||||
|
return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Open an writecrash file handle.
|
||||||
|
*/
|
||||||
|
static int writecrashOpen(
|
||||||
|
sqlite3_vfs *pVfs,
|
||||||
|
const char *zName,
|
||||||
|
sqlite3_file *pFile,
|
||||||
|
int flags,
|
||||||
|
int *pOutFlags
|
||||||
|
){
|
||||||
|
static sqlite3_io_methods writecrash_io_methods = {
|
||||||
|
2, /* iVersion */
|
||||||
|
devsymClose, /* xClose */
|
||||||
|
devsymRead, /* xRead */
|
||||||
|
writecrashWrite, /* xWrite */
|
||||||
|
devsymTruncate, /* xTruncate */
|
||||||
|
devsymSync, /* xSync */
|
||||||
|
devsymFileSize, /* xFileSize */
|
||||||
|
devsymLock, /* xLock */
|
||||||
|
devsymUnlock, /* xUnlock */
|
||||||
|
devsymCheckReservedLock, /* xCheckReservedLock */
|
||||||
|
devsymFileControl, /* xFileControl */
|
||||||
|
writecrashSectorSize, /* xSectorSize */
|
||||||
|
writecrashDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||||
|
devsymShmMap, /* xShmMap */
|
||||||
|
devsymShmLock, /* xShmLock */
|
||||||
|
devsymShmBarrier, /* xShmBarrier */
|
||||||
|
devsymShmUnmap /* xShmUnmap */
|
||||||
|
};
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
devsym_file *p = (devsym_file *)pFile;
|
||||||
|
p->pReal = (sqlite3_file *)&p[1];
|
||||||
|
rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
|
||||||
|
if( p->pReal->pMethods ){
|
||||||
|
pFile->pMethods = &writecrash_io_methods;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sqlite3_vfs devsym_vfs = {
|
||||||
|
2, /* iVersion */
|
||||||
|
sizeof(devsym_file), /* szOsFile */
|
||||||
|
DEVSYM_MAX_PATHNAME, /* mxPathname */
|
||||||
|
0, /* pNext */
|
||||||
|
DEVSYM_VFS_NAME, /* zName */
|
||||||
|
0, /* pAppData */
|
||||||
|
devsymOpen, /* xOpen */
|
||||||
|
devsymDelete, /* xDelete */
|
||||||
|
devsymAccess, /* xAccess */
|
||||||
|
devsymFullPathname, /* xFullPathname */
|
||||||
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||||
|
devsymDlOpen, /* xDlOpen */
|
||||||
|
devsymDlError, /* xDlError */
|
||||||
|
devsymDlSym, /* xDlSym */
|
||||||
|
devsymDlClose, /* xDlClose */
|
||||||
|
#else
|
||||||
|
0, /* xDlOpen */
|
||||||
|
0, /* xDlError */
|
||||||
|
0, /* xDlSym */
|
||||||
|
0, /* xDlClose */
|
||||||
|
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
|
||||||
|
devsymRandomness, /* xRandomness */
|
||||||
|
devsymSleep, /* xSleep */
|
||||||
|
devsymCurrentTime, /* xCurrentTime */
|
||||||
|
0, /* xGetLastError */
|
||||||
|
0 /* xCurrentTimeInt64 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static sqlite3_vfs writecrash_vfs = {
|
||||||
|
2, /* iVersion */
|
||||||
|
sizeof(devsym_file), /* szOsFile */
|
||||||
|
DEVSYM_MAX_PATHNAME, /* mxPathname */
|
||||||
|
0, /* pNext */
|
||||||
|
WRITECRASH_NAME, /* zName */
|
||||||
|
0, /* pAppData */
|
||||||
|
writecrashOpen, /* xOpen */
|
||||||
|
devsymDelete, /* xDelete */
|
||||||
|
devsymAccess, /* xAccess */
|
||||||
|
devsymFullPathname, /* xFullPathname */
|
||||||
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||||
|
devsymDlOpen, /* xDlOpen */
|
||||||
|
devsymDlError, /* xDlError */
|
||||||
|
devsymDlSym, /* xDlSym */
|
||||||
|
devsymDlClose, /* xDlClose */
|
||||||
|
#else
|
||||||
|
0, /* xDlOpen */
|
||||||
|
0, /* xDlError */
|
||||||
|
0, /* xDlSym */
|
||||||
|
0, /* xDlClose */
|
||||||
|
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
|
||||||
|
devsymRandomness, /* xRandomness */
|
||||||
|
devsymSleep, /* xSleep */
|
||||||
|
devsymCurrentTime, /* xCurrentTime */
|
||||||
|
0, /* xGetLastError */
|
||||||
|
0 /* xCurrentTimeInt64 */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This procedure registers the devsym vfs with SQLite. If the argument is
|
** This procedure registers the devsym vfs with SQLite. If the argument is
|
||||||
@ -379,10 +483,13 @@ static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
|||||||
** available function in this file.
|
** available function in this file.
|
||||||
*/
|
*/
|
||||||
void devsym_register(int iDeviceChar, int iSectorSize){
|
void devsym_register(int iDeviceChar, int iSectorSize){
|
||||||
|
|
||||||
if( g.pVfs==0 ){
|
if( g.pVfs==0 ){
|
||||||
g.pVfs = sqlite3_vfs_find(0);
|
g.pVfs = sqlite3_vfs_find(0);
|
||||||
devsym_vfs.szOsFile += g.pVfs->szOsFile;
|
devsym_vfs.szOsFile += g.pVfs->szOsFile;
|
||||||
|
writecrash_vfs.szOsFile += g.pVfs->szOsFile;
|
||||||
sqlite3_vfs_register(&devsym_vfs, 0);
|
sqlite3_vfs_register(&devsym_vfs, 0);
|
||||||
|
sqlite3_vfs_register(&writecrash_vfs, 0);
|
||||||
}
|
}
|
||||||
if( iDeviceChar>=0 ){
|
if( iDeviceChar>=0 ){
|
||||||
g.iDeviceChar = iDeviceChar;
|
g.iDeviceChar = iDeviceChar;
|
||||||
@ -403,4 +510,15 @@ void devsym_unregister(){
|
|||||||
g.iSectorSize = 0;
|
g.iSectorSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void devsym_crash_on_write(int nWrite){
|
||||||
|
if( g.pVfs==0 ){
|
||||||
|
g.pVfs = sqlite3_vfs_find(0);
|
||||||
|
devsym_vfs.szOsFile += g.pVfs->szOsFile;
|
||||||
|
writecrash_vfs.szOsFile += g.pVfs->szOsFile;
|
||||||
|
sqlite3_vfs_register(&devsym_vfs, 0);
|
||||||
|
sqlite3_vfs_register(&writecrash_vfs, 0);
|
||||||
|
}
|
||||||
|
g.nWriteCrash = nWrite;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1608,6 +1608,54 @@ proc crashsql {args} {
|
|||||||
lappend r $msg
|
lappend r $msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# crash_on_write ?-devchar DEVCHAR? CRASHDELAY SQL
|
||||||
|
#
|
||||||
|
proc crash_on_write {args} {
|
||||||
|
|
||||||
|
set nArg [llength $args]
|
||||||
|
if {$nArg<2 || $nArg%2} {
|
||||||
|
error "bad args: $args"
|
||||||
|
}
|
||||||
|
set zSql [lindex $args end]
|
||||||
|
set nDelay [lindex $args end-1]
|
||||||
|
|
||||||
|
set devchar {}
|
||||||
|
for {set ii 0} {$ii < $nArg-2} {incr ii 2} {
|
||||||
|
set opt [lindex $args $ii]
|
||||||
|
switch -- [lindex $args $ii] {
|
||||||
|
-devchar {
|
||||||
|
set devchar [lindex $args [expr $ii+1]]
|
||||||
|
}
|
||||||
|
|
||||||
|
default { error "unrecognized option: $opt" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set f [open crash.tcl w]
|
||||||
|
puts $f "sqlite3_crash_on_write $nDelay"
|
||||||
|
puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
|
||||||
|
puts $f "sqlite3 db test.db -vfs writecrash"
|
||||||
|
puts $f "db eval {$zSql}"
|
||||||
|
puts $f "set {} {}"
|
||||||
|
|
||||||
|
close $f
|
||||||
|
set r [catch {
|
||||||
|
exec [info nameofexec] crash.tcl >@stdout
|
||||||
|
} msg]
|
||||||
|
|
||||||
|
# Windows/ActiveState TCL returns a slightly different
|
||||||
|
# error message. We map that to the expected message
|
||||||
|
# so that we don't have to change all of the test
|
||||||
|
# cases.
|
||||||
|
if {$::tcl_platform(platform)=="windows"} {
|
||||||
|
if {$msg=="child killed: unknown signal"} {
|
||||||
|
set msg "child process exited abnormally"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lappend r $msg
|
||||||
|
}
|
||||||
|
|
||||||
proc run_ioerr_prep {} {
|
proc run_ioerr_prep {} {
|
||||||
set ::sqlite_io_error_pending 0
|
set ::sqlite_io_error_pending 0
|
||||||
catch {db close}
|
catch {db close}
|
||||||
|
62
test/writecrash.test
Normal file
62
test/writecrash.test
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# 2009 January 8
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
#
|
||||||
|
# Test the outcome of a writer crashing within a call to the VFS
|
||||||
|
# xWrite function.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
set testprefix writecrash
|
||||||
|
|
||||||
|
do_not_use_codec
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB UNIQUE);
|
||||||
|
WITH s(i) AS (
|
||||||
|
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100
|
||||||
|
)
|
||||||
|
INSERT INTO t1 SELECT NULL, randomblob(900) FROM s;
|
||||||
|
} {}
|
||||||
|
|
||||||
|
set bGo 1
|
||||||
|
for {set tn 1} {$bGo} {incr tn} {
|
||||||
|
|
||||||
|
db close
|
||||||
|
sqlite3 db test.db
|
||||||
|
|
||||||
|
do_test 1.$tn.1 {
|
||||||
|
set res [crash_on_write $tn {
|
||||||
|
UPDATE t1 SET b = randomblob(899) WHERE (a%3)==0
|
||||||
|
}]
|
||||||
|
set bGo 0
|
||||||
|
if {[string match {1 {child killed:*}} $res]} {
|
||||||
|
set res {0 {}}
|
||||||
|
set bGo 1
|
||||||
|
}
|
||||||
|
set res
|
||||||
|
} {0 {}}
|
||||||
|
|
||||||
|
#db close
|
||||||
|
#sqlite3 db test.db
|
||||||
|
|
||||||
|
do_execsql_test 1.$tn.2 { PRAGMA integrity_check } {ok}
|
||||||
|
|
||||||
|
db close
|
||||||
|
sqlite3 db test.db
|
||||||
|
|
||||||
|
do_execsql_test 1.$tn.3 { PRAGMA integrity_check } {ok}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
Loading…
Reference in New Issue
Block a user