Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/telemetry/tests/gtest/TestHistograms.cpp
Line
Count
Source (jump to first uncovered line)
1
/* vim:set ts=2 sw=2 sts=0 et: */
2
/* Any copyright is dedicated to the Public Domain.
3
 * http://creativecommons.org/publicdomain/zero/1.0/
4
 */
5
6
#include "gtest/gtest.h"
7
#include "js/Conversions.h"
8
#include "nsITelemetry.h"
9
#include "mozilla/Telemetry.h"
10
#include "TelemetryFixture.h"
11
#include "TelemetryTestHelpers.h"
12
13
using namespace mozilla;
14
using namespace TelemetryTestHelpers;
15
16
TEST_F(TelemetryTestFixture, AccumulateCountHistogram)
17
0
{
18
0
  const uint32_t kExpectedValue = 200;
19
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
20
0
21
0
  const char* telemetryTestCountName = Telemetry::GetHistogramName(Telemetry::TELEMETRY_TEST_COUNT);
22
0
  ASSERT_STREQ(telemetryTestCountName, "TELEMETRY_TEST_COUNT") << "The histogram name is wrong";
23
0
24
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_COUNT"),
25
0
                       false);
26
0
27
0
  // Accumulate in the histogram
28
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_COUNT, kExpectedValue/2);
29
0
  Telemetry::Accumulate("TELEMETRY_TEST_COUNT", kExpectedValue/2);
30
0
31
0
  // Get a snapshot for all the histograms
32
0
  JS::RootedValue snapshot(cx.GetJSContext());
33
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, telemetryTestCountName, &snapshot, false);
34
0
35
0
  // Get the histogram from the snapshot
36
0
  JS::RootedValue histogram(cx.GetJSContext());
37
0
  GetProperty(cx.GetJSContext(), telemetryTestCountName, snapshot, &histogram);
38
0
39
0
  // Get "sum" property from histogram
40
0
  JS::RootedValue sum(cx.GetJSContext());
41
0
  GetProperty(cx.GetJSContext(), "sum", histogram,  &sum);
42
0
43
0
  // Check that the "sum" stored in the histogram matches with |kExpectedValue|
44
0
  uint32_t uSum = 0;
45
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
46
0
  ASSERT_EQ(uSum, kExpectedValue) << "The histogram is not returning expected value";
47
0
}
48
49
TEST_F(TelemetryTestFixture, AccumulateKeyedCountHistogram)
50
0
{
51
0
  const uint32_t kExpectedValue = 100;
52
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
53
0
54
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
55
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_COUNT"), true);
56
0
57
0
  // Accumulate data in the provided key within the histogram
58
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_KEYED_COUNT, NS_LITERAL_CSTRING("sample"),
59
0
                        kExpectedValue);
60
0
61
0
  // Get a snapshot for all the histograms
62
0
  JS::RootedValue snapshot(cx.GetJSContext());
63
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_COUNT", &snapshot, true);
64
0
65
0
  // Get the histogram from the snapshot
66
0
  JS::RootedValue histogram(cx.GetJSContext());
67
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_COUNT", snapshot, &histogram);
68
0
69
0
  // Get "sample" property from histogram
70
0
  JS::RootedValue expectedKeyData(cx.GetJSContext());
71
0
  GetProperty(cx.GetJSContext(), "sample", histogram,  &expectedKeyData);
72
0
73
0
  // Get "sum" property from keyed data
74
0
  JS::RootedValue sum(cx.GetJSContext());
75
0
  GetProperty(cx.GetJSContext(), "sum", expectedKeyData,  &sum);
76
0
77
0
  // Check that the sum stored in the histogram matches with |kExpectedValue|
78
0
  uint32_t uSum = 0;
79
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
80
0
  ASSERT_EQ(uSum, kExpectedValue) << "The histogram is not returning expected sum";
81
0
}
82
83
TEST_F(TelemetryTestFixture, TestKeyedKeysHistogram)
84
0
{
85
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
86
0
87
0
  JS::RootedValue testHistogram(cx.GetJSContext());
88
0
  JS::RootedValue rval(cx.GetJSContext());
89
0
90
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
91
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_KEYS"), true);
92
0
93
0
  // Test the accumulation on both the allowed and unallowed keys, using
94
0
  // the API that accepts histogram IDs.
95
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_KEYED_KEYS, NS_LITERAL_CSTRING("not-allowed"), 1);
96
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_KEYED_KEYS, NS_LITERAL_CSTRING("testkey"), 0);
97
0
  // Do the same, using the API that accepts the histogram name as a string.
98
0
  Telemetry::Accumulate("TELEMETRY_TEST_KEYED_KEYS", NS_LITERAL_CSTRING("not-allowed"), 1);
99
0
  Telemetry::Accumulate("TELEMETRY_TEST_KEYED_KEYS", NS_LITERAL_CSTRING("CommonKey"), 1);
100
0
101
0
  // Get a snapshot for all the histograms
102
0
  JS::RootedValue snapshot(cx.GetJSContext());
103
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_KEYS", &snapshot, true);
104
0
105
0
  // Get the histogram from the snapshot
106
0
  JS::RootedValue histogram(cx.GetJSContext());
