Add a JS implementation of Java's SQLTester.
FossilOrigin-Name: b530792a514d95c4e8f93cf2170d9fc4de367055fa1704fc171551c946024fa9
This commit is contained in:
commit
24c32c2e39
@ -181,7 +181,7 @@ public class SQLTester {
|
||||
private int nTestFile = 0;
|
||||
//! Number of scripts which were aborted.
|
||||
private int nAbortedScript = 0;
|
||||
//! Per-script test counter.
|
||||
//! Incremented by test case handlers
|
||||
private int nTest = 0;
|
||||
//! True to enable column name output from execSql()
|
||||
private boolean emitColNames;
|
||||
@ -270,7 +270,6 @@ public class SQLTester {
|
||||
final long timeEnd = System.currentTimeMillis();
|
||||
outln("🏁",(threw ? "❌" : "✅")," ",nTest," test(s) in ",
|
||||
(timeEnd-timeStart),"ms.");
|
||||
//ts.getFilename());
|
||||
}
|
||||
}
|
||||
final long tEnd = System.currentTimeMillis();
|
||||
@ -336,7 +335,9 @@ public class SQLTester {
|
||||
}
|
||||
|
||||
sqlite3 setCurrentDb(int n) throws Exception{
|
||||
return affirmDbId(n).aDb[n];
|
||||
affirmDbId(n);
|
||||
iCurrentDb = n;
|
||||
return this.aDb[n];
|
||||
}
|
||||
|
||||
sqlite3 getCurrentDb(){ return aDb[iCurrentDb]; }
|
||||
@ -399,7 +400,7 @@ public class SQLTester {
|
||||
nullView = "nil";
|
||||
emitColNames = false;
|
||||
iCurrentDb = 0;
|
||||
dbInitSql.append("SELECT 1;");
|
||||
//dbInitSql.append("SELECT 1;");
|
||||
}
|
||||
|
||||
void setNullValue(String v){nullView = v;}
|
||||
@ -580,6 +581,10 @@ public class SQLTester {
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
sqlite3_reset(stmt
|
||||
/* In order to trigger an exception in the
|
||||
INSERT...RETURNING locking scenario:
|
||||
https://sqlite.org/forum/forumpost/36f7a2e7494897df */);
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
if( 0!=rc && throwOnError ){
|
||||
@ -924,8 +929,8 @@ class RunCommand extends Command {
|
||||
final sqlite3 db = (1==argv.length)
|
||||
? t.getCurrentDb() : t.getDbById( Integer.parseInt(argv[1]) );
|
||||
final String sql = t.takeInputBuffer();
|
||||
int rc = t.execSql(db, false, ResultBufferMode.NONE,
|
||||
ResultRowMode.ONELINE, sql);
|
||||
final int rc = t.execSql(db, false, ResultBufferMode.NONE,
|
||||
ResultRowMode.ONELINE, sql);
|
||||
if( 0!=rc && t.isVerbose() ){
|
||||
String msg = sqlite3_errmsg(db);
|
||||
ts.verbose1(argv[0]," non-fatal command error #",rc,": ",
|
||||
@ -948,8 +953,7 @@ class TableResultCommand extends Command {
|
||||
if( !body.endsWith("\n--end") ){
|
||||
ts.toss(argv[0], " must be terminated with --end.");
|
||||
}else{
|
||||
int n = body.length();
|
||||
body = body.substring(0, n-6);
|
||||
body = body.substring(0, body.length()-6);
|
||||
}
|
||||
final String[] globs = body.split("\\s*\\n\\s*");
|
||||
if( globs.length < 1 ){
|
||||
@ -1238,14 +1242,15 @@ class TestScript {
|
||||
final int oldPB = cur.putbackPos;
|
||||
final int oldPBL = cur.putbackLineNo;
|
||||
final int oldLine = cur.lineNo;
|
||||
final String rc = getLine();
|
||||
cur.peekedPos = cur.pos;
|
||||
cur.peekedLineNo = cur.lineNo;
|
||||
cur.pos = oldPos;
|
||||
cur.lineNo = oldLine;
|
||||
cur.putbackPos = oldPB;
|
||||
cur.putbackLineNo = oldPBL;
|
||||
return rc;
|
||||
try{ return getLine(); }
|
||||
finally{
|
||||
cur.peekedPos = cur.pos;
|
||||
cur.peekedLineNo = cur.lineNo;
|
||||
cur.pos = oldPos;
|
||||
cur.lineNo = oldLine;
|
||||
cur.putbackPos = oldPB;
|
||||
cur.putbackLineNo = oldPBL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1372,11 +1377,10 @@ class TestScript {
|
||||
String line;
|
||||
while( (null != (line = peekLine())) ){
|
||||
checkForDirective(tester, line);
|
||||
if( !isCommandLine(line, true) ){
|
||||
if( isCommandLine(line, true) ) break;
|
||||
else {
|
||||
sb.append(line).append("\n");
|
||||
consumePeeked();
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
line = sb.toString();
|
||||
|
55
ext/wasm/SQLTester/GNUmakefile
Normal file
55
ext/wasm/SQLTester/GNUmakefile
Normal file
@ -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 $< > $@
|
||||
CLEAN_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)
|
1296
ext/wasm/SQLTester/SQLTester.mjs
Normal file
1296
ext/wasm/SQLTester/SQLTester.mjs
Normal file
File diff suppressed because it is too large
Load Diff
145
ext/wasm/SQLTester/SQLTester.run.mjs
Normal file
145
ext/wasm/SQLTester/SQLTester.run.mjs
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
** 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 allTests} from './test-list.mjs';
|
||||
|
||||
globalThis.sqlite3 = ns.sqlite3;
|
||||
const log = function f(...args){
|
||||
console.log('SQLTester.run:',...args);
|
||||
return f;
|
||||
};
|
||||
|
||||
const out = function f(...args){ return f.outer.out(...args) };
|
||||
out.outer = new ns.Outer();
|
||||
out.outer.getOutputPrefix = ()=>'SQLTester.run: ';
|
||||
const outln = (...args)=>{ return out.outer.outln(...args) };
|
||||
|
||||
const affirm = function(expr, msg){
|
||||
if( !expr ){
|
||||
throw new Error(arguments[1]
|
||||
? ("Assertion failed: "+arguments[1])
|
||||
: "Assertion failed");
|
||||
}
|
||||
}
|
||||
|
||||
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-0
|
||||
** xMIXED_MODULE_NAME: mixed-module
|
||||
** xMODULE_NAME: module-name
|
||||
** xREQUIRED_PROPERTIES: small fast reliable
|
||||
** xREQUIRED_PROPERTIES: RECURSIVE_TRIGGERS
|
||||
** xREQUIRED_PROPERTIES: TEMPSTORE_MEM TEMPSTORE_FILE
|
||||
**
|
||||
*/
|
||||
/* --verbosity 3 */
|
||||
/* ---must-fail */
|
||||
/* # must fail */
|
||||
/* --verbosity 0 */
|
||||
--print Hello, world.
|
||||
--close all
|
||||
--oom
|
||||
--db 0
|
||||
--new my.db
|
||||
--null zilch
|
||||
--testcase 1.0
|
||||
SELECT 1, null;
|
||||
--result 1 zilch
|
||||
--glob *zil*
|
||||
--notglob *ZIL*
|
||||
SELECT 1, 2;
|
||||
intentional error;
|
||||
--run
|
||||
--testcase json-1
|
||||
SELECT json_array(1,2,3)
|
||||
--json [1,2,3]
|
||||
--testcase tableresult-1
|
||||
select 1, 'a';
|
||||
select 2, 'b';
|
||||
--tableresult
|
||||
# [a-z]
|
||||
2 b
|
||||
--end
|
||||
--testcase json-block-1
|
||||
select json_array(1,2,3);
|
||||
select json_object('a',1,'b',2);
|
||||
--json-block
|
||||
[1,2,3]
|
||||
{"a":1,"b":2}
|
||||
--end
|
||||
--testcase col-names-on
|
||||
--column-names 1
|
||||
select 1 as 'a', 2 as 'b';
|
||||
--result a 1 b 2
|
||||
--testcase col-names-off
|
||||
--column-names 0
|
||||
select 1 as 'a', 2 as 'b';
|
||||
--result 1 2
|
||||
--close
|
||||
--print Until next time
|
||||
`);
|
||||
|
||||
const sqt = new ns.SQLTester()
|
||||
.setLogger(console.log.bind(console))
|
||||
.verbosity(1)
|
||||
.addTestScript(ts);
|
||||
|
||||
const runTests = function(){
|
||||
try{
|
||||
if( 0 ){
|
||||
affirm( !sqt.getCurrentDb(), 'sqt.getCurrentDb()' );
|
||||
sqt.openDb('/foo.db', true);
|
||||
affirm( !!sqt.getCurrentDb(),'sqt.getCurrentDb()' );
|
||||
affirm( 'zilch' !== sqt.nullValue() );
|
||||
ts.run(sqt);
|
||||
affirm( 'zilch' === sqt.nullValue() );
|
||||
sqt.addTestScript(ts);
|
||||
sqt.runTests();
|
||||
}else{
|
||||
for(const t of allTests){
|
||||
sqt.addTestScript( new ns.TestScript(t) );
|
||||
}
|
||||
allTests.length = 0;
|
||||
sqt.runTests();
|
||||
}
|
||||
}finally{
|
||||
//log( "Metrics:", sqt.metrics );
|
||||
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();
|
||||
}
|
116
ext/wasm/SQLTester/index.html
Normal file
116
ext/wasm/SQLTester/index.html
Normal file
@ -0,0 +1,116 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||
<!--link rel="stylesheet" href="../common/emscripten.css"/-->
|
||||
<link rel="stylesheet" href="../common/testing.css"/>
|
||||
<title>SQLTester</title>
|
||||
</head>
|
||||
<style>
|
||||
fieldset {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-right: 1em;
|
||||
}
|
||||
fieldset > :not(.legend) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-right: 1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<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>
|
||||
<fieldset>
|
||||
<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>
|
||||
<!--script src='SQLTester.run.mjs' type='module'></script-->
|
||||
<script>
|
||||
(async function(){
|
||||
const W = new Worker('SQLTester.run.mjs',{
|
||||
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>
|
||||
</body>
|
||||
</html>
|
29
ext/wasm/SQLTester/touint8array.c
Normal file
29
ext/wasm/SQLTester/touint8array.c
Normal file
@ -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;
|
||||
}
|
@ -1135,7 +1135,23 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
return 1===n
|
||||
? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
|
||||
: wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
|
||||
},
|
||||
|
||||
/**
|
||||
Records the current pstack position, calls the given function,
|
||||
passing it the sqlite3 object, then restores the pstack
|
||||
regardless of whether the function throws. Returns the result
|
||||
of the call or propagates an exception on error.
|
||||
|
||||
Added in 3.44.
|
||||
*/
|
||||
call: function(f){
|
||||
const stackPos = wasm.pstack.pointer;
|
||||
try{ return f(sqlite3) } finally{
|
||||
wasm.pstack.restore(stackPos);
|
||||
}
|
||||
}
|
||||
|
||||
})/*wasm.pstack*/;
|
||||
Object.defineProperties(wasm.pstack, {
|
||||
/**
|
||||
@ -1543,6 +1559,26 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Converts SQL input from a variety of convenient formats
|
||||
to plain strings.
|
||||
|
||||
If v is a string, it is returned as-is. If it is-a Array, its
|
||||
join("") result is returned. If is is a Uint8Array, Int8Array,
|
||||
or ArrayBuffer, it is assumed to hold UTF-8-encoded text and is
|
||||
decoded to a string. If it looks like a WASM pointer,
|
||||
wasm.cstrToJs(sql) is returned. Else undefined is returned.
|
||||
|
||||
Added in 3.44
|
||||
*/
|
||||
capi.sqlite3_js_sql_to_string = (sql)=>{
|
||||
if('string' === typeof sql){
|
||||
return sql;
|
||||
}
|
||||
const x = flexibleString(v);
|
||||
return x===v ? undefined : x;
|
||||
}
|
||||
|
||||
if( util.isUIThread() ){
|
||||
/* Features specific to the main window thread... */
|
||||
|
||||
|
@ -1801,6 +1801,118 @@ char * sqlite3_wasm_test_str_hello(int fail){
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
** For testing using SQLTester scripts.
|
||||
**
|
||||
** Return non-zero if string z matches glob pattern zGlob and zero if the
|
||||
** pattern does not match.
|
||||
**
|
||||
** To repeat:
|
||||
**
|
||||
** zero == no match
|
||||
** non-zero == match
|
||||
**
|
||||
** Globbing rules:
|
||||
**
|
||||
** '*' Matches any sequence of zero or more characters.
|
||||
**
|
||||
** '?' Matches exactly one character.
|
||||
**
|
||||
** [...] Matches one character from the enclosed list of
|
||||
** characters.
|
||||
**
|
||||
** [^...] Matches one character not in the enclosed list.
|
||||
**
|
||||
** '#' Matches any sequence of one or more digits with an
|
||||
** optional + or - sign in front, or a hexadecimal
|
||||
** literal of the form 0x...
|
||||
*/
|
||||
static int sqlite3_wasm_SQLTester_strnotglob(const char *zGlob, const char *z){
|
||||
int c, c2;
|
||||
int invert;
|
||||
int seen;
|
||||
typedef int (*recurse_f)(const char *,const char *);
|
||||
static const recurse_f recurse = sqlite3_wasm_SQLTester_strnotglob;
|
||||
|
||||
while( (c = (*(zGlob++)))!=0 ){
|
||||
if( c=='*' ){
|
||||
while( (c=(*(zGlob++))) == '*' || c=='?' ){
|
||||
if( c=='?' && (*(z++))==0 ) return 0;
|
||||
}
|
||||
if( c==0 ){
|
||||
return 1;
|
||||
}else if( c=='[' ){
|
||||
while( *z && recurse(zGlob-1,z)==0 ){
|
||||
z++;
|
||||
}
|
||||
return (*z)!=0;
|
||||
}
|
||||
while( (c2 = (*(z++)))!=0 ){
|
||||
while( c2!=c ){
|
||||
c2 = *(z++);
|
||||
if( c2==0 ) return 0;
|
||||
}
|
||||
if( recurse(zGlob,z) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}else if( c=='?' ){
|
||||
if( (*(z++))==0 ) return 0;
|
||||
}else if( c=='[' ){
|
||||
int prior_c = 0;
|
||||
seen = 0;
|
||||
invert = 0;
|
||||
c = *(z++);
|
||||
if( c==0 ) return 0;
|
||||
c2 = *(zGlob++);
|
||||
if( c2=='^' ){
|
||||
invert = 1;
|
||||
c2 = *(zGlob++);
|
||||
}
|
||||
if( c2==']' ){
|
||||
if( c==']' ) seen = 1;
|
||||
c2 = *(zGlob++);
|
||||
}
|
||||
while( c2 && c2!=']' ){
|
||||
if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
|
||||
c2 = *(zGlob++);
|
||||
if( c>=prior_c && c<=c2 ) seen = 1;
|
||||
prior_c = 0;
|
||||
}else{
|
||||
if( c==c2 ){
|
||||
seen = 1;
|
||||
}
|
||||
prior_c = c2;
|
||||
}
|
||||
c2 = *(zGlob++);
|
||||
}
|
||||
if( c2==0 || (seen ^ invert)==0 ) return 0;
|
||||
}else if( c=='#' ){
|
||||
if( z[0]=='0'
|
||||
&& (z[1]=='x' || z[1]=='X')
|
||||
&& sqlite3Isxdigit(z[2])
|
||||
){
|
||||
z += 3;
|
||||
while( sqlite3Isxdigit(z[0]) ){ z++; }
|
||||
}else{
|
||||
if( (z[0]=='-' || z[0]=='+') && sqlite3Isdigit(z[1]) ) z++;
|
||||
if( !sqlite3Isdigit(z[0]) ) return 0;
|
||||
z++;
|
||||
while( sqlite3Isdigit(z[0]) ){ z++; }
|
||||
}
|
||||
}else{
|
||||
if( c!=(*(z++)) ) return 0;
|
||||
}
|
||||
}
|
||||
return *z==0;
|
||||
}
|
||||
|
||||
SQLITE_WASM_EXPORT
|
||||
int sqlite3_wasm_SQLTester_strglob(const char *zGlob, const char *z){
|
||||
return !sqlite3_wasm_SQLTester_strnotglob(zGlob, z);
|
||||
}
|
||||
|
||||
|
||||
#endif /* SQLITE_WASM_TESTS */
|
||||
|
||||
#undef SQLITE_WASM_EXPORT
|
||||
|
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
||||
C New\sconversion\sletters\sadded\sto\sstrftime():\s%e,\s%k,\s%I,\s%l,\s%R,\s%P,\s%p,\s%T,\s%u.
|
||||
D 2023-08-29T18:28:08.008
|
||||
C Add\sa\sJS\simplementation\sof\sJava's\sSQLTester.
|
||||
D 2023-08-30T13:07:35.058
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -283,7 +283,7 @@ F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c38
|
||||
F ext/jni/src/org/sqlite/jni/sqlite3_context.java 66ca95ce904044263a4aff684abe262d56f73e6b06bca6cf650761d79d7779ad
|
||||
F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 78e6d1b95ac600a9475e9db4623f69449322b0c93d1bd4e1616e76ed547ed9fc
|
||||
F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a
|
||||
F ext/jni/src/org/sqlite/jni/tester/SQLTester.java bf350903abe04a9bed2d8a2a71692ed4291dbb4eece2d3329ed91d15b0321e6d
|
||||
F ext/jni/src/org/sqlite/jni/tester/SQLTester.java e5a1a4b55ed940e61558be1292aa66563219f360c7c1f9d40d770307e6da3c07
|
||||
F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md f9f25126127045d051e918fe59004a1485311c50a13edbf18c79a6ff9160030e
|
||||
F ext/jni/src/tests/000-000-sanity.test cfe6dc1b950751d6096e3f5695becaadcdaa048bfe9567209d6eb676e693366d
|
||||
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
|
||||
@ -548,6 +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/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
F ext/wasm/SQLTester/SQLTester.mjs 4a8fc2194a67180772830f503129c93fe44887b9573f50a4e24868b4bbc817f4
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs a50a1f9314d22d68b62a2f21d8913de163fce1fa420229711d6749c2b4fff9d0
|
||||
F ext/wasm/SQLTester/index.html e5f18af71749d81d86e4649d8c6efc9b78361738cb8e5c5014ba0dd3dc3de6ac
|
||||
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
|
||||
@ -560,14 +565,14 @@ F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057af
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||
F ext/wasm/api/sqlite3-api-glue.js b65e546568f1dfb35205b9792feb5146a6323d71b55cda58e2ed30def6dd52f3
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
|
||||
F ext/wasm/api/sqlite3-api-prologue.js ef6f67c5ea718490806e5e17d2644b8b2f6e6ba5284d23dc1fbfd14d401c1ab5
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
|
||||
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 561463ac5380e4ccf1839a1922e6d7a5585660f32e3b9701a270b78cd35566cf
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js d9e62d42b86f7bb3143eb071628b24e2ba7dcc749e41a0e9d3e2451bfea1a6b6
|
||||
F ext/wasm/api/sqlite3-wasm.c 6773e949034369ddd2a1efdedc39b2808a10b7274b0769188905432e561feebe
|
||||
F ext/wasm/api/sqlite3-wasm.c 65d60439671e24d50d9119ca805ac1c68fb36129e164377eb46f8d037bd88b07
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
|
||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||
@ -2110,8 +2115,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 253fe4a45decdcc4180c5aeccaf4cd0d1325a0f6df0913b0e6721ea3e26b4fe2
|
||||
R ec116b42076aac24bc9f57b015b724bc
|
||||
U drh
|
||||
Z f129cd2d47b4d4fea322d97826168fb6
|
||||
P 058722b2d0b995195a8ce3effe9722ae1c18cb1e7a520b481030da0bd579fe41 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c
|
||||
R 1d37ca9b2e6614cb5d02f3816f204e9d
|
||||
T +closed 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c Closed\sby\sintegrate-merge.
|
||||
U stephan
|
||||
Z 4d7d0ed957593edddd1409081f78edf6
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
058722b2d0b995195a8ce3effe9722ae1c18cb1e7a520b481030da0bd579fe41
|
||||
b530792a514d95c4e8f93cf2170d9fc4de367055fa1704fc171551c946024fa9
|
Loading…
Reference in New Issue
Block a user