From: stephan Date: Wed, 30 Aug 2023 00:22:54 +0000 (+0000) Subject: Add a mechanism with which to import external SQLTester scripts into the JS testing... X-Git-Tag: version-3.44.0~239^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ac5e1f82ce5e4103bf31882252587f3cbb2a564b;p=thirdparty%2Fsqlite.git Add a mechanism with which to import external SQLTester scripts into the JS testing tool. FossilOrigin-Name: bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624 --- diff --git a/ext/wasm/SQLTester/GNUmakefile b/ext/wasm/SQLTester/GNUmakefile new file mode 100644 index 0000000000..63388084d9 --- /dev/null +++ b/ext/wasm/SQLTester/GNUmakefile @@ -0,0 +1,55 @@ +#!/this/is/make +# +# This makefile compiles SQLTester test files into something +# we can readily import into JavaScript. +all: + +SHELL := $(shell which bash 2>/dev/null) +MAKEFILE := $(lastword $(MAKEFILE_LIST)) +CLEAN_FILES := +DISTCLEAN_FILES := ./--dummy-- *~ + +test-list.mjs := test-list.mjs +test-list.mjs.gz := $(test-list.mjs).gz +CLEAN_FILES += $(test-list.mjs) + +tests.dir := $(firstword $(wildcard tests ../../jni/src/tests)) +$(info test script dir=$(tests.dir)) + +tests.all := $(wildcard $(tests.dir)/*.test) + +bin.touint8array := ./touint8array +$(bin.touint8array): $(bin.touint8array).c $(MAKEFILE) + $(CC) -o $@ $< +CLEAN_FILES += $(bin.touint8array) + +ifneq (,$(tests.all)) +$(test-list.mjs): $(bin.touint8array) $(tests.all) $(MAKEFILE) + @{\ + echo 'export default ['; \ + sep=''; \ + for f in $(sort $(tests.all)); do \ + echo -en $$sep'{"name": "'$${f##*/}'", "content":'; \ + $(bin.touint8array) < $$f; \ + echo -n '}'; \ + sep=',\n'; \ + done; \ + echo '];'; \ + } > $@ + @echo "Created $@" +$(test-list.mjs.gz): $(test-list.mjs) + gzip -c $< > $@ +CLEAAN_FILES += $(test-list.mjs.gz) +all: $(test-list.mjs.gz) +else + @echo "Cannot build $(test-list.mjs) for lack of input test files."; \ + echo "Symlink ./tests to a directory containing SQLTester-format "; \ + echo "test scripts named *.test, then try again"; \ + exit 1 +endif + +.PHONY: clean distclean +clean: + -rm -f $(CLEAN_FILES) +distclean: clean + -rm -f $(DISTCLEAN_FILES) diff --git a/ext/wasm/SQLTester/SQLTester.mjs b/ext/wasm/SQLTester/SQLTester.mjs index aa02d7a5ec..0ec82ca464 100644 --- a/ext/wasm/SQLTester/SQLTester.mjs +++ b/ext/wasm/SQLTester/SQLTester.mjs @@ -9,12 +9,13 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains the main application entry pointer for the -** JS implementation of the SQLTester framework. +** This file contains the main application entry pointer for the JS +** implementation of the SQLTester framework. This version is not well +** documented because the one it's a direct port of is documented: +** in the main SQLite3 source tree, see +** ext/jni/src/org/sqlite/jni/tester/SQLite3Tester.java. */ -// UNDER CONSTRUCTION. Still being ported from the Java impl. - import sqlite3ApiInit from '/jswasm/sqlite3.mjs'; const sqlite3 = await sqlite3ApiInit(); @@ -23,6 +24,43 @@ const log = (...args)=>{ console.log('SQLTester:',...args); }; +const tryInstallVfs = function f(vfsName){ + if(f.vfsName) return false; + const pVfs = sqlite3.capi.sqlite3_vfs_find(vfsName); + if(pVfs){ + log("Installing",'"'+vfsName+'"',"as default VFS."); + const rc = sqlite3.capi.sqlite3_vfs_register(pVfs, 1); + if(rc){ + sqlite3.SQLite3Error.toss(rc,"While trying to register",vfsName,"vfs."); + } + f.vfsName = vfsName; + } + return !!pVfs; +}; +tryInstallVfs.vfsName = undefined; + +if( 1 ){ + // Try OPFS storage, if available... + if(sqlite3.installOpfsSAHPoolVfs){ + await sqlite3.installOpfsSAHPoolVfs({ + clearOnInit: true, + initialCapacity: 15, + name: 'opfs-SQLTester' + }).then(pool=>{ + tryInstallVfs(pool.vfsName); + }).catch(e=>{ + log("OpfsSAHPool could not load:",e); + }); + } + if(sqlite3.oo1.OpfsDb){ + tryInstallVfs("opfs"); + } +} + +const wPost = (type,...payload)=>{ + postMessage({type, payload}); +}; + // Return a new enum entry value const newE = ()=>Object.create(null); @@ -215,7 +253,7 @@ class SQLTester { //! Test result buffer. #resultBuffer = []; //! Output representation of SQL NULL. - #nullView = "nil"; + #nullView; metrics = newObj({ //! Total tests run nTotalTest: 0, @@ -245,6 +283,7 @@ class SQLTester { }); constructor(){ + this.reset(); } outln(...args){ return this.#outer.outln(...args); } @@ -261,7 +300,7 @@ class SQLTester { this.#clearBuffer(this.#db.initSql); this.closeAllDbs(); this.metrics.nTest = 0; - this.nullView = "nil"; + this.#nullView = "nil"; this.emitColNames = false; this.#db.iCurrentDb = 0; //this.#db.initSql.push("SELECT 1;"); @@ -424,12 +463,19 @@ class SQLTester { runTests(){ const tStart = (new Date()).getTime(); + let isVerbose = this.verbosity(); for(const ts of this.#aScripts){ this.reset(); ++this.metrics.nTestFile; let threw = false; const timeStart = (new Date()).getTime(); + let msgTail = ''; try{ + if( isVerbose ){ + this.#outer.verbose1("Running ",ts.filename()); + }else{ + msgTail = ' '+ts.filename(); + } ts.run(this); }catch(e){ if(e instanceof SQLTesterException){ @@ -446,7 +492,7 @@ class SQLTester { }finally{ const timeEnd = (new Date()).getTime(); this.outln("🏁", (threw ? "❌" : "✅"), " ", this.metrics.nTest, - " test(s) in ", (timeEnd-timeStart),"ms."); + " test(s) in ", (timeEnd-timeStart),"ms.",msgTail); } } const tEnd = (new Date()).getTime(); @@ -544,7 +590,7 @@ class SQLTester { if(throwOnError){ throw new DbException(self, pDb, rc); }else if( sb ){ - self.#appendDbErr(db, sb, rc); + self.#appendDbErr(pDb, sb, rc); } break; } @@ -666,13 +712,20 @@ class TestScript { if( 2 == args.length ){ filename = args[0]; content = args[1]; - }else{ - content = args[0]; + }else if( 1 == args.length ){ + if(args[0] instanceof Object){ + const o = args[0]; + filename = o.name; + content = o.content; + }else{ + content = args[0]; + } } if(!(content instanceof Uint8Array)){ if('string' === typeof content){ content = Util.utf8Encode(content); - }else if(content instanceof ArrayBuffer){ + }else if((content instanceof ArrayBuffer) + ||(content instanceof Array)){ content = new Uint8Array(content); }else{ toss(Error, "Invalid content type for TestScript constructor."); @@ -686,6 +739,10 @@ class TestScript { return (0==arguments.length) ? this.#testCaseName : (this.#testCaseName = arguments[0]); } + filename(){ + return (0==arguments.length) + ? this.#filename : (this.#filename = arguments[0]); + } getOutputPrefix() { let rc = "["+(this.#moduleName || this.#filename)+"]"; @@ -1041,7 +1098,7 @@ class RunCommand extends Command { ResultRowMode.ONELINE, sql); if( 0!==rc && t.verbosity()>0 ){ const msg = sqlite3.capi.sqlite3_errmsg(pDb); - ts.verbose1(argv[0]," non-fatal command error #",rc,": ", + ts.verbose2(argv[0]," non-fatal command error #",rc,": ", msg,"\nfor SQL:\n",sql); } } diff --git a/ext/wasm/SQLTester/SQLTester.run.mjs b/ext/wasm/SQLTester/SQLTester.run.mjs index e58db93450..e6730253b6 100644 --- a/ext/wasm/SQLTester/SQLTester.run.mjs +++ b/ext/wasm/SQLTester/SQLTester.run.mjs @@ -1,4 +1,18 @@ +/* +** 2023-08-29 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains a test application for SQLTester.js. +*/ import {default as ns} from './SQLTester.mjs'; +import {default as tests} from './test-list.mjs'; globalThis.sqlite3 = ns.sqlite3; const log = function f(...args){ @@ -19,16 +33,13 @@ const affirm = function(expr, msg){ } } -console.log("Loaded",ns); - -log("ns =",ns); -outln("SQLTester is ready."); +log("SQLTester is ready."); let ts = new ns.TestScript('/foo.test',` /* ** This is a comment. There are many like it but this one is mine. ** -** SCRIPT_MODULE_NAME: sanity-check +** SCRIPT_MODULE_NAME: sanity-check-0 ** xMIXED_MODULE_NAME: mixed-module ** xMODULE_NAME: module-name ** xREQUIRED_PROPERTIES: small fast reliable @@ -45,10 +56,10 @@ let ts = new ns.TestScript('/foo.test',` --oom --db 0 --new my.db ---null zilch +--null zilchy --testcase 1.0 SELECT 1, null; ---result 1 zilch +--result 1 zilchy --glob *zil* --notglob *ZIL* SELECT 1, 2; @@ -85,20 +96,27 @@ SELECT json_array(1,2,3) const sqt = new ns.SQLTester(); try{ - affirm( !sqt.getCurrentDb(), 'sqt.getCurrentDb()' ); - sqt.openDb('/foo.db', true); - affirm( !!sqt.getCurrentDb(),'sqt.getCurrentDb()' ); - sqt.verbosity(0); - if(false){ - affirm( 'zilch' !== sqt.nullValue() ); - ts.run(sqt); - affirm( 'zilch' === sqt.nullValue() ); + if( 0 ){ + affirm( !sqt.getCurrentDb(), 'sqt.getCurrentDb()' ); + sqt.openDb('/foo.db', true); + affirm( !!sqt.getCurrentDb(),'sqt.getCurrentDb()' ); + sqt.verbosity(0); + if(false){ + affirm( 'zilch' !== sqt.nullValue() ); + ts.run(sqt); + affirm( 'zilch' === sqt.nullValue() ); + } + sqt.addTestScript(ts); + sqt.runTests(); + }else{ + for(const t of tests){ + sqt.addTestScript( new ns.TestScript(t) ); + } + tests.length = 0; + sqt.verbosity(0); + sqt.runTests(); } - sqt.addTestScript(ts); - sqt.runTests(); }finally{ + log( "Metrics:", sqt.metrics ); sqt.reset(); } -log( 'sqt.getCurrentDb()', sqt.getCurrentDb() ); -log( "Metrics:", sqt.metrics ); - diff --git a/ext/wasm/SQLTester/index.html b/ext/wasm/SQLTester/index.html index e782f1367d..8ae3e27a36 100644 --- a/ext/wasm/SQLTester/index.html +++ b/ext/wasm/SQLTester/index.html @@ -14,13 +14,14 @@

