1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory3.xul Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,353 @@ 1.4 +<?xml version="1.0"?> 1.5 +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> 1.6 +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> 1.7 +<window title="about:memory" 1.8 + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> 1.9 + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> 1.10 + <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 1.11 + 1.12 + <!-- This file tests the saving and loading of memory reports to/from file in 1.13 + about:memory. --> 1.14 + 1.15 + <!-- test results are displayed in the html:body --> 1.16 + <body xmlns="http://www.w3.org/1999/xhtml"></body> 1.17 + 1.18 + <!-- test code goes here --> 1.19 + <script type="application/javascript"> 1.20 + <![CDATA[ 1.21 + "use strict"; 1.22 + 1.23 + const Cc = Components.classes; 1.24 + const Ci = Components.interfaces; 1.25 + let mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. 1.26 + getService(Ci.nsIMemoryReporterManager); 1.27 + 1.28 + // Hide all the real reporters; we'll restore them at the end. 1.29 + mgr.blockRegistrationAndHideExistingReporters(); 1.30 + 1.31 + // Setup a minimal number of fake reporters. 1.32 + const KB = 1024; 1.33 + const MB = KB * KB; 1.34 + const HEAP = Ci.nsIMemoryReporter.KIND_HEAP; 1.35 + const OTHER = Ci.nsIMemoryReporter.KIND_OTHER; 1.36 + const BYTES = Ci.nsIMemoryReporter.UNITS_BYTES; 1.37 + 1.38 + let fakeReporters = [ 1.39 + { collectReports: function(aCbObj, aClosure) { 1.40 + function f(aP, aK, aA, aD) { 1.41 + aCbObj.callback("", aP, aK, BYTES, aA, aD, aClosure); 1.42 + } 1.43 + f("heap-allocated", OTHER, 250 * MB, "Heap allocated."); 1.44 + f("explicit/a/b", HEAP, 50 * MB, "A b."); 1.45 + f("other/a", OTHER, 0.2 * MB, "Other a."); 1.46 + f("other/b", OTHER, 0.1 * MB, "Other b."); 1.47 + } 1.48 + } 1.49 + ]; 1.50 + 1.51 + for (let i = 0; i < fakeReporters.length; i++) { 1.52 + mgr.registerStrongReporterEvenIfBlocked(fakeReporters[i]); 1.53 + } 1.54 + 1.55 + ]]> 1.56 + </script> 1.57 + 1.58 + <iframe id="amFrame" height="400" src="about:memory"></iframe> 1.59 + 1.60 + <script type="application/javascript"> 1.61 + <![CDATA[ 1.62 + function finish() 1.63 + { 1.64 + mgr.unblockRegistrationAndRestoreOriginalReporters(); 1.65 + SimpleTest.finish(); 1.66 + } 1.67 + 1.68 + // Load the given file into the frame, then copy+paste the entire frame and 1.69 + // check that the cut text matches what we expect. 1.70 + function test(aFilename, aFilename2, aExpected, aDumpFirst, aNext) { 1.71 + let frame = document.getElementById("amFrame"); 1.72 + frame.focus(); 1.73 + 1.74 + let doc = frame.contentWindow.document; 1.75 + let verbosity = doc.getElementById("verbose"); 1.76 + verbosity.checked = true; 1.77 + 1.78 + function getFilePath(aFilename) { 1.79 + let file = Cc["@mozilla.org/file/directory_service;1"] 1.80 + .getService(Components.interfaces.nsIProperties) 1.81 + .get("CurWorkD", Components.interfaces.nsIFile); 1.82 + file.append("chrome"); 1.83 + file.append("toolkit"); 1.84 + file.append("components"); 1.85 + file.append("aboutmemory"); 1.86 + file.append("tests"); 1.87 + file.append(aFilename); 1.88 + return file.path; 1.89 + } 1.90 + 1.91 + let filePath = getFilePath(aFilename); 1.92 + 1.93 + let e = document.createEvent('Event'); 1.94 + e.initEvent('change', true, true); 1.95 + 1.96 + function check() { 1.97 + // Initialize the clipboard contents. 1.98 + SpecialPowers.clipboardCopyString("initial clipboard value"); 1.99 + 1.100 + let numFailures = 0, maxFailures = 30; 1.101 + 1.102 + // Because the file load is async, we don't know when it will finish and 1.103 + // the output will show up. So we poll. 1.104 + function copyPasteAndCheck() { 1.105 + // Copy and paste frame contents, and filter out non-deterministic 1.106 + // differences. 1.107 + synthesizeKey("A", {accelKey: true}); 1.108 + synthesizeKey("C", {accelKey: true}); 1.109 + let actual = SpecialPowers.getClipboardData("text/unicode"); 1.110 + actual = actual.replace(/\(pid \d+\)/g, "(pid NNN)"); 1.111 + 1.112 + if (actual === aExpected) { 1.113 + SimpleTest.ok(true, "Clipboard has the expected contents"); 1.114 + aNext(); 1.115 + } else { 1.116 + numFailures++; 1.117 + if (numFailures === maxFailures) { 1.118 + ok(false, "pasted text doesn't match"); 1.119 + dump("******EXPECTED******\n"); 1.120 + dump(aExpected); 1.121 + dump("*******ACTUAL*******\n"); 1.122 + dump(actual); 1.123 + dump("********************\n"); 1.124 + finish(); 1.125 + } else { 1.126 + setTimeout(copyPasteAndCheck, 100); 1.127 + } 1.128 + } 1.129 + } 1.130 + copyPasteAndCheck(); 1.131 + } 1.132 + 1.133 + if (!aFilename2) { 1.134 + function loadAndCheck() { 1.135 + let fileInput1 = 1.136 + frame.contentWindow.document.getElementById("fileInput1"); 1.137 + fileInput1.value = filePath; // this works because it's a chrome test 1.138 + 1.139 + fileInput1.dispatchEvent(e); 1.140 + check(); 1.141 + } 1.142 + 1.143 + if (aDumpFirst) { 1.144 + let dumper = Cc["@mozilla.org/memory-info-dumper;1"]. 1.145 + getService(Ci.nsIMemoryInfoDumper); 1.146 + dumper.dumpMemoryReportsToNamedFile(filePath, loadAndCheck, null); 1.147 + } else { 1.148 + loadAndCheck(); 1.149 + } 1.150 + 1.151 + } else { 1.152 + let fileInput2 = 1.153 + frame.contentWindow.document.getElementById("fileInput2"); 1.154 + fileInput2.value = filePath; // this works because it's a chrome test 1.155 + 1.156 + // Hack alert: fileInput2's onchange handler calls fileInput2.click(). 1.157 + // But we don't want that to happen, because we want to bypass the file 1.158 + // picker for the test. So we set |e.skipClick|, which causes 1.159 + // fileInput2.click() to be skipped, and dispatch the second change event 1.160 + // directly ourselves. 1.161 + 1.162 + e.skipClick = true; 1.163 + fileInput2.dispatchEvent(e); 1.164 + 1.165 + let filePath2 = getFilePath(aFilename2); 1.166 + fileInput2.value = filePath2; // this works because it's a chrome test 1.167 + 1.168 + let e2 = document.createEvent('Event'); 1.169 + e2.initEvent('change', true, true); 1.170 + fileInput2.dispatchEvent(e); 1.171 + 1.172 + check(); 1.173 + } 1.174 + } 1.175 + 1.176 + // Returns a function that chains together multiple test() calls. 1.177 + function chain(aPieces) { 1.178 + let x = aPieces.shift(); 1.179 + if (x) { 1.180 + return function() { test(x.filename, x.filename2, x.expected, x.dumpFirst, chain(aPieces)); } 1.181 + } else { 1.182 + return function() { finish(); }; 1.183 + } 1.184 + } 1.185 + 1.186 + let expectedGood = 1.187 +"\ 1.188 +Explicit-only process\n\ 1.189 +\n\ 1.190 +WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ 1.191 +Explicit Allocations\n\ 1.192 +\n\ 1.193 +100,000 B (100.0%) -- explicit\n\ 1.194 +└──100,000 B (100.0%) ── a/b\n\ 1.195 +\n\ 1.196 +Other Measurements\n\ 1.197 +\n\ 1.198 +End of Explicit-only process\n\ 1.199 +Main Process (pid NNN)\n\ 1.200 +Explicit Allocations\n\ 1.201 +\n\ 1.202 +262,144,000 B (100.0%) -- explicit\n\ 1.203 +├──209,715,200 B (80.00%) ── heap-unclassified\n\ 1.204 +└───52,428,800 B (20.00%) ── a/b\n\ 1.205 +\n\ 1.206 +Other Measurements\n\ 1.207 +\n\ 1.208 +1,024 B (100.0%) -- compartments\n\ 1.209 +└──1,024 B (100.0%) ── system/a\n\ 1.210 +\n\ 1.211 +1,024 B (100.0%) -- ghost-windows\n\ 1.212 +└──1,024 B (100.0%) ── a\n\ 1.213 +\n\ 1.214 +314,572 B (100.0%) -- other\n\ 1.215 +├──209,715 B (66.67%) ── a\n\ 1.216 +└──104,857 B (33.33%) ── b\n\ 1.217 +\n\ 1.218 +1,024 B (100.0%) -- pss\n\ 1.219 +└──1,024 B (100.0%) ── a\n\ 1.220 +\n\ 1.221 +1,024 B (100.0%) -- rss\n\ 1.222 +└──1,024 B (100.0%) ── a\n\ 1.223 +\n\ 1.224 +1,024 B (100.0%) -- size\n\ 1.225 +└──1,024 B (100.0%) ── a\n\ 1.226 +\n\ 1.227 +1,024 B (100.0%) -- swap\n\ 1.228 +└──1,024 B (100.0%) ── a\n\ 1.229 +\n\ 1.230 +262,144,000 B ── heap-allocated\n\ 1.231 +\n\ 1.232 +End of Main Process (pid NNN)\n\ 1.233 +Other-only process\n\ 1.234 +Other Measurements\n\ 1.235 +\n\ 1.236 +200,000 B (100.0%) -- a\n\ 1.237 +├──100,000 B (50.00%) ── b\n\ 1.238 +└──100,000 B (50.00%) ── c\n\ 1.239 +\n\ 1.240 +500,000 B ── heap-allocated\n\ 1.241 +\n\ 1.242 +End of Other-only process\n\ 1.243 +"; 1.244 + 1.245 + let expectedGood2 = 1.246 +"\ 1.247 +Main Process (pid NNN)\n\ 1.248 +Explicit Allocations\n\ 1.249 +\n\ 1.250 +262,144,000 B (100.0%) -- explicit\n\ 1.251 +├──209,715,200 B (80.00%) ── heap-unclassified\n\ 1.252 +└───52,428,800 B (20.00%) ── a/b\n\ 1.253 +\n\ 1.254 +Other Measurements\n\ 1.255 +\n\ 1.256 +314,572 B (100.0%) -- other\n\ 1.257 +├──209,715 B (66.67%) ── a\n\ 1.258 +└──104,857 B (33.33%) ── b\n\ 1.259 +\n\ 1.260 +262,144,000 B ── heap-allocated\n\ 1.261 +\n\ 1.262 +End of Main Process (pid NNN)\n\ 1.263 +"; 1.264 + 1.265 + // This is the output for a malformed data file. 1.266 + let expectedBad = 1.267 +"\ 1.268 +Invalid memory report(s): missing 'hasMozMallocUsableSize' property\ 1.269 +"; 1.270 + 1.271 + // This is the output for a diff. 1.272 + let expectedDiff = 1.273 +"\ 1.274 +P\n\ 1.275 +\n\ 1.276 +WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ 1.277 +Explicit Allocations\n\ 1.278 +\n\ 1.279 +-10,005 B (100.0%) -- explicit\n\ 1.280 +├──-10,000 B (99.95%) ── storage/prefixset/goog-phish-shavar\n\ 1.281 +├───────-6 B (00.06%) ── spell-check [2]\n\ 1.282 +└────────1 B (-0.01%) ── xpcom/category-manager\n\ 1.283 +\n\ 1.284 +Other Measurements\n\ 1.285 +\n\ 1.286 +3,000 B ── canvas-2d-pixel-bytes [2] [+]\n\ 1.287 + -100 B ── foobar [-]\n\ 1.288 +\n\ 1.289 +End of P\n\ 1.290 +P2 (pid NNN)\n\ 1.291 +Other Measurements\n\ 1.292 +\n\ 1.293 +11 B ── z 0xNNN\n\ 1.294 +\n\ 1.295 +End of P2 (pid NNN)\n\ 1.296 +P3\n\ 1.297 +Other Measurements\n\ 1.298 +\n\ 1.299 +-55 B ── p3 [-]\n\ 1.300 +\n\ 1.301 +End of P3\n\ 1.302 +P4\n\ 1.303 +Other Measurements\n\ 1.304 +\n\ 1.305 +66 B ── p4 [+]\n\ 1.306 +\n\ 1.307 +End of P4\n\ 1.308 +P7\n\ 1.309 +Other Measurements\n\ 1.310 +\n\ 1.311 +7 B (100.0%) -- p7\n\ 1.312 +├──4 B (57.14%) ── c [+]\n\ 1.313 +└──3 B (42.86%) ── b [+]\n\ 1.314 +\n\ 1.315 +-5 B ── p7 [-]\n\ 1.316 +\n\ 1.317 +End of P7\n\ 1.318 +P8\n\ 1.319 +Other Measurements\n\ 1.320 +\n\ 1.321 +-22 B (100.0%) -- p8\n\ 1.322 +└──-22 B (100.0%) -- a\n\ 1.323 + ├──-11 B (50.00%) -- b\n\ 1.324 + │ ├───-7 B (31.82%) -- c\n\ 1.325 + │ │ ├──-4 B (18.18%) ── e [-]\n\ 1.326 + │ │ └──-3 B (13.64%) ── d [-]\n\ 1.327 + │ ├───-5 B (22.73%) ── f [-]\n\ 1.328 + │ └────1 B (-4.55%) ── (fake child) [!]\n\ 1.329 + └──-11 B (50.00%) -- g\n\ 1.330 + ├───-7 B (31.82%) ── i [-]\n\ 1.331 + ├───-6 B (27.27%) ── h [-]\n\ 1.332 + └────2 B (-9.09%) ── (fake child) [!]\n\ 1.333 +\n\ 1.334 +End of P8\n\ 1.335 +"; 1.336 + 1.337 + let frames = [ 1.338 + // This loads a pre-existing file that is valid. 1.339 + { filename: "memory-reports-good.json", expected: expectedGood, dumpFirst: false }, 1.340 + 1.341 + // This dumps to a file and then reads it back in. 1.342 + { filename: "memory-reports-dumped.json.gz", expected: expectedGood2, dumpFirst: true }, 1.343 + 1.344 + // This loads a pre-existing file that is invalid. 1.345 + { filename: "memory-reports-bad.json", expected: expectedBad, dumpFirst: false }, 1.346 + 1.347 + // This loads a pre-existing diff file. 1.348 + { filename: "memory-reports-diff1.json", filename2: "memory-reports-diff2.json", expected: expectedDiff, dumpFirst: false } 1.349 + ]; 1.350 + 1.351 + SimpleTest.waitForFocus(chain(frames)); 1.352 + 1.353 + SimpleTest.waitForExplicitFinish(); 1.354 + ]]> 1.355 + </script> 1.356 +</window>