1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
/**
* Returns a Promise that resolves once a crash report has
* been submitted. This function will also test the crash
* reports extra data to see if it matches expectedExtra.
*
* @param expectedExtra (object)
* An Object whose key-value pairs will be compared
* against the key-value pairs in the extra data of the
* crash report. A test failure will occur if there is
* a mismatch.
*
* If the value of the key-value pair is "null", this will
* be interpreted as "this key should not be included in the
* extra data", and will cause a test failure if it is detected
* in the crash report.
*
* Note that this will ignore any keys that are not included
* in expectedExtra. It's possible that the crash report
* will contain other extra information that is not
* compared against.
* @returns Promise
*/
function promiseCrashReport(expectedExtra={}) {
return Task.spawn(function*() {
info("Starting wait on crash-report-status");
let [subject, ] =
yield TestUtils.topicObserved("crash-report-status", (unused, data) => {
return data == "success";
});
info("Topic observed!");
if (!(subject instanceof Ci.nsIPropertyBag2)) {
throw new Error("Subject was not a Ci.nsIPropertyBag2");
}
let remoteID = getPropertyBagValue(subject, "serverCrashID");
if (!remoteID) {
throw new Error("Report should have a server ID");
}
let file = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
file.initWithPath(Services.crashmanager._submittedDumpsDir);
file.append(remoteID + ".txt");
if (!file.exists()) {
throw new Error("Report should have been received by the server");
}
file.remove(false);
let extra = getPropertyBagValue(subject, "extra");
if (!(extra instanceof Ci.nsIPropertyBag2)) {
throw new Error("extra was not a Ci.nsIPropertyBag2");
}
info("Iterating crash report extra keys");
let enumerator = extra.enumerator;
while (enumerator.hasMoreElements()) {
let key = enumerator.getNext().QueryInterface(Ci.nsIProperty).name;
let value = extra.getPropertyAsAString(key);
if (key in expectedExtra) {
if (expectedExtra[key] == null) {
ok(false, `Got unexpected key ${key} with value ${value}`);
} else {
is(value, expectedExtra[key],
`Crash report had the right extra value for ${key}`);
}
}
}
});
}
/**
* For an nsIPropertyBag, returns the value for a given
* key.
*
* @param bag
* The nsIPropertyBag to retrieve the value from
* @param key
* The key that we want to get the value for from the
* bag
* @returns The value corresponding to the key from the bag,
* or null if the value could not be retrieved (for
* example, if no value is set at that key).
*/
function getPropertyBagValue(bag, key) {
try {
let val = bag.getProperty(key);
return val;
} catch (e) {
if (e.result != Cr.NS_ERROR_FAILURE) {
throw e;
}
}
return null;
}
/**
* Monkey patches TabCrashHandler.getDumpID to return null in order to test
* about:tabcrashed when a dump is not available.
*/
function prepareNoDump() {
let originalGetDumpID = TabCrashHandler.getDumpID;
TabCrashHandler.getDumpID = function(browser) { return null; };
registerCleanupFunction(() => {
TabCrashHandler.getDumpID = originalGetDumpID;
});
}
|