File: TelemetryTestHelpers.cpp

package info (click to toggle)
thunderbird 1%3A60.9.0-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,339,492 kB
  • sloc: cpp: 5,457,040; ansic: 2,360,385; python: 596,167; asm: 340,963; java: 326,296; xml: 258,830; sh: 84,445; makefile: 23,705; perl: 17,317; objc: 3,768; yacc: 1,766; ada: 1,681; lex: 1,364; pascal: 1,264; cs: 879; exp: 527; php: 436; lisp: 258; ruby: 153; awk: 152; sed: 53; csh: 27
file content (189 lines) | stat: -rw-r--r-- 7,639 bytes parent folder | download | duplicates (2)
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

#include "TelemetryTestHelpers.h"

#include "gtest/gtest.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/Unused.h"

using namespace mozilla;

// Helper methods provided to simplify writing tests and meant to be used in C++
// Gtests.
namespace TelemetryTestHelpers {

void CheckUintScalar(const char* aName, JSContext* aCx,
                     JS::HandleValue aSnapshot, uint32_t expectedValue) {
  // Validate the value of the test scalar.
  JS::RootedValue value(aCx);
  JS::RootedObject scalarObj(aCx, &aSnapshot.toObject());
  ASSERT_TRUE(JS_GetProperty(aCx, scalarObj, aName, &value))
      << "The test scalar must be reported.";
  JS_GetProperty(aCx, scalarObj, aName, &value);

  ASSERT_TRUE(value.isInt32())
      << "The scalar value must be of the correct type.";
  ASSERT_TRUE(value.toInt32() >= 0)
      << "The uint scalar type must contain a value >= 0.";
  ASSERT_EQ(static_cast<uint32_t>(value.toInt32()), expectedValue)
      << "The scalar value must match the expected value.";
}

void CheckBoolScalar(const char* aName, JSContext* aCx,
                     JS::HandleValue aSnapshot, bool expectedValue) {
  // Validate the value of the test scalar.
  JS::RootedValue value(aCx);
  JS::RootedObject scalarObj(aCx, &aSnapshot.toObject());
  ASSERT_TRUE(JS_GetProperty(aCx, scalarObj, aName, &value))
      << "The test scalar must be reported.";
  ASSERT_TRUE(value.isBoolean())
      << "The scalar value must be of the correct type.";
  ASSERT_EQ(static_cast<bool>(value.toBoolean()), expectedValue)
      << "The scalar value must match the expected value.";
}

void CheckStringScalar(const char* aName, JSContext* aCx,
                       JS::HandleValue aSnapshot, const char* expectedValue) {
  // Validate the value of the test scalar.
  JS::RootedValue value(aCx);
  JS::RootedObject scalarObj(aCx, &aSnapshot.toObject());
  ASSERT_TRUE(JS_GetProperty(aCx, scalarObj, aName, &value))
      << "The test scalar must be reported.";
  ASSERT_TRUE(value.isString())
      << "The scalar value must be of the correct type.";

  bool sameString;
  ASSERT_TRUE(
      JS_StringEqualsAscii(aCx, value.toString(), expectedValue, &sameString))
      << "JS String comparison failed";
  ASSERT_TRUE(sameString) << "The scalar value must match the expected string";
}

void CheckKeyedUintScalar(const char* aName, const char* aKey, JSContext* aCx,
                          JS::HandleValue aSnapshot, uint32_t expectedValue) {
  JS::RootedValue keyedScalar(aCx);
  JS::RootedObject scalarObj(aCx, &aSnapshot.toObject());
  // Get the aName keyed scalar object from the scalars snapshot.
  ASSERT_TRUE(JS_GetProperty(aCx, scalarObj, aName, &keyedScalar))
      << "The keyed scalar must be reported.";

  CheckUintScalar(aKey, aCx, keyedScalar, expectedValue);
}

void CheckKeyedBoolScalar(const char* aName, const char* aKey, JSContext* aCx,
                          JS::HandleValue aSnapshot, bool expectedValue) {
  JS::RootedValue keyedScalar(aCx);
  JS::RootedObject scalarObj(aCx, &aSnapshot.toObject());
  // Get the aName keyed scalar object from the scalars snapshot.
  ASSERT_TRUE(JS_GetProperty(aCx, scalarObj, aName, &keyedScalar))
      << "The keyed scalar must be reported.";

  CheckBoolScalar(aKey, aCx, keyedScalar, expectedValue);
}

void CheckNumberOfProperties(const char* aName, JSContext* aCx,
                             JS::HandleValue aSnapshot,
                             uint32_t expectedNumProperties) {
  JS::RootedValue keyedScalar(aCx);
  JS::RootedObject scalarObj(aCx, &aSnapshot.toObject());
  // Get the aName keyed scalar object from the scalars snapshot.
  ASSERT_TRUE(JS_GetProperty(aCx, scalarObj, aName, &keyedScalar))
      << "The keyed scalar must be reported.";

  JS::RootedObject keyedScalarObj(aCx, &keyedScalar.toObject());
  JS::Rooted<JS::IdVector> ids(aCx, JS::IdVector(aCx));
  ASSERT_TRUE(JS_Enumerate(aCx, keyedScalarObj, &ids))
      << "We must be able to get keyed scalar members.";

  ASSERT_EQ(expectedNumProperties, ids.length())
      << "The scalar must report the expected number of properties.";
}

void GetScalarsSnapshot(bool aKeyed, JSContext* aCx,
                        JS::MutableHandle<JS::Value> aResult) {
  nsCOMPtr<nsITelemetry> telemetry =
      do_GetService("@mozilla.org/base/telemetry;1");

  // Get a snapshot of the scalars.
  JS::RootedValue scalarsSnapshot(aCx);
  nsresult rv;

  if (aKeyed) {
    rv = telemetry->SnapshotKeyedScalars(
        nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN, false, aCx, 0,
        &scalarsSnapshot);
  } else {
    rv = telemetry->SnapshotScalars(nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN,
                                    false, aCx, 0, &scalarsSnapshot);
  }

  // Validate the snapshot.
  ASSERT_EQ(rv, NS_OK) << "Creating a snapshot of the data must not fail.";
  ASSERT_TRUE(scalarsSnapshot.isObject()) << "The snapshot must be an object.";

  // We currently only support scalars from the parent process in the gtests.
  JS::RootedValue parentScalars(aCx);
  JS::RootedObject scalarObj(aCx, &scalarsSnapshot.toObject());
  // Don't complain if no scalars for the parent process can be found. Just
  // return an empty object.
  Unused << JS_GetProperty(aCx, scalarObj, "parent", &parentScalars);

  aResult.set(parentScalars);
}

void GetAndClearHistogram(JSContext* cx, nsCOMPtr<nsITelemetry> mTelemetry,
                          const nsACString& name, bool is_keyed) {
  JS::RootedValue testHistogram(cx);
  nsresult rv =
      is_keyed ? mTelemetry->GetKeyedHistogramById(name, cx, &testHistogram)
               : mTelemetry->GetHistogramById(name, cx, &testHistogram);

  ASSERT_EQ(rv, NS_OK) << "Cannot fetch histogram";

  // Clear the stored value
  JS::RootedObject testHistogramObj(cx, &testHistogram.toObject());
  JS::RootedValue rval(cx);
  ASSERT_TRUE(JS_CallFunctionName(cx, testHistogramObj, "clear",
                                  JS::HandleValueArray::empty(), &rval))
      << "Cannot clear histogram";
}

void GetProperty(JSContext* cx, const char* name, JS::HandleValue valueIn,
                 JS::MutableHandleValue valueOut) {
  JS::RootedValue property(cx);
  JS::RootedObject valueInObj(cx, &valueIn.toObject());
  ASSERT_TRUE(JS_GetProperty(cx, valueInObj, name, &property))
      << "Cannot get property '" << name << "'";
  valueOut.set(property);
}

void GetElement(JSContext* cx, uint32_t index, JS::HandleValue valueIn,
                JS::MutableHandleValue valueOut) {
  JS::RootedValue element(cx);
  JS::RootedObject valueInObj(cx, &valueIn.toObject());
  ASSERT_TRUE(JS_GetElement(cx, valueInObj, index, &element))
      << "Cannot get element at index '" << index << "'";
  valueOut.set(element);
}

void GetSnapshots(JSContext* cx, nsCOMPtr<nsITelemetry> mTelemetry,
                  const char* name, JS::MutableHandleValue valueOut,
                  bool is_keyed) {
  JS::RootedValue snapshots(cx);
  nsresult rv = is_keyed ? mTelemetry->SnapshotKeyedHistograms(
                               nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN,
                               false, false, cx, &snapshots)
                         : mTelemetry->SnapshotHistograms(
                               nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN,
                               false, false, cx, &snapshots);

  JS::RootedValue snapshot(cx);
  GetProperty(cx, "parent", snapshots, &snapshot);

  ASSERT_EQ(rv, NS_OK) << "Cannot call histogram snapshots";
  valueOut.set(snapshot);
}

}  // namespace TelemetryTestHelpers