|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 /* |
|
5 * This file tests the CrashStore type in CrashManager.jsm. |
|
6 */ |
|
7 |
|
8 "use strict"; |
|
9 |
|
10 const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
|
11 |
|
12 let bsp = Cu.import("resource://gre/modules/CrashManager.jsm", this); |
|
13 Cu.import("resource://gre/modules/osfile.jsm", this); |
|
14 Cu.import("resource://gre/modules/Task.jsm", this); |
|
15 |
|
16 const CrashStore = bsp.CrashStore; |
|
17 |
|
18 let STORE_DIR_COUNT = 0; |
|
19 |
|
20 function getStore() { |
|
21 return Task.spawn(function* () { |
|
22 let storeDir = do_get_tempdir().path; |
|
23 storeDir = OS.Path.join(storeDir, "store-" + STORE_DIR_COUNT++); |
|
24 |
|
25 yield OS.File.makeDir(storeDir, {unixMode: OS.Constants.libc.S_IRWXU}); |
|
26 |
|
27 let s = new CrashStore(storeDir); |
|
28 yield s.load(); |
|
29 |
|
30 return s; |
|
31 }); |
|
32 } |
|
33 |
|
34 function run_test() { |
|
35 run_next_test(); |
|
36 } |
|
37 |
|
38 add_task(function* test_constructor() { |
|
39 let s = new CrashStore("/some/path"); |
|
40 Assert.ok(s instanceof CrashStore); |
|
41 }); |
|
42 |
|
43 add_task(function test_add_crash() { |
|
44 let s = yield getStore(); |
|
45 |
|
46 Assert.equal(s.crashesCount, 0); |
|
47 let d = new Date(Date.now() - 5000); |
|
48 s.addMainProcessCrash("id1", d); |
|
49 |
|
50 Assert.equal(s.crashesCount, 1); |
|
51 |
|
52 let crashes = s.crashes; |
|
53 Assert.equal(crashes.length, 1); |
|
54 let c = crashes[0]; |
|
55 |
|
56 Assert.equal(c.id, "id1", "ID set properly."); |
|
57 Assert.equal(c.crashDate.getTime(), d.getTime(), "Date set."); |
|
58 |
|
59 s.addMainProcessCrash("id2", new Date()); |
|
60 Assert.equal(s.crashesCount, 2); |
|
61 }); |
|
62 |
|
63 add_task(function test_save_load() { |
|
64 let s = yield getStore(); |
|
65 |
|
66 yield s.save(); |
|
67 |
|
68 let d1 = new Date(); |
|
69 let d2 = new Date(d1.getTime() - 10000); |
|
70 s.addMainProcessCrash("id1", d1); |
|
71 s.addMainProcessCrash("id2", d2); |
|
72 |
|
73 yield s.save(); |
|
74 |
|
75 yield s.load(); |
|
76 Assert.ok(!s.corruptDate); |
|
77 let crashes = s.crashes; |
|
78 |
|
79 Assert.equal(crashes.length, 2); |
|
80 let c = s.getCrash("id1"); |
|
81 Assert.equal(c.crashDate.getTime(), d1.getTime()); |
|
82 }); |
|
83 |
|
84 add_task(function test_corrupt_json() { |
|
85 let s = yield getStore(); |
|
86 |
|
87 let buffer = new TextEncoder().encode("{bad: json-file"); |
|
88 yield OS.File.writeAtomic(s._storePath, buffer, {compression: "lz4"}); |
|
89 |
|
90 yield s.load(); |
|
91 Assert.ok(s.corruptDate, "Corrupt date is defined."); |
|
92 |
|
93 let date = s.corruptDate; |
|
94 yield s.save(); |
|
95 s._data = null; |
|
96 yield s.load(); |
|
97 Assert.ok(s.corruptDate); |
|
98 Assert.equal(date.getTime(), s.corruptDate.getTime()); |
|
99 }); |
|
100 |
|
101 add_task(function* test_add_main_crash() { |
|
102 let s = yield getStore(); |
|
103 |
|
104 s.addMainProcessCrash("id1", new Date()); |
|
105 Assert.equal(s.crashesCount, 1); |
|
106 |
|
107 let c = s.crashes[0]; |
|
108 Assert.ok(c.crashDate); |
|
109 Assert.equal(c.type, bsp.CrashStore.prototype.TYPE_MAIN_CRASH); |
|
110 Assert.ok(c.isMainProcessCrash); |
|
111 |
|
112 s.addMainProcessCrash("id2", new Date()); |
|
113 Assert.equal(s.crashesCount, 2); |
|
114 |
|
115 // Duplicate. |
|
116 s.addMainProcessCrash("id1", new Date()); |
|
117 Assert.equal(s.crashesCount, 2); |
|
118 |
|
119 Assert.equal(s.mainProcessCrashes.length, 2); |
|
120 }); |
|
121 |
|
122 add_task(function* test_add_plugin_crash() { |
|
123 let s = yield getStore(); |
|
124 |
|
125 s.addPluginCrash("id1", new Date()); |
|
126 Assert.equal(s.crashesCount, 1); |
|
127 |
|
128 let c = s.crashes[0]; |
|
129 Assert.ok(c.crashDate); |
|
130 Assert.equal(c.type, bsp.CrashStore.prototype.TYPE_PLUGIN_CRASH); |
|
131 Assert.ok(c.isPluginCrash); |
|
132 |
|
133 s.addPluginCrash("id2", new Date()); |
|
134 Assert.equal(s.crashesCount, 2); |
|
135 |
|
136 s.addPluginCrash("id1", new Date()); |
|
137 Assert.equal(s.crashesCount, 2); |
|
138 |
|
139 Assert.equal(s.pluginCrashes.length, 2); |
|
140 }); |
|
141 |
|
142 add_task(function* test_add_plugin_hang() { |
|
143 let s = yield getStore(); |
|
144 |
|
145 s.addPluginHang("id1", new Date()); |
|
146 Assert.equal(s.crashesCount, 1); |
|
147 |
|
148 let c = s.crashes[0]; |
|
149 Assert.ok(c.crashDate); |
|
150 Assert.equal(c.type, bsp.CrashStore.prototype.TYPE_PLUGIN_HANG); |
|
151 Assert.ok(c.isPluginHang); |
|
152 |
|
153 s.addPluginHang("id2", new Date()); |
|
154 Assert.equal(s.crashesCount, 2); |
|
155 |
|
156 s.addPluginHang("id1", new Date()); |
|
157 Assert.equal(s.crashesCount, 2); |
|
158 |
|
159 Assert.equal(s.pluginHangs.length, 2); |
|
160 }); |
|
161 |
|
162 add_task(function* test_add_mixed_types() { |
|
163 let s = yield getStore(); |
|
164 |
|
165 s.addMainProcessCrash("main", new Date()); |
|
166 s.addPluginCrash("pcrash", new Date()); |
|
167 s.addPluginHang("phang", new Date()); |
|
168 |
|
169 Assert.equal(s.crashesCount, 3); |
|
170 |
|
171 yield s.save(); |
|
172 |
|
173 s._data.crashes.clear(); |
|
174 Assert.equal(s.crashesCount, 0); |
|
175 |
|
176 yield s.load(); |
|
177 |
|
178 Assert.equal(s.crashesCount, 3); |
|
179 |
|
180 Assert.equal(s.mainProcessCrashes.length, 1); |
|
181 Assert.equal(s.pluginCrashes.length, 1); |
|
182 Assert.equal(s.pluginHangs.length, 1); |
|
183 }); |
|
184 |
|
185 // Crashes added beyond the high water mark behave properly. |
|
186 add_task(function* test_high_water() { |
|
187 let s = yield getStore(); |
|
188 |
|
189 let d1 = new Date(2014, 0, 1, 0, 0, 0); |
|
190 let d2 = new Date(2014, 0, 2, 0, 0, 0); |
|
191 |
|
192 for (let i = 0; i < s.HIGH_WATER_DAILY_THRESHOLD + 1; i++) { |
|
193 s.addMainProcessCrash("m1" + i, d1); |
|
194 s.addMainProcessCrash("m2" + i, d2); |
|
195 s.addPluginCrash("pc1" + i, d1); |
|
196 s.addPluginCrash("pc2" + i, d2); |
|
197 s.addPluginHang("ph1" + i, d1); |
|
198 s.addPluginHang("ph2" + i, d2); |
|
199 } |
|
200 |
|
201 // We preserve main process crashes. Plugin crashes and hangs beyond should |
|
202 // be discarded. |
|
203 Assert.equal(s.crashesCount, 6 * s.HIGH_WATER_DAILY_THRESHOLD + 2); |
|
204 Assert.equal(s.mainProcessCrashes.length, 2 * s.HIGH_WATER_DAILY_THRESHOLD + 2); |
|
205 Assert.equal(s.pluginCrashes.length, 2 * s.HIGH_WATER_DAILY_THRESHOLD); |
|
206 Assert.equal(s.pluginHangs.length, 2 * s.HIGH_WATER_DAILY_THRESHOLD); |
|
207 |
|
208 // But raw counts should be preserved. |
|
209 let day1 = bsp.dateToDays(d1); |
|
210 let day2 = bsp.dateToDays(d2); |
|
211 Assert.ok(s._countsByDay.has(day1)); |
|
212 Assert.ok(s._countsByDay.has(day2)); |
|
213 Assert.equal(s._countsByDay.get(day1).get(s.TYPE_MAIN_CRASH), |
|
214 s.HIGH_WATER_DAILY_THRESHOLD + 1); |
|
215 Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_CRASH), |
|
216 s.HIGH_WATER_DAILY_THRESHOLD + 1); |
|
217 Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_HANG), |
|
218 s.HIGH_WATER_DAILY_THRESHOLD + 1); |
|
219 |
|
220 yield s.save(); |
|
221 yield s.load(); |
|
222 |
|
223 Assert.ok(s._countsByDay.has(day1)); |
|
224 Assert.ok(s._countsByDay.has(day2)); |
|
225 Assert.equal(s._countsByDay.get(day1).get(s.TYPE_MAIN_CRASH), |
|
226 s.HIGH_WATER_DAILY_THRESHOLD + 1); |
|
227 Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_CRASH), |
|
228 s.HIGH_WATER_DAILY_THRESHOLD + 1); |
|
229 Assert.equal(s._countsByDay.get(day1).get(s.TYPE_PLUGIN_HANG), |
|
230 s.HIGH_WATER_DAILY_THRESHOLD + 1); |
|
231 }); |