diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 79d4f609b..74db06655 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -69,7 +69,7 @@ jobs: - name: 'Install dependencies' run: ./ci/mac_ci_setup.sh - name: Run iOS tests (tsan) - run: env -u ANDROID_NDK_HOME ./bazelw test $(./bazelw query 'kind(ios_unit_test, //test/platform/swift/unit_integration:test_tsan)') --test_tag_filters=macos_only --test_output=errors --config ci --config ios-tsan + run: env -u ANDROID_NDK_HOME ./bazelw test $(./bazelw query 'kind(ios_unit_test, //test/platform/swift/unit_integration/core/...)') --test_tag_filters=macos_only --test_output=errors --config ci --config ios-tsan verify_ios: runs-on: ubuntu-latest needs: ["macos_tsan", "macos_asan", "swift_hello_world"] diff --git a/.gitignore b/.gitignore index 383261b71..a60690d6e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ # Bazel /bazel-* +**/Bazel Generated/ compile_commands.json .DS_Store diff --git a/BUILD b/BUILD index 9a76f9757..04cdcd203 100644 --- a/BUILD +++ b/BUILD @@ -192,7 +192,8 @@ xcodeproj( ], ), # Tests - "//test/platform/swift/unit_integration:test", + "//test/platform/swift/unit_integration/core:test", + "//test/platform/swift/unit_integration/integrations:test", ], xcode_configurations = { "Debug": { @@ -233,7 +234,15 @@ xcodeproj( name = "iOS Capture Unit Integration Tests", test = xcschemes.test( test_targets = [ - "//test/platform/swift/unit_integration:test", + "//test/platform/swift/unit_integration/core:test", + ], + ), + ), + xcschemes.scheme( + name = "iOS Capture URLSession Integration Tests", + test = xcschemes.test( + test_targets = [ + "//test/platform/swift/unit_integration/integrations:test", ], ), ), diff --git a/examples/swift/benchmark/BUILD b/examples/swift/benchmark/BUILD index 4e30d17ea..fc25c1846 100644 --- a/examples/swift/benchmark/BUILD +++ b/examples/swift/benchmark/BUILD @@ -1,5 +1,6 @@ load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application") load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") +load("//bazel:config.bzl", "MINIMUM_IOS_VERSION_TESTS") # App that directly imports Bitdrift as a `swift_library` for compatibility with `rules_xcodeproj` # and allowing building the app and all its deps in a single step. @@ -23,7 +24,7 @@ ios_application( bundle_id = "io.bitdrift.example.benchmarkapp", families = ["iphone"], infoplists = ["Info.plist"], - minimum_os_version = "13.0", + minimum_os_version = MINIMUM_IOS_VERSION_TESTS, provisioning_profile = select({ "//bazel:ios_device_build": "//bazel/ios:ios_provisioning_profile", "//conditions:default": None, diff --git a/examples/swift/benchmark/ResourceProfiler.swift b/examples/swift/benchmark/ResourceProfiler.swift index 6a51dda6e..463a4fef4 100644 --- a/examples/swift/benchmark/ResourceProfiler.swift +++ b/examples/swift/benchmark/ResourceProfiler.swift @@ -34,10 +34,7 @@ final class ResourceProfiler { self.startNetworkProfiling( isRunning: isRunning, name: "Simple", - configuration: .init( - sessionReplayConfiguration: nil, - resourceReportingConfiguration: nil - ), + configuration: .init(sessionReplayConfiguration: nil), streamHandler: { streamID in configure_benchmarking_configuration(streamID) await_configuration_ack(streamID) @@ -86,16 +83,17 @@ final class ResourceProfiler { let url = self.makeDirectoryURL() self.logger = Logger( withAPIKey: "foo", - appInstallID: "device-id", bufferDirectory: url, // swiftlint:disable:next force_unwrapping apiURL: URL(string: "https://localhost:\(port)")!, remoteErrorReporter: nil, configuration: configuration, - sessionProvider: InMemorySessionProvider(sessionIDGenerator: { UUID().uuidString }), + sessionStrategy: .fixed(), dateProvider: nil, fieldProviders: [], - enableNetwork: true + enableNetwork: true, + storageProvider: Storage.shared, + timeProvider: SystemTimeProvider() ) self.loggerURL = url diff --git a/test/platform/swift/ResourceReporterUtilizationTest.swift b/test/platform/swift/ResourceReporterUtilizationTest.swift deleted file mode 100644 index e60e3ce7e..000000000 --- a/test/platform/swift/ResourceReporterUtilizationTest.swift +++ /dev/null @@ -1,16 +0,0 @@ -// capture-sdk - bitdrift's client SDK -// Copyright Bitdrift, Inc. All rights reserved. -// -// Use of this source code is governed by a source available license that can be found in the -// LICENSE file or at: -// https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt - -@testable import Capture -import XCTest - -final class ResourceReporterUtilizationTest: XCTestCase { - func testReporterDoesNotCrash() { - let reporter = ResourceUtilizationReporter() - XCTAssertTrue(!reporter.fields().isEmpty) - } -} diff --git a/test/platform/swift/unit_integration/BUILD b/test/platform/swift/unit_integration/BUILD deleted file mode 100644 index 711150ebb..000000000 --- a/test/platform/swift/unit_integration/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -load("//bazel:bitdrift_swift_test.bzl", "bitdrift_mobile_swift_test") - -bitdrift_mobile_swift_test( - name = "test", - srcs = glob(["**/*.swift"]), - repository = "@capture", - tags = ["macos_only"], - visibility = ["//visibility:public"], - deps = [ - "//platform/swift/source:ios_lib", - "//platform/swift/source:rust_bridge", - "//test/platform/swift/benchmark:benchmarks", - "//test/platform/swift/bridging:rust_bridge", - "@Difference//:difference", - "@SwiftBenchmark//:swift_benchmark", - ], -) - -# TODO(Augustyniak): Organize this code better. -# Separate target needed since TSAN gives false positives while running `URLSessionIntegrationTests` tests. -bitdrift_mobile_swift_test( - name = "test_tsan", - srcs = glob( - include = ["**/*.swift"], - exclude = ["integrations/URLSessionIntegrationTests.swift"], - ), - repository = "@capture", - tags = ["macos_only"], - visibility = ["//visibility:public"], - deps = [ - "//platform/swift/source:ios_lib", - "//platform/swift/source:rust_bridge", - "//test/platform/swift/benchmark:benchmarks", - "//test/platform/swift/bridging:rust_bridge", - "@Difference//:difference", - "@SwiftBenchmark//:swift_benchmark", - ], -) diff --git a/test/platform/swift/unit_integration/ANRReporterTests.swift b/test/platform/swift/unit_integration/core/ANRReporterTests.swift similarity index 98% rename from test/platform/swift/unit_integration/ANRReporterTests.swift rename to test/platform/swift/unit_integration/core/ANRReporterTests.swift index 9ff54ad3a..b8c1e0dcd 100644 --- a/test/platform/swift/unit_integration/ANRReporterTests.swift +++ b/test/platform/swift/unit_integration/core/ANRReporterTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/AppUpdateEventListenerTests.swift b/test/platform/swift/unit_integration/core/AppUpdateEventListenerTests.swift similarity index 98% rename from test/platform/swift/unit_integration/AppUpdateEventListenerTests.swift rename to test/platform/swift/unit_integration/core/AppUpdateEventListenerTests.swift index b29e81aa3..b1e0bf32b 100644 --- a/test/platform/swift/unit_integration/AppUpdateEventListenerTests.swift +++ b/test/platform/swift/unit_integration/core/AppUpdateEventListenerTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import XCTest final class AppUpdateEventListenerTests: XCTestCase { diff --git a/test/platform/swift/unit_integration/core/BUILD b/test/platform/swift/unit_integration/core/BUILD new file mode 100644 index 000000000..32cd380bf --- /dev/null +++ b/test/platform/swift/unit_integration/core/BUILD @@ -0,0 +1,18 @@ +load("//bazel:bitdrift_swift_test.bzl", "bitdrift_mobile_swift_test") + +bitdrift_mobile_swift_test( + name = "test", + srcs = glob(["**/*.swift"]), + repository = "@capture", + tags = ["macos_only"], + visibility = ["//visibility:public"], + deps = [ + "//platform/swift/source:ios_lib", + "//platform/swift/source:rust_bridge", + "//test/platform/swift/benchmark:benchmarks", + "//test/platform/swift/bridging:rust_bridge", + "//test/platform/swift/unit_integration/mocks", + "@Difference//:difference", + "@SwiftBenchmark//:swift_benchmark", + ], +) diff --git a/test/platform/swift/unit_integration/ConfigurationTests.swift b/test/platform/swift/unit_integration/core/ConfigurationTests.swift similarity index 99% rename from test/platform/swift/unit_integration/ConfigurationTests.swift rename to test/platform/swift/unit_integration/core/ConfigurationTests.swift index 200c7ae86..43b034836 100644 --- a/test/platform/swift/unit_integration/ConfigurationTests.swift +++ b/test/platform/swift/unit_integration/core/ConfigurationTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/CoreLoggerTests.swift b/test/platform/swift/unit_integration/core/CoreLoggerTests.swift similarity index 99% rename from test/platform/swift/unit_integration/CoreLoggerTests.swift rename to test/platform/swift/unit_integration/core/CoreLoggerTests.swift index 194c6682c..311be334e 100644 --- a/test/platform/swift/unit_integration/CoreLoggerTests.swift +++ b/test/platform/swift/unit_integration/core/CoreLoggerTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import CapturePassable import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/DeviceAttributesTests.swift b/test/platform/swift/unit_integration/core/DeviceAttributesTests.swift similarity index 100% rename from test/platform/swift/unit_integration/DeviceAttributesTests.swift rename to test/platform/swift/unit_integration/core/DeviceAttributesTests.swift diff --git a/test/platform/swift/unit_integration/ErrorBridgeTest.swift b/test/platform/swift/unit_integration/core/ErrorBridgeTest.swift similarity index 99% rename from test/platform/swift/unit_integration/ErrorBridgeTest.swift rename to test/platform/swift/unit_integration/core/ErrorBridgeTest.swift index 98d29c841..4162625f5 100644 --- a/test/platform/swift/unit_integration/ErrorBridgeTest.swift +++ b/test/platform/swift/unit_integration/core/ErrorBridgeTest.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import CaptureTestBridge import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/FieldExtensionsTests.swift b/test/platform/swift/unit_integration/core/FieldExtensionsTests.swift similarity index 100% rename from test/platform/swift/unit_integration/FieldExtensionsTests.swift rename to test/platform/swift/unit_integration/core/FieldExtensionsTests.swift diff --git a/test/platform/swift/unit_integration/mocks/Logger+Tests.swift b/test/platform/swift/unit_integration/core/Logger+Tests.swift similarity index 99% rename from test/platform/swift/unit_integration/mocks/Logger+Tests.swift rename to test/platform/swift/unit_integration/core/Logger+Tests.swift index fbaa9647e..5ca005423 100644 --- a/test/platform/swift/unit_integration/mocks/Logger+Tests.swift +++ b/test/platform/swift/unit_integration/core/Logger+Tests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/LoggerBenchmarkTests.swift b/test/platform/swift/unit_integration/core/LoggerBenchmarkTests.swift similarity index 100% rename from test/platform/swift/unit_integration/LoggerBenchmarkTests.swift rename to test/platform/swift/unit_integration/core/LoggerBenchmarkTests.swift diff --git a/test/platform/swift/unit_integration/LoggerIntegratorTests.swift b/test/platform/swift/unit_integration/core/LoggerIntegratorTests.swift similarity index 98% rename from test/platform/swift/unit_integration/LoggerIntegratorTests.swift rename to test/platform/swift/unit_integration/core/LoggerIntegratorTests.swift index 24362b63a..170edf156 100644 --- a/test/platform/swift/unit_integration/LoggerIntegratorTests.swift +++ b/test/platform/swift/unit_integration/core/LoggerIntegratorTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/LoggerSharedTests.swift b/test/platform/swift/unit_integration/core/LoggerSharedTests.swift similarity index 98% rename from test/platform/swift/unit_integration/LoggerSharedTests.swift rename to test/platform/swift/unit_integration/core/LoggerSharedTests.swift index 8b3466617..85b808068 100644 --- a/test/platform/swift/unit_integration/LoggerSharedTests.swift +++ b/test/platform/swift/unit_integration/core/LoggerSharedTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import XCTest final class LoggerSharedTests: XCTestCase { diff --git a/test/platform/swift/unit_integration/LoggerTests.swift b/test/platform/swift/unit_integration/core/LoggerTests.swift similarity index 99% rename from test/platform/swift/unit_integration/LoggerTests.swift rename to test/platform/swift/unit_integration/core/LoggerTests.swift index a41c70a12..ba6094435 100644 --- a/test/platform/swift/unit_integration/LoggerTests.swift +++ b/test/platform/swift/unit_integration/core/LoggerTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import CapturePassable import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/MetadataProviderTests.swift b/test/platform/swift/unit_integration/core/MetadataProviderTests.swift similarity index 99% rename from test/platform/swift/unit_integration/MetadataProviderTests.swift rename to test/platform/swift/unit_integration/core/MetadataProviderTests.swift index 729b40705..926c7a22f 100644 --- a/test/platform/swift/unit_integration/MetadataProviderTests.swift +++ b/test/platform/swift/unit_integration/core/MetadataProviderTests.swift @@ -7,6 +7,7 @@ @testable import Capture @testable import CaptureLoggerBridge +import CaptureMocks import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/core/ResourceUtilizationTargetTest.swift b/test/platform/swift/unit_integration/core/ResourceUtilizationTargetTest.swift new file mode 100644 index 000000000..7c34d641c --- /dev/null +++ b/test/platform/swift/unit_integration/core/ResourceUtilizationTargetTest.swift @@ -0,0 +1,29 @@ +// capture-sdk - bitdrift's client SDK +// Copyright Bitdrift, Inc. All rights reserved. +// +// Use of this source code is governed by a source available license that can be found in the +// LICENSE file or at: +// https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt + +@testable import Capture +import CaptureMocks +import XCTest + +final class ResourceUtilizationTargetTest: XCTestCase { + func testTargetDoesNotCrash() { + let target = ResourceUtilizationTarget( + storageProvider: MockStorageProvider(), + timeProvider: MockTimeProvider() + ) + + let logger = MockCoreLogging() + target.logger = logger + + let expectation = self.expectation(description: "resource utilization log is emitted") + logger.logResourceUtilizationExpectation = expectation + + target.tick() + + XCTAssertEqual(.completed, XCTWaiter().wait(for: [expectation], timeout: 0.5)) + } +} diff --git a/test/platform/swift/unit_integration/SessionStrategyTests.swift b/test/platform/swift/unit_integration/core/SessionStrategyTests.swift similarity index 100% rename from test/platform/swift/unit_integration/SessionStrategyTests.swift rename to test/platform/swift/unit_integration/core/SessionStrategyTests.swift diff --git a/test/platform/swift/unit_integration/SessionURLTests.swift b/test/platform/swift/unit_integration/core/SessionURLTests.swift similarity index 100% rename from test/platform/swift/unit_integration/SessionURLTests.swift rename to test/platform/swift/unit_integration/core/SessionURLTests.swift diff --git a/test/platform/swift/unit_integration/bindings/HTTPRequestInfo+ExtensionsTests.swift b/test/platform/swift/unit_integration/core/bindings/HTTPRequestInfo+ExtensionsTests.swift similarity index 100% rename from test/platform/swift/unit_integration/bindings/HTTPRequestInfo+ExtensionsTests.swift rename to test/platform/swift/unit_integration/core/bindings/HTTPRequestInfo+ExtensionsTests.swift diff --git a/test/platform/swift/unit_integration/bridge/EventsListenerTargetTests.swift b/test/platform/swift/unit_integration/core/bridge/EventsListenerTargetTests.swift similarity index 97% rename from test/platform/swift/unit_integration/bridge/EventsListenerTargetTests.swift rename to test/platform/swift/unit_integration/core/bridge/EventsListenerTargetTests.swift index 99a82261b..e4ebb78f7 100644 --- a/test/platform/swift/unit_integration/bridge/EventsListenerTargetTests.swift +++ b/test/platform/swift/unit_integration/core/bridge/EventsListenerTargetTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks @testable import CaptureTestBridge import XCTest diff --git a/test/platform/swift/unit_integration/bridge/KeyValueStorageTests.swift b/test/platform/swift/unit_integration/core/bridge/KeyValueStorageTests.swift similarity index 100% rename from test/platform/swift/unit_integration/bridge/KeyValueStorageTests.swift rename to test/platform/swift/unit_integration/core/bridge/KeyValueStorageTests.swift diff --git a/test/platform/swift/unit_integration/bridge/ResourceUtilizationTargetTests.swift b/test/platform/swift/unit_integration/core/bridge/ResourceUtilizationTargetTests.swift similarity index 99% rename from test/platform/swift/unit_integration/bridge/ResourceUtilizationTargetTests.swift rename to test/platform/swift/unit_integration/core/bridge/ResourceUtilizationTargetTests.swift index 8b985e11a..58917cc22 100644 --- a/test/platform/swift/unit_integration/bridge/ResourceUtilizationTargetTests.swift +++ b/test/platform/swift/unit_integration/core/bridge/ResourceUtilizationTargetTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks @testable import CaptureTestBridge import XCTest diff --git a/test/platform/swift/unit_integration/helpers/XCTestCase+Extensions.swift b/test/platform/swift/unit_integration/core/helpers/XCTestCase+Extensions.swift similarity index 100% rename from test/platform/swift/unit_integration/helpers/XCTestCase+Extensions.swift rename to test/platform/swift/unit_integration/core/helpers/XCTestCase+Extensions.swift diff --git a/test/platform/swift/unit_integration/logging/HTTPHeadersTests.swift b/test/platform/swift/unit_integration/core/logging/HTTPHeadersTests.swift similarity index 100% rename from test/platform/swift/unit_integration/logging/HTTPHeadersTests.swift rename to test/platform/swift/unit_integration/core/logging/HTTPHeadersTests.swift diff --git a/test/platform/swift/unit_integration/logging/HTTPRequestInfoTests.swift b/test/platform/swift/unit_integration/core/logging/HTTPRequestInfoTests.swift similarity index 100% rename from test/platform/swift/unit_integration/logging/HTTPRequestInfoTests.swift rename to test/platform/swift/unit_integration/core/logging/HTTPRequestInfoTests.swift diff --git a/test/platform/swift/unit_integration/logging/HTTPResponseInfoTests.swift b/test/platform/swift/unit_integration/core/logging/HTTPResponseInfoTests.swift similarity index 100% rename from test/platform/swift/unit_integration/logging/HTTPResponseInfoTests.swift rename to test/platform/swift/unit_integration/core/logging/HTTPResponseInfoTests.swift diff --git a/test/platform/swift/unit_integration/logging/HTTPResponseTests.swift b/test/platform/swift/unit_integration/core/logging/HTTPResponseTests.swift similarity index 100% rename from test/platform/swift/unit_integration/logging/HTTPResponseTests.swift rename to test/platform/swift/unit_integration/core/logging/HTTPResponseTests.swift diff --git a/test/platform/swift/unit_integration/logging/SpanTests.swift b/test/platform/swift/unit_integration/core/logging/SpanTests.swift similarity index 99% rename from test/platform/swift/unit_integration/logging/SpanTests.swift rename to test/platform/swift/unit_integration/core/logging/SpanTests.swift index 906579d76..5e9bec3f5 100644 --- a/test/platform/swift/unit_integration/logging/SpanTests.swift +++ b/test/platform/swift/unit_integration/core/logging/SpanTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/network/CaptureNetworkTests.swift b/test/platform/swift/unit_integration/core/network/CaptureNetworkTests.swift similarity index 100% rename from test/platform/swift/unit_integration/network/CaptureNetworkTests.swift rename to test/platform/swift/unit_integration/core/network/CaptureNetworkTests.swift diff --git a/test/platform/swift/unit_integration/network/LoggerE2ETest.swift b/test/platform/swift/unit_integration/core/network/LoggerE2ETest.swift similarity index 99% rename from test/platform/swift/unit_integration/network/LoggerE2ETest.swift rename to test/platform/swift/unit_integration/core/network/LoggerE2ETest.swift index fa2c5d7d6..ca35c9015 100644 --- a/test/platform/swift/unit_integration/network/LoggerE2ETest.swift +++ b/test/platform/swift/unit_integration/core/network/LoggerE2ETest.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import CapturePassable import CaptureTestBridge import Foundation diff --git a/test/platform/swift/unit_integration/network/helper/BaseNetworkingTestCase.swift b/test/platform/swift/unit_integration/core/network/helper/BaseNetworkingTestCase.swift similarity index 99% rename from test/platform/swift/unit_integration/network/helper/BaseNetworkingTestCase.swift rename to test/platform/swift/unit_integration/core/network/helper/BaseNetworkingTestCase.swift index 05348fccb..c41db19e1 100644 --- a/test/platform/swift/unit_integration/network/helper/BaseNetworkingTestCase.swift +++ b/test/platform/swift/unit_integration/core/network/helper/BaseNetworkingTestCase.swift @@ -7,6 +7,7 @@ @testable import Capture import CaptureLoggerBridge +import CaptureMocks import CaptureTestBridge import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/network/helper/TestServerHelpers.swift b/test/platform/swift/unit_integration/core/network/helper/TestServerHelpers.swift similarity index 100% rename from test/platform/swift/unit_integration/network/helper/TestServerHelpers.swift rename to test/platform/swift/unit_integration/core/network/helper/TestServerHelpers.swift diff --git a/test/platform/swift/unit_integration/shared/Extensions/EncodableExtensionsTests.swift b/test/platform/swift/unit_integration/core/shared/Extensions/EncodableExtensionsTests.swift similarity index 100% rename from test/platform/swift/unit_integration/shared/Extensions/EncodableExtensionsTests.swift rename to test/platform/swift/unit_integration/core/shared/Extensions/EncodableExtensionsTests.swift diff --git a/test/platform/swift/unit_integration/shared/QueueTimerTests.swift b/test/platform/swift/unit_integration/core/shared/QueueTimerTests.swift similarity index 100% rename from test/platform/swift/unit_integration/shared/QueueTimerTests.swift rename to test/platform/swift/unit_integration/core/shared/QueueTimerTests.swift diff --git a/test/platform/swift/unit_integration/integrations/BUILD b/test/platform/swift/unit_integration/integrations/BUILD new file mode 100644 index 000000000..2d97ecafc --- /dev/null +++ b/test/platform/swift/unit_integration/integrations/BUILD @@ -0,0 +1,13 @@ +load("//bazel:bitdrift_swift_test.bzl", "bitdrift_mobile_swift_test") + +bitdrift_mobile_swift_test( + name = "test", + srcs = glob(["**/*.swift"]), + repository = "@capture", + tags = ["macos_only"], + visibility = ["//visibility:public"], + deps = [ + "//platform/swift/source:ios_lib", + "//test/platform/swift/unit_integration/mocks", + ], +) diff --git a/test/platform/swift/unit_integration/integrations/URLSessionIntegrationTests.swift b/test/platform/swift/unit_integration/integrations/URLSessionIntegrationTests.swift index 729f9e640..bbe88d7df 100644 --- a/test/platform/swift/unit_integration/integrations/URLSessionIntegrationTests.swift +++ b/test/platform/swift/unit_integration/integrations/URLSessionIntegrationTests.swift @@ -6,6 +6,7 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt @testable import Capture +import CaptureMocks import Foundation import XCTest diff --git a/test/platform/swift/unit_integration/mocks/BUILD b/test/platform/swift/unit_integration/mocks/BUILD new file mode 100644 index 000000000..d5db0e370 --- /dev/null +++ b/test/platform/swift/unit_integration/mocks/BUILD @@ -0,0 +1,17 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "mocks", + testonly = True, + srcs = glob(["**/*.swift"]), + features = [ + "swift.enable_library_evolution", + ], + module_name = "CaptureMocks", + tags = ["macos_only"], + visibility = ["//visibility:public"], + deps = [ + "//platform/swift/source:ios_lib", + "//platform/swift/source:rust_bridge", + ], +) diff --git a/test/platform/swift/unit_integration/mocks/MockConnection.swift b/test/platform/swift/unit_integration/mocks/MockConnection.swift index f197354b7..629855383 100644 --- a/test/platform/swift/unit_integration/mocks/MockConnection.swift +++ b/test/platform/swift/unit_integration/mocks/MockConnection.swift @@ -9,34 +9,34 @@ import CapturePassable import Foundation -final class MockConnection: NSObject, Connection, NetworkStream { +public final class MockConnection: NSObject, Connection, NetworkStream { // MARK: - Connection var onConnect: (() -> Void)? var onOpenAndProvideStream: (() -> Void)? var onEnd: (() -> Void)? - func connect() { + public func connect() { self.onConnect?() } - func openAndProvideStream(_: (InputStream?) -> Void) { + public func openAndProvideStream(_: (InputStream?) -> Void) { self.onOpenAndProvideStream?() } - func end() { + public func end() { self.onEnd?() } // MARK: - NetworkStream - var handler: ConnectionDataHandler = StreamHandle(streamID: 0) - var onSendData: ((UnsafePointer, Int) -> Void)? + public var handler: ConnectionDataHandler = StreamHandle(streamID: 0) + public var onSendData: ((UnsafePointer, Int) -> Void)? - func sendData(_ baseAddress: UnsafePointer, count: Int) -> Int { + public func sendData(_ baseAddress: UnsafePointer, count: Int) -> Int { self.onSendData?(baseAddress, count) return count } - func shutdown() {} + public func shutdown() {} } diff --git a/test/platform/swift/unit_integration/mocks/MockCoreLogging.swift b/test/platform/swift/unit_integration/mocks/MockCoreLogging.swift index 3f88f2f7b..35f146186 100644 --- a/test/platform/swift/unit_integration/mocks/MockCoreLogging.swift +++ b/test/platform/swift/unit_integration/mocks/MockCoreLogging.swift @@ -10,46 +10,48 @@ import CaptureLoggerBridge import Foundation import XCTest -final class MockCoreLogging { - struct Log { - let level: LogLevel - let message: String - let file: String? - let line: Int? - let function: String? - let fields: Fields? - let matchingFields: Fields? - let error: Error? - let type: Logger.LogType - let blocking: Bool +public final class MockCoreLogging { + public struct Log { + public let level: LogLevel + public let message: String + public let file: String? + public let line: Int? + public let function: String? + public let fields: Fields? + public let matchingFields: Fields? + public let error: Error? + public let type: Logger.LogType + public let blocking: Bool } - struct ResourceUtilizationLog { - let fields: Fields - let duration: TimeInterval + public struct ResourceUtilizationLog { + public let fields: Fields + public let duration: TimeInterval } - private(set) var logs = [Log]() - var logExpectation: XCTestExpectation? + public private(set) var logs = [Log]() + public var logExpectation: XCTestExpectation? - private(set) var logAppUpdateCount = 0 - var logAppUpdateExpectation: XCTestExpectation? + public private(set) var logAppUpdateCount = 0 + public var logAppUpdateExpectation: XCTestExpectation? - private(set) var resourceUtilizationLogs = [ResourceUtilizationLog]() - var logResourceUtilizationExpectation: XCTestExpectation? + public private(set) var resourceUtilizationLogs = [ResourceUtilizationLog]() + public var logResourceUtilizationExpectation: XCTestExpectation? - var shouldLogAppUpdateEvent = false + public var shouldLogAppUpdateEvent = false - private(set) var mockedRuntimeVariables = [String: Any]() + public private(set) var mockedRuntimeVariables = [String: Any]() - func mockRuntimeVariable(_ variable: RuntimeVariable, with value: T) { + public init() {} + + public func mockRuntimeVariable(_ variable: RuntimeVariable, with value: T) { let values = [variable.name: value] self.mockedRuntimeVariables.mergeOverwritingConflictingKeys(values) } } extension MockCoreLogging: CoreLogging { - static func makeLogger( + public static func makeLogger( apiKey _: String, bufferDirectory _: URL?, sessionStrategy _: SessionStrategy, @@ -64,15 +66,15 @@ extension MockCoreLogging: CoreLogging { return MockCoreLogging() } - func start() {} + public func start() {} - func startNewSession() {} + public func startNewSession() {} - func getSessionID() -> String { "foo" } + public func getSessionID() -> String { "foo" } - func getDeviceID() -> String { "deviceID" } + public func getDeviceID() -> String { "deviceID" } - func log( + public func log( level: LogLevel, message: @autoclosure () -> String, file: String?, @@ -101,20 +103,20 @@ extension MockCoreLogging: CoreLogging { self.logExpectation?.fulfill() } - func logSessionReplay(screen _: SessionReplayScreenCapture, duration _: TimeInterval) {} + public func logSessionReplay(screen _: SessionReplayScreenCapture, duration _: TimeInterval) {} - func logResourceUtilization(fields: Fields, duration: TimeInterval) { + public func logResourceUtilization(fields: Fields, duration: TimeInterval) { self.resourceUtilizationLogs.append(ResourceUtilizationLog(fields: fields, duration: duration)) self.logResourceUtilizationExpectation?.fulfill() } - func logSDKStart(fields _: Fields, duration _: TimeInterval) {} + public func logSDKStart(fields _: Fields, duration _: TimeInterval) {} - func shouldLogAppUpdate(appVersion _: String, buildNumber _: String) -> Bool { + public func shouldLogAppUpdate(appVersion _: String, buildNumber _: String) -> Bool { return self.shouldLogAppUpdateEvent } - func logAppUpdate( + public func logAppUpdate( appVersion _: String, buildNumber _: String, appSizeBytes _: UInt64, @@ -124,15 +126,15 @@ extension MockCoreLogging: CoreLogging { self.logAppUpdateExpectation?.fulfill() } - func logAppLaunchTTI(_: TimeInterval) {} + public func logAppLaunchTTI(_: TimeInterval) {} - func addField(withKey _: String, value _: String) {} + public func addField(withKey _: String, value _: String) {} - func removeField(withKey _: String) {} + public func removeField(withKey _: String) {} - func flush(blocking _: Bool) {} + public func flush(blocking _: Bool) {} - func runtimeValue(_ variable: RuntimeVariable) -> T { + public func runtimeValue(_ variable: RuntimeVariable) -> T { if let value = self.mockedRuntimeVariables[variable.name] { // swiftlint:disable:next force_cast value as! T @@ -141,7 +143,7 @@ extension MockCoreLogging: CoreLogging { } } - func handleError(context _: String, error _: Error) {} + public func handleError(context _: String, error _: Error) {} - func enableBlockingShutdown() {} + public func enableBlockingShutdown() {} } diff --git a/test/platform/swift/unit_integration/mocks/MockDateProvider.swift b/test/platform/swift/unit_integration/mocks/MockDateProvider.swift index 30b4d5630..9f82a711c 100644 --- a/test/platform/swift/unit_integration/mocks/MockDateProvider.swift +++ b/test/platform/swift/unit_integration/mocks/MockDateProvider.swift @@ -8,15 +8,15 @@ import Capture import Foundation -final class MockDateProvider: DateProvider { - var getDateClosure: () -> Date +public final class MockDateProvider: DateProvider { + public var getDateClosure: () -> Date // This should return "2022-10-26T17:56:41.520058155Z" when formatted. - init(getDateClosure: @escaping () -> Date = { Date(timeIntervalSince1970: 1_666_807_001.52005815) }) { + public init(getDateClosure: @escaping () -> Date = { Date(timeIntervalSince1970: 1_666_807_001.52005815) }) { self.getDateClosure = getDateClosure } - func getDate() -> Date { + public func getDate() -> Date { return self.getDateClosure() } } diff --git a/test/platform/swift/unit_integration/mocks/MockErrorHandler.swift b/test/platform/swift/unit_integration/mocks/MockErrorHandler.swift index 8c4328fdc..d669eef37 100644 --- a/test/platform/swift/unit_integration/mocks/MockErrorHandler.swift +++ b/test/platform/swift/unit_integration/mocks/MockErrorHandler.swift @@ -7,15 +7,17 @@ @testable import Capture -final class MockErrorHandler { - struct ErrorReport { - let context: String - let error: Error +public final class MockErrorHandler { + public struct ErrorReport { + public let context: String + public let error: Error } - private(set) var errors: [ErrorReport] = [] + public private(set) var errors: [ErrorReport] = [] - func handleError(context: String, error: Error) { + public init() {} + + public func handleError(context: String, error: Error) { self.errors.append(ErrorReport(context: context, error: error)) } } diff --git a/test/platform/swift/unit_integration/mocks/MockEventsListenerTarget.swift b/test/platform/swift/unit_integration/mocks/MockEventsListenerTarget.swift index 59c674146..39a0aee74 100644 --- a/test/platform/swift/unit_integration/mocks/MockEventsListenerTarget.swift +++ b/test/platform/swift/unit_integration/mocks/MockEventsListenerTarget.swift @@ -7,7 +7,9 @@ @testable import CaptureLoggerBridge -final class MockEventsListenerTarget: CaptureLoggerBridge.EventsListenerTarget { - func start() {} - func stop() {} +public final class MockEventsListenerTarget: CaptureLoggerBridge.EventsListenerTarget { + public init() {} + + public func start() {} + public func stop() {} } diff --git a/test/platform/swift/unit_integration/mocks/MockFieldProvider.swift b/test/platform/swift/unit_integration/mocks/MockFieldProvider.swift index 98598449a..b7795cc15 100644 --- a/test/platform/swift/unit_integration/mocks/MockFieldProvider.swift +++ b/test/platform/swift/unit_integration/mocks/MockFieldProvider.swift @@ -7,14 +7,14 @@ import Capture -final class MockFieldProvider: FieldProvider { - let getFieldsClosure: () -> Fields +public final class MockFieldProvider: FieldProvider { + public let getFieldsClosure: () -> Fields - init(getFieldsClosure: @escaping () -> Fields = { [:] }) { + public init(getFieldsClosure: @escaping () -> Fields = { [:] }) { self.getFieldsClosure = getFieldsClosure } - func getFields() -> Fields { + public func getFields() -> Fields { return self.getFieldsClosure() } } diff --git a/test/platform/swift/unit_integration/mocks/MockLoggerBridging.swift b/test/platform/swift/unit_integration/mocks/MockLoggerBridging.swift index 13dd4f2e3..68f97bd01 100644 --- a/test/platform/swift/unit_integration/mocks/MockLoggerBridging.swift +++ b/test/platform/swift/unit_integration/mocks/MockLoggerBridging.swift @@ -10,50 +10,52 @@ import CaptureLoggerBridge import Foundation import XCTest -final class MockLoggerBridging { - struct HandledError { - let context: String - let error: Error +public final class MockLoggerBridging { + public struct HandledError { + public let context: String + public let error: Error } - struct Log { - let level: LogLevel - let message: String - let fields: InternalFields? - let matchingFields: InternalFields? - let type: Logger.LogType - let blocking: Bool + public struct Log { + public let level: LogLevel + public let message: String + public let fields: InternalFields? + public let matchingFields: InternalFields? + public let type: Logger.LogType + public let blocking: Bool } - private(set) var mockedRuntimeVariables = [String: Any]() + public private(set) var mockedRuntimeVariables = [String: Any]() - private(set) var underlyingLogs = Atomic([Log]()) - var logs: [Log] { + public private(set) var underlyingLogs = Atomic([Log]()) + public var logs: [Log] { return self.underlyingLogs.load() } - private(set) var errors: [HandledError] = [] + public private(set) var errors: [HandledError] = [] - var shouldLogAppUpdateEvent = false + public var shouldLogAppUpdateEvent = false - var logAppUpdateExpectation: XCTestExpectation? + public var logAppUpdateExpectation: XCTestExpectation? - func mockRuntimeVariable(_ variable: RuntimeVariable, with value: T) { + public init() {} + + public func mockRuntimeVariable(_ variable: RuntimeVariable, with value: T) { let values = [variable.name: value] self.mockedRuntimeVariables.mergeOverwritingConflictingKeys(values) } } extension MockLoggerBridging: LoggerBridging { - func start() {} + public func start() {} - func getSessionID() -> String { "foo" } + public func getSessionID() -> String { "foo" } - func startNewSession() {} + public func startNewSession() {} - func getDeviceID() -> String { "deviceID" } + public func getDeviceID() -> String { "deviceID" } - func log( + public func log( level: LogLevel, message: @autoclosure () -> String, fields: InternalFields?, @@ -75,17 +77,17 @@ extension MockLoggerBridging: LoggerBridging { } } - func logSessionReplay(fields _: [Field], duration _: TimeInterval) {} + public func logSessionReplay(fields _: [Field], duration _: TimeInterval) {} - func logResourceUtilization(fields _: [Field], duration _: TimeInterval) {} + public func logResourceUtilization(fields _: [Field], duration _: TimeInterval) {} - func logSDKStart(fields _: [Field], duration _: TimeInterval) {} + public func logSDKStart(fields _: [Field], duration _: TimeInterval) {} - func shouldLogAppUpdate(appVersion _: String, buildNumber _: String) -> Bool { + public func shouldLogAppUpdate(appVersion _: String, buildNumber _: String) -> Bool { self.shouldLogAppUpdateEvent } - func logAppUpdate( + public func logAppUpdate( appVersion _: String, buildNumber _: String, appSizeBytes _: UInt64, @@ -94,15 +96,15 @@ extension MockLoggerBridging: LoggerBridging { self.logAppUpdateExpectation?.fulfill() } - func logAppLaunchTTI(_: TimeInterval) {} + public func logAppLaunchTTI(_: TimeInterval) {} - func addField(withKey _: String, value _: String) {} + public func addField(withKey _: String, value _: String) {} - func removeField(withKey _: String) {} + public func removeField(withKey _: String) {} - func flush(blocking _: Bool) {} + public func flush(blocking _: Bool) {} - func runtimeValue(_ variable: RuntimeVariable) -> T { + public func runtimeValue(_ variable: RuntimeVariable) -> T { if let value = self.mockedRuntimeVariables[variable.name] { // swiftlint:disable:next force_cast value as! T @@ -111,9 +113,9 @@ extension MockLoggerBridging: LoggerBridging { } } - func handleError(context: String, error: Error) { + public func handleError(context: String, error: Error) { self.errors.append(HandledError(context: context, error: error)) } - func enableBlockingShutdown() {} + public func enableBlockingShutdown() {} } diff --git a/test/platform/swift/unit_integration/mocks/MockLoggerBridgingFactory.swift b/test/platform/swift/unit_integration/mocks/MockLoggerBridgingFactory.swift index 9ab04f17f..9b6818894 100644 --- a/test/platform/swift/unit_integration/mocks/MockLoggerBridgingFactory.swift +++ b/test/platform/swift/unit_integration/mocks/MockLoggerBridgingFactory.swift @@ -9,15 +9,15 @@ import CaptureLoggerBridge import Foundation -final class MockLoggerBridgingFactory: LoggerBridgingFactoryProvider { +public final class MockLoggerBridgingFactory: LoggerBridgingFactoryProvider { private let logger: LoggerBridging? - private(set) var makeLoggerCallsCount = 0 + public private(set) var makeLoggerCallsCount = 0 - init(logger: LoggerBridging?) { + public init(logger: LoggerBridging?) { self.logger = logger } - func makeLogger( + public func makeLogger( apiKey _: String, bufferDirectoryPath _: String?, sessionStrategy _: SessionStrategy, diff --git a/test/platform/swift/unit_integration/mocks/MockLogging.swift b/test/platform/swift/unit_integration/mocks/MockLogging.swift index b7db23649..84a8c3c8d 100644 --- a/test/platform/swift/unit_integration/mocks/MockLogging.swift +++ b/test/platform/swift/unit_integration/mocks/MockLogging.swift @@ -9,8 +9,8 @@ import XCTest /// Logging interface mock. -final class MockLogging { - struct Log { +public final class MockLogging { + public struct Log { enum Object { case message(String) case request(HTTPRequestInfo) @@ -21,7 +21,7 @@ final class MockLogging { let object: Object let fields: Fields? - func message() -> String? { + public func message() -> String? { if case let .message(message) = self.object { return message } @@ -29,7 +29,7 @@ final class MockLogging { return nil } - func request() -> HTTPRequestInfo? { + public func request() -> HTTPRequestInfo? { if case let .request(request) = self.object { return request } @@ -37,7 +37,7 @@ final class MockLogging { return nil } - func response() -> HTTPResponseInfo? { + public func response() -> HTTPResponseInfo? { if case let .response(response) = self.object { return response } @@ -46,27 +46,29 @@ final class MockLogging { } } - var logExpectation: XCTestExpectation? - var logRequestExpectation: XCTestExpectation? - var logResponseExpectation: XCTestExpectation? + public var logExpectation: XCTestExpectation? + public var logRequestExpectation: XCTestExpectation? + public var logResponseExpectation: XCTestExpectation? + + public init() {} /// The logs emitted by the logger - private(set) var logs = [Log]() + public private(set) var logs = [Log]() /// The number of logs emitted by the logger. - var logsCount: Int { self.logs.count } + public var logsCount: Int { self.logs.count } /// A closure that's called every time a log is emitted by the logger. - var onLog: (_ log: Log) -> Void = { _ in } + public var onLog: (_ log: Log) -> Void = { _ in } } extension MockLogging: Logging { - var sessionID: String { "fooID" } - var sessionURL: String { "fooURL" } + public var sessionID: String { "fooID" } + public var sessionURL: String { "fooURL" } - func startNewSession() {} + public func startNewSession() {} - var deviceID: String { "deviceID" } + public var deviceID: String { "deviceID" } - func log( + public func log( level: LogLevel, message: @autoclosure () -> String, file _: String?, @@ -85,7 +87,7 @@ extension MockLogging: Logging { self.onLog(log) } - func log(_ request: HTTPRequestInfo, file _: String?, line _: Int?, function _: String?) { + public func log(_ request: HTTPRequestInfo, file _: String?, line _: Int?, function _: String?) { let log = Log( level: .debug, object: .request(request), @@ -97,7 +99,7 @@ extension MockLogging: Logging { self.onLog(log) } - func log(_ response: HTTPResponseInfo, file _: String?, line _: Int?, function _: String?) { + public func log(_ response: HTTPResponseInfo, file _: String?, line _: Int?, function _: String?) { let log = Log( level: .debug, object: .response(response), @@ -109,11 +111,11 @@ extension MockLogging: Logging { self.onLog(log) } - func logAppLaunchTTI(_: TimeInterval) {} + public func logAppLaunchTTI(_: TimeInterval) {} - func addField(withKey _: String, value _: FieldValue) {} + public func addField(withKey _: String, value _: FieldValue) {} - func removeField(withKey _: String) {} + public func removeField(withKey _: String) {} - func createTemporaryDeviceCode(completion _: @escaping (Result) -> Void) {} + public func createTemporaryDeviceCode(completion _: @escaping (Result) -> Void) {} } diff --git a/test/platform/swift/unit_integration/mocks/MockNetworkClient.swift b/test/platform/swift/unit_integration/mocks/MockNetworkClient.swift index df1fe5243..9e891be17 100644 --- a/test/platform/swift/unit_integration/mocks/MockNetworkClient.swift +++ b/test/platform/swift/unit_integration/mocks/MockNetworkClient.swift @@ -8,13 +8,13 @@ @testable import Capture import Foundation -final class MockNetworkClient: NetworkClient { - func createConnection(to _: URL, - handler _: ConnectionDataHandler, - headers _: [String: String]) -> NetworkStreamConnection +public final class MockNetworkClient: NetworkClient { + public func createConnection(to _: URL, + handler _: ConnectionDataHandler, + headers _: [String: String]) -> NetworkStreamConnection { return MockConnection() } - func tearDown() {} + public func tearDown() {} } diff --git a/test/platform/swift/unit_integration/mocks/MockRemoteErrorReporter.swift b/test/platform/swift/unit_integration/mocks/MockRemoteErrorReporter.swift index febbedbda..a0fd5cd69 100644 --- a/test/platform/swift/unit_integration/mocks/MockRemoteErrorReporter.swift +++ b/test/platform/swift/unit_integration/mocks/MockRemoteErrorReporter.swift @@ -11,7 +11,7 @@ import Foundation import XCTest public final class MockRemoteErrorReporter: NSObject { - var onReportError: ((String) -> Void)? + public var onReportError: ((String) -> Void)? } extension MockRemoteErrorReporter: RemoteErrorReporting { diff --git a/test/platform/swift/unit_integration/mocks/MockStorageProvider.swift b/test/platform/swift/unit_integration/mocks/MockStorageProvider.swift index 14bc98386..2c8f3ea05 100644 --- a/test/platform/swift/unit_integration/mocks/MockStorageProvider.swift +++ b/test/platform/swift/unit_integration/mocks/MockStorageProvider.swift @@ -8,14 +8,16 @@ @testable import Capture import Foundation -final class MockStorageProvider: StorageProvider { +public final class MockStorageProvider: StorageProvider { private var storage = [String: Any]() - func get(_ key: StorageKey) -> T? { + public init() {} + + public func get(_ key: StorageKey) -> T? { return self.storage[key.key] as? T } - func set(_ value: T?, forKey key: StorageKey) { + public func set(_ value: T?, forKey key: StorageKey) { self.storage[key.key] = value } } diff --git a/test/platform/swift/unit_integration/mocks/MockTimingProvider.swift b/test/platform/swift/unit_integration/mocks/MockTimingProvider.swift index 4175e2699..0cde6b932 100644 --- a/test/platform/swift/unit_integration/mocks/MockTimingProvider.swift +++ b/test/platform/swift/unit_integration/mocks/MockTimingProvider.swift @@ -8,20 +8,20 @@ @testable import Capture import Foundation -final class MockTimeProvider { +public final class MockTimeProvider { var timeIntervalSince1970: TimeInterval - init(timeIntervalSince1970: TimeInterval = Date().timeIntervalSince1970) { + public init(timeIntervalSince1970: TimeInterval = Date().timeIntervalSince1970) { self.timeIntervalSince1970 = timeIntervalSince1970 } - func advanceBy(timeInterval: TimeInterval) { + public func advanceBy(timeInterval: TimeInterval) { self.timeIntervalSince1970 += timeInterval } } extension MockTimeProvider: TimeProvider { - func uptime() -> Uptime { Uptime(uptime: self.timeIntervalSince1970) } + public func uptime() -> Uptime { Uptime(uptime: self.timeIntervalSince1970) } - func now() -> Date { Date(timeIntervalSince1970: self.timeIntervalSince1970) } + public func now() -> Date { Date(timeIntervalSince1970: self.timeIntervalSince1970) } }