Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/
3 */
5 // This file tests the Vacuum Manager.
7 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
8 Components.utils.import("resource://gre/modules/Services.jsm");
10 /**
11 * Loads a test component that will register as a vacuum-participant.
12 * If other participants are found they will be unregistered, to avoid conflicts
13 * with the test itself.
14 */
15 function load_test_vacuum_component()
16 {
17 const CATEGORY_NAME = "vacuum-participant";
19 do_load_manifest("vacuumParticipant.manifest");
21 // This is a lazy check, there could be more participants than just this test
22 // we just mind that the test exists though.
23 const EXPECTED_ENTRIES = ["vacuumParticipant"];
24 let catMan = Cc["@mozilla.org/categorymanager;1"].
25 getService(Ci.nsICategoryManager);
26 let found = false;
27 let entries = catMan.enumerateCategory(CATEGORY_NAME);
28 while (entries.hasMoreElements()) {
29 let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
30 print("Check if the found category entry (" + entry + ") is expected.");
31 if (EXPECTED_ENTRIES.indexOf(entry) != -1) {
32 print("Check that only one test entry exists.");
33 do_check_false(found);
34 found = true;
35 }
36 else {
37 // Temporary unregister other participants for this test.
38 catMan.deleteCategoryEntry("vacuum-participant", entry, false);
39 }
40 }
41 print("Check the test entry exists.");
42 do_check_true(found);
43 }
45 /**
46 * Sends a fake idle-daily notification to the VACUUM Manager.
47 */
48 function synthesize_idle_daily()
49 {
50 let vm = Cc["@mozilla.org/storage/vacuum;1"].getService(Ci.nsIObserver);
51 vm.observe(null, "idle-daily", null);
52 }
54 /**
55 * Returns a new nsIFile reference for a profile database.
56 * @param filename for the database, excluded the .sqlite extension.
57 */
58 function new_db_file(name)
59 {
60 let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
61 file.append(name + ".sqlite");
62 return file;
63 }
65 function run_test()
66 {
67 do_test_pending();
69 // Change initial page size. Do it immediately since it would require an
70 // additional vacuum op to do it later. As a bonus this makes the page size
71 // change test really fast since it only has to check results.
72 let conn = getDatabase(new_db_file("testVacuum"));
73 conn.executeSimpleSQL("PRAGMA page_size = 1024");
74 print("Check current page size.");
75 let stmt = conn.createStatement("PRAGMA page_size");
76 try {
77 while (stmt.executeStep()) {
78 do_check_eq(stmt.row.page_size, 1024);
79 }
80 }
81 finally {
82 stmt.finalize();
83 }
85 load_test_vacuum_component();
87 run_next_test();
88 }
90 function run_next_test()
91 {
92 if (TESTS.length == 0) {
93 Services.obs.notifyObservers(null, "test-options", "dispose");
94 do_test_finished();
95 }
96 else {
97 // Set last VACUUM to a date in the past.
98 Services.prefs.setIntPref("storage.vacuum.last.testVacuum.sqlite",
99 parseInt(Date.now() / 1000 - 31 * 86400));
100 do_execute_soon(TESTS.shift());
101 }
102 }
104 const TESTS = [
106 function test_common_vacuum()
107 {
108 print("\n*** Test that a VACUUM correctly happens and all notifications are fired.");
109 // Wait for VACUUM begin.
110 let beginVacuumReceived = false;
111 Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
112 Services.obs.removeObserver(onVacuum, aTopic);
113 beginVacuumReceived = true;
114 }, "test-begin-vacuum", false);
116 // Wait for heavy IO notifications.
117 let heavyIOTaskBeginReceived = false;
118 let heavyIOTaskEndReceived = false;
119 Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
120 if (heavyIOTaskBeginReceived && heavyIOTaskEndReceived) {
121 Services.obs.removeObserver(onVacuum, aTopic);
122 }
124 if (aData == "vacuum-begin") {
125 heavyIOTaskBeginReceived = true;
126 }
127 else if (aData == "vacuum-end") {
128 heavyIOTaskEndReceived = true;
129 }
130 }, "heavy-io-task", false);
132 // Wait for VACUUM end.
133 Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
134 Services.obs.removeObserver(onVacuum, aTopic);
135 print("Check we received onBeginVacuum");
136 do_check_true(beginVacuumReceived);
137 print("Check we received heavy-io-task notifications");
138 do_check_true(heavyIOTaskBeginReceived);
139 do_check_true(heavyIOTaskEndReceived);
140 print("Received onEndVacuum");
141 run_next_test();
142 }, "test-end-vacuum", false);
144 synthesize_idle_daily();
145 },
147 function test_skipped_if_recent_vacuum()
148 {
149 print("\n*** Test that a VACUUM is skipped if it was run recently.");
150 Services.prefs.setIntPref("storage.vacuum.last.testVacuum.sqlite",
151 parseInt(Date.now() / 1000));
153 // Wait for VACUUM begin.
154 let vacuumObserver = {
155 gotNotification: false,
156 observe: function VO_observe(aSubject, aTopic, aData) {
157 this.gotNotification = true;
158 },
159 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
160 }
161 Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
163 // Check after a couple seconds that no VACUUM has been run.
164 do_timeout(2000, function () {
165 print("Check VACUUM did not run.");
166 do_check_false(vacuumObserver.gotNotification);
167 Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
168 run_next_test();
169 });
171 synthesize_idle_daily();
172 },
174 function test_page_size_change()
175 {
176 print("\n*** Test that a VACUUM changes page_size");
178 // We did setup the database with a small page size, the previous vacuum
179 // should have updated it.
180 print("Check that page size was updated.");
181 let conn = getDatabase(new_db_file("testVacuum"));
182 let stmt = conn.createStatement("PRAGMA page_size");
183 try {
184 while (stmt.executeStep()) {
185 do_check_eq(stmt.row.page_size, conn.defaultPageSize);
186 }
187 }
188 finally {
189 stmt.finalize();
190 }
192 run_next_test();
193 },
195 function test_skipped_optout_vacuum()
196 {
197 print("\n*** Test that a VACUUM is skipped if the participant wants to opt-out.");
198 Services.obs.notifyObservers(null, "test-options", "opt-out");
200 // Wait for VACUUM begin.
201 let vacuumObserver = {
202 gotNotification: false,
203 observe: function VO_observe(aSubject, aTopic, aData) {
204 this.gotNotification = true;
205 },
206 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
207 }
208 Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
210 // Check after a couple seconds that no VACUUM has been run.
211 do_timeout(2000, function () {
212 print("Check VACUUM did not run.");
213 do_check_false(vacuumObserver.gotNotification);
214 Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
215 run_next_test();
216 });
218 synthesize_idle_daily();
219 },
221 /* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
222 function test_page_size_change_with_wal()
223 {
224 print("\n*** Test that a VACUUM changes page_size with WAL mode");
225 Services.obs.notifyObservers(null, "test-options", "wal");
227 // Set a small page size.
228 let conn = getDatabase(new_db_file("testVacuum2"));
229 conn.executeSimpleSQL("PRAGMA page_size = 1024");
230 let stmt = conn.createStatement("PRAGMA page_size");
231 try {
232 while (stmt.executeStep()) {
233 do_check_eq(stmt.row.page_size, 1024);
234 }
235 }
236 finally {
237 stmt.finalize();
238 }
240 // Use WAL journal mode.
241 conn.executeSimpleSQL("PRAGMA journal_mode = WAL");
242 stmt = conn.createStatement("PRAGMA journal_mode");
243 try {
244 while (stmt.executeStep()) {
245 do_check_eq(stmt.row.journal_mode, "wal");
246 }
247 }
248 finally {
249 stmt.finalize();
250 }
252 // Wait for VACUUM end.
253 let vacuumObserver = {
254 observe: function VO_observe(aSubject, aTopic, aData) {
255 Services.obs.removeObserver(this, aTopic);
256 print("Check page size has been updated.");
257 let stmt = conn.createStatement("PRAGMA page_size");
258 try {
259 while (stmt.executeStep()) {
260 do_check_eq(stmt.row.page_size, Ci.mozIStorageConnection.DEFAULT_PAGE_SIZE);
261 }
262 }
263 finally {
264 stmt.finalize();
265 }
267 print("Check journal mode has been restored.");
268 stmt = conn.createStatement("PRAGMA journal_mode");
269 try {
270 while (stmt.executeStep()) {
271 do_check_eq(stmt.row.journal_mode, "wal");
272 }
273 }
274 finally {
275 stmt.finalize();
276 }
278 run_next_test();
279 },
280 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
281 }
282 Services.obs.addObserver(vacuumObserver, "test-end-vacuum", false);
284 synthesize_idle_daily();
285 },
286 */
288 function test_memory_database_crash()
289 {
290 print("\n*** Test that we don't crash trying to vacuum a memory database");
291 Services.obs.notifyObservers(null, "test-options", "memory");
293 // Wait for VACUUM begin.
294 let vacuumObserver = {
295 gotNotification: false,
296 observe: function VO_observe(aSubject, aTopic, aData) {
297 this.gotNotification = true;
298 },
299 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
300 }
301 Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
303 // Check after a couple seconds that no VACUUM has been run.
304 do_timeout(2000, function () {
305 print("Check VACUUM did not run.");
306 do_check_false(vacuumObserver.gotNotification);
307 Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
308 run_next_test();
309 });
311 synthesize_idle_daily();
312 },
314 /* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
315 function test_wal_restore_fail()
316 {
317 print("\n*** Test that a failing WAL restoration notifies failure");
318 Services.obs.notifyObservers(null, "test-options", "wal-fail");
320 // Wait for VACUUM end.
321 let vacuumObserver = {
322 observe: function VO_observe(aSubject, aTopic, aData) {
323 Services.obs.removeObserver(vacuumObserver, "test-end-vacuum");
324 print("Check WAL restoration failed.");
325 do_check_false(aData);
326 run_next_test();
327 },
328 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
329 }
330 Services.obs.addObserver(vacuumObserver, "test-end-vacuum", false);
332 synthesize_idle_daily();
333 },
334 */
335 ];