107
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_KEYS", snapshot, &histogram);
108
0
109
0
  // Get "testkey" property from histogram and check that it stores the correct
110
0
  // data.
111
0
  JS::RootedValue expectedKeyData(cx.GetJSContext());
112
0
  GetProperty(cx.GetJSContext(), "testkey", histogram,  &expectedKeyData);
113
0
  ASSERT_TRUE(!expectedKeyData.isUndefined())
114
0
    << "Cannot find the expected key in the histogram data";
115
0
  JS::RootedValue sum(cx.GetJSContext());
116
0
  GetProperty(cx.GetJSContext(), "sum", expectedKeyData,  &sum);
117
0
  uint32_t uSum = 0;
118
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
119
0
  ASSERT_EQ(uSum, 0U) << "The histogram is not returning expected sum for 'testkey'";
120
0
121
0
  // Do the same for the "CommonKey" property.
122
0
  GetProperty(cx.GetJSContext(), "CommonKey", histogram,  &expectedKeyData);
123
0
  ASSERT_TRUE(!expectedKeyData.isUndefined())
124
0
    << "Cannot find the expected key in the histogram data";
125
0
  GetProperty(cx.GetJSContext(), "sum", expectedKeyData,  &sum);
126
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
127
0
  ASSERT_EQ(uSum, 1U) << "The histogram is not returning expected sum for 'CommonKey'";
128
0
129
0
  GetProperty(cx.GetJSContext(), "not-allowed", histogram,  &expectedKeyData);
130
0
  ASSERT_TRUE(expectedKeyData.isUndefined())
131
0
    << "Unallowed keys must not be recorded in the histogram data";
132
0
133
0
  // The 'not-allowed' key accumulation for 'TELEMETRY_TESTED_KEYED_KEYS' was
134
0
  // attemtped twice, so we expect the count of
135
0
  // 'telemetry.accumulate_unknown_histogram_keys' to be 2
136
0
  const uint32_t expectedAccumulateUnknownCount = 2;
137
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
138
0
  GetScalarsSnapshot(true, cx.GetJSContext(),&scalarsSnapshot);
139
0
  CheckKeyedUintScalar("telemetry.accumulate_unknown_histogram_keys",
140
0
                       "TELEMETRY_TEST_KEYED_KEYS", cx.GetJSContext(),
141
0
                       scalarsSnapshot, expectedAccumulateUnknownCount);
142
0
}
143
144
TEST_F(TelemetryTestFixture, AccumulateCategoricalHistogram)
145
0
{
146
0
  const uint32_t kExpectedValue = 2;
147
0
148
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
149
0
150
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
151
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_CATEGORICAL"), false);
152
0
153
0
  // Accumulate one unit into the categorical histogram with label
154
0
  // Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel
155
0
  Telemetry::AccumulateCategorical(Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel);
156
0
157
0
  // Accumulate another unit into the same categorical histogram using a string label
158
0
  Telemetry::AccumulateCategorical(Telemetry::TELEMETRY_TEST_CATEGORICAL,
159
0
                                   NS_LITERAL_CSTRING("CommonLabel"));
160
0
161
0
  // Get a snapshot for all the histograms
162
0
  JS::RootedValue snapshot(cx.GetJSContext());
163
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_CATEGORICAL", &snapshot, false);
164
0
165
0
  // Get our histogram from the snapshot
166
0
  JS::RootedValue histogram(cx.GetJSContext());
167
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_CATEGORICAL", snapshot, &histogram);
168
0
169
0
  // Get counts array from histogram. Each entry in the array maps to a label in the histogram.
170
0
  JS::RootedValue counts(cx.GetJSContext());
171
0
  GetProperty(cx.GetJSContext(), "counts", histogram,  &counts);
172
0
173
0
  // Get the value for the label we care about
174
0
  JS::RootedValue value(cx.GetJSContext());
175
0
  GetElement(cx.GetJSContext(),
176
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel),
177
0
             counts, &value);
178
0
179
0
  // Check that the value stored in the histogram matches with |kExpectedValue|
180
0
  uint32_t uValue = 0;
181
0
  JS::ToUint32(cx.GetJSContext(), value, &uValue);
182
0
  ASSERT_EQ(uValue, kExpectedValue) << "The histogram is not returning expected value";
