diff options
Diffstat (limited to 'chromium/third_party/sqlite/src/ext/fiddle/testing2.js')
-rw-r--r-- | chromium/third_party/sqlite/src/ext/fiddle/testing2.js | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/chromium/third_party/sqlite/src/ext/fiddle/testing2.js b/chromium/third_party/sqlite/src/ext/fiddle/testing2.js new file mode 100644 index 00000000000..4bb21b95f0b --- /dev/null +++ b/chromium/third_party/sqlite/src/ext/fiddle/testing2.js @@ -0,0 +1,235 @@ +/* + 2022-05-22 + + 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. + + *********************************************************************** + + A basic test script for sqlite3-worker.js. +*/ +(function(){ + const T = self.SqliteTestUtil; + const SW = new Worker("sqlite3-worker.js"); + /** Posts a worker message as {type:type, data:data}. */ + const wMsg = function(type,data){ + SW.postMessage({type, data}); + return SW; + }; + const log = console.log.bind(console); + const warn = console.warn.bind(console); + const error = console.error.bind(console); + + SW.onerror = function(event){ + error("onerror",event); + }; + + /** + A queue for callbacks which are to be run in response to async + DB commands. See the notes in runTests() for why we need + this. The event-handling plumbing of this file requires that + any DB command which includes a `messageId` property also have + a queued callback entry, as the existence of that property in + response payloads is how it knows whether or not to shift an + entry off of the queue. + */ + 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 = ()=>log("Total test count:",T.counter); + + const runOneTest = function(eventType, eventData, callback){ + T.assert(eventData && 'object'===typeof eventData); + /* ^^^ that is for the testing and messageId-related code, not + a hard requirement of all of the Worker-exposed APIs. */ + eventData.messageId = MsgHandlerQueue.push(eventType,function(ev){ + log("runOneTest",eventType,"result",ev.data); + if(callback instanceof Function){ + callback(ev); + testCount(); + } + }); + wMsg(eventType, eventData); + }; + + /** Methods which map directly to onmessage() event.type keys. + They get passed the inbound event.data. */ + const dbMsgHandler = { + open: function(ev){ + log("open result",ev.data); + }, + exec: function(ev){ + log("exec result",ev.data); + }, + export: function(ev){ + log("exec result",ev.data); + }, + error: function(ev){ + error("ERROR from the worker:",ev.data); + }, + resultRowTest1: function f(ev){ + if(undefined === f.counter) f.counter = 0; + if(ev.data) ++f.counter; + //log("exec() result row:",ev.data); + T.assert(null===ev.data || 'number' === typeof ev.data.b); + } + }; + + const runTests = function(){ + const mustNotReach = ()=>{ + throw new Error("This is not supposed to be reached."); + }; + /** + "The problem" now is that the test results are async. We + know, however, that the messages posted to the worker will + be processed in the order they are passed to it, so we can + create a queue of callbacks to handle them. The problem + with that approach is that it's not error-handling + friendly, in that an error can cause us to bypass a result + handler queue entry. We have to perform some extra + acrobatics to account for that. + */ + runOneTest('open', {filename:'testing2.sqlite3'}, function(ev){ + //log("open result",ev); + T.assert('testing2.sqlite3'===ev.data.filename) + .assert(ev.data.messageId); + }); + runOneTest('exec',{ + sql: ["create table t(a,b)", + "insert into t(a,b) values(1,2),(3,4),(5,6)" + ].join(';'), + multi: true, + resultRows: [], columnNames: [] + }, function(ev){ + ev = ev.data; + T.assert(0===ev.resultRows.length) + .assert(0===ev.columnNames.length); + }); + runOneTest('exec',{ + sql: 'select a a, b b from t order by a', + resultRows: [], columnNames: [], + }, function(ev){ + ev = ev.data; + 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.data; + T.assert(3===ev.resultRows.length) + .assert(1===ev.resultRows[0].a) + .assert(6===ev.resultRows[2].b) + }); + runOneTest('exec',{sql:'intentional_error'}, mustNotReach); + // Ensure that the message-handler queue survives ^^^ that error... + runOneTest('exec',{ + sql:'select 1', + resultRows: [], + //rowMode: 'array', // array is the default in the Worker interface + }, function(ev){ + ev = ev.data; + 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: 'delete from t where a>3'}); + runOneTest('exec',{ + sql: 'select count(a) from t', + resultRows: [] + },function(ev){ + ev = ev.data; + T.assert(1===ev.resultRows.length) + .assert(2===ev.resultRows[0][0]); + }); + runOneTest('export',{}, function(ev){ + ev = ev.data; + T.assert('string' === typeof ev.filename) + .assert(ev.buffer instanceof Uint8Array) + .assert(ev.buffer.length > 1024) + .assert('application/x-sqlite3' === ev.mimetype); + }); + + /***** close() tests must come last. *****/ + runOneTest('close',{unlink:true},function(ev){ + ev = ev.data; + T.assert('string' === typeof ev.filename); + }); + runOneTest('close',{unlink:true},function(ev){ + ev = ev.data; + T.assert(undefined === ev.filename); + }); + }; + + SW.onmessage = function(ev){ + if(!ev.data || 'object'!==typeof ev.data){ + warn("Unknown sqlite3-worker message type:",ev); + return; + } + ev = ev.data/*expecting a nested object*/; + //log("main window onmessage:",ev); + if(ev.data && ev.data.messageId){ + /* We're expecting a queued-up callback handler. */ + 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.data){ + case 'loaded': + log("Message:",ev); return; + case 'ready': + log("Message:",ev); + self.sqlite3TestModule.setStatus(null); + setTimeout(runTests, 0); + 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."); +})(); |