| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 'use strict'; |
| (function(){ |
| const T = globalThis.SqliteTestUtil; |
| const SW = new Worker("jswasm/sqlite3-worker1.js"); |
| const DbState = { |
| id: undefined |
| }; |
| const eOutput = document.querySelector('#test-output'); |
| const log = console.log.bind(console); |
| const logHtml = function(cssClass,...args){ |
| log.apply(this, args); |
| const ln = document.createElement('div'); |
| if(cssClass) ln.classList.add(cssClass); |
| ln.append(document.createTextNode(args.join(' '))); |
| eOutput.append(ln); |
| }; |
| const warn = console.warn.bind(console); |
| const error = console.error.bind(console); |
| const toss = (...args)=>{throw new Error(args.join(' '))}; |
|
|
| SW.onerror = function(event){ |
| error("onerror",event); |
| }; |
|
|
| let startTime; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const MsgHandlerQueue = { |
| queue: [], |
| id: 0, |
| push: function(type,callback){ |
| this.queue.push(callback); |
| return type + '-' + (++this.id); |
| }, |
| shift: function(){ |
| return this.queue.shift(); |
| } |
| }; |
|
|
| const testCount = ()=>{ |
| logHtml("","Total test count:",T.counter+". Total time =",(performance.now() - startTime),"ms"); |
| }; |
|
|
| const logEventResult = function(ev){ |
| const evd = ev.result; |
| logHtml(evd.errorClass ? 'error' : '', |
| "runOneTest",ev.messageId,"Worker time =", |
| (ev.workerRespondTime - ev.workerReceivedTime),"ms.", |
| "Round-trip event time =", |
| (performance.now() - ev.departureTime),"ms.", |
| (evd.errorClass ? evd.message : "") |
| ); |
| }; |
|
|
| const runOneTest = function(eventType, eventArgs, callback){ |
| T.assert(eventArgs && 'object'===typeof eventArgs); |
| |
| |
| const messageId = MsgHandlerQueue.push(eventType,function(ev){ |
| logEventResult(ev); |
| if(callback instanceof Function){ |
| callback(ev); |
| testCount(); |
| } |
| }); |
| const msg = { |
| type: eventType, |
| args: eventArgs, |
| dbId: DbState.id, |
| messageId: messageId, |
| departureTime: performance.now() |
| }; |
| log("Posting",eventType,"message to worker dbId="+(DbState.id||'default')+':',msg); |
| SW.postMessage(msg); |
| }; |
|
|
| |
| |
| const dbMsgHandler = { |
| open: function(ev){ |
| DbState.id = ev.dbId; |
| log("open result",ev); |
| }, |
| exec: function(ev){ |
| log("exec result",ev); |
| }, |
| export: function(ev){ |
| log("export result",ev); |
| }, |
| error: function(ev){ |
| error("ERROR from the worker:",ev); |
| logEventResult(ev); |
| }, |
| resultRowTest1: function f(ev){ |
| if(undefined === f.counter) f.counter = 0; |
| if(null === ev.rowNumber){ |
| |
| T.assert(undefined === ev.row) |
| .assert(Array.isArray(ev.columnNames)) |
| .assert(ev.columnNames.length); |
| }else{ |
| T.assert(ev.rowNumber > 0); |
| ++f.counter; |
| } |
| |
| T.assert(null === ev.rowNumber || 'number' === typeof ev.row.b); |
| } |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const runTests2 = function(){ |
| const mustNotReach = ()=>{ |
| throw new Error("This is not supposed to be reached."); |
| }; |
| runOneTest('exec',{ |
| sql: ["create table t(a,b);", |
| "insert into t(a,b) values(1,2),(3,4),(5,6)" |
| ], |
| lastInsertRowId: true, |
| resultRows: [], columnNames: [] |
| }, function(ev){ |
| ev = ev.result; |
| T.assert(0===ev.resultRows.length) |
| .assert(0===ev.columnNames.length) |
| .assert('bigint'===typeof ev.lastInsertRowId) |
| .assert(ev.lastInsertRowId>=3); |
| }); |
| runOneTest('exec',{ |
| sql: 'select a a, b b from t order by a', |
| resultRows: [], columnNames: [], saveSql:[] |
| }, function(ev){ |
| ev = ev.result; |
| T.assert(3===ev.resultRows.length) |
| .assert(1===ev.resultRows[0][0]) |
| .assert(6===ev.resultRows[2][1]) |
| .assert(2===ev.columnNames.length) |
| .assert('b'===ev.columnNames[1]); |
| }); |
| |
| runOneTest('exec',{ |
| sql: 'select a a, b b from t order by a', |
| resultRows: [], columnNames: [], |
| rowMode: 'object' |
| }, function(ev){ |
| ev = ev.result; |
| T.assert(3===ev.resultRows.length) |
| .assert(1===ev.resultRows[0].a) |
| .assert(6===ev.resultRows[2].b) |
| }); |
| runOneTest('exec',{sql:'intentional_error'}, mustNotReach); |
| |
| runOneTest('exec',{ |
| sql:'select 1', |
| resultRows: [], |
| |
| }, function(ev){ |
| ev = ev.result; |
| T.assert(1 === ev.resultRows.length) |
| .assert(1 === ev.resultRows[0][0]); |
| }); |
| runOneTest('exec',{ |
| sql: 'select a a, b b from t order by a', |
| callback: 'resultRowTest1', |
| rowMode: 'object' |
| }, function(ev){ |
| T.assert(3===dbMsgHandler.resultRowTest1.counter); |
| dbMsgHandler.resultRowTest1.counter = 0; |
| }); |
| runOneTest('exec',{ |
| sql:[ |
| "pragma foreign_keys=0;", |
| |
| "select a, b from t order by a desc;", |
| "select a from t;" |
| |
| |
| |
| ], |
| rowMode: 1, |
| resultRows: [] |
| },function(ev){ |
| const rows = ev.result.resultRows; |
| T.assert(3===rows.length). |
| assert(6===rows[0]); |
| }); |
| runOneTest('exec',{sql: 'delete from t where a>3'}); |
| runOneTest('exec',{ |
| sql: 'select count(a) from t', |
| resultRows: [] |
| },function(ev){ |
| ev = ev.result; |
| T.assert(1===ev.resultRows.length) |
| .assert(2===ev.resultRows[0][0]); |
| }); |
| runOneTest('export',{}, function(ev){ |
| ev = ev.result; |
| log("export result:",ev); |
| T.assert('string' === typeof ev.filename) |
| .assert(ev.byteArray instanceof Uint8Array) |
| .assert(ev.byteArray.length > 1024) |
| .assert('application/x-sqlite3' === ev.mimetype); |
| }); |
| |
| runOneTest('close',{unlink:true},function(ev){ |
| ev = ev.result; |
| T.assert('string' === typeof ev.filename); |
| }); |
| runOneTest('close',{unlink:true},function(ev){ |
| ev = ev.result; |
| T.assert(undefined === ev.filename); |
| logHtml('warning',"This is the final test."); |
| }); |
| logHtml('warning',"Finished posting tests. Waiting on async results."); |
| }; |
|
|
| const runTests = function(){ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const waitForOpen = 1, |
| simulateOpenError = 0 |
| |
| ; |
| logHtml('', |
| "Sending 'open' message and",(waitForOpen ? "" : "NOT ")+ |
| "waiting for its response before continuing."); |
| startTime = performance.now(); |
| runOneTest('open', { |
| filename:'testing2.sqlite3', |
| simulateError: simulateOpenError |
| }, function(ev){ |
| log("open result",ev); |
| T.assert('testing2.sqlite3'===ev.result.filename) |
| .assert(ev.dbId) |
| .assert(ev.messageId) |
| .assert('string' === typeof ev.result.vfs); |
| DbState.id = ev.dbId; |
| if(waitForOpen) setTimeout(runTests2, 0); |
| }); |
| if(!waitForOpen) runTests2(); |
| }; |
|
|
| SW.onmessage = function(ev){ |
| if(!ev.data || 'object'!==typeof ev.data){ |
| warn("Unknown sqlite3-worker message type:",ev); |
| return; |
| } |
| ev = ev.data; |
| |
| if(ev.result && ev.messageId){ |
| |
| const f = MsgHandlerQueue.shift(); |
| if('error'===ev.type){ |
| dbMsgHandler.error(ev); |
| return; |
| } |
| T.assert(f instanceof Function); |
| f(ev); |
| return; |
| } |
| switch(ev.type){ |
| case 'sqlite3-api': |
| switch(ev.result){ |
| case 'worker1-ready': |
| log("Message:",ev); |
| globalThis.sqlite3TestModule.setStatus(null); |
| runTests(); |
| return; |
| default: |
| warn("Unknown sqlite3-api message type:",ev); |
| return; |
| } |
| default: |
| if(dbMsgHandler.hasOwnProperty(ev.type)){ |
| try{dbMsgHandler[ev.type](ev);} |
| catch(err){ |
| error("Exception while handling db result message", |
| ev,":",err); |
| } |
| return; |
| } |
| warn("Unknown sqlite3-api message type:",ev); |
| } |
| }; |
| log("Init complete, but async init bits may still be running."); |
| log("Installing Worker into global scope SW for dev purposes."); |
| globalThis.SW = SW; |
| })(); |
|
|