183
0
}
184
185
TEST_F(TelemetryTestFixture, AccumulateKeyedCategoricalHistogram)
186
0
{
187
0
  const uint32_t kSampleExpectedValue = 2;
188
0
  const uint32_t kOtherSampleExpectedValue = 1;
189
0
190
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
191
0
192
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
193
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_CATEGORICAL"), true);
194
0
195
0
  // Accumulate one unit into the categorical histogram with label
196
0
  // Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel
197
0
  Telemetry::AccumulateCategoricalKeyed(NS_LITERAL_CSTRING("sample"),
198
0
                                        Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel);
199
0
  // Accumulate another unit into the same categorical histogram
200
0
  Telemetry::AccumulateCategoricalKeyed(NS_LITERAL_CSTRING("sample"),
201
0
                                        Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel);
202
0
  // Accumulate another unit into a different categorical histogram
203
0
  Telemetry::AccumulateCategoricalKeyed(NS_LITERAL_CSTRING("other-sample"),
204
0
                                        Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel);
205
0
206
0
  // Get a snapshot for all the histograms
207
0
  JS::RootedValue snapshot(cx.GetJSContext());
208
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_CATEGORICAL", &snapshot, true);
209
0
  // Get the histogram from the snapshot
210
0
  JS::RootedValue histogram(cx.GetJSContext());
211
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_CATEGORICAL", snapshot, &histogram);
212
0
213
0
  // Check that the sample histogram contains the values we expect
214
0
  JS::RootedValue sample(cx.GetJSContext());
215
0
  GetProperty(cx.GetJSContext(), "sample", histogram,  &sample);
216
0
  // Get counts array from the sample. Each entry in the array maps to a label in the histogram.
217
0
  JS::RootedValue sampleCounts(cx.GetJSContext());
218
0
  GetProperty(cx.GetJSContext(), "counts", sample,  &sampleCounts);
219
0
  // Get the value for the label we care about
220
0
  JS::RootedValue sampleValue(cx.GetJSContext());
221
0
  GetElement(cx.GetJSContext(),
222
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel),
223
0
             sampleCounts, &sampleValue);
224
0
  // Check that the value stored in the histogram matches with |kSampleExpectedValue|
225
0
  uint32_t uSampleValue = 0;
226
0
  JS::ToUint32(cx.GetJSContext(), sampleValue, &uSampleValue);
227
0
  ASSERT_EQ(uSampleValue, kSampleExpectedValue) << "The sample histogram is not returning expected value";
228
0
229
0
  // Check that the other-sample histogram contains the values we expect
230
0
  JS::RootedValue otherSample(cx.GetJSContext());
231
0
  GetProperty(cx.GetJSContext(), "other-sample", histogram,  &otherSample);
232
0
  // Get counts array from the other-sample. Each entry in the array maps to a label in the histogram.
233
0
  JS::RootedValue otherCounts(cx.GetJSContext());
234
0
  GetProperty(cx.GetJSContext(), "counts", otherSample,  &otherCounts);
235
0
  // Get the value for the label we care about
236
0
  JS::RootedValue otherValue(cx.GetJSContext());
237
0
  GetElement(cx.GetJSContext(),
238
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel),
239
0
             otherCounts, &otherValue);
240
0
  // Check that the value stored in the histogram matches with |kOtherSampleExpectedValue|
241
0
  uint32_t uOtherValue = 0;
242
0
  JS::ToUint32(cx.GetJSContext(), otherValue, &uOtherValue);
243
0
  ASSERT_EQ(uOtherValue, kOtherSampleExpectedValue) << "The other-sample histogram is not returning expected value";
244
0
}
245
246
TEST_F(TelemetryTestFixture, AccumulateCountHistogram_MultipleSamples)
247
0
{
248
0
  nsTArray<uint32_t> samples({4,4,4});
249
0
  const uint32_t kExpectedSum = 12;
250
0
251
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
252
0
253
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_COUNT"),
254
0
                        false);
255
0
256
0
  // Accumulate in histogram
257
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_COUNT, samples);
258
0
259
0
  // Get a snapshot of all the histograms
260
0
  JS::RootedValue snapshot(cx.GetJSContext());
261
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_COUNT", &snapshot, false);
262
0
263
0
  // Get histogram from snapshot
264
0
  JS::RootedValue histogram(cx.GetJSContext());
265
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_COUNT", snapshot, &histogram);
266
0
267
0
  // Get "sum" from histogram
268
0
  JS::RootedValue sum(cx.GetJSContext());
269
0
  GetProperty(cx.GetJSContext(), "sum", histogram, &sum);
270
0
271
0
  // Check that sum matches with aValue
272
0
  uint32_t uSum = 0;
273
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
274
0
  ASSERT_EQ(uSum, kExpectedSum) << "This histogram is not returning expected value";
275
0
}
276
277
TEST_F(TelemetryTestFixture, AccumulateLinearHistogram_MultipleSamples)
278
0
{
279
0
  nsTArray<uint32_t> samples({4,4,4});
280
0
  const uint32_t kExpectedCount = 3;
281
0
282
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
283
0
284
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_LINEAR"),
285
0
                        false);
286
0
287
0
  // Accumulate in the histogram
288
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_LINEAR, samples);
289
0
290
0
  // Get a snapshot of all the histograms
291
0
  JS::RootedValue snapshot(cx.GetJSContext());
292
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_LINEAR", &snapshot, false);
293
0
294
0
  // Get histogram from snapshot
295
0
  JS::RootedValue histogram(cx.GetJSContext());
296
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_LINEAR", snapshot, &histogram);
297
0
298
0
  // Get "counts" array from histogram
299
0
  JS::RootedValue counts(cx.GetJSContext());
300
0
  GetProperty(cx.GetJSContext(), "counts", histogram, &counts);
301
0
302
0
  // Index 0 is only for values less than 'low'. Values within range start at index 1
303
0
  JS::RootedValue count(cx.GetJSContext());
304
0
  const uint32_t index = 1;
305
0
  GetElement(cx.GetJSContext(), index, counts, &count);
306
0
307
0
  // Check that this count matches with nSamples
308
0
  uint32_t uCount = 0;
309
0
  JS::ToUint32(cx.GetJSContext(), count, &uCount);
