Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/telemetry/tests/gtest/TestScalars.cpp
Line
Count
Source (jump to first uncovered line)
1
/* vim:set ts=2 sw=2 sts=2 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
8
#include "js/Conversions.h"
9
#include "mozilla/Unused.h"
10
#include "nsJSUtils.h" // nsAutoJSString
11
#include "nsITelemetry.h"
12
#include "nsThreadUtils.h"
13
#include "mozilla/Telemetry.h"
14
#include "mozilla/TelemetryProcessEnums.h"
15
#include "TelemetryFixture.h"
16
#include "core/TelemetryScalar.h"
17
#include "TelemetryTestHelpers.h"
18
19
using namespace mozilla;
20
using namespace TelemetryTestHelpers;
21
using mozilla::Telemetry::ProcessID;
22
23
0
#define EXPECTED_STRING "Nice, expected and creative string."
24
25
// Test that we can properly write unsigned scalars using the C++ API.
26
0
TEST_F(TelemetryTestFixture, ScalarUnsigned) {
27
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
28
0
29
0
  // Make sure we don't get scalars from other tests.
30
0
  Unused << mTelemetry->ClearScalars();
31
0
32
0
  // Set the test scalar to a known value.
33
0
  const uint32_t kInitialValue = 1172015;
34
0
  const uint32_t kExpectedUint = 1172017;
35
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, kInitialValue);
36
0
  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, kExpectedUint - kInitialValue);
37
0
38
0
  // Check the recorded value.
39
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
40
0
  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
41
0
  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, kExpectedUint);
42
0
43
0
  // Try to use SetMaximum.
44
0
  const uint32_t kExpectedUintMaximum = kExpectedUint * 2;
45
0
  Telemetry::ScalarSetMaximum(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, kExpectedUintMaximum);
46
0
47
0
  // Make sure that calls of the unsupported type don't corrupt the stored value.
48
0
  // Don't run this part in debug builds as that intentionally asserts.
49
0
  #ifndef DEBUG
50
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, false);
51
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, NS_LITERAL_STRING("test"));
52
0
  #endif
53
0
54
0
  // Check the recorded value.
55
0
  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
56
0
  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, kExpectedUintMaximum);
57
0
}
58
59
// Test that we can properly write boolean scalars using the C++ API.
60
0
TEST_F(TelemetryTestFixture, ScalarBoolean) {
61
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
62
0
63
0
  Unused << mTelemetry->ClearScalars();
64
0
65
0
  // Set the test scalar to a known value.
66
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, true);
67
0
68
0
  // Make sure that calls of the unsupported type don't corrupt the stored value.
69
0
  // Don't run this part in debug builds as that intentionally asserts.
70
0
  #ifndef DEBUG
71
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, static_cast<uint32_t>(12));
72
0
    Telemetry::ScalarSetMaximum(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, 20);
73
0
    Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, 2);
74
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, NS_LITERAL_STRING("test"));
75
0
  #endif
76
0
77
0
  // Check the recorded value.
78
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
79
0
  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
80
0
  CheckBoolScalar("telemetry.test.boolean_kind", cx.GetJSContext(), scalarsSnapshot, true);
81
0
}
82
83
// Test that we can properly write string scalars using the C++ API.
84
0
TEST_F(TelemetryTestFixture, ScalarString) {
85
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
86
0
87
0
  Unused << mTelemetry->ClearScalars();
88
0
89
0
  // Set the test scalar to a known value.
90
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, NS_LITERAL_STRING(EXPECTED_STRING));
91
0
92
0
  // Make sure that calls of the unsupported type don't corrupt the stored value.
93
0
  // Don't run this part in debug builds as that intentionally asserts.
94
0
  #ifndef DEBUG
95
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, static_cast<uint32_t>(12));
96
0
    Telemetry::ScalarSetMaximum(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, 20);
97
0
    Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, 2);
98
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, true);
99
0
  #endif
100
0
101
0
  // Check the recorded value.
102
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
103
0
  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
104
0
  CheckStringScalar("telemetry.test.string_kind", cx.GetJSContext(), scalarsSnapshot, EXPECTED_STRING);
105
0
}
106
107
// Test that we can properly write keyed unsigned scalars using the C++ API.
108
0
TEST_F(TelemetryTestFixture, KeyedScalarUnsigned) {
109
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
110
0
111
0
  Unused << mTelemetry->ClearScalars();
112
0
113
0
  // Set the test scalar to a known value.
114
0
  const char* kScalarName = "telemetry.test.keyed_unsigned_int";
115
0
  const uint32_t kKey1Value = 1172015;
116
0
  const uint32_t kKey2Value = 1172017;
117
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
118
0
                       NS_LITERAL_STRING("key1"), kKey1Value);
119
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
120
0
                       NS_LITERAL_STRING("key2"), kKey1Value);
121
0
  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
122
0
                       NS_LITERAL_STRING("key2"), 2);
123
0
124
0
  // Make sure that calls of the unsupported type don't corrupt the stored value.
125
0
  // Don't run this part in debug builds as that intentionally asserts.
126
0
  #ifndef DEBUG
127
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
128
0
                         NS_LITERAL_STRING("key1"), false);
129
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT, NS_LITERAL_STRING("test"));
130
0
  #endif
131
0
132
0
  // Check the recorded value.
133
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
134
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
135
0
136
0
  // Check the keyed scalar we're interested in.
137
0
  CheckKeyedUintScalar(kScalarName, "key1", cx.GetJSContext(), scalarsSnapshot, kKey1Value);
138
0
  CheckKeyedUintScalar(kScalarName, "key2", cx.GetJSContext(), scalarsSnapshot, kKey2Value);
139
0
  CheckNumberOfProperties(kScalarName, cx.GetJSContext(), scalarsSnapshot, 2);
140
0
141
0
  // Try to use SetMaximum.
142
0
  const uint32_t kExpectedUintMaximum = kKey1Value * 2;
143
0
  Telemetry::ScalarSetMaximum(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
144
0
                              NS_LITERAL_STRING("key1"), kExpectedUintMaximum);
145
0
146
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
147
0
  // The first key should be different and te second is expected to be the same.
148
0
  CheckKeyedUintScalar(kScalarName, "key1", cx.GetJSContext(), scalarsSnapshot, kExpectedUintMaximum);
149
0
  CheckKeyedUintScalar(kScalarName, "key2", cx.GetJSContext(), scalarsSnapshot, kKey2Value);
150
0
  CheckNumberOfProperties(kScalarName, cx.GetJSContext(), scalarsSnapshot, 2);
151
0
}
152
153
0
TEST_F(TelemetryTestFixture, KeyedScalarBoolean) {
154
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
155
0
156
0
  Unused << mTelemetry->ClearScalars();
157
0
158
0
  // Set the test scalar to a known value.
159
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
160
0
                       NS_LITERAL_STRING("key1"), false);
161
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
162
0
                       NS_LITERAL_STRING("key2"), true);
163
0
164
0
  // Make sure that calls of the unsupported type don't corrupt the stored value.
165
0
  // Don't run this part in debug builds as that intentionally asserts.
166
0
  #ifndef DEBUG
167
0
    Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
168
0
                         NS_LITERAL_STRING("key1"), static_cast<uint32_t>(12));
169
0
    Telemetry::ScalarSetMaximum(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
170
0
                                NS_LITERAL_STRING("key1"), 20);
171
0
    Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
172
0
                         NS_LITERAL_STRING("key1"), 2);
173
0
  #endif
174
0
175
0
  // Check the recorded value.
176
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
177
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
178
0
179
0
  // Make sure that the keys contain the expected values.
180
0
  const char* kScalarName = "telemetry.test.keyed_boolean_kind";
181
0
  CheckKeyedBoolScalar(kScalarName, "key1", cx.GetJSContext(), scalarsSnapshot, false);
182
0
  CheckKeyedBoolScalar(kScalarName, "key2", cx.GetJSContext(), scalarsSnapshot, true);
183
0
  CheckNumberOfProperties(kScalarName, cx.GetJSContext(), scalarsSnapshot, 2);
184
0
}
185
186
0
TEST_F(TelemetryTestFixture, NonMainThreadAdd) {
187
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
188
0
189
0
  Unused << mTelemetry->ClearScalars();
190
0
191
0
  // Define the function that will be called on the testing thread.
192
0
  nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
193
0
    "TelemetryTestFixture_NonMainThreadAdd_Test::TestBody", []() -> void {
194
0
      Telemetry::ScalarAdd(
195
0
        Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, 37);
196
0
    });
197
0
198
0
  // Spawn the testing thread and run the function.
199
0
  nsCOMPtr<nsIThread> testingThread;
200
0
  nsresult rv =
201
0
    NS_NewNamedThread("Test thread", getter_AddRefs(testingThread), runnable);
202
0
  ASSERT_EQ(rv, NS_OK);
203
0
204
0
  // Shutdown the thread. This also waits for the runnable to complete.
205
0
  testingThread->Shutdown();
206
0
207
0
  // Check the recorded value.
208
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
209
0
  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
210
0
  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, 37);
211
0
}
212
213
0
TEST_F(TelemetryTestFixture, ScalarUnknownID) {
214
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
215
0
216
0
  // Make sure we don't get scalars from other tests.
217
0
  Unused << mTelemetry->ClearScalars();
218
0
219
0
// Don't run this part in debug builds as that intentionally asserts.
220
0
#ifndef DEBUG
221
0
  const uint32_t kTestFakeIds[] = {
222
0
    static_cast<uint32_t>(Telemetry::ScalarID::ScalarCount),
223
0
    static_cast<uint32_t>(Telemetry::ScalarID::ScalarCount) + 378537,
224
0
    std::numeric_limits<uint32_t>::max()
225
0
  };
226
0
227
0
  for (auto id : kTestFakeIds) {
228
0
    Telemetry::ScalarID scalarId = static_cast<Telemetry::ScalarID>(id);
229
0
    Telemetry::ScalarSet(scalarId, static_cast<uint32_t>(1));
230
0
    Telemetry::ScalarSet(scalarId, true);
231
0
    Telemetry::ScalarSet(scalarId, NS_LITERAL_STRING("test"));
232
0
    Telemetry::ScalarAdd(scalarId, 1);
233
0
    Telemetry::ScalarSetMaximum(scalarId, 1);
234
0
235
0
    // Make sure that nothing was recorded in the plain scalars.
236
0
    JS::RootedValue scalarsSnapshot(cx.GetJSContext());
237
0
    GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
238
0
    ASSERT_TRUE(scalarsSnapshot.isUndefined()) << "No scalar must be recorded";
239
0
240
0
    // Same for the keyed scalars.
241
0
    Telemetry::ScalarSet(scalarId, NS_LITERAL_STRING("key1"), static_cast<uint32_t>(1));
242
0
    Telemetry::ScalarSet(scalarId, NS_LITERAL_STRING("key1"), true);
243
0
    Telemetry::ScalarAdd(scalarId, NS_LITERAL_STRING("key1"), 1);
244
0
    Telemetry::ScalarSetMaximum(scalarId, NS_LITERAL_STRING("key1"), 1);
245
0
246
0
    // Make sure that nothing was recorded in the keyed scalars.
247
0
    JS::RootedValue keyedSnapshot(cx.GetJSContext());
248
0
    GetScalarsSnapshot(true, cx.GetJSContext(), &keyedSnapshot);
249
0
    ASSERT_TRUE(keyedSnapshot.isUndefined()) << "No keyed scalar must be recorded";
250
0
  }
251
0
#endif
252
0
}
253
254
0
TEST_F(TelemetryTestFixture, ScalarEventSummary) {
255
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
256
0
257
0
  // Make sure we don't get scalars from other tests.
258
0
  Unused << mTelemetry->ClearScalars();
259
0
260
0
  const char* kScalarName = "telemetry.event_counts";
261
0
262
0
  const char* kLongestEvent = "oohwowlookthiscategoryissolong#thismethodislongtooo#thisobjectisnoslouch";
263
0
  TelemetryScalar::SummarizeEvent(nsCString(kLongestEvent), ProcessID::Parent, false /* aDynamic */);
