Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | http://creativecommons.org/publicdomain/zero/1.0/ |
michael@0 | 3 | */ |
michael@0 | 4 | /* A testcase to make sure reading late writes stacks works. */ |
michael@0 | 5 | |
michael@0 | 6 | const Cc = Components.classes; |
michael@0 | 7 | const Ci = Components.interfaces; |
michael@0 | 8 | const Cu = Components.utils; |
michael@0 | 9 | const Cr = Components.results; |
michael@0 | 10 | |
michael@0 | 11 | Cu.import("resource://gre/modules/Services.jsm", this); |
michael@0 | 12 | |
michael@0 | 13 | const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); |
michael@0 | 14 | |
michael@0 | 15 | // Constants from prio.h for nsIFileOutputStream.init |
michael@0 | 16 | const PR_WRONLY = 0x2; |
michael@0 | 17 | const PR_CREATE_FILE = 0x8; |
michael@0 | 18 | const PR_TRUNCATE = 0x20; |
michael@0 | 19 | const RW_OWNER = 0600; |
michael@0 | 20 | |
michael@0 | 21 | const STACK_SUFFIX1 = "stack1.txt"; |
michael@0 | 22 | const STACK_SUFFIX2 = "stack2.txt"; |
michael@0 | 23 | const STACK_BOGUS_SUFFIX = "bogus.txt"; |
michael@0 | 24 | const LATE_WRITE_PREFIX = "Telemetry.LateWriteFinal-"; |
michael@0 | 25 | |
michael@0 | 26 | // The names and IDs don't matter, but the format of the IDs does. |
michael@0 | 27 | const LOADED_MODULES = { |
michael@0 | 28 | '4759A7E6993548C89CAF716A67EC242D00': 'libtest.so', |
michael@0 | 29 | 'F77AF15BB8D6419FA875954B4A3506CA00': 'libxul.so', |
michael@0 | 30 | '1E2F7FB590424E8F93D60BB88D66B8C500': 'libc.so' |
michael@0 | 31 | }; |
michael@0 | 32 | const N_MODULES = Object.keys(LOADED_MODULES).length; |
michael@0 | 33 | |
michael@0 | 34 | // Format of individual items is [index, offset-in-library]. |
michael@0 | 35 | const STACK1 = [ |
michael@0 | 36 | [ 0, 0 ], |
michael@0 | 37 | [ 1, 1 ], |
michael@0 | 38 | [ 2, 2 ] |
michael@0 | 39 | ]; |
michael@0 | 40 | const STACK2 = [ |
michael@0 | 41 | [ 0, 0 ], |
michael@0 | 42 | [ 1, 5 ], |
michael@0 | 43 | [ 2, 10 ], |
michael@0 | 44 | ]; |
michael@0 | 45 | // XXX The only error checking is for a zero-sized stack. |
michael@0 | 46 | const STACK_BOGUS = []; |
michael@0 | 47 | |
michael@0 | 48 | function write_string_to_file(file, contents) { |
michael@0 | 49 | let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"] |
michael@0 | 50 | .createInstance(Ci.nsIFileOutputStream); |
michael@0 | 51 | ostream.init(file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, |
michael@0 | 52 | RW_OWNER, ostream.DEFER_OPEN); |
michael@0 | 53 | ostream.write(contents, contents.length); |
michael@0 | 54 | ostream.QueryInterface(Ci.nsISafeOutputStream).finish(); |
michael@0 | 55 | ostream.close(); |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | function construct_file(suffix) { |
michael@0 | 59 | let profileDirectory = Services.dirsvc.get("ProfD", Ci.nsIFile); |
michael@0 | 60 | let file = profileDirectory.clone(); |
michael@0 | 61 | file.append(LATE_WRITE_PREFIX + suffix); |
michael@0 | 62 | return file; |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | function write_late_writes_file(stack, suffix) |
michael@0 | 66 | { |
michael@0 | 67 | let file = construct_file(suffix); |
michael@0 | 68 | let contents = N_MODULES + "\n"; |
michael@0 | 69 | for (let id in LOADED_MODULES) { |
michael@0 | 70 | contents += id + " " + LOADED_MODULES[id] + "\n"; |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | contents += stack.length + "\n"; |
michael@0 | 74 | for (let element of stack) { |
michael@0 | 75 | contents += element[0] + " " + element[1].toString(16) + "\n"; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | write_string_to_file(file, contents); |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | function run_test() { |
michael@0 | 82 | do_get_profile(); |
michael@0 | 83 | |
michael@0 | 84 | write_late_writes_file(STACK1, STACK_SUFFIX1); |
michael@0 | 85 | write_late_writes_file(STACK2, STACK_SUFFIX2); |
michael@0 | 86 | write_late_writes_file(STACK_BOGUS, STACK_BOGUS_SUFFIX); |
michael@0 | 87 | |
michael@0 | 88 | let lateWrites = Telemetry.lateWrites; |
michael@0 | 89 | do_check_true("memoryMap" in lateWrites); |
michael@0 | 90 | do_check_eq(lateWrites.memoryMap.length, 0); |
michael@0 | 91 | do_check_true("stacks" in lateWrites); |
michael@0 | 92 | do_check_eq(lateWrites.stacks.length, 0); |
michael@0 | 93 | |
michael@0 | 94 | do_test_pending(); |
michael@0 | 95 | Telemetry.asyncFetchTelemetryData(function () { |
michael@0 | 96 | actual_test(); |
michael@0 | 97 | }); |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | function actual_test() { |
michael@0 | 101 | do_check_false(construct_file(STACK_SUFFIX1).exists()); |
michael@0 | 102 | do_check_false(construct_file(STACK_SUFFIX2).exists()); |
michael@0 | 103 | do_check_false(construct_file(STACK_BOGUS_SUFFIX).exists()); |
michael@0 | 104 | |
michael@0 | 105 | let lateWrites = Telemetry.lateWrites; |
michael@0 | 106 | |
michael@0 | 107 | do_check_true("memoryMap" in lateWrites); |
michael@0 | 108 | do_check_eq(lateWrites.memoryMap.length, N_MODULES); |
michael@0 | 109 | for (let id in LOADED_MODULES) { |
michael@0 | 110 | let matchingLibrary = lateWrites.memoryMap.filter(function(library, idx, array) { |
michael@0 | 111 | return library[1] == id; |
michael@0 | 112 | }); |
michael@0 | 113 | do_check_eq(matchingLibrary.length, 1); |
michael@0 | 114 | let library = matchingLibrary[0] |
michael@0 | 115 | let name = library[0]; |
michael@0 | 116 | do_check_eq(LOADED_MODULES[id], name); |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | do_check_true("stacks" in lateWrites); |
michael@0 | 120 | do_check_eq(lateWrites.stacks.length, 2); |
michael@0 | 121 | let uneval_STACKS = [uneval(STACK1), uneval(STACK2)]; |
michael@0 | 122 | let first_stack = lateWrites.stacks[0]; |
michael@0 | 123 | let second_stack = lateWrites.stacks[1]; |
michael@0 | 124 | function stackChecker(canonicalStack) { |
michael@0 | 125 | let unevalCanonicalStack = uneval(canonicalStack); |
michael@0 | 126 | return function(obj, idx, array) { |
michael@0 | 127 | return unevalCanonicalStack == obj; |
michael@0 | 128 | } |
michael@0 | 129 | } |
michael@0 | 130 | do_check_eq(uneval_STACKS.filter(stackChecker(first_stack)).length, 1); |
michael@0 | 131 | do_check_eq(uneval_STACKS.filter(stackChecker(second_stack)).length, 1); |
michael@0 | 132 | |
michael@0 | 133 | do_test_finished(); |
michael@0 | 134 | } |