diff --git a/Datadog/Example/Base.lproj/Main.storyboard b/Datadog/Example/Base.lproj/Main.storyboard index 7be1531e1c..69ba745349 100644 --- a/Datadog/Example/Base.lproj/Main.storyboard +++ b/Datadog/Example/Base.lproj/Main.storyboard @@ -320,28 +320,74 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -367,6 +413,7 @@ + diff --git a/Datadog/Example/Debugging/DebugLoggingViewController.swift b/Datadog/Example/Debugging/DebugLoggingViewController.swift index bcf967b44e..fd14b1a19d 100644 --- a/Datadog/Example/Debugging/DebugLoggingViewController.swift +++ b/Datadog/Example/Debugging/DebugLoggingViewController.swift @@ -5,6 +5,7 @@ */ import UIKit +import Datadog class DebugLoggingViewController: UIViewController { @IBOutlet weak var logLevelSegmentedControl: UISegmentedControl! @@ -12,6 +13,7 @@ class DebugLoggingViewController: UIViewController { @IBOutlet weak var logServiceNameTextField: UITextField! @IBOutlet weak var sendOnceButton: UIButton! @IBOutlet weak var send10xButton: UIButton! + @IBOutlet weak var stressTestButton: UIButton! @IBOutlet weak var consoleTextView: UITextView! struct StructError: Error { @@ -78,4 +80,43 @@ class DebugLoggingViewController: UIViewController { private func repeat10x(block: () -> Void) { (0..<10).forEach { _ in block() } } + + // MARK: - Stress testing + + var queues: [DispatchQueue] = [] + var loggers: [Logger] = [] + + @IBAction func didTapStressTest(_ sender: Any) { + stressTestButton.disableFor(seconds: 10) + + loggers = (0..<5).map { index in + return Logger.builder.set(loggerName: "stress-logger-\(index)") + .sendNetworkInfo(true) + .build() + } + + queues = (0..<5).map { index in + return DispatchQueue(label: "com.datadoghq.example.stress-testing-queue\(index)") + } + + let endDate = Date(timeIntervalSinceNow: 10) // 10s + zip(loggers, queues).forEach { logger, queue in + keepSendingLogs(on: queue, using: logger, every: 0.01, until: endDate) + } + } + + private func keepSendingLogs(on queue: DispatchQueue, using logger: Logger, every timeInterval: TimeInterval, until endDate: Date) { + if Date() < endDate { + queue.asyncAfter(deadline: .now() + timeInterval) { [weak self] in + logger.debug(self?.randomLogMessage() ?? "") + self?.keepSendingLogs(on: queue, using: logger, every: timeInterval, until: endDate) + } + } + } + + private let alphanumerics = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + + private func randomLogMessage() -> String { + return String((0..<20).map { _ in alphanumerics.randomElement()! }) + } } diff --git a/Sources/Datadog/Core/System/CarrierInfoProvider.swift b/Sources/Datadog/Core/System/CarrierInfoProvider.swift index 61817616eb..89aac41367 100644 --- a/Sources/Datadog/Core/System/CarrierInfoProvider.swift +++ b/Sources/Datadog/Core/System/CarrierInfoProvider.swift @@ -66,88 +66,147 @@ extension CarrierInfo.RadioAccessTechnology { } } -/// An interface for the target-specific carrier info provider. -internal protocol WrappedCarrierInfoProvider { - var current: CarrierInfo? { get } -} - +/// Platform-agnostic carrier info provider. It wraps the platform-specific provider inside. internal class CarrierInfoProvider: CarrierInfoProviderType { /// The `CarrierInfo` provider for the current platform. - private let wrappedProvider: WrappedCarrierInfoProvider - /// Publisher for notifying observers on `CarrierInfo` change. - private let publisher: ValuePublisher + private let wrappedProvider: CarrierInfoProviderType convenience init() { #if targetEnvironment(macCatalyst) - self.init( - wrappedProvider: MacCatalystCarrierInfoProvider() - ) + self.init( + wrappedProvider: MacCatalystCarrierInfoProvider() + ) #else - self.init( - wrappedProvider: iOSCarrierInfoProvider( - networkInfo: CTTelephonyNetworkInfo() - ) - ) + if #available(iOS 12.0, *) { + self.init(wrappedProvider: iOS12CarrierInfoProvider(networkInfo: CTTelephonyNetworkInfo())) + } else { + self.init(wrappedProvider: iOS11CarrierInfoProvider(networkInfo: CTTelephonyNetworkInfo())) + } #endif } - init(wrappedProvider: WrappedCarrierInfoProvider) { + init(wrappedProvider: CarrierInfoProviderType) { self.wrappedProvider = wrappedProvider - self.publisher = ValuePublisher(initialValue: nil) } var current: CarrierInfo? { - let nextValue = wrappedProvider.current - // `CarrierInfo` subscribers are notified as a side-effect of retrieving the - // current `CarrierInfo` value. - publisher.publishAsync(nextValue) - return nextValue + wrappedProvider.current } func subscribe(_ subscriber: Observer) where Observer.ObservedValue == CarrierInfo? { - publisher.subscribe(subscriber) + wrappedProvider.subscribe(subscriber) } } #if targetEnvironment(macCatalyst) -internal struct MacCatalystCarrierInfoProvider: WrappedCarrierInfoProvider { - /// Carrier info is not supported on macCatalyst +/// Dummy provider for Mac Catalyst which doesn't support carrier info. +internal struct MacCatalystCarrierInfoProvider: CarrierInfoProviderType { var current: CarrierInfo? { return nil } + func subscribe(_ subscriber: Observer) where Observer: ValueObserver, Observer.ObservedValue == CarrierInfo? {} } #else -internal struct iOSCarrierInfoProvider: WrappedCarrierInfoProvider { - let networkInfo: CTTelephonyNetworkInfo +/// Carrier info provider for iOS 12 and above. +/// It reads `CarrierInfo?` from `CTTelephonyNetworkInfo` only when `CTCarrier` has changed (e.g. when the SIM card was swapped). +@available(iOS 12, *) +internal class iOS12CarrierInfoProvider: CarrierInfoProviderType { + private let networkInfo: CTTelephonyNetworkInfo + /// Publisher for notifying observers on `CarrierInfo` change. + private let publisher: ValuePublisher - var current: CarrierInfo? { - let carrier: CTCarrier? - let radioTechnology: String? + init(networkInfo: CTTelephonyNetworkInfo) { + self.networkInfo = networkInfo + self.publisher = ValuePublisher( + initialValue: iOS12CarrierInfoProvider.readCarrierInfo( + from: networkInfo, + cellularProviderKey: networkInfo.serviceCurrentRadioAccessTechnology?.keys.first + ) + ) - if #available(iOS 12, *) { - guard let cellularProviderKey = networkInfo.serviceCurrentRadioAccessTechnology?.keys.first else { - return nil + // The `serviceSubscriberCellularProvidersDidUpdateNotifier` block object executes on the default priority + // global dispatch queue when the user’s cellular provider information changes. + // This occurs, for example, if a user swaps the device’s SIM card with one from another provider, while the app is running. + // ref.: https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo/3024512-servicesubscribercellularprovide + networkInfo.serviceSubscriberCellularProvidersDidUpdateNotifier = { [weak self] cellularProviderKey in + guard let strongSelf = self else { + return } - radioTechnology = networkInfo.serviceCurrentRadioAccessTechnology?[cellularProviderKey] - carrier = networkInfo.serviceSubscriberCellularProviders?[cellularProviderKey] - } else { - radioTechnology = networkInfo.currentRadioAccessTechnology - carrier = networkInfo.subscriberCellularProvider + + let carrierInfo = iOS12CarrierInfoProvider.readCarrierInfo( + from: strongSelf.networkInfo, + cellularProviderKey: cellularProviderKey + ) + + // On iOS12+ `CarrierInfo` subscribers are notified on actual change to cellular provider. + strongSelf.publisher.publishAsync(carrierInfo) } + } - guard let radioAccessTechnology = radioTechnology, - let currentCTCarrier = carrier else { - return nil + private static func readCarrierInfo(from networkInfo: CTTelephonyNetworkInfo, cellularProviderKey: String?) -> CarrierInfo? { + guard let cellularProviderKey = cellularProviderKey, + let radioTechnology = networkInfo.serviceCurrentRadioAccessTechnology?[cellularProviderKey], + let carrier = networkInfo.serviceSubscriberCellularProviders?[cellularProviderKey] else { + return nil // the service is not registered on any network } + return CarrierInfo( + carrierName: carrier.carrierName, + carrierISOCountryCode: carrier.isoCountryCode, + carrierAllowsVOIP: carrier.allowsVOIP, + radioAccessTechnology: .init(ctRadioAccessTechnologyConstant: radioTechnology) + ) + } + + var current: CarrierInfo? { + publisher.currentValue + } + + func subscribe(_ subscriber: Observer) where Observer: ValueObserver, Observer.ObservedValue == CarrierInfo? { + publisher.subscribe(subscriber) + } +} + +/// Carrier info provider for iOS 11. +/// It reads `CarrierInfo?` from `CTTelephonyNetworkInfo` each time. +internal class iOS11CarrierInfoProvider: CarrierInfoProviderType { + private let networkInfo: CTTelephonyNetworkInfo + /// Publisher for notifying observers on `CarrierInfo` change. + private let publisher: ValuePublisher + + init(networkInfo: CTTelephonyNetworkInfo) { + self.networkInfo = networkInfo + self.publisher = ValuePublisher( + initialValue: iOS11CarrierInfoProvider.readCarrierInfo(from: networkInfo) + ) + } + private static func readCarrierInfo(from networkInfo: CTTelephonyNetworkInfo) -> CarrierInfo? { + guard let radioTechnology = networkInfo.currentRadioAccessTechnology, + let carrier = networkInfo.subscriberCellularProvider else { + return nil // the service is not registered on any network + } return CarrierInfo( - carrierName: currentCTCarrier.carrierName, - carrierISOCountryCode: currentCTCarrier.isoCountryCode, - carrierAllowsVOIP: currentCTCarrier.allowsVOIP, - radioAccessTechnology: .init(ctRadioAccessTechnologyConstant: radioAccessTechnology) + carrierName: carrier.carrierName, + carrierISOCountryCode: carrier.isoCountryCode, + carrierAllowsVOIP: carrier.allowsVOIP, + radioAccessTechnology: .init(ctRadioAccessTechnologyConstant: radioTechnology) ) } + + var current: CarrierInfo? { + let carrierInfo = iOS11CarrierInfoProvider.readCarrierInfo(from: networkInfo) + + // On iOS11 `CarrierInfo` subscribers are notified as a side-effect of pulling the + // current `CarrierInfo` value. + publisher.publishAsync(carrierInfo) + + return carrierInfo + } + + func subscribe(_ subscriber: Observer) where Observer: ValueObserver, Observer.ObservedValue == CarrierInfo? { + publisher.subscribe(subscriber) + } } #endif diff --git a/Sources/Datadog/Core/System/NetworkConnectionInfoProvider.swift b/Sources/Datadog/Core/System/NetworkConnectionInfoProvider.swift index cccdaa3428..c9371755d1 100644 --- a/Sources/Datadog/Core/System/NetworkConnectionInfoProvider.swift +++ b/Sources/Datadog/Core/System/NetworkConnectionInfoProvider.swift @@ -172,7 +172,7 @@ internal class iOS11NetworkConnectionInfoProvider: WrappedNetworkConnectionInfoP } } -// MARK: Conversion helpers +// MARK: - Conversion helpers extension NetworkConnectionInfo.Reachability { @available(iOS 12, *) diff --git a/Tests/DatadogTests/Datadog/Core/System/CarrierInfoProviderTests.swift b/Tests/DatadogTests/Datadog/Core/System/CarrierInfoProviderTests.swift index c793e3cffa..e738230dc9 100644 --- a/Tests/DatadogTests/Datadog/Core/System/CarrierInfoProviderTests.swift +++ b/Tests/DatadogTests/Datadog/Core/System/CarrierInfoProviderTests.swift @@ -9,37 +9,138 @@ import CoreTelephony @testable import Datadog class CarrierInfoProviderTests: XCTestCase { + /// Mock `CTTelephonyNetworkInfo` when user’s cellular service provider is available. + private let availableCTTelephonyNetworkInfo = CTTelephonyNetworkInfoMock( + serviceCurrentRadioAccessTechnology: ["000001": CTRadioAccessTechnologyLTE], + serviceSubscriberCellularProviders: ["000001": CTCarrierMock(carrierName: "Carrier", isoCountryCode: "US", allowsVOIP: true)] + ) + /// Mock `CTTelephonyNetworkInfo` when user’s cellular service provider is unavailable. + private let unavailableCTTelephonyNetworkInfo = CTTelephonyNetworkInfoMock( + serviceCurrentRadioAccessTechnology: [:], + serviceSubscriberCellularProviders: [:] + ) + func testItIsAvailableOnMobile() { XCTAssertNotNil(CarrierInfoProvider()) } - func testWhenCellularServiceIsAvailable_itReturnsCarrierInfo() { - let serviceID = "000001" - let telephonyNetworkInfo = CTTelephonyNetworkInfoMock( - serviceCurrentRadioAccessTechnology: [serviceID: CTRadioAccessTechnologyLTE], - serviceSubscriberCellularProviders: [serviceID: CTCarrierMock(carrierName: "Carrier", isoCountryCode: "US", allowsVOIP: true)] - ) + func testGivenCellularServiceAvailableOnIOS11_whenReadingCurrentCarrierInfo_itReturnsValue() { + // Given + let iOS11Provider = iOS11CarrierInfoProvider(networkInfo: availableCTTelephonyNetworkInfo) - let provider = CarrierInfoProvider( - wrappedProvider: iOSCarrierInfoProvider(networkInfo: telephonyNetworkInfo) - ) + // When + let iOS11CarrierInfo = CarrierInfoProvider(wrappedProvider: iOS11Provider).current - XCTAssertEqual(provider.current?.carrierName, "Carrier") - XCTAssertEqual(provider.current?.carrierISOCountryCode, "US") - XCTAssertEqual(provider.current?.carrierAllowsVOIP, true) + // Then + XCTAssertEqual(iOS11CarrierInfo?.carrierName, "Carrier") + XCTAssertEqual(iOS11CarrierInfo?.carrierISOCountryCode, "US") + XCTAssertEqual(iOS11CarrierInfo?.carrierAllowsVOIP, true) } - func testWhenCellularServiceIsUnavailable_itReturnsNoCarrierInfo() { - let telephonyNetworkInfo = CTTelephonyNetworkInfoMock( - serviceCurrentRadioAccessTechnology: [:], - serviceSubscriberCellularProviders: [:] - ) + func testGivenCellularServiceAvailableOnIOS12AndAbove_whenReadingCurrentCarrierInfo_itReturnsValue() { + if #available(iOS 12, *) { + // Given + let iOS12Provider = iOS12CarrierInfoProvider(networkInfo: availableCTTelephonyNetworkInfo) + + // When + let iOS12CarrierInfo = CarrierInfoProvider(wrappedProvider: iOS12Provider).current + + // Then + XCTAssertEqual(iOS12CarrierInfo?.carrierName, "Carrier") + XCTAssertEqual(iOS12CarrierInfo?.carrierISOCountryCode, "US") + XCTAssertEqual(iOS12CarrierInfo?.carrierAllowsVOIP, true) + } + } + + func testGivenCellularServiceUnavailableOnIOS11_whenReadingCurrentCarrierInfo_itReturnsNoValue() { + // Given + let iOS11Provider = iOS11CarrierInfoProvider(networkInfo: unavailableCTTelephonyNetworkInfo) + + // When + let iOS11CarrierInfo = CarrierInfoProvider(wrappedProvider: iOS11Provider).current + + // Then + XCTAssertNil(iOS11CarrierInfo) + } + + func testGivenCellularServiceUnavailableOnIOS12AndAbove_whenReadingCurrentCarrierInfo_itReturnsNoValue() { + if #available(iOS 12, *) { + // Given + let iOS12Provider = iOS12CarrierInfoProvider(networkInfo: unavailableCTTelephonyNetworkInfo) + + // When + let iOS12CarrierInfo = CarrierInfoProvider(wrappedProvider: iOS12Provider).current + + // Then + XCTAssertNil(iOS12CarrierInfo) + } + } - let provider = CarrierInfoProvider( - wrappedProvider: iOSCarrierInfoProvider(networkInfo: telephonyNetworkInfo) + func testGivenSubscribediOS11CarrierInfoProvider_whenCarrierInfoChanges_itNotifiesSubscribersAfterReadingValue() throws { + let notifyCarrierInfoChangeExpectation = expectation(description: "Notify `CarrierInfo` change") + var recordedChange: (old: CarrierInfo?, new: CarrierInfo?)? = nil + + // Given + let subscriber = ValueObserverMock { oldValue, newValue in + recordedChange = (old: oldValue, new: newValue) + notifyCarrierInfoChangeExpectation.fulfill() + } + + let iOS11Provider = iOS11CarrierInfoProvider(networkInfo: availableCTTelephonyNetworkInfo) + iOS11Provider.subscribe(subscriber) + + let initialCarrierInfo = iOS11Provider.current + + // When + availableCTTelephonyNetworkInfo.changeCarrier( + newCarrierName: .mockRandom(), + newISOCountryCode: .mockRandom(), + newAllowsVOIP: .mockRandom(), + newRadioAccessTechnology: [CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge].randomElement()! ) - XCTAssertNil(provider.current) + // Then + let newCarrierInfo = iOS11Provider.current + + waitForExpectations(timeout: 1, handler: nil) + let notifiedCarrierInfoChange = try XCTUnwrap(recordedChange) + XCTAssertEqual(notifiedCarrierInfoChange.old, initialCarrierInfo) + XCTAssertEqual(notifiedCarrierInfoChange.new, newCarrierInfo) + } + + func testGivenSubscribediOS12CarrierInfoProvider_whenCarrierInfoChanges_itNotifiesSubscribers() throws { + if #available(iOS 12, *) { + let notifyCarrierInfoChangeExpectation = expectation(description: "Notify `CarrierInfo` change") + var recordedChange: (old: CarrierInfo?, new: CarrierInfo?)? = nil + + // Given + let subscriber = ValueObserverMock { oldValue, newValue in + recordedChange = (old: oldValue, new: newValue) + notifyCarrierInfoChangeExpectation.fulfill() + } + + let iOS12Provider = iOS12CarrierInfoProvider(networkInfo: availableCTTelephonyNetworkInfo) + iOS12Provider.subscribe(subscriber) + + let initialCarrierInfo = iOS12Provider.current + + // When + availableCTTelephonyNetworkInfo.changeCarrier( + newCarrierName: .mockRandom(), + newISOCountryCode: .mockRandom(), + newAllowsVOIP: .mockRandom(), + newRadioAccessTechnology: [CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge].randomElement()! + ) + + // Then + waitForExpectations(timeout: 1, handler: nil) + + let newCarrierInfo = iOS12Provider.current + + let notifiedCarrierInfoChange = try XCTUnwrap(recordedChange) + XCTAssertEqual(notifiedCarrierInfoChange.old, initialCarrierInfo) + XCTAssertEqual(notifiedCarrierInfoChange.new, newCarrierInfo) + } } func testDifferentCarrierInfoRadioAccessTechnologies() { diff --git a/Tests/DatadogTests/Datadog/CrashReporting/CrashContext/CrashContextProviderTests.swift b/Tests/DatadogTests/Datadog/CrashReporting/CrashContext/CrashContextProviderTests.swift index 0cd7fef4c7..65bbe66c85 100644 --- a/Tests/DatadogTests/Datadog/CrashReporting/CrashContext/CrashContextProviderTests.swift +++ b/Tests/DatadogTests/Datadog/CrashReporting/CrashContext/CrashContextProviderTests.swift @@ -6,6 +6,7 @@ import XCTest @testable import Datadog +import CoreTelephony /// This suite tests if `CrashContextProvider` gets updated by different SDK components, each updating /// separate part of the `CrashContext` information. @@ -143,17 +144,22 @@ class CrashContextProviderTests: XCTestCase { // MARK: - `CarrierInfo` Integration - func testWhenCurrentValueIsObtainedFromCarrierInfoProvider_thenCrashContextProviderNotifiesNewContext() { + private let ctTelephonyNetworkInfoMock = CTTelephonyNetworkInfoMock( + serviceCurrentRadioAccessTechnology: ["000001": CTRadioAccessTechnologyLTE], + serviceSubscriberCellularProviders: ["000001": CTCarrierMock(carrierName: "Carrier", isoCountryCode: "US", allowsVOIP: true)] + ) + + func testGivenRunningOniOS11_whenCurrentValueIsObtainedFromCarrierInfoProvider_thenCrashContextProviderNotifiesNewContext() throws { let expectation = self.expectation(description: "Notify new crash context") - let initialCarrierInfo: CarrierInfo = .mockRandom() - let wrappedProvider = CarrierInfoProviderMock(carrierInfo: initialCarrierInfo) - let mainProvider = CarrierInfoProvider(wrappedProvider: wrappedProvider) + let carrierInfoProvider = CarrierInfoProvider( + wrappedProvider: iOS11CarrierInfoProvider(networkInfo: ctTelephonyNetworkInfoMock) + ) let crashContextProvider = CrashContextProvider( consentProvider: .mockAny(), userInfoProvider: .mockAny(), networkConnectionInfoProvider: NetworkConnectionInfoProviderMock.mockAny(), - carrierInfoProvider: mainProvider, + carrierInfoProvider: carrierInfoProvider, rumViewEventProvider: .mockRandom() ) @@ -165,13 +171,57 @@ class CrashContextProviderTests: XCTestCase { updatedContext = newContext expectation.fulfill() } - wrappedProvider.set(current: .mockRandom()) // change `CarrierInfo` in wrapped provider - let currentCarrierInfo = mainProvider.current // obtain new info through the main provider + ctTelephonyNetworkInfoMock.changeCarrier( + newCarrierName: .mockRandom(), + newISOCountryCode: .mockRandom(), + newAllowsVOIP: .mockRandom(), + newRadioAccessTechnology: [CTRadioAccessTechnologyLTE, CTRadioAccessTechnologyEdge].randomElement()! + ) // change `CTCarrier` info + _ = carrierInfoProvider.current // obtain `CarrierInfo` from provider // Then waitForExpectations(timeout: 1, handler: nil) - XCTAssertEqual(initialContext.lastCarrierInfo, initialCarrierInfo) - XCTAssertEqual(updatedContext?.lastCarrierInfo, currentCarrierInfo) + let carrierInfoInInitialContext = try XCTUnwrap(initialContext.lastCarrierInfo) + let carrierInfoInUpdatedContext = try XCTUnwrap(updatedContext?.lastCarrierInfo) + XCTAssertNotEqual(carrierInfoInInitialContext, carrierInfoInUpdatedContext) + } + + func testGivenRunningOniOS12AndAbove_whenCTCarrierChanges_thenCrashContextProviderNotifiesNewContext() throws { + if #available(iOS 12, *) { + let expectation = self.expectation(description: "Notify new crash context") + let carrierInfoProvider = CarrierInfoProvider( + wrappedProvider: iOS12CarrierInfoProvider(networkInfo: ctTelephonyNetworkInfoMock) + ) + + let crashContextProvider = CrashContextProvider( + consentProvider: .mockAny(), + userInfoProvider: .mockAny(), + networkConnectionInfoProvider: NetworkConnectionInfoProviderMock.mockAny(), + carrierInfoProvider: carrierInfoProvider, + rumViewEventProvider: .mockRandom() + ) + + let initialContext = crashContextProvider.currentCrashContext + var updatedContext: CrashContext? + + // When + crashContextProvider.onCrashContextChange = { newContext in + updatedContext = newContext + expectation.fulfill() + } + ctTelephonyNetworkInfoMock.changeCarrier( + newCarrierName: .mockRandom(), + newISOCountryCode: .mockRandom(), + newAllowsVOIP: .mockRandom(), + newRadioAccessTechnology: [CTRadioAccessTechnologyLTE, CTRadioAccessTechnologyEdge].randomElement()! + ) // change `CTCarrier` info + + // Then + waitForExpectations(timeout: 1, handler: nil) + let carrierInfoInInitialContext = try XCTUnwrap(initialContext.lastCarrierInfo) + let carrierInfoInUpdatedContext = try XCTUnwrap(updatedContext?.lastCarrierInfo) + XCTAssertNotEqual(carrierInfoInInitialContext, carrierInfoInUpdatedContext) + } } // MARK: - Thread safety diff --git a/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift b/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift index 929e5ddae9..0d44af542f 100644 --- a/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift +++ b/Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift @@ -924,7 +924,7 @@ extension CarrierInfo: RandomMockable { } } -class CarrierInfoProviderMock: CarrierInfoProviderType, WrappedCarrierInfoProvider { +class CarrierInfoProviderMock: CarrierInfoProviderType { private let queue = DispatchQueue(label: "com.datadoghq.CarrierInfoProviderMock") private var _current: CarrierInfo? diff --git a/Tests/DatadogTests/Datadog/Mocks/SystemFrameworks/CoreTelephonyMocks.swift b/Tests/DatadogTests/Datadog/Mocks/SystemFrameworks/CoreTelephonyMocks.swift index 4add09751d..e77c7f58da 100644 --- a/Tests/DatadogTests/Datadog/Mocks/SystemFrameworks/CoreTelephonyMocks.swift +++ b/Tests/DatadogTests/Datadog/Mocks/SystemFrameworks/CoreTelephonyMocks.swift @@ -28,8 +28,8 @@ class CTCarrierMock: CTCarrier { } class CTTelephonyNetworkInfoMock: CTTelephonyNetworkInfo { - private let _serviceCurrentRadioAccessTechnology: [String: String]? - private let _serviceSubscriberCellularProviders: [String: CTCarrier]? + private var _serviceCurrentRadioAccessTechnology: [String: String]? + private var _serviceSubscriberCellularProviders: [String: CTCarrier]? init( serviceCurrentRadioAccessTechnology: [String: String], @@ -39,6 +39,24 @@ class CTTelephonyNetworkInfoMock: CTTelephonyNetworkInfo { _serviceSubscriberCellularProviders = serviceSubscriberCellularProviders } + func changeCarrier( + newCarrierName: String, + newISOCountryCode: String, + newAllowsVOIP: Bool, + newRadioAccessTechnology: String + ) { + _serviceCurrentRadioAccessTechnology = [ + "000001": newRadioAccessTechnology + ] + _serviceSubscriberCellularProviders = [ + "000001": CTCarrierMock(carrierName: newCarrierName, isoCountryCode: newISOCountryCode, allowsVOIP: newAllowsVOIP) + ] + + if #available(iOS 12.0, *) { + serviceSubscriberCellularProvidersDidUpdateNotifier?("000001") + } + } + // MARK: - iOS 12+ override var serviceCurrentRadioAccessTechnology: [String: String]? { _serviceCurrentRadioAccessTechnology }