From: drh <> Date: Tue, 13 Aug 2024 19:30:03 +0000 (+0000) Subject: Infrastructure for a new test program named "iotester" that strives to verify X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5caee6fad84bf59210890bcd787ae998cf54b591;p=thirdparty%2Fsqlite.git Infrastructure for a new test program named "iotester" that strives to verify the operation of a VFS object. FossilOrigin-Name: b46d86c22bd486789affa9c5e41b8f6ee47bae23eee5efe0640db3d3860e8a7a --- diff --git a/Makefile.in b/Makefile.in index 7ff6e901e4..cb74e35443 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1537,6 +1537,9 @@ threadtest: threadtest3$(TEXE) threadtest5: sqlite3.c $(TOP)/test/threadtest5.c $(LTLINK) $(TOP)/test/threadtest5.c sqlite3.c -o $@ $(TLIBS) +iotester: sqlite3.lo $(TOP)/test/iotester.c + $(LTLINK) $(TOP)/test/iotester.c sqlite3.lo -o $@ $(TLIBS) + # Standard install and cleanup targets # lib_install: libsqlite3.la diff --git a/Makefile.msc b/Makefile.msc index e31aee0899..844e33b771 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1301,7 +1301,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ # Object files for the amalgamation. # -LIBOBJS1 = sqlite3.lo +LIBOBJS1 = sqlite3.obj # Determine the real value of LIBOBJ based on the 'configure' script # @@ -1944,7 +1944,7 @@ sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl # Rule to build the amalgamation # -sqlite3.lo: $(SQLITE3C) +sqlite3.obj: $(SQLITE3C) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C) # <> @@ -2700,6 +2700,9 @@ THREADTEST3_SRC = \ threadtest3.exe: $(THREADTEST3_SRC) $(TOP)\src\test_multiplex.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(TOP)\test\threadtest3.c $(TOP)\src\test_multiplex.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) +iotester.exe: sqlite3.obj $(TOP)\test\iotester.c + $(LTLINK) $(TOP)\test\iotester.c sqlite3.obj /link $(LDFLAGS) $(LTLINKOPTS) + LSMDIR=$(TOP)\ext\lsm1 !INCLUDE $(LSMDIR)\Makefile.msc diff --git a/manifest b/manifest index 159330c456..fe9be1b930 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Resolve\sparameters\sBind\s$int_N\sand\s$test_T\sin\sfuzzcheck\sinputs. -D 2024-08-12T09:49:02.212 +C Infrastructure\sfor\sa\snew\stest\sprogram\snamed\s"iotester"\sthat\sstrives\sto\sverify\nthe\soperation\sof\sa\sVFS\sobject. +D 2024-08-13T19:30:03.469 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in cf96aa7d2682650dec56dc2f03cfe463feb101a1be594e4929bcd38662bc2ea8 +F Makefile.in b3af743d2ce5be536a2643143847feca680a745e309a8884a9b45220f56228ab F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6 -F Makefile.msc 6c3fe8b6ce60e73f34a148c957d78b4648745c8d30e792423aa1a8d8bf12d065 +F Makefile.msc 744d25d85ceb0080b147cfc188740fbdba1a45a53f08a421f530fb80b60eadba F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3 F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1337,6 +1337,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c F test/ioerr5.test 5984da7bf74b6540aa356f2ab0c6ae68a6d12039a3d798a9ac6a100abc17d520 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b +F test/iotester.c 4df6dff77a78162808854dd6d3810ed4fe2a8fe4ba5e95a74575548f23480026 F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9 F test/join.test f7abfef3faeaf2800308872e33a57e5b6e4a2b44fb8c6b90c6068412e71a6cf4 F test/join2.test 8561fe82ce434ac96de91544072e578dc2cadddf2d9bc9cd802f866a9b92502e @@ -2204,8 +2205,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d4014c87ba9b011a6a04c2bf85879b668dc762ebcbbfb50a2f8a417ce594ef88 -R 33ab7e360692d6ed2c1cd4d18565e8ac +P 9c10664416274df6f8da53ddd86f6356c9704ad798fd4034d2784ae433c1c056 +R d53719958cd6e7f4f987278bf19c1278 U drh -Z 32b23835ef00f951c0107d2a77ff843c +Z 4d2d6900391d50d204c15f38c15fadf7 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ef73d7fbbd..6e9d3c7338 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9c10664416274df6f8da53ddd86f6356c9704ad798fd4034d2784ae433c1c056 +b46d86c22bd486789affa9c5e41b8f6ee47bae23eee5efe0640db3d3860e8a7a diff --git a/test/iotester.c b/test/iotester.c new file mode 100644 index 0000000000..56bb287aa5 --- /dev/null +++ b/test/iotester.c @@ -0,0 +1,353 @@ +/* +** 2024-08-13 +** +** 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. +** +************************************************************************* +** +** A program to test I/O through a VFS implementations. +** +** This program is intended as a template for custom test module used +** to verify ports of SQLite to non-standard platforms. Typically +** porting SQLite to a new platform requires writing a new VFS object +** to implement the I/O methods required by SQLite. This file contains +** code that attempts exercise such a VFS object and verify that it is +** operating correctly. +*/ +#include "sqlite3.h" +#include +#include + +/* Number of elements in static array X */ +#define COUNT(X) (sizeof(X)/sizeof(X[0])) + +/* +** State of the tester. +*/ +typedef struct IOTester IOTester; +struct IOTester { + int pgsz; /* Databases should use this page size */ + const char *zJMode; /* Databases should use this journal mode */ + int isExclusive; /* True for exclusive locking mode */ + sqlite3_int64 szMMap; /* Memory-map size */ + const char *zTestModule; /* Test module currently running */ + int iTestNum; /* Test number currently running */ + int nTest; /* Total number of tests run */ + int nFault; /* Number of test failures */ + int nOOM; /* Out of memory faults */ + int eVerbosity; /* How much output */ + sqlite3_str *errTxt; /* Error text written here */ +}; + + +/* Forward declarations of subroutines and functions. */ +void iotestError(IOTester*,const char *zFormat, ...); +sqlite3 *iotestOpenDb(IOTester*,const char *zDbName); +void iotestUnlink(IOTester *p, const char *zFilename); +void iotestBeginTest(IOTester *p, int iTestnum); + + +void iotestBasic1(IOTester*); + + +/********************************** Utilities ******************************* +** +** Functions intended for common use by all test modules. +*/ + +/* +** Record a test failure. +*/ +void iotestError(IOTester *p, const char *zFormat, ...){ + va_list ap; + p->nFault++; + if( p->errTxt==0 ){ + p->errTxt = sqlite3_str_new(0); + if( p==0 ){ + p->nOOM++; + return; + } + } + sqlite3_str_appendf(p->errTxt, + "FAULT: %s-%d pgsz=%d journal-mode=%s mmap-size=%lld", + p->zTestModule, p->iTestNum, + p->pgsz, p->zJMode, p->szMMap); + if( p->isExclusive ){ + sqlite3_str_appendf(p->errTxt, " exclusive-locking-mode"); + } + sqlite3_str_appendf(p->errTxt, "\n"); + if( zFormat ){ + va_start(ap, zFormat); + sqlite3_str_vappendf(p->errTxt, zFormat, ap); + va_end(ap); + } +} + +/* +** Create a new prepared statement based on SQL text. +*/ +sqlite3_stmt *iotestVPrepare( + IOTester *p, + sqlite3 *db, + const char *zFormat, + va_list ap +){ + char *zSql = 0; + int rc; + sqlite3_stmt *pStmt = 0; + if( db==0 ) return 0; + zSql = sqlite3_vmprintf(zFormat, ap); + if( zSql==0 ){ + p->nOOM++; + return 0; + } + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK || pStmt==0 ){ + iotestError(p, "unable to prepare statement: \"%s\"\n", zSql); + sqlite3_free(zSql); + sqlite3_finalize(pStmt); + } + return pStmt; +} + + +/* +** Run a statement against a database. Expect no results. +*/ +void iotestRun( + IOTester *p, + sqlite3 *db, + const char *zSql, + ... +){ + va_list ap; + sqlite3_stmt *pStmt = 0; + if( db==0 ) return; + va_start(ap, zSql); + pStmt = iotestVPrepare(p, db, zSql, ap); + va_end(ap); + if( pStmt ){ + int rc; + while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){} + if( rc==SQLITE_ERROR ){ + iotestError(p, "error running SQL statement %s: %s\n", + sqlite3_sql(pStmt), sqlite3_errmsg(db)); + } + } + sqlite3_finalize(pStmt); +} + +/* +** Run a query against a database that returns a single integer. +*/ +sqlite3_int64 iotestQueryInt( + IOTester *p, + sqlite3 *db, + sqlite3_int64 iDflt, + const char *zSql, + ... +){ + va_list ap; + sqlite3_stmt *pStmt = 0; + sqlite3_int64 res = iDflt; + int rc; + if( db==0 ) return iDflt; + va_start(ap, zSql); + pStmt = iotestVPrepare(p, db, zSql, ap); + va_end(ap); + if( pStmt==0 ){ + return iDflt; + } + rc = sqlite3_step(pStmt); + if( rc==SQLITE_ROW ){ + res = sqlite3_column_int64(pStmt, 0); + }else if( rc==SQLITE_ERROR ){ + iotestError(p, "error while running \"%s\": %s\n", + sqlite3_sql(pStmt), sqlite3_errmsg(db)); + res = iDflt; + } + sqlite3_finalize(pStmt); + return res; +} + +/* +** Open a database. Return a pointer to that database connection, +** or if something goes wrong, return a NULL pointer. +** +** If the database does not previously exist, then do all the necessary +** setup as proscribed by the IOTester configuration. +*/ +sqlite3 *iotestOpen(IOTester *p, const char *zDbFilename){ + sqlite3 *db; + int rc; + + rc = sqlite3_open(zDbFilename, &db); + if( rc!=SQLITE_OK ){ + iotestError(p, "cannot open database \"%s\"\n", zDbFilename); + sqlite3_close(db); + return 0; + } + if( iotestQueryInt(p, db, -1, "PRAGMA page_count")==0 ){ + iotestRun(p, db, "PRAGMA page_size=%d", p->pgsz); + iotestRun(p, db, "PRAGMA journal_mode=%s", p->zJMode); + iotestRun(p, db, "PRAGMA mmap_size=%lld", p->szMMap); + if( p->isExclusive ){ + iotestRun(p, db, "PRAGMA locking_mode=EXCLUSIVE;"); + } + iotestRun(p, db, "PRAGMA cache_size=2;"); + } + return db; +} + + +/*********************************** Test Modules **************************** +*/ +void iotestBasic1(IOTester *p){ + sqlite3 *db = 0; + p->zTestModule = "basic1"; + iotestBeginTest(p, 1); + iotestUnlink(p, "basic1.db"); + if( p->nFault ) return; + iotestBeginTest(p, 2); + db = iotestOpen(p, "basic1.db"); + if( p->nFault ) goto basic1_exit; + iotestBeginTest(p, 3); + iotestRun(p, db, "CREATE TABLE t1(a,b,c);"); + if( p->nFault ) goto basic1_exit; + iotestBeginTest(p, 4); + iotestRun(p, db, "DROP TABLE t1;"); + +basic1_exit: + sqlite3_close(db); + iotestUnlink(p, "basic1.db"); +} + +/********************** Out-Of-Band System Interactions ********************** +** +** Any customizations that need to be made to port this test program to +** new platforms are made below this point. +** +** These functions access the filesystem directly or make other system +** interactions that are non-portable. Modify these routines as necessary +** to work on alternative operating systems. +*/ +#include +#ifdef _WIN32 +# include +#else +# include +# include +#endif + +/* Remove the named file from disk, if it exists. +** +** If the file does not exist, this routine is a no-op. +** If the file does exists but could not be removed, this routine raises +** and error in the IOTester module. +*/ +void iotestUnlink(IOTester *p, const char *zFilename){ + int rc; +#ifdef _WIN32 + rc = remove(zFilename); +#else + rc = unlink(zFilename); +#endif + if( rc!=0 && errno!=ENOENT ){ + iotestError(p, "cannot delete file \"%s\"\n", zFilename); + } +} + +/* +** Start a new test case. (This is under the "Out-of-band" section because +** of its optional use of printf().) +*/ +void iotestBeginTest(IOTester *p, int iTN){ + p->iTestNum = iTN; + p->nTest++; + if( p->eVerbosity>=2 ) printf("%s-%d\n", p->zTestModule, iTN); +} + +/*********************************** Main ************************************ +** +** The main test driver. +*/ +int main(int argc, char **argv){ + IOTester x; + int i; + static const int aPgsz[] = { + 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 + }; + static const char *azJMode[] = { + "delete", "truncate", "persist", "wal" + }; + static const sqlite3_int64 aszMMap[] = { + 0, 2097152, 2147483648 + }; + memset(&x, 0, sizeof(x)); + for(i=1; i=1 ){ + printf("pgsz=%d journal_mode=%s mmap_size=%lld exclusive=%d\n", + x.pgsz, x.zJMode, x.szMMap, x.isExclusive); + } + + iotestBasic1(&x); + if( x.nFault ) break; + } + + /* Report results */ + printf("%d tests and %d errors\n", x.nTest, x.nFault); + if( x.nOOM ) printf("%d out-of-memory faults\n", x.nOOM); + if( x.errTxt ){ + char *zMsg = sqlite3_str_finish(x.errTxt); + if( zMsg ){ + printf("%s", zMsg); + sqlite3_free(zMsg); + } + } + return x.nFault>0; +}