[PATCH 2/2] Bug 833286 - added tests for improvements to atomic backup of sessionstore.js. r=yoric, ttaubert
authorYura Zenevich <yura.zenevich@gmail.com>
Tue, 30 Apr 2013 14:07:54 +0200
changeset 141359 af86d146f476d1ed69c935676c5737cc578a3def
parent 141358 f76c76faf47496accda7cc5972f23f2b417d4a61
child 141360 59ce4fbce0c2a38fcab1f2051cf25c2e2709baaf
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyoric, ttaubert
bugs833286, 100644
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
[PATCH 2/2] Bug 833286 - added tests for improvements to atomic backup of sessionstore.js. r=yoric, ttaubert --- browser/components/sessionstore/test/Makefile.in | 1 + .../test/browser_833286_atomic_backup.js | 143 ++++++++++++++++++++ 2 files changed, 144 insertions(+), 0 deletions(-) create mode 100644 browser/components/sessionstore/test/browser_833286_atomic_backup.js
browser/components/sessionstore/test/Makefile.in
browser/components/sessionstore/test/browser_833286_atomic_backup.js
--- a/browser/components/sessionstore/test/Makefile.in
+++ b/browser/components/sessionstore/test/Makefile.in
@@ -134,16 +134,17 @@ MOCHITEST_BROWSER_FILES = \
 	browser_694378.js \
 	browser_701377.js \
 	browser_705597.js \
 	browser_707862.js \
 	browser_739531.js \
 	browser_739531_sample.html \
 	browser_739805.js \
 	browser_819510_perwindowpb.js \
+	browser_833286_atomic_backup.js \
 	$(filter disabled-for-intermittent-failures--bug-766044, browser_459906_empty.html) \
 	$(filter disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html) \
 	$(filter disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html) \
 	$(NULL)
 
 # Disabled on Windows for frequent intermittent failures
 ifneq ($(OS_ARCH), WINNT)
 MOCHITEST_FILES += \
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_833286_atomic_backup.js
@@ -0,0 +1,143 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This tests are for a sessionstore.js atomic backup.
+
+let tmp = {};
+Cu.import("resource://gre/modules/osfile.jsm", tmp);
+Cu.import("resource://gre/modules/Task.jsm", tmp);
+Cu.import("resource:///modules/sessionstore/_SessionFile.jsm", tmp);
+
+const {OS, Task, _SessionFile} = tmp;
+
+const PREF_SS_INTERVAL = "browser.sessionstore.interval";
+// Full paths for sessionstore.js and sessionstore.bak.
+const path = OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.js");
+const backupPath = OS.Path.join(OS.Constants.Path.profileDir,
+  "sessionstore.bak");
+
+// A text decoder.
+let gDecoder = new TextDecoder();
+// Global variables that contain sessionstore.js and sessionstore.bak data for
+// comparison between tests.
+let gSSData;
+let gSSBakData;
+
+// waitForSaveStateComplete waits for a state write completion.
+function waitForSaveStateComplete(aSaveStateCallback) {
+  let topic = "sessionstore-state-write-complete";
+
+  function observer() {
+    Services.prefs.clearUserPref(PREF_SS_INTERVAL);
+    Services.obs.removeObserver(observer, topic);
+    executeSoon(function taskCallback() {
+      Task.spawn(aSaveStateCallback);
+    });
+  }
+
+  Services.obs.addObserver(observer, topic, false);
+}
+
+// Register next test callback and trigger state saving change.
+function nextTest(testFunc) {
+  waitForSaveStateComplete(testFunc);
+  Services.prefs.setIntPref(PREF_SS_INTERVAL, 0);
+}
+
+registerCleanupFunction(function() {
+  // Cleaning up after the test: removing the sessionstore.bak file.
+  Task.spawn(function cleanupTask() {
+    yield OS.File.remove(backupPath);
+  });
+});
+
+function test() {
+  waitForExplicitFinish();
+  nextTest(testInitialWriteNoBackup);
+}
+
+function testInitialWriteNoBackup() {
+  // Ensure that sessionstore.js is created, but not sessionstore.bak.
+  let ssExists = yield OS.File.exists(path);
+  let ssBackupExists = yield OS.File.exists(backupPath);
+  ok(ssExists, "sessionstore.js should be created.");
+  ok(!ssBackupExists, "sessionstore.bak should not have been created, yet.");
+
+  nextTest(testWriteNoBackup);
+}
+
+function testWriteNoBackup() {
+  // Ensure sessionstore.bak is not created.
+  let ssExists = yield OS.File.exists(path);
+  let ssBackupExists = yield OS.File.exists(backupPath);
+  ok(ssExists, "sessionstore.js should exist.");
+  ok(!ssBackupExists, "sessionstore.bak should not have been created, yet");
+
+  // Save sessionstore.js data to compare to the sessionstore.bak data in the
+  // next test.
+  let array = yield OS.File.read(path);
+  gSSData = gDecoder.decode(array);
+
+  // Manually trigger _SessionFile.createBackupCopy since the backup once
+  // promise is already resolved and backup would not be triggered again.
+  yield _SessionFile.createBackupCopy();
+
+  nextTest(testWriteBackup);
+}
+
+function testWriteBackup() {
+  // Ensure sessionstore.bak is finally created.
+  let ssExists = yield OS.File.exists(path);
+  let ssBackupExists = yield OS.File.exists(backupPath);
+  ok(ssExists, "sessionstore.js exists.");
+  ok(ssBackupExists, "sessionstore.bak should now be created.");
+
+  // Read sessionstore.bak data.
+  let array = yield OS.File.read(backupPath);
+  gSSBakData = gDecoder.decode(array);
+
+  // Make sure that the sessionstore.bak is identical to the last
+  // sessionstore.js.
+  is(gSSBakData, gSSData, "sessionstore.js is backed up correctly.");
+
+  // Read latest sessionstore.js.
+  array = yield OS.File.read(path);
+  gSSData = gDecoder.decode(array);
+
+  // Read sessionstore.js with _SessionFile.read.
+  let ssDataRead = yield _SessionFile.read();
+  is(ssDataRead, gSSData, "_SessionFile.read read sessionstore.js correctly.");
+
+  // Read sessionstore.js with _SessionFile.syncRead.
+  ssDataRead = _SessionFile.syncRead();
+  is(ssDataRead, gSSData,
+    "_SessionFile.syncRead read sessionstore.js correctly.");
+
+  // Remove sessionstore.js to test fallback onto sessionstore.bak.
+  yield OS.File.remove(path);
+  ssExists = yield OS.File.exists(path);
+  ok(!ssExists, "sessionstore.js should be removed now.");
+
+  // Read sessionstore.bak with _SessionFile.read.
+  ssDataRead = yield _SessionFile.read();
+  is(ssDataRead, gSSBakData,
+    "_SessionFile.read read sessionstore.bak correctly.");
+
+  // Read sessionstore.bak with _SessionFile.syncRead.
+  ssDataRead = _SessionFile.syncRead();
+  is(ssDataRead, gSSBakData,
+    "_SessionFile.syncRead read sessionstore.bak correctly.");
+  nextTest(testNoWriteBackup);
+}
+
+function testNoWriteBackup() {
+  // Ensure sessionstore.bak is backed up only once.
+
+  // Read sessionstore.bak data.
+  let array = yield OS.File.read(backupPath);
+  let ssBakData = gDecoder.decode(array);
+  // Ensure the sessionstore.bak did not change.
+  is(ssBakData, gSSBakData, "sessionstore.bak is unchanged.");
+
+  executeSoon(finish);
+}
\ No newline at end of file