mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add a UI, of sorts, to the JS SQLTester.
FossilOrigin-Name: 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c
This commit is contained in:
@@ -39,7 +39,7 @@ $(test-list.mjs): $(bin.touint8array) $(tests.all) $(MAKEFILE)
|
|||||||
@echo "Created $@"
|
@echo "Created $@"
|
||||||
$(test-list.mjs.gz): $(test-list.mjs)
|
$(test-list.mjs.gz): $(test-list.mjs)
|
||||||
gzip -c $< > $@
|
gzip -c $< > $@
|
||||||
CLEAAN_FILES += $(test-list.mjs.gz)
|
CLEAN_FILES += $(test-list.mjs.gz)
|
||||||
all: $(test-list.mjs.gz)
|
all: $(test-list.mjs.gz)
|
||||||
else
|
else
|
||||||
@echo "Cannot build $(test-list.mjs) for lack of input test files."; \
|
@echo "Cannot build $(test-list.mjs) for lack of input test files."; \
|
||||||
|
@@ -10,10 +10,11 @@
|
|||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains the main application entry pointer for the JS
|
** This file contains the main application entry pointer for the JS
|
||||||
** implementation of the SQLTester framework. This version is not well
|
** implementation of the SQLTester framework.
|
||||||
** documented because the one it's a direct port of is documented:
|
**
|
||||||
** in the main SQLite3 source tree, see
|
** This version is not well-documented because it's a direct port of
|
||||||
** ext/jni/src/org/sqlite/jni/tester/SQLite3Tester.java.
|
** the Java immplementation, which is documented: in the main SQLite3
|
||||||
|
** source tree, see ext/jni/src/org/sqlite/jni/tester/SQLite3Tester.java.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import sqlite3ApiInit from '/jswasm/sqlite3.mjs';
|
import sqlite3ApiInit from '/jswasm/sqlite3.mjs';
|
||||||
@@ -24,6 +25,12 @@ const log = (...args)=>{
|
|||||||
console.log('SQLTester:',...args);
|
console.log('SQLTester:',...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Try to install vfsName as the new default VFS. Once this succeeds
|
||||||
|
(returns true) then it becomes a no-op on future calls. Throws if
|
||||||
|
vfs registration as the default VFS fails but has no side effects
|
||||||
|
if vfsName is not currently registered.
|
||||||
|
*/
|
||||||
const tryInstallVfs = function f(vfsName){
|
const tryInstallVfs = function f(vfsName){
|
||||||
if(f.vfsName) return false;
|
if(f.vfsName) return false;
|
||||||
const pVfs = sqlite3.capi.sqlite3_vfs_find(vfsName);
|
const pVfs = sqlite3.capi.sqlite3_vfs_find(vfsName);
|
||||||
@@ -39,9 +46,13 @@ const tryInstallVfs = function f(vfsName){
|
|||||||
};
|
};
|
||||||
tryInstallVfs.vfsName = undefined;
|
tryInstallVfs.vfsName = undefined;
|
||||||
|
|
||||||
if( 1 ){
|
if( 0 && globalThis.WorkerGlobalScope ){
|
||||||
// Try OPFS storage, if available...
|
// Try OPFS storage, if available...
|
||||||
if(sqlite3.installOpfsSAHPoolVfs){
|
if( 0 && sqlite3.oo1.OpfsDb ){
|
||||||
|
/* Really slow with these tests */
|
||||||
|
tryInstallVfs("opfs");
|
||||||
|
}
|
||||||
|
if( sqlite3.installOpfsSAHPoolVfs ){
|
||||||
await sqlite3.installOpfsSAHPoolVfs({
|
await sqlite3.installOpfsSAHPoolVfs({
|
||||||
clearOnInit: true,
|
clearOnInit: true,
|
||||||
initialCapacity: 15,
|
initialCapacity: 15,
|
||||||
@@ -52,14 +63,16 @@ if( 1 ){
|
|||||||
log("OpfsSAHPool could not load:",e);
|
log("OpfsSAHPool could not load:",e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(sqlite3.oo1.OpfsDb){
|
|
||||||
tryInstallVfs("opfs");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const wPost = (type,...payload)=>{
|
const wPost = (function(){
|
||||||
|
return (('undefined'===typeof WorkerGlobalScope)
|
||||||
|
? ()=>{}
|
||||||
|
: (type, payload)=>{
|
||||||
postMessage({type, payload});
|
postMessage({type, payload});
|
||||||
};
|
});
|
||||||
|
})();
|
||||||
|
//log("WorkerGlobalScope",globalThis.WorkerGlobalScope);
|
||||||
|
|
||||||
// Return a new enum entry value
|
// Return a new enum entry value
|
||||||
const newE = ()=>Object.create(null);
|
const newE = ()=>Object.create(null);
|
||||||
@@ -99,6 +112,12 @@ class SQLTesterException extends globalThis.Error {
|
|||||||
}
|
}
|
||||||
this.name = 'SQLTesterException';
|
this.name = 'SQLTesterException';
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
If this overrideable method returns false (the default) then
|
||||||
|
exceptions of that type are fatal to a whole test run, instead of
|
||||||
|
just the test which triggered it. If the the "keep going" flag
|
||||||
|
is set, this preference is ignored.
|
||||||
|
*/
|
||||||
isFatal() { return false; }
|
isFatal() { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +126,7 @@ SQLTesterException.toss = (...args)=>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DbException extends SQLTesterException {
|
class DbException extends SQLTesterException {
|
||||||
constructor(testScript, pDb, rc, closeDb){
|
constructor(testScript, pDb, rc, closeDb=false){
|
||||||
super(testScript, "DB error #"+rc+": "+sqlite3.capi.sqlite3_errmsg(pDb));
|
super(testScript, "DB error #"+rc+": "+sqlite3.capi.sqlite3_errmsg(pDb));
|
||||||
this.name = 'DbException';
|
this.name = 'DbException';
|
||||||
if( closeDb ) sqlite3.capi.sqlite3_close_v2(pDb);
|
if( closeDb ) sqlite3.capi.sqlite3_close_v2(pDb);
|
||||||
@@ -137,12 +156,14 @@ class IncompatibleDirective extends SQLTesterException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! For throwing where an expression is required.
|
||||||
const toss = (errType, ...args)=>{
|
const toss = (errType, ...args)=>{
|
||||||
throw new errType(...args);
|
throw new errType(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
const __utf8Decoder = new TextDecoder();
|
const __utf8Decoder = new TextDecoder();
|
||||||
const __utf8Encoder = new TextEncoder('utf-8');
|
const __utf8Encoder = new TextEncoder('utf-8');
|
||||||
|
//! Workaround for Util.utf8Decode()
|
||||||
const __SAB = ('undefined'===typeof globalThis.SharedArrayBuffer)
|
const __SAB = ('undefined'===typeof globalThis.SharedArrayBuffer)
|
||||||
? function(){} : globalThis.SharedArrayBuffer;
|
? function(){} : globalThis.SharedArrayBuffer;
|
||||||
|
|
||||||
@@ -190,26 +211,41 @@ class Outer {
|
|||||||
#verbosity = 0;
|
#verbosity = 0;
|
||||||
#logger = console.log.bind(console);
|
#logger = console.log.bind(console);
|
||||||
|
|
||||||
constructor(){
|
constructor(func){
|
||||||
|
if(func) this.setFunc(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger(...args){
|
||||||
|
if(args.length){
|
||||||
|
this.#logger = args[0];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return this.#logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
out(...args){
|
out(...args){
|
||||||
if(!this.#lnBuf.length && this.getOutputPrefix ){
|
if( this.getOutputPrefix && !this.#lnBuf.length ){
|
||||||
this.#lnBuf.push(this.getOutputPrefix());
|
this.#lnBuf.push(this.getOutputPrefix());
|
||||||
}
|
}
|
||||||
this.#lnBuf.push(...args);
|
this.#lnBuf.push(...args);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
outln(...args){
|
|
||||||
if(!this.#lnBuf.length && this.getOutputPrefix ){
|
#outlnImpl(vLevel, ...args){
|
||||||
|
if( this.getOutputPrefix && !this.#lnBuf.length ){
|
||||||
this.#lnBuf.push(this.getOutputPrefix());
|
this.#lnBuf.push(this.getOutputPrefix());
|
||||||
}
|
}
|
||||||
this.#lnBuf.push(...args,'\n');
|
this.#lnBuf.push(...args,'\n');
|
||||||
this.#logger(this.#lnBuf.join(''));
|
const msg = this.#lnBuf.join('');
|
||||||
this.#lnBuf.length = 0;
|
this.#lnBuf.length = 0;
|
||||||
|
this.#logger(msg);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outln(...args){
|
||||||
|
return this.#outlnImpl(0,...args);
|
||||||
|
}
|
||||||
|
|
||||||
outputPrefix(){
|
outputPrefix(){
|
||||||
if( 0==arguments.length ){
|
if( 0==arguments.length ){
|
||||||
return (this.getOutputPrefix
|
return (this.getOutputPrefix
|
||||||
@@ -220,9 +256,9 @@ class Outer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verboseN(lvl, argv){
|
verboseN(lvl, args){
|
||||||
if( this.#verbosity>=lvl ){
|
if( this.#verbosity>=lvl ){
|
||||||
this.outln('VERBOSE ',lvl,': ',...argv);
|
this.#outlnImpl(lvl,'VERBOSE ',lvl,': ',...args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verbose1(...args){ return this.verboseN(1,args); }
|
verbose1(...args){ return this.verboseN(1,args); }
|
||||||
@@ -230,13 +266,8 @@ class Outer {
|
|||||||
verbose3(...args){ return this.verboseN(3,args); }
|
verbose3(...args){ return this.verboseN(3,args); }
|
||||||
|
|
||||||
verbosity(){
|
verbosity(){
|
||||||
let rc;
|
const rc = this.#verbosity;
|
||||||
if(arguments.length){
|
if(arguments.length) this.#verbosity = +arguments[0];
|
||||||
rc = this.#verbosity;
|
|
||||||
this.#verbosity = arguments[0];
|
|
||||||
}else{
|
|
||||||
rc = this.#verbosity;
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +292,7 @@ class SQLTester {
|
|||||||
nTestFile: 0,
|
nTestFile: 0,
|
||||||
//! Number of scripts which were aborted
|
//! Number of scripts which were aborted
|
||||||
nAbortedScript: 0,
|
nAbortedScript: 0,
|
||||||
//! Incremented by test case handlers
|
//! Test-case count for to the current TestScript
|
||||||
nTest: 0
|
nTest: 0
|
||||||
});
|
});
|
||||||
#emitColNames = false;
|
#emitColNames = false;
|
||||||
@@ -288,6 +319,24 @@ class SQLTester {
|
|||||||
|
|
||||||
outln(...args){ return this.#outer.outln(...args); }
|
outln(...args){ return this.#outer.outln(...args); }
|
||||||
out(...args){ return this.#outer.out(...args); }
|
out(...args){ return this.#outer.out(...args); }
|
||||||
|
outer(...args){
|
||||||
|
if(args.length){
|
||||||
|
this.#outer = args[0];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return this.#outer;
|
||||||
|
}
|
||||||
|
verbose1(...args){ return this.#outer.verboseN(1,args); }
|
||||||
|
verbose2(...args){ return this.#outer.verboseN(2,args); }
|
||||||
|
verbose3(...args){ return this.#outer.verboseN(3,args); }
|
||||||
|
verbosity(...args){
|
||||||
|
const rc = this.#outer.verbosity(...args);
|
||||||
|
return args.length ? this : rc;
|
||||||
|
}
|
||||||
|
setLogger(func){
|
||||||
|
this.#outer.logger(func);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
incrementTestCounter(){
|
incrementTestCounter(){
|
||||||
++this.metrics.nTotalTest;
|
++this.metrics.nTotalTest;
|
||||||
@@ -339,8 +388,6 @@ class SQLTester {
|
|||||||
return this.#takeBuffer(this.#resultBuffer);
|
return this.#takeBuffer(this.#resultBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
verbosity(...args){ return this.#outer.verbosity(...args); }
|
|
||||||
|
|
||||||
nullValue(){
|
nullValue(){
|
||||||
if( 0==arguments.length ){
|
if( 0==arguments.length ){
|
||||||
return this.#nullView;
|
return this.#nullView;
|
||||||
@@ -427,7 +474,7 @@ class SQLTester {
|
|||||||
pDb = wasm.peekPtr(ppOut);
|
pDb = wasm.peekPtr(ppOut);
|
||||||
});
|
});
|
||||||
if( 0==rc && this.#db.initSql.length > 0){
|
if( 0==rc && this.#db.initSql.length > 0){
|
||||||
//this.#outer.verbose2("RUNNING DB INIT CODE: ",this.#db.initSql.toString());
|
this.#outer.verbose2("RUNNING DB INIT CODE: ",this.#db.initSql.toString());
|
||||||
rc = this.execSql(pDb, false, ResultBufferMode.NONE,
|
rc = this.execSql(pDb, false, ResultBufferMode.NONE,
|
||||||
null, this.#db.initSql.join(''));
|
null, this.#db.initSql.join(''));
|
||||||
}
|
}
|
||||||
@@ -464,6 +511,8 @@ class SQLTester {
|
|||||||
runTests(){
|
runTests(){
|
||||||
const tStart = (new Date()).getTime();
|
const tStart = (new Date()).getTime();
|
||||||
let isVerbose = this.verbosity();
|
let isVerbose = this.verbosity();
|
||||||
|
this.metrics.nAbortedScript = 0;
|
||||||
|
this.metrics.nTotalTest = 0;
|
||||||
for(const ts of this.#aScripts){
|
for(const ts of this.#aScripts){
|
||||||
this.reset();
|
this.reset();
|
||||||
++this.metrics.nTestFile;
|
++this.metrics.nTestFile;
|
||||||
@@ -471,11 +520,6 @@ class SQLTester {
|
|||||||
const timeStart = (new Date()).getTime();
|
const timeStart = (new Date()).getTime();
|
||||||
let msgTail = '';
|
let msgTail = '';
|
||||||
try{
|
try{
|
||||||
if( isVerbose ){
|
|
||||||
this.#outer.verbose1("Running ",ts.filename());
|
|
||||||
}else{
|
|
||||||
msgTail = ' '+ts.filename();
|
|
||||||
}
|
|
||||||
ts.run(this);
|
ts.run(this);
|
||||||
}catch(e){
|
}catch(e){
|
||||||
if(e instanceof SQLTesterException){
|
if(e instanceof SQLTesterException){
|
||||||
@@ -483,21 +527,35 @@ class SQLTester {
|
|||||||
this.outln("🔥EXCEPTION: ",e);
|
this.outln("🔥EXCEPTION: ",e);
|
||||||
++this.metrics.nAbortedScript;
|
++this.metrics.nAbortedScript;
|
||||||
if( this.#keepGoing ){
|
if( this.#keepGoing ){
|
||||||
this.outln("Continuing anyway becaure of the keep-going option.");
|
this.outln("Continuing anyway because of the keep-going option.");
|
||||||
|
}else if( e.isFatal() ){
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
else if( e.isFatal() ) throw e;
|
|
||||||
}else{
|
}else{
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}finally{
|
}finally{
|
||||||
const timeEnd = (new Date()).getTime();
|
const timeEnd = (new Date()).getTime();
|
||||||
this.outln("🏁", (threw ? "❌" : "✅"), " ", this.metrics.nTest,
|
this.out("🏁", (threw ? "❌" : "✅"), " ",
|
||||||
" test(s) in ", (timeEnd-timeStart),"ms.",msgTail);
|
this.metrics.nTest, " test(s) in ",
|
||||||
|
(timeEnd-timeStart),"ms. ");
|
||||||
|
const mod = ts.moduleName();
|
||||||
|
if( mod ){
|
||||||
|
this.out( "[",mod,"] " );
|
||||||
|
}
|
||||||
|
this.outln(ts.filename());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const tEnd = (new Date()).getTime();
|
const tEnd = (new Date()).getTime();
|
||||||
this.outln("Total run-time: ",(tEnd-tStart),"ms");
|
|
||||||
Util.unlink(this.#db.initialDbName);
|
Util.unlink(this.#db.initialDbName);
|
||||||
|
this.outln("Took ",(tEnd-tStart),"ms. test count = ",
|
||||||
|
this.metrics.nTotalTest,", script count = ",
|
||||||
|
this.#aScripts.length,(
|
||||||
|
this.metrics.nAbortedScript
|
||||||
|
? ", aborted scripts = "+this.metrics.nAbortedScript
|
||||||
|
: ""
|
||||||
|
)
|
||||||
|
);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,10 +569,6 @@ class SQLTester {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Returns v or some escaped form of v, as defined in the tester's
|
|
||||||
spec doc.
|
|
||||||
*/
|
|
||||||
#escapeSqlValue(v){
|
#escapeSqlValue(v){
|
||||||
if( !v ) return "{}";
|
if( !v ) return "{}";
|
||||||
if( !Rx.special.test(v) ){
|
if( !Rx.special.test(v) ){
|
||||||
@@ -735,6 +789,11 @@ class TestScript {
|
|||||||
this.#cursor.src = content;
|
this.#cursor.src = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moduleName(){
|
||||||
|
return (0==arguments.length)
|
||||||
|
? this.#moduleName : (this.#moduleName = arguments[0]);
|
||||||
|
}
|
||||||
|
|
||||||
testCaseName(){
|
testCaseName(){
|
||||||
return (0==arguments.length)
|
return (0==arguments.length)
|
||||||
? this.#testCaseName : (this.#testCaseName = arguments[0]);
|
? this.#testCaseName : (this.#testCaseName = arguments[0]);
|
||||||
@@ -760,6 +819,14 @@ class TestScript {
|
|||||||
throw new TestScriptFailed(this,...args);
|
throw new TestScriptFailed(this,...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verbose1(...args){ return this.#outer.verboseN(1,args); }
|
||||||
|
verbose2(...args){ return this.#outer.verboseN(2,args); }
|
||||||
|
verbose3(...args){ return this.#outer.verboseN(3,args); }
|
||||||
|
verbosity(...args){
|
||||||
|
const rc = this.#outer.verbosity(...args);
|
||||||
|
return args.length ? this : rc;
|
||||||
|
}
|
||||||
|
|
||||||
#checkForDirective(tester,line){
|
#checkForDirective(tester,line){
|
||||||
if(line.startsWith("#")){
|
if(line.startsWith("#")){
|
||||||
throw new IncompatibleDirective(this, "C-preprocessor input: "+line);
|
throw new IncompatibleDirective(this, "C-preprocessor input: "+line);
|
||||||
@@ -818,7 +885,8 @@ class TestScript {
|
|||||||
|
|
||||||
run(tester){
|
run(tester){
|
||||||
this.reset();
|
this.reset();
|
||||||
this.#outer.verbosity(tester.verbosity());
|
this.#outer.verbosity( tester.verbosity() );
|
||||||
|
this.#outer.logger( tester.outer().logger() );
|
||||||
let line, directive, argv = [];
|
let line, directive, argv = [];
|
||||||
while( null != (line = this.getLine()) ){
|
while( null != (line = this.getLine()) ){
|
||||||
this.verbose3("run() input line: ",line);
|
this.verbose3("run() input line: ",line);
|
||||||
@@ -942,11 +1010,6 @@ class TestScript {
|
|||||||
cur.lineNo = cur.putbackLineNo;
|
cur.lineNo = cur.putbackLineNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose1(...args){ return this.#outer.verboseN(1,args); }
|
|
||||||
verbose2(...args){ return this.#outer.verboseN(2,args); }
|
|
||||||
verbose3(...args){ return this.#outer.verboseN(3,args); }
|
|
||||||
verbosity(...args){ return this.#outer.verbosity(...args); }
|
|
||||||
|
|
||||||
}/*TestScript*/;
|
}/*TestScript*/;
|
||||||
|
|
||||||
//! --close command
|
//! --close command
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
** This file contains a test application for SQLTester.js.
|
** This file contains a test application for SQLTester.js.
|
||||||
*/
|
*/
|
||||||
import {default as ns} from './SQLTester.mjs';
|
import {default as ns} from './SQLTester.mjs';
|
||||||
import {default as tests} from './test-list.mjs';
|
import {default as allTests} from './test-list.mjs';
|
||||||
|
|
||||||
globalThis.sqlite3 = ns.sqlite3;
|
globalThis.sqlite3 = ns.sqlite3;
|
||||||
const log = function f(...args){
|
const log = function f(...args){
|
||||||
@@ -33,8 +33,6 @@ const affirm = function(expr, msg){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log("SQLTester is ready.");
|
|
||||||
|
|
||||||
let ts = new ns.TestScript('/foo.test',`
|
let ts = new ns.TestScript('/foo.test',`
|
||||||
/*
|
/*
|
||||||
** This is a comment. There are many like it but this one is mine.
|
** This is a comment. There are many like it but this one is mine.
|
||||||
@@ -56,10 +54,10 @@ let ts = new ns.TestScript('/foo.test',`
|
|||||||
--oom
|
--oom
|
||||||
--db 0
|
--db 0
|
||||||
--new my.db
|
--new my.db
|
||||||
--null zilchy
|
--null zilch
|
||||||
--testcase 1.0
|
--testcase 1.0
|
||||||
SELECT 1, null;
|
SELECT 1, null;
|
||||||
--result 1 zilchy
|
--result 1 zilch
|
||||||
--glob *zil*
|
--glob *zil*
|
||||||
--notglob *ZIL*
|
--notglob *ZIL*
|
||||||
SELECT 1, 2;
|
SELECT 1, 2;
|
||||||
@@ -94,29 +92,54 @@ SELECT json_array(1,2,3)
|
|||||||
--print Until next time
|
--print Until next time
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const sqt = new ns.SQLTester();
|
const sqt = new ns.SQLTester()
|
||||||
try{
|
.setLogger(console.log.bind(console))
|
||||||
|
.verbosity(1)
|
||||||
|
.addTestScript(ts);
|
||||||
|
|
||||||
|
const runTests = function(){
|
||||||
|
try{
|
||||||
if( 0 ){
|
if( 0 ){
|
||||||
affirm( !sqt.getCurrentDb(), 'sqt.getCurrentDb()' );
|
affirm( !sqt.getCurrentDb(), 'sqt.getCurrentDb()' );
|
||||||
sqt.openDb('/foo.db', true);
|
sqt.openDb('/foo.db', true);
|
||||||
affirm( !!sqt.getCurrentDb(),'sqt.getCurrentDb()' );
|
affirm( !!sqt.getCurrentDb(),'sqt.getCurrentDb()' );
|
||||||
sqt.verbosity(0);
|
|
||||||
if(false){
|
|
||||||
affirm( 'zilch' !== sqt.nullValue() );
|
affirm( 'zilch' !== sqt.nullValue() );
|
||||||
ts.run(sqt);
|
ts.run(sqt);
|
||||||
affirm( 'zilch' === sqt.nullValue() );
|
affirm( 'zilch' === sqt.nullValue() );
|
||||||
}
|
|
||||||
sqt.addTestScript(ts);
|
sqt.addTestScript(ts);
|
||||||
sqt.runTests();
|
sqt.runTests();
|
||||||
}else{
|
}else{
|
||||||
for(const t of tests){
|
for(const t of allTests){
|
||||||
sqt.addTestScript( new ns.TestScript(t) );
|
sqt.addTestScript( new ns.TestScript(t) );
|
||||||
}
|
}
|
||||||
tests.length = 0;
|
allTests.length = 0;
|
||||||
sqt.verbosity(0);
|
|
||||||
sqt.runTests();
|
sqt.runTests();
|
||||||
}
|
}
|
||||||
}finally{
|
}finally{
|
||||||
log( "Metrics:", sqt.metrics );
|
//log( "Metrics:", sqt.metrics );
|
||||||
sqt.reset();
|
sqt.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if( globalThis.WorkerGlobalScope ){
|
||||||
|
const wPost = (type,payload)=>globalThis.postMessage({type, payload});
|
||||||
|
globalThis.onmessage = function({data}){
|
||||||
|
switch(data.type){
|
||||||
|
case 'run-tests':{
|
||||||
|
try{ runTests(); }
|
||||||
|
finally{ wPost('tests-end'); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log("unhandled onmessage: ",data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sqt.setLogger((msg)=>{
|
||||||
|
wPost('stdout', {message: msg});
|
||||||
|
});
|
||||||
|
wPost('is-ready');
|
||||||
|
//globalThis.onmessage({data:{type:'run-tests'}});
|
||||||
|
}else{
|
||||||
|
runTests();
|
||||||
}
|
}
|
||||||
|
@@ -8,19 +8,108 @@
|
|||||||
<link rel="stylesheet" href="../common/testing.css"/>
|
<link rel="stylesheet" href="../common/testing.css"/>
|
||||||
<title>SQLTester</title>
|
<title>SQLTester</title>
|
||||||
</head>
|
</head>
|
||||||
|
<style>
|
||||||
|
fieldset {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
fieldset > :not(.legend) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<p>SQLTester App.
|
<h1>SQLTester for JS/WASM</h1>
|
||||||
|
<p>This app reads in a build-time-defined set of SQLTester test
|
||||||
|
scripts and runs them through the test suite.
|
||||||
</p>
|
</p>
|
||||||
<p>All stuff on this page happens in the dev console.</p>
|
<fieldset>
|
||||||
<hr>
|
<legend>Options</legend>
|
||||||
|
<span class='input-wrapper'>
|
||||||
|
<input type='checkbox' id='cb-log-reverse' checked>
|
||||||
|
<label for='cb-log-reverse'>Reverse log order?</label>
|
||||||
|
</span>
|
||||||
|
<input type='button' id='btn-run-tests' value='Run tests'/>
|
||||||
|
</fieldset>
|
||||||
<div id='test-output'></div>
|
<div id='test-output'></div>
|
||||||
<!--script src='SQLTester.run.mjs' type='module'></script-->
|
<!--script src='SQLTester.run.mjs' type='module'></script-->
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(async function(){
|
||||||
// Noting that Firefox can't do this yet.
|
|
||||||
const W = new Worker('SQLTester.run.mjs',{
|
const W = new Worker('SQLTester.run.mjs',{
|
||||||
type: 'module'
|
type: 'module'
|
||||||
});
|
});
|
||||||
|
const wPost = (type,payload)=>W.postMessage({type,payload});
|
||||||
|
const mapToString = (v)=>{
|
||||||
|
switch(typeof v){
|
||||||
|
case 'string': return v;
|
||||||
|
case 'number': case 'boolean':
|
||||||
|
case 'undefined': case 'bigint':
|
||||||
|
return ''+v;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if(null===v) return 'null';
|
||||||
|
if(v instanceof Error){
|
||||||
|
v = {
|
||||||
|
message: v.message,
|
||||||
|
stack: v.stack,
|
||||||
|
errorClass: v.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return JSON.stringify(v,undefined,2);
|
||||||
|
};
|
||||||
|
const normalizeArgs = (args)=>args.map(mapToString);
|
||||||
|
const logTarget = document.querySelector('#test-output');
|
||||||
|
const logClass = function(cssClass,...args){
|
||||||
|
const ln = document.createElement('div');
|
||||||
|
if(cssClass){
|
||||||
|
for(const c of (Array.isArray(cssClass) ? cssClass : [cssClass])){
|
||||||
|
ln.classList.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
|
||||||
|
logTarget.append(ln);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
const cbReverse = document.querySelector('#cb-log-reverse');
|
||||||
|
const cbReverseKey = 'SQLTester:cb-log-reverse';
|
||||||
|
const cbReverseIt = ()=>{
|
||||||
|
logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
|
||||||
|
};
|
||||||
|
cbReverse.addEventListener('change', cbReverseIt, true);
|
||||||
|
cbReverseIt();
|
||||||
|
}
|
||||||
|
|
||||||
|
const btnRun = document.querySelector('#btn-run-tests');
|
||||||
|
const runTests = ()=>{
|
||||||
|
btnRun.setAttribute('disabled','disabled');
|
||||||
|
wPost('run-tests');
|
||||||
|
logTarget.innerText = 'Running tests...';
|
||||||
|
}
|
||||||
|
btnRun.addEventListener('click', runTests);
|
||||||
|
const log2 = function f(...args){
|
||||||
|
logClass('', ...args);
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
const log = function f(...args){
|
||||||
|
logClass('','index.html:',...args);
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
W.onmessage = function({data}){
|
||||||
|
switch(data.type){
|
||||||
|
case 'stdout': log2(data.payload.message); break;
|
||||||
|
case 'tests-end': btnRun.removeAttribute('disabled'); break;
|
||||||
|
case 'is-ready':
|
||||||
|
log("SQLTester.run.mjs is ready.");
|
||||||
|
runTests(); break;
|
||||||
|
default:
|
||||||
|
log("unhandled onmessage",data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//runTests()
|
||||||
|
/* Inexplicably, */
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sa\smechanism\swith\swhich\sto\simport\sexternal\sSQLTester\sscripts\sinto\sthe\sJS\stesting\stool.
|
C Add\sa\sUI,\sof\ssorts,\sto\sthe\sJS\sSQLTester.
|
||||||
D 2023-08-30T00:22:54.642
|
D 2023-08-30T11:54:43.323
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@@ -548,10 +548,10 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
|
|||||||
F ext/wasm/GNUmakefile 0e362f3fc04eab6628cbe4f1e35f4ab4a200881f6b5f753b27fb45eabeddd9d2
|
F ext/wasm/GNUmakefile 0e362f3fc04eab6628cbe4f1e35f4ab4a200881f6b5f753b27fb45eabeddd9d2
|
||||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||||
F ext/wasm/SQLTester/GNUmakefile ba0430646d75a832d1647d6d204c999112d831f5e85d3ed99d8f663fea20fe19
|
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||||
F ext/wasm/SQLTester/SQLTester.mjs 378868be0fcbbb92456aea10e3056f88b042e106b2c348aa51060e93726f6e10
|
F ext/wasm/SQLTester/SQLTester.mjs 4a8fc2194a67180772830f503129c93fe44887b9573f50a4e24868b4bbc817f4
|
||||||
F ext/wasm/SQLTester/SQLTester.run.mjs 2695490e2092af0c6a9d1e4128edf830648687a54ec1f0ecd16bd1be083f3938
|
F ext/wasm/SQLTester/SQLTester.run.mjs a50a1f9314d22d68b62a2f21d8913de163fce1fa420229711d6749c2b4fff9d0
|
||||||
F ext/wasm/SQLTester/index.html 317636557257608b103fa740c07f2d440d57b924ef2072e59c1372d4a4004c06
|
F ext/wasm/SQLTester/index.html e5f18af71749d81d86e4649d8c6efc9b78361738cb8e5c5014ba0dd3dc3de6ac
|
||||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
||||||
@@ -2113,8 +2113,8 @@ 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 7cef4a8300826adbdcb3b205e134a4272b12b4aa7dbee97731ac12282a4a9f06
|
P bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624
|
||||||
R 018b862c43a96a36d2df3223b087af85
|
R 8240e3c6439a4fca46c74a72b36ea777
|
||||||
U stephan
|
U stephan
|
||||||
Z 18f8112180ee272e1f7e50a87a0ce726
|
Z cef4bceac8cb673301c00562148f0e5f
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@@ -1 +1 @@
|
|||||||
bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624
|
249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c
|
Reference in New Issue
Block a user