310
0
  ASSERT_EQ(uCount, kExpectedCount) << "The histogram did not accumulate the correct number of values";
311
0
}
312
313
TEST_F(TelemetryTestFixture, AccumulateLinearHistogram_DifferentSamples)
314
0
{
315
0
  nsTArray<uint32_t> samples({4, 8, 2147483646, uint32_t(INT_MAX) + 1, UINT32_MAX});
316
0
317
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
318
0
319
0
  mTelemetry->ClearScalars();
320
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_LINEAR"),
321
0
                        false);
322
0
323
0
  // Accumulate in histogram
324
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_LINEAR, samples);
325
0
326
0
  // Get a snapshot of all histograms
327
0
  JS::RootedValue snapshot(cx.GetJSContext());
328
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_LINEAR", &snapshot, false);
329
0
330
0
  // Get histogram from snapshot
331
0
  JS::RootedValue histogram(cx.GetJSContext());
332
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_LINEAR", snapshot, &histogram);
333
0
334
0
  // Get counts array from histogram
335
0
  JS::RootedValue counts(cx.GetJSContext());
336
0
  GetProperty(cx.GetJSContext(), "counts", histogram, &counts);
337
0
338
0
  // Get counts in first and last buckets
339
0
  JS::RootedValue countFirst(cx.GetJSContext());
340
0
  JS::RootedValue countLast(cx.GetJSContext());
341
0
  const uint32_t firstIndex = 1;
342
0
  const uint32_t lastIndex = 9;
343
0
  GetElement(cx.GetJSContext(), firstIndex, counts, &countFirst);
344
0
  GetElement(cx.GetJSContext(), lastIndex, counts, &countLast);
345
0
346
0
  // Check that the counts match
347
0
  uint32_t uCountFirst = 0;
348
0
  uint32_t uCountLast = 0;
349
0
  JS::ToUint32(cx.GetJSContext(), countFirst, &uCountFirst);
350
0
  JS::ToUint32(cx.GetJSContext(), countLast, &uCountLast);
351
0
352
0
  const uint32_t kExpectedCountFirst = 2;
353
0
  // We expect 2147483646 to be in the last bucket, as well the two samples above 2^31
354
0
  // (prior to bug 1438335, values between INT_MAX and UINT32_MAX would end up as 0s)
355
0
  const uint32_t kExpectedCountLast = 3;
356
0
  ASSERT_EQ(uCountFirst, kExpectedCountFirst) << "The first bucket did not accumulate the correct number of values";
357
0
  ASSERT_EQ(uCountLast, kExpectedCountLast) << "The last bucket did not accumulate the correct number of values";
358
0
359
0
  // We accumulated two values that had to be clamped. We expect the count in
360
0
  // 'telemetry.accumulate_clamped_values' to be 2 (only one storage).
361
0
  const uint32_t expectedAccumulateClampedCount = 2;
362
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
363
0
  GetScalarsSnapshot(true, cx.GetJSContext(),&scalarsSnapshot);
364
0
  CheckKeyedUintScalar("telemetry.accumulate_clamped_values",
365
0
                       "TELEMETRY_TEST_LINEAR", cx.GetJSContext(),
366
0
                       scalarsSnapshot, expectedAccumulateClampedCount);
367
0
}
368
369
TEST_F(TelemetryTestFixture, AccumulateKeyedCountHistogram_MultipleSamples)
370
0
{
371
0
  const nsTArray<uint32_t> samples({5, 10, 15});
372
0
  const uint32_t kExpectedSum = 5 + 10 + 15;
373
0
374
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
375
0
376
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
377
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_COUNT"), true);
378
0
379
0
  // Accumulate data in the provided key within the histogram
380
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_KEYED_COUNT, NS_LITERAL_CSTRING("sample"),
381
0
                        samples);
382
0
383
0
  // Get a snapshot for all the histograms
384
0
  JS::RootedValue snapshot(cx.GetJSContext());
385
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_COUNT", &snapshot, true);
386
0
387
0
  // Get the histogram from the snapshot
388
0
  JS::RootedValue histogram(cx.GetJSContext());
389
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_COUNT", snapshot, &histogram);
390
0
391
0
  // Get "sample" property from histogram
392
0
  JS::RootedValue expectedKeyData(cx.GetJSContext());
393
0
  GetProperty(cx.GetJSContext(), "sample", histogram,  &expectedKeyData);
394
0
395
0
  // Get "sum" property from keyed data
396
0
  JS::RootedValue sum(cx.GetJSContext());
397
0
  GetProperty(cx.GetJSContext(), "sum", expectedKeyData,  &sum);
398
0
399
0
  // Check that the sum stored in the histogram matches with |kExpectedSum|
400
0
  uint32_t uSum = 0;
401
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
402
0
  ASSERT_EQ(uSum, kExpectedSum) << "The histogram is not returning expected sum";
403
0
}
404
405
TEST_F(TelemetryTestFixture, TestKeyedLinearHistogram_MultipleSamples)
406
0
{
407
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
408
0
409
0
  mTelemetry->ClearScalars();
410
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
411
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_LINEAR"), true);
412
0
413
0
  const nsTArray<uint32_t> samples({1, 5, 250000, UINT_MAX});
414
0
  // Test the accumulation on the key 'testkey', using
415
0
  // the API that accepts histogram IDs.
416
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_KEYED_LINEAR,
417
0
                        NS_LITERAL_CSTRING("testkey"), samples);