264
0
265
0
  // Check the recorded value.
266
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
267
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
268
0
269
0
  CheckKeyedUintScalar(kScalarName, kLongestEvent, cx.GetJSContext(), scalarsSnapshot, 1);
270
0
271
0
// Don't run this part in debug builds as that intentionally asserts.
272
0
#ifndef DEBUG
273
0
  const char* kTooLongEvent = "oohwowlookthiscategoryissolong#thismethodislongtooo#thisobjectisnoslouch2";
274
0
  TelemetryScalar::SummarizeEvent(nsCString(kTooLongEvent), ProcessID::Parent, false /* aDynamic */);
275
0
276
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
277
0
  CheckNumberOfProperties(kScalarName, cx.GetJSContext(), scalarsSnapshot, 1);
278
0
#endif // #ifndef DEBUG
279
0
280
0
  // Test we can fill the next 499 keys up to our 500 maximum
281
0
  for (int i = 1; i < 500; i++) {
282
0
    std::ostringstream eventName;
283
0
    eventName << "category#method#object" << i;
284
0
    TelemetryScalar::SummarizeEvent(nsCString(eventName.str().c_str()), ProcessID::Parent, false /* aDynamic */);
285
0
  }
286
0
287
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
288
0
  CheckNumberOfProperties(kScalarName, cx.GetJSContext(), scalarsSnapshot, 500);
