head_telemetry.js (5510B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 */ 5 6 "use strict"; 7 8 const { TelemetryTestUtils } = ChromeUtils.importESModule( 9 "resource://testing-common/TelemetryTestUtils.sys.mjs" 10 ); 11 12 var HandshakeTelemetryHelpers = { 13 HISTOGRAMS: ["SSL_HANDSHAKE_RESULT", "SSL_TIME_UNTIL_READY"], 14 FLAVORS: ["", "_FIRST_TRY", "_CONSERVATIVE", "_ECH", "_ECH_GREASE"], 15 16 /** 17 * Prints the Histogram to console. 18 * 19 * @param {*} name The identifier of the Histogram. 20 */ 21 dumpHistogram(name) { 22 let values = Services.telemetry.getHistogramById(name).snapshot().values; 23 dump(`${name}: ${JSON.stringify(values)}\n`); 24 }, 25 26 /** 27 * Counts the number of entries in the histogram, ignoring the bucket value. 28 * e.g. {0: 1, 1: 2, 3: 3} has 6 entries. 29 * 30 * @param {object} histObject The histogram to count the entries of. 31 * @returns The count of the number of entries in the histogram. 32 */ 33 countHistogramEntries(histObject) { 34 Assert.ok( 35 !mozinfo.socketprocess_networking, 36 "Histograms don't populate on network process" 37 ); 38 let count = 0; 39 let m = histObject.snapshot().values; 40 for (let k in m) { 41 count += m[k]; 42 } 43 return count; 44 }, 45 46 /** 47 * Assert that the histogram index is the right value. It expects that 48 * other indexes are all zero. 49 * 50 * @param {object} histogram The histogram to check. 51 * @param {number} index The index to check against the expected value. 52 * @param {number} expected The expected value of the index. 53 */ 54 assertHistogramMap(histogram, expectedEntries) { 55 Assert.ok( 56 !mozinfo.socketprocess_networking, 57 "Histograms don't populate on network process" 58 ); 59 let snapshot = JSON.parse(JSON.stringify(histogram)); 60 for (let [Tk, Tv] of expectedEntries.entries()) { 61 let found = false; 62 for (let [i, val] of Object.entries(snapshot.values)) { 63 if (i == Tk) { 64 found = true; 65 Assert.equal(val, Tv, `expected counts should match at index ${i}`); 66 snapshot.values[i] = 0; // Reset the value 67 } 68 } 69 Assert.ok(found, `Should have found an entry at index ${Tk}`); 70 } 71 for (let k in snapshot.values) { 72 Assert.equal( 73 snapshot.values[k], 74 0, 75 `Should NOT have found an entry at index ${k} of value ${snapshot.values[k]}` 76 ); 77 } 78 }, 79 80 /** 81 * Generates the pairwise concatonation of histograms and flavors. 82 * 83 * @param {Array} histogramList A subset of HISTOGRAMS. 84 * @param {Array} flavorList A subset of FLAVORS. 85 * @returns {Array} Valid TLS Histogram identifiers 86 */ 87 getHistogramNames(histogramList, flavorList) { 88 let output = []; 89 for (let h of histogramList) { 90 Assert.ok(this.HISTOGRAMS.includes(h), "Histogram name valid"); 91 for (let f of flavorList) { 92 Assert.ok(this.FLAVORS.includes(f), "Histogram flavor valid"); 93 output.push(h.concat(f)); 94 } 95 } 96 return output; 97 }, 98 99 /** 100 * getHistogramNames but mapped to Histogram objects. 101 */ 102 getHistograms(histogramList, flavorList) { 103 return this.getHistogramNames(histogramList, flavorList).map(x => 104 Services.telemetry.getHistogramById(x) 105 ); 106 }, 107 108 /** 109 * Clears TLS Handshake Histograms. 110 */ 111 resetHistograms() { 112 let allHistograms = this.getHistograms(this.HISTOGRAMS, this.FLAVORS); 113 for (let h of allHistograms) { 114 h.clear(); 115 } 116 }, 117 118 /** 119 * Checks that all TLS Handshake Histograms of a particular flavor have 120 * exactly resultCount entries for the resultCode and no other entries. 121 * 122 * @param {Array} flavors An array of strings corresponding to which types 123 * of histograms should have entries. See 124 * HandshakeTelemetryHelpers.FLAVORS. 125 * @param {number} resultCode The expected result code, see sslerr.h. 0 is success, all others are errors. 126 * @param {number} resultCount The number of handshake results expected. 127 */ 128 checkEntry(flavors, resultCode, resultCount) { 129 Assert.ok( 130 !mozinfo.socketprocess_networking, 131 "Histograms don't populate on network process" 132 ); 133 // SSL_HANDSHAKE_RESULT_{FLAVOR} 134 for (let h of this.getHistograms(["SSL_HANDSHAKE_RESULT"], flavors)) { 135 TelemetryTestUtils.assertHistogram(h, resultCode, resultCount); 136 } 137 138 // SSL_TIME_UNTIL_READY_{FLAVOR} should only contain values if we expected success. 139 if (resultCode === 0) { 140 for (let h of this.getHistograms(["SSL_TIME_UNTIL_READY"], flavors)) { 141 Assert.strictEqual( 142 this.countHistogramEntries(h), 143 resultCount, 144 "Timing entry count correct" 145 ); 146 } 147 } else { 148 for (let h of this.getHistograms(["SSL_TIME_UNTIL_READY"], flavors)) { 149 Assert.strictEqual( 150 this.countHistogramEntries(h), 151 0, 152 "No timing entries expected" 153 ); 154 } 155 } 156 }, 157 158 checkSuccess(flavors, resultCount = 1) { 159 this.checkEntry(flavors, 0, resultCount); 160 }, 161 162 checkEmpty(flavors) { 163 for (let h of this.getHistogramNames(this.HISTOGRAMS, flavors)) { 164 let hObj = Services.telemetry.getHistogramById(h); 165 Assert.strictEqual( 166 this.countHistogramEntries(hObj), 167 0, 168 `No entries expected in ${h.name}. Contents: ${JSON.stringify( 169 hObj.snapshot() 170 )}` 171 ); 172 } 173 }, 174 };