418
0
419
0
  // Get a snapshot for all the histograms
420
0
  JS::RootedValue snapshot(cx.GetJSContext());
421
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_LINEAR", &snapshot, true);
422
0
423
0
  // Get the histogram from the snapshot
424
0
  JS::RootedValue histogram(cx.GetJSContext());
425
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_LINEAR", snapshot, &histogram);
426
0
427
0
  // Get "testkey" property from histogram.
428
0
  JS::RootedValue expectedKeyData(cx.GetJSContext());
429
0
  GetProperty(cx.GetJSContext(), "testkey", histogram,  &expectedKeyData);
430
0
  ASSERT_TRUE(!expectedKeyData.isUndefined())
431
0
    << "Cannot find the expected key in the histogram data";
432
0
433
0
  // Get counts array from 'testkey' histogram.
434
0
  JS::RootedValue counts(cx.GetJSContext());
435
0
  GetProperty(cx.GetJSContext(), "counts", expectedKeyData, &counts);
436
0
437
0
  // Get counts in first and last buckets.
438
0
  JS::RootedValue countFirst(cx.GetJSContext());
439
0
  JS::RootedValue countLast(cx.GetJSContext());
440
0
  const uint32_t firstIndex = 1;
441
0
  const uint32_t lastIndex = 9;
442
0
  GetElement(cx.GetJSContext(), firstIndex, counts, &countFirst);
443
0
  GetElement(cx.GetJSContext(), lastIndex, counts, &countLast);
444
0
445
0
  // Check that the counts match.
446
0
  uint32_t uCountFirst = 0;
447
0
  uint32_t uCountLast = 0;
448
0
  JS::ToUint32(cx.GetJSContext(), countFirst, &uCountFirst);
449
0
  JS::ToUint32(cx.GetJSContext(), countLast, &uCountLast);
450
0
451
0
  const uint32_t kExpectedCountFirst = 2;
452
0
  const uint32_t kExpectedCountLast = 2;
453
0
  ASSERT_EQ(uCountFirst, kExpectedCountFirst)
454
0
    << "The first bucket did not accumulate the correct number of values for key 'testkey'";
455
0
  ASSERT_EQ(uCountLast, kExpectedCountLast)
456
0
    << "The last bucket did not accumulate the correct number of values for key 'testkey'";
457
0
458
0
  // We accumulated one keyed values that had to be clamped. We expect the
459
0
  // count in 'telemetry.accumulate_clamped_values' to be 1
460
0
  const uint32_t expectedAccumulateClampedCount = 1;
461
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
462
0
  GetScalarsSnapshot(true, cx.GetJSContext(),&scalarsSnapshot);
463
0
  CheckKeyedUintScalar("telemetry.accumulate_clamped_values",
464
0
                       "TELEMETRY_TEST_KEYED_LINEAR", cx.GetJSContext(),
465
0
                       scalarsSnapshot, expectedAccumulateClampedCount);
466
0
}
467
468
TEST_F(TelemetryTestFixture, TestKeyedKeysHistogram_MultipleSamples)
469
0
{
470
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
471
0
  mTelemetry->ClearScalars();
472
0
  const nsTArray<uint32_t> samples({false, false, true, 32, true});
473
0
474
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
475
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_KEYS"), true);
476
0
477
0
  // Test the accumulation on both the allowed and unallowed keys, using
478
0
  // the API that accepts histogram IDs.
479
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_KEYED_KEYS,
480
0
                        NS_LITERAL_CSTRING("not-allowed"), samples);
481
0
  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_KEYED_KEYS,
482
0
                        NS_LITERAL_CSTRING("testkey"), samples);
483
0
484
0
  // Get a snapshot for all the histograms
485
0
  JS::RootedValue snapshot(cx.GetJSContext());
486
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_KEYS", &snapshot, true);
487
0
488
0
  // Get the histogram from the snapshot
489
0
  JS::RootedValue histogram(cx.GetJSContext());
490
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_KEYS", snapshot, &histogram);
491
0
492
0
  // Get "testkey" property from histogram and check that it stores the correct data.
493
0
  JS::RootedValue testKeyData(cx.GetJSContext());
494
0
  GetProperty(cx.GetJSContext(), "testkey", histogram,  &testKeyData);
495
0
  ASSERT_TRUE(!testKeyData.isUndefined())
496
0
    << "Cannot find the key 'testkey' in the histogram data";
497
0
498
0
  JS::RootedValue counts(cx.GetJSContext());
499
0
  GetProperty(cx.GetJSContext(), "counts", testKeyData,  &counts);
500
0
501
0
  // Get counts in buckets 0,1,2
502
0
  const uint32_t falseIndex = 0;
503
0
  const uint32_t trueIndex = 1;
504
0
  const uint32_t otherIndex = 2;
505
0
506
0
  JS::RootedValue countFalse(cx.GetJSContext());
507
0
  JS::RootedValue countTrue(cx.GetJSContext());
508
0
  JS::RootedValue countOther(cx.GetJSContext());
