mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
Port the first 180-odd unit tests from testing1.* into the new tester1.*. Fix a stray-keystroke-induced typo which broke pstack.allocChunks().
FossilOrigin-Name: ef689e33e464829f5cbe4ca24a53d9dba59abe74d3d80a37a91b93a4eccccf2d
This commit is contained in:
@ -941,8 +941,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
*/
|
*/
|
||||||
allocChunks: (n,sz)=>{
|
allocChunks: (n,sz)=>{
|
||||||
const mem = wasm.pstack.alloc(n * sz);
|
const mem = wasm.pstack.alloc(n * sz);
|
||||||
const r
|
const rc = [];
|
||||||
= [];
|
|
||||||
let i = 0, offset = 0;
|
let i = 0, offset = 0;
|
||||||
for(; i < n; offset = (sz * ++i)){
|
for(; i < n; offset = (sz * ++i)){
|
||||||
rc.push(mem + offset);
|
rc.push(mem + offset);
|
||||||
|
@ -36,9 +36,13 @@ span.labeled-input {
|
|||||||
background-color: yellow;
|
background-color: yellow;
|
||||||
}
|
}
|
||||||
.warning { color: firebrick; }
|
.warning { color: firebrick; }
|
||||||
|
.green { color: darkgreen; }
|
||||||
|
.group-start { color: blue; }
|
||||||
|
.group-end { color: blue; }
|
||||||
.input-wrapper { white-space: nowrap; }
|
.input-wrapper { white-space: nowrap; }
|
||||||
#test-output {
|
#test-output {
|
||||||
border: 1px inset;
|
border: 1px inset;
|
||||||
|
border-radius: 0.25em;
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
/*max-height: 30em;*/
|
/*max-height: 30em;*/
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
@ -15,12 +15,14 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>sqlite3 WASM/JS tester #1 (Worker thread)</h1>
|
<h1>sqlite3 WASM/JS tester #1 (Worker thread)</h1>
|
||||||
|
<div id='test-output'></div>
|
||||||
<script>(function(){
|
<script>(function(){
|
||||||
|
const logTarget = document.querySelector('#test-output');
|
||||||
const logHtml = function(cssClass,...args){
|
const logHtml = function(cssClass,...args){
|
||||||
const ln = document.createElement('div');
|
const ln = document.createElement('div');
|
||||||
if(cssClass) ln.classList.add(cssClass);
|
if(cssClass) ln.classList.add(cssClass);
|
||||||
ln.append(document.createTextNode(args.join(' ')));
|
ln.append(document.createTextNode(args.join(' ')));
|
||||||
document.body.append(ln);
|
logTarget.append(ln);
|
||||||
};
|
};
|
||||||
const w = new Worker("tester1.js");
|
const w = new Worker("tester1.js");
|
||||||
w.onmessage = function({data}){
|
w.onmessage = function({data}){
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>sqlite3 WASM/JS tester #1 (UI thread)</h1>
|
<h1>sqlite3 WASM/JS tester #1 (UI thread)</h1>
|
||||||
|
<div id='test-output'></div>
|
||||||
<script src="sqlite3.js"></script>
|
<script src="sqlite3.js"></script>
|
||||||
<script src="tester1.js"></script>
|
<script src="tester1.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -11,6 +11,23 @@
|
|||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
|
||||||
Main functional and regression tests for the sqlite3 WASM API.
|
Main functional and regression tests for the sqlite3 WASM API.
|
||||||
|
|
||||||
|
This mini-framework works like so:
|
||||||
|
|
||||||
|
This script adds a series of test groups, each of which contains an
|
||||||
|
arbitrary number of tests, into a queue. After loading of the
|
||||||
|
sqlite3 WASM/JS module is complete, that queue is processed. If any
|
||||||
|
given test fails, the whole thing fails. This script is built such
|
||||||
|
that it can run from the main UI thread or worker thread. Test
|
||||||
|
groups and individual tests can be assigned a predicate function
|
||||||
|
which determines whether to run them or not, and this is
|
||||||
|
specifically intended to be used to toggle certain tests on or off
|
||||||
|
for the main/worker threads.
|
||||||
|
|
||||||
|
Each test group defines a state object which gets applied as each
|
||||||
|
test function's `this`. Test functions can use that to, e.g., set up
|
||||||
|
a db in an early test and close it in a later test. Each test gets
|
||||||
|
passed the sqlite3 namespace object as its only argument.
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
(function(){
|
(function(){
|
||||||
@ -19,8 +36,16 @@
|
|||||||
on whether we are running in a worker thread or
|
on whether we are running in a worker thread or
|
||||||
the main (UI) thread.
|
the main (UI) thread.
|
||||||
*/
|
*/
|
||||||
let logHtml;
|
let logClass;
|
||||||
|
/* Predicate for tests/groups. */
|
||||||
const isUIThread = ()=>(self.window===self && self.document);
|
const isUIThread = ()=>(self.window===self && self.document);
|
||||||
|
/* Predicate for tests/groups. */
|
||||||
|
const isWorker = ()=>!isUIThread();
|
||||||
|
/* Predicate for tests/groups. */
|
||||||
|
const testIsTodo = ()=>false;
|
||||||
|
const haveJaccwabytTests = function(){
|
||||||
|
return !!wasm.exports.jaccwabyt_test_int64_max;
|
||||||
|
};
|
||||||
const mapToString = (v)=>{
|
const mapToString = (v)=>{
|
||||||
switch(typeof v){
|
switch(typeof v){
|
||||||
case 'number': case 'string': case 'boolean':
|
case 'number': case 'string': case 'boolean':
|
||||||
@ -29,20 +54,28 @@
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if(null===v) return 'null';
|
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);
|
return JSON.stringify(v,undefined,2);
|
||||||
};
|
};
|
||||||
const normalizeArgs = (args)=>args.map(mapToString);
|
const normalizeArgs = (args)=>args.map(mapToString);
|
||||||
if( isUIThread() ){
|
if( isUIThread() ){
|
||||||
console.log("Running UI thread.");
|
console.log("Running in UI thread.");
|
||||||
logHtml = function(cssClass,...args){
|
const logTarget = document.querySelector('#test-output');
|
||||||
|
logClass = function(cssClass,...args){
|
||||||
const ln = document.createElement('div');
|
const ln = document.createElement('div');
|
||||||
if(cssClass) ln.classList.add(cssClass);
|
if(cssClass) ln.classList.add(cssClass);
|
||||||
ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
|
ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
|
||||||
document.body.append(ln);
|
logTarget.append(ln);
|
||||||
};
|
};
|
||||||
}else{ /* Worker thread */
|
}else{ /* Worker thread */
|
||||||
console.log("Running Worker thread.");
|
console.log("Running Worker thread.");
|
||||||
logHtml = function(cssClass,...args){
|
logClass = function(cssClass,...args){
|
||||||
postMessage({
|
postMessage({
|
||||||
type:'log',
|
type:'log',
|
||||||
payload:{cssClass, args: normalizeArgs(args)}
|
payload:{cssClass, args: normalizeArgs(args)}
|
||||||
@ -51,21 +84,24 @@
|
|||||||
}
|
}
|
||||||
const log = (...args)=>{
|
const log = (...args)=>{
|
||||||
//console.log(...args);
|
//console.log(...args);
|
||||||
logHtml('',...args);
|
logClass('',...args);
|
||||||
}
|
}
|
||||||
const warn = (...args)=>{
|
const warn = (...args)=>{
|
||||||
console.warn(...args);
|
console.warn(...args);
|
||||||
logHtml('warning',...args);
|
logClass('warning',...args);
|
||||||
}
|
}
|
||||||
const error = (...args)=>{
|
const error = (...args)=>{
|
||||||
console.error(...args);
|
console.error(...args);
|
||||||
logHtml('error',...args);
|
logClass('error',...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toss = (...args)=>{
|
const toss = (...args)=>{
|
||||||
error(...args);
|
error(...args);
|
||||||
throw new Error(args.join(' '));
|
throw new Error(args.join(' '));
|
||||||
};
|
};
|
||||||
|
const tossQuietly = (...args)=>{
|
||||||
|
throw new Error(args.join(' '));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Helpers for writing sqlite3-specific tests.
|
Helpers for writing sqlite3-specific tests.
|
||||||
@ -74,6 +110,8 @@
|
|||||||
/** Running total of the number of tests run via
|
/** Running total of the number of tests run via
|
||||||
this API. */
|
this API. */
|
||||||
counter: 0,
|
counter: 0,
|
||||||
|
/* Separator line for log messages. */
|
||||||
|
separator: '------------------------------------------------------------',
|
||||||
/**
|
/**
|
||||||
If expr is a function, it is called and its result
|
If expr is a function, it is called and its result
|
||||||
is returned, coerced to a bool, else expr, coerced to
|
is returned, coerced to a bool, else expr, coerced to
|
||||||
@ -155,32 +193,531 @@
|
|||||||
if(!this.toBool(expr)) throw new Error(msg || "throwUnless() failed");
|
if(!this.toBool(expr)) throw new Error(msg || "throwUnless() failed");
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
TestGroup: class {
|
eqApprox: (v1,v2,factor=0.05)=>(v1>=(v2-factor) && v1<=(v2+factor)),
|
||||||
constructor(name){
|
TestGroup: (function(){
|
||||||
|
let groupCounter = 0;
|
||||||
|
const TestGroup = function(name, predicate){
|
||||||
|
this.number = ++groupCounter;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.predicate = predicate;
|
||||||
this.tests = [];
|
this.tests = [];
|
||||||
}
|
};
|
||||||
push(name,callback){
|
TestGroup.prototype = {
|
||||||
}
|
addTest: function(testObj){
|
||||||
}/*TestGroup*/,
|
this.tests.push(testObj);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
run: async function(sqlite3){
|
||||||
|
if(this.predicate && !this.predicate()){
|
||||||
|
log("SKIPPING test group #"+this.number,this.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log(TestUtil.separator);
|
||||||
|
logClass('group-start',"Group #"+this.number+':',this.name);
|
||||||
|
const indent = '....';
|
||||||
|
const assertCount = TestUtil.counter;
|
||||||
|
const groupState = Object.create(null);
|
||||||
|
const skipped = [];
|
||||||
|
for(let i in this.tests){
|
||||||
|
const t = this.tests[i];
|
||||||
|
const n = this.number+"."+i;
|
||||||
|
if(t.predicate && !t.predicate()){
|
||||||
|
logClass('warning',indent, n+': SKIPPING',t.name);
|
||||||
|
skipped.push( n+': '+t.name );
|
||||||
|
}else{
|
||||||
|
const tc = TestUtil.counter
|
||||||
|
log(indent, n+":", t.name);
|
||||||
|
await t.test.call(groupState, sqlite3);
|
||||||
|
//log(indent, indent, 'assertion count:',TestUtil.counter - tc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logClass('green',
|
||||||
|
"Group #"+this.number,"assertion count:",(TestUtil.counter - assertCount));
|
||||||
|
if(skipped.length){
|
||||||
|
log("SKIPPED test(s) in group",this.number+":",skipped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return TestGroup;
|
||||||
|
})()/*TestGroup*/,
|
||||||
testGroups: [],
|
testGroups: [],
|
||||||
currentTestGroup: undefined,
|
currentTestGroup: undefined,
|
||||||
addGroup: function(name){
|
addGroup: function(name, predicate){
|
||||||
if(this.testGroups[name]){
|
|
||||||
toss("Test group already exists:",name);
|
|
||||||
}
|
|
||||||
this.testGroups.push( this.currentTestGroup = new this.TestGroup(name) );
|
this.testGroups.push( this.currentTestGroup = new this.TestGroup(name) );
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
addTest: function(name, callback){
|
addTest: function(name, callback){
|
||||||
this.currentTestGroup.push(name, callback);
|
let predicate;
|
||||||
|
if(1===arguments.length){
|
||||||
|
const opt = arguments[0];
|
||||||
|
predicate = opt.predicate;
|
||||||
|
name = opt.name;
|
||||||
|
callback = opt.test;
|
||||||
|
}
|
||||||
|
this.currentTestGroup.addTest({
|
||||||
|
name, predicate, test: callback
|
||||||
|
});
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
runTests: function(){
|
runTests: async function(sqlite3){
|
||||||
toss("TODO: runTests()");
|
return new Promise(async function(pok,pnok){
|
||||||
|
try {
|
||||||
|
for(let g of this.testGroups){
|
||||||
|
await g.run(sqlite3);
|
||||||
|
}
|
||||||
|
log(TestUtil.separator);
|
||||||
|
log("Done running tests. Total assertion count:",TestUtil.counter);
|
||||||
|
pok();
|
||||||
|
}catch(e){
|
||||||
|
error(e);
|
||||||
|
pnok(e);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
}
|
}
|
||||||
}/*TestUtil*/;
|
}/*TestUtil*/;
|
||||||
|
const T = TestUtil;
|
||||||
|
T.g = T.addGroup;
|
||||||
|
T.t = T.addTest;
|
||||||
|
let capi, wasm/*assigned after module init*/;
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// End of infrastructure setup. Now define the tests...
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
T.g('Basic sanity checks')
|
||||||
|
.t('Namespace object checks', function(sqlite3){
|
||||||
|
const wasmCtypes = wasm.ctype;
|
||||||
|
T.assert(wasmCtypes.structs[0].name==='sqlite3_vfs').
|
||||||
|
assert(wasmCtypes.structs[0].members.szOsFile.sizeof>=4).
|
||||||
|
assert(wasmCtypes.structs[1/*sqlite3_io_methods*/
|
||||||
|
].members.xFileSize.offset>0);
|
||||||
|
[ /* Spot-check a handful of constants to make sure they got installed... */
|
||||||
|
'SQLITE_SCHEMA','SQLITE_NULL','SQLITE_UTF8',
|
||||||
|
'SQLITE_STATIC', 'SQLITE_DIRECTONLY',
|
||||||
|
'SQLITE_OPEN_CREATE', 'SQLITE_OPEN_DELETEONCLOSE'
|
||||||
|
].forEach((k)=>T.assert('number' === typeof capi[k]));
|
||||||
|
[/* Spot-check a few of the WASM API methods. */
|
||||||
|
'alloc', 'dealloc', 'installFunction'
|
||||||
|
].forEach((k)=>T.assert(wasm[k] instanceof Function));
|
||||||
|
|
||||||
|
T.assert(capi.sqlite3_errstr(capi.SQLITE_IOERR_ACCESS).indexOf("I/O")>=0).
|
||||||
|
assert(capi.sqlite3_errstr(capi.SQLITE_CORRUPT).indexOf('malformed')>0).
|
||||||
|
assert(capi.sqlite3_errstr(capi.SQLITE_OK) === 'not an error');
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw new sqlite3.WasmAllocError;
|
||||||
|
}catch(e){
|
||||||
|
T.assert(e instanceof Error)
|
||||||
|
.assert(e instanceof sqlite3.WasmAllocError);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.t('strglob/strlike', function(sqlite3){
|
||||||
|
T.assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
|
||||||
|
assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
|
||||||
|
assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)).
|
||||||
|
assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0));
|
||||||
|
})
|
||||||
|
|
||||||
|
.t('sqlite3.capi.wasm.pstack', function(sqlite3){
|
||||||
|
const w = sqlite3.capi.wasm, P = w.pstack;
|
||||||
|
const isAllocErr = (e)=>e instanceof sqlite3.WasmAllocError;
|
||||||
|
const stack = P.pointer;
|
||||||
|
T.assert(0===stack % 8 /* must be 8-byte aligned */);
|
||||||
|
try{
|
||||||
|
const remaining = P.remaining;
|
||||||
|
T.assert(P.quota >= 4096)
|
||||||
|
.assert(remaining === P.quota)
|
||||||
|
.mustThrowMatching(()=>P.alloc(0), isAllocErr)
|
||||||
|
.mustThrowMatching(()=>P.alloc(-1), isAllocErr);
|
||||||
|
let p1 = P.alloc(12);
|
||||||
|
T.assert(p1 === stack - 16/*8-byte aligned*/)
|
||||||
|
.assert(P.pointer === p1);
|
||||||
|
let p2 = P.alloc(7);
|
||||||
|
T.assert(p2 === p1-8/*8-byte aligned, stack grows downwards*/)
|
||||||
|
.mustThrowMatching(()=>P.alloc(remaining), isAllocErr)
|
||||||
|
.assert(24 === stack - p2)
|
||||||
|
.assert(P.pointer === p2);
|
||||||
|
let n = remaining - (stack - p2);
|
||||||
|
let p3 = P.alloc(n);
|
||||||
|
T.assert(p3 === stack-remaining)
|
||||||
|
.mustThrowMatching(()=>P.alloc(1), isAllocErr);
|
||||||
|
}finally{
|
||||||
|
P.restore(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
T.assert(P.pointer === stack);
|
||||||
|
try {
|
||||||
|
const [p1, p2, p3] = P.allocChunks(3,4);
|
||||||
|
T.assert(P.pointer === stack-16/*always rounded to multiple of 8*/)
|
||||||
|
.assert(p2 === p1 + 4)
|
||||||
|
.assert(p3 === p2 + 4);
|
||||||
|
T.mustThrowMatching(()=>P.allocChunks(1024, 1024 * 16),
|
||||||
|
(e)=>e instanceof sqlite3.WasmAllocError)
|
||||||
|
}finally{
|
||||||
|
P.restore(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
T.assert(P.pointer === stack);
|
||||||
|
try {
|
||||||
|
let [p1, p2, p3] = P.allocPtr(3,false);
|
||||||
|
let sPos = stack-16/*always rounded to multiple of 8*/;
|
||||||
|
T.assert(P.pointer === sPos)
|
||||||
|
.assert(p2 === p1 + 4)
|
||||||
|
.assert(p3 === p2 + 4);
|
||||||
|
[p1, p2, p3] = P.allocPtr(3);
|
||||||
|
T.assert(P.pointer === sPos-24/*3 x 8 bytes*/)
|
||||||
|
.assert(p2 === p1 + 8)
|
||||||
|
.assert(p3 === p2 + 8);
|
||||||
|
p1 = P.allocPtr();
|
||||||
|
T.assert('number'===typeof p1);
|
||||||
|
}finally{
|
||||||
|
P.restore(stack);
|
||||||
|
}
|
||||||
|
}/*pstack tests*/)
|
||||||
|
;/*end of basic sanity checks*/
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
T.g('sqlite3.oo1 sanity checks')
|
||||||
|
.t('Create db', function(sqlite3){
|
||||||
|
const db = this.db = new sqlite3.oo1.DB();
|
||||||
|
T.assert(Number.isInteger(db.pointer)).
|
||||||
|
mustThrowMatching(()=>db.pointer=1, /read-only/).
|
||||||
|
assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1)).
|
||||||
|
assert('main'===db.dbName(0));
|
||||||
|
|
||||||
|
// Custom db error message handling via sqlite3_prepare_v2/v3()
|
||||||
|
let rc = capi.sqlite3_prepare_v3(db.pointer, {/*invalid*/}, -1, 0, null, null);
|
||||||
|
T.assert(capi.SQLITE_MISUSE === rc)
|
||||||
|
.assert(0 === capi.sqlite3_errmsg(db.pointer).indexOf("Invalid SQL"));
|
||||||
|
})
|
||||||
|
.t('DB.Stmt sanity checks', function(S){
|
||||||
|
let pId;
|
||||||
|
let st = this.db.prepare(
|
||||||
|
new TextEncoder('utf-8').encode("select 3 as a")
|
||||||
|
);
|
||||||
|
//debug("statement =",st);
|
||||||
|
try {
|
||||||
|
T.assert(Number.isInteger(st.pointer))
|
||||||
|
.mustThrowMatching(()=>st.pointer=1, /read-only/)
|
||||||
|
.assert(1===this.db.openStatementCount())
|
||||||
|
.assert(!st._mayGet)
|
||||||
|
.assert('a' === st.getColumnName(0))
|
||||||
|
.assert(1===st.columnCount)
|
||||||
|
.assert(0===st.parameterCount)
|
||||||
|
.mustThrow(()=>st.bind(1,null))
|
||||||
|
.assert(true===st.step())
|
||||||
|
.assert(3 === st.get(0))
|
||||||
|
.mustThrow(()=>st.get(1))
|
||||||
|
.mustThrow(()=>st.get(0,~capi.SQLITE_INTEGER))
|
||||||
|
.assert(3 === st.get(0,capi.SQLITE_INTEGER))
|
||||||
|
.assert(3 === st.getInt(0))
|
||||||
|
.assert('3' === st.get(0,capi.SQLITE_TEXT))
|
||||||
|
.assert('3' === st.getString(0))
|
||||||
|
.assert(3.0 === st.get(0,capi.SQLITE_FLOAT))
|
||||||
|
.assert(3.0 === st.getFloat(0))
|
||||||
|
.assert(3 === st.get({}).a)
|
||||||
|
.assert(3 === st.get([])[0])
|
||||||
|
.assert(3 === st.getJSON(0))
|
||||||
|
.assert(st.get(0,capi.SQLITE_BLOB) instanceof Uint8Array)
|
||||||
|
.assert(1===st.get(0,capi.SQLITE_BLOB).length)
|
||||||
|
.assert(st.getBlob(0) instanceof Uint8Array)
|
||||||
|
.assert('3'.charCodeAt(0) === st.getBlob(0)[0])
|
||||||
|
.assert(st._mayGet)
|
||||||
|
.assert(false===st.step())
|
||||||
|
.assert(!st._mayGet)
|
||||||
|
;
|
||||||
|
pId = st.pointer;
|
||||||
|
T.assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
|
||||||
|
assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
|
||||||
|
assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)).
|
||||||
|
assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0));
|
||||||
|
}finally{
|
||||||
|
st.finalize();
|
||||||
|
}
|
||||||
|
T.assert(!st.pointer)
|
||||||
|
.assert(0===this.db.openStatementCount());
|
||||||
|
})
|
||||||
|
.t('Table t', function(sqlite3){
|
||||||
|
const db = this.db;
|
||||||
|
let list = [];
|
||||||
|
db.exec({
|
||||||
|
sql:['CREATE TABLE t(a,b);',
|
||||||
|
"INSERT INTO t(a,b) VALUES(1,2),(3,4),",
|
||||||
|
"(?,?),('blob',X'6869')"/*intentionally missing semicolon to test for
|
||||||
|
off-by-one bug in string-to-WASM conversion*/],
|
||||||
|
saveSql: list,
|
||||||
|
bind: [5,6]
|
||||||
|
});
|
||||||
|
//debug("Exec'd SQL:", list);
|
||||||
|
T.assert(2 === list.length)
|
||||||
|
.assert('string'===typeof list[1])
|
||||||
|
.assert(4===db.changes());
|
||||||
|
if(capi.wasm.bigIntEnabled){
|
||||||
|
T.assert(4n===db.changes(false,true));
|
||||||
|
}
|
||||||
|
let blob = db.selectValue("select b from t where a='blob'");
|
||||||
|
T.assert(blob instanceof Uint8Array).
|
||||||
|
assert(0x68===blob[0] && 0x69===blob[1]);
|
||||||
|
blob = null;
|
||||||
|
let counter = 0, colNames = [];
|
||||||
|
list.length = 0;
|
||||||
|
db.exec(new TextEncoder('utf-8').encode("SELECT a a, b b FROM t"),{
|
||||||
|
rowMode: 'object',
|
||||||
|
resultRows: list,
|
||||||
|
columnNames: colNames,
|
||||||
|
callback: function(row,stmt){
|
||||||
|
++counter;
|
||||||
|
T.assert((row.a%2 && row.a<6) || 'blob'===row.a);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
T.assert(2 === colNames.length)
|
||||||
|
.assert('a' === colNames[0])
|
||||||
|
.assert(4 === counter)
|
||||||
|
.assert(4 === list.length);
|
||||||
|
list.length = 0;
|
||||||
|
db.exec("SELECT a a, b b FROM t",{
|
||||||
|
rowMode: 'array',
|
||||||
|
callback: function(row,stmt){
|
||||||
|
++counter;
|
||||||
|
T.assert(Array.isArray(row))
|
||||||
|
.assert((0===row[1]%2 && row[1]<7)
|
||||||
|
|| (row[1] instanceof Uint8Array));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
T.assert(8 === counter);
|
||||||
|
T.assert(Number.MIN_SAFE_INTEGER ===
|
||||||
|
db.selectValue("SELECT "+Number.MIN_SAFE_INTEGER)).
|
||||||
|
assert(Number.MAX_SAFE_INTEGER ===
|
||||||
|
db.selectValue("SELECT "+Number.MAX_SAFE_INTEGER));
|
||||||
|
if(capi.wasm.bigIntEnabled && haveJaccwabytTests()){
|
||||||
|
const mI = capi.wasm.xCall('jaccwabyt_test_int64_max');
|
||||||
|
const b = BigInt(Number.MAX_SAFE_INTEGER * 2);
|
||||||
|
T.assert(b === db.selectValue("SELECT "+b)).
|
||||||
|
assert(b === db.selectValue("SELECT ?", b)).
|
||||||
|
assert(mI == db.selectValue("SELECT $x", {$x:mI}));
|
||||||
|
}else{
|
||||||
|
/* Curiously, the JS spec seems to be off by one with the definitions
|
||||||
|
of MIN/MAX_SAFE_INTEGER:
|
||||||
|
|
||||||
|
https://github.com/emscripten-core/emscripten/issues/17391 */
|
||||||
|
T.mustThrow(()=>db.selectValue("SELECT "+(Number.MAX_SAFE_INTEGER+1))).
|
||||||
|
mustThrow(()=>db.selectValue("SELECT "+(Number.MIN_SAFE_INTEGER-1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let st = db.prepare("update t set b=:b where a='blob'");
|
||||||
|
try {
|
||||||
|
const ndx = st.getParamIndex(':b');
|
||||||
|
T.assert(1===ndx);
|
||||||
|
st.bindAsBlob(ndx, "ima blob").reset(true);
|
||||||
|
} finally {
|
||||||
|
st.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.prepare("/*empty SQL*/");
|
||||||
|
toss("Must not be reached.");
|
||||||
|
}catch(e){
|
||||||
|
T.assert(e instanceof sqlite3.SQLite3Error)
|
||||||
|
.assert(0==e.message.indexOf('Cannot prepare empty'));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
.t('Scalar UDFs', function(sqlite3){
|
||||||
|
const db = this.db;
|
||||||
|
db.createFunction("foo",(pCx,a,b)=>a+b);
|
||||||
|
T.assert(7===db.selectValue("select foo(3,4)")).
|
||||||
|
assert(5===db.selectValue("select foo(3,?)",2)).
|
||||||
|
assert(5===db.selectValue("select foo(?,?2)",[1,4])).
|
||||||
|
assert(5===db.selectValue("select foo($a,$b)",{$a:0,$b:5}));
|
||||||
|
db.createFunction("bar", {
|
||||||
|
arity: -1,
|
||||||
|
callback: function(pCx){
|
||||||
|
var rc = 0;
|
||||||
|
for(let i = 1; i < arguments.length; ++i) rc += arguments[i];
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}).createFunction({
|
||||||
|
name: "asis",
|
||||||
|
callback: (pCx,arg)=>arg
|
||||||
|
});
|
||||||
|
T.assert(0===db.selectValue("select bar()")).
|
||||||
|
assert(1===db.selectValue("select bar(1)")).
|
||||||
|
assert(3===db.selectValue("select bar(1,2)")).
|
||||||
|
assert(-1===db.selectValue("select bar(1,2,-4)")).
|
||||||
|
assert('hi' === db.selectValue("select asis('hi')")).
|
||||||
|
assert('hi' === db.selectValue("select ?",'hi')).
|
||||||
|
assert(null === db.selectValue("select null")).
|
||||||
|
assert(null === db.selectValue("select asis(null)")).
|
||||||
|
assert(1 === db.selectValue("select ?",1)).
|
||||||
|
assert(2 === db.selectValue("select ?",[2])).
|
||||||
|
assert(3 === db.selectValue("select $a",{$a:3})).
|
||||||
|
assert(T.eqApprox(3.1,db.selectValue("select 3.0 + 0.1"))).
|
||||||
|
assert(T.eqApprox(1.3,db.selectValue("select asis(1 + 0.3)")));
|
||||||
|
|
||||||
|
let blobArg = new Uint8Array(2);
|
||||||
|
blobArg.set([0x68, 0x69], 0);
|
||||||
|
let blobRc = db.selectValue("select asis(?1)", blobArg);
|
||||||
|
T.assert(blobRc instanceof Uint8Array).
|
||||||
|
assert(2 === blobRc.length).
|
||||||
|
assert(0x68==blobRc[0] && 0x69==blobRc[1]);
|
||||||
|
blobRc = db.selectValue("select asis(X'6869')");
|
||||||
|
T.assert(blobRc instanceof Uint8Array).
|
||||||
|
assert(2 === blobRc.length).
|
||||||
|
assert(0x68==blobRc[0] && 0x69==blobRc[1]);
|
||||||
|
|
||||||
|
blobArg = new Int8Array(2);
|
||||||
|
blobArg.set([0x68, 0x69]);
|
||||||
|
//debug("blobArg=",blobArg);
|
||||||
|
blobRc = db.selectValue("select asis(?1)", blobArg);
|
||||||
|
T.assert(blobRc instanceof Uint8Array).
|
||||||
|
assert(2 === blobRc.length);
|
||||||
|
//debug("blobRc=",blobRc);
|
||||||
|
T.assert(0x68==blobRc[0] && 0x69==blobRc[1]);
|
||||||
|
})
|
||||||
|
|
||||||
|
.t({
|
||||||
|
name: 'Aggregate UDFs (tests are TODO)',
|
||||||
|
predicate: testIsTodo
|
||||||
|
})
|
||||||
|
|
||||||
|
.t({
|
||||||
|
name: 'Window UDFs (tests are TODO)',
|
||||||
|
predicate: testIsTodo
|
||||||
|
})
|
||||||
|
|
||||||
|
.t("ATTACH", function(){
|
||||||
|
const db = this.db;
|
||||||
|
const resultRows = [];
|
||||||
|
db.exec({
|
||||||
|
sql:new TextEncoder('utf-8').encode([
|
||||||
|
// ^^^ testing string-vs-typedarray handling in exec()
|
||||||
|
"attach 'session' as foo;" /* name 'session' is magic for kvvfs! */,
|
||||||
|
"create table foo.bar(a);",
|
||||||
|
"insert into foo.bar(a) values(1),(2),(3);",
|
||||||
|
"select a from foo.bar order by a;"
|
||||||
|
].join('')),
|
||||||
|
rowMode: 0,
|
||||||
|
resultRows
|
||||||
|
});
|
||||||
|
T.assert(3===resultRows.length)
|
||||||
|
.assert(2===resultRows[1]);
|
||||||
|
T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));
|
||||||
|
let colCount = 0, rowCount = 0;
|
||||||
|
const execCallback = function(pVoid, nCols, aVals, aNames){
|
||||||
|
colCount = nCols;
|
||||||
|
++rowCount;
|
||||||
|
T.assert(2===aVals.length)
|
||||||
|
.assert(2===aNames.length)
|
||||||
|
.assert(+(aVals[1]) === 2 * +(aVals[0]));
|
||||||
|
};
|
||||||
|
let rc = capi.sqlite3_exec(
|
||||||
|
db.pointer, "select a, a*2 from foo.bar", execCallback,
|
||||||
|
0, 0
|
||||||
|
);
|
||||||
|
T.assert(0===rc).assert(3===rowCount).assert(2===colCount);
|
||||||
|
rc = capi.sqlite3_exec(
|
||||||
|
db.pointer, "select a from foo.bar", ()=>{
|
||||||
|
tossQuietly("Testing throwing from exec() callback.");
|
||||||
|
}, 0, 0
|
||||||
|
);
|
||||||
|
T.assert(capi.SQLITE_ABORT === rc);
|
||||||
|
db.exec("detach foo");
|
||||||
|
T.mustThrow(()=>db.exec("select * from foo.bar"));
|
||||||
|
})
|
||||||
|
|
||||||
|
.t({
|
||||||
|
name: 'Jaccwabyt-specific int-pointer tests (if compiled in)',
|
||||||
|
predicate: haveJaccwabytTests,
|
||||||
|
test: function(){
|
||||||
|
const w = wasm, db = this.db;
|
||||||
|
const stack = w.scopedAllocPush();
|
||||||
|
let ptrInt;
|
||||||
|
const origValue = 512;
|
||||||
|
const ptrValType = 'i32';
|
||||||
|
try{
|
||||||
|
ptrInt = w.scopedAlloc(4);
|
||||||
|
w.setMemValue(ptrInt,origValue, ptrValType);
|
||||||
|
const cf = w.xGet('jaccwabyt_test_intptr');
|
||||||
|
const oldPtrInt = ptrInt;
|
||||||
|
//log('ptrInt',ptrInt);
|
||||||
|
//log('getMemValue(ptrInt)',w.getMemValue(ptrInt));
|
||||||
|
T.assert(origValue === w.getMemValue(ptrInt, ptrValType));
|
||||||
|
const rc = cf(ptrInt);
|
||||||
|
//log('cf(ptrInt)',rc);
|
||||||
|
//log('ptrInt',ptrInt);
|
||||||
|
//log('getMemValue(ptrInt)',w.getMemValue(ptrInt,ptrValType));
|
||||||
|
T.assert(2*origValue === rc).
|
||||||
|
assert(rc === w.getMemValue(ptrInt,ptrValType)).
|
||||||
|
assert(oldPtrInt === ptrInt);
|
||||||
|
const pi64 = w.scopedAlloc(8)/*ptr to 64-bit integer*/;
|
||||||
|
const o64 = 0x010203040506/*>32-bit integer*/;
|
||||||
|
const ptrType64 = 'i64';
|
||||||
|
if(w.bigIntEnabled){
|
||||||
|
w.setMemValue(pi64, o64, ptrType64);
|
||||||
|
//log("pi64 =",pi64, "o64 = 0x",o64.toString(16), o64);
|
||||||
|
const v64 = ()=>w.getMemValue(pi64,ptrType64)
|
||||||
|
//log("getMemValue(pi64)",v64());
|
||||||
|
T.assert(v64() == o64);
|
||||||
|
//T.assert(o64 === w.getMemValue(pi64, ptrType64));
|
||||||
|
const cf64w = w.xGet('jaccwabyt_test_int64ptr');
|
||||||
|
cf64w(pi64);
|
||||||
|
//log("getMemValue(pi64)",v64());
|
||||||
|
T.assert(v64() == BigInt(2 * o64));
|
||||||
|
cf64w(pi64);
|
||||||
|
T.assert(v64() == BigInt(4 * o64));
|
||||||
|
|
||||||
|
const biTimes2 = w.xGet('jaccwabyt_test_int64_times2');
|
||||||
|
T.assert(BigInt(2 * o64) ===
|
||||||
|
biTimes2(BigInt(o64)/*explicit conv. required to avoid TypeError
|
||||||
|
in the call :/ */));
|
||||||
|
|
||||||
|
const pMin = w.scopedAlloc(16);
|
||||||
|
const pMax = pMin + 8;
|
||||||
|
const g64 = (p)=>w.getMemValue(p,ptrType64);
|
||||||
|
w.setMemValue(pMin, 0, ptrType64);
|
||||||
|
w.setMemValue(pMax, 0, ptrType64);
|
||||||
|
const minMaxI64 = [
|
||||||
|
w.xCall('jaccwabyt_test_int64_min'),
|
||||||
|
w.xCall('jaccwabyt_test_int64_max')
|
||||||
|
];
|
||||||
|
T.assert(minMaxI64[0] < BigInt(Number.MIN_SAFE_INTEGER)).
|
||||||
|
assert(minMaxI64[1] > BigInt(Number.MAX_SAFE_INTEGER));
|
||||||
|
//log("int64_min/max() =",minMaxI64, typeof minMaxI64[0]);
|
||||||
|
w.xCall('jaccwabyt_test_int64_minmax', pMin, pMax);
|
||||||
|
T.assert(g64(pMin) === minMaxI64[0], "int64 mismatch").
|
||||||
|
assert(g64(pMax) === minMaxI64[1], "int64 mismatch");
|
||||||
|
//log("pMin",g64(pMin), "pMax",g64(pMax));
|
||||||
|
w.setMemValue(pMin, minMaxI64[0], ptrType64);
|
||||||
|
T.assert(g64(pMin) === minMaxI64[0]).
|
||||||
|
assert(minMaxI64[0] === db.selectValue("select ?",g64(pMin))).
|
||||||
|
assert(minMaxI64[1] === db.selectValue("select ?",g64(pMax)));
|
||||||
|
const rxRange = /too big/;
|
||||||
|
T.mustThrowMatching(()=>{db.prepare("select ?").bind(minMaxI64[0] - BigInt(1))},
|
||||||
|
rxRange).
|
||||||
|
mustThrowMatching(()=>{db.prepare("select ?").bind(minMaxI64[1] + BigInt(1))},
|
||||||
|
(e)=>rxRange.test(e.message));
|
||||||
|
}else{
|
||||||
|
log("No BigInt support. Skipping related tests.");
|
||||||
|
log("\"The problem\" here is that we can manipulate, at the byte level,",
|
||||||
|
"heap memory to set 64-bit values, but we can't get those values",
|
||||||
|
"back into JS because of the lack of 64-bit integer support.");
|
||||||
|
}
|
||||||
|
}finally{
|
||||||
|
const x = w.scopedAlloc(1), y = w.scopedAlloc(1), z = w.scopedAlloc(1);
|
||||||
|
//log("x=",x,"y=",y,"z=",z); // just looking at the alignment
|
||||||
|
w.scopedAllocPop(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}/* jaccwabyt-specific tests */)
|
||||||
|
|
||||||
|
.t('Close db', function(){
|
||||||
|
T.assert(this.db).assert(Number.isInteger(this.db.pointer));
|
||||||
|
wasm.exports.sqlite3_wasm_db_reset(this.db.pointer);
|
||||||
|
this.db.close();
|
||||||
|
T.assert(!this.db.pointer);
|
||||||
|
})
|
||||||
|
;/* end of oo1 checks */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
log("Loading and initializing sqlite3 WASM module...");
|
log("Loading and initializing sqlite3 WASM module...");
|
||||||
if(!isUIThread()){
|
if(!isUIThread()){
|
||||||
importScripts("sqlite3.js");
|
importScripts("sqlite3.js");
|
||||||
@ -190,11 +727,15 @@
|
|||||||
printErr: error
|
printErr: error
|
||||||
}).then(function(sqlite3){
|
}).then(function(sqlite3){
|
||||||
//console.log('sqlite3 =',sqlite3);
|
//console.log('sqlite3 =',sqlite3);
|
||||||
log("Done initializing. Running tests...");
|
log("Done initializing WASM/JS bits. Running tests...");
|
||||||
try {
|
capi = sqlite3.capi;
|
||||||
TestUtil.runTests();
|
wasm = capi.wasm;
|
||||||
}catch(e){
|
log("sqlite3 version:",capi.sqlite3_libversion(),
|
||||||
error("Tests failed:",e.message);
|
capi.sqlite3_sourceid());
|
||||||
|
log("BigInt/int64 support is",(wasm.bigIntEnabled ? "enabled" : "disabled"));
|
||||||
|
if(haveJaccwabytTests()){
|
||||||
|
log("Jaccwabyt test C code found. Jaccwabyt-specific low-level tests.");
|
||||||
}
|
}
|
||||||
|
TestUtil.runTests(sqlite3);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -94,7 +94,6 @@
|
|||||||
"INSERT INTO t(a,b) VALUES(1,2),(3,4),",
|
"INSERT INTO t(a,b) VALUES(1,2),(3,4),",
|
||||||
"(?,?),('blob',X'6869')"/*intentionally missing semicolon to test for
|
"(?,?),('blob',X'6869')"/*intentionally missing semicolon to test for
|
||||||
off-by-one bug in string-to-WASM conversion*/],
|
off-by-one bug in string-to-WASM conversion*/],
|
||||||
multi: true,
|
|
||||||
saveSql: list,
|
saveSql: list,
|
||||||
bind: [5,6]
|
bind: [5,6]
|
||||||
});
|
});
|
||||||
@ -258,7 +257,6 @@
|
|||||||
"insert into foo.bar(a) values(1),(2),(3);",
|
"insert into foo.bar(a) values(1),(2),(3);",
|
||||||
"select a from foo.bar order by a;"
|
"select a from foo.bar order by a;"
|
||||||
].join('')),
|
].join('')),
|
||||||
multi: true,
|
|
||||||
rowMode: 0,
|
rowMode: 0,
|
||||||
resultRows
|
resultRows
|
||||||
});
|
});
|
||||||
@ -1083,7 +1081,7 @@
|
|||||||
}finally{
|
}finally{
|
||||||
P.restore(stack);
|
P.restore(stack);
|
||||||
}
|
}
|
||||||
}/*testPstack()*/;
|
}/*testPstack()*/;
|
||||||
|
|
||||||
const clearKvvfs = function(){
|
const clearKvvfs = function(){
|
||||||
const sz = sqlite3.capi.sqlite3_web_kvvfs_size();
|
const sz = sqlite3.capi.sqlite3_web_kvvfs_size();
|
||||||
|
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
|||||||
C Updates\sto\sthe\sfuzzer\squery\sinvariant\schecker\s-\stracking\schanges\smade\nover\sin\sdbsqlfuzz.
|
C Port\sthe\sfirst\s180-odd\sunit\stests\sfrom\stesting1.*\sinto\sthe\snew\stester1.*.\sFix\sa\sstray-keystroke-induced\stypo\swhich\sbroke\spstack.allocChunks().
|
||||||
D 2022-10-12T18:40:25.766
|
D 2022-10-13T08:03:31.255
|
||||||
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
|
||||||
@ -487,7 +487,7 @@ F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb4
|
|||||||
F ext/wasm/api/sqlite3-api-glue.js 3b2a43c7b2ceb2b60f5f4a1afefbd93508c2fe0f2e667eea278afe570be4b606
|
F ext/wasm/api/sqlite3-api-glue.js 3b2a43c7b2ceb2b60f5f4a1afefbd93508c2fe0f2e667eea278afe570be4b606
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js ac1e08d36bdfb5aa0a2d75b7d4c892fd51819d34c932370c3282810672bcc086
|
F ext/wasm/api/sqlite3-api-oo1.js ac1e08d36bdfb5aa0a2d75b7d4c892fd51819d34c932370c3282810672bcc086
|
||||||
F ext/wasm/api/sqlite3-api-opfs.js 5a8ab3b76880c8ada8710ca9ba1ca5b160872edfd8bd5322e4f179a7f41cc616
|
F ext/wasm/api/sqlite3-api-opfs.js 5a8ab3b76880c8ada8710ca9ba1ca5b160872edfd8bd5322e4f179a7f41cc616
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js daf288df965cab1e8eabee4451f6ba3beb03d5a579722b0b0f90e5203962f515
|
F ext/wasm/api/sqlite3-api-prologue.js 5c56056810333974c971f6310c5c9698cf7ca8b06f6d2f1986cec819d0f5bbad
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
|
F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
|
||||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||||
F ext/wasm/api/sqlite3-wasm.c a321f12ceedac8611c1377ccfb5df0c0547bd9395f7fd7613827de365d994948
|
F ext/wasm/api/sqlite3-wasm.c a321f12ceedac8611c1377ccfb5df0c0547bd9395f7fd7613827de365d994948
|
||||||
@ -495,7 +495,7 @@ F ext/wasm/batch-runner.html cf1a410c92bad50fcec2ddc71390b4e9df63a6ea1bef12a5163
|
|||||||
F ext/wasm/batch-runner.js 5bae81684728b6be157d1f92b39824153f0fd019345b39f2ab8930f7ee2a57d8
|
F ext/wasm/batch-runner.js 5bae81684728b6be157d1f92b39824153f0fd019345b39f2ab8930f7ee2a57d8
|
||||||
F ext/wasm/common/SqliteTestUtil.js 647bf014bd30bdd870a7e9001e251d12fc1c9ec9ce176a1004b838a4b33c5c05
|
F ext/wasm/common/SqliteTestUtil.js 647bf014bd30bdd870a7e9001e251d12fc1c9ec9ce176a1004b838a4b33c5c05
|
||||||
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
||||||
F ext/wasm/common/testing.css bd6b23c4666be765139c1e50569cac301d949d5e251f7ad442376995ec5aa39a
|
F ext/wasm/common/testing.css 12bd88c69eea1b61649ad9add3ff24f0fbc3b79a7616d74ab3997b7271cd8482
|
||||||
F ext/wasm/common/whwasmutil.js bc8522a071f4754af7b50f53807b95f691d2f9e44fc3b3e8c65dff6ef2485c0d
|
F ext/wasm/common/whwasmutil.js bc8522a071f4754af7b50f53807b95f691d2f9e44fc3b3e8c65dff6ef2485c0d
|
||||||
F ext/wasm/demo-123-worker.html e50b51dc7271b9d3cc830cb7c2fba294d622f56b7acb199f7257d11195a63d49
|
F ext/wasm/demo-123-worker.html e50b51dc7271b9d3cc830cb7c2fba294d622f56b7acb199f7257d11195a63d49
|
||||||
F ext/wasm/demo-123.html 7c239c9951d1b113f9f532969ac039294cf1dcfee2b3ae0a2c1ed2b3d59f8dfa
|
F ext/wasm/demo-123.html 7c239c9951d1b113f9f532969ac039294cf1dcfee2b3ae0a2c1ed2b3d59f8dfa
|
||||||
@ -526,13 +526,13 @@ F ext/wasm/sqlite3-worker1-promiser.js 307d7837420ca6a9d3780dfc81194f1c0715637e6
|
|||||||
F ext/wasm/sqlite3-worker1.js 466e9bd39409ab03f3e00999887aaffc11e95b416e2689596e3d7f1516673fdf
|
F ext/wasm/sqlite3-worker1.js 466e9bd39409ab03f3e00999887aaffc11e95b416e2689596e3d7f1516673fdf
|
||||||
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
|
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
|
||||||
F ext/wasm/test-opfs-vfs.js 56c3d725044c668fa7910451e96c1195d25ad95825f9ac79f747a7759d1973d0
|
F ext/wasm/test-opfs-vfs.js 56c3d725044c668fa7910451e96c1195d25ad95825f9ac79f747a7759d1973d0
|
||||||
F ext/wasm/tester1-worker.html 9d24bfc5aec4d81ce00695dea2dbed262eb486f59e3ce75746de9f5b58b128a0
|
F ext/wasm/tester1-worker.html 0af7a22025ff1da72a84765d64f8f221844a57c6e6e314acf3a30f176101fd3f
|
||||||
F ext/wasm/tester1.html 13ad0dc087bdd8be1e9a4869d591d0c9915e89c8e191bce7803dc23b45cdd912
|
F ext/wasm/tester1.html fde0e0bdeaaa2c39877c749dc86a8c1c306f771c3d75b89a6289a5ed11243e9d
|
||||||
F ext/wasm/tester1.js 2f05d90d7c8f519ff6a09bb5a7a1a3ad853aea72c4e51553f2c004446465b179
|
F ext/wasm/tester1.js d25cf7615bd39ab9ab4be2f231fecf1fff1378227e695083dc35adc4fdff668e
|
||||||
F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
|
F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
|
||||||
F ext/wasm/testing-worker1-promiser.js bd788e33c1807e0a6dda9c9a9d784bd3350ca49c9dd8ae2cc8719b506b6e013e
|
F ext/wasm/testing-worker1-promiser.js bd788e33c1807e0a6dda9c9a9d784bd3350ca49c9dd8ae2cc8719b506b6e013e
|
||||||
F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
|
F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
|
||||||
F ext/wasm/testing1.js 15fc3dca6b2fc22c1458cca2cc2c484281dfc91f01c048ad4e38d5d3924ea961
|
F ext/wasm/testing1.js 2034cf6972ab1506e75e41e532ca7cd3060e194c37edab3ff65d00d8a8af8ba2
|
||||||
F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
|
F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
|
||||||
F ext/wasm/testing2.js 88f40ef3cd8201bdadd120a711c36bbf0ce56cc0eab1d5e7debb71fed7822494
|
F ext/wasm/testing2.js 88f40ef3cd8201bdadd120a711c36bbf0ce56cc0eab1d5e7debb71fed7822494
|
||||||
F ext/wasm/wasmfs.make 3cce1820006196de140f90f2da4b4ea657083fb5bfee7d125be43f7a85748c8f
|
F ext/wasm/wasmfs.make 3cce1820006196de140f90f2da4b4ea657083fb5bfee7d125be43f7a85748c8f
|
||||||
@ -2034,8 +2034,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 368fa6b25bc803ded7c1a0184615980902657879370caec22ceea42496ec0566
|
P 4ca16a304ad10fbb48f78b4384b347fe883e1a4f222f113ac981e89845c3e113
|
||||||
R b6417444abfe9dc882e90feaa0e7d85d
|
R 624f8080126a42bc3dcbc00f2cc651c0
|
||||||
U drh
|
U stephan
|
||||||
Z 6e9d8b3a258c07649344995d3cb09455
|
Z 26dc7314d65c80886c8a3b55a6ce8b4e
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
4ca16a304ad10fbb48f78b4384b347fe883e1a4f222f113ac981e89845c3e113
|
ef689e33e464829f5cbe4ca24a53d9dba59abe74d3d80a37a91b93a4eccccf2d
|
Reference in New Issue
Block a user