289
0
290
0
// Don't run this part in debug builds as that intentionally asserts.
291
0
#ifndef DEBUG
292
0
  TelemetryScalar::SummarizeEvent(nsCString("whoops#too#many"), ProcessID::Parent, false /* aDynamic */);
293
0
294
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
295
0
  CheckNumberOfProperties(kScalarName, cx.GetJSContext(), scalarsSnapshot, 500);
296
0
#endif // #ifndef DEBUG
297
0
298
0
}
299
300
0
TEST_F(TelemetryTestFixture, ScalarEventSummary_Dynamic) {
301
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
302
0
303
0
  // Make sure we don't get scalars from other tests.
304
0
  Unused << mTelemetry->ClearScalars();
305
0
306
0
  const char* kScalarName = "telemetry.dynamic_event_counts";
307
0
  const char* kLongestEvent = "oohwowlookthiscategoryissolong#thismethodislongtooo#thisobjectisnoslouch";
308
0
  TelemetryScalar::SummarizeEvent(nsCString(kLongestEvent), ProcessID::Parent, true /* aDynamic */);
309
0
  TelemetryScalar::SummarizeEvent(nsCString(kLongestEvent), ProcessID::Content, true /* aDynamic */);
310
0
311
0
  // Check the recorded value.
312
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
313
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot, ProcessID::Dynamic);
314
0
315
0
  // Recording in parent or content doesn't matter for dynamic scalars