509
0
510
0
  GetElement(cx.GetJSContext(), falseIndex, counts, &countFalse);
511
0
  GetElement(cx.GetJSContext(), trueIndex, counts, &countTrue);
512
0
  GetElement(cx.GetJSContext(), otherIndex, counts, &countOther);
513
0
514
0
  uint32_t uCountFalse = 0;
515
0
  uint32_t uCountTrue = 0;
516
0
  uint32_t uCountOther = 0;
517
0
  JS::ToUint32(cx.GetJSContext(), countFalse, &uCountFalse);
518
0
  JS::ToUint32(cx.GetJSContext(), countTrue, &uCountTrue);
519
0
  JS::ToUint32(cx.GetJSContext(), countOther, &uCountOther);
520
0
521
0
  const uint32_t kExpectedCountFalse = 2;
522
0
  const uint32_t kExpectedCountTrue = 3;
523
0
  const uint32_t kExpectedCountOther = 0;
524
0
525
0
  ASSERT_EQ(uCountFalse, kExpectedCountFalse)
526
0
    << "The histogram did not accumulate the correct number of 'false' booleans for key 'testkey'";
527
0
  ASSERT_EQ(uCountTrue, kExpectedCountTrue)
528
0
    << "The histogram did not accumulate the correct number of 'true' booleans for key 'testkey'";
529
0
  ASSERT_EQ(uCountOther, kExpectedCountOther)
530
0
    << "The histogram did not accumulate the correct number of undefined values for key 'testkey'";
531
0
532
0
  // Here we check that we are not accumulating to a different (but still 'allowed') key.
533
0
  // Get "CommonKey" property from histogram and check that it has no data.
534
0
  // Since we accumulated no data to it, commonKeyData should be undefined.
535
0
  JS::RootedValue commonKeyData(cx.GetJSContext());
536
0
  GetProperty(cx.GetJSContext(), "CommonKey", histogram,  &commonKeyData);
537
0
  ASSERT_TRUE(commonKeyData.isUndefined())
538
0
    << "Found data in key 'CommonKey' even though we accumulated no data to it";
539
0
540
0
  // Here we check that our function does not allow accumulation into unallowed keys.
541
0
  // Get 'not-allowed' property from histogram and check that this also has no data.
542
0
  // This should contain no data because this key is not allowed.
543
0
  JS::RootedValue notAllowedKeyData(cx.GetJSContext());
544
0
  GetProperty(cx.GetJSContext(), "not-allowed", histogram, &notAllowedKeyData);
545
0
  ASSERT_TRUE(notAllowedKeyData.isUndefined())
546
0
    << "Found data in key 'not-allowed' even though accumuling data to it is not allowed";
547
0
548
0
  // The 'not-allowed' key accumulation for 'TELEMETRY_TESTED_KEYED_KEYS' was
549
0
  // attemtped once, so we expect the count of
550
0
  // 'telemetry.accumulate_unknown_histogram_keys' to be 1
551
0
  const uint32_t expectedAccumulateUnknownCount = 1;
552
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
553
0
  GetScalarsSnapshot(true, cx.GetJSContext(),&scalarsSnapshot);
554
0
  CheckKeyedUintScalar("telemetry.accumulate_unknown_histogram_keys",
555
0
                       "TELEMETRY_TEST_KEYED_KEYS", cx.GetJSContext(),
556
0
                       scalarsSnapshot, expectedAccumulateUnknownCount);
557
0
}
558
559
TEST_F(TelemetryTestFixture, AccumulateCategoricalHistogram_MultipleStringLabels)
560
0
{
561
0
  const uint32_t kExpectedValue = 2;
562
0
  const nsTArray<nsCString> labels({
563
0
                            NS_LITERAL_CSTRING("CommonLabel"),
564
0
                            NS_LITERAL_CSTRING("CommonLabel")});
565
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
566
0
567
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
568
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_CATEGORICAL"), false);
569
0
570
0
  // Accumulate the units into a categorical histogram using a string label
571
0
  Telemetry::AccumulateCategorical(Telemetry::TELEMETRY_TEST_CATEGORICAL, labels);
572
0
573
0
  // Get a snapshot for all the histograms
574
0
  JS::RootedValue snapshot(cx.GetJSContext());
575
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_CATEGORICAL", &snapshot, false);
576
0
577
0
  // Get our histogram from the snapshot
578
0
  JS::RootedValue histogram(cx.GetJSContext());
579
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_CATEGORICAL", snapshot, &histogram);
580
0
581
0
  // Get counts array from histogram. Each entry in the array maps to a label in the histogram.
582
0
  JS::RootedValue counts(cx.GetJSContext());
583
0
  GetProperty(cx.GetJSContext(), "counts", histogram,  &counts);
584
0
585
0
  // Get the value for the label we care about
586
0
  JS::RootedValue value(cx.GetJSContext());
587
0
  GetElement(cx.GetJSContext(),
588
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel),
589
0
             counts, &value);
590
0
591
0
  // Check that the value stored in the histogram matches with |kExpectedValue|
592
0
  uint32_t uValue = 0;
593
0
  JS::ToUint32(cx.GetJSContext(), value, &uValue);
