Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add tests to pager1.test and pagerfault.test. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
008513ee6115f8d6f4b4e1428c1c6382 |
User & Date: | dan 2010-06-29 10:30:24.000 |
Context
2010-06-30
| ||
04:29 | Add coverage test cases. Have sqlite3_backup_step() transform SQLITE_IOERR_NOMEM to SQLITE_NOMEM before returning. (check-in: 5e19bc360e user: dan tags: trunk) | |
2010-06-29
| ||
10:30 | Add tests to pager1.test and pagerfault.test. (check-in: 008513ee61 user: dan tags: trunk) | |
2010-06-28
| ||
19:04 | Add extra pager tests. (check-in: 6b7e419ddc user: dan tags: trunk) | |
Changes
Changes to src/test_vfs.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** */ #if SQLITE_TEST /* This file is used for testing only */ #include "sqlite3.h" #include "sqliteInt.h" typedef struct Testvfs Testvfs; typedef struct TestvfsShm TestvfsShm; typedef struct TestvfsBuffer TestvfsBuffer; typedef struct TestvfsFile TestvfsFile; /* ** An open file handle. */ struct TestvfsFile { sqlite3_file base; /* Base class. Must be first */ sqlite3_vfs *pVfs; /* The VFS */ const char *zFilename; /* Filename as passed to xOpen() */ sqlite3_file *pReal; /* The real, underlying file descriptor */ Tcl_Obj *pShmId; /* Shared memory id for Tcl callbacks */ TestvfsBuffer *pShm; /* Shared memory buffer */ u32 excllock; /* Mask of exclusive locks */ u32 sharedlock; /* Mask of shared locks */ | > > > > > > > > > > > > > > > > > > > > > | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 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 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** */ #if SQLITE_TEST /* This file is used for testing only */ /* ** This file contains the implementation of the Tcl [testvfs] command, ** used to create SQLite VFS implementations with various properties and ** instrumentation to support testing SQLite. ** ** testvfs VFSNAME ?OPTIONS? ** ** Available options are: ** ** -noshm BOOLEAN (True to omit shm methods. Default false) ** -default BOOLEAN (True to make the vfs default. Default false) ** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile) ** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname) */ #include "sqlite3.h" #include "sqliteInt.h" typedef struct Testvfs Testvfs; typedef struct TestvfsShm TestvfsShm; typedef struct TestvfsBuffer TestvfsBuffer; typedef struct TestvfsFile TestvfsFile; typedef struct TestvfsFd TestvfsFd; /* ** An open file handle. */ struct TestvfsFile { sqlite3_file base; /* Base class. Must be first */ TestvfsFd *pFd; /* File data */ }; #define tvfsGetFd(pFile) (((TestvfsFile *)pFile)->pFd) struct TestvfsFd { sqlite3_vfs *pVfs; /* The VFS */ const char *zFilename; /* Filename as passed to xOpen() */ sqlite3_file *pReal; /* The real, underlying file descriptor */ Tcl_Obj *pShmId; /* Shared memory id for Tcl callbacks */ TestvfsBuffer *pShm; /* Shared memory buffer */ u32 excllock; /* Mask of exclusive locks */ u32 sharedlock; /* Mask of shared locks */ TestvfsFd *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 { |
︙ | ︙ | |||
114 115 116 117 118 119 120 | ** memory region opened by clients. If two clients open the same file, ** there are two TestvfsFile structures but only one TestvfsBuffer structure. */ struct TestvfsBuffer { char *zFile; /* Associated file name */ int pgsz; /* Page size */ u8 *aPage[TESTVFS_MAX_PAGES]; /* Array of ckalloc'd pages */ | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | ** memory region opened by clients. If two clients open the same file, ** there are two TestvfsFile structures but only one TestvfsBuffer structure. */ struct TestvfsBuffer { char *zFile; /* Associated file name */ int pgsz; /* Page size */ u8 *aPage[TESTVFS_MAX_PAGES]; /* Array of ckalloc'd pages */ TestvfsFd *pFile; /* List of open handles */ TestvfsBuffer *pNext; /* Next in linked list of all buffers */ }; #define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent) #define TESTVFS_MAX_ARGS 12 |
︙ | ︙ | |||
292 293 294 295 296 297 298 | } /* ** Close an tvfs-file. */ static int tvfsClose(sqlite3_file *pFile){ | > | > | > > > | | | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | } /* ** Close an tvfs-file. */ static int tvfsClose(sqlite3_file *pFile){ int rc; TestvfsFile *pTestfile = (TestvfsFile *)pFile; TestvfsFd *pFd = pTestfile->pFd; Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){ tvfsExecTcl(p, "xClose", Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 ); } if( pFd->pShmId ){ Tcl_DecrRefCount(pFd->pShmId); pFd->pShmId = 0; } if( pFile->pMethods ){ ckfree((char *)pFile->pMethods); } rc = sqlite3OsClose(pFd->pReal); ckfree((char *)pFd); pTestfile->pFd = 0; return rc; } /* ** Read data from an tvfs-file. */ static int tvfsRead( sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst ){ TestvfsFd *p = tvfsGetFd(pFile); return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); } /* ** Write data to an tvfs-file. */ static int tvfsWrite( sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ tvfsExecTcl(p, "xWrite", Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 ); tvfsResultCode(p, &rc); |
︙ | ︙ | |||
362 363 364 365 366 367 368 | } /* ** Truncate an tvfs-file. */ static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ int rc = SQLITE_OK; | | | | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | } /* ** Truncate an tvfs-file. */ static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){ tvfsExecTcl(p, "xTruncate", Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 ); tvfsResultCode(p, &rc); } if( rc==SQLITE_OK ){ rc = sqlite3OsTruncate(pFd->pReal, size); } return rc; } /* ** Sync an tvfs-file. */ static int tvfsSync(sqlite3_file *pFile, int flags){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_SYNC_MASK ){ char *zFlags; switch( flags ){ case SQLITE_SYNC_NORMAL: |
︙ | ︙ | |||
426 427 428 429 430 431 432 | return rc; } /* ** Return the current file-size of an tvfs-file. */ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ | | | | | | | | | > > > > | 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 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 | return rc; } /* ** Return the current file-size of an tvfs-file. */ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ TestvfsFd *p = tvfsGetFd(pFile); return sqlite3OsFileSize(p->pReal, pSize); } /* ** Lock an tvfs-file. */ static int tvfsLock(sqlite3_file *pFile, int eLock){ TestvfsFd *p = tvfsGetFd(pFile); return sqlite3OsLock(p->pReal, eLock); } /* ** Unlock an tvfs-file. */ static int tvfsUnlock(sqlite3_file *pFile, int eLock){ TestvfsFd *p = tvfsGetFd(pFile); return sqlite3OsUnlock(p->pReal, eLock); } /* ** Check if another file-handle holds a RESERVED lock on an tvfs-file. */ static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ TestvfsFd *p = tvfsGetFd(pFile); return sqlite3OsCheckReservedLock(p->pReal, pResOut); } /* ** File control method. For custom operations on an tvfs-file. */ static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ TestvfsFd *p = tvfsGetFd(pFile); return sqlite3OsFileControl(p->pReal, op, pArg); } /* ** Return the sector-size in bytes for an tvfs-file. */ static int tvfsSectorSize(sqlite3_file *pFile){ TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->iSectorsize>=0 ){ return p->iSectorsize; } return sqlite3OsSectorSize(pFd->pReal); } /* ** Return the device characteristic flags supported by an tvfs-file. */ static int tvfsDeviceCharacteristics(sqlite3_file *pFile){ TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; if( p->iDevchar>=0 ){ return p->iDevchar; } return sqlite3OsDeviceCharacteristics(pFd->pReal); } /* ** Open an tvfs file handle. */ static int tvfsOpen( sqlite3_vfs *pVfs, const char *zName, sqlite3_file *pFile, int flags, int *pOutFlags ){ int rc; TestvfsFile *pTestfile = (TestvfsFile *)pFile; TestvfsFd *pFd; Tcl_Obj *pId = 0; Testvfs *p = (Testvfs *)pVfs->pAppData; pFd = (TestvfsFd *)ckalloc(sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile); memset(pFd, 0, sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile); pFd->pShm = 0; pFd->pShmId = 0; pFd->zFilename = zName; pFd->pVfs = pVfs; pFd->pReal = (sqlite3_file *)&pFd[1]; pTestfile->pFd = pFd; /* Evaluate the Tcl script: ** ** SCRIPT xOpen FILENAME ** ** If the script returns an SQLite error code other than SQLITE_OK, an ** error is returned to the caller. If it returns SQLITE_OK, the new |
︙ | ︙ | |||
536 537 538 539 540 541 542 | if( !pId ){ pId = Tcl_NewStringObj("anon", -1); } Tcl_IncrRefCount(pId); pFd->pShmId = pId; Tcl_ResetResult(p->interp); | < | 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | 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 ){ |
︙ | ︙ | |||
678 679 680 681 682 683 684 | /* ** Return the current time as a Julian Day number in *pTimeOut. */ static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); } | | < < | | | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | /* ** Return the current time as a Julian Day number in *pTimeOut. */ static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); } static int tvfsShmOpen(sqlite3_file *pFile){ Testvfs *p; int rc = SQLITE_OK; /* Return code */ TestvfsBuffer *pBuffer; /* Buffer to open connection to */ TestvfsFd *pFd; /* The testvfs file structure */ pFd = tvfsGetFd(pFile); p = (Testvfs *)pFd->pVfs->pAppData; assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 ); /* Evaluate the Tcl script: ** ** SCRIPT xShmOpen FILENAME */ |
︙ | ︙ | |||
745 746 747 748 749 750 751 | sqlite3_file *pFile, /* Handle open on database file */ int iPage, /* Page to retrieve */ int pgsz, /* Size of pages */ int isWrite, /* True to extend file if necessary */ void volatile **pp /* OUT: Mapped memory */ ){ int rc = SQLITE_OK; | | | 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 | sqlite3_file *pFile, /* Handle open on database file */ int iPage, /* Page to retrieve */ int pgsz, /* Size of pages */ int isWrite, /* True to extend file if necessary */ void volatile **pp /* OUT: Mapped memory */ ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){ Tcl_Obj *pArg = Tcl_NewObj(); Tcl_IncrRefCount(pArg); Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage)); Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz)); |
︙ | ︙ | |||
780 781 782 783 784 785 786 | static int tvfsShmLock( sqlite3_file *pFile, int ofst, int n, int flags ){ int rc = SQLITE_OK; | | | 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 | static int tvfsShmLock( sqlite3_file *pFile, int ofst, int n, int flags ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); int nLock; char zLock[80]; if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); nLock = strlen(zLock); |
︙ | ︙ | |||
815 816 817 818 819 820 821 | } if( rc==SQLITE_OK ){ int isLock = (flags & SQLITE_SHM_LOCK); int isExcl = (flags & SQLITE_SHM_EXCLUSIVE); u32 mask = (((1<<n)-1) << ofst); if( isLock ){ | | | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 | } if( rc==SQLITE_OK ){ int isLock = (flags & SQLITE_SHM_LOCK); int isExcl = (flags & SQLITE_SHM_EXCLUSIVE); u32 mask = (((1<<n)-1) << ofst); if( isLock ){ TestvfsFd *p2; for(p2=pFd->pShm->pFile; p2; p2=p2->pNext){ if( p2==pFd ) continue; if( (p2->excllock&mask) || (isExcl && p2->sharedlock&mask) ){ rc = SQLITE_BUSY; break; } } |
︙ | ︙ | |||
837 838 839 840 841 842 843 | } } return rc; } static void tvfsShmBarrier(sqlite3_file *pFile){ | | | | | 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | } } return rc; } static void tvfsShmBarrier(sqlite3_file *pFile){ TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 ); } } static int tvfsShmClose( sqlite3_file *pFile, int deleteFlag ){ int rc = SQLITE_OK; TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); TestvfsBuffer *pBuffer = pFd->pShm; TestvfsFd **ppFd; assert( pFd->pShmId && pFd->pShm ); if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ tvfsExecTcl(p, "xShmClose", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 ); |
︙ | ︙ | |||
1230 1231 1232 1233 1234 1235 1236 | ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static sqlite3_vfs tvfs_vfs = { 2, /* iVersion */ | | | 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 | ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static sqlite3_vfs tvfs_vfs = { 2, /* iVersion */ 0, /* szOsFile */ 0, /* mxPathname */ 0, /* pNext */ 0, /* zName */ 0, /* pAppData */ tvfsOpen, /* xOpen */ tvfsDelete, /* xDelete */ tvfsAccess, /* xAccess */ |
︙ | ︙ | |||
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 | sqlite3_vfs *pVfs; /* New VFS */ char *zVfs; int nByte; /* Bytes of space to allocate at p */ int i; int isNoshm = 0; /* True if -noshm is passed */ int isDefault = 0; /* True if -default is passed */ if( objc<2 || 0!=(objc%2) ) goto bad_args; for(i=2; i<objc; i += 2){ int nSwitch; char *zSwitch; | > > < > > > > > > > > > > > > > > > | 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 | sqlite3_vfs *pVfs; /* New VFS */ char *zVfs; int nByte; /* Bytes of space to allocate at p */ int i; int isNoshm = 0; /* True if -noshm is passed */ int isDefault = 0; /* True if -default is passed */ int szOsFile = 0; /* Value passed to -szosfile */ int mxPathname = -1; /* Value passed to -mxpathname */ if( objc<2 || 0!=(objc%2) ) goto bad_args; for(i=2; i<objc; i += 2){ int nSwitch; char *zSwitch; zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch); if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){ return TCL_ERROR; } } else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){ if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){ return TCL_ERROR; } } else{ goto bad_args; } } if( szOsFile<sizeof(TestvfsFile) ){ szOsFile = sizeof(TestvfsFile); } zVfs = Tcl_GetString(objv[1]); nByte = sizeof(Testvfs) + strlen(zVfs)+1; p = (Testvfs *)ckalloc(nByte); memset(p, 0, nByte); p->iDevchar = -1; p->iSectorsize = -1; |
︙ | ︙ | |||
1313 1314 1315 1316 1317 1318 1319 | memcpy(p->zName, zVfs, strlen(zVfs)+1); pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs)); memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs)); pVfs->pAppData = (void *)p; pVfs->zName = p->zName; pVfs->mxPathname = p->pParent->mxPathname; | > > > | | | 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 | memcpy(p->zName, zVfs, strlen(zVfs)+1); pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs)); memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs)); pVfs->pAppData = (void *)p; pVfs->zName = p->zName; pVfs->mxPathname = p->pParent->mxPathname; if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){ pVfs->mxPathname = mxPathname; } pVfs->szOsFile = szOsFile; p->pVfs = pVfs; p->isNoshm = isNoshm; p->mask = TESTVFS_ALL_MASK; sqlite3_vfs_register(pVfs, isDefault); return TCL_OK; bad_args: Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT?"); return TCL_ERROR; } int Sqlitetestvfs_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); return TCL_OK; } #endif |
Changes to test/pager1.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # # pager1-12.*: Tests involving "PRAGMA page_size" # # pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST" # # pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF" # set a_string_counter 1 proc a_string {n} { global a_string_counter incr a_string_counter string range [string repeat "${a_string_counter}." $n] 1 $n } | > > > > > > > > > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | # # pager1-12.*: Tests involving "PRAGMA page_size" # # pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST" # # pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF" # # pager1-15.*: Varying sqlite3_vfs.szOsFile # # pager1-16.*: Varying sqlite3_vfs.mxPathname # # pager1-17.*: Tests related to "PRAGMA omit_readlock" # # pager1-18.*: Test that the pager layer responds correctly if the b-tree # requests an invalid page number (due to db corruption). # set a_string_counter 1 proc a_string {n} { global a_string_counter incr a_string_counter string range [string repeat "${a_string_counter}." $n] 1 $n } |
︙ | ︙ | |||
354 355 356 357 358 359 360 361 362 363 364 365 366 367 | # # pager1.4.5.*: Test that hot-journal rollback stops if it encounters a # journal-record for which the checksum fails. # # pager1.4.6.*: Test that when rolling back a hot-journal that contains a # master journal pointer, the master journal file is deleted # after all the hot-journals that refer to it are deleted. # do_test pager1.4.1.1 { faultsim_delete_and_reopen execsql { CREATE TABLE x(y, z); INSERT INTO x VALUES(1, 2); } | > > > > | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | # # pager1.4.5.*: Test that hot-journal rollback stops if it encounters a # journal-record for which the checksum fails. # # pager1.4.6.*: Test that when rolling back a hot-journal that contains a # master journal pointer, the master journal file is deleted # after all the hot-journals that refer to it are deleted. # # pager1.4.7.*: Test that if a hot-journal file exists but a client can # open it for reading only, the database cannot be accessed and # SQLITE_CANTOPEN is returned. # do_test pager1.4.1.1 { faultsim_delete_and_reopen execsql { CREATE TABLE x(y, z); INSERT INTO x VALUES(1, 2); } |
︙ | ︙ | |||
631 632 633 634 635 636 637 | # journal file to commit a transaction. The transaction modifies exactly # two database pages (and page 1 - the change counter). # testvfs tv -default 1 tv sectorsize 512 tv script copy_on_journal_delete tv filter xDelete | < | 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | # journal file to commit a transaction. The transaction modifies exactly # two database pages (and page 1 - the change counter). # testvfs tv -default 1 tv sectorsize 512 tv script copy_on_journal_delete tv filter xDelete proc copy_on_journal_delete {method filename args} { if {[string match *journal $filename]} faultsim_save return SQLITE_OK } faultsim_delete_and_reopen do_execsql_test pager1.4.5.1 { PRAGMA page_size = 1024; |
︙ | ︙ | |||
801 802 803 804 805 806 807 808 809 810 811 812 813 814 | ATTACH 'test.db3' AS three; SELECT * FROM t3; } {1 t3.1} do_test pager1.4.6.15 { file exists $::mj_filename } {0} db close tv delete #------------------------------------------------------------------------- # The following tests deal with multi-file commits. # # pager1-5.1.*: The case where a multi-file cannot be committed because # another connection is holding a SHARED lock on one of the # files. After the SHARED lock is removed, the COMMIT succeeds. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 | ATTACH 'test.db3' AS three; SELECT * FROM t3; } {1 t3.1} do_test pager1.4.6.15 { file exists $::mj_filename } {0} db close tv delete testvfs tv -default 1 tv sectorsize 512 tv script copy_on_journal_delete tv filter xDelete proc copy_on_journal_delete {method filename args} { if {[string match *journal $filename]} faultsim_save return SQLITE_OK } faultsim_delete_and_reopen do_execsql_test pager1.4.7.1 { CREATE TABLE t1(x PRIMARY KEY, y); CREATE INDEX i1 ON t1(y); INSERT INTO t1 VALUES('I', 'one'); INSERT INTO t1 VALUES('II', 'four'); INSERT INTO t1 VALUES('III', 'nine'); BEGIN; INSERT INTO t1 VALUES('IV', 'sixteen'); INSERT INTO t1 VALUES('V' , 'twentyfive'); COMMIT; } {} tv filter {} db close tv delete do_test pager1.4.7.2 { faultsim_restore_and_reopen catch {file attributes test.db-journal -permissions r--------} catch {file attributes test.db-journal -readonly 1} catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} do_test pager1.4.7.3 { db close catch {file attributes test.db-journal -permissions rw-rw-rw-} catch {file attributes test.db-journal -readonly 0} file delete test.db-journal file exists test.db-journal } {0} #------------------------------------------------------------------------- # The following tests deal with multi-file commits. # # pager1-5.1.*: The case where a multi-file cannot be committed because # another connection is holding a SHARED lock on one of the # files. After the SHARED lock is removed, the COMMIT succeeds. |
︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | 2 "" } { do_test pager1-8.$tn.1 { faultsim_delete_and_reopen db close sqlite3 db $filename execsql { CREATE TABLE x1(x); INSERT INTO x1 VALUES('Charles'); INSERT INTO x1 VALUES('James'); INSERT INTO x1 VALUES('Mary'); SELECT * FROM x1; } } {Charles James Mary} | > | 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 | 2 "" } { do_test pager1-8.$tn.1 { faultsim_delete_and_reopen db close sqlite3 db $filename execsql { PRAGMA auto_vacuum = 1; CREATE TABLE x1(x); INSERT INTO x1 VALUES('Charles'); INSERT INTO x1 VALUES('James'); INSERT INTO x1 VALUES('Mary'); SELECT * FROM x1; } } {Charles James Mary} |
︙ | ︙ | |||
1373 1374 1375 1376 1377 1378 1379 1380 1381 | INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; } {1 {PRIMARY KEY must be unique}} do_execsql_test pager1-14.1.5 { COMMIT; SELECT * FROM t1; } {1 2 3 4 2 2 4 4} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 | INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; } {1 {PRIMARY KEY must be unique}} do_execsql_test pager1-14.1.5 { COMMIT; SELECT * FROM t1; } {1 2 3 4 2 2 4 4} #------------------------------------------------------------------------- # Test opening and closing the pager sub-system with different values # for the sqlite3_vfs.szOsFile variable. # faultsim_delete_and_reopen do_execsql_test pager1-15.0 { CREATE TABLE tx(y, z); INSERT INTO tx VALUES('Ayutthaya', 'Beijing'); INSERT INTO tx VALUES('London', 'Tokyo'); } {} db close for {set i 0} {$i<513} {incr i 3} { testvfs tv -default 1 -szosfile $i sqlite3 db test.db do_execsql_test pager1-15.$i.1 { SELECT * FROM tx; } {Ayutthaya Beijing London Tokyo} db close tv delete } #------------------------------------------------------------------------- # Check that it is not possible to open a database file if the full path # to the associated journal file will be longer than sqlite3_vfs.mxPathname. # testvfs tv -default 1 tv script xOpenCb tv filter xOpen proc xOpenCb {method filename} { set ::file_len [string length $filename] } sqlite3 db test.db db close tv delete for {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} { testvfs tv -default 1 -mxpathname $ii # The length of the full path to file "test.db-journal" is ($::file_len+8). # If the configured sqlite3_vfs.mxPathname value greater than or equal to # this, then the file can be opened. Otherwise, it cannot. # if {$ii >= [expr $::file_len+8]} { set res {0 {}} } else { set res {1 {unable to open database file}} } do_test pager1-16.1.$ii { list [catch { sqlite3 db test.db } msg] $msg } $res catch {db close} tv delete } #------------------------------------------------------------------------- # Test "PRAGMA omit_readlock". # # pager1-17.$tn.1.*: Test that if a second connection has an open # read-transaction, it is not usually possible to write # the database. # # pager1-17.$tn.2.*: Test that if the second connection was opened with # the SQLITE_OPEN_READONLY flag, and # "PRAGMA omit_readlock = 1" is executed before attaching # the database and opening a read-transaction on it, it is # possible to write the db. # # pager1-17.$tn.3.*: Test that if the second connection was *not* opened with # the SQLITE_OPEN_READONLY flag, executing # "PRAGMA omit_readlock = 1" has no effect. # do_multiclient_test tn { do_test pager1-17.$tn.1.1 { sql1 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } sql2 { BEGIN; SELECT * FROM t1; } } {1 2} do_test pager1-17.$tn.1.2 { csql1 { INSERT INTO t1 VALUES(3, 4) } } {1 {database is locked}} do_test pager1-17.$tn.1.3 { sql2 { COMMIT } sql1 { INSERT INTO t1 VALUES(3, 4) } } {} do_test pager1-17.$tn.2.1 { code2 { db2 close sqlite3 db2 :memory: -readonly 1 } sql2 { PRAGMA omit_readlock = 1; ATTACH 'test.db' AS two; BEGIN; SELECT * FROM t1; } } {1 2 3 4} do_test pager1-17.$tn.2.2 { sql1 "INSERT INTO t1 VALUES(5, 6)" } {} do_test pager1-17.$tn.2.3 { sql2 "SELECT * FROM t1" } {1 2 3 4} do_test pager1-17.$tn.2.4 { sql2 "COMMIT ; SELECT * FROM t1" } {1 2 3 4 5 6} do_test pager1-17.$tn.3.1 { code2 { db2 close sqlite3 db2 :memory: } sql2 { PRAGMA omit_readlock = 1; ATTACH 'test.db' AS two; BEGIN; SELECT * FROM t1; } } {1 2 3 4 5 6} do_test pager1-17.$tn.3.2 { csql1 { INSERT INTO t1 VALUES(3, 4) } } {1 {database is locked}} do_test pager1-17.$tn.3.3 { sql2 COMMIT } {} } #------------------------------------------------------------------------- # Test the pagers response to the b-tree layer requesting illegal page # numbers: # # + The locking page, # + Page 0, # + A page with a page number greater than (2^31-1). # do_test pager1-18.1 { faultsim_delete_and_reopen db func a_string a_string execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(a_string(500), a_string(200)); INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; } } {} do_test pager1-18.2 { set root [db one "SELECT rootpage FROM sqlite_master"] set lockingpage [expr (0x10000/1024) + 1] execsql { PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage = $lockingpage; } sqlite3 db2 test.db catchsql { SELECT count(*) FROM t1 } db2 } {1 {database disk image is malformed}} db2 close do_test pager1-18.3 { execsql { CREATE TABLE t2(x); INSERT INTO t2 VALUES(a_string(5000)); } set pgno [expr ([file size test.db] / 1024)-2] hexio_write test.db [expr ($pgno-1)*1024] 00000000 sqlite3 db2 test.db catchsql { SELECT length(x) FROM t2 } db2 } {1 {database disk image is malformed}} db2 close do_test pager1-18.4 { hexio_write test.db [expr ($pgno-1)*1024] 90000000 sqlite3 db2 test.db catchsql { SELECT length(x) FROM t2 } db2 } {1 {database disk image is malformed}} db2 close do_test pager1-18.5 { sqlite3 db "" execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; PRAGMA writable_schema = 0; ALTER TABLE t1 RENAME TO x1; } catchsql { SELECT * FROM x1 } } {} db close finish_test |
Changes to test/pagerfault.test.
︙ | ︙ | |||
469 470 471 472 473 474 475 | error "Content looks no good... ($sl)" } } #------------------------------------------------------------------------- # Test fault injection with a temporary database file. # | > | | | | | | | | | | | | | | | | | | > | | > | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | error "Content looks no good... ($sl)" } } #------------------------------------------------------------------------- # Test fault injection with a temporary database file. # foreach v {a b} { do_faultsim_test pagerfault-10$v -prep { sqlite3 db "" db func a_string a_string; execsql { PRAGMA cache_size = 10; BEGIN; CREATE TABLE xx(a, b, UNIQUE(a, b)); INSERT INTO xx VALUES(a_string(200), a_string(200)); INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; COMMIT; } } -body { execsql { UPDATE xx SET a = a_string(300) } } -test { faultsim_test_result {0 {}} if {$::v == "b"} { execsql { PRAGMA journal_mode = TRUNCATE } } faultsim_integrity_check faultsim_integrity_check } } #------------------------------------------------------------------------- # Test fault injection with transaction savepoints (savepoints created # when a SAVEPOINT command is executed outside of any other savepoint # or transaction context). # |
︙ | ︙ | |||
538 539 540 541 542 543 544 | RELEASE trans; } } -test { faultsim_test_result {0 {}} faultsim_integrity_check } | < > > > | | 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | RELEASE trans; } } -test { faultsim_test_result {0 {}} faultsim_integrity_check } #------------------------------------------------------------------------- # Test fault injection when writing to a database file that resides on # a file-system with a sector-size larger than the database page-size. # do_test pagerfault-12-pre1 { testvfs ss_layer -default 1 ss_layer sectorsize 4096 faultsim_delete_and_reopen db func a_string a_string; execsql { |
︙ | ︙ | |||
575 576 577 578 579 580 581 582 | UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y)); } } -test { faultsim_test_result {0 {}} faultsim_integrity_check } | > | > > > > > > > > > > > > > > > > > > > > > > > > > | 580 581 582 583 584 585 586 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 | UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y)); } } -test { faultsim_test_result {0 {}} faultsim_integrity_check } #------------------------------------------------------------------------- # do_test pagerfault-13-pre1 { faultsim_delete_and_reopen db func a_string a_string; execsql { PRAGMA journal_mode = PERSIST; BEGIN; CREATE TABLE t1(x, y UNIQUE); INSERT INTO t1 VALUES(a_string(333), a_string(444)); COMMIT; } db close file delete -force test.db faultsim_save } {} do_faultsim_test pagerfault-13 -prep { faultsim_restore_and_reopen } -body { execsql { CREATE TABLE xx(a, b) } } -test { faultsim_test_result {0 {}} } } finish_test |