316
0
  // which all end up in the same place.
317
0
  CheckKeyedUintScalar(kScalarName, kLongestEvent, cx.GetJSContext(), scalarsSnapshot, 2);
318
0
}
319
320
0
TEST_F(TelemetryTestFixture, WrongScalarOperator) {
321
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
322
0
323
0
  // Make sure we don't get scalars from other tests.
324
0
  Unused << mTelemetry->ClearScalars();
325
0
326
0
  const uint32_t expectedValue = 1172015;
327
0
328
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, expectedValue);
329
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, NS_LITERAL_STRING(EXPECTED_STRING));
330
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, true);
331
0
332
0
  TelemetryScalar::DeserializationStarted();
333
0
334
0
  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, 1447);
335
0
  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, 1447);
336
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, true);
337
0
  TelemetryScalar::ApplyPendingOperations();
338
0
339
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
340
0
  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
341
0
  CheckStringScalar("telemetry.test.string_kind", cx.GetJSContext(), scalarsSnapshot, EXPECTED_STRING);
342
0
  CheckBoolScalar("telemetry.test.boolean_kind", cx.GetJSContext(), scalarsSnapshot, true);
343
0
  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, expectedValue);
344
0
}
345
346
0
TEST_F(TelemetryTestFixture, WrongKeyedScalarOperator) {
347
0
  AutoJSContextWithGlobal cx(mCleanGlobal);
348
0
349
0
  // Make sure we don't get scalars from other tests.
350
0
  Unused << mTelemetry->ClearScalars();
351
0
352
0
  const uint32_t kExpectedUint = 1172017;
353
0
354
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
355
0
                       NS_LITERAL_STRING("key1"), kExpectedUint);
356
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
357
0
                       NS_LITERAL_STRING("key2"), true);
358
0
359
0
  TelemetryScalar::DeserializationStarted();
360
0
361
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
362
0
                       NS_LITERAL_STRING("key1"), false);
363
0
  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
364
0
                       NS_LITERAL_STRING("key2"), static_cast<uint32_t>(13));
365
0
366
0
  TelemetryScalar::ApplyPendingOperations();
367
0
368
0
  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
369
0
  GetScalarsSnapshot(true, cx.GetJSContext(), &scalarsSnapshot);
370
0
  CheckKeyedUintScalar("telemetry.test.keyed_unsigned_int", "key1",
371
0
                       cx.GetJSContext(), scalarsSnapshot, kExpectedUint);
372
0
  CheckKeyedBoolScalar("telemetry.test.keyed_boolean_kind", "key2",
373
0
                       cx.GetJSContext(), scalarsSnapshot, true);
374
0
}