594
0
  ASSERT_EQ(uValue, kExpectedValue) << "The histogram is not returning expected value";
595
0
596
0
  // Now we check for no accumulation when a bad label is present in the array.
597
0
  //
598
0
  // The 'counts' property is not initialized unless data is accumulated so keeping another test
599
0
  // to check for this case alone is wasteful as we will have to accumulate some data anyway.
600
0
601
0
  const nsTArray<nsCString> badLabelArray({
602
0
                            NS_LITERAL_CSTRING("CommonLabel"),
603
0
                            NS_LITERAL_CSTRING("BadLabel")});
604
0
605
0
  // Try to accumulate the array into the histogram.
606
0
  Telemetry::AccumulateCategorical(Telemetry::TELEMETRY_TEST_CATEGORICAL, badLabelArray);
607
0
608
0
  // Get snapshot of all the histograms
609
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_CATEGORICAL", &snapshot, false);
610
0
611
0
  // Get our histogram from the snapshot
612
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_CATEGORICAL", snapshot, &histogram);
613
0
614
0
  // Get counts array from histogram
615
0
  GetProperty(cx.GetJSContext(), "counts", histogram, &counts);
616
0
617
0
  // Get the value for the label we care about
618
0
  GetElement(cx.GetJSContext(),
619
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel),
620
0
             counts, &value);
621
0
622
0
  // Check that the value stored in the histogram matches with |kExpectedValue|
623
0
  uValue = 0;
624
0
  JS::ToUint32(cx.GetJSContext(), value, &uValue);
625
0
  ASSERT_EQ(uValue, kExpectedValue) << "The histogram accumulated data when it should not have";
626
0
}
627
628
TEST_F(TelemetryTestFixture, AccumulateCategoricalHistogram_MultipleEnumValues)
629
0
{
630
0
  const uint32_t kExpectedValue = 2;
631
0
  const nsTArray<Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL> enumLabels({
632
0
                  Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel,
633
0
                  Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel});
634
0
635
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
636
0
637
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
638
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_CATEGORICAL"), false);
639
0
640
0
  // Accumulate the units into a categorical histogram using the enumLabels array
641
0
  Telemetry::AccumulateCategorical<Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL>(enumLabels);
642
0
643
0
  // Get a snapshot for all the histograms
644
0
  JS::RootedValue snapshot(cx.GetJSContext());
645
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_CATEGORICAL", &snapshot, false);
646
0
647
0
  // Get our histogram from the snapshot
648
0
  JS::RootedValue histogram(cx.GetJSContext());
649
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_CATEGORICAL", snapshot, &histogram);
650
0
651
0
  // Get counts array from histogram. Each entry in the array maps to a label in the histogram.
652
0
  JS::RootedValue counts(cx.GetJSContext());
653
0
  GetProperty(cx.GetJSContext(), "counts", histogram,  &counts);
654
0
655
0
  // Get the value for the label we care about
656
0
  JS::RootedValue value(cx.GetJSContext());
657
0
  GetElement(cx.GetJSContext(),
658
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL::CommonLabel),
659
0
             counts, &value);
660
0
661
0
  // Check that the value stored in the histogram matches with |kExpectedValue|
662
0
  uint32_t uValue = 0;
663
0
  JS::ToUint32(cx.GetJSContext(), value, &uValue);
664
0
  ASSERT_EQ(uValue, kExpectedValue) << "The histogram is not returning expected value";
665
0
}
666
667
TEST_F(TelemetryTestFixture, AccumulateKeyedCategoricalHistogram_MultipleEnumValues)
668
0
{
669
0
  const uint32_t kExpectedCommonLabel = 2;
670
0
  const uint32_t kExpectedLabel2 = 1;
671
0
  const nsTArray<Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL> enumLabels({
672
0
                  Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel,
673
0
                  Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel,
674
0
                  Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::Label2});
675
0
676
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
677
0
678
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
679
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_CATEGORICAL"), true);
680
0
681
0
  // Accumulate the array into the categorical keyed histogram
682
0
  Telemetry::AccumulateCategoricalKeyed(NS_LITERAL_CSTRING("sampleKey"), enumLabels);
683
0
684
0
  // Get a snapshot for all the histograms
685
0
  JS::RootedValue snapshot(cx.GetJSContext());
686
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_CATEGORICAL", &snapshot, true);
687
0
688
0
  // Get the histogram from the snapshot
689
0
  JS::RootedValue histogram(cx.GetJSContext());
690
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_CATEGORICAL", snapshot, &histogram);
691
0
692
0
  // Check that the sampleKey histogram contains correct number of CommonLabel samples
693
0
  JS::RootedValue sample(cx.GetJSContext());
694
0
  GetProperty(cx.GetJSContext(), "sampleKey", histogram,  &sample);
695
0
696
0
  // Get counts array from the sample. Each entry in the array maps to a label in the histogram.
697
0
  JS::RootedValue sampleKeyCounts(cx.GetJSContext());
698
0
  GetProperty(cx.GetJSContext(), "counts", sample,  &sampleKeyCounts);
699
0
700
0
  // Get the count of CommonLabel
701
0
  JS::RootedValue commonLabelValue(cx.GetJSContext());
702
0
  GetElement(cx.GetJSContext(),
703
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel),
704
0
             sampleKeyCounts, &commonLabelValue);
