1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/crashes/CrashManagerTest.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,187 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * This file provides common and shared functionality to facilitate 1.10 + * testing of the Crashes component (CrashManager.jsm). 1.11 + */ 1.12 + 1.13 +"use strict"; 1.14 + 1.15 +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; 1.16 + 1.17 +this.EXPORTED_SYMBOLS = [ 1.18 + "configureLogging", 1.19 + "getManager", 1.20 + "sleep", 1.21 + "TestingCrashManager", 1.22 +]; 1.23 + 1.24 +Cu.import("resource://gre/modules/CrashManager.jsm", this); 1.25 +Cu.import("resource://gre/modules/Log.jsm", this); 1.26 +Cu.import("resource://gre/modules/osfile.jsm", this); 1.27 +Cu.import("resource://gre/modules/Promise.jsm", this); 1.28 +Cu.import("resource://gre/modules/Task.jsm", this); 1.29 +Cu.import("resource://gre/modules/Timer.jsm", this); 1.30 + 1.31 +let loggingConfigured = false; 1.32 + 1.33 +this.configureLogging = function () { 1.34 + if (loggingConfigured) { 1.35 + return; 1.36 + } 1.37 + 1.38 + let log = Log.repository.getLogger("Crashes.CrashManager"); 1.39 + log.level = Log.Level.All; 1.40 + let appender = new Log.DumpAppender(); 1.41 + appender.level = Log.Level.All; 1.42 + log.addAppender(appender); 1.43 + loggingConfigured = true; 1.44 +}; 1.45 + 1.46 +this.sleep = function (wait) { 1.47 + let deferred = Promise.defer(); 1.48 + 1.49 + setTimeout(() => { 1.50 + deferred.resolve(); 1.51 + }, wait); 1.52 + 1.53 + return deferred.promise; 1.54 +}; 1.55 + 1.56 +this.TestingCrashManager = function (options) { 1.57 + CrashManager.call(this, options); 1.58 +} 1.59 + 1.60 +this.TestingCrashManager.prototype = { 1.61 + __proto__: CrashManager.prototype, 1.62 + 1.63 + createDummyDump: function (submitted=false, date=new Date(), hr=false) { 1.64 + let uuid = Cc["@mozilla.org/uuid-generator;1"] 1.65 + .getService(Ci.nsIUUIDGenerator) 1.66 + .generateUUID() 1.67 + .toString(); 1.68 + uuid = uuid.substring(1, uuid.length - 1); 1.69 + 1.70 + let path; 1.71 + let mode; 1.72 + if (submitted) { 1.73 + if (hr) { 1.74 + path = OS.Path.join(this._submittedDumpsDir, "bp-hr-" + uuid + ".txt"); 1.75 + } else { 1.76 + path = OS.Path.join(this._submittedDumpsDir, "bp-" + uuid + ".txt"); 1.77 + } 1.78 + mode = OS.Constants.libc.S_IRUSR | OS.Constants.libc.S_IWUSR | 1.79 + OS.Constants.libc.S_IRGRP | OS.Constants.libc.S_IROTH; 1.80 + } else { 1.81 + path = OS.Path.join(this._pendingDumpsDir, uuid + ".dmp"); 1.82 + mode = OS.Constants.libc.S_IRUSR | OS.Constants.libc.S_IWUSR; 1.83 + } 1.84 + 1.85 + return Task.spawn(function* () { 1.86 + let f = yield OS.File.open(path, {create: true}, {unixMode: mode}); 1.87 + yield f.setDates(date, date); 1.88 + yield f.close(); 1.89 + dump("Created fake crash: " + path + "\n"); 1.90 + 1.91 + return uuid; 1.92 + }); 1.93 + }, 1.94 + 1.95 + createIgnoredDumpFile: function (filename, submitted=false) { 1.96 + let path; 1.97 + if (submitted) { 1.98 + path = OS.Path.join(this._submittedDumpsDir, filename); 1.99 + } else { 1.100 + path = OS.Path.join(this._pendingDumpsDir, filename); 1.101 + } 1.102 + 1.103 + return Task.spawn(function* () { 1.104 + let mode = OS.Constants.libc.S_IRUSR | OS.Constants.libc.S_IWUSR; 1.105 + yield OS.File.open(path, {create: true}, {unixMode: mode}); 1.106 + dump ("Create ignored dump file: " + path + "\n"); 1.107 + }); 1.108 + }, 1.109 + 1.110 + createEventsFile: function (filename, type, date, content, index=0) { 1.111 + let path = OS.Path.join(this._eventsDirs[index], filename); 1.112 + 1.113 + let data = type + "\n" + 1.114 + Math.floor(date.getTime() / 1000) + "\n" + 1.115 + content; 1.116 + let encoder = new TextEncoder(); 1.117 + let array = encoder.encode(data); 1.118 + 1.119 + return Task.spawn(function* () { 1.120 + yield OS.File.writeAtomic(path, array); 1.121 + yield OS.File.setDates(path, date, date); 1.122 + }); 1.123 + }, 1.124 + 1.125 + /** 1.126 + * Overwrite event file handling to process our test file type. 1.127 + * 1.128 + * We can probably delete this once we have actual events defined. 1.129 + */ 1.130 + _handleEventFilePayload: function (store, entry, type, date, payload) { 1.131 + if (type == "test.1") { 1.132 + if (payload == "malformed") { 1.133 + return this.EVENT_FILE_ERROR_MALFORMED; 1.134 + } else if (payload == "success") { 1.135 + return this.EVENT_FILE_SUCCESS; 1.136 + } else { 1.137 + return this.EVENT_FILE_ERROR_UNKNOWN_EVENT; 1.138 + } 1.139 + } 1.140 + 1.141 + return CrashManager.prototype._handleEventFilePayload.call(this, 1.142 + store, 1.143 + entry, 1.144 + type, 1.145 + date, 1.146 + payload); 1.147 + }, 1.148 +}; 1.149 + 1.150 +let DUMMY_DIR_COUNT = 0; 1.151 + 1.152 +this.getManager = function () { 1.153 + return Task.spawn(function* () { 1.154 + const dirMode = OS.Constants.libc.S_IRWXU; 1.155 + let baseFile = OS.Constants.Path.profileDir; 1.156 + 1.157 + function makeDir(create=true) { 1.158 + return Task.spawn(function* () { 1.159 + let path = OS.Path.join(baseFile, "dummy-dir-" + DUMMY_DIR_COUNT++); 1.160 + 1.161 + if (!create) { 1.162 + return path; 1.163 + } 1.164 + 1.165 + dump("Creating directory: " + path + "\n"); 1.166 + yield OS.File.makeDir(path, {unixMode: dirMode}); 1.167 + 1.168 + return path; 1.169 + }); 1.170 + } 1.171 + 1.172 + let pendingD = yield makeDir(); 1.173 + let submittedD = yield makeDir(); 1.174 + let eventsD1 = yield makeDir(); 1.175 + let eventsD2 = yield makeDir(); 1.176 + 1.177 + // Store directory is created at run-time if needed. Ensure those code 1.178 + // paths are triggered. 1.179 + let storeD = yield makeDir(false); 1.180 + 1.181 + let m = new TestingCrashManager({ 1.182 + pendingDumpsDir: pendingD, 1.183 + submittedDumpsDir: submittedD, 1.184 + eventsDirs: [eventsD1, eventsD2], 1.185 + storeDir: storeD, 1.186 + }); 1.187 + 1.188 + return m; 1.189 + }); 1.190 +};