|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 importScripts("worker_sqlite_shared.js", |
|
5 "resource://gre/modules/workers/require.js"); |
|
6 |
|
7 self.onmessage = function onmessage(msg) { |
|
8 try { |
|
9 run_test(); |
|
10 } catch (ex) { |
|
11 let {message, moduleStack, moduleName, lineNumber} = ex; |
|
12 let error = new Error(message, moduleName, lineNumber); |
|
13 error.stack = moduleStack; |
|
14 dump("Uncaught error: " + error + "\n"); |
|
15 dump("Full stack: " + moduleStack + "\n"); |
|
16 throw error; |
|
17 } |
|
18 }; |
|
19 |
|
20 let Sqlite; |
|
21 |
|
22 let SQLITE_OK; /* Successful result */ |
|
23 let SQLITE_ROW; /* sqlite3_step() has another row ready */ |
|
24 let SQLITE_DONE; /* sqlite3_step() has finished executing */ |
|
25 |
|
26 function test_init() { |
|
27 do_print("Starting test_init"); |
|
28 // Sqlite should be loaded. |
|
29 Sqlite = require("resource://gre/modules/sqlite/sqlite_internal.js"); |
|
30 do_check_neq(typeof Sqlite, "undefined"); |
|
31 do_check_neq(typeof Sqlite.Constants, "undefined"); |
|
32 SQLITE_OK = Sqlite.Constants.SQLITE_OK; |
|
33 SQLITE_ROW = Sqlite.Constants.SQLITE_ROW; |
|
34 SQLITE_DONE = Sqlite.Constants.SQLITE_DONE; |
|
35 } |
|
36 |
|
37 /** |
|
38 * Clean up the database. |
|
39 * @param {sqlite3_ptr} db A pointer to the database. |
|
40 */ |
|
41 function cleanupDB(db) { |
|
42 withQuery(db, "DROP TABLE IF EXISTS TEST;", SQLITE_DONE); |
|
43 } |
|
44 |
|
45 /** |
|
46 * Open and close sqlite3 database. |
|
47 * @param {String} open A name of the sqlite3 open function to be |
|
48 * used. |
|
49 * @param {Array} openArgs = [] Optional arguments to open function. |
|
50 * @param {Function} callback = null An optional callback to be run after the |
|
51 * database is opened but before it is |
|
52 * closed. |
|
53 */ |
|
54 function withDB(open, openArgs = [], callback = null) { |
|
55 let db = Sqlite.Type.sqlite3_ptr.implementation(); |
|
56 let dbPtr = db.address(); |
|
57 |
|
58 // Open database. |
|
59 let result = Sqlite[open].apply(Sqlite, ["data/test.db", dbPtr].concat( |
|
60 openArgs)); |
|
61 do_check_eq(result, SQLITE_OK); |
|
62 |
|
63 // Drop the test table if it already exists. |
|
64 cleanupDB(db); |
|
65 |
|
66 try { |
|
67 if (callback) { |
|
68 callback(db); |
|
69 } |
|
70 } catch (ex) { |
|
71 do_check_true(false); |
|
72 throw ex; |
|
73 } finally { |
|
74 // Drop the test table if it still exists. |
|
75 cleanupDB(db); |
|
76 // Close data base. |
|
77 result = Sqlite.close(db); |
|
78 do_check_eq(result, SQLITE_OK); |
|
79 } |
|
80 } |
|
81 |
|
82 /** |
|
83 * Execute an SQL query using sqlite3 API. |
|
84 * @param {sqlite3_ptr} db A pointer to the database. |
|
85 * @param {String} sql A SQL query string. |
|
86 * @param {Number} stepResult Expected result code after evaluating the |
|
87 * SQL statement. |
|
88 * @param {Function} bind An optional callback with SQL binding steps. |
|
89 * @param {Function} callback An optional callback that runs after the SQL |
|
90 * query completes. |
|
91 */ |
|
92 function withQuery(db, sql, stepResult, bind, callback) { |
|
93 // Create an instance of a single SQL statement. |
|
94 let sqlStmt = Sqlite.Type.sqlite3_stmt_ptr.implementation(); |
|
95 let sqlStmtPtr = sqlStmt.address(); |
|
96 |
|
97 // Unused portion of an SQL query. |
|
98 let unused = Sqlite.Type.cstring.implementation(); |
|
99 let unusedPtr = unused.address(); |
|
100 |
|
101 // Compile an SQL statement. |
|
102 let result = Sqlite.prepare_v2(db, sql, sql.length, sqlStmtPtr, unusedPtr); |
|
103 do_check_eq(result, SQLITE_OK); |
|
104 |
|
105 try { |
|
106 if (bind) { |
|
107 bind(sqlStmt); |
|
108 } |
|
109 |
|
110 // Evaluate an SQL statement. |
|
111 result = Sqlite.step(sqlStmt); |
|
112 do_check_eq(result, stepResult); |
|
113 |
|
114 if (callback) { |
|
115 callback(sqlStmt); |
|
116 } |
|
117 } catch (ex) { |
|
118 do_check_true(false); |
|
119 throw ex; |
|
120 } finally { |
|
121 // Destroy a prepared statement object. |
|
122 result = Sqlite.finalize(sqlStmt); |
|
123 do_check_eq(result, SQLITE_OK); |
|
124 } |
|
125 } |
|
126 |
|
127 function test_open_close() { |
|
128 do_print("Starting test_open_close"); |
|
129 do_check_eq(typeof Sqlite.open, "function"); |
|
130 do_check_eq(typeof Sqlite.close, "function"); |
|
131 |
|
132 withDB("open"); |
|
133 } |
|
134 |
|
135 function test_open_v2_close() { |
|
136 do_print("Starting test_open_v2_close"); |
|
137 do_check_eq(typeof Sqlite.open_v2, "function"); |
|
138 |
|
139 withDB("open_v2", [0x02, null]); |
|
140 } |
|
141 |
|
142 function createTableOnOpen(db) { |
|
143 withQuery(db, "CREATE TABLE TEST(" + |
|
144 "ID INT PRIMARY KEY NOT NULL," + |
|
145 "FIELD1 INT," + |
|
146 "FIELD2 REAL," + |
|
147 "FIELD3 TEXT," + |
|
148 "FIELD4 TEXT," + |
|
149 "FIELD5 BLOB" + |
|
150 ");", SQLITE_DONE); |
|
151 } |
|
152 |
|
153 function test_create_table() { |
|
154 do_print("Starting test_create_table"); |
|
155 do_check_eq(typeof Sqlite.prepare_v2, "function"); |
|
156 do_check_eq(typeof Sqlite.step, "function"); |
|
157 do_check_eq(typeof Sqlite.finalize, "function"); |
|
158 |
|
159 withDB("open", [], createTableOnOpen); |
|
160 } |
|
161 |
|
162 /** |
|
163 * Read column values after evaluating the SQL SELECT statement. |
|
164 * @param {sqlite3_stmt_ptr} sqlStmt A pointer to the SQL statement. |
|
165 */ |
|
166 function onSqlite3Step(sqlStmt) { |
|
167 // Get an int value from a query result from the ID (column 0). |
|
168 let field = Sqlite.column_int(sqlStmt, 0); |
|
169 do_check_eq(field, 3); |
|
170 |
|
171 // Get an int value from a query result from the column 1. |
|
172 field = Sqlite.column_int(sqlStmt, 1); |
|
173 do_check_eq(field, 2); |
|
174 // Get an int64 value from a query result from the column 1. |
|
175 field = Sqlite.column_int64(sqlStmt, 1); |
|
176 do_check_eq(field, 2); |
|
177 |
|
178 // Get a double value from a query result from the column 2. |
|
179 field = Sqlite.column_double(sqlStmt, 2); |
|
180 do_check_eq(field, 1.2); |
|
181 |
|
182 // Get a number of bytes of the value in the column 3. |
|
183 let bytes = Sqlite.column_bytes(sqlStmt, 3); |
|
184 do_check_eq(bytes, 4); |
|
185 // Get a text(cstring) value from a query result from the column 3. |
|
186 field = Sqlite.column_text(sqlStmt, 3); |
|
187 do_check_eq(field.readString(), "DATA"); |
|
188 |
|
189 // Get a number of bytes of the UTF-16 value in the column 4. |
|
190 bytes = Sqlite.column_bytes16(sqlStmt, 4); |
|
191 do_check_eq(bytes, 8); |
|
192 // Get a text16(wstring) value from a query result from the column 4. |
|
193 field = Sqlite.column_text16(sqlStmt, 4); |
|
194 do_check_eq(field.readString(), "TADA"); |
|
195 |
|
196 // Get a blob value from a query result from the column 5. |
|
197 field = Sqlite.column_blob(sqlStmt, 5); |
|
198 do_check_eq(ctypes.cast(field, |
|
199 Sqlite.Type.cstring.implementation).readString(), "BLOB"); |
|
200 } |
|
201 |
|
202 function test_insert_select() { |
|
203 do_print("Starting test_insert_select"); |
|
204 do_check_eq(typeof Sqlite.column_int, "function"); |
|
205 do_check_eq(typeof Sqlite.column_int64, "function"); |
|
206 do_check_eq(typeof Sqlite.column_double, "function"); |
|
207 do_check_eq(typeof Sqlite.column_bytes, "function"); |
|
208 do_check_eq(typeof Sqlite.column_text, "function"); |
|
209 do_check_eq(typeof Sqlite.column_text16, "function"); |
|
210 do_check_eq(typeof Sqlite.column_blob, "function"); |
|
211 |
|
212 function onOpen(db) { |
|
213 createTableOnOpen(db); |
|
214 withQuery(db, |
|
215 "INSERT INTO TEST VALUES (3, 2, 1.2, \"DATA\", \"TADA\", \"BLOB\");", |
|
216 SQLITE_DONE); |
|
217 withQuery(db, "SELECT * FROM TEST;", SQLITE_ROW, null, onSqlite3Step); |
|
218 } |
|
219 |
|
220 withDB("open", [], onOpen); |
|
221 } |
|
222 |
|
223 function test_insert_bind_select() { |
|
224 do_print("Starting test_insert_bind_select"); |
|
225 do_check_eq(typeof Sqlite.bind_int, "function"); |
|
226 do_check_eq(typeof Sqlite.bind_int64, "function"); |
|
227 do_check_eq(typeof Sqlite.bind_double, "function"); |
|
228 do_check_eq(typeof Sqlite.bind_text, "function"); |
|
229 do_check_eq(typeof Sqlite.bind_text16, "function"); |
|
230 do_check_eq(typeof Sqlite.bind_blob, "function"); |
|
231 |
|
232 function onBind(sqlStmt) { |
|
233 // Bind an int value to the ID (column 0). |
|
234 let result = Sqlite.bind_int(sqlStmt, 1, 3); |
|
235 do_check_eq(result, SQLITE_OK); |
|
236 |
|
237 // Bind an int64 value to the FIELD1 (column 1). |
|
238 result = Sqlite.bind_int64(sqlStmt, 2, 2); |
|
239 do_check_eq(result, SQLITE_OK); |
|
240 |
|
241 // Bind a double value to the FIELD2 (column 2). |
|
242 result = Sqlite.bind_double(sqlStmt, 3, 1.2); |
|
243 do_check_eq(result, SQLITE_OK); |
|
244 |
|
245 // Destructor. |
|
246 let destructor = Sqlite.Constants.SQLITE_TRANSIENT; |
|
247 // Bind a text value to the FIELD3 (column 3). |
|
248 result = Sqlite.bind_text(sqlStmt, 4, "DATA", 4, destructor); |
|
249 do_check_eq(result, SQLITE_OK); |
|
250 |
|
251 // Bind a text16 value to the FIELD4 (column 4). |
|
252 result = Sqlite.bind_text16(sqlStmt, 5, "TADA", 8, destructor); |
|
253 do_check_eq(result, SQLITE_OK); |
|
254 |
|
255 // Bind a blob value to the FIELD5 (column 5). |
|
256 result = Sqlite.bind_blob(sqlStmt, 6, ctypes.char.array()("BLOB"), 4, |
|
257 destructor); |
|
258 do_check_eq(result, SQLITE_OK); |
|
259 } |
|
260 |
|
261 function onOpen(db) { |
|
262 createTableOnOpen(db); |
|
263 withQuery(db, "INSERT INTO TEST VALUES (?, ?, ?, ?, ?, ?);", SQLITE_DONE, |
|
264 onBind); |
|
265 withQuery(db, "SELECT * FROM TEST;", SQLITE_ROW, null, onSqlite3Step); |
|
266 } |
|
267 |
|
268 withDB("open", [], onOpen); |
|
269 } |
|
270 |
|
271 function run_test() { |
|
272 test_init(); |
|
273 test_open_close(); |
|
274 test_open_v2_close(); |
|
275 test_create_table(); |
|
276 test_insert_select(); |
|
277 test_insert_bind_select(); |
|
278 do_test_complete(); |
|
279 } |