michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: /* michael@0: * This file tests the CrashStore type in CrashManager.jsm. michael@0: */ michael@0: michael@0: "use strict"; michael@0: michael@0: const {classes: Cc, interfaces: Ci, utils: Cu} = Components; michael@0: michael@0: let bsp = Cu.import("resource://gre/modules/CrashManager.jsm", this); michael@0: Cu.import("resource://gre/modules/osfile.jsm", this); michael@0: Cu.import("resource://gre/modules/Task.jsm", this); michael@0: michael@0: const CrashStore = bsp.CrashStore; michael@0: michael@0: let STORE_DIR_COUNT = 0; michael@0: michael@0: function getStore() { michael@0: return Task.spawn(function* () { michael@0: let storeDir = do_get_tempdir().path; michael@0: storeDir = OS.Path.join(storeDir, "store-" + STORE_DIR_COUNT++); michael@0: michael@0: yield OS.File.makeDir(storeDir, {unixMode: OS.Constants.libc.S_IRWXU}); michael@0: michael@0: let s = new CrashStore(storeDir); michael@0: yield s.load(); michael@0: michael@0: return s; michael@0: }); michael@0: } michael@0: michael@0: function run_test() { michael@0: run_next_test(); michael@0: } michael@0: michael@0: add_task(function* test_constructor() { michael@0: let s = new CrashStore("/some/path"); michael@0: Assert.ok(s instanceof CrashStore); michael@0: }); michael@0: michael@0: add_task(function test_add_crash() { michael@0: let s = yield getStore(); michael@0: michael@0: Assert.equal(s.crashesCount, 0); michael@0: let d = new Date(Date.now() - 5000); michael@0: s.addMainProcessCrash("id1", d); michael@0: michael@0: Assert.equal(s.crashesCount, 1); michael@0: michael@0: let crashes = s.crashes; michael@0: Assert.equal(crashes.length, 1); michael@0: let c = crashes[0]; michael@0: michael@0: Assert.equal(c.id, "id1", "ID set properly."); michael@0: Assert.equal(c.crashDate.getTime(), d.getTime(), "Date set."); michael@0: michael@0: s.addMainProcessCrash("id2", new Date()); michael@0: Assert.equal(s.crashesCount, 2); michael@0: }); michael@0: michael@0: add_task(function test_save_load() { michael@0: let s = yield getStore(); michael@0: michael@0: yield s.save(); michael@0: michael@0: let d1 = new Date(); michael@0: let d2 = new Date(d1.getTime() - 10000); michael@0: s.addMainProcessCrash("id1", d1); michael@0: s.addMainProcessCrash("id2", d2); michael@0: michael@0: yield s.save(); michael@0: michael@0: yield s.load(); michael@0: Assert.ok(!s.corruptDate); michael@0: let crashes = s.crashes; michael@0: michael@0: Assert.equal(crashes.length, 2); michael@0: let c = s.getCrash("id1"); michael@0: Assert.equal(c.crashDate.getTime(), d1.getTime()); michael@0: }); michael@0: michael@0: add_task(function test_corrupt_json() { michael@0: let s = yield getStore(); michael@0: michael@0: let buffer = new TextEncoder().encode("{bad: json-file"); michael@0: yield OS.File.writeAtomic(s._storePath, buffer, {compression: "lz4"}); michael@0: michael@0: yield s.load(); michael@0: Assert.ok(s.corruptDate, "Corrupt date is defined."); michael@0: michael@0: let date = s.corruptDate; michael@0: yield s.save(); michael@0: s._data = null; michael@0: yield s.load(); michael@0: Assert.ok(s.corruptDate); michael@0: Assert.equal(date.getTime(), s.corruptDate.getTime()); michael@0: }); michael@0: michael@0: add_task(function* test_add_main_crash() { michael@0: let s = yield getStore(); michael@0: michael@0: s.addMainProcessCrash("id1", new Date()); michael@0: Assert.equal(s.crashesCount, 1); michael@0: michael@0: let c = s.crashes[0]; michael@0: Assert.ok(c.crashDate); michael@0: Assert.equal(c.type, bsp.CrashStore.prototype.TYPE_MAIN_CRASH); michael@0: Assert.ok(c.isMainProcessCrash); michael@0: michael@0: s.addMainProcessCrash("id2", new Date()); michael@0: Assert.equal(s.crashesCount, 2); michael@0: michael@0: // Duplicate. michael@0: s.addMainProcessCrash("id1", new Date()); michael@0: Assert.equal(s.crashesCount, 2); michael@0: michael@0: Assert.equal(s.mainProcessCrashes.length, 2); michael@0: }); michael@0: michael@0: add_task(function* test_add_plugin_crash() { michael@0: let s = yield getStore(); michael@0: michael@0: s.addPluginCrash("id1", new Date()); michael@0: Assert.equal(s.crashesCount, 1); michael@0: michael@0: let c = s.crashes[0]; michael@0: Assert.ok(c.crashDate); michael@0: Assert.equal(c.type, bsp.CrashStore.prototype.TYPE_PLUGIN_CRASH); michael@0: Assert.ok(c.isPluginCrash); michael@0: michael@0: s.addPluginCrash("id2", new Date()); michael@0: Assert.equal(s.crashesCount, 2); michael@0: michael@0: s.addPluginCrash("id1", new Date()); michael@0: Assert.equal(s.crashesCount, 2); michael@0: michael@0: Assert.equal(s.pluginCrashes.length, 2); michael@0: }); michael@0: michael@0: add_task(function* test_add_plugin_hang() { michael@0: let s = yield getStore(); michael@0: michael@0: s.addPluginHang("id1", new Date()); michael@0: Assert.equal(s.crashesCount, 1); michael@0: michael@0: let c = s.crashes[0]; michael@0: Assert.ok(c.crashDate); michael@0: Assert.equal(c.type, bsp.CrashStore.prototype.TYPE_PLUGIN_HANG); michael@0: Assert.ok(c.isPluginHang); michael@0: michael@0: s.addPluginHang("id2", new Date()); michael@0: Assert.equal(s.crashesCount, 2); michael@0: michael@0: s.addPluginHang("id1", new Date()); michael@0: Assert.equal(s.crashesCount, 2); michael@0: michael@0: Assert.equal(s.pluginHangs.length, 2); michael@0: }); michael@0: michael@0: add_task(function* test_add_mixed_types() { michael@0: let s = yield getStore(); michael@0: michael@0: s.addMainProcessCrash("main", new Date()); michael@0: s.addPluginCrash("pcrash", new Date()); michael@0: s.addPluginHang("phang", new Date()); michael@0: michael@0: Assert.equal(s.crashesCount, 3); michael@0: michael@0: yield s.save(); michael@0: michael@0: s._data.crashes.clear(); michael@0: Assert.equal(s.crashesCount, 0); michael@0: michael@0: yield s.load(); michael@0: michael@0: Assert.equal(s.crashesCount, 3); michael@0: michael@0: Assert.equal(s.mainProcessCrashes.length, 1); michael@0: Assert.equal(s.pluginCrashes.length, 1); michael@0: Assert.equal(s.pluginHangs.length, 1); michael@0: }); michael@0: michael@0: // Crashes added beyond the high water mark behave properly. michael@0: add_task(function* test_high_water() { michael@0: let s = yield getStore(); michael@0: michael@0: let d1 = new Date(2014, 0, 1, 0, 0, 0); michael@0: let d2 = new Date(2014, 0, 2, 0, 0, 0); michael@0: michael@0: for (let i = 0; i < s.HIGH_WATER_DAILY_THRESHOLD + 1; i++) { michael@0: s.addMainProcessCrash("m1" + i, d1); michael@0: s.addMainProcessCrash("m2" + i, d2); michael@0: s.addPluginCrash("pc1" + i, d1); michael@0: s.addPluginCrash("pc2" + i, d2); michael@0: s.addPluginHang("ph1" + i, d1); michael@0: s.addPluginHang("ph2" + i, d2); michael@0: } michael@0: michael@0: // We preserve main process crashes. Plugin crashes and hangs beyond should michael@0: // be discarded. michael@0: Assert.equal(s.crashesCount, 6 * s.HIGH_WATER_DAILY_THRESHOLD + 2); michael@0: Assert.equal(s.mainProcessCrashes.length, 2 * s.HIGH_WATER_DAILY_THRESHOLD + 2); michael@0: Assert.equal(s.pluginCrashes.length, 2 * s.HIGH_WATER_DAILY_THRESHOLD); michael@0: Assert.equal(s.pluginHangs.length, 2 * s.HIGH_WATER_DAILY_THRESHOLD); michael@0: michael@0: // But raw counts should be preserved. michael@0: let day1 = bsp.dateToDays(d1); michael@0: let day2 = bsp.dateToDays(d2); michael@0: Assert.ok(s._countsByDay.has(day1)); michael@0: Assert.ok(s._countsByDay.has(day2)); michael@0: Assert.equal(s._countsByDay.get(day1).get(s.TYPE_MAIN_CRASH), michael@0: s.HIGH_WATER_DAILY_THRESHOLD + 1); michael@0: Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_CRASH), michael@0: s.HIGH_WATER_DAILY_THRESHOLD + 1); michael@0: Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_HANG), michael@0: s.HIGH_WATER_DAILY_THRESHOLD + 1); michael@0: michael@0: yield s.save(); michael@0: yield s.load(); michael@0: michael@0: Assert.ok(s._countsByDay.has(day1)); michael@0: Assert.ok(s._countsByDay.has(day2)); michael@0: Assert.equal(s._countsByDay.get(day1).get(s.TYPE_MAIN_CRASH), michael@0: s.HIGH_WATER_DAILY_THRESHOLD + 1); michael@0: Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_CRASH), michael@0: s.HIGH_WATER_DAILY_THRESHOLD + 1); michael@0: Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_HANG), michael@0: s.HIGH_WATER_DAILY_THRESHOLD + 1); michael@0: });