summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/head_telemetry.js
blob: c3b1ec66aa1bc06b52a1596cd3c09c1f880d9db2 (plain)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

"use strict";

const { TelemetryTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/TelemetryTestUtils.sys.mjs"
);

var HandshakeTelemetryHelpers = {
  HISTOGRAMS: ["SSL_HANDSHAKE_RESULT", "SSL_TIME_UNTIL_READY"],
  FLAVORS: ["", "_FIRST_TRY", "_CONSERVATIVE", "_ECH", "_ECH_GREASE"],

  /**
   * Prints the Histogram to console.
   *
   * @param {*} name The identifier of the Histogram.
   */
  dumpHistogram(name) {
    let values = Services.telemetry.getHistogramById(name).snapshot().values;
    dump(`${name}: ${JSON.stringify(values)}\n`);
  },

  /**
   * Counts the number of entries in the histogram, ignoring the bucket value.
   * e.g. {0: 1, 1: 2, 3: 3} has 6 entries.
   *
   * @param {Object} histObject The histogram to count the entries of.
   * @returns The count of the number of entries in the histogram.
   */
  countHistogramEntries(histObject) {
    Assert.ok(
      !mozinfo.socketprocess_networking,
      "Histograms don't populate on network process"
    );
    let count = 0;
    let m = histObject.snapshot().values;
    for (let k in m) {
      count += m[k];
    }
    return count;
  },

  /**
   * Assert that the histogram index is the right value. It expects that
   * other indexes are all zero.
   *
   * @param {Object} histogram The histogram to check.
   * @param {Number} index The index to check against the expected value.
   * @param {Number} expected The expected value of the index.
   */
  assertHistogramMap(histogram, expectedEntries) {
    Assert.ok(
      !mozinfo.socketprocess_networking,
      "Histograms don't populate on network process"
    );
    let snapshot = JSON.parse(JSON.stringify(histogram));
    for (let [Tk, Tv] of expectedEntries.entries()) {
      let found = false;
      for (let [i, val] of Object.entries(snapshot.values)) {
        if (i == Tk) {
          found = true;
          Assert.equal(val, Tv, `expected counts should match at index ${i}`);
          snapshot.values[i] = 0; // Reset the value
        }
      }
      Assert.ok(found, `Should have found an entry at index ${Tk}`);
    }
    for (let k in snapshot.values) {
      Assert.equal(
        snapshot.values[k],
        0,
        `Should NOT have found an entry at index ${k} of value ${snapshot.values[k]}`
      );
    }
  },

  /**
   * Generates the pairwise concatonation of histograms and flavors.
   *
   * @param {Array} histogramList A subset of HISTOGRAMS.
   * @param {Array} flavorList  A subset of FLAVORS.
   * @returns {Array} Valid TLS Histogram identifiers
   */
  getHistogramNames(histogramList, flavorList) {
    let output = [];
    for (let h of histogramList) {
      Assert.ok(this.HISTOGRAMS.includes(h), "Histogram name valid");
      for (let f of flavorList) {
        Assert.ok(this.FLAVORS.includes(f), "Histogram flavor valid");
        output.push(h.concat(f));
      }
    }
    return output;
  },

  /**
   * getHistogramNames but mapped to Histogram objects.
   */
  getHistograms(histogramList, flavorList) {
    return this.getHistogramNames(histogramList, flavorList).map(x =>
      Services.telemetry.getHistogramById(x)
    );
  },

  /**
   * Clears TLS Handshake Histograms.
   */
  resetHistograms() {
    let allHistograms = this.getHistograms(this.HISTOGRAMS, this.FLAVORS);
    for (let h of allHistograms) {
      h.clear();
    }
  },

  /**
   * Checks that all TLS Handshake Histograms of a particular flavor have
   * exactly resultCount entries for the resultCode and no other entries.
   *
   * @param {Array} flavors An array of strings corresponding to which types
   *                        of histograms should have entries. See
   *                        HandshakeTelemetryHelpers.FLAVORS.
   * @param {number} resultCode The expected result code, see sslerr.h. 0 is success, all others are errors.
   * @param {number} resultCount The number of handshake results expected.
   */
  checkEntry(flavors, resultCode, resultCount) {
    Assert.ok(
      !mozinfo.socketprocess_networking,
      "Histograms don't populate on network process"
    );
    // SSL_HANDSHAKE_RESULT_{FLAVOR}
    for (let h of this.getHistograms(["SSL_HANDSHAKE_RESULT"], flavors)) {
      TelemetryTestUtils.assertHistogram(h, resultCode, resultCount);
    }

    // SSL_TIME_UNTIL_READY_{FLAVOR} should only contain values if we expected success.
    if (resultCode === 0) {
      for (let h of this.getHistograms(["SSL_TIME_UNTIL_READY"], flavors)) {
        Assert.ok(
          this.countHistogramEntries(h) === resultCount,
          "Timing entry count correct"
        );
      }
    } else {
      for (let h of this.getHistograms(["SSL_TIME_UNTIL_READY"], flavors)) {
        Assert.ok(
          this.countHistogramEntries(h) === 0,
          "No timing entries expected"
        );
      }
    }
  },

  checkSuccess(flavors, resultCount = 1) {
    this.checkEntry(flavors, 0, resultCount);
  },

  checkEmpty(flavors) {
    for (let h of this.getHistogramNames(this.HISTOGRAMS, flavors)) {
      let hObj = Services.telemetry.getHistogramById(h);
      Assert.ok(
        this.countHistogramEntries(hObj) === 0,
        `No entries expected in ${h.name}. Contents: ${JSON.stringify(
          hObj.snapshot()
        )}`
      );
    }
  },
};