зеркало из https://github.com/mozilla/glean.git
Bug 1791789 - Fix for iOS startup crash caused by Glean (#2206)
This commit is contained in:
Родитель
232ac2a1d2
Коммит
679691540c
|
@ -23,6 +23,7 @@
|
|||
1FB8F8382326EABD00618E47 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB8F8372326EABD00618E47 /* ConfigurationTests.swift */; };
|
||||
1FD4527523395B4500F4C7E8 /* UuidMetric.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD4527423395B4500F4C7E8 /* UuidMetric.swift */; };
|
||||
1FD4527723395EEB00F4C7E8 /* UuidMetricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD4527623395EEB00F4C7E8 /* UuidMetricTests.swift */; };
|
||||
60691AEB28DD0BF200BDF31A /* BaselinePingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60691AEA28DD0BF200BDF31A /* BaselinePingTests.swift */; };
|
||||
AC06529C26E032E300D92D5E /* QuantityMetric.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC06529B26E032E300D92D5E /* QuantityMetric.swift */; };
|
||||
AC06529E26E034BF00D92D5E /* QuantityMetricTypeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC06529D26E034BF00D92D5E /* QuantityMetricTypeTest.swift */; };
|
||||
AC1DB401237EF0ED005A0F8A /* Glean.h in Headers */ = {isa = PBXBuildFile; fileRef = BF3DE3942243A2F20018E23F /* Glean.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -95,6 +96,7 @@
|
|||
1FB8F8372326EABD00618E47 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = "<group>"; };
|
||||
1FD4527423395B4500F4C7E8 /* UuidMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UuidMetric.swift; sourceTree = "<group>"; };
|
||||
1FD4527623395EEB00F4C7E8 /* UuidMetricTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UuidMetricTests.swift; sourceTree = "<group>"; };
|
||||
60691AEA28DD0BF200BDF31A /* BaselinePingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BaselinePingTests.swift; path = Net/BaselinePingTests.swift; sourceTree = "<group>"; };
|
||||
AC06529B26E032E300D92D5E /* QuantityMetric.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuantityMetric.swift; sourceTree = "<group>"; };
|
||||
AC06529D26E034BF00D92D5E /* QuantityMetricTypeTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuantityMetricTypeTest.swift; sourceTree = "<group>"; };
|
||||
BF10007F23548B0500064051 /* MemoryDistributionMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryDistributionMetric.swift; sourceTree = "<group>"; };
|
||||
|
@ -292,6 +294,7 @@
|
|||
BF3DE39E2243A2F20018E23F /* GleanTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
60691AEA28DD0BF200BDF31A /* BaselinePingTests.swift */,
|
||||
1F39E7B1239F0741009B13B3 /* Debug */,
|
||||
1FB8F8392326EBA500618E47 /* Config */,
|
||||
BF43A8CB232A613100545310 /* Metrics */,
|
||||
|
@ -546,7 +549,7 @@
|
|||
};
|
||||
CD0CADA527E216F40015A997 /* Run UniFFI bindgen */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
buildActionMask = 12;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
|
@ -611,6 +614,7 @@
|
|||
files = (
|
||||
1F39E7B3239F0777009B13B3 /* GleanDebugUtilityTests.swift in Sources */,
|
||||
BFAED50A2369752400DF293D /* StringListMetricTests.swift in Sources */,
|
||||
60691AEB28DD0BF200BDF31A /* BaselinePingTests.swift in Sources */,
|
||||
BF890561232BC227003CA2BA /* StringMetricTests.swift in Sources */,
|
||||
CD0F7CC226F0F28900EDA6A4 /* UrlMetricTests.swift in Sources */,
|
||||
BFCBD6AB246D55CC0032096D /* TestUtils.swift in Sources */,
|
||||
|
|
|
@ -150,36 +150,33 @@ public class HttpPingUploader {
|
|||
func process() {
|
||||
// Limits are enforced by glean-core to avoid an inifinite loop here.
|
||||
// Whenever a limit is reached, this binding will receive `.done` and step out.
|
||||
while true {
|
||||
let task = gleanGetUploadTask()
|
||||
let task = gleanGetUploadTask()
|
||||
|
||||
switch task {
|
||||
case let .upload(request):
|
||||
var body = Data(capacity: request.body.count)
|
||||
body.append(contentsOf: request.body)
|
||||
self.upload(path: request.path, data: body, headers: request.headers) { result in
|
||||
let action = gleanProcessPingUploadResponse(request.documentId, result)
|
||||
switch action {
|
||||
case .next:
|
||||
// launch a new iteration.
|
||||
Dispatchers.shared.launchAsync {
|
||||
HttpPingUploader(configuration: self.config, testingMode: self.testingMode).process()
|
||||
}
|
||||
case .end:
|
||||
return
|
||||
switch task {
|
||||
case let .upload(request):
|
||||
var body = Data(capacity: request.body.count)
|
||||
body.append(contentsOf: request.body)
|
||||
self.upload(path: request.path, data: body, headers: request.headers) { result in
|
||||
let action = gleanProcessPingUploadResponse(request.documentId, result)
|
||||
switch action {
|
||||
case .next:
|
||||
// launch a new iteration.
|
||||
Dispatchers.shared.launchAsync {
|
||||
HttpPingUploader(configuration: self.config, testingMode: self.testingMode).process()
|
||||
}
|
||||
|
||||
case .end:
|
||||
return
|
||||
}
|
||||
|
||||
// we don't want to launch multiple uploads at once.
|
||||
// if the upload finishes, we going to launch the next one.
|
||||
return
|
||||
case .wait(let time):
|
||||
sleep(UInt32(time) / 1000)
|
||||
continue
|
||||
case .done:
|
||||
return
|
||||
}
|
||||
case .wait(let time):
|
||||
sleep(UInt32(time) / 1000)
|
||||
// launch a new iteration.
|
||||
Dispatchers.shared.launchAsync {
|
||||
HttpPingUploader(configuration: self.config, testingMode: self.testingMode).process()
|
||||
}
|
||||
case .done:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import XCTest
|
|||
|
||||
private typealias GleanInternalMetrics = GleanMetrics.GleanInternalMetrics
|
||||
|
||||
// swiftlint:disable type_body_length
|
||||
class GleanTests: XCTestCase {
|
||||
var expectation: XCTestExpectation?
|
||||
|
||||
|
@ -103,224 +102,6 @@ class GleanTests: XCTestCase {
|
|||
)
|
||||
}
|
||||
|
||||
func testSendingOfForegroundBaselinePing() {
|
||||
stubServerReceive { _, json in
|
||||
// Check for the "dirty_startup" flag
|
||||
let pingInfo = json?["ping_info"] as? [String: Any]
|
||||
XCTAssertEqual("active", pingInfo?["reason"] as? String)
|
||||
|
||||
// We may get error metrics in foreground pings,
|
||||
// so 'metrics' may exist.
|
||||
let metrics = json?["metrics"] as? [String: Any]
|
||||
if metrics != nil {
|
||||
// Since we are only expecting error metrics,
|
||||
// let's check that this is all we got (plus the `validation.first_run_hour`).
|
||||
XCTAssertEqual(metrics?.count, 2, "metrics has more keys than expected: \(JSONStringify(metrics!))")
|
||||
let labeledCounters = metrics?["labeled_counter"] as? [String: Any]
|
||||
labeledCounters!.forEach { key, _ in
|
||||
XCTAssertTrue(
|
||||
key.starts(with: "glean.error") || key.starts(with: "glean.validation"),
|
||||
"Should only see glean.* counters, saw \(key)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the expectation that will be fulfilled by the stub above
|
||||
expectation = expectation(description: "Baseline Ping Received")
|
||||
|
||||
// Set the last time the "metrics" ping was sent to now. This is required for us to not
|
||||
// send a metrics pings the first time we initialize Glean and to keep it from interfering
|
||||
// with these tests.
|
||||
let now = Date()
|
||||
Glean.shared.metricsPingScheduler!.updateSentDate(now)
|
||||
|
||||
// Resetting Glean doesn't trigger lifecycle events in tests so we must call the method
|
||||
// invoked by the lifecycle observer directly.
|
||||
Glean.shared.handleForegroundEvent()
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME: This test causes crashes in subsequent tests,
|
||||
probably because of some race condition triggered by restarting Glean.
|
||||
func testSendingOfBaselinePingWithDirtyFlag() {
|
||||
// Set the dirty flag
|
||||
gleanSetDirtyFlag(true)
|
||||
|
||||
// Set up the test stub based on the default telemetry endpoint
|
||||
stubServerReceive { pingType, json in
|
||||
XCTAssertEqual("baseline", pingType)
|
||||
XCTAssert(json != nil)
|
||||
|
||||
// Check for the "dirty_startup" flag
|
||||
let pingInfo = json!["ping_info"] as! [String: Any]
|
||||
let reason = pingInfo["reason"] as! String
|
||||
if reason == "active" {
|
||||
// Skip initial "active" ping.
|
||||
// Glean is initialized ahead of this test and thus we might get one.
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual("dirty_startup", reason, "Expected a dirty_startup, got \(reason)")
|
||||
|
||||
// 'metrics' will exist and include exactly one valid metric.
|
||||
// No errors should be reported.
|
||||
let metrics = json!["metrics"] as? [String: Any]
|
||||
if metrics != nil {
|
||||
let datetimes = metrics!["datetime"] as! [String: Any]
|
||||
XCTAssertTrue(datetimes.keys.contains("glean.validation.first_run_hour"),
|
||||
"Datetime should have first_run_hour: \(datetimes)")
|
||||
|
||||
if metrics!.count > 1 {
|
||||
// Since we are only expecting error metrics,
|
||||
// let's check that this is all we got (plus the `validation.first_run_hour`).
|
||||
XCTAssertEqual(metrics?.count, 2, "metrics has more keys than expected: \(JSONStringify(metrics!))")
|
||||
let labeledCounters = metrics?["labeled_counter"] as? [String: Any]
|
||||
labeledCounters!.forEach { key, _ in
|
||||
XCTAssertTrue(
|
||||
key.starts(with: "glean.error") || key.starts(with: "glean.validation"),
|
||||
"Should only see glean.* counters, saw \(key)"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the expectation that will be fulfilled by the stub above
|
||||
expectation = expectation(description: "Baseline Ping Received")
|
||||
|
||||
// Set the last time the "metrics" ping was sent to now. This is required for us to not
|
||||
// send a metrics pings the first time we initialize Glean and to keep it from interfering
|
||||
// with these tests.
|
||||
let now = Date()
|
||||
Glean.shared.metricsPingScheduler.updateSentDate(now)
|
||||
// Restart Glean and don't clear the stores and then await the expectation
|
||||
Glean.shared.resetGlean(clearStores: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func testSendingDeletionPingIfDisabledOutsideOfRun() {
|
||||
stubServerReceive { pingType, _ in
|
||||
// Since we are starting Glean with upload disabled, the only ping we
|
||||
// should see is the deletion request ping
|
||||
XCTAssertEqual("deletion-request", pingType)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the expectation that will be fulfilled by the stub above
|
||||
expectation = expectation(description: "Deletion Request Received")
|
||||
|
||||
// Now reset Glean with uploadEnabled = false and not clearing the stores to
|
||||
// trigger the deletion request ping. Since `uploadEnabled` is `false`, only
|
||||
// the deletion-request ping should be generated.
|
||||
Glean.shared.resetGlean(clearStores: false, uploadEnabled: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
|
||||
func testNotSendingDeletionRequestIfUnchangedOutsideOfRun() {
|
||||
XCTAssert(Glean.shared.isInitialized(), "Glean should be initialized")
|
||||
|
||||
// Set up the test stub based on the default telemetry endpoint
|
||||
stubServerReceive { _, _ in
|
||||
XCTFail("Should not have recieved any ping")
|
||||
}
|
||||
|
||||
// Set up the expectation that will NOT be fulfilled by the stub above. If it is
|
||||
// then it will trigger an assertion due to the `assertForOverFulfill` property.
|
||||
expectation = expectation(description: "Deletion Request Received")
|
||||
|
||||
// So we can wait for expectations below, we will go ahead and fulfill the
|
||||
// expectation. We want to assert if the ping is triggered and over fulfills it
|
||||
// from the stub above.
|
||||
expectation?.fulfill()
|
||||
|
||||
// Reset Glean with uploadEnabled = false
|
||||
Glean.shared.resetGlean(clearStores: true, uploadEnabled: false)
|
||||
|
||||
// Now reset Glean with uploadEnabled = false again without clearing the stores to
|
||||
// make sure we don't trigger the deletion request ping. If it does, then we will
|
||||
// have overfulfilled the expectation which will trigger a test assertion.
|
||||
Glean.shared.resetGlean(clearStores: false, uploadEnabled: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable force_cast
|
||||
func testSendingOfStartupBaselinePingWithAppLifetimeMetric() {
|
||||
// Set the dirty flag.
|
||||
gleanSetDirtyFlag(true)
|
||||
|
||||
let stringMetric = StringMetricType(CommonMetricData(
|
||||
category: "telemetry",
|
||||
name: "app_lifetime",
|
||||
sendInPings: ["baseline"],
|
||||
lifetime: .application,
|
||||
disabled: false
|
||||
))
|
||||
stringMetric.set("HELLOOOOO!")
|
||||
|
||||
// Set up the test stub based on the default telemetry endpoint
|
||||
stubServerReceive { pingType, json in
|
||||
XCTAssertEqual("baseline", pingType)
|
||||
XCTAssert(json != nil)
|
||||
|
||||
// Check for the "dirty_startup" flag
|
||||
let pingInfo = json!["ping_info"] as! [String: Any]
|
||||
let reason = pingInfo["reason"] as! String
|
||||
if reason == "active" {
|
||||
// Skip initial "active" ping.
|
||||
// Glean is initialized ahead of this test and thus we might get one.
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual("dirty_startup", reason)
|
||||
|
||||
// Ensure there is only the expected locale string metric
|
||||
let metrics = json?["metrics"] as? [String: Any]
|
||||
let strings = metrics?["string"] as? [String: Any]
|
||||
let metric = strings?["telemetry.app_lifetime"] as? String
|
||||
XCTAssertEqual("HELLOOOOO!", metric)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
expectation = expectation(description: "baseline ping received")
|
||||
|
||||
// Restart glean and don't clear the stores.
|
||||
// This should trigger a baseline ping with a "dirty_startup" reason.
|
||||
Glean.shared.resetGlean(clearStores: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
// swiftlint:enable force_cast
|
||||
|
||||
func testGleanIsNotInitializedFromOtherProcesses() {
|
||||
// Check to see if Glean is initialized
|
||||
XCTAssert(Glean.shared.isInitialized())
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
/* 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/. */
|
||||
|
||||
@testable import Glean
|
||||
import OHHTTPStubs
|
||||
import OHHTTPStubsSwift
|
||||
import XCTest
|
||||
|
||||
final class BaselinePingTests: XCTestCase {
|
||||
var expectation: XCTestExpectation?
|
||||
|
||||
override func setUp() {
|
||||
resetGleanDiscardingInitialPings(testCase: self, tag: "GleanTests")
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
Glean.shared.testDestroyGleanHandle()
|
||||
expectation = nil
|
||||
tearDownStubs()
|
||||
}
|
||||
|
||||
func testSendingOfForegroundBaselinePing() {
|
||||
stubServerReceive { _, json in
|
||||
// Check for the "dirty_startup" flag
|
||||
let pingInfo = json?["ping_info"] as? [String: Any]
|
||||
XCTAssertEqual("active", pingInfo?["reason"] as? String)
|
||||
|
||||
// We may get error metrics in foreground pings,
|
||||
// so 'metrics' may exist.
|
||||
let metrics = json?["metrics"] as? [String: Any]
|
||||
if metrics != nil {
|
||||
// Since we are only expecting error metrics,
|
||||
// let's check that this is all we got (plus the `validation.first_run_hour`).
|
||||
XCTAssertEqual(metrics?.count, 2, "metrics has more keys than expected: \(JSONStringify(metrics!))")
|
||||
let labeledCounters = metrics?["labeled_counter"] as? [String: Any]
|
||||
labeledCounters!.forEach { key, _ in
|
||||
XCTAssertTrue(
|
||||
key.starts(with: "glean.error") || key.starts(with: "glean.validation"),
|
||||
"Should only see glean.* counters, saw \(key)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the expectation that will be fulfilled by the stub above
|
||||
expectation = expectation(description: "Baseline Ping Received")
|
||||
|
||||
// Set the last time the "metrics" ping was sent to now. This is required for us to not
|
||||
// send a metrics pings the first time we initialize Glean and to keep it from interfering
|
||||
// with these tests.
|
||||
let now = Date()
|
||||
Glean.shared.metricsPingScheduler!.updateSentDate(now)
|
||||
|
||||
// Resetting Glean doesn't trigger lifecycle events in tests so we must call the method
|
||||
// invoked by the lifecycle observer directly.
|
||||
Glean.shared.handleForegroundEvent()
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME: This test causes crashes in subsequent tests,
|
||||
probably because of some race condition triggered by restarting Glean.
|
||||
func testSendingOfBaselinePingWithDirtyFlag() {
|
||||
// Set the dirty flag
|
||||
gleanSetDirtyFlag(true)
|
||||
|
||||
// Set up the test stub based on the default telemetry endpoint
|
||||
stubServerReceive { pingType, json in
|
||||
XCTAssertEqual("baseline", pingType)
|
||||
XCTAssert(json != nil)
|
||||
|
||||
// Check for the "dirty_startup" flag
|
||||
let pingInfo = json!["ping_info"] as! [String: Any]
|
||||
let reason = pingInfo["reason"] as! String
|
||||
if reason == "active" {
|
||||
// Skip initial "active" ping.
|
||||
// Glean is initialized ahead of this test and thus we might get one.
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual("dirty_startup", reason, "Expected a dirty_startup, got \(reason)")
|
||||
|
||||
// 'metrics' will exist and include exactly one valid metric.
|
||||
// No errors should be reported.
|
||||
let metrics = json!["metrics"] as? [String: Any]
|
||||
if metrics != nil {
|
||||
let datetimes = metrics!["datetime"] as! [String: Any]
|
||||
XCTAssertTrue(datetimes.keys.contains("glean.validation.first_run_hour"),
|
||||
"Datetime should have first_run_hour: \(datetimes)")
|
||||
|
||||
if metrics!.count > 1 {
|
||||
// Since we are only expecting error metrics,
|
||||
// let's check that this is all we got (plus the `validation.first_run_hour`).
|
||||
XCTAssertEqual(metrics?.count, 2, "metrics has more keys than expected: \(JSONStringify(metrics!))")
|
||||
let labeledCounters = metrics?["labeled_counter"] as? [String: Any]
|
||||
labeledCounters!.forEach { key, _ in
|
||||
XCTAssertTrue(
|
||||
key.starts(with: "glean.error") || key.starts(with: "glean.validation"),
|
||||
"Should only see glean.* counters, saw \(key)"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the expectation that will be fulfilled by the stub above
|
||||
expectation = expectation(description: "Baseline Ping Received")
|
||||
|
||||
// Set the last time the "metrics" ping was sent to now. This is required for us to not
|
||||
// send a metrics pings the first time we initialize Glean and to keep it from interfering
|
||||
// with these tests.
|
||||
let now = Date()
|
||||
Glean.shared.metricsPingScheduler.updateSentDate(now)
|
||||
// Restart Glean and don't clear the stores and then await the expectation
|
||||
Glean.shared.resetGlean(clearStores: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// swiftlint:disable force_cast
|
||||
func testSendingOfStartupBaselinePingWithAppLifetimeMetric() {
|
||||
// Set the dirty flag.
|
||||
gleanSetDirtyFlag(true)
|
||||
|
||||
let stringMetric = StringMetricType(CommonMetricData(
|
||||
category: "telemetry",
|
||||
name: "app_lifetime",
|
||||
sendInPings: ["baseline"],
|
||||
lifetime: .application,
|
||||
disabled: false
|
||||
))
|
||||
stringMetric.set("HELLOOOOO!")
|
||||
|
||||
// Set up the test stub based on the default telemetry endpoint
|
||||
stubServerReceive { pingType, json in
|
||||
XCTAssertEqual("baseline", pingType)
|
||||
XCTAssert(json != nil)
|
||||
|
||||
// Check for the "dirty_startup" flag
|
||||
let pingInfo = json!["ping_info"] as! [String: Any]
|
||||
let reason = pingInfo["reason"] as! String
|
||||
if reason == "active" {
|
||||
// Skip initial "active" ping.
|
||||
// Glean is initialized ahead of this test and thus we might get one.
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual("dirty_startup", reason)
|
||||
|
||||
// Ensure there is only the expected locale string metric
|
||||
let metrics = json?["metrics"] as? [String: Any]
|
||||
let strings = metrics?["string"] as? [String: Any]
|
||||
let metric = strings?["telemetry.app_lifetime"] as? String
|
||||
XCTAssertEqual("HELLOOOOO!", metric)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
expectation = expectation(description: "baseline ping received")
|
||||
|
||||
// Restart glean and don't clear the stores.
|
||||
// This should trigger a baseline ping with a "dirty_startup" reason.
|
||||
Glean.shared.resetGlean(clearStores: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
// swiftlint:enable force_cast
|
||||
}
|
|
@ -27,11 +27,69 @@ class DeletionRequestPingTests: XCTestCase {
|
|||
}
|
||||
|
||||
override func tearDown() {
|
||||
Glean.shared.testDestroyGleanHandle()
|
||||
lastPingJson = nil
|
||||
expectation = nil
|
||||
tearDownStubs()
|
||||
}
|
||||
|
||||
func testSendingDeletionPingIfDisabledOutsideOfRun() {
|
||||
resetGleanDiscardingInitialPings(testCase: self, tag: "GleanTests")
|
||||
|
||||
stubServerReceive { pingType, _ in
|
||||
// Since we are starting Glean with upload disabled, the only ping we
|
||||
// should see is the deletion request ping
|
||||
XCTAssertEqual("deletion-request", pingType)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// let the response get processed before we mark the expectation fulfilled
|
||||
self.expectation?.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the expectation that will be fulfilled by the stub above
|
||||
expectation = expectation(description: "Deletion Request Received")
|
||||
|
||||
// Now reset Glean with uploadEnabled = false and not clearing the stores to
|
||||
// trigger the deletion request ping. Since `uploadEnabled` is `false`, only
|
||||
// the deletion-request ping should be generated.
|
||||
Glean.shared.resetGlean(clearStores: false, uploadEnabled: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
|
||||
func testNotSendingDeletionRequestIfUnchangedOutsideOfRun() {
|
||||
resetGleanDiscardingInitialPings(testCase: self, tag: "GleanTests")
|
||||
|
||||
XCTAssert(Glean.shared.isInitialized(), "Glean should be initialized")
|
||||
|
||||
// Set up the test stub based on the default telemetry endpoint
|
||||
stubServerReceive { _, _ in
|
||||
XCTFail("Should not have recieved any ping")
|
||||
}
|
||||
|
||||
// Set up the expectation that will NOT be fulfilled by the stub above. If it is
|
||||
// then it will trigger an assertion due to the `assertForOverFulfill` property.
|
||||
expectation = expectation(description: "Deletion Request Received")
|
||||
|
||||
// So we can wait for expectations below, we will go ahead and fulfill the
|
||||
// expectation. We want to assert if the ping is triggered and over fulfills it
|
||||
// from the stub above.
|
||||
expectation?.fulfill()
|
||||
|
||||
// Reset Glean with uploadEnabled = false
|
||||
Glean.shared.resetGlean(clearStores: true, uploadEnabled: false)
|
||||
|
||||
// Now reset Glean with uploadEnabled = false again without clearing the stores to
|
||||
// make sure we don't trigger the deletion request ping. If it does, then we will
|
||||
// have overfulfilled the expectation which will trigger a test assertion.
|
||||
Glean.shared.resetGlean(clearStores: false, uploadEnabled: false)
|
||||
waitForExpectations(timeout: 5.0) { error in
|
||||
XCTAssertNil(error, "Test timed out waiting for upload: \(error!)")
|
||||
}
|
||||
}
|
||||
|
||||
func testDeletionRequestPingsAreSentWhenUploadDisabled() {
|
||||
resetGleanDiscardingInitialPings(testCase: self, tag: "DeletionRequestPingTests")
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче