From 930823c9ad02a220c264ebdaabe43666ae62c77c Mon Sep 17 00:00:00 2001 From: Andrew Heard Date: Tue, 31 Oct 2023 16:03:21 -0400 Subject: [PATCH 1/2] Replace FIRDeviceCheckAPIServiceE2ETests with AppCheckE2ETests --- FirebaseAppCheck.podspec | 4 +- .../Tests/Integration/AppCheckE2ETests.swift | 128 ++++++++++++++++++ .../FIRDeviceCheckAPIServiceE2ETests.m | 101 -------------- 3 files changed, 129 insertions(+), 104 deletions(-) create mode 100644 FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift delete mode 100644 FirebaseAppCheck/Tests/Integration/FIRDeviceCheckAPIServiceE2ETests.m diff --git a/FirebaseAppCheck.podspec b/FirebaseAppCheck.podspec index 16e88889ea2..0e7e5a11816 100644 --- a/FirebaseAppCheck.podspec +++ b/FirebaseAppCheck.podspec @@ -81,10 +81,8 @@ Pod::Spec.new do |s| :tvos => tvos_deployment_target } integration_tests.source_files = [ - base_dir + 'Tests/Integration/**/*.[mh]', - base_dir + 'Tests/Integration/**/*.[mh]', + base_dir + 'Tests/Integration/**/*.swift', ] - integration_tests.resources = base_dir + 'Tests/Fixture/**/*' integration_tests.requires_app_host = true end diff --git a/FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift b/FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift new file mode 100644 index 00000000000..216d5dfc666 --- /dev/null +++ b/FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift @@ -0,0 +1,128 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import FirebaseAppCheck +import FirebaseCore +import XCTest + +// Tests that use the Keychain require a host app and Swift Package Manager does not support adding +// a host app to test targets. +#if !SWIFT_PACKAGE + + final class AppCheckE2ETests: XCTestCase { + let appName = "test_app_name" + var app: FirebaseApp! + + override func setUp() { + AppCheck.setAppCheckProviderFactory(TestAppCheckProviderFactory()) + let options = FirebaseOptions( + googleAppID: "1:123456789:ios:abc123", + gcmSenderID: "123456789" + ) + options.projectID = "test_project_id" + options.apiKey = "test_api_key" + FirebaseApp.configure(name: appName, options: options) + + app = FirebaseApp.app(name: appName) + } + + override func tearDown() { + let semaphore = DispatchSemaphore(value: 0) + app.delete { _ in + semaphore.signal() + } + semaphore.wait() + } + + func testInitAppCheck() throws { + let appCheck = AppCheck.appCheck(app: app) + + XCTAssertNotNil(appCheck) + } + + func testInitAppCheckDebugProvider() throws { + let debugProvider = AppCheckDebugProvider(app: app) + + XCTAssertNotNil(debugProvider) + } + + func testInitAppCheckDebugProviderFactory() throws { + let debugProvider = AppCheckDebugProviderFactory().createProvider(with: app) + + XCTAssertNotNil(debugProvider) + } + + @available(iOS 11.0, macOS 10.15, macCatalyst 13.0, tvOS 11.0, watchOS 9.0, *) + func testInitDeviceCheckProvider() throws { + let deviceCheckProvider = DeviceCheckProvider(app: app) + + XCTAssertNotNil(deviceCheckProvider) + } + + @available(iOS 11.0, macOS 10.15, macCatalyst 13.0, tvOS 11.0, watchOS 9.0, *) + func testDeviceCheckProviderFactoryCreate() throws { + let deviceCheckProvider = DeviceCheckProviderFactory().createProvider(with: app) + + XCTAssertNotNil(deviceCheckProvider) + } + + @available(iOS 14.0, macOS 11.3, macCatalyst 14.5, tvOS 15.0, watchOS 9.0, *) + func testInitAppAttestProvider() throws { + let appAttestProvider = AppAttestProvider(app: app) + + XCTAssertNotNil(appAttestProvider) + } + + // The following test is disabled on macOS since `token(forcingRefresh:handler:)` requires a + // provisioning profile to access the keychain to cache tokens. + // See go/firebase-macos-keychain-popups for more details. + #if !os(macOS) && !targetEnvironment(macCatalyst) + func testGetToken() throws { + guard let appCheck = AppCheck.appCheck(app: app) else { + XCTFail("AppCheck instance is nil.") + return + } + + let expectation = XCTestExpectation() + appCheck.token(forcingRefresh: true) { token, error in + XCTAssertNil(error) + XCTAssertNotNil(token) + XCTAssertEqual(token?.token, TestAppCheckProvider.tokenValue) + expectation.fulfill() + } + + wait(for: [expectation], timeout: 0.5) + } + #endif // !os(macOS) && !targetEnvironment(macCatalyst) + } + + class TestAppCheckProvider: NSObject, AppCheckProvider { + static let tokenValue = "TestToken" + + func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) { + let token = AppCheckToken( + token: TestAppCheckProvider.tokenValue, + expirationDate: Date.distantFuture + ) + handler(token, nil) + } + } + + class TestAppCheckProviderFactory: NSObject, AppCheckProviderFactory { + func createProvider(with app: FirebaseApp) -> AppCheckProvider? { + return TestAppCheckProvider() + } + } + +#endif // !SWIFT_PACKAGE diff --git a/FirebaseAppCheck/Tests/Integration/FIRDeviceCheckAPIServiceE2ETests.m b/FirebaseAppCheck/Tests/Integration/FIRDeviceCheckAPIServiceE2ETests.m deleted file mode 100644 index 36ec2f93190..00000000000 --- a/FirebaseAppCheck/Tests/Integration/FIRDeviceCheckAPIServiceE2ETests.m +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -// Tests that use the Keychain require a host app and Swift Package Manager -// does not support adding a host app to test targets. -#if !SWIFT_PACKAGE - -// Skip keychain tests on Catalyst and macOS. Tests are skipped because they -// involve interactions with the keychain that require a provisioning profile. -// See go/firebase-macos-keychain-popups for more details. -#if !TARGET_OS_MACCATALYST && !TARGET_OS_OSX - -#import - -#import "FBLPromise+Testing.h" - -#import - -#import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h" -#import "FirebaseAppCheck/Sources/DeviceCheckProvider/API/FIRDeviceCheckAPIService.h" -#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckToken.h" - -#import "FirebaseCore/Extension/FirebaseCoreInternal.h" - -@interface FIRDeviceCheckAPIServiceE2ETests : XCTestCase -@property(nonatomic) FIRDeviceCheckAPIService *deviceCheckAPIService; -@property(nonatomic) FIRAppCheckAPIService *APIService; -@property(nonatomic) NSURLSession *URLSession; -@end - -// TODO(ncooke3): Fix these tests up and get them running on CI. - -@implementation FIRDeviceCheckAPIServiceE2ETests - -- (void)setUp { - self.URLSession = [NSURLSession - sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; - FIROptions *options = [self firebaseTestOptions]; - FIRHeartbeatLogger *heartbeatLogger = - [[FIRHeartbeatLogger alloc] initWithAppID:options.googleAppID]; - - self.APIService = [[FIRAppCheckAPIService alloc] initWithURLSession:self.URLSession - APIKey:options.APIKey - appID:options.googleAppID - heartbeatLogger:heartbeatLogger]; - self.deviceCheckAPIService = - [[FIRDeviceCheckAPIService alloc] initWithAPIService:self.APIService - projectID:options.projectID - appID:options.googleAppID]; -} - -- (void)tearDown { - self.deviceCheckAPIService = nil; - self.APIService = nil; - self.URLSession = nil; -} - -// TODO: Re-enable the test once secret with "GoogleService-Info.plist" is configured. -- (void)temporaryDisabled_testAppCheckTokenSuccess { - __auto_type appCheckPromise = - [self.deviceCheckAPIService appCheckTokenWithDeviceToken:[NSData data]]; - - XCTAssert(FBLWaitForPromisesWithTimeout(20)); - - XCTAssertNil(appCheckPromise.error); - XCTAssertNotNil(appCheckPromise.value); - - XCTAssertNotNil(appCheckPromise.value.token); - XCTAssertNotNil(appCheckPromise.value.expirationDate); -} - -#pragma mark - Helpers - -- (FIROptions *)firebaseTestOptions { - NSString *plistPath = - [[NSBundle bundleForClass:[self class]] pathForResource:@"GoogleService-Info" - ofType:@"plist"]; - FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:plistPath]; - return options; -} - -@end - -#endif // !TARGET_OS_MACCATALYST && !TARGET_OS_OSX - -#endif // !SWIFT_PACKAGE From ace85bbbaeb2e2b3829cb0ef253b80ff3dfd905a Mon Sep 17 00:00:00 2001 From: Andrew Heard Date: Tue, 31 Oct 2023 17:54:43 -0400 Subject: [PATCH 2/2] Move test fixture JSON responses to subdir --- FirebaseAppCheck.podspec | 3 +- .../Tests/Integration/AppCheckE2ETests.swift | 170 +++++++++--------- .../AppAttestAttestationResponseSuccess.json | 0 .../AppAttestResponseMissingChallenge.json | 0 .../Fixture/AppAttestResponseSuccess.json | 0 .../DeviceCheckResponseMissingTimeToLive.json | 0 .../DeviceCheckResponseMissingToken.json | 0 .../FACTokenExchangeResponseSuccess.json | 0 Package.swift | 8 +- 9 files changed, 87 insertions(+), 94 deletions(-) rename FirebaseAppCheck/Tests/{ => Unit}/Fixture/AppAttestAttestationResponseSuccess.json (100%) rename FirebaseAppCheck/Tests/{ => Unit}/Fixture/AppAttestResponseMissingChallenge.json (100%) rename FirebaseAppCheck/Tests/{ => Unit}/Fixture/AppAttestResponseSuccess.json (100%) rename FirebaseAppCheck/Tests/{ => Unit}/Fixture/DeviceCheckResponseMissingTimeToLive.json (100%) rename FirebaseAppCheck/Tests/{ => Unit}/Fixture/DeviceCheckResponseMissingToken.json (100%) rename FirebaseAppCheck/Tests/{ => Unit}/Fixture/FACTokenExchangeResponseSuccess.json (100%) diff --git a/FirebaseAppCheck.podspec b/FirebaseAppCheck.podspec index 0e7e5a11816..650380aab24 100644 --- a/FirebaseAppCheck.podspec +++ b/FirebaseAppCheck.podspec @@ -62,14 +62,13 @@ Pod::Spec.new do |s| } unit_tests.source_files = [ base_dir + 'Tests/Unit/**/*.[mh]', - base_dir + 'Tests/Utils/**/*.[mh]', 'SharedTestUtilities/AppCheckFake/*', 'SharedTestUtilities/AppCheckBackoffWrapperFake/*', 'SharedTestUtilities/Date/*', 'SharedTestUtilities/URLSession/*', ] - unit_tests.resources = base_dir + 'Tests/Fixture/**/*' + unit_tests.resources = base_dir + 'Tests/Unit/Fixture/**/*' unit_tests.dependency 'OCMock' unit_tests.requires_app_host = true end diff --git a/FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift b/FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift index 216d5dfc666..18b9d3dddc4 100644 --- a/FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift +++ b/FirebaseAppCheck/Tests/Integration/AppCheckE2ETests.swift @@ -16,113 +16,107 @@ import FirebaseAppCheck import FirebaseCore import XCTest -// Tests that use the Keychain require a host app and Swift Package Manager does not support adding -// a host app to test targets. -#if !SWIFT_PACKAGE - - final class AppCheckE2ETests: XCTestCase { - let appName = "test_app_name" - var app: FirebaseApp! - - override func setUp() { - AppCheck.setAppCheckProviderFactory(TestAppCheckProviderFactory()) - let options = FirebaseOptions( - googleAppID: "1:123456789:ios:abc123", - gcmSenderID: "123456789" - ) - options.projectID = "test_project_id" - options.apiKey = "test_api_key" - FirebaseApp.configure(name: appName, options: options) - - app = FirebaseApp.app(name: appName) - } +final class AppCheckE2ETests: XCTestCase { + let appName = "test_app_name" + var app: FirebaseApp! + + override func setUp() { + AppCheck.setAppCheckProviderFactory(TestAppCheckProviderFactory()) + let options = FirebaseOptions( + googleAppID: "1:123456789:ios:abc123", + gcmSenderID: "123456789" + ) + options.projectID = "test_project_id" + options.apiKey = "test_api_key" + FirebaseApp.configure(name: appName, options: options) + + app = FirebaseApp.app(name: appName) + } - override func tearDown() { - let semaphore = DispatchSemaphore(value: 0) - app.delete { _ in - semaphore.signal() - } - semaphore.wait() + override func tearDown() { + let semaphore = DispatchSemaphore(value: 0) + app.delete { _ in + semaphore.signal() } + semaphore.wait() + } - func testInitAppCheck() throws { - let appCheck = AppCheck.appCheck(app: app) + func testInitAppCheck() throws { + let appCheck = AppCheck.appCheck(app: app) - XCTAssertNotNil(appCheck) - } + XCTAssertNotNil(appCheck) + } - func testInitAppCheckDebugProvider() throws { - let debugProvider = AppCheckDebugProvider(app: app) + func testInitAppCheckDebugProvider() throws { + let debugProvider = AppCheckDebugProvider(app: app) - XCTAssertNotNil(debugProvider) - } + XCTAssertNotNil(debugProvider) + } - func testInitAppCheckDebugProviderFactory() throws { - let debugProvider = AppCheckDebugProviderFactory().createProvider(with: app) + func testInitAppCheckDebugProviderFactory() throws { + let debugProvider = AppCheckDebugProviderFactory().createProvider(with: app) - XCTAssertNotNil(debugProvider) - } + XCTAssertNotNil(debugProvider) + } - @available(iOS 11.0, macOS 10.15, macCatalyst 13.0, tvOS 11.0, watchOS 9.0, *) - func testInitDeviceCheckProvider() throws { - let deviceCheckProvider = DeviceCheckProvider(app: app) + @available(iOS 11.0, macOS 10.15, macCatalyst 13.0, tvOS 11.0, watchOS 9.0, *) + func testInitDeviceCheckProvider() throws { + let deviceCheckProvider = DeviceCheckProvider(app: app) - XCTAssertNotNil(deviceCheckProvider) - } + XCTAssertNotNil(deviceCheckProvider) + } - @available(iOS 11.0, macOS 10.15, macCatalyst 13.0, tvOS 11.0, watchOS 9.0, *) - func testDeviceCheckProviderFactoryCreate() throws { - let deviceCheckProvider = DeviceCheckProviderFactory().createProvider(with: app) + @available(iOS 11.0, macOS 10.15, macCatalyst 13.0, tvOS 11.0, watchOS 9.0, *) + func testDeviceCheckProviderFactoryCreate() throws { + let deviceCheckProvider = DeviceCheckProviderFactory().createProvider(with: app) - XCTAssertNotNil(deviceCheckProvider) - } + XCTAssertNotNil(deviceCheckProvider) + } - @available(iOS 14.0, macOS 11.3, macCatalyst 14.5, tvOS 15.0, watchOS 9.0, *) - func testInitAppAttestProvider() throws { - let appAttestProvider = AppAttestProvider(app: app) + @available(iOS 14.0, macOS 11.3, macCatalyst 14.5, tvOS 15.0, watchOS 9.0, *) + func testInitAppAttestProvider() throws { + let appAttestProvider = AppAttestProvider(app: app) - XCTAssertNotNil(appAttestProvider) - } + XCTAssertNotNil(appAttestProvider) + } - // The following test is disabled on macOS since `token(forcingRefresh:handler:)` requires a - // provisioning profile to access the keychain to cache tokens. - // See go/firebase-macos-keychain-popups for more details. - #if !os(macOS) && !targetEnvironment(macCatalyst) - func testGetToken() throws { - guard let appCheck = AppCheck.appCheck(app: app) else { - XCTFail("AppCheck instance is nil.") - return - } - - let expectation = XCTestExpectation() - appCheck.token(forcingRefresh: true) { token, error in - XCTAssertNil(error) - XCTAssertNotNil(token) - XCTAssertEqual(token?.token, TestAppCheckProvider.tokenValue) - expectation.fulfill() - } - - wait(for: [expectation], timeout: 0.5) + // The following test is disabled on macOS since `token(forcingRefresh:handler:)` requires a + // provisioning profile to access the keychain to cache tokens. + // See go/firebase-macos-keychain-popups for more details. + #if !os(macOS) && !targetEnvironment(macCatalyst) + func testGetToken() throws { + guard let appCheck = AppCheck.appCheck(app: app) else { + XCTFail("AppCheck instance is nil.") + return } - #endif // !os(macOS) && !targetEnvironment(macCatalyst) - } - class TestAppCheckProvider: NSObject, AppCheckProvider { - static let tokenValue = "TestToken" + let expectation = XCTestExpectation() + appCheck.token(forcingRefresh: true) { token, error in + XCTAssertNil(error) + XCTAssertNotNil(token) + XCTAssertEqual(token?.token, TestAppCheckProvider.tokenValue) + expectation.fulfill() + } - func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) { - let token = AppCheckToken( - token: TestAppCheckProvider.tokenValue, - expirationDate: Date.distantFuture - ) - handler(token, nil) + wait(for: [expectation], timeout: 0.5) } + #endif // !os(macOS) && !targetEnvironment(macCatalyst) +} + +class TestAppCheckProvider: NSObject, AppCheckProvider { + static let tokenValue = "TestToken" + + func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) { + let token = AppCheckToken( + token: TestAppCheckProvider.tokenValue, + expirationDate: Date.distantFuture + ) + handler(token, nil) } +} - class TestAppCheckProviderFactory: NSObject, AppCheckProviderFactory { - func createProvider(with app: FirebaseApp) -> AppCheckProvider? { - return TestAppCheckProvider() - } +class TestAppCheckProviderFactory: NSObject, AppCheckProviderFactory { + func createProvider(with app: FirebaseApp) -> AppCheckProvider? { + return TestAppCheckProvider() } - -#endif // !SWIFT_PACKAGE +} diff --git a/FirebaseAppCheck/Tests/Fixture/AppAttestAttestationResponseSuccess.json b/FirebaseAppCheck/Tests/Unit/Fixture/AppAttestAttestationResponseSuccess.json similarity index 100% rename from FirebaseAppCheck/Tests/Fixture/AppAttestAttestationResponseSuccess.json rename to FirebaseAppCheck/Tests/Unit/Fixture/AppAttestAttestationResponseSuccess.json diff --git a/FirebaseAppCheck/Tests/Fixture/AppAttestResponseMissingChallenge.json b/FirebaseAppCheck/Tests/Unit/Fixture/AppAttestResponseMissingChallenge.json similarity index 100% rename from FirebaseAppCheck/Tests/Fixture/AppAttestResponseMissingChallenge.json rename to FirebaseAppCheck/Tests/Unit/Fixture/AppAttestResponseMissingChallenge.json diff --git a/FirebaseAppCheck/Tests/Fixture/AppAttestResponseSuccess.json b/FirebaseAppCheck/Tests/Unit/Fixture/AppAttestResponseSuccess.json similarity index 100% rename from FirebaseAppCheck/Tests/Fixture/AppAttestResponseSuccess.json rename to FirebaseAppCheck/Tests/Unit/Fixture/AppAttestResponseSuccess.json diff --git a/FirebaseAppCheck/Tests/Fixture/DeviceCheckResponseMissingTimeToLive.json b/FirebaseAppCheck/Tests/Unit/Fixture/DeviceCheckResponseMissingTimeToLive.json similarity index 100% rename from FirebaseAppCheck/Tests/Fixture/DeviceCheckResponseMissingTimeToLive.json rename to FirebaseAppCheck/Tests/Unit/Fixture/DeviceCheckResponseMissingTimeToLive.json diff --git a/FirebaseAppCheck/Tests/Fixture/DeviceCheckResponseMissingToken.json b/FirebaseAppCheck/Tests/Unit/Fixture/DeviceCheckResponseMissingToken.json similarity index 100% rename from FirebaseAppCheck/Tests/Fixture/DeviceCheckResponseMissingToken.json rename to FirebaseAppCheck/Tests/Unit/Fixture/DeviceCheckResponseMissingToken.json diff --git a/FirebaseAppCheck/Tests/Fixture/FACTokenExchangeResponseSuccess.json b/FirebaseAppCheck/Tests/Unit/Fixture/FACTokenExchangeResponseSuccess.json similarity index 100% rename from FirebaseAppCheck/Tests/Fixture/FACTokenExchangeResponseSuccess.json rename to FirebaseAppCheck/Tests/Unit/Fixture/FACTokenExchangeResponseSuccess.json diff --git a/Package.swift b/Package.swift index 999d06d39c6..b3534b20bdf 100644 --- a/Package.swift +++ b/Package.swift @@ -1256,17 +1256,17 @@ let package = Package( "SharedTestUtilities", .product(name: "OCMock", package: "ocmock"), ], - path: "FirebaseAppCheck/Tests", + path: "FirebaseAppCheck/Tests/Unit", exclude: [ // Swift tests are in the target `FirebaseAppCheckUnitSwift` since mixed language targets - // are not supported (as of Xcode 14.3). - "Unit/Swift", + // are not supported (as of Xcode 15.0). + "Swift", ], resources: [ .process("Fixture"), ], cSettings: [ - .headerSearchPath("../.."), + .headerSearchPath("../../.."), ] ), .testTarget(