705
0
706
0
  // Check that the value stored in the histogram matches with |kExpectedCommonLabel|
707
0
  uint32_t uCommonLabelValue = 0;
708
0
  JS::ToUint32(cx.GetJSContext(), commonLabelValue, &uCommonLabelValue);
709
0
  ASSERT_EQ(uCommonLabelValue, kExpectedCommonLabel)
710
0
        << "The sampleKey histogram did not accumulate the correct number of CommonLabel samples";
711
0
712
0
  // Check that the sampleKey histogram contains the correct number of Label2 values
713
0
  // Get the count of Label2
714
0
  JS::RootedValue label2Value(cx.GetJSContext());
715
0
  GetElement(cx.GetJSContext(),
716
0
             static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::Label2),
717
0
             sampleKeyCounts, &label2Value);
718
0
719
0
  // Check that the value stored in the histogram matches with |kExpectedLabel2|
720
0
  uint32_t uLabel2Value = 0;
721
0
  JS::ToUint32(cx.GetJSContext(), label2Value, &uLabel2Value);
722
0
  ASSERT_EQ(uLabel2Value, kExpectedLabel2)
723
0
        << "The sampleKey histogram did not accumulate the correct number of Label2 samples";
724
0
}
725
726
TEST_F(TelemetryTestFixture, AccumulateTimeDelta)
727
0
{
728
0
  const uint32_t kExpectedValue = 100;
729
0
  const TimeStamp start = TimeStamp::Now();
730
0
  const TimeDuration delta = TimeDuration::FromMilliseconds(50);
731
0
732
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
733
0
734
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_COUNT"),
735
0
                       false);
736
0
737
0
  // Accumulate in the histogram
738
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_COUNT, start - delta, start);
739
0
740
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_COUNT, start - delta, start);
741
0
742
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_COUNT, start, start);
743
0
744
0
  // end > start timestamp gives zero contribution
745
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_COUNT, start + delta, start);
746
0
747
0
  // Get a snapshot for all the histograms
748
0
  JS::RootedValue snapshot(cx.GetJSContext());
749
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_COUNT", &snapshot, false);
750
0
751
0
  // Get the histogram from the snapshot
752
0
  JS::RootedValue histogram(cx.GetJSContext());
753
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_COUNT", snapshot, &histogram);
754
0
755
0
  // Get "sum" property from histogram
756
0
  JS::RootedValue sum(cx.GetJSContext());
757
0
  GetProperty(cx.GetJSContext(), "sum", histogram,  &sum);
758
0
759
0
  // Check that the "sum" stored in the histogram matches with |kExpectedValue|
760
0
  uint32_t uSum = 0;
761
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
762
0
  ASSERT_EQ(uSum, kExpectedValue) << "The histogram is not returning expected value";
763
0
}
764
765
TEST_F(TelemetryTestFixture, AccumulateKeyedTimeDelta)
766
0
{
767
0
  const uint32_t kExpectedValue = 100;
768
0
  const TimeStamp start = TimeStamp::Now();
769
0
  const TimeDuration delta = TimeDuration::FromMilliseconds(50);
770
0
771
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
772
0
773
0
  GetAndClearHistogram(cx.GetJSContext(), mTelemetry,
774
0
                       NS_LITERAL_CSTRING("TELEMETRY_TEST_KEYED_COUNT"), true);
775
0
776
0
  // Accumulate time delta in the provided key within the histogram
777
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_KEYED_COUNT, NS_LITERAL_CSTRING("sample"),
778
0
                                 start - delta, start);
779
0
780
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_KEYED_COUNT, NS_LITERAL_CSTRING("sample"),
781
0
                                 start - delta, start);
782
0
783
0
  // end > start timestamp gives zero contribution
784
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_KEYED_COUNT, NS_LITERAL_CSTRING("sample"),
785
0
                                 start + delta, start);
786
0
787
0
  Telemetry::AccumulateTimeDelta(Telemetry::TELEMETRY_TEST_KEYED_COUNT, NS_LITERAL_CSTRING("sample"),
788
0
                                 start, start);
789
0
790
0
  // Get a snapshot for all the histograms
791
0
  JS::RootedValue snapshot(cx.GetJSContext());
792
0
  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_KEYED_COUNT", &snapshot, true);
793
0
794
0
  // Get the histogram from the snapshot
795
0
  JS::RootedValue histogram(cx.GetJSContext());
796
0
  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_KEYED_COUNT", snapshot, &histogram);
797
0
798
0
  // Get "sample" property from histogram
799
0
  JS::RootedValue expectedKeyData(cx.GetJSContext());
800
0
  GetProperty(cx.GetJSContext(), "sample", histogram,  &expectedKeyData);
801
0
802
0
  // Get "sum" property from keyed data
803
0
  JS::RootedValue sum(cx.GetJSContext());
804
0
  GetProperty(cx.GetJSContext(), "sum", expectedKeyData,  &sum);
805
0
806
0
  // Check that the sum stored in the histogram matches with |kExpectedValue|
807
0
  uint32_t uSum = 0;
808
0
  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
809
0
  ASSERT_EQ(uSum, kExpectedValue) << "The histogram is not returning expected sum";
810
0
}