summaryrefslogtreecommitdiff
path: root/chromium/third_party/sqlite/src/ext/fiddle/testing2.js
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/sqlite/src/ext/fiddle/testing2.js')
-rw-r--r--chromium/third_party/sqlite/src/ext/fiddle/testing2.js235
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.");
+})();