1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 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();
}
|