From: stephan Date: Tue, 29 Aug 2023 11:22:45 +0000 (+0000) Subject: Init bits of a port of Java's SQLTester to JS. Far from complete. X-Git-Tag: version-3.44.0~239^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=524ddc940d47184bd83771781a6dbd472ccc6365;p=thirdparty%2Fsqlite.git Init bits of a port of Java's SQLTester to JS. Far from complete. FossilOrigin-Name: 60eec5ceda80c64870713df8e9aeabeef933c007f2010792225a07d5ef36baef --- diff --git a/ext/wasm/SQLTester/SQLTester.mjs b/ext/wasm/SQLTester/SQLTester.mjs new file mode 100644 index 0000000000..c295bbd849 --- /dev/null +++ b/ext/wasm/SQLTester/SQLTester.mjs @@ -0,0 +1,290 @@ +/* +** 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 the main application entry pointer for the +** JS implementation of the SQLTester framework. +*/ + +// UNDER CONSTRUCTION. Still being ported from the Java impl. + +import sqlite3ApiInit from '/jswasm/sqlite3.mjs'; + +const sqlite3 = await sqlite3ApiInit(); + +const log = (...args)=>{ + console.log('SQLTester:',...args); +}; + +// Return a new enum entry value +const newE = ()=>Object.create(null); + +const newObj = (props)=>Object.assign(newE(), props); + +/** + Modes for how to escape (or not) column values and names from + SQLTester.execSql() to the result buffer output. +*/ +const ResultBufferMode = Object.assign(Object.create(null),{ + //! Do not append to result buffer + NONE: newE(), + //! Append output escaped. + ESCAPED: newE(), + //! Append output as-is + ASIS: newE() +}); + +/** + Modes to specify how to emit multi-row output from + SQLTester.execSql() to the result buffer. +*/ +const ResultRowMode = newObj({ + //! Keep all result rows on one line, space-separated. + ONLINE: newE(), + //! Add a newline between each result row. + NEWLINE: newE() +}); + +class SQLTesterException extends globalThis.Error { + constructor(...args){ + super(args.join(' ')); + } + isFatal() { return false; } +} + +SQLTesterException.toss = (...args)=>{ + throw new SQLTesterException(...args); +} + +class DbException extends SQLTesterException { + constructor(...args){ + super(...args); + //TODO... + //const db = args[0]; + //if( db instanceof sqlite3.oo1.DB ) + } + isFatal() { return true; } +} + +class TestScriptFailed extends SQLTesterException { + constructor(...args){ + super(...args); + } + isFatal() { return true; } +} + +class UnknownCommand extends SQLTesterException { + constructor(...args){ + super(...args); + } +} + +class IncompatibleDirective extends SQLTesterException { + constructor(...args){ + super(...args); + } +} + +const toss = (errType, ...args)=>{ + if( !(errType instanceof SQLTesterException)){ + args.unshift(errType); + errType = SQLTesterException; + } + throw new errType(...args); +}; + +const __utf8Decoder = new TextDecoder(); +const __utf8Encoder = new TextEncoder('utf-8'); +const __SAB = ('undefined'===typeof globalThis.SharedArrayBuffer) + ? function(){} : globalThis.SharedArrayBuffer; + +const Util = newObj({ + toss, + + unlink: function(fn){ + return 0==sqlite3.wasm.sqlite3_wasm_vfs_unlink(0,fn); + }, + + argvToString: (list)=>list.join(" "), + + utf8Decode: function(arrayBuffer, begin, end){ + return __utf8Decoder.decode( + (arrayBuffer.buffer instanceof __SAB) + ? arrayBuffer.slice(begin, end) + : arrayBuffer.subarray(begin, end) + ); + }, + + utf8Encode: (str)=>__utf8Encoder.encode(str) +})/*Util*/; + +class Outer { + #lnBuf = []; + #verbosity = 0; + #logger = console.log.bind(console); + + out(...args){ + this.#lnBuf.append(...args); + return this; + } + outln(...args){ + this.#lnBuf.append(...args,'\n'); + this.logger(this.#lnBuf.join('')); + this.#lnBuf.length = 0; + return this; + } + + #verboseN(lvl, argv){ + if( this.#verbosity>=lvl ){ + const pre = this.getOutputPrefix ? this.getOutputPrefix() : ''; + this.outln('VERBOSE ',lvl,' ',pre,': ',...argv); + } + } + verbose1(...args){ return this.#verboseN(1,args); } + verbose2(...args){ return this.#verboseN(2,args); } + verbose3(...args){ return this.#verboseN(3,args); } + + verbosity(){ + let rc; + if(arguments.length){ + rc = this.#verbosity; + this.#verbosity = arguments[0]; + }else{ + rc = this.#verbosity; + } + return rc; + } + +}/*Outer*/ + +class SQLTester { + SQLTester(){} + + #aFiles = []; + #inputBuffer = []; + #outputBuffer = []; + #resultBuffer = []; + #nullView = "nil"; + #metrics = newObj({ + nTotalTest: 0, nTestFile: 0, nAbortedScript: 0 + }); + #emitColNames = false; + #keepGoing = false; + #aDb = []; + #db = newObj({ + list: [], + iCurrent: 0, + initialDbName: "test.db", + }); + +}/*SQLTester*/ + +class Command { + Command(){ + } + process(sqlTester,testScript,argv){ + SQLTesterException.toss("process() must be overridden"); + } + argcCheck(testScript,argv,min,max){ + const argc = argv.length-1; + if(argc=0 && argc>max)){ + if( min==max ){ + testScript.toss(argv[0]," requires exactly ",min," argument(s)"); + }else if(max>0){ + testScript.toss(argv[0]," requires ",min,"-",max," arguments."); + }else{ + testScript.toss(argv[0]," requires at least ",min," arguments."); + } + } + + } +} + +class Cursor { + src; + buffer = []; + pos = 0; + //! Current line number. Starts at 0 for internal reasons and will + // line up with 1-based reality once parsing starts. + lineNo = 0 /* yes, zero */; + //! Putback value for this.pos. + putbackPos = 0; + //! Putback line number + putbackLineNo = 0; + //! Peeked-to pos, used by peekLine() and consumePeeked(). + peekedPos = 0; + //! Peeked-to line number. + peekedLineNo = 0; + + //! Restore parsing state to the start of the stream. + rewind(){ + this.buffer.length = 0; + this.pos = this.lineNo = this.putbackPos = + this.putbackLineNo = this.peekedPos = this.peekedLineNo = 0; + } +} + +class TestScript { + #cursor = new Cursor(); + #verbosity = 0; + #moduleName = null; + #filename = null; + #testCaseName = null; + #outer = new Outer(); + #verboseN(lvl, argv){ + if( this.#verbosity>=lvl ){ + this.outln('VERBOSE ',lvl,': ',...argv); + } + } + + verbose1(...args){ return this.#verboseN(1,args); } + verbose2(...args){ return this.#verboseN(2,args); } + verbose3(...args){ return this.#verboseN(3,args); } + + TestScript(content){ + this.cursor.src = content; + this.outer.outputPrefix = ()=>this.getOutputPrefix(); + } + + verbosity(){ + let rc; + if(arguments.length){ + rc = this.#verbosity; + this.#verbosity = arguments[0]; + }else{ + rc = this.#verbosity; + } + return rc; + } + + getOutputPrefix() { + const rc = "["+(this.moduleName || this.filename)+"]"; + if( this.testCaseName ) rc += "["+this.testCaseName+"]"; + return rc + " line "+ this.cur.lineNo; + } + + toss(...args){ + Util.toss(this.getOutputPrefix()+":",TestScriptFailed,...args) + } + +}/*TestScript*/; + + +const namespace = newObj({ + SQLTester: new SQLTester(), + DbException, + IncompatibleDirective, + SQLTesterException, + TestScriptFailed, + UnknownCommand +}); + + +export {namespace as default}; diff --git a/ext/wasm/SQLTester/SQLTester.run.mjs b/ext/wasm/SQLTester/SQLTester.run.mjs new file mode 100644 index 0000000000..0a0f8903b7 --- /dev/null +++ b/ext/wasm/SQLTester/SQLTester.run.mjs @@ -0,0 +1,8 @@ +import {default as ns} from './SQLTester.mjs'; + +const log = (...args)=>{ + console.log('SQLTester.run:',...args); +}; + + +log("SQLTester is ostensibly ready."); diff --git a/ext/wasm/SQLTester/index.html b/ext/wasm/SQLTester/index.html new file mode 100644 index 0000000000..e782f1367d --- /dev/null +++ b/ext/wasm/SQLTester/index.html @@ -0,0 +1,26 @@ + + + + + + + + + SQLTester + + +

