]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a mechanism with which to import external SQLTester scripts into the JS testing...
authorstephan <stephan@noemail.net>
Wed, 30 Aug 2023 00:22:54 +0000 (00:22 +0000)
committerstephan <stephan@noemail.net>
Wed, 30 Aug 2023 00:22:54 +0000 (00:22 +0000)
FossilOrigin-Name: bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624

ext/wasm/SQLTester/GNUmakefile [new file with mode: 0644]
ext/wasm/SQLTester/SQLTester.mjs
ext/wasm/SQLTester/SQLTester.run.mjs
ext/wasm/SQLTester/index.html
ext/wasm/SQLTester/touint8array.c [new file with mode: 0644]
manifest
manifest.uuid

diff --git a/ext/wasm/SQLTester/GNUmakefile b/ext/wasm/SQLTester/GNUmakefile
new file mode 100644 (file)
index 0000000..6338808
--- /dev/null
@@ -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)
index aa02d7a5ec597775f6f66e133b2bc2d60eac5523..0ec82ca464f5978477339bdf85f42e0ed9056fdb 100644 (file)
@@ -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);
     }
   }
index e58db93450720c279f93988b2ee7eaabf7ef16b1..e6730253b6256919afa50d55dbe179b4666fbcd2 100644 (file)
@@ -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 );
-
index e782f1367d4866136b81b335e3e3233c7c1cbc41..8ae3e27a36d1b351184f7a2908e2c1145d06c704 100644 (file)
     <p>All stuff on this page happens in the dev console.</p>
     <hr>
     <div id='test-output'></div>
-    <script src='SQLTester.run.mjs' type='module'></script>
-    <!--script>
+    <!--script src='SQLTester.run.mjs' type='module'></script-->
+    <script>
       (function(){
-          const W = new Worker('scratchpad-wasmfs.mjs',{
-              type: 'module'
-          });
+        // Noting that Firefox can't do this yet.
+        const W = new Worker('SQLTester.run.mjs',{
+          type: 'module'
+        });
       })();
-    </script-->
+    </script>
   </body>
 </html>
diff --git a/ext/wasm/SQLTester/touint8array.c b/ext/wasm/SQLTester/touint8array.c
new file mode 100644 (file)
index 0000000..b03ad42
--- /dev/null
@@ -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 <stdio.h>
+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;
+}
index c8e5581fdaa0c91e51863454b02e16ad1d03d1c3..7088c67f0588746e5bfd71a45e1fb8fb32a1ca7a 100644 (file)
--- 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.
index cb91036e81445fb0328df84c790aad6e4fa46afc..7168a7b8adc518b0851ae5ff9dfbdae1cc33832c 100644 (file)
@@ -1 +1 @@
-7cef4a8300826adbdcb3b205e134a4272b12b4aa7dbee97731ac12282a4a9f06
\ No newline at end of file
+bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624
\ No newline at end of file