diff options
Diffstat (limited to 'toolkit/components/sqlite')
8 files changed, 713 insertions, 0 deletions
diff --git a/toolkit/components/sqlite/moz.build b/toolkit/components/sqlite/moz.build new file mode 100644 index 000000000..bbe5b8b96 --- /dev/null +++ b/toolkit/components/sqlite/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini'] + +EXTRA_JS_MODULES.sqlite += [ + 'sqlite_internal.js', +] diff --git a/toolkit/components/sqlite/sqlite_internal.js b/toolkit/components/sqlite/sqlite_internal.js new file mode 100644 index 000000000..18b07ff50 --- /dev/null +++ b/toolkit/components/sqlite/sqlite_internal.js @@ -0,0 +1,323 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * This file defines an Sqlite object containing js-ctypes bindings for + * sqlite3. It should be included from a worker thread using require. + * + * It serves the following purposes: + * - opens libxul; + * - defines sqlite3 API functions; + * - defines the necessary sqlite3 types. + */ + +"use strict"; + +importScripts("resource://gre/modules/workers/require.js"); + +var SharedAll = require( + "resource://gre/modules/osfile/osfile_shared_allthreads.jsm"); + +// Open the sqlite3 library. +var path; +if (SharedAll.Constants.Sys.Name === "Android") { + path = ctypes.libraryName("sqlite3"); +} else if (SharedAll.Constants.Win) { + path = ctypes.libraryName("nss3"); +} else { + path = SharedAll.Constants.Path.libxul; +} + +var lib; +try { + lib = ctypes.open(path); +} catch (ex) { + throw new Error("Could not open system library: " + ex.message); +} + +var declareLazyFFI = SharedAll.declareLazyFFI; + +var Type = Object.create(SharedAll.Type); + +/** + * Opaque Structure |sqlite3_ptr|. + * |sqlite3_ptr| is equivalent to a void*. + */ +Type.sqlite3_ptr = Type.voidptr_t.withName("sqlite3_ptr"); + +/** + * |sqlite3_stmt_ptr| an instance of an object representing a single SQL + * statement. + * |sqlite3_stmt_ptr| is equivalent to a void*. + */ +Type.sqlite3_stmt_ptr = Type.voidptr_t.withName("sqlite3_stmt_ptr"); + +/** + * |sqlite3_destructor_ptr| a constant defining a special destructor behaviour. + * |sqlite3_destructor_ptr| is equivalent to a void*. + */ +Type.sqlite3_destructor_ptr = Type.voidptr_t.withName( + "sqlite3_destructor_ptr"); + +/** + * A C double. + */ +Type.double = new SharedAll.Type("double", ctypes.double); + +/** + * |sqlite3_int64| typedef for 64-bit integer. + */ +Type.sqlite3_int64 = Type.int64_t.withName("sqlite3_int64"); + +/** + * Sqlite3 constants. + */ +var Constants = {}; + +/** + * |SQLITE_STATIC| a special value for the destructor that is passed as an + * argument to routines like bind_blob, bind_text and bind_text16. It means that + * the content pointer is constant and will never change and does need to be + * destroyed. + */ +Constants.SQLITE_STATIC = Type.sqlite3_destructor_ptr.implementation(0); + +/** + * |SQLITE_TRANSIENT| a special value for the destructor that is passed as an + * argument to routines like bind_blob, bind_text and bind_text16. It means that + * the content will likely change in the near future and that SQLite should make + * its own private copy of the content before returning. + */ +Constants.SQLITE_TRANSIENT = Type.sqlite3_destructor_ptr.implementation(-1); + +/** + * |SQLITE_OK| + * Successful result. + */ +Constants.SQLITE_OK = 0; + +/** + * |SQLITE_ROW| + * sqlite3_step() has another row ready. + */ +Constants.SQLITE_ROW = 100; + +/** + * |SQLITE_DONE| + * sqlite3_step() has finished executing. + */ +Constants.SQLITE_DONE = 101; + +var Sqlite3 = { + Constants: Constants, + Type: Type +}; + +declareLazyFFI(Sqlite3, "open", lib, "sqlite3_open", null, + /* return*/ Type.int, + /* path*/ Type.char.in_ptr, + /* db handle*/ Type.sqlite3_ptr.out_ptr); + +declareLazyFFI(Sqlite3, "open_v2", lib, "sqlite3_open_v2", null, + /* return*/ Type.int, + /* path*/ Type.char.in_ptr, + /* db handle*/ Type.sqlite3_ptr.out_ptr, + /* flags*/ Type.int, + /* VFS*/ Type.char.in_ptr); + +declareLazyFFI(Sqlite3, "close", lib, "sqlite3_close", null, + /* return*/ Type.int, + /* db handle*/ Type.sqlite3_ptr); + +declareLazyFFI(Sqlite3, "prepare_v2", lib, "sqlite3_prepare_v2", null, + /* return*/ Type.int, + /* db handle*/ Type.sqlite3_ptr, + /* zSql*/ Type.char.in_ptr, + /* nByte*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr.out_ptr, + /* unused*/ Type.cstring.out_ptr); + +declareLazyFFI(Sqlite3, "step", lib, "sqlite3_step", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr); + +declareLazyFFI(Sqlite3, "finalize", lib, "sqlite3_finalize", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr); + +declareLazyFFI(Sqlite3, "reset", lib, "sqlite3_reset", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr); + +declareLazyFFI(Sqlite3, "column_int", lib, "sqlite3_column_int", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "column_blob", lib, "sqlite3_column_blob", null, + /* return*/ Type.voidptr_t, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "column_bytes", lib, "sqlite3_column_bytes", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "column_bytes16", lib, "sqlite3_column_bytes16", + null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "column_double", lib, "sqlite3_column_double", null, + /* return*/ Type.double, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "column_int64", lib, "sqlite3_column_int64", null, + /* return*/ Type.sqlite3_int64, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "column_text", lib, "sqlite3_column_text", null, + /* return*/ Type.cstring, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "column_text16", lib, "sqlite3_column_text16", null, + /* return*/ Type.wstring, + /* statement*/ Type.sqlite3_stmt_ptr, + /* col*/ Type.int); + +declareLazyFFI(Sqlite3, "bind_int", lib, "sqlite3_bind_int", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int, + /* value*/ Type.int); + +declareLazyFFI(Sqlite3, "bind_int64", lib, "sqlite3_bind_int64", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int, + /* value*/ Type.sqlite3_int64); + +declareLazyFFI(Sqlite3, "bind_double", lib, "sqlite3_bind_double", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int, + /* value*/ Type.double); + +declareLazyFFI(Sqlite3, "bind_null", lib, "sqlite3_bind_null", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int); + +declareLazyFFI(Sqlite3, "bind_zeroblob", lib, "sqlite3_bind_zeroblob", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int, + /* nBytes*/ Type.int); + +declareLazyFFI(Sqlite3, "bind_text", lib, "sqlite3_bind_text", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int, + /* value*/ Type.cstring, + /* nBytes*/ Type.int, + /* destructor*/ Type.sqlite3_destructor_ptr); + +declareLazyFFI(Sqlite3, "bind_text16", lib, "sqlite3_bind_text16", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int, + /* value*/ Type.wstring, + /* nBytes*/ Type.int, + /* destructor*/ Type.sqlite3_destructor_ptr); + +declareLazyFFI(Sqlite3, "bind_blob", lib, "sqlite3_bind_blob", null, + /* return*/ Type.int, + /* statement*/ Type.sqlite3_stmt_ptr, + /* index*/ Type.int, + /* value*/ Type.voidptr_t, + /* nBytes*/ Type.int, + /* destructor*/ Type.sqlite3_destructor_ptr); + +module.exports = { + get Constants() { + return Sqlite3.Constants; + }, + get Type() { + return Sqlite3.Type; + }, + get open() { + return Sqlite3.open; + }, + get open_v2() { + return Sqlite3.open_v2; + }, + get close() { + return Sqlite3.close; + }, + get prepare_v2() { + return Sqlite3.prepare_v2; + }, + get step() { + return Sqlite3.step; + }, + get finalize() { + return Sqlite3.finalize; + }, + get reset() { + return Sqlite3.reset; + }, + get column_int() { + return Sqlite3.column_int; + }, + get column_blob() { + return Sqlite3.column_blob; + }, + get column_bytes() { + return Sqlite3.column_bytes; + }, + get column_bytes16() { + return Sqlite3.column_bytes16; + }, + get column_double() { + return Sqlite3.column_double; + }, + get column_int64() { + return Sqlite3.column_int64; + }, + get column_text() { + return Sqlite3.column_text; + }, + get column_text16() { + return Sqlite3.column_text16; + }, + get bind_int() { + return Sqlite3.bind_int; + }, + get bind_int64() { + return Sqlite3.bind_int64; + }, + get bind_double() { + return Sqlite3.bind_double; + }, + get bind_null() { + return Sqlite3.bind_null; + }, + get bind_zeroblob() { + return Sqlite3.bind_zeroblob; + }, + get bind_text() { + return Sqlite3.bind_text; + }, + get bind_text16() { + return Sqlite3.bind_text16; + }, + get bind_blob() { + return Sqlite3.bind_blob; + } +}; diff --git a/toolkit/components/sqlite/tests/xpcshell/.eslintrc.js b/toolkit/components/sqlite/tests/xpcshell/.eslintrc.js new file mode 100644 index 000000000..d35787cd2 --- /dev/null +++ b/toolkit/components/sqlite/tests/xpcshell/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "../../../../../testing/xpcshell/xpcshell.eslintrc.js" + ] +}; diff --git a/toolkit/components/sqlite/tests/xpcshell/data/chrome.manifest b/toolkit/components/sqlite/tests/xpcshell/data/chrome.manifest new file mode 100644 index 000000000..92b9cf60b --- /dev/null +++ b/toolkit/components/sqlite/tests/xpcshell/data/chrome.manifest @@ -0,0 +1 @@ +content test_sqlite_internal ./ diff --git a/toolkit/components/sqlite/tests/xpcshell/data/worker_sqlite_internal.js b/toolkit/components/sqlite/tests/xpcshell/data/worker_sqlite_internal.js new file mode 100644 index 000000000..7f0b3af03 --- /dev/null +++ b/toolkit/components/sqlite/tests/xpcshell/data/worker_sqlite_internal.js @@ -0,0 +1,279 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +importScripts("worker_sqlite_shared.js", + "resource://gre/modules/workers/require.js"); + +self.onmessage = function onmessage(msg) { + try { + run_test(); + } catch (ex) { + let {message, moduleStack, moduleName, lineNumber} = ex; + let error = new Error(message, moduleName, lineNumber); + error.stack = moduleStack; + dump("Uncaught error: " + error + "\n"); + dump("Full stack: " + moduleStack + "\n"); + throw error; + } +}; + +var Sqlite; + +var SQLITE_OK; /* Successful result */ +var SQLITE_ROW; /* sqlite3_step() has another row ready */ +var SQLITE_DONE; /* sqlite3_step() has finished executing */ + +function test_init() { + do_print("Starting test_init"); + // Sqlite should be loaded. + Sqlite = require("resource://gre/modules/sqlite/sqlite_internal.js"); + do_check_neq(typeof Sqlite, "undefined"); + do_check_neq(typeof Sqlite.Constants, "undefined"); + SQLITE_OK = Sqlite.Constants.SQLITE_OK; + SQLITE_ROW = Sqlite.Constants.SQLITE_ROW; + SQLITE_DONE = Sqlite.Constants.SQLITE_DONE; +} + +/** + * Clean up the database. + * @param {sqlite3_ptr} db A pointer to the database. + */ +function cleanupDB(db) { + withQuery(db, "DROP TABLE IF EXISTS TEST;", SQLITE_DONE); +} + +/** + * Open and close sqlite3 database. + * @param {String} open A name of the sqlite3 open function to be + * used. + * @param {Array} openArgs = [] Optional arguments to open function. + * @param {Function} callback = null An optional callback to be run after the + * database is opened but before it is + * closed. + */ +function withDB(open, openArgs = [], callback = null) { + let db = Sqlite.Type.sqlite3_ptr.implementation(); + let dbPtr = db.address(); + + // Open database. + let result = Sqlite[open].apply(Sqlite, ["data/test.db", dbPtr].concat( + openArgs)); + do_check_eq(result, SQLITE_OK); + + // Drop the test table if it already exists. + cleanupDB(db); + + try { + if (callback) { + callback(db); + } + } catch (ex) { + do_check_true(false); + throw ex; + } finally { + // Drop the test table if it still exists. + cleanupDB(db); + // Close data base. + result = Sqlite.close(db); + do_check_eq(result, SQLITE_OK); + } +} + +/** + * Execute an SQL query using sqlite3 API. + * @param {sqlite3_ptr} db A pointer to the database. + * @param {String} sql A SQL query string. + * @param {Number} stepResult Expected result code after evaluating the + * SQL statement. + * @param {Function} bind An optional callback with SQL binding steps. + * @param {Function} callback An optional callback that runs after the SQL + * query completes. + */ +function withQuery(db, sql, stepResult, bind, callback) { + // Create an instance of a single SQL statement. + let sqlStmt = Sqlite.Type.sqlite3_stmt_ptr.implementation(); + let sqlStmtPtr = sqlStmt.address(); + + // Unused portion of an SQL query. + let unused = Sqlite.Type.cstring.implementation(); + let unusedPtr = unused.address(); + + // Compile an SQL statement. + let result = Sqlite.prepare_v2(db, sql, sql.length, sqlStmtPtr, unusedPtr); + do_check_eq(result, SQLITE_OK); + + try { + if (bind) { + bind(sqlStmt); + } + + // Evaluate an SQL statement. + result = Sqlite.step(sqlStmt); + do_check_eq(result, stepResult); + + if (callback) { + callback(sqlStmt); + } + } catch (ex) { + do_check_true(false); + throw ex; + } finally { + // Destroy a prepared statement object. + result = Sqlite.finalize(sqlStmt); + do_check_eq(result, SQLITE_OK); + } +} + +function test_open_close() { + do_print("Starting test_open_close"); + do_check_eq(typeof Sqlite.open, "function"); + do_check_eq(typeof Sqlite.close, "function"); + + withDB("open"); +} + +function test_open_v2_close() { + do_print("Starting test_open_v2_close"); + do_check_eq(typeof Sqlite.open_v2, "function"); + + withDB("open_v2", [0x02, null]); +} + +function createTableOnOpen(db) { + withQuery(db, "CREATE TABLE TEST(" + + "ID INT PRIMARY KEY NOT NULL," + + "FIELD1 INT," + + "FIELD2 REAL," + + "FIELD3 TEXT," + + "FIELD4 TEXT," + + "FIELD5 BLOB" + + ");", SQLITE_DONE); +} + +function test_create_table() { + do_print("Starting test_create_table"); + do_check_eq(typeof Sqlite.prepare_v2, "function"); + do_check_eq(typeof Sqlite.step, "function"); + do_check_eq(typeof Sqlite.finalize, "function"); + + withDB("open", [], createTableOnOpen); +} + +/** + * Read column values after evaluating the SQL SELECT statement. + * @param {sqlite3_stmt_ptr} sqlStmt A pointer to the SQL statement. + */ +function onSqlite3Step(sqlStmt) { + // Get an int value from a query result from the ID (column 0). + let field = Sqlite.column_int(sqlStmt, 0); + do_check_eq(field, 3); + + // Get an int value from a query result from the column 1. + field = Sqlite.column_int(sqlStmt, 1); + do_check_eq(field, 2); + // Get an int64 value from a query result from the column 1. + field = Sqlite.column_int64(sqlStmt, 1); + do_check_eq(field, 2); + + // Get a double value from a query result from the column 2. + field = Sqlite.column_double(sqlStmt, 2); + do_check_eq(field, 1.2); + + // Get a number of bytes of the value in the column 3. + let bytes = Sqlite.column_bytes(sqlStmt, 3); + do_check_eq(bytes, 4); + // Get a text(cstring) value from a query result from the column 3. + field = Sqlite.column_text(sqlStmt, 3); + do_check_eq(field.readString(), "DATA"); + + // Get a number of bytes of the UTF-16 value in the column 4. + bytes = Sqlite.column_bytes16(sqlStmt, 4); + do_check_eq(bytes, 8); + // Get a text16(wstring) value from a query result from the column 4. + field = Sqlite.column_text16(sqlStmt, 4); + do_check_eq(field.readString(), "TADA"); + + // Get a blob value from a query result from the column 5. + field = Sqlite.column_blob(sqlStmt, 5); + do_check_eq(ctypes.cast(field, + Sqlite.Type.cstring.implementation).readString(), "BLOB"); +} + +function test_insert_select() { + do_print("Starting test_insert_select"); + do_check_eq(typeof Sqlite.column_int, "function"); + do_check_eq(typeof Sqlite.column_int64, "function"); + do_check_eq(typeof Sqlite.column_double, "function"); + do_check_eq(typeof Sqlite.column_bytes, "function"); + do_check_eq(typeof Sqlite.column_text, "function"); + do_check_eq(typeof Sqlite.column_text16, "function"); + do_check_eq(typeof Sqlite.column_blob, "function"); + + function onOpen(db) { + createTableOnOpen(db); + withQuery(db, + "INSERT INTO TEST VALUES (3, 2, 1.2, \"DATA\", \"TADA\", \"BLOB\");", + SQLITE_DONE); + withQuery(db, "SELECT * FROM TEST;", SQLITE_ROW, null, onSqlite3Step); + } + + withDB("open", [], onOpen); +} + +function test_insert_bind_select() { + do_print("Starting test_insert_bind_select"); + do_check_eq(typeof Sqlite.bind_int, "function"); + do_check_eq(typeof Sqlite.bind_int64, "function"); + do_check_eq(typeof Sqlite.bind_double, "function"); + do_check_eq(typeof Sqlite.bind_text, "function"); + do_check_eq(typeof Sqlite.bind_text16, "function"); + do_check_eq(typeof Sqlite.bind_blob, "function"); + + function onBind(sqlStmt) { + // Bind an int value to the ID (column 0). + let result = Sqlite.bind_int(sqlStmt, 1, 3); + do_check_eq(result, SQLITE_OK); + + // Bind an int64 value to the FIELD1 (column 1). + result = Sqlite.bind_int64(sqlStmt, 2, 2); + do_check_eq(result, SQLITE_OK); + + // Bind a double value to the FIELD2 (column 2). + result = Sqlite.bind_double(sqlStmt, 3, 1.2); + do_check_eq(result, SQLITE_OK); + + // Destructor. + let destructor = Sqlite.Constants.SQLITE_TRANSIENT; + // Bind a text value to the FIELD3 (column 3). + result = Sqlite.bind_text(sqlStmt, 4, "DATA", 4, destructor); + do_check_eq(result, SQLITE_OK); + + // Bind a text16 value to the FIELD4 (column 4). + result = Sqlite.bind_text16(sqlStmt, 5, "TADA", 8, destructor); + do_check_eq(result, SQLITE_OK); + + // Bind a blob value to the FIELD5 (column 5). + result = Sqlite.bind_blob(sqlStmt, 6, ctypes.char.array()("BLOB"), 4, + destructor); + do_check_eq(result, SQLITE_OK); + } + + function onOpen(db) { + createTableOnOpen(db); + withQuery(db, "INSERT INTO TEST VALUES (?, ?, ?, ?, ?, ?);", SQLITE_DONE, + onBind); + withQuery(db, "SELECT * FROM TEST;", SQLITE_ROW, null, onSqlite3Step); + } + + withDB("open", [], onOpen); +} + +function run_test() { + test_init(); + test_open_close(); + test_open_v2_close(); + test_create_table(); + test_insert_select(); + test_insert_bind_select(); + do_test_complete(); +} diff --git a/toolkit/components/sqlite/tests/xpcshell/data/worker_sqlite_shared.js b/toolkit/components/sqlite/tests/xpcshell/data/worker_sqlite_shared.js new file mode 100644 index 000000000..54351a02a --- /dev/null +++ b/toolkit/components/sqlite/tests/xpcshell/data/worker_sqlite_shared.js @@ -0,0 +1,39 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function send(message) { + self.postMessage(message); +} + +function do_test_complete() { + send({kind: "do_test_complete", args: []}); +} + +function do_check_true(x) { + send({kind: "do_check_true", args: [!!x]}); + if (x) { + dump("TEST-PASS: " + x + "\n"); + } else { + throw new Error("do_check_true failed"); + } +} + +function do_check_eq(a, b) { + let result = a == b; + send({kind: "do_check_true", args: [result]}); + if (!result) { + throw new Error("do_check_eq failed " + a + " != " + b); + } +} + +function do_check_neq(a, b) { + let result = a != b; + send({kind: "do_check_true", args: [result]}); + if (!result) { + throw new Error("do_check_neq failed " + a + " == " + b); + } +} + +function do_print(x) { + dump("TEST-INFO: " + x + "\n"); +} diff --git a/toolkit/components/sqlite/tests/xpcshell/test_sqlite_internal.js b/toolkit/components/sqlite/tests/xpcshell/test_sqlite_internal.js new file mode 100644 index 000000000..725cbfaea --- /dev/null +++ b/toolkit/components/sqlite/tests/xpcshell/test_sqlite_internal.js @@ -0,0 +1,43 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +Components.utils.import("resource://gre/modules/Promise.jsm"); + +var WORKER_SOURCE_URI = + "chrome://test_sqlite_internal/content/worker_sqlite_internal.js"; +do_load_manifest("data/chrome.manifest"); + +function run_test() { + run_next_test(); +} + +add_task(function() { + let worker = new ChromeWorker(WORKER_SOURCE_URI); + let deferred = Promise.defer(); + worker.onmessage = function(event) { + let data = event.data; + switch (data.kind) { + case "do_check_true": + try { + do_check_true(data.args[0]); + } catch (ex) { + // Ignore errors + } + break; + case "do_test_complete": + deferred.resolve(); + worker.terminate(); + break; + case "do_print": + do_print(data.args[0]); + break; + } + }; + worker.onerror = function(event) { + let error = new Error(event.message, event.filename, event.lineno); + worker.terminate(); + deferred.reject(error); + }; + worker.postMessage("START"); + return deferred.promise; +}); diff --git a/toolkit/components/sqlite/tests/xpcshell/xpcshell.ini b/toolkit/components/sqlite/tests/xpcshell/xpcshell.ini new file mode 100644 index 000000000..d652dbb1d --- /dev/null +++ b/toolkit/components/sqlite/tests/xpcshell/xpcshell.ini @@ -0,0 +1,10 @@ +[DEFAULT] +head = +tail = +skip-if = toolkit == 'android' || (os == 'mac' && appname == 'thunderbird') +support-files = + data/worker_sqlite_shared.js + data/worker_sqlite_internal.js + data/chrome.manifest + +[test_sqlite_internal.js] |