SQLTester App. +

+

All stuff on this page happens in the dev console.

+
+
+ + + + diff --git a/manifest b/manifest index b237cd5f65..9e9e27578e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\ssome\sdead\scode.\sAdd\sa\sskeleton\sSQLTester\sscript\sfor\sfts5. -D 2023-08-29T00:10:31.208 +C Init\sbits\sof\sa\sport\sof\sJava's\sSQLTester\sto\sJS.\sFar\sfrom\scomplete. +D 2023-08-29T11:22:45.711 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -548,6 +548,9 @@ 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 a3d6ed049e578b2d0965273016f56293584823760df8ff850868c1f8aea17533 +F ext/wasm/SQLTester/SQLTester.run.mjs 156e174b98e7dd78bf6d1438d32e60d7a647f8b51d8246a3054e5fdfe6042478 +F ext/wasm/SQLTester/index.html 88d87e3ccbc33e7ab3773a8e48c1172e876951c4be31d1307c3700671262cddf 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 @@ -2108,8 +2111,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 76d3911c370b3dc02d119045003f87ad20a6efd9f7a44d4feb59b7c801ac8981 -R 7d288c901b3674a6a88e2405123881f5 +P 6c83e31fa96f65b61377c0c801cc32b3c8ca27a0c8442f860364bec258c003cb +R 94685fe29bdbe21cb1fdfbf40f131ffe +T *branch * js-tester +T *sym-js-tester * +T -sym-trunk * Cancelled\sby\sbranch. U stephan -Z 6f3a62c9006357f22c26cb9d02ee32ca +Z 952fd010d6a4d240388ad80f3eddac99 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 094b411e25..d92a1595ed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c83e31fa96f65b61377c0c801cc32b3c8ca27a0c8442f860364bec258c003cb \ No newline at end of file +60eec5ceda80c64870713df8e9aeabeef933c007f2010792225a07d5ef36baef \ No newline at end of file