All stuff on this page happens in the dev console.


- - + diff --git a/ext/wasm/SQLTester/touint8array.c b/ext/wasm/SQLTester/touint8array.c new file mode 100644 index 0000000000..b03ad42f03 --- /dev/null +++ b/ext/wasm/SQLTester/touint8array.c @@ -0,0 +1,29 @@ +/* +** 2023-08-29 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains a tool for writing out the contents of stdin as +** a comma-separated list of numbers, one per byte. +*/ + +#include +int main(int argc, char const **argv){ + int i; + int rc = 0, colWidth = 30; + int ch; + printf("["); + for( i=0; EOF!=(ch = fgetc(stdin)); ++i ){ + if( 0!=i ) printf(","); + if( i && 0==(i%colWidth) ) puts(""); + printf("%d",ch); + } + printf("]"); + return rc; +} diff --git a/manifest b/manifest index c8e5581fda..7088c67f05 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sdirectives\ssupport\sto\sJS\sSQLTester\scomparable\sto\sthe\sJava\simpl.\sThis\sbrings\sthe\stwo\sto\sfeature\sparity. -D 2023-08-29T21:30:37.122 +C Add\sa\smechanism\swith\swhich\sto\simport\sexternal\sSQLTester\sscripts\sinto\sthe\sJS\stesting\stool. +D 2023-08-30T00:22:54.642 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -548,9 +548,11 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce F ext/wasm/GNUmakefile 0e362f3fc04eab6628cbe4f1e35f4ab4a200881f6b5f753b27fb45eabeddd9d2 F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576 F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193 -F ext/wasm/SQLTester/SQLTester.mjs 40583ad88bbc32c602e9bfbcd7a90ea6bdfeed41994c1fcc0a7e9d0ffdcd9a5e -F ext/wasm/SQLTester/SQLTester.run.mjs de03763f8085a130e17706a8c475d7bab37f77eff4f5322b0cc33504733394d7 -F ext/wasm/SQLTester/index.html 88d87e3ccbc33e7ab3773a8e48c1172e876951c4be31d1307c3700671262cddf +F ext/wasm/SQLTester/GNUmakefile ba0430646d75a832d1647d6d204c999112d831f5e85d3ed99d8f663fea20fe19 +F ext/wasm/SQLTester/SQLTester.mjs 378868be0fcbbb92456aea10e3056f88b042e106b2c348aa51060e93726f6e10 +F ext/wasm/SQLTester/SQLTester.run.mjs 2695490e2092af0c6a9d1e4128edf830648687a54ec1f0ecd16bd1be083f3938 +F ext/wasm/SQLTester/index.html 317636557257608b103fa740c07f2d440d57b924ef2072e59c1372d4a4004c06 +F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 @@ -2111,8 +2113,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8c503dfb9fa15389613a819fcc1792e23d3c05f99a9f450f82eac5125298726f -R e03f3f1709d7ca32242a0e49e3b98e3f +P 7cef4a8300826adbdcb3b205e134a4272b12b4aa7dbee97731ac12282a4a9f06 +R 018b862c43a96a36d2df3223b087af85 U stephan -Z ecc2ea98d4d7da8116d2d29b184f2709 +Z 18f8112180ee272e1f7e50a87a0ce726 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index cb91036e81..7168a7b8ad 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7cef4a8300826adbdcb3b205e134a4272b12b4aa7dbee97731ac12282a4a9f06 \ No newline at end of file +bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624 \ No newline at end of file