storage/test/unit/test_storage_connection.js

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:50647fb91bbc
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 // This file tests the functions of mozIStorageConnection
6
7 ////////////////////////////////////////////////////////////////////////////////
8 //// Test Functions
9
10 function asyncClone(db, readOnly) {
11 let deferred = Promise.defer();
12 db.asyncClone(readOnly, function(status, db2) {
13 if (Components.isSuccessCode(status)) {
14 deferred.resolve(db2);
15 } else {
16 deferred.reject(status);
17 }
18 });
19 return deferred.promise;
20 }
21
22 function asyncClose(db) {
23 let deferred = Promise.defer();
24 db.asyncClose(function(status) {
25 if (Components.isSuccessCode(status)) {
26 deferred.resolve();
27 } else {
28 deferred.reject(status);
29 }
30 });
31 return deferred.promise;
32 }
33
34 function openAsyncDatabase(file, options) {
35 let deferred = Promise.defer();
36 let properties;
37 if (options) {
38 properties = Cc["@mozilla.org/hash-property-bag;1"].
39 createInstance(Ci.nsIWritablePropertyBag);
40 for (let k in options) {
41 properties.setProperty(k, options[k]);
42 }
43 }
44 getService().openAsyncDatabase(file, properties, function(status, db) {
45 if (Components.isSuccessCode(status)) {
46 deferred.resolve(db.QueryInterface(Ci.mozIStorageAsyncConnection));
47 } else {
48 deferred.reject(status);
49 }
50 });
51 return deferred.promise;
52 }
53
54 function executeAsync(statement, onResult) {
55 let deferred = Promise.defer();
56 statement.executeAsync({
57 handleError: function(error) {
58 deferred.reject(error);
59 },
60 handleResult: function(result) {
61 if (onResult) {
62 onResult(result);
63 }
64 },
65 handleCompletion: function(result) {
66 deferred.resolve(result);
67 }
68 });
69 return deferred.promise;
70 }
71
72 add_task(function test_connectionReady_open()
73 {
74 // there doesn't seem to be a way for the connection to not be ready (unless
75 // we close it with mozIStorageConnection::Close(), but we don't for this).
76 // It can only fail if GetPath fails on the database file, or if we run out
77 // of memory trying to use an in-memory database
78
79 var msc = getOpenedDatabase();
80 do_check_true(msc.connectionReady);
81 });
82
83 add_task(function test_connectionReady_closed()
84 {
85 // This also tests mozIStorageConnection::Close()
86
87 var msc = getOpenedDatabase();
88 msc.close();
89 do_check_false(msc.connectionReady);
90 gDBConn = null; // this is so later tests don't start to fail.
91 });
92
93 add_task(function test_databaseFile()
94 {
95 var msc = getOpenedDatabase();
96 do_check_true(getTestDB().equals(msc.databaseFile));
97 });
98
99 add_task(function test_tableExists_not_created()
100 {
101 var msc = getOpenedDatabase();
102 do_check_false(msc.tableExists("foo"));
103 });
104
105 add_task(function test_indexExists_not_created()
106 {
107 var msc = getOpenedDatabase();
108 do_check_false(msc.indexExists("foo"));
109 });
110
111 add_task(function test_temp_tableExists_and_indexExists()
112 {
113 var msc = getOpenedDatabase();
114 msc.executeSimpleSQL("CREATE TEMP TABLE test_temp(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)");
115 do_check_true(msc.tableExists("test_temp"));
116
117 msc.executeSimpleSQL("CREATE INDEX test_temp_ind ON test_temp (name)");
118 do_check_true(msc.indexExists("test_temp_ind"));
119
120 msc.executeSimpleSQL("DROP INDEX test_temp_ind");
121 msc.executeSimpleSQL("DROP TABLE test_temp");
122 });
123
124 add_task(function test_createTable_not_created()
125 {
126 var msc = getOpenedDatabase();
127 msc.createTable("test", "id INTEGER PRIMARY KEY, name TEXT");
128 do_check_true(msc.tableExists("test"));
129 });
130
131 add_task(function test_indexExists_created()
132 {
133 var msc = getOpenedDatabase();
134 msc.executeSimpleSQL("CREATE INDEX name_ind ON test (name)");
135 do_check_true(msc.indexExists("name_ind"));
136 });
137
138 add_task(function test_createTable_already_created()
139 {
140 var msc = getOpenedDatabase();
141 do_check_true(msc.tableExists("test"));
142 try {
143 msc.createTable("test", "id INTEGER PRIMARY KEY, name TEXT");
144 do_throw("We shouldn't get here!");
145 } catch (e) {
146 do_check_eq(Cr.NS_ERROR_FAILURE, e.result);
147 }
148 });
149
150 add_task(function test_attach_createTable_tableExists_indexExists()
151 {
152 var msc = getOpenedDatabase();
153 var file = do_get_file("storage_attach.sqlite", true);
154 var msc2 = getDatabase(file);
155 msc.executeSimpleSQL("ATTACH DATABASE '" + file.path + "' AS sample");
156
157 do_check_false(msc.tableExists("sample.test"));
158 msc.createTable("sample.test", "id INTEGER PRIMARY KEY, name TEXT");
159 do_check_true(msc.tableExists("sample.test"));
160 try {
161 msc.createTable("sample.test", "id INTEGER PRIMARY KEY, name TEXT");
162 do_throw("We shouldn't get here!");
163 } catch (e if e.result == Components.results.NS_ERROR_FAILURE) {
164 // we expect to fail because this table should exist already.
165 }
166
167 do_check_false(msc.indexExists("sample.test_ind"));
168 msc.executeSimpleSQL("CREATE INDEX sample.test_ind ON test (name)");
169 do_check_true(msc.indexExists("sample.test_ind"));
170
171 msc.executeSimpleSQL("DETACH DATABASE sample");
172 msc2.close();
173 try { file.remove(false); } catch(e) { }
174 });
175
176 add_task(function test_lastInsertRowID()
177 {
178 var msc = getOpenedDatabase();
179 msc.executeSimpleSQL("INSERT INTO test (name) VALUES ('foo')");
180 do_check_eq(1, msc.lastInsertRowID);
181 });
182
183 add_task(function test_transactionInProgress_no()
184 {
185 var msc = getOpenedDatabase();
186 do_check_false(msc.transactionInProgress);
187 });
188
189 add_task(function test_transactionInProgress_yes()
190 {
191 var msc = getOpenedDatabase();
192 msc.beginTransaction();
193 do_check_true(msc.transactionInProgress);
194 msc.commitTransaction();
195 do_check_false(msc.transactionInProgress);
196
197 msc.beginTransaction();
198 do_check_true(msc.transactionInProgress);
199 msc.rollbackTransaction();
200 do_check_false(msc.transactionInProgress);
201 });
202
203 add_task(function test_commitTransaction_no_transaction()
204 {
205 var msc = getOpenedDatabase();
206 do_check_false(msc.transactionInProgress);
207 try {
208 msc.commitTransaction();
209 do_throw("We should not get here!");
210 } catch (e) {
211 do_check_eq(Cr.NS_ERROR_UNEXPECTED, e.result);
212 }
213 });
214
215 add_task(function test_rollbackTransaction_no_transaction()
216 {
217 var msc = getOpenedDatabase();
218 do_check_false(msc.transactionInProgress);
219 try {
220 msc.rollbackTransaction();
221 do_throw("We should not get here!");
222 } catch (e) {
223 do_check_eq(Cr.NS_ERROR_UNEXPECTED, e.result);
224 }
225 });
226
227 add_task(function test_get_schemaVersion_not_set()
228 {
229 do_check_eq(0, getOpenedDatabase().schemaVersion);
230 });
231
232 add_task(function test_set_schemaVersion()
233 {
234 var msc = getOpenedDatabase();
235 const version = 1;
236 msc.schemaVersion = version;
237 do_check_eq(version, msc.schemaVersion);
238 });
239
240 add_task(function test_set_schemaVersion_same()
241 {
242 var msc = getOpenedDatabase();
243 const version = 1;
244 msc.schemaVersion = version; // should still work ok
245 do_check_eq(version, msc.schemaVersion);
246 });
247
248 add_task(function test_set_schemaVersion_negative()
249 {
250 var msc = getOpenedDatabase();
251 const version = -1;
252 msc.schemaVersion = version;
253 do_check_eq(version, msc.schemaVersion);
254 });
255
256 add_task(function test_createTable(){
257 var temp = getTestDB().parent;
258 temp.append("test_db_table");
259 try {
260 var con = getService().openDatabase(temp);
261 con.createTable("a","");
262 } catch (e) {
263 if (temp.exists()) try {
264 temp.remove(false);
265 } catch (e2) {}
266 do_check_true(e.result==Cr.NS_ERROR_NOT_INITIALIZED ||
267 e.result==Cr.NS_ERROR_FAILURE);
268 } finally {
269 if (con) {
270 con.close();
271 }
272 }
273 });
274
275 add_task(function test_defaultSynchronousAtNormal()
276 {
277 var msc = getOpenedDatabase();
278 var stmt = createStatement("PRAGMA synchronous;");
279 try {
280 stmt.executeStep();
281 do_check_eq(1, stmt.getInt32(0));
282 }
283 finally {
284 stmt.reset();
285 stmt.finalize();
286 }
287 });
288
289 // must be ran before executeAsync tests
290 add_task(function test_close_does_not_spin_event_loop()
291 {
292 // We want to make sure that the event loop on the calling thread does not
293 // spin when close is called.
294 let event = {
295 ran: false,
296 run: function()
297 {
298 this.ran = true;
299 },
300 };
301
302 // Post the event before we call close, so it would run if the event loop was
303 // spun during close.
304 let thread = Cc["@mozilla.org/thread-manager;1"].
305 getService(Ci.nsIThreadManager).
306 currentThread;
307 thread.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
308
309 // Sanity check, then close the database. Afterwards, we should not have ran!
310 do_check_false(event.ran);
311 getOpenedDatabase().close();
312 do_check_false(event.ran);
313
314 // Reset gDBConn so that later tests will get a new connection object.
315 gDBConn = null;
316 });
317
318 add_task(function test_asyncClose_succeeds_with_finalized_async_statement()
319 {
320 // XXX this test isn't perfect since we can't totally control when events will
321 // run. If this paticular function fails randomly, it means we have a
322 // real bug.
323
324 // We want to make sure we create a cached async statement to make sure that
325 // when we finalize our statement, we end up finalizing the async one too so
326 // close will succeed.
327 let stmt = createStatement("SELECT * FROM test");
328 stmt.executeAsync();
329 stmt.finalize();
330
331 yield asyncClose(getOpenedDatabase());
332 // Reset gDBConn so that later tests will get a new connection object.
333 gDBConn = null;
334 });
335
336 add_task(function test_close_then_release_statement() {
337 // Testing the behavior in presence of a bad client that finalizes
338 // statements after the database has been closed (typically by
339 // letting the gc finalize the statement).
340 let db = getOpenedDatabase();
341 let stmt = createStatement("SELECT * FROM test -- test_close_then_release_statement");
342 db.close();
343 stmt.finalize(); // Finalize too late - this should not crash
344
345 // Reset gDBConn so that later tests will get a new connection object.
346 gDBConn = null;
347 });
348
349 add_task(function test_asyncClose_then_release_statement() {
350 // Testing the behavior in presence of a bad client that finalizes
351 // statements after the database has been async closed (typically by
352 // letting the gc finalize the statement).
353 let db = getOpenedDatabase();
354 let stmt = createStatement("SELECT * FROM test -- test_asyncClose_then_release_statement");
355 yield asyncClose(db);
356 stmt.finalize(); // Finalize too late - this should not crash
357
358 // Reset gDBConn so that later tests will get a new connection object.
359 gDBConn = null;
360 });
361
362 add_task(function test_close_fails_with_async_statement_ran()
363 {
364 let deferred = Promise.defer();
365 let stmt = createStatement("SELECT * FROM test");
366 stmt.executeAsync();
367 stmt.finalize();
368
369 let db = getOpenedDatabase();
370 try {
371 db.close();
372 do_throw("should have thrown");
373 }
374 catch (e) {
375 do_check_eq(e.result, Cr.NS_ERROR_UNEXPECTED);
376 }
377 finally {
378 // Clean up after ourselves.
379 db.asyncClose(function() {
380 // Reset gDBConn so that later tests will get a new connection object.
381 gDBConn = null;
382 deferred.resolve();
383 });
384 }
385 yield deferred.promise;
386 });
387
388 add_task(function test_clone_optional_param()
389 {
390 let db1 = getService().openUnsharedDatabase(getTestDB());
391 let db2 = db1.clone();
392 do_check_true(db2.connectionReady);
393
394 // A write statement should not fail here.
395 let stmt = db2.createStatement("INSERT INTO test (name) VALUES (:name)");
396 stmt.params.name = "dwitte";
397 stmt.execute();
398 stmt.finalize();
399
400 // And a read statement should succeed.
401 stmt = db2.createStatement("SELECT * FROM test");
402 do_check_true(stmt.executeStep());
403 stmt.finalize();
404
405 // Additionally check that it is a connection on the same database.
406 do_check_true(db1.databaseFile.equals(db2.databaseFile));
407
408 db1.close();
409 db2.close();
410 });
411
412 function standardAsyncTest(promisedDB, name, shouldInit = false) {
413 do_print("Performing standard async test " + name);
414
415 let adb = yield promisedDB;
416 do_check_true(adb instanceof Ci.mozIStorageAsyncConnection);
417 do_check_false(adb instanceof Ci.mozIStorageConnection);
418
419 if (shouldInit) {
420 let stmt = adb.createAsyncStatement("CREATE TABLE test(name TEXT)");
421 yield executeAsync(stmt);
422 stmt.finalize();
423 }
424
425 // Generate a name to insert and fetch back
426 name = "worker bee " + Math.random() + " (" + name + ")";
427
428 let stmt = adb.createAsyncStatement("INSERT INTO test (name) VALUES (:name)");
429 stmt.params.name = name;
430 let result = yield executeAsync(stmt);
431 do_print("Request complete");
432 stmt.finalize();
433 do_check_true(Components.isSuccessCode(result));
434 do_print("Extracting data");
435 stmt = adb.createAsyncStatement("SELECT * FROM test");
436 let found = false;
437 yield executeAsync(stmt, function(result) {
438 do_print("Data has been extracted");
439
440 for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
441 if (row.getResultByName("name") == name) {
442 found = true;
443 break;
444 }
445 }
446 });
447 do_check_true(found);
448 stmt.finalize();
449 yield asyncClose(adb);
450
451 do_print("Standard async test " + name + " complete");
452 }
453
454 add_task(function test_open_async() {
455 yield standardAsyncTest(openAsyncDatabase(getTestDB(), null), "default");
456 yield standardAsyncTest(openAsyncDatabase(getTestDB()), "no optional arg");
457 yield standardAsyncTest(openAsyncDatabase(getTestDB(),
458 {shared: false, growthIncrement: 54}), "non-default options");
459 yield standardAsyncTest(openAsyncDatabase("memory"),
460 "in-memory database", true);
461 yield standardAsyncTest(openAsyncDatabase("memory",
462 {shared: false, growthIncrement: 54}),
463 "in-memory database and options", true);
464
465 do_print("Testing async opening with bogus options 1");
466 let raised = false;
467 let adb = null;
468 try {
469 adb = yield openAsyncDatabase(getTestDB(), {shared: "forty-two"});
470 } catch (ex) {
471 raised = true;
472 } finally {
473 if (adb) {
474 yield asyncClose(adb);
475 }
476 }
477 do_check_true(raised);
478
479 do_print("Testing async opening with bogus options 2");
480 raised = false;
481 adb = null;
482 try {
483 adb = yield openAsyncDatabase(getTestDB(), {growthIncrement: "forty-two"});
484 } catch (ex) {
485 raised = true;
486 } finally {
487 if (adb) {
488 yield asyncClose(adb);
489 }
490 }
491 do_check_true(raised);
492 });
493
494
495 add_task(function test_async_open_with_shared_cache() {
496 do_print("Testing that opening with a shared cache doesn't break stuff");
497 let adb = yield openAsyncDatabase(getTestDB(), {shared: true});
498
499 let stmt = adb.createAsyncStatement("INSERT INTO test (name) VALUES (:name)");
500 stmt.params.name = "clockworker";
501 let result = yield executeAsync(stmt);
502 do_print("Request complete");
503 stmt.finalize();
504 do_check_true(Components.isSuccessCode(result));
505 do_print("Extracting data");
506 stmt = adb.createAsyncStatement("SELECT * FROM test");
507 let found = false;
508 yield executeAsync(stmt, function(result) {
509 do_print("Data has been extracted");
510
511 for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
512 if (row.getResultByName("name") == "clockworker") {
513 found = true;
514 break;
515 }
516 }
517 });
518 do_check_true(found);
519 stmt.finalize();
520 yield asyncClose(adb);
521 });
522
523 add_task(function test_clone_trivial_async()
524 {
525 let db1 = getService().openDatabase(getTestDB());
526 do_print("Opened adb1");
527 do_check_true(db1 instanceof Ci.mozIStorageAsyncConnection);
528 let adb2 = yield asyncClone(db1, true);
529 do_check_true(adb2 instanceof Ci.mozIStorageAsyncConnection);
530 do_print("Cloned to adb2");
531 db1.close();
532 do_print("Closed db1");
533 yield asyncClose(adb2);
534 });
535
536 add_task(function test_clone_no_optional_param_async()
537 {
538 "use strict";
539 do_print("Testing async cloning");
540 let adb1 = yield openAsyncDatabase(getTestDB(), null);
541 do_check_true(adb1 instanceof Ci.mozIStorageAsyncConnection);
542
543 do_print("Cloning database");
544 do_check_true(Components.isSuccessCode(result));
545
546 let adb2 = yield asyncClone(adb1);
547 do_print("Testing that the cloned db is a mozIStorageAsyncConnection " +
548 "and not a mozIStorageConnection");
549 do_check_true(adb2 instanceof Ci.mozIStorageAsyncConnection);
550 do_check_false(adb2 instanceof Ci.mozIStorageConnection);
551
552 do_print("Inserting data into source db");
553 let stmt = adb1.
554 createAsyncStatement("INSERT INTO test (name) VALUES (:name)");
555
556 stmt.params.name = "yoric";
557 let result = yield executeAsync(stmt);
558 do_print("Request complete");
559 stmt.finalize();
560 do_check_true(Components.isSuccessCode(result));
561 do_print("Extracting data from clone db");
562 stmt = adb2.createAsyncStatement("SELECT * FROM test");
563 let found = false;
564 yield executeAsync(stmt, function(result) {
565 do_print("Data has been extracted");
566
567 for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
568 if (row.getResultByName("name") == "yoric") {
569 found = true;
570 break;
571 }
572 }
573 });
574 do_check_true(found);
575 stmt.finalize();
576 do_print("Closing databases");
577 yield asyncClose(adb2);
578 do_print("First db closed");
579
580 yield asyncClose(adb1);
581 do_print("Second db closed");
582 });
583
584 add_task(function test_clone_readonly()
585 {
586 let db1 = getService().openUnsharedDatabase(getTestDB());
587 let db2 = db1.clone(true);
588 do_check_true(db2.connectionReady);
589
590 // A write statement should fail here.
591 let stmt = db2.createStatement("INSERT INTO test (name) VALUES (:name)");
592 stmt.params.name = "reed";
593 expectError(Cr.NS_ERROR_FILE_READ_ONLY, function() stmt.execute());
594 stmt.finalize();
595
596 // And a read statement should succeed.
597 stmt = db2.createStatement("SELECT * FROM test");
598 do_check_true(stmt.executeStep());
599 stmt.finalize();
600
601 db1.close();
602 db2.close();
603 });
604
605 add_task(function test_clone_shared_readonly()
606 {
607 let db1 = getService().openDatabase(getTestDB());
608 let db2 = db1.clone(true);
609 do_check_true(db2.connectionReady);
610
611 let stmt = db2.createStatement("INSERT INTO test (name) VALUES (:name)");
612 stmt.params.name = "parker";
613 // TODO currently SQLite does not actually work correctly here. The behavior
614 // we want is commented out, and the current behavior is being tested
615 // for. Our IDL comments will have to be updated when this starts to
616 // work again.
617 stmt.execute();
618 // expectError(Components.results.NS_ERROR_FILE_READ_ONLY, function() stmt.execute());
619 stmt.finalize();
620
621 // And a read statement should succeed.
622 stmt = db2.createStatement("SELECT * FROM test");
623 do_check_true(stmt.executeStep());
624 stmt.finalize();
625
626 db1.close();
627 db2.close();
628 });
629
630 add_task(function test_close_clone_fails()
631 {
632 let calls = [
633 "openDatabase",
634 "openUnsharedDatabase",
635 ];
636 calls.forEach(function(methodName) {
637 let db = getService()[methodName](getTestDB());
638 db.close();
639 expectError(Cr.NS_ERROR_NOT_INITIALIZED, function() db.clone());
640 });
641 });
642
643 add_task(function test_memory_clone_fails()
644 {
645 let db = getService().openSpecialDatabase("memory");
646 db.close();
647 expectError(Cr.NS_ERROR_NOT_INITIALIZED, function() db.clone());
648 });
649
650 add_task(function test_clone_copies_functions()
651 {
652 const FUNC_NAME = "test_func";
653 let calls = [
654 "openDatabase",
655 "openUnsharedDatabase",
656 ];
657 let functionMethods = [
658 "createFunction",
659 "createAggregateFunction",
660 ];
661 calls.forEach(function(methodName) {
662 [true, false].forEach(function(readOnly) {
663 functionMethods.forEach(function(functionMethod) {
664 let db1 = getService()[methodName](getTestDB());
665 // Create a function for db1.
666 db1[functionMethod](FUNC_NAME, 1, {
667 onFunctionCall: function() 0,
668 onStep: function() 0,
669 onFinal: function() 0,
670 });
671
672 // Clone it, and make sure the function exists still.
673 let db2 = db1.clone(readOnly);
674 // Note: this would fail if the function did not exist.
675 let stmt = db2.createStatement("SELECT " + FUNC_NAME + "(id) FROM test");
676 stmt.finalize();
677 db1.close();
678 db2.close();
679 });
680 });
681 });
682 });
683
684 add_task(function test_clone_copies_overridden_functions()
685 {
686 const FUNC_NAME = "lower";
687 function test_func() {
688 this.called = false;
689 }
690 test_func.prototype = {
691 onFunctionCall: function() {
692 this.called = true;
693 },
694 onStep: function() {
695 this.called = true;
696 },
697 onFinal: function() 0,
698 };
699
700 let calls = [
701 "openDatabase",
702 "openUnsharedDatabase",
703 ];
704 let functionMethods = [
705 "createFunction",
706 "createAggregateFunction",
707 ];
708 calls.forEach(function(methodName) {
709 [true, false].forEach(function(readOnly) {
710 functionMethods.forEach(function(functionMethod) {
711 let db1 = getService()[methodName](getTestDB());
712 // Create a function for db1.
713 let func = new test_func();
714 db1[functionMethod](FUNC_NAME, 1, func);
715 do_check_false(func.called);
716
717 // Clone it, and make sure the function gets called.
718 let db2 = db1.clone(readOnly);
719 let stmt = db2.createStatement("SELECT " + FUNC_NAME + "(id) FROM test");
720 stmt.executeStep();
721 do_check_true(func.called);
722 stmt.finalize();
723 db1.close();
724 db2.close();
725 });
726 });
727 });
728 });
729
730 add_task(function test_clone_copies_pragmas()
731 {
732 const PRAGMAS = [
733 { name: "cache_size", value: 500, copied: true },
734 { name: "temp_store", value: 2, copied: true },
735 { name: "foreign_keys", value: 1, copied: true },
736 { name: "journal_size_limit", value: 524288, copied: true },
737 { name: "synchronous", value: 2, copied: true },
738 { name: "wal_autocheckpoint", value: 16, copied: true },
739 { name: "ignore_check_constraints", value: 1, copied: false },
740 ];
741
742 let db1 = getService().openUnsharedDatabase(getTestDB());
743
744 // Sanity check initial values are different from enforced ones.
745 PRAGMAS.forEach(function (pragma) {
746 let stmt = db1.createStatement("PRAGMA " + pragma.name);
747 do_check_true(stmt.executeStep());
748 do_check_neq(pragma.value, stmt.getInt32(0));
749 stmt.finalize();
750 });
751 // Execute pragmas.
752 PRAGMAS.forEach(function (pragma) {
753 db1.executeSimpleSQL("PRAGMA " + pragma.name + " = " + pragma.value);
754 });
755
756 let db2 = db1.clone();
757 do_check_true(db2.connectionReady);
758
759 // Check cloned connection inherited pragma values.
760 PRAGMAS.forEach(function (pragma) {
761 let stmt = db2.createStatement("PRAGMA " + pragma.name);
762 do_check_true(stmt.executeStep());
763 let validate = pragma.copied ? do_check_eq : do_check_neq;
764 validate(pragma.value, stmt.getInt32(0));
765 stmt.finalize();
766 });
767
768 db1.close();
769 db2.close();
770 });
771
772 add_task(function test_readonly_clone_copies_pragmas()
773 {
774 const PRAGMAS = [
775 { name: "cache_size", value: 500, copied: true },
776 { name: "temp_store", value: 2, copied: true },
777 { name: "foreign_keys", value: 1, copied: false },
778 { name: "journal_size_limit", value: 524288, copied: false },
779 { name: "synchronous", value: 2, copied: false },
780 { name: "wal_autocheckpoint", value: 16, copied: false },
781 { name: "ignore_check_constraints", value: 1, copied: false },
782 ];
783
784 let db1 = getService().openUnsharedDatabase(getTestDB());
785
786 // Sanity check initial values are different from enforced ones.
787 PRAGMAS.forEach(function (pragma) {
788 let stmt = db1.createStatement("PRAGMA " + pragma.name);
789 do_check_true(stmt.executeStep());
790 do_check_neq(pragma.value, stmt.getInt32(0));
791 stmt.finalize();
792 });
793 // Execute pragmas.
794 PRAGMAS.forEach(function (pragma) {
795 db1.executeSimpleSQL("PRAGMA " + pragma.name + " = " + pragma.value);
796 });
797
798 let db2 = db1.clone(true);
799 do_check_true(db2.connectionReady);
800
801 // Check cloned connection inherited pragma values.
802 PRAGMAS.forEach(function (pragma) {
803 let stmt = db2.createStatement("PRAGMA " + pragma.name);
804 do_check_true(stmt.executeStep());
805 let validate = pragma.copied ? do_check_eq : do_check_neq;
806 validate(pragma.value, stmt.getInt32(0));
807 stmt.finalize();
808 });
809
810 db1.close();
811 db2.close();
812 });
813
814 add_task(function test_getInterface()
815 {
816 let db = getOpenedDatabase();
817 let target = db.QueryInterface(Ci.nsIInterfaceRequestor)
818 .getInterface(Ci.nsIEventTarget);
819 // Just check that target is non-null. Other tests will ensure that it has
820 // the correct value.
821 do_check_true(target != null);
822
823 yield asyncClose(db);
824 gDBConn = null;
825 });
826
827
828 function run_test()
829 {
830 run_next_test();
831 }

mercurial