From 2e7ff6a892f868c46665febb8708e5b4708c347b Mon Sep 17 00:00:00 2001 From: Andrew Heard Date: Tue, 5 Mar 2024 02:32:26 +0000 Subject: [PATCH 01/25] [Release] Update versions for Release 10.23.0 (#12467) --- Firebase.podspec | 48 +++++++++---------- FirebaseABTesting.podspec | 2 +- FirebaseAnalytics.podspec | 6 +-- FirebaseAnalyticsOnDeviceConversion.podspec | 4 +- FirebaseAppCheck.podspec | 2 +- FirebaseAppCheckInterop.podspec | 2 +- FirebaseAppDistribution.podspec | 2 +- FirebaseAuth.podspec | 2 +- FirebaseAuthInterop.podspec | 2 +- FirebaseCore.podspec | 2 +- FirebaseCoreExtension.podspec | 2 +- FirebaseCoreInternal.podspec | 2 +- FirebaseCrashlytics.podspec | 2 +- FirebaseDatabase.podspec | 2 +- FirebaseDynamicLinks.podspec | 2 +- FirebaseFirestore.podspec | 2 +- FirebaseFirestoreInternal.podspec | 2 +- FirebaseFunctions.podspec | 2 +- FirebaseInAppMessaging.podspec | 2 +- FirebaseInstallations.podspec | 2 +- FirebaseMLModelDownloader.podspec | 2 +- FirebaseMessaging.podspec | 2 +- FirebaseMessagingInterop.podspec | 2 +- FirebasePerformance.podspec | 2 +- FirebaseRemoteConfig.podspec | 2 +- FirebaseSessions.podspec | 2 +- FirebaseSharedSwift.podspec | 2 +- FirebaseStorage.podspec | 2 +- GoogleAppMeasurement.podspec | 4 +- ...leAppMeasurementOnDeviceConversion.podspec | 2 +- Package.swift | 2 +- .../FirebaseManifest/FirebaseManifest.swift | 2 +- 32 files changed, 59 insertions(+), 59 deletions(-) diff --git a/Firebase.podspec b/Firebase.podspec index c7e3709a691..a56eeced656 100644 --- a/Firebase.podspec +++ b/Firebase.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Firebase' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase' s.description = <<-DESC @@ -36,14 +36,14 @@ Simplify your app development, grow your user base, and monetize more effectivel ss.ios.deployment_target = '10.0' ss.osx.deployment_target = '10.13' ss.tvos.deployment_target = '12.0' - ss.ios.dependency 'FirebaseAnalytics', '~> 10.22.0' - ss.osx.dependency 'FirebaseAnalytics', '~> 10.22.0' - ss.tvos.dependency 'FirebaseAnalytics', '~> 10.22.0' + ss.ios.dependency 'FirebaseAnalytics', '~> 10.23.0' + ss.osx.dependency 'FirebaseAnalytics', '~> 10.23.0' + ss.tvos.dependency 'FirebaseAnalytics', '~> 10.23.0' ss.dependency 'Firebase/CoreOnly' end s.subspec 'CoreOnly' do |ss| - ss.dependency 'FirebaseCore', '10.22.0' + ss.dependency 'FirebaseCore', '10.23.0' ss.source_files = 'CoreOnly/Sources/Firebase.h' ss.preserve_paths = 'CoreOnly/Sources/module.modulemap' if ENV['FIREBASE_POD_REPO_FOR_DEV_POD'] then @@ -79,13 +79,13 @@ Simplify your app development, grow your user base, and monetize more effectivel ss.ios.deployment_target = '10.0' ss.osx.deployment_target = '10.13' ss.tvos.deployment_target = '12.0' - ss.dependency 'FirebaseAnalytics/WithoutAdIdSupport', '~> 10.22.0' + ss.dependency 'FirebaseAnalytics/WithoutAdIdSupport', '~> 10.23.0' ss.dependency 'Firebase/CoreOnly' end s.subspec 'ABTesting' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseABTesting', '~> 10.22.0' + ss.dependency 'FirebaseABTesting', '~> 10.23.0' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -95,13 +95,13 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'AppDistribution' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.ios.dependency 'FirebaseAppDistribution', '~> 10.22.0-beta' + ss.ios.dependency 'FirebaseAppDistribution', '~> 10.23.0-beta' ss.ios.deployment_target = '11.0' end s.subspec 'AppCheck' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseAppCheck', '~> 10.22.0' + ss.dependency 'FirebaseAppCheck', '~> 10.23.0' ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' ss.tvos.deployment_target = '12.0' @@ -110,7 +110,7 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'Auth' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseAuth', '~> 10.22.0' + ss.dependency 'FirebaseAuth', '~> 10.23.0' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -120,7 +120,7 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'Crashlytics' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseCrashlytics', '~> 10.22.0' + ss.dependency 'FirebaseCrashlytics', '~> 10.23.0' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -130,7 +130,7 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'Database' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseDatabase', '~> 10.22.0' + ss.dependency 'FirebaseDatabase', '~> 10.23.0' # Standard platforms PLUS watchOS 7. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -140,13 +140,13 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'DynamicLinks' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.ios.dependency 'FirebaseDynamicLinks', '~> 10.22.0' + ss.ios.dependency 'FirebaseDynamicLinks', '~> 10.23.0' ss.ios.deployment_target = '11.0' end s.subspec 'Firestore' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseFirestore', '~> 10.22.0' + ss.dependency 'FirebaseFirestore', '~> 10.23.0' ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' ss.tvos.deployment_target = '12.0' @@ -154,7 +154,7 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'Functions' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseFunctions', '~> 10.22.0' + ss.dependency 'FirebaseFunctions', '~> 10.23.0' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -164,20 +164,20 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'InAppMessaging' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.ios.dependency 'FirebaseInAppMessaging', '~> 10.22.0-beta' - ss.tvos.dependency 'FirebaseInAppMessaging', '~> 10.22.0-beta' + ss.ios.dependency 'FirebaseInAppMessaging', '~> 10.23.0-beta' + ss.tvos.dependency 'FirebaseInAppMessaging', '~> 10.23.0-beta' ss.ios.deployment_target = '11.0' ss.tvos.deployment_target = '12.0' end s.subspec 'Installations' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseInstallations', '~> 10.22.0' + ss.dependency 'FirebaseInstallations', '~> 10.23.0' end s.subspec 'Messaging' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseMessaging', '~> 10.22.0' + ss.dependency 'FirebaseMessaging', '~> 10.23.0' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -187,7 +187,7 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'MLModelDownloader' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseMLModelDownloader', '~> 10.22.0-beta' + ss.dependency 'FirebaseMLModelDownloader', '~> 10.23.0-beta' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -197,15 +197,15 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'Performance' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.ios.dependency 'FirebasePerformance', '~> 10.22.0' - ss.tvos.dependency 'FirebasePerformance', '~> 10.22.0' + ss.ios.dependency 'FirebasePerformance', '~> 10.23.0' + ss.tvos.dependency 'FirebasePerformance', '~> 10.23.0' ss.ios.deployment_target = '11.0' ss.tvos.deployment_target = '12.0' end s.subspec 'RemoteConfig' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseRemoteConfig', '~> 10.22.0' + ss.dependency 'FirebaseRemoteConfig', '~> 10.23.0' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' @@ -215,7 +215,7 @@ Simplify your app development, grow your user base, and monetize more effectivel s.subspec 'Storage' do |ss| ss.dependency 'Firebase/CoreOnly' - ss.dependency 'FirebaseStorage', '~> 10.22.0' + ss.dependency 'FirebaseStorage', '~> 10.23.0' # Standard platforms PLUS watchOS. ss.ios.deployment_target = '11.0' ss.osx.deployment_target = '10.13' diff --git a/FirebaseABTesting.podspec b/FirebaseABTesting.podspec index 60e3584c1f0..dbd855d6486 100644 --- a/FirebaseABTesting.podspec +++ b/FirebaseABTesting.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseABTesting' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase ABTesting' s.description = <<-DESC diff --git a/FirebaseAnalytics.podspec b/FirebaseAnalytics.podspec index 6b4b7412480..0259cc52c58 100644 --- a/FirebaseAnalytics.podspec +++ b/FirebaseAnalytics.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAnalytics' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Analytics for iOS' s.description = <<-DESC @@ -37,12 +37,12 @@ Pod::Spec.new do |s| s.default_subspecs = 'AdIdSupport' s.subspec 'AdIdSupport' do |ss| - ss.dependency 'GoogleAppMeasurement', '10.22.0' + ss.dependency 'GoogleAppMeasurement', '10.23.0' ss.vendored_frameworks = 'Frameworks/FirebaseAnalytics.xcframework' end s.subspec 'WithoutAdIdSupport' do |ss| - ss.dependency 'GoogleAppMeasurement/WithoutAdIdSupport', '10.22.0' + ss.dependency 'GoogleAppMeasurement/WithoutAdIdSupport', '10.23.0' ss.vendored_frameworks = 'Frameworks/FirebaseAnalytics.xcframework' end diff --git a/FirebaseAnalyticsOnDeviceConversion.podspec b/FirebaseAnalyticsOnDeviceConversion.podspec index 3dddf28a777..e4ec770b8e5 100644 --- a/FirebaseAnalyticsOnDeviceConversion.podspec +++ b/FirebaseAnalyticsOnDeviceConversion.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAnalyticsOnDeviceConversion' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'On device conversion measurement plugin for FirebaseAnalytics. Not intended for direct use.' s.description = <<-DESC @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.cocoapods_version = '>= 1.12.0' - s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.22.0' + s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.23.0' s.static_framework = true diff --git a/FirebaseAppCheck.podspec b/FirebaseAppCheck.podspec index 232d4b29318..da7607cd677 100644 --- a/FirebaseAppCheck.podspec +++ b/FirebaseAppCheck.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAppCheck' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase App Check SDK.' s.description = <<-DESC diff --git a/FirebaseAppCheckInterop.podspec b/FirebaseAppCheckInterop.podspec index f1a238848b6..bc5111f6ae8 100644 --- a/FirebaseAppCheckInterop.podspec +++ b/FirebaseAppCheckInterop.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAppCheckInterop' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Interfaces that allow other Firebase SDKs to use AppCheck functionality.' s.description = <<-DESC diff --git a/FirebaseAppDistribution.podspec b/FirebaseAppDistribution.podspec index ccf859c21bb..11bbbacd781 100644 --- a/FirebaseAppDistribution.podspec +++ b/FirebaseAppDistribution.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAppDistribution' - s.version = '10.22.0-beta' + s.version = '10.23.0-beta' s.summary = 'App Distribution for Firebase iOS SDK.' s.description = <<-DESC diff --git a/FirebaseAuth.podspec b/FirebaseAuth.podspec index 5333ffc3b4b..73f6666d777 100644 --- a/FirebaseAuth.podspec +++ b/FirebaseAuth.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAuth' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Apple platform client for Firebase Authentication' s.description = <<-DESC diff --git a/FirebaseAuthInterop.podspec b/FirebaseAuthInterop.podspec index 65d84553e7b..87990ae36dc 100644 --- a/FirebaseAuthInterop.podspec +++ b/FirebaseAuthInterop.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAuthInterop' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Interfaces that allow other Firebase SDKs to use Auth functionality.' s.description = <<-DESC diff --git a/FirebaseCore.podspec b/FirebaseCore.podspec index 5320d32e4ef..4957df4fa6e 100644 --- a/FirebaseCore.podspec +++ b/FirebaseCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseCore' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Core' s.description = <<-DESC diff --git a/FirebaseCoreExtension.podspec b/FirebaseCoreExtension.podspec index 9f8aff68ce6..5c2e7e8a4d0 100644 --- a/FirebaseCoreExtension.podspec +++ b/FirebaseCoreExtension.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseCoreExtension' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Extended FirebaseCore APIs for Firebase product SDKs' s.description = <<-DESC diff --git a/FirebaseCoreInternal.podspec b/FirebaseCoreInternal.podspec index 330587c824d..1990db42d28 100644 --- a/FirebaseCoreInternal.podspec +++ b/FirebaseCoreInternal.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseCoreInternal' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'APIs for internal FirebaseCore usage.' s.description = <<-DESC diff --git a/FirebaseCrashlytics.podspec b/FirebaseCrashlytics.podspec index e4b5cebea5c..108645728e4 100644 --- a/FirebaseCrashlytics.podspec +++ b/FirebaseCrashlytics.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseCrashlytics' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Best and lightest-weight crash reporting for mobile, desktop and tvOS.' s.description = 'Firebase Crashlytics helps you track, prioritize, and fix stability issues that erode app quality.' s.homepage = 'https://firebase.google.com/' diff --git a/FirebaseDatabase.podspec b/FirebaseDatabase.podspec index ab9551fac82..3aa94748bda 100644 --- a/FirebaseDatabase.podspec +++ b/FirebaseDatabase.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseDatabase' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Realtime Database' s.description = <<-DESC diff --git a/FirebaseDynamicLinks.podspec b/FirebaseDynamicLinks.podspec index d0c2cf282b8..aaa43aec721 100644 --- a/FirebaseDynamicLinks.podspec +++ b/FirebaseDynamicLinks.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseDynamicLinks' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Dynamic Links' s.description = <<-DESC diff --git a/FirebaseFirestore.podspec b/FirebaseFirestore.podspec index 53d0f8a0877..b7ea45b827c 100644 --- a/FirebaseFirestore.podspec +++ b/FirebaseFirestore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseFirestore' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Google Cloud Firestore' s.description = <<-DESC Google Cloud Firestore is a NoSQL document database built for automatic scaling, high performance, and ease of application development. diff --git a/FirebaseFirestoreInternal.podspec b/FirebaseFirestoreInternal.podspec index 139ef417636..f6f3235d733 100644 --- a/FirebaseFirestoreInternal.podspec +++ b/FirebaseFirestoreInternal.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseFirestoreInternal' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Google Cloud Firestore' s.description = <<-DESC diff --git a/FirebaseFunctions.podspec b/FirebaseFunctions.podspec index 75f42c569ff..9c74c320285 100644 --- a/FirebaseFunctions.podspec +++ b/FirebaseFunctions.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseFunctions' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Cloud Functions for Firebase' s.description = <<-DESC diff --git a/FirebaseInAppMessaging.podspec b/FirebaseInAppMessaging.podspec index 5f8e245690e..f0122b8ec7c 100644 --- a/FirebaseInAppMessaging.podspec +++ b/FirebaseInAppMessaging.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseInAppMessaging' - s.version = '10.22.0-beta' + s.version = '10.23.0-beta' s.summary = 'Firebase In-App Messaging for iOS' s.description = <<-DESC diff --git a/FirebaseInstallations.podspec b/FirebaseInstallations.podspec index 815ac860204..e8cb5c352b8 100644 --- a/FirebaseInstallations.podspec +++ b/FirebaseInstallations.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseInstallations' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Installations' s.description = <<-DESC diff --git a/FirebaseMLModelDownloader.podspec b/FirebaseMLModelDownloader.podspec index 317b3ddb3b6..7d17f6a05ac 100644 --- a/FirebaseMLModelDownloader.podspec +++ b/FirebaseMLModelDownloader.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseMLModelDownloader' - s.version = '10.22.0-beta' + s.version = '10.23.0-beta' s.summary = 'Firebase ML Model Downloader' s.description = <<-DESC diff --git a/FirebaseMessaging.podspec b/FirebaseMessaging.podspec index 0cee992e8b3..15195fc96f1 100644 --- a/FirebaseMessaging.podspec +++ b/FirebaseMessaging.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseMessaging' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Messaging' s.description = <<-DESC diff --git a/FirebaseMessagingInterop.podspec b/FirebaseMessagingInterop.podspec index f93f2b9dec7..6e8989948cd 100644 --- a/FirebaseMessagingInterop.podspec +++ b/FirebaseMessagingInterop.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseMessagingInterop' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Interfaces that allow other Firebase SDKs to use Messaging functionality.' s.description = <<-DESC diff --git a/FirebasePerformance.podspec b/FirebasePerformance.podspec index 971eb5f2c34..c8d89bb17f5 100644 --- a/FirebasePerformance.podspec +++ b/FirebasePerformance.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebasePerformance' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Performance' s.description = <<-DESC diff --git a/FirebaseRemoteConfig.podspec b/FirebaseRemoteConfig.podspec index 1efbc8ff746..efef50fef50 100644 --- a/FirebaseRemoteConfig.podspec +++ b/FirebaseRemoteConfig.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseRemoteConfig' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Remote Config' s.description = <<-DESC diff --git a/FirebaseSessions.podspec b/FirebaseSessions.podspec index c44ee45d889..9ff30a18019 100644 --- a/FirebaseSessions.podspec +++ b/FirebaseSessions.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseSessions' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Sessions' s.description = <<-DESC diff --git a/FirebaseSharedSwift.podspec b/FirebaseSharedSwift.podspec index 9412356fc06..c451e29e1d7 100644 --- a/FirebaseSharedSwift.podspec +++ b/FirebaseSharedSwift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseSharedSwift' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Shared Swift Extensions for Firebase' s.description = <<-DESC diff --git a/FirebaseStorage.podspec b/FirebaseStorage.podspec index a9ea3bd4127..51fbc91dd24 100644 --- a/FirebaseStorage.podspec +++ b/FirebaseStorage.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseStorage' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Firebase Storage' s.description = <<-DESC diff --git a/GoogleAppMeasurement.podspec b/GoogleAppMeasurement.podspec index df2097af8c9..2167fa94cb5 100644 --- a/GoogleAppMeasurement.podspec +++ b/GoogleAppMeasurement.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'GoogleAppMeasurement' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = 'Shared measurement methods for Google libraries. Not intended for direct use.' s.description = <<-DESC @@ -37,7 +37,7 @@ Pod::Spec.new do |s| s.default_subspecs = 'AdIdSupport' s.subspec 'AdIdSupport' do |ss| - ss.dependency 'GoogleAppMeasurement/WithoutAdIdSupport', '10.22.0' + ss.dependency 'GoogleAppMeasurement/WithoutAdIdSupport', '10.23.0' ss.vendored_frameworks = 'Frameworks/GoogleAppMeasurementIdentitySupport.xcframework' end diff --git a/GoogleAppMeasurementOnDeviceConversion.podspec b/GoogleAppMeasurementOnDeviceConversion.podspec index bd77bd0edde..f56e61e7aca 100644 --- a/GoogleAppMeasurementOnDeviceConversion.podspec +++ b/GoogleAppMeasurementOnDeviceConversion.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'GoogleAppMeasurementOnDeviceConversion' - s.version = '10.22.0' + s.version = '10.23.0' s.summary = <<-SUMMARY On device conversion measurement plugin for Google App Measurement. Not intended for direct use. diff --git a/Package.swift b/Package.swift index 05ca701bd7f..c95d29bfd51 100644 --- a/Package.swift +++ b/Package.swift @@ -19,7 +19,7 @@ import class Foundation.ProcessInfo import PackageDescription -let firebaseVersion = "10.22.0" +let firebaseVersion = "10.23.0" let package = Package( name: "Firebase", diff --git a/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift b/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift index 093aacae131..5bd4f3dd5e2 100755 --- a/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift +++ b/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift @@ -21,7 +21,7 @@ import Foundation /// The version and releasing fields of the non-Firebase pods should be reviewed every release. /// The array should be ordered so that any pod's dependencies precede it in the list. public let shared = Manifest( - version: "10.22.0", + version: "10.23.0", pods: [ Pod("FirebaseSharedSwift"), Pod("FirebaseCoreInternal"), From 42fea7d4894b5a530324a459586dd817321ba755 Mon Sep 17 00:00:00 2001 From: tsunghung <78230356+tsunghung@users.noreply.github.com> Date: Tue, 5 Mar 2024 07:32:18 -0800 Subject: [PATCH 02/25] Add API tests for hashed email and phone number (#12469) --- FirebaseAnalyticsSwift/Tests/ObjCAPI/ObjCAPITests.m | 2 ++ FirebaseAnalyticsSwift/Tests/SwiftUnit/AnalyticsAPITests.swift | 2 ++ 2 files changed, 4 insertions(+) diff --git a/FirebaseAnalyticsSwift/Tests/ObjCAPI/ObjCAPITests.m b/FirebaseAnalyticsSwift/Tests/ObjCAPI/ObjCAPITests.m index a0be6eee954..6392674a812 100644 --- a/FirebaseAnalyticsSwift/Tests/ObjCAPI/ObjCAPITests.m +++ b/FirebaseAnalyticsSwift/Tests/ObjCAPI/ObjCAPITests.m @@ -60,6 +60,8 @@ - (void)consentTests:(NSURL *)url { - (void)onDeviceConversionTests:(NSURL *)url { [FIRAnalytics initiateOnDeviceConversionMeasurementWithEmailAddress:@"a@.a.com"]; [FIRAnalytics initiateOnDeviceConversionMeasurementWithPhoneNumber:@"+15555555555"]; + [FIRAnalytics initiateOnDeviceConversionMeasurementWithHashedEmailAddress:[NSData data]]; + [FIRAnalytics initiateOnDeviceConversionMeasurementWithHashedPhoneNumber:[NSData data]]; } - (NSArray *)eventNames { diff --git a/FirebaseAnalyticsSwift/Tests/SwiftUnit/AnalyticsAPITests.swift b/FirebaseAnalyticsSwift/Tests/SwiftUnit/AnalyticsAPITests.swift index 0b0542f8417..1d6a454f771 100644 --- a/FirebaseAnalyticsSwift/Tests/SwiftUnit/AnalyticsAPITests.swift +++ b/FirebaseAnalyticsSwift/Tests/SwiftUnit/AnalyticsAPITests.swift @@ -73,6 +73,8 @@ final class AnalyticsAPITests { Analytics.initiateOnDeviceConversionMeasurement(emailAddress: "test@gmail.com") Analytics.initiateOnDeviceConversionMeasurement(phoneNumber: "+15555555555") + Analytics.initiateOnDeviceConversionMeasurement(hashedEmailAddress: Data()) + Analytics.initiateOnDeviceConversionMeasurement(hashedPhoneNumber: Data()) // MARK: - EventNames From 28007226650d76ee191597a3c42e4d1fb08640b6 Mon Sep 17 00:00:00 2001 From: themiswang Date: Tue, 5 Mar 2024 13:41:41 -0500 Subject: [PATCH 03/25] Update upload-symbols to 13.7 (#12471) --- Crashlytics/CHANGELOG.md | 3 +++ Crashlytics/upload-symbols | Bin 742656 -> 759536 bytes 2 files changed, 3 insertions(+) diff --git a/Crashlytics/CHANGELOG.md b/Crashlytics/CHANGELOG.md index 4c449c579b5..2c06843fcea 100644 --- a/Crashlytics/CHANGELOG.md +++ b/Crashlytics/CHANGELOG.md @@ -1,3 +1,6 @@ +# Unreleased +- [added] Updated upload-symbols to 13.7 with VisionPro build phase support. (#12306) + # 10.22.0 - [fixed] Force validation or rotation of FIDs for FirebaseSessions. - [changed] Removed calls to statfs in the Crashlytics SDK to comply with Apple Privacy Manifests. This change removes support for collecting Disk Space Free in Crashlytics reports. diff --git a/Crashlytics/upload-symbols b/Crashlytics/upload-symbols index ace10d505b61e96229910f9c823dee9f435ed6f0..481428e6200d238fdd5e7950e98bb0caaf2d946a 100755 GIT binary patch literal 759536 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

QiGj*Q(c9877aeRWId3*s33sgXUt2kB@++Y;3Zn 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
NF^XEoiLXf5@w^Y&RKV%79ruO!hKKhV{ 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�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

7MRFLs z_!QQRNL?J~CGRU5+-~6QiViL`tGGy;?^WXx=FPu(((gA^-qHs5>X+nBqrasBiU`81 zXb92i7L3w>7u}gp`XxN7a?Kew5nb%c;k*Tmjmp>@EAS;U$T@h}449{&x{v7Xj%>8h zz3RL_%9vidf}sJw1_auTuCX_;5Rvn(bw2)rNf&`PM(%^SJIobbTIVCok{+YjHfwMh ze>uBfn{PLYkZ_H55d0lQ6%oIscv?_-Am+C^*lOe7in8?AMZAvN&J5|77ifLnC49&P z<^N)enj!QfV#`uCY)F`uxL|_s%JG4Y0%M3CAcd%~3U}~C`msi#3+3$?LPHMa-T-@{ zQa40ksN4;4Xn28w%NMSc9kMwEyqZU;Q7`DggIN^sCscvjrlJDRvBj^=Qyi!*? zf>NvzORhz>2n=t)Y_IWpN#WTPkzuCH%F#*j03!abgmVlCY=@`RUWiGZu@Dg1#`4R} z6*Jhl>mOl7(O{iL7shLU{!`FlBpQsBagOY>efomlvajEVp&8%eH&8g31fism>*mv1PRCQ7b zVeyEH$2%I76Z(dllsyEA3doG%N#X}T&lye8qpGGroMLF0|IBZj4I zhiSuFyT&^78>*ETf|_`c#93HP4u^q?MOxK;jYeIHpRfSg2}cOFfBhPJPspu_>tt|| zlQ}5uW0a!#@sq!dzQC{)L`sY~<0>-8xVDA$bh*@q>?W+@B!H?eZ)A!ENyOdY$e5?9 z#$q=#W!@tl$^i}@tSJ=u6F4zinnf43jeQox*m?28dVQF1017ZaGH8)vF;`U(w!_3h zY*fI0;2~l+%nywoq6?>F2S${7zZJUA%(9C?F3fd>Q868zNoIc<1W`C2!>+M+D6`fyqb)&}?$ zu{YAg(9~>^La=xflMxMEv4MQUB4++s^+5==x#_6DIG_uSfGD<(h-)oU=CSvSP+%#< zL6&8j6>~XY;N###!^&ucC(h0UT^1CYRCWVJCd;3FTfSy>E3 z+N!Zhw08-7(I@7S&`(bj4Mt)PSj1jTPy-(v&0^|vR&cQUBl@>jwTEe;kWvE?5oQ3WU^)GA0HsRuAnmSyc zH4aU09>NB@fBrqEKCxlbw{+tY5N@UbcS^R0MTA17ncRd=4Nm*9B!h}y@T-du$6+Hks?K>aU=w-_Pp+kH`o^}@(p4! zE_V|CydOa7T9s*Ib9^w3dVm4c&$3O7GBLPV7a2?}DH%{V?5pT`hA$C~ z6%?pS5?v2RrJ&5&gQCNvS@`4YqqtnUDVCiJ^6uvv@dp$KDi%j%MpY~oRjja*aTl^4 z1nYvRa7YkUo{zF(*D2IG-*Z*fJQg*3v1?{gSD~c{Mu9Ag+`!~pTA<&-3MO|eo!-P=Ei0)+rNlju+jJ%tGE+*>W-ja1RHFKVU#cGDhUhPn zOxOEXm9!&{CNFB9wrhlrP-@w*Ibs?#Fr8Y9&j}IV9jFgg}zB0wC z2MCop+=}gH7hA8=jWK0wbQ39+2^ZsTOtxjeaJCBmv~SqBspFx|AMX4}c6rw)iqqKXtxBs<$ z5(dJ3dVa5jE2VbztTZq9cO2KSc$N0{KW})Kb`r_DWy|YVth{B_t+(CYaL1kRTK(?3 z-m~Vt@4I{L```D058l)Gp*8E?mua}8KRt>lN?K~5AJVCVOv9ah+pCWvYB$wf~q_wErqKZzp zU{KTr5CZt5%6oknXpt|LC^DY*n~JmhY!1~)Z`jnjDbsKtR)bdPnJxvuwoa6Bb4X#K zf-}FZM#Qv;&X#Ftq>?zYS3ohrzSmkP%+IvKPdz);x*^j(wz;+a(Ty7iHg-I;d(&pj zooT~rgc%$Yd~8F^_^H&RK)}e@-aQ*P?)Y%W zo(=7-8#X;^NzMSKb{T!N?pbC%nqgck2Kvw-;46^(dsCkFRjt)6rSDh z)9M90ug_|A0nb%WYV|6fhv&6=1JC2%rB(g+Ija79v?}0v>ie`hf@jll)W=hu)ape% zFP=hqJYW1AFnP>T7oOLu8P5Yhsnr2IU-~K3!}HANwK|RGxt~EjJP)7M>Sa9Jzo6A+ zJdKdN)=e1h*{lMFAYt@bC;O}TPis!1A(H@?wzogY+Jda+|>I9zcU(@O=o(+Gk z)pc?WMb9_2x{l|CZvYQJfbsslR!w-W{Rgc&@jUV#M?FK|_c-b-p6WqI zy^QBMJTK!p+>ANGv(N(Aeh_fBqAZ^0@odL4x6x7kc)s)y-tlbS?5GN!$M8Ig=kSNo zF6HBS0nh1=IOmO3fo?ow) zztE)W&OD&hGY=}~bhAnxZBw^Azd_w{p+ntq?ZarVQ|WZ4x~08aImaGWs$q+AK@W< z!SlqYlzQz`%DH?{>DLdcWyfYza^EcaEvh=@DZS29iGDnv@qlwrIY%n$c6A8+c}VHp zA?2(-td@^Hh4!98drv9#(o@Rme@3Yno&o&Nsx@oAL#d`Cs;=|9RI>gk=Hz=IY`#Y= z8~$G4{(IFeXTD!0U;6=7x9^9Qp8jEV=cP|8edW{2x%3&8So5QRX`*G#G@to4vo>R$}pI7S4PbmHJPhjjnsr2YiDyRK4=IFFa z9Q`S!*8Md4_-W-NKd;o;&ton=uj*d-S>>Gnf~tGv1@!xZQu}^EIfs7{c=|=Ojpu33D)^zSOC;rGzS?;F;dhTm7ti@y&TFREn!AFAc`UsBGgFR8@UFRA2-S1{gJl)Cl`aP(z$ z*P5>=-TW0*cm9%cp8q3^@sHH<*Irdl)1RnhFf1#FL`0wcRYpDM@%ZL9Gu>K|H{I4J)|4J=C{?|%( z{Ebr2|BZ4^Usd|WtIE0fw@R)3I{4u4z)OFp5?B5XbAxC4P4MrVD)9=Qui@GG4W$Ra zfpLEWYsWW~Q~G<<|9hpn{{iX$0Q_B3b>07{^tpco4*v<`ysq?_>uCR3EGPGN;!_RLD{TwSS`UA;x?HLG;p z#dm2ny;|$jt9A0lcWbBrF39b>v_6mLoA1%i=`~toEpcAC8;jyvt*6&&_4-=v9Qc6N zr4MN5Y)Y%wQrg+qsFQCtYG-gAg3sG?d)yQ z>R5|**0gHf+^U^7Td|h3>BP}CtxvXT=W@GN9UHXn-=Ni*4ccki2-&_-*S+~+46;+# z9r=h>&va>hqD$9xc4K|%)^#WQFvdQ>(ytTE16sd4pw*h~TDNc4t5@&Pb@hY#-K&PQ zZW_{cZ+%?rwZppZ@=mQ9cIiaVF1ReL8VsA8@%3<9h-!?k0>vQwkS$jy=?>nUR;94d_bGokoKj>uVFG5jz zQLjAyOS=C0FX>y){<3yn`W3);4s>!(tCQz+{Y&Tc%C)}+diXWa>96bh%fEp+`c1uR z^>1PRe@m;u3tD&lj$U>2_fY3$tnvR5xcYsaIQ*Z0n?KM_&mV%WzoeJH@CxAhvexxq z0lvS2G5+7$dEt_-Klz`vQ~D#!|9{c94!)|LE3fM0OMeV<`4h~=pX&O`W$ldq8FZlk zs&8%jZ-DQ=X|?K#cFtYFT+;KaI&tNzTEFpCeOt$$>syciIdJ(Gz}tVv_t!w@U(@e- z@Vx$)nD@WZy7D&|!&T@Tf2*A}U&lOu9WZ?zbN_ef=S^LA`0sV{ z8uXCdHPF%j01W>FeDaS-|0kV1dL49p9qs=!@bS+m|Nnv}|EG2u-qOjAe*rE03zpJ< z)w=Yr;GcifI`?mwKjk>1+R-30m2w>Cvg7DC9Y>8OoW$!1C;4j9(VcbBdFq_Rbvz5p z9R18P$2qp#(JwBCZddQ<_Il^`>6MN?wh}tdN~iASTb<;^+nlfU{!ygU&Jlqx)0P zAyZD`LJDx)Ev-@x;5i<3Cf;;iU_PWD=>lQ`Y(ESuf{y={ZD z;`m1AmTQ}wL}v%|vWJ}HN$6$QHaoX;cS5h~bexwy;w0Yuh@%I)fTxc-x&VFbM7N{Q zKo7h2u;aV{J#4tg(Ul%2d8`*W>2>tQUMHE}1|6=?(X0EM<;i|W?dx}R3D44io`Yq&`opbBj-4$rZCPa2g>)&KQ}RO69YFf za1#SJF>n(DH!*M%12-{n69YFfa1#SJF>n(DH!*M%12-{n69YFfa1#SJF>n(DH!*M% z12-{n69YFfa1#SJF>n(DH!<+dW1wBCzJgd%3PiXj&kH~5@HYo(hnlzLn?6@NKP6=k z+5Avlc|`;$V)GD-%7G8xnc(O2XUy}MJkQGWqCDS_XZ??wa!v9al;^ZOkID0_JTJ=g z4SCj|l=|`BDayVb|e5w)}M2v}@_fA8$WqI22x(Yvbyr;j{lz%~yf9O2M%(#jpMmj z-rxF?DL;sqUP9$peoe+x7b=X`xb}UyLP7MQKNkLKy7S9d!5@d;>UnDV`6!-xq|fSc zw_K2MRKaEY@!_bV9}BmiUj?VlZ@`%ls=5?^#Fe-0SM!rCZ}Y3=y@kJ;4*l{no@1Xk zcp8-F8}hVMWZS8hJ65hWNWo(#Ogr_z6vca|s7i1RjgO&s6C*w!Lb6{QAXrhQFoCSM!e@pXDC`(_i354c7Nwrif5PbGSvh1b&GmBS|AuDjLk4Svzcg=u*<$@8Mf4cnfjhyVGX z4gRa=3*{J|qo1t}kFCGde1H0K?e+%+khuQsc&qEDf7HNp{$B+yX~)7-O|Q0n76Nwg zc&6k%aaHIqlqat|{&k24r>Q!2JSuOI#Q6>HmikrmW%Dmeeq4QpGkQ!4G4&6$Me~n! z(h*IZtCZ&{d7hRhviQ%%<>vV&&eKu(?dH?}*XDothfKcf=a?6p{}Ynm9FzZtlK-)o z{CEGbX@5gZ{tn51q)Oh}{y%rZ)W=br$RC^kt3P7$VJ=1f*!Wq+HZ@=A6X**J0!nqcz*leCHe1)Y5%j5Z|U0>v+(`4C;M{9}^;Yz%!Y z`>bjIPpT%s!vED%CSUGs@O!cOS0#V5pJQHZ{)c3pt6H9Y{5-Nm{-aCeKQ8$zV)}O_ zziPSn`#-ou{*z1OKP&mGWBRYLZg5G9pC6U_!cKlGHvc)vj~n0FCGvk+^5e$;;E$X6 zts)N}KP{3U2j4@IUqwEC{Z7eW=8w$0*zs*$qW@mWuaBw!u_fvcOMWcko-9OPe^{1I`89eO7i3A>lw+9!~b_kew=*&!6o|twB*O(|I`xopO^eN_rR{e zKaI(MOY-B^&rLsN>c{C{lafCa)BcN+AID$6EctQs_hreCe@9IH(~`d`CjaLpKaPLTNq(Gs_;tyT z!~Y*he%$);!k{C`RE~;&tA_kQNBkQhcdf5(fE>%A zm=(tVCdggaXSYJ`^6yT_UF)YGKXY*Z6nJ{JI`;SN!gT+;x9$ zC*-dC8-Iq}HNUOJ{wP=Z$02vk4}XE&m7gy|?z(?<_`@0>*Zq+bAa~7Qr$HWa^xq=L zUF}~Axodv95^`7nH9?;1sDC5mA8^Qj4tdxi&wNDV;~L-ZgWR?LSpd0ferbT*wSH}a z+%-OKgWQ#${gAuvpFIb;>-_No98g$oD}0X-EFg z`?0qFEQkE}kh}bU8*yz$2DvM~H$v_@|8(N|%N3t3DDN77TOoIqe<(@$ z?Mce_CMo|Y-h{ zkh}al9Q#LI#!vdsCLe!i;`bY_ z>w^zM?#jPYAa~Wj8TFs;XkYEm)xV_<`D2jhJLJ=LP9EO~`^79AOzXFH6;WsLG`L`KzS9~<L4vh*bhT~r$e53$X)BVOvqj1 z?@-8H-|wCTxodu10J+`2ynlQ#;d3hQ104p<`>Wz@po5?}&nw;n+7B8YR=gUt z2Q=_E#Y;guK}SIgUr>1;=rCyBi;A~_rtMWe2Q&&g0vdiv}B5cp%Dy24*PVda2Uv%}NLQl;-|e zY4J~#1|NeQl>Kc^Ut#MUmSR&8NJStOfm8%i5lBTK6@gR)QV~c+AQgdB1X2-5MIaS{ zR0L8HNJStOfm8%i5lBTK6@gR)QV~c+AQgdB1X2-5MIaS{R0L8HNJStOfm8%i5lBTK z6@gR)QV~c+AQgdB1X2-5MIaS{R0L8HNJStOfm8%i5lBTK6@gR)QV~c+AQgfCiwF#^ z(dQ8C0UZI|4;r{mSqviCTI@m9MCXm5ojrBC1?Za8qhY-^`KGEO`tuXJ3t3OcY_Xt?gLG`Uj57j z%?6zXnhQD?v=FoeGy+-++5);3v>kKdlL1AES~zLw4b&yv0T97Pseko^1h>brJ%IqqO{+VM89%xVt(d! zCHj-hesvQ4rLfvh24d(Puf@&wFrk ze_pZd_ivkA-?l%TME|3Bt`^JnY=3w52b1Uz!G0H>FVhdo`dl;u!Eh4&+!5{H;12aW z2h?SkIPDiE(Z3S*`yN;OgP^oCYVpKrKlh2L#gpau{3$++!j5Ha=B8nZJDQ+f?oGd2v(Kcj@stb1wP+HO}YQu^xMz6aRl3<#Y7t7sm;o zr$?NW&)*|&Q^yeM$!N03L z`u$<>^k*UXO3*KW-U3R0?g3A~9tHmlDC7Be@bn{XRO@G)4+j4c&?3+p&{d%92gc>| zz_Z>`d$U0of-VIu2WgWdKpj$v60cC%zOVj(c zyMey|%Jyu4{9B;E1pN~z=bu->Gfy}U5A&&g=ILqR*)GQaT;P{bj`-3~ws*TpadjJw@V&abaQk9i(U*Lrh68Hah`+3)o8S;X=0pv)8IPa(>29xnsW z`N|bX#^dk|^@rup0MGJlx7|L*i}SLp9=4BhIuG_&g5CsrFX)5lw`x$1Q&)e||DR9O zcFrnb}JMiy;{t)zW&_U2wLH#qdeO%uh37-D4{u6<-ee{p*oC7)Ia{>5z&{oiIf_8!O z{LOJn`&?JC-&r5mKkP@g`w`gtEhzn9Ke9dhA!obTZpyO{(s-NzdKzdRD9dr3dKU0` zp!Ruv8Sr0X{=WkJO3)iXZv)*3`kqYngZ?uPT%R^!-TiUsT?xwZ#`v&&JLI>4ZUX%Y z=(C_)ufAd7te@pMju|)RCH>*Lp5^TIp@e^-pl5?# z1iB1#Ip`YDn?dgeeE{^QpuA7S`$C6&KZSG zx!z&^@V?f?u+RC8*HOGqV}JTSsQ%h=_7Cqb9tAzFKUqKTD{{Q?z8CL1oQ85dFLT_? z2Oa^f25kmqJl27~6O`9=JRfjgdJytH(5FCo{r495%p7emuP@&OPyY`%N#*qSF!0BN z7J-(6o`m_J2|WF{2R!}!A$XpD9|8Xx(EkN}71Z}3_2Y0*_CNFGL-6|q$QhUO!B>LX zdB^iTuUi?vmC)yTW;OWRKrflC{`?N@WxSXN?C%=rwSaOQFb{cun)!Vc+CjgVmu&CN zu*380J>b6&%KHp|0MB(9?+-BlIDas&hM@m8=)oV>_A$?SKY{lxxb9-V+HvK)#<;K? z+rx7Fz9l19>pKSYGSHhq?**m3o!}W4_8a5NykPtO0sWIt(|XPX<@ts2E&$H;Gvl=c zIL9;RA@-Zyz6$8qfUW|)9+c-ho*#IAW0H=;w^nRgdwZJ>J*mIORH;-}kY8d%g52*kga* z37&b!@0B(Ke*%>DehZ%0WwbX0oOWx$)9+F68FREfhl73+v;wpN^g2+^1I)+&0saHf zCqS7`Pl2CyhSqZt=mt=pC!YlW2hcY`(>|)@P6NFWv=IJ(9X$J!_r2M#_dxzb(07{&B_GFN`na&v+338uaf1we{Gq^pE#@7zf6i-wO}G4&(6@c-BYz z@7C_GKB4Vm{Fo=S%l>7)5NCaC_d#c>9lL&(v)jk`ABA!!f$~0>UC$TZtM>1Po*g&V z%lK`99`lKDwC&O!{j=@3%0CAC1#{Ie_P1@Heoxt7>;qT|yS1R71^p`M2GILJ*&kWS$m4kMZI407f^`LJPu+GT$~2A=n!e+QoN;kttN?bvS|?}tMF7|>aur-1Uhjr%az4_tR~{lsx` z$U^n+{h+*Fn**Nna2PzVgBO9{k9w~Ie>>=A&;ii(*gx_b_@mF(dO3gI3%(06{?+MKxct6ALxHBaE@<&Pm~Yb&g(_M=^y8D-mkk3a`qe7?aUL_&wQmH zc7Aic&3@+iH-Z=kq-sOB-e2&KJGEmNIb>QhA+spRTkB^?G< zclk$go(Qbh@7Fhqz`Qe^`!wDQychV_MV5m@NbK{ETeSS(nN$0HN4t~^;D{NKKWHZ& zo9u7X4&yKP$(#d!XUdD?4es)HHuR!%|1*DSXEGn-Wyas>a&Z6Q!aFo>B{S7u?h_=Q zd#vKzH%PovUJP&A$9;qBzmE4Q&i#eNXCJRP_ahSDaDw8lIOV~=;oSOEh^Gmj(ZYrFaV>n~w<)&+|H5&PYkM{|L5Um5Z23swI)=ySZ~0Dl?y)384mcu1T! z<1vJ|?}y%>p%))_qsMyv*uSt|K=zA>({`d9n<5-M%+5WW^tKZxY$Np$vq&W8%=Au0v zz&{B4dBCHaPBLm{vdGf z%ccGhaPAYM{xERvKc)T%aPCK?{wQ$nPo;j^VvQ&Ft5QDzocmX)9|X>Qah#{Jfpgz1 z=cy2I-v6il9N_$3ka#X|es4%T5BNv$JtFZiaC;mU0uM>fy+@8&7>A!id3%1$fxHOv z`N$tLCz|ulY{+XMUjRABaW3RdkY8-c=Rm&NAx~F6-W6nZ z$3@^dPHVw)9Nq|?=Q!C7p5x%3;F;&|Nz-*U^LrL}=Ji7G%;zh?bKY-| zwwljTh%@Kgym>l5bH42=NSv=*7Ao(Wx1Z{K_vhCc;s^H`{{!VmFuu6&fakxBB|4vQ z|9arNT3_~3#kp_&Sm1Lm!F=x1cyU|@mnqKuznp(^fpZ@)^$UP=pDytd;M|W(yb`!Q zZ>$9#k~W)hUyZ!n0sl^h-yHXqkne)r9=8$5_dxzBtNb#^-+;W_lAF9Yez08`evK2` za~62s$EpL*_;i40UYRwQ`MiOCWIl|XotQ_%h06aOdJX4Ho>#NJ_wMs*n)t!rBXHfe z2l2P_YR#uLANYF&=35(Zem}(ion5B-cK^-=9+JAvnx_`=|0&{R&)X*cMvwM?ZpG8c z&4=qV#-Z@s#CY~w{0Mm0IPLp4;+ZLa*yFSq?X}}MJEHC4?=!ewY6Z^UT`Gx;e?XZGn6<%D-rpZ-D&Wj%&8F7k1e`j&sIy1af;^?}i`D zpN{hq^RTZ-`DdV4c>d($`YW5>{kT3v;>-J1?3Z?^J*h-{%&SF>~D}0tQpsKzHMk!oWFmgonGMV54LLnIDa=s{Sn}t zm#Lr8r1tsyA>vuUcV%dv)6Oj5c0T6;4@n!m^Fxw+ZA+4mt&qFUb88`g8U8(qIC8x3 zJjM1-o2KnxJ5L4AcvpaDJU4*1^SKlCFb_i)B<6Gbh01>qdfCO3=kpNsBy3aqnCsR9 z<*@U%1M#=>u)SIPm%p>({J8-*e^15!O}ke0`Fkhk!@AXq&zqi@4;z3pZq)Ar&iE1^ z0B+~c5b%(+&Gcah`gbwvv)4K6ljKi3*3tbXn)!Hkn>r^`Fl6! z!yMrJ{TlI2*Qq{#7sq}qzESa?S@{qF&Nx!P8Mr+!tq0D2pnfNCJKuVM+xfE-ct~Pl z`ZbFF{{#H9*SQ;#woa>&yNR4P4;{;^Yatu&j4`#K9Kp={YBO1?+@9Jm0wbvl%|?*QEZ`}@5gxd-JYq~J_PDJC9+DWDKIy`^d=lkL z5N|VQ2ju96d;s!KTXK$DwqrN+=;v$T?QzTX82h&s{mTCByu=#E;7$LUb@`VvH6Iy= zncq|VCM#bemnPbgq7#0?KxseoV71RY$=am$UGw~3QE%TA>ofJ3dBgr*suK0^J|Ww; zk2w4qMSc5$p9nndK^=D)o7LY_fYVMUa62!ufQQ5<)Av2-_m89eL9lCb##~SILhicX z+Xs0*%1?CP#MHxf@_y({=${Wt|1Sg2JPJu!^Wl9e#y{t>#QyHH_?%@bH}N-Z;qR5% z&y`y=Zhu65#Ao(S-v9N8Pbcgf-zNK*`ptEN-Txz~pZjCD?(6E-`WY|w=O}RAeK-EC*<#g{Gm9xnV$wA{~+WO<(ct=aXS-wjMsVK*}lucGj5bK@AAZ!`P=|M z*zY-?PRzT&<%xVdc+(~`e|-h@FrL*(^6LfE7b;7%YkZmLW9l*MNd8{>pD4cx_3-!F ztiS&e^^3pLCZ6`F;&)p927uoO{Md(d-U$NlvG5RZJ702vhs0NNzjqh<^GTFH8Fo!R zm~+h_$K0rKUrZ{~tbIrc!l-yt_X7(W>&<_F_Rp7DAQe*eul z9S5HA`6PJeS6FPD5ASQR-`lKy&x<7H!4P=n*E-nc{1ri*UFWYm5r@|DM7!$E_%J>K6k)#rnR!3%EV61$U_Z2QB*{ z;164P4)Ae#3OpojHn}p4JlTQr_r~R^nV0rLz7z88mfYl#8K10w7xd`o%itMD<`v_| zd5m$Robe*hIFV!&d(fU6Gg%Ie5OlDgRzM?Dej(X+GR{*wmAFJ;mpt zus>B>=6d|T;Io$gNx;8o;R}GTxA0ovydO;a{9VGmmVPtzZJhgvxsInD?qlwiUir_rK=eh9w+W?%;b>V%9QQ-D^ zf8eKj-s1CJmZN>4#}(&uUYday0_SsI)&Q>r&ga0~415qcpVM+T@P;SUKA+=qKkz-k z`J9-?ssA(8=ksCq0B_r=IG=Au`*VJ!IG+o{>zhL0_V{W8&gax{T(1LepQqOY4@uvc zu{477@Dk+Rw1+iM%vd((X|CsJ|8nU4r}G@ov&O#p@IEE;Y#8~)JZrl$F;Ba|n>;h~ zZXjF76ThE~qMdxM4fCw$*V^t6L!Wsz0{l9(k8zCrM)f)GOf>HqSrP1A_Nc~BAn#KH zp5@!7INnY|xnjIuW;DrrW=tHiJad=o z^EpDy%Oc=>t`PB^!1??j+9~{<+TnAAh)00)`9L=?j=xv^2;$50%FIE{s$^_wkT3-?-jpo{|4=%_}BO=EM7698aaSI*)KXh3gXMl}_+xJelh^ zK8K3qsQ~@J=ZP)t)A7C!IG-EE`KJ1h+RuD06!-0|0e&T(?^F&ufg#oBbEUW*%z9RF zK7Xnf`g?)%`BR?(9{jWF^Ep(U7jyS0&gYbI9ngop@}rzfC`wx%2d6G`|?v9nUN7TCeoM-`uOG=C7&8&5Y#`#06+bGe9j0}rDeoX65$P<`Hi5Zrk%aO`Mfvkj{;9S zR>v9j1OHGvd|n&#Y9??#zm0h{8#tfmM*DMtA7Bn~qe$_wD!q)-k^RPHxvj3&}e2yQ_i?zV{JU_0J z_X6kh0_jiN+iHi;`=kAx!1;VY;sx)hKA#gvycam1Lr6SV&U)s&$L9_b?*RTwSp^z7 z$7zmF_4(YvCFrL<;Cv1v+cf~3&-vlF+YS6w#FO^-0=LIqnqTV;i7)0lY$ozP59RIO z356g(&mqr&{L_$Mj&|^TGYj%M$jdD`&o^vWGxQjjTflRi7{ASj>qO@F2*!a*<$INu z#BmZ?t-Nc!)ch{TNxM`u(R%6K+HsBB+ux->JpVn3cricLp}%<_lXwSk`+oP1bj=Tb zpGf_6(-i0Pv6yG;f%CpT^)~>22L4cgBXIsMi29p=zi#Pw1LyCGsNV~GdMI&R?Euc_ zb5egN@FOk#UBGjIQ-26}*wP;c&hI&>KLUK2r9TSX9)}sz$Ht-g-efk$iR*V6xsb1b zef#=w4&<)io8>|7`n}p*$XCO@y)PyV`Ij8^7eJou`yu946n2<5J>Z!ayTP;H-v-Zq zJ??nzclO&{@a&fr;5l!EF)?&uTycDLe#V+7)+F+U*C}ttm+2=ykCo3^Xh1*m`K-L| z%soK+xBEo(lh+|b!1;^uU z*iM9J9C6Kav@@=N12FM3=NrD)h2y3psQ#WYOXEbm;84Z+{sYD-3Y^c2rT)6ZCU5s^ zXm{cD|5>|f$I;AjuxYpXo`cVK<@Nh8{N;0C4}MJ7Y5RfmdA9sMBkM?QU&9A9PRz4e z!1-Px;=S3b&*#Z9pXMH|csuOy{zl0$ir)`B2mVw8=ktNt4|CtA`mQ|lqkOpaKZ`f* zj0>y-F!46)tXI(v=12C4llyxa{O!8oKl7J%9PW*SjlX8C#P=)E-yZn;fe$8*i(SC^ z++FtfNRswFh4w{m{Lk7)JL4MS0N6f0rkwZT8{MxP|rNn&-*^%4{H57yyT*S5;xq(1>V^AXQ_oRy@HyxlKP~y1AABx3 z^Sf}K;(VSw@i_|==kv)qpM=j=oX^2$z7_-LbIOSi6skU-Q%*Yt=O}*KhjkvK{!ZY0 z&N=mmfS(I}ey`hhp4#~X`kVe|6)E0m*{{7wab6!%f6pSt?fVXUfnN_h)ZYjEX3PG5 z;CER1fyHY7J_`>5x4-Af2F~{mFg_vRTP!=Xfp4??nFE~9$LD-87x)h7bG|45ZqFA* zz(bN-=K8c5IgJ-{f7Cgt_*T8e!-3^}o`XG4r+W>g3W5VK_ z`S3mi=ZV6b6X&1Kb%}iYSCn_nH#45ld0(w3|JTenX707`(}tZhwE(0r|%ue;@LJ>wpcAp9T5xmOKi10p#|$-3a*-$Y)#SO)i=Fh5cOtJ@)74 zz_Y*F!LvW^0?&9q2%ho$BY5WDzre4Tg{`^I&hz|C_{H(i^VP(06mC!C17BC(jE95e zcn$A!2>ndQQ#JaD@74GS@K)e_uLiHXN-x$tI05f-I2-!w%M|DPI4%X=dxheBF9*;2 zrB^D>_jvGmG|g8j&i8k)-u=M&{_|^Lf3!~Z`JQxMr(|BOINx`{eC=*hobLm<5q3(O z73X_DZUf$OjpDBRJTsuzk2p(+C;haGbfWJ~XlK&GaYC0r&%&QL)k*&}d10<=?0GVK zwYHn@Jz@No0k`MR4Z!)nkJsVHF!0NfFK+`6en#!{y(b6$T=Q`baK3ls2;gDhJnww~ zcp-4Ek4^<%44m&zITLs(a6W&3KJW-|zJG=K)xh~480t3w=X+YH-vXTPf1!RW@Q}pX zTn}_&zTrCL0{FrCY!l@5h}%V$ybJQrI^^Auw>jiJklzCN;yC+et}}<3x7j~;LXYv^ z1fKET2A=WzIe5nB8Su;}?w{j$;QS_4dLQQT&@GAcS@Erj{3v*n$0l}s{|)DpHpHFp zm$~m(nrAyctNF+G(mVis|K}zj?_Y&p=WU68sMq8FW&6ySkN?n4JT}?iw~8s<%E^@5pL8hQMOaTvHgv0sWi68RSJCST0=F-!1X8s0zYzeU@1 zsfDM>iP-pKKaV>5HpQ!;&+}U^aJGZxTA=6Z&y$|kI1E~T$G6q|9lk@`W!iDP9DIKf z`)BU$>X-dHgg}SleBaNh)3>LobNm8f&QMT z;(Q+v^?SdiINuNC`(JJU#(Nd#`HYU9&i5(NPD`iae2>z(u%G)~ z#ra;PAMe(B1K(Gi?@>DWkBYC^tT^A7)B?P=OL4wW=?UODTNLN}ncn*h>^z`&AN;=; z_{Ob@+vnAc2Nmc3kdywTcJ@D{INuw60{vzxzf&SWUicibaamo8U>$fX@qJ;-~ z6+g$q!w)NdHE^!C+8$Ay?}K8!C66k82lVOZ?moruweUT_dx0|#_XD@*o4}9Njy>Om zfrn&lm^r1-ns4qxTsYtCfcy`r_mUxvGv)n|?}5C|lACdE_KmWg`=Q77&BFVoIDdsi z*L?UK8;<)Z#zU6zoV)gIU`q!d<_IJihirf7+8+b@6GV|+B#JLUS?fW0R9^(AZeYf;K z`>w?KzS`p19#fb3jC*d4U=zh>+FvxjULpBs&|#Ny6Cd;YbH11DXp~<&qH(atdEcvw z^S&_e53GGnaeJTA%-0pSpK~+#hT?qR8RNejINy6l`+I=%J!sYNb1!hdua5WU_5tVn z(rAA_aJzpq-c*0ajZfeqiIG`n4xrzkN540~4>SHuU+;qab;!3uZpMH)j}JorHslY* zl{f2!-H>PE{cQIAg(1j~fZWczJ&@0We5YmK_-NKujQi=(W4xDvXPoQ6Grl)~XIwkL zbG`_RZSy%2^)esx?$&%~K1QO6`JeMG<(>KNm=Ao`CFhERUT zKeYeteDC_F;=_bYDadkb(o->d(n`iwjCu@*Sr$H#R-GjKak*8mSm8%$0Oqraa< zKiK<1_d@QKRn-cr>mVZ;9Tc!%23?S$KW)@?R@M2Zs%kFbk(=>aTnrk zKWA(Rxc!{5)_~fnxB6`qIN$5YyiPk%_3iu(01rtlOh1hvKW~Ix`}YLw7us)wp6mR| zeu*OP?3b>46Z>ZnJoAG44VWL|n)hM8^1Y;d4glrkX@})It^9K3(Q$v%IMH6~cM|<1 zPHOxy->dLFl=D$O3vspm%$%Y2?L3MAxASNexSdClgVc_lM{6?`=X*EV|82ne9!);? zpdGlK7ahPu(l!&zeaMSp^!G(*C)c^7kpBbnPg`=6H|BgzzYfIvGU?BU!L$AU?sFxW zho)c5htD-(zYe26*{}WgCH8NyQ~7^4f6`t^%%48kQ*XxqYy33xINw`(Fv|BM{&xPf zA3SmXbOLAmxK8T=Zs$)Qa65lCyhrV`UzjIR;C7yL0uM1!`3VC4GJGB4b?st=C z=ELVOZYTy@I`pv-k9%SmT0dD7U z8}N|C!sKTL@^~fe+WSBPkYDSNXF|^JU+n9}Amm?gl+S|vHiw+!i2b$^dhC}z@QnKq zc*gZL@QmBxc%L!Po4FDL^WpC)nOD)xR=)lqkuUw>*f=uhPTsd>UJW45d>=N)*WeMF zZzdm2Ilfn!{U(t2;d_^9k9ZyOz75oyi$oYWAkjbK)fR5zX=L=b8}V?BvxTT<6zy&A zO00)|bpki-GS64Azc(p7T-(j}bn`w*FYul4gY(T!;C38Zj#N8#+**P2{oi~}Y|l}u z&-a1zIkA1f`JQt6(+`~QEvG*N!0qug2s|WhHfzIdmz=dZ`};Zs*BH;2{Z(8TYf$&nKY#>u3-2BnR@3Kz{7Y+8)YH ze;QkyzqsyaKjc1;*nc_QiM$l`KBgby=L60+d*H8;n{@);L(lshUSavC5B~AJhQ#^4 zdRzZ@4t%rHgEhj`;YATK_Kt*ChW4mh-b`8>__6~VI11}e6PKY zAMUX8eh1F^yc+#W`g!oAcY`N2u`-{2%$OU}8D7I`*%Lr|BDe zK3_LW^RWc+ww$y#(Ll(=>wD3voSA}puGLu z`dr9A?U2ub{7Q#B5Aqhsdyy}kcjiL=Mab>@y|9ChrCVMUfYjguGa5rFY5{aNZXsN9=5|?7rW-mg;qN{QIG9EdD9MaT~%Ps zi?dGCb`&7aT<^>QZqJvMA5ndK-O+M};`Thz3Oporo3UDmapqcw7D3(&e?EhDa-0`K z?s|>@$D66oeE5Dn#w*aP{lR#(fmiLZe@(nh4u7v8asAed_FRtjE6=mDKdSA&9)5HF zYyFk$6RLlxv>^wFkl5!=#5M0> zjYmx2_`}3wqJ5?%sOS5ZU$wyP{Yx2Vs$cfHxCOYqE^Y^IuZu%-)sDR`&I4}eXFqUz zT|5MQ9^%dOZTnejzrw-(=yvz&9dqbKX=xs{1DPhklWU@rUu#%(eFQ+6e4#x9kUh{O{R+ z4E`VRs!Mq{{R>960eO2S@`>^bt^De=^2>FeIR^gHPVtUJe~FWt{4m#$ z`{4)Ae{G1b?O$zy#{IvQ-<%Ka^())a1^->`7>3*xkFXUFw%bKbJj`5gU+3;XyY2Jq zo&_2YJ5B`)6%WB)1m}e-7V5g;2J|n_E0vI64Y_^)y&Ccs$nE=ujN?qHFaE>!_x&_6 z4}y;;@+^}qUpM1^*?KEqnMWPg`I~k>@4&weJ6s2l(vQH5L_b~qTx#`m;S-7F=m)9s zccS~#>(17Gv->&o9L4SShk@JeZUt_)dmZhdAKBgx-~$#u3jB<-HE*^fUg2}qpWC6& z`wdax*8%7Ku}#23(rz=}YmrY?u=^`39~&TVg518oH~D6+Z&?4$(ECr%cg$nc&+#Aj zZzuYd{TuC1?B`+d?>2v~weqL!$wa&HzL>vF{+K%KeCS4;O*{S@=YPh-o*(J&F#L4+ z8~B;Fk9S)gRY=rmLVA_~q2vZR#=igYygZ{16*=h_Ag5Ci4QV zpYt^LC+r7q@6Ri|Q1$J7GaG;}LcP5I5(RGGm+Ar@5?{^uZNd1x6y;s}Eor|3dc5Dn zeBpj4#;w7MTj*DbaV!MS{#kDI&tS2(*OgB{Moy>m8jyFWJqxBIhXk=n8Qvl6(yzA0HeaX)VY9+Ebg`F#!g?Pu`s9>jy| z*jC7Y2f4iuWG&=>ag=X^{7pxB)9)sK7`M!GH19cX%^VQ_VSfb&67yit;v>ISInR?* zy`TRu+Rr-sV28X-nRoX03SEdZ+hNZ?tS9sv^)p#L@3tK~t#-7b9@~HNu6Fb!X$R{W zhW%vqyxVpRS?wtPZDPOEe^S#9vmWO8l;g7x?XdePP@>}`BxQ_m>yWSSMIPGu&i*uc z8~>r7UGR^74m8|8)Fk|?5w1el7FxqR!p%1t{&xe;J#-|q5p&MoBrqg{=XBS_gnGlaM(>2pAgz>$0rKhj?ZvuVthLO&G^v&QTR>& z3;!^AeE7Qww#zlX=34RTaoD9DlRst-*oyD5&PVy&OSHZAc|CHO;`VucAfmXv9?Pgu z{3NWiW9tdvD{;NRby^U3vxR2^ztqA*z{@N=2Y5Ab)|(5w7~_TY<^jLV!o$GlVLe9u zLg00lelhUN(O&A80=M%j0z4#rVD|rRKwe!3yY{>tg?ugK_Pn(b@^ub*C**vuw_Sb{ zaHc z-+&(TFymZZw=w^Y1JAt62hV)F1U&O>6?o>?=fN|tz6GB7^aOb3(Tm`jKZl;D{&2pH zi0|feF51QMo;|4Z2giH#sl@pt@W0BN@os(}bv^9ze7dJn$LTjMd_$Gu-4f*ru87ioKl4^*rEDHguFM)3=Q^Ly^$D;2*E_S@g9PI_IzN*ySX1s`?I0P_Fn*=?IzFmmO;*T)`RDG{T%h@WI^s9Lc8btko7>mtZP@QTYT5OinBX5%kNG|2^YEYbU!i`(dBsB&T`eagql-BtDt;51?O8KpgDzzKOHZqy1B%XY$<0 zO#94-dCvGmo=uGVsKtl=taA24z10tU;HPUndo}u@6?W7M_rL6i3#@vIP>J22Z7p<6@y(sDpy)e0c;Ht^xY;Uw$ z^%|1ci_}leUa)p*deH{e>qt`XF!X|s`HbzzZkk%X#aF9d1ooWs%QcDiT=P`~^}6Kr zuWfarJ>oX)wCc6xn4}8-U#fGchR2DslApY^`>1vwR*dt z*Pq1R=oIaRZqRzOUz)uBYUsJzNqhi$)k*AS-#B@FwATf_o+S20p_lve*tx4>4+%z?NeP2|)fh6{FzB)B~X*a80=#|O!TfaWJob7Euy$wn172h&7djaV6 zC9xN|ZEE&9rdaPN>WwC`7rAF@_J&aJND_M^_fE}T=|!+Nwp*zuD@tcV}^@dSzXy3$g>a}j0Tu#0A2dAbN*sgkoN$PEY9__p6DD*m#*o)wI zkHI%4_j9Coayk9zgS{x?+vc#_^0?aTck~18g`ZTtmLz()KUKZyJ>$mi%Z_^g!K~Iu)^g%CoRNFJ;(2x8ovAr(4IlolB)+F{? zemymN{Z_qpJIN2iUMK1$Zqx8@66>|)j-fGzEOJXlK z$^IYOYe2ohe@tF~@$V;>(_TC3jU=(x@Q10{>q5OL{HMv~ zG5dd1z2YSHx~BMjP#5Zr!d{NUZk~1D-c^70v+CbS5_^5teSVj{DC*^RY=)Y{JnNj_ z_k`qc^SxNE9C>ntKHTo{xWye*< z*on7A-uN4mBS#L~Kk67?`M05lk1sb>>?G6?ub=F1Bj*ucFR^$UFV8_;CQe~F3gsx4 zqf`!-G5Y2xd``#3FlZjXUjQ8h&B1;17SMjsYTU2p_c;OFe=P;=1RVt}d;#@==2`a# z1Gs-t3fc)e3fh6|?mS!vw}B3V=HU9S1+*VD`!%h%8ng$L&#mmlb;Bs=FxJbwj>yCM zH3G_Y;M2&5vA zia;s?sR*PZkcvPm0;ve3B9MweDgvnpq#}@tKq>;M2&5vAia;s?sR*PZkcvPm0;ve3 zB9MweDgvnpq#}@tKq>;M2&5vAia;s?sR*PZkcvPm0;ve3B9MweDgvnpq#}@tKq>;M z2&5vAia;s?sR*PZkcvPm0;ve3B9Mx}|L-Dj=m~wk#q(SJ*^!y^7SA95Uqg07V6jLV zvKPh6^BaO*DN~>!dvU&~ENtcQvD^5&{ zT$sNoKXO8Tt3OcCkd1$*1*D`nZU2+s5E6~W3#hp0Twz7gJI0E8ri_+%i0N$OzChRPa0ASf9`!0Q4O$?fH2;}!&ewWGE+Gh%GP_SWpSkf{14x+Ly-RUi;=A zjs3M$JSv&5sL7KhN&dFOs*RG0I9`v@fgsUONG;QV5@`U2L)^^kIUL8EEDm|OEdR=& zGG`mHX)?n6HHIla{@?i0YRe!zKw@vT-9v^-h8@$qQrn-=*fR$$?>va+V;@`|gcROGQ;fb4`6++C_)A4nOyfete>N!Qv%#l~s+kt8403ENE=3 zZ#=JRb=pNodXl30it^f;&s0?wR5evJ)_4Xyv2jOA<~KH$ug)zi6Qhax3(IS2S2b2G zsw!`)ud}T#tf{S9ELOc%T{VAUeyy~zyt%%yplW&fs@i6?W+GHszpA-GBBO3DD)KBD z+v4kzMMaC78z*pD(5mv41?A1<7dO^4H&@k_)Sq9qvc7S(3OxVST`}QVoF{Q!(OAE# zuCk=O>8knVbrn^$wN;hseOx%GUr@iYyhbAFxwU9jT~U2~!~FV{E9>jdudl3XQvao4 z^Tc9p)zYfQCJB5jZk07n4du-h)n&#=+11*-`2MPqWH`c$aQzimR+KeJ`T9EPhvwB~ z*W_v{l&xrK87DZZJzTlEwo>A@>WZ=}YD}-H@v^e{3ni%}6=NIKKUhL(Rnvz^;9XzC` zz5BuK(UzXA+qXO@dHCS{TiUnY|IpU$-CNr4Z|{DnJKEvv^XGMo=z;bv-4FC^7p~7= zJl?2Dj`Pdw%2ycYTYL60Qy<(KZHadIdZPWlE!|t?uV|+~8ciQ>;QUq19%nGtD)Ip)OB z+ZeS{eRL@O{%D_HJczbUi;noCea}qL3{61OLnB}N7Yh%jOB?*r4l&Sr!1(Hl8|y2o znwrk3TV5|MZ+nF*cXhhmNnpj7`(IV_H4F=y3W& zk|fd5^k~cY66Y?y@PfrvjWuRAD%WXD+VnbW8DC(2b$MfXMRQf-;wqU>wnqo2n@|l; z;QPh(jaSKlG^60K*3p1qE%I^#O{%; zZEw<5GdQ}VBW7$_{fxx*96r3Y^R2NG67~KJNfe3C_+s7+X6oqL#}YkTd!v2nCaqfi z4@qi{FNC_JNsFqkURBj3G0JKk{yPmsdnO2!Okh=&OJqbDW-|HK$tfVep`o@$P9fg;?XcFKSR}?< zl-%>?yI^!AJ=z%8D%n#H;GfOv~;{orY{+N&8v%QnwrPW7=h^U1a%jdloWd-p{YSm zlG2E*)^<#_?@XZ16O1>B9o|}e|3l-wUSiFWOk4dzgmhlQa+%Bgl`Rjph zkA0xeA8LPC%%RS)g4?7WW!@60YGs2gjw;G4swE<=(E+AT-yOct_{Op+tz9w2ZQa|V zeRA^2=$7_8(k;___al87h24GAgzF0!sKfWjw(dvdKgl7ZJM7zLlqWFH+23?d+wbX1 zw0{P5t;mk)w+_4!ubviLjg4E3>4ij7+7V%mfLt%gYBGP7tfH%GWz}s~ug$9(>z0<+ z${DCVttmjw@-ZDtB}f&RFvYTu79W<>T`Q}}vPD%*t5$l(LV{Mc)HEB79HS9;HM3ln z=LXNEwYUn4>+5Ta>l=(XkK&b0D;8JPRT?ZzOj~21LPF){BEcZVM5^k<8=Yazkn|>h zk(W|#*So5z+LVt_J}zWdII52{7e^(MTlI~yj4Y^WlmQ@@5ynUZjfm%xce0u{XbaIR zs#eI-K8CmYBu24izg*pUL2UC;y=iq_MJ%4}M!7*QY?_xFn;kK&asC={G$vLfW@<5b zr|-StvLz)Ys~f7!xk#pgrjmLi=!z9U;1{ow{QHOz^~6L?CXM8DQeU^i2>QkZRn44W z%j#rx-CV!2rlPE(zQK!1|CpXJaB)@nRi^kr436s(BN#MIE%Pp8O%_Xdy(rbo94yiy z-=X2M6`!f71wX93Oz(9@JfiHia*gMykB&Dc*ElsRJmpqDV_jQcUTGYY&XxgF<>g&l zOe$Az((2Xpyxkw)ak5ZaRaGXJ=4J^Y9(2TtY1ioWxCo*#fr$)_b;i(|x|(L9U8ahr z+NvsVRP^}0q${e|xGPs!zfvw|;6$v>8=;3O~%Oq&;IJB zie_(A4jOhvRda(}WQugie|T6f4j1X1VUS_JBua(=@qGd_%| z{&X)6OO~8dpp6-8$bc;}MUCRT)y;CPFNFt<_2rFKnzdfdvDs?au=D4aEiTMI&FGF8 zUUIBflX%pym5p*PpOa_Atr@~M)L(1{8J zQp!4vto#bOt}&X?X-Ane_yvobPcJJw?X-`SmDN?XG@HqNWz_;Ng*%P@$||{abd49e zF2hTD)K#q1`Cys^xT&hv4A~3HwX6FKwo<}bUl|Yg8@R%Bls6xr?NT2rJEzCD zp{6NjwaW;sz%bA~)1@J6(vZ}UzMOl@((OOosvcYTGfDu8`EHhGBRh_wo<;~E8@x@qRC?53gnZ|4l$JrV? zRgD<5K}MilikW=!mKLK16of0Q)&qpULhgk&%dHbH9or0IMZnB0wdGe-8P5lf+v#r$ zX7Bf{_vhsF`C4}Sy8Ye$_30!2*69Pjb>4q#eLFlFuHKNIHIg2X&raWvuPwdTzcIZ# zeYbx!eXXx#qrW%3)8CP?aeDXk;y_^c0fYYHydA#m4qrhqE33!fmSGA`@agn*`}X-a zOy8SP63h%`1%shThc9zudN6CZuVm1_$v@y5@XL*He=t*Il>??~Uw@#(w&jtYB6sSS-NC^j%VL?E%6IR^07tomQL~=<@Yu1VeM%(yKfD zJN!kJb7r?^45U|g_?8X(Hu*M9>-F!So;mE#-0AC;%GUV`H~KdD*ZW3%a`)0V;46|w zWajSowPa0>NNz@t$cLe8FHO5|r}6Hs7GHIA>;ahp%}kJv=vehrh5W+&*n)RyZS& z*_IK^YseVzRW^rPeQUC#z6}|p{vEz{iM&_6xYXrq&RREZoqy0bE1J>o-|27lN7hQP z*7}Ne`6~mN;`WGdzkf6%*zF(j1@pT7QGaG|ldsh`I!%HrQIsRAdaXYYFg;(=>f7Ke zh-AxuS*5|!ybhmH3KwN=^7ngLU|Mag1~O~=BsN(a{loqZ>H7nle9QLwmSuGWg6;lb zprPI0Am7+!?K)uh0a4$~ne7tF+CY!L%Qv%Il4zGWm{pLsQQ98t65ji3z2wA3Uvcp+ z-#WkCBKFOlGwffpTZ-hi`?7ZU=9UI`_?HC&(z*fP-f8PHg01PzVx}{Foo{f)sQ9mL z8UJcqie?4D8edDY_xSet*7|4enilF!&&%DB9^NIz`h6P?+2F68X}WlQdemRrklp3) zFaZcx?(*&Q5Bb;n=N5#Ea%LGL`swxeOy4_gqi=tPBy3>WvhZHtKt|?n-=KdW!~8pE zudk%rUmM8l$f(V0_3f0j2+8e>>CtIx(+7QWE7QN;-#oX+H<-RJV`N%y`Yx%kwAG&% z8BNdJ?{D|-^Y{3r8zm@#?94n#+hxm^6)u~TGvrwp)22RC5oxcqtJ~k>GuV3nT&aJT zZ_O_MumB_e>h+S$@mz7IFEHxM$=vBLT{Gw_>6L71p4B@|$LZWauq|U$hC`okuOwOC zh)?j$=3ZZJZFO;P`hI_2-l(s#&DZ5$=g$a4eJvs#^_6t^sy7NB$nE!K2ZFn$P-dHd zk1xBSu*duzDJ(LEGT9%6;k@R|jCKB;mOzhJZ|=J3Yh@zYAvwDzBjEiPZk}Vt-srUU z^y+Riwj@f11~WV}B{}Q;!7l&$>4CWo%Xau0HpygE7?NqHIlJ9w{_m1Jnk%0<^63}5 zQQxq?V2`gf>W}pMD>wM(gfqpjh;-|EUtwWZbwp+tsjsLcBbc?`pBr2!sT~~gm5P6b z(u=LW%vN8&U;mlgl`%4-JHvAwNwL<~=?i9OXUo?E-hb;PK0(tk@s;dNIv^NLt!lVdgC;pJuSRGt$z0X=(DWex5iWkw5!jkN0$q zMzO^YPfwJWTJoFKUab7=2-*}K$Upm}Po1yX;zgg`Gs-F*PeK9`Y z;&1nR_F{5*9ioXxj6dDdKUmurlMh(_FS7JYs>>XnH)1~EO_3gI! zZ^#RP;{DxXl|NYJQY+$N@uy4V;{7{E`B;4si@(m&UnQFH`eOcm&dP@eE&X=2FQxSJMX@YU%)ghc_T6IHE3oqGB6)#XeEDvx{B*1R|FZHc z*J}TVwZA1w`q`@Oi?#nrE50F7i?9C@%fC8{&$QxMsP)I<_X~|zj32i60V_X4YA@#R zJga}VY5v9HeV-Nos1^TDs6DAgKk`~B(>`g1erBkCjQ_OO7vq1T_GA3Vq*#3UXSBW2 z3;H=x{fqH$dGgj6@ALY1j6YlL#rmU2{fqH)EPDaXkC?q0Egy?VtMV~_zhUtYXgZ9W$NV|hlAmjpzt`%IN38xBu=tBCd&QRgcx{h_ zNIxI4_>Wk8sg@U1Ki%qojQ_o5|2C^X@3Q#&to|&u{Jq@bzc1B_vt#|Q{>Au*Ect-N zzhLpJw7+BJpSSFtZ}DHU^bZhc;{Ex8=3C6(n^yTUi$C5fze>k%to*5#{49%q&GKij zB|q2Ve`nSIKURG=S^PDY{tTUOWBwgu@!z!C|B%(c8+AOz$}hM2_fyt*y1?T5t^9ev z#ec%$7hB`!Wc4>T-k!7kYq9*>YSsTsi~qY-{u9zN33<%^%~ty|todZ6HC|q|>{m*@ zn)g0lEJv{%$H{T19A$DGCWkEV)4m`_l^n;)aiko_$T3rn!{zv*9LwdnNRBJyD3{|$ zazy3$x*QwixI~WYh?j?vmqP zIZEXCA35%k&%=b;R{Tza)nYm9!o? z*2vK%N4*>^ax}_utsIgn-n&74LhqB~b~&Vb(xgk$8szwl9MauspO)i?a{NG!WpZ34 z$E9-IB*!*69+cx|IabQiDaU3xw#d;YN0uCy$q|twU5*SnBxTZ$lH&n6zAHzw99PRx zEypG~u9Txj4m0<4%du6CS~;$fBPvI#AOFAKkJ624_BOEi4Uo1B-+b8L$jc4%BpWp0=#?_JdZ(9@@+sYtq^1e}>VCT1pCfF`+yBN3Y zb?oZ{Z{LF>3h2MMJq)U-fZ1unEfIEA@nIO-t%QxQwsOL*P+REjO0~i98&7Qw`I;%V zU)Gi-?2EO97joavMcyt^TWr2%x3RIks^j-|$jFV`kZ+en(wHq?8rj6%ABc9`whtig z{T}g2GVykQ+XvmLYHj$y9t{gM-#M9WAF=%(@`v|zu29|aq5j2hC{ZMS2Zti#c6^{| zu`MdLpRtZX{H=k{Zc7_W?S!2nYF?)z-4dcmY%hqiu}vU$_2??;f9}ndP{)2V;e~xg z8n%oGm$*AbfaKdk>>3ld>P{$)+xKhBy_~Z4GA~Zt*&DaTME;y;$H)}6oY?hFu=kfc zTgoQ-Rf&8P>+OQE?RYza4;pGSLQ=i8i@lFAX=x2sOK6u#HBy)^G!i?xwMu%^5*=>~K$tD!8Iq4}z!oDCGVR{Cd=!ac)6|#J~Ds7UjKO*veSA}0&$)qyD54y0C$li(M?KQGN zY)`WNNZ4#%Hr8GE>Dk2lh0KN|v!^GvG0EO-WHQ5S)|5f1JBe&>61EVH-#e7BqbauC zNs@V#} zw;Sv24pMb2yJaioSY#8n{fxm$b`MRoF(`)pKka=7R20j)H8Tu(7;**~$s(bLBsoXP z5+n$cgJgy*aX^v?N>YLZK}19(BT+z9Kv9t>l0*g)wZE?d`zHAOjN6?Fv^Qty$2_0C;BQli{(Q0DR|Wieb>GT@KQH}UBJle> zqJ0yFe$FNO^R=<${e8;NzpPL6wzl(@6ciK{Ly3rr2x0Bv{m18VcqO4xA3_a07oQz%*c(WEBSrCfkj}=>soVfhX4WV~T?p*@}ejx^TeY?tyj5{Plqw zz84R{A^l#Yt%sX{133HE2AotcVCxM|KXVQAakfPZ_7y~6ABQX+ijx*Fh346paW`J*J;VUN*QdmUyt!S>JGYe`e#Y3p zpD&xAC$wDMLexgvK2r0zX4un4fw#1St5}O~Z9yj?A{6 zgEyq~1SBIT+*XT7hk9R~WefVS(&2KF&ulCLT{CjOi84VS|Ant@310}a0bo zFFB^0rcbybG~bQN=z@;J2<@|n*5b)x%R^+!b*+!Q9fG+t22E4o{&ER5%e@uyoN3BU zG)|NFxTPUR#nDPtE(tGYVsH90xYQ$2H1dsCk9YWUNbg)s_RF`wWAK_=EGS}2V|Gk5 zhEt}!%|&C$_0ZTztf~Fu&v!(&2fXJ`7uMCeL<_lodc-AUQlpcKW6kHLA$&4iC{DGs z#<1Zve?{gpp7fYkN!sF(PgWDxpQgLZe5<w4RCrAmf`A9_uK?J8AYa6WUk%%XSp)umd(BVu2f$ene6!2Cg+@4St% z(B~U0bVz*dT=Q7*hcUw$?=wA;1HZK@vOc%adv{^{skjyYt1#$r#qC< zWdbTRYmcK{>C*n1 zlwpK{>Zt^sxYY19e%pamT)i<Qt)bS$&~fIAWuomV23xeXd$9bu(mxtDVsXx)i+Fp}K<-HG~H> zCC=JLIT26mT=gxR6c#iIzk-rFNpr6;D=@;Y-SAzwyGPrnyN`mIuN0qjJ;`9Ivo!}i zTi@i)c`T~uMSr#GJR`!Td79q$(4oj|orHxW;@{rEo@sTbXvm~UrVk+LT5{>t7H7Kn zm#a;iNy8l)U1`b)?wNDFAscSh=kMo9KA!&aDzd>NCLeu0BYSF{q2ku3?)w_tvqFV0 zpHHs5UbdpQ4YIMm<`KnceT2GovH)ihIgU_xZDP!wTj#u^qt1YFIV3i0kiu`<@@|Y} zX@iWfqTAHe+W7J$DpOFlmcsUKdP&FA?2YxR50eo*^!`9=`fa7LYbWE~REN%V&l^b} zdjb>`#ic~!5)fC$6OU6isOsNwLXecTel~qUrg=*J%Y!f_9}AkKwpyx$BIumvTFu%~x<{^5UC*sVw0-8~P=alP%&-0`!n%$|LW)-`HxH z6bVsIQOfC*dr4g@z88yDUPP-6YZSabe>miM$3~wPYK&`5Kz`kjV4?6030Ys71{He( zPxQmfA2m~9;!|XqH$Qq`T^yJhw3#!Y_JL4*3-Ek{x7B~T$NtNV{Y$Ck!E;AvUe2An zc4r1*DHc3f4ta2e=nQUsf~z~<=lpZBUg=*E{N#xvZl{-Qg@+NG%HZ6EDB+_&rT^wY%TgcJwcGw z(!YbYQ}%p0jcXX!WcXmK*>^-ten#fWg%PO1sPsoeiI~sMc>PqK_*K^5E{p>WVV1U= z@wrT+HH!G;#o?OXP69C7PH=i`4DIQNg{0wGp05bVOX(%HhDoLJ#(}|COCGP_7n$gz zE|%pK^3^^(eT-$zq5V|Ma<54I!#)jr&H?&WUS_uWX@2b*_u}I{XBc`t+9-2dd%t$i zr;t=IAIc6vsa-nhz(An0;eJR+a7BM1TfoSrBhBa4%^TLu^ZTO7T&n2KVy1ufEUwnMc|S^eN+9g;#?a z?MshcyKY6(%vJP$_M{}+yU|W{f9Nrd5{LS6a1D=SYL>iAltlL^#I5B->=mZ!ILwLe zXStGMn>N~-=2dU31`yva645FJ(ldJde-Z5KFQ+SHNsp&Y+%m&k@>M((N3S zWj&XbJ^YCOlve$9u|Wg2EbVdJN6CNp{QuMI&wNVPQ!W!Po*TTAaE(Hpw;_|}s8kDS zCz{y0lj(@SNQL=?ws*@~>Lq?1I=-8-mJ~09>;(wZ;gEZ>7D-UE|B@5xXS|+VtE$w__^$d8}o4sz)7S44Y>l=Ng5(B?~ju zr1A(kESxMR-)}yc5VUUMJbU!1GEC&QkE>VG3f;%XSHmZ!zB8 z_ldWFW#PzIxLz172Hm4ZIw+|SD}VJ3g`t%lFC6Pz54++aAroWfk^uW zbk_v^g+gRW5kv>!s16Lc@0F_k5`kZMMMD@Sd9YP{TuKpA0u%PHrQ zTs@CY0^)yKzy2;ig2(^<(eje`PEF`c-#)L+*~w3<*&+-jKJlZbODw7tZ6Xyy)7>fcAKg5_JMuZ90-`#2uE! z$n8_*G&fE-TcO|5CJ5u+JFBg2&i>>Pto7B|o$%L!@9bcwPv;kDnD(=nx_<)RRcD~M zXpZJ8lLkdttvsvtdCzOcMG*i>eyq^%1W)WQR;N>gap2GHNGUcBJGzRM|J?sw`Tiph zc4Qr!7d!fky$>;Ow0iWWtsOoT8~gp(yN(V0ybi&RQ-43OBhc7`811`jCkyCe$G(5u zZ=acf^Ld;EEQ6g32*)SdEr%3B0L=>rciDqLP-FlpK9N

  • a6q28H0^>`w&d%EKVS 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

    ZS~;Pa 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�Lmb|>bRdkr)Ab6b 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 z�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 From 89526bf44a74f0cc1e53a18de74090e01f1828db Mon Sep 17 00:00:00 2001 From: tsunghung <78230356+tsunghung@users.noreply.github.com> Date: Wed, 6 Mar 2024 15:22:54 -0800 Subject: [PATCH 04/25] Analytics 10.22.1 (#12482) --- FirebaseAnalyticsOnDeviceConversion.podspec | 4 ++-- GoogleAppMeasurementOnDeviceConversion.podspec | 4 ++-- Package.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/FirebaseAnalyticsOnDeviceConversion.podspec b/FirebaseAnalyticsOnDeviceConversion.podspec index e4ec770b8e5..52d1135775e 100644 --- a/FirebaseAnalyticsOnDeviceConversion.podspec +++ b/FirebaseAnalyticsOnDeviceConversion.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAnalyticsOnDeviceConversion' - s.version = '10.23.0' + s.version = '10.22.1' s.summary = 'On device conversion measurement plugin for FirebaseAnalytics. Not intended for direct use.' s.description = <<-DESC @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.cocoapods_version = '>= 1.12.0' - s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.23.0' + s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.22.1' s.static_framework = true diff --git a/GoogleAppMeasurementOnDeviceConversion.podspec b/GoogleAppMeasurementOnDeviceConversion.podspec index f56e61e7aca..d2a11cd4683 100644 --- a/GoogleAppMeasurementOnDeviceConversion.podspec +++ b/GoogleAppMeasurementOnDeviceConversion.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'GoogleAppMeasurementOnDeviceConversion' - s.version = '10.23.0' + s.version = '10.22.1' s.summary = <<-SUMMARY On device conversion measurement plugin for Google App Measurement. Not intended for direct use. @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.authors = 'Google, Inc.' s.source = { - :http => 'https://dl.google.com/firebase/ios/analytics/a0551aa6065a8330/GoogleAppMeasurementOnDeviceConversion-10.22.0.tar.gz' + :http => 'https://dl.google.com/firebase/ios/analytics/c696679c30b9561e/GoogleAppMeasurementOnDeviceConversion-10.22.1.tar.gz' } s.cocoapods_version = '>= 1.12.0' diff --git a/Package.swift b/Package.swift index c95d29bfd51..ae854aa3f10 100644 --- a/Package.swift +++ b/Package.swift @@ -1324,7 +1324,7 @@ func googleAppMeasurementDependency() -> Package.Dependency { return .package(url: appMeasurementURL, branch: "main") } - return .package(url: appMeasurementURL, exact: "10.22.0") + return .package(url: appMeasurementURL, exact: "10.22.1") } func abseilDependency() -> Package.Dependency { From 5797426f043e2f40b1249feb76f83bcae70801da Mon Sep 17 00:00:00 2001 From: Andrew Heard Date: Thu, 7 Mar 2024 01:44:20 +0000 Subject: [PATCH 05/25] Upgrade `clang-format` to v18 (#12483) --- CONTRIBUTING.md | 2 +- FirebaseDatabase/Tests/Integration/FData.m | 7 ++++--- .../Tests/Integration/FIRDatabaseQueryTests.m | 4 +--- FirebaseDatabase/Tests/Integration/FOrderByTests.m | 4 +--- Firestore/core/src/immutable/keys_view.h | 4 ++-- Firestore/core/src/util/hashing.h | 8 ++++---- README.md | 2 +- scripts/setup_check.sh | 2 +- scripts/style.sh | 4 ++-- 9 files changed, 17 insertions(+), 20 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2023549978c..b62328f4dde 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -132,7 +132,7 @@ To develop Firebase software, **install**: To install [clang-format] and [mint] using [Homebrew]: ```console - brew install clang-format@17 + brew install clang-format@18 brew install mint ``` diff --git a/FirebaseDatabase/Tests/Integration/FData.m b/FirebaseDatabase/Tests/Integration/FData.m index 012603b8ca0..2fa04319f9f 100644 --- a/FirebaseDatabase/Tests/Integration/FData.m +++ b/FirebaseDatabase/Tests/Integration/FData.m @@ -314,9 +314,10 @@ - (void)testWriteLeafNodeOverwriteAtParentMultipleTimesVerifyExpectedEvents { ios - sdk / firebase - ios - sdk / Example / Database / Tests / Helpers / FEventTester - .m : 123 because it was raised inside test case -[FEventTester(null)] which has no - associated XCTestRun object.This may happen when test cases are - constructed and invoked independently of standard XCTest infrastructure, + .m : 123 because it was raised inside test case - + [FEventTester( + null)] which has no associated XCTestRun object.This may happen when test cases + are constructed and invoked independently of standard XCTest infrastructure, or when the test has already finished ." - Expected http://localhost:9000/-M8IJYWb68MuqQKKz2IY/a aa (0) to match " "http://localhost:9000/-M8IJYWb68MuqQKKz2IY/a (null) (4)' from " diff --git a/FirebaseDatabase/Tests/Integration/FIRDatabaseQueryTests.m b/FirebaseDatabase/Tests/Integration/FIRDatabaseQueryTests.m index a9945b50e49..4163cd15ae6 100644 --- a/FirebaseDatabase/Tests/Integration/FIRDatabaseQueryTests.m +++ b/FirebaseDatabase/Tests/Integration/FIRDatabaseQueryTests.m @@ -4192,9 +4192,7 @@ - (void)testGetForParentReturnsCorrectValue { [ref getDataWithCompletionBlock:^(NSError* err, FIRDataSnapshot* snapshot) { XCTAssertNil(err); - XCTAssertEqualObjects( - [snapshot value], - @{@"a" : @1}); + XCTAssertEqualObjects([snapshot value], @{@"a" : @1}); done = YES; }]; } diff --git a/FirebaseDatabase/Tests/Integration/FOrderByTests.m b/FirebaseDatabase/Tests/Integration/FOrderByTests.m index 86642d36e65..e3734f8d915 100644 --- a/FirebaseDatabase/Tests/Integration/FOrderByTests.m +++ b/FirebaseDatabase/Tests/Integration/FOrderByTests.m @@ -235,9 +235,7 @@ - (void)testFiresChildMovedEvents { moved = YES; XCTAssertEqualObjects(snapshot.key, @"greg", @""); XCTAssertEqualObjects(prevName, @"rob", @""); - XCTAssertEqualObjects( - snapshot.value, - @{@"nuggets" : @57}, @""); + XCTAssertEqualObjects(snapshot.value, @{@"nuggets" : @57}, @""); }]; [ref setValue:initial]; diff --git a/Firestore/core/src/immutable/keys_view.h b/Firestore/core/src/immutable/keys_view.h index fad8510cd59..c866ba5ef6c 100644 --- a/Firestore/core/src/immutable/keys_view.h +++ b/Firestore/core/src/immutable/keys_view.h @@ -47,8 +47,8 @@ auto KeysView(const Range& range) -> KeysRange { } template -auto KeysViewFrom(const Range& range, const K& key) - -> KeysRange { +auto KeysViewFrom(const Range& range, + const K& key) -> KeysRange { auto keys_begin = util::make_iterator_first(range.lower_bound(key)); auto keys_end = util::make_iterator_first(std::end(range)); return util::make_range(keys_begin, keys_end); diff --git a/Firestore/core/src/util/hashing.h b/Firestore/core/src/util/hashing.h index 7286c44cc32..33375f03a63 100644 --- a/Firestore/core/src/util/hashing.h +++ b/Firestore/core/src/util/hashing.h @@ -190,8 +190,8 @@ auto RankedInvokeHash(const Range& range, HashChoice<3>) * value can itself be hashed. */ template -auto RankedInvokeHash(const absl::optional& option, HashChoice<4>) - -> decltype(InvokeHash(*option)) { +auto RankedInvokeHash(const absl::optional& option, + HashChoice<4>) -> decltype(InvokeHash(*option)) { return option ? InvokeHash(*option) : -1171; } @@ -202,8 +202,8 @@ size_t RankedInvokeHash(K value, HashChoice<5>) { } template -auto RankedInvokeHash(const std::unique_ptr& ptr, HashChoice<6>) - -> decltype(InvokeHash(*ptr)) { +auto RankedInvokeHash(const std::unique_ptr& ptr, + HashChoice<6>) -> decltype(InvokeHash(*ptr)) { return ptr ? InvokeHash(*ptr) : 23631; } diff --git a/README.md b/README.md index 7ab83d9c446..6e0742ddb29 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ GitHub Actions will verify that any code changes are done in a style-compliant way. Install `clang-format` and `mint`: ```console -brew install clang-format@17 +brew install clang-format@18 brew install mint ``` diff --git a/scripts/setup_check.sh b/scripts/setup_check.sh index 057abc47c0b..eb323eb0473 100755 --- a/scripts/setup_check.sh +++ b/scripts/setup_check.sh @@ -35,7 +35,7 @@ fi # install clang-format brew update -brew install clang-format@17 +brew install clang-format@18 # mint installs tools from Mintfile on demand. brew install mint diff --git a/scripts/style.sh b/scripts/style.sh index 58feb1d3da8..e8fcf12f37a 100755 --- a/scripts/style.sh +++ b/scripts/style.sh @@ -56,7 +56,7 @@ version="${version/ (*)/}" version="${version/.*/}" case "$version" in - 17) + 18) ;; google3-trunk) echo "Please use a publicly released clang-format; a recent LLVM release" @@ -65,7 +65,7 @@ case "$version" in exit 1 ;; *) - echo "Please upgrade to clang-format version 17." + echo "Please upgrade to clang-format version 18." echo "If it's installed via homebrew you can run:" echo "brew upgrade clang-format" exit 1 From 33cf55b444005a697c4b2acdc512974547a3e0f5 Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Thu, 7 Mar 2024 11:53:56 -0500 Subject: [PATCH 06/25] [Release] Add patch note for 10.22.1 (#12490) --- FirebaseCore/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/FirebaseCore/CHANGELOG.md b/FirebaseCore/CHANGELOG.md index 10aeb1cc605..79ec5d5f636 100644 --- a/FirebaseCore/CHANGELOG.md +++ b/FirebaseCore/CHANGELOG.md @@ -1,3 +1,9 @@ +# Firebase 10.22.1 +- [Swift Package Manager / CocoaPods] Fix app validation issues on Xcode 15.3 + for those using the `FirebaseAnalyticsOnDeviceConversion` SDK. This issue was + caused by embedding an incomplete `Info.plist` from a dependency of the SDK. + (#12441) + # Firebase 10.22.0 - [Swift Package Manager] Firebase now enforces a Swift 5.7.1 minimum version, which is aligned with the Xcode 14.1 minimum. (#12350) From 48a77e345196c2123dcfdd58b7166c16604e63ed Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Fri, 8 Mar 2024 07:28:24 -0800 Subject: [PATCH 07/25] Restore 10.23.0 versions to main after 10.22.1 (#12497) --- FirebaseAnalyticsOnDeviceConversion.podspec | 4 ++-- GoogleAppMeasurementOnDeviceConversion.podspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FirebaseAnalyticsOnDeviceConversion.podspec b/FirebaseAnalyticsOnDeviceConversion.podspec index 52d1135775e..e4ec770b8e5 100644 --- a/FirebaseAnalyticsOnDeviceConversion.podspec +++ b/FirebaseAnalyticsOnDeviceConversion.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FirebaseAnalyticsOnDeviceConversion' - s.version = '10.22.1' + s.version = '10.23.0' s.summary = 'On device conversion measurement plugin for FirebaseAnalytics. Not intended for direct use.' s.description = <<-DESC @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.cocoapods_version = '>= 1.12.0' - s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.22.1' + s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.23.0' s.static_framework = true diff --git a/GoogleAppMeasurementOnDeviceConversion.podspec b/GoogleAppMeasurementOnDeviceConversion.podspec index d2a11cd4683..717e14fb888 100644 --- a/GoogleAppMeasurementOnDeviceConversion.podspec +++ b/GoogleAppMeasurementOnDeviceConversion.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'GoogleAppMeasurementOnDeviceConversion' - s.version = '10.22.1' + s.version = '10.23.0' s.summary = <<-SUMMARY On device conversion measurement plugin for Google App Measurement. Not intended for direct use. From 6ae867d07e49cf47ad7beefe951218557c39a8b8 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Fri, 8 Mar 2024 13:30:52 -0800 Subject: [PATCH 08/25] Patch abseil-cpp to ignore deprecated errors in new Xcode. (#12498) --- cmake/external/abseil-cpp.cmake | 3 +++ cmake/external/abseil-cpp.patch.txt | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 cmake/external/abseil-cpp.patch.txt diff --git a/cmake/external/abseil-cpp.cmake b/cmake/external/abseil-cpp.cmake index 8546dbfb875..7fde8522ccf 100644 --- a/cmake/external/abseil-cpp.cmake +++ b/cmake/external/abseil-cpp.cmake @@ -14,6 +14,7 @@ include(ExternalProject) +# Note: When updating to 20230802.0 or later, remove the PATCH_COMMAND below. set(version 20220623.0) ExternalProject_Add( @@ -31,4 +32,6 @@ ExternalProject_Add( INSTALL_COMMAND "" TEST_COMMAND "" HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" + + PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/abseil-cpp.patch.txt ) diff --git a/cmake/external/abseil-cpp.patch.txt b/cmake/external/abseil-cpp.patch.txt new file mode 100644 index 00000000000..5c906321a38 --- /dev/null +++ b/cmake/external/abseil-cpp.patch.txt @@ -0,0 +1,27 @@ +diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h +index d886cb30..c2a2d15e 100644 +--- a/absl/meta/type_traits.h ++++ b/absl/meta/type_traits.h +@@ -35,6 +35,12 @@ + #ifndef ABSL_META_TYPE_TRAITS_H_ + #define ABSL_META_TYPE_TRAITS_H_ + ++// Added by firebase-ios-sdk/cmake/external/abseil-cpp.patch.txt ++#if __clang__ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wdeprecated" ++#endif // __clang__ ++ + #include + #include + #include +@@ -794,4 +800,9 @@ using swap_internal::StdSwapIsUnconstrained; + ABSL_NAMESPACE_END + } // namespace absl + ++// Added by firebase-ios-sdk/cmake/external/abseil-cpp.patch.txt ++#if __clang__ ++#pragma clang diagnostic pop ++#endif // __clang__ ++ + #endif // ABSL_META_TYPE_TRAITS_H_ From d715ee896924bbc6969e2e9b19170f21df7a65aa Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Fri, 8 Mar 2024 18:17:30 -0800 Subject: [PATCH 09/25] Fix CI breakage from recent merge (#12504) --- cmake/external/abseil-cpp.patch.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/external/abseil-cpp.patch.txt b/cmake/external/abseil-cpp.patch.txt index 5c906321a38..1624ee06fab 100644 --- a/cmake/external/abseil-cpp.patch.txt +++ b/cmake/external/abseil-cpp.patch.txt @@ -5,7 +5,7 @@ index d886cb30..c2a2d15e 100644 @@ -35,6 +35,12 @@ #ifndef ABSL_META_TYPE_TRAITS_H_ #define ABSL_META_TYPE_TRAITS_H_ - + +// Added by firebase-ios-sdk/cmake/external/abseil-cpp.patch.txt +#if __clang__ +#pragma clang diagnostic push @@ -18,7 +18,7 @@ index d886cb30..c2a2d15e 100644 @@ -794,4 +800,9 @@ using swap_internal::StdSwapIsUnconstrained; ABSL_NAMESPACE_END } // namespace absl - + +// Added by firebase-ios-sdk/cmake/external/abseil-cpp.patch.txt +#if __clang__ +#pragma clang diagnostic pop From 01c7d950dbea30720dfb560f45d28d8611c654e2 Mon Sep 17 00:00:00 2001 From: hs7 Date: Mon, 11 Mar 2024 23:53:01 +0900 Subject: [PATCH 10/25] Resolved warning no rule to process file 'PrivacyInfo.xcprivacy' of type 'text.xml' with CocoaPods (#12513) --- FirebaseMessaging.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FirebaseMessaging.podspec b/FirebaseMessaging.podspec index 15195fc96f1..6e3cbcde4e6 100644 --- a/FirebaseMessaging.podspec +++ b/FirebaseMessaging.podspec @@ -37,7 +37,7 @@ device, and it is completely free. base_dir = "FirebaseMessaging/" s.source_files = [ - base_dir + 'Sources/**/*', + base_dir + 'Sources/**/*.{c,m,h}', base_dir + 'Sources/Protogen/nanopb/*.h', base_dir + 'Interop/*.h', 'Interop/Analytics/Public/*.h', From 34667bc0bfc6c853f45d822ccaa0f864d443e588 Mon Sep 17 00:00:00 2001 From: wu-hui <53845758+wu-hui@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:12:09 -0400 Subject: [PATCH 11/25] Upgrade grpc to 1.62 for cocoapods (#12398) --- FirebaseFirestoreInternal.podspec | 5 +++-- Firestore/core/test/unit/nanopb/message_test.cc | 7 ------- Firestore/core/test/unit/util/to_string_test.cc | 5 +++-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/FirebaseFirestoreInternal.podspec b/FirebaseFirestoreInternal.podspec index f6f3235d733..4717dcf1cf7 100644 --- a/FirebaseFirestoreInternal.podspec +++ b/FirebaseFirestoreInternal.podspec @@ -94,7 +94,7 @@ Google Cloud Firestore is a NoSQL document database built for automatic scaling, s.dependency 'FirebaseAppCheckInterop', '~> 10.17' s.dependency 'FirebaseCore', '~> 10.0' - abseil_version = '~> 1.20220623.0' + abseil_version = '~> 1.20240116.1' s.dependency 'abseil/algorithm', abseil_version s.dependency 'abseil/base', abseil_version s.dependency 'abseil/container/flat_hash_map', abseil_version @@ -104,7 +104,8 @@ Google Cloud Firestore is a NoSQL document database built for automatic scaling, s.dependency 'abseil/time', abseil_version s.dependency 'abseil/types', abseil_version - s.dependency 'gRPC-C++', '~> 1.49.1' + s.dependency 'gRPC-Core', '~> 1.62.0' + s.dependency 'gRPC-C++', '~> 1.62.0' s.dependency 'leveldb-library', '~> 1.22' s.dependency 'nanopb', '>= 2.30908.0', '< 2.30911.0' diff --git a/Firestore/core/test/unit/nanopb/message_test.cc b/Firestore/core/test/unit/nanopb/message_test.cc index 78489edbbad..77549e80857 100644 --- a/Firestore/core/test/unit/nanopb/message_test.cc +++ b/Firestore/core/test/unit/nanopb/message_test.cc @@ -25,7 +25,6 @@ #include "Firestore/core/src/nanopb/writer.h" #include "Firestore/core/src/remote/grpc_nanopb.h" #include "Firestore/core/test/unit/testutil/status_testing.h" -#include "grpcpp/impl/codegen/grpc_library.h" #include "grpcpp/support/byte_buffer.h" #include "gtest/gtest.h" @@ -60,12 +59,6 @@ class MessageTest : public testing::Test { grpc::ByteBuffer BadProto() const { return {}; } - - private: - // Note: gRPC slice will crash upon destruction if gRPC library hasn't been - // initialized, which is normally done by inheriting from this class (which - // does initialization in its constructor). - grpc::GrpcLibraryCodegen grpc_initializer_; }; #if !__clang_analyzer__ diff --git a/Firestore/core/test/unit/util/to_string_test.cc b/Firestore/core/test/unit/util/to_string_test.cc index a5b38d177c9..9f4a6f58a37 100644 --- a/Firestore/core/test/unit/util/to_string_test.cc +++ b/Firestore/core/test/unit/util/to_string_test.cc @@ -49,8 +49,9 @@ TEST(ToStringTest, SimpleTypes) { EXPECT_EQ(ToString(nullptr), "null"); - void* ptr = reinterpret_cast(0xBAAAAAAD); - EXPECT_EQ(ToString(ptr), "baaaaaad"); + // TODO(b/326402002): Below no longer passes after abseil upgrade + // to 1.20240116.1 void* ptr = reinterpret_cast(0xBAAAAAAD); + // EXPECT_EQ(ToString(ptr), "baaaaaad"); } TEST(ToStringTest, CustomToString) { From 07b76691759cb99b3890a1162dde8f499e2ade79 Mon Sep 17 00:00:00 2001 From: Mila <107142260+milaGGL@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:53:11 -0400 Subject: [PATCH 12/25] Snapshot listener source from cache (#12370) --- Firestore/CHANGELOG.md | 3 + .../Firestore.xcodeproj/project.pbxproj | 22 + .../Example/Tests/SpecTests/FSTSpecTests.mm | 19 +- .../Tests/SpecTests/FSTSyncEngineTestDriver.h | 3 +- .../SpecTests/FSTSyncEngineTestDriver.mm | 4 +- .../json/listen_source_spec_test.json | 5895 +++++++++++++++++ .../Tests/Util/FSTIntegrationTestCase.h | 5 + .../Tests/Util/FSTIntegrationTestCase.mm | 16 + Firestore/Source/API/FIRDocumentReference.mm | 9 + Firestore/Source/API/FIRQuery.mm | 9 + .../Source/API/FIRSnapshotListenOptions.mm | 63 + Firestore/Source/API/converters.h | 4 + Firestore/Source/API/converters.mm | 12 + .../FirebaseFirestore/FIRDocumentReference.h | 17 + .../Public/FirebaseFirestore/FIRQuery.h | 16 + .../FIRSnapshotListenOptions.h | 83 + .../FirebaseFirestore/FirebaseFirestore.h | 1 + Firestore/Swift/Tests/BridgingHeader.h | 1 + .../SnapshotListenerSourceTests.swift | 684 ++ Firestore/core/src/api/listen_source.h | 37 + Firestore/core/src/core/event_manager.cc | 65 +- Firestore/core/src/core/event_manager.h | 25 +- Firestore/core/src/core/listen_options.h | 51 +- Firestore/core/src/core/query_listener.cc | 5 + Firestore/core/src/core/query_listener.h | 4 + Firestore/core/src/core/sync_engine.cc | 40 +- Firestore/core/src/core/sync_engine.h | 38 +- .../core/test/unit/core/event_manager_test.cc | 44 +- 28 files changed, 7138 insertions(+), 37 deletions(-) create mode 100644 Firestore/Example/Tests/SpecTests/json/listen_source_spec_test.json create mode 100644 Firestore/Source/API/FIRSnapshotListenOptions.mm create mode 100644 Firestore/Source/Public/FirebaseFirestore/FIRSnapshotListenOptions.h create mode 100644 Firestore/Swift/Tests/Integration/SnapshotListenerSourceTests.swift create mode 100644 Firestore/core/src/api/listen_source.h diff --git a/Firestore/CHANGELOG.md b/Firestore/CHANGELOG.md index 60d99030d03..ceded5649ef 100644 --- a/Firestore/CHANGELOG.md +++ b/Firestore/CHANGELOG.md @@ -1,3 +1,6 @@ +# Unreleased +- [feature] Enable snapshot listener option to retrieve data from local cache only. (#12370) + # 10.22.0 - [fixed] Fix the flaky offline behaviour when using `arrayRemove` on `Map` object. (#12378) diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index b0aa3693dd8..99f967e3ccd 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -205,6 +205,7 @@ 1CC56DCA513B98CE39A6ED45 /* memory_local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F6CA0C5638AB6627CB5B4CF4 /* memory_local_store_test.cc */; }; 1CC9BABDD52B2A1E37E2698D /* mutation_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = C8522DE226C467C54E6788D8 /* mutation_test.cc */; }; 1CEEB0E7FBBB974224BBA557 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = A2E6F09AD1EE0A6A452E9A08 /* bloom_filter_test.cc */; }; + 1CFBD4563960D8A20C4679A3 /* SnapshotListenerSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */; }; 1D618761796DE311A1707AA2 /* database_id_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB71064B201FA60300344F18 /* database_id_test.cc */; }; 1D71CA6BBA1E3433F243188E /* common.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 544129D221C2DDC800EFB9CC /* common.pb.cc */; }; 1D76DDBE57A4D66C64C00B65 /* FIRFieldValueTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04A202154AA00B64F25 /* FIRFieldValueTests.mm */; }; @@ -238,6 +239,7 @@ 21E588CF29C72813D8A7A0A1 /* FSTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */; }; 21E66B6A4A00786C3E934EB1 /* query_engine_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B8A853940305237AFDA8050B /* query_engine_test.cc */; }; 224496E752E42E220F809FAC /* resource.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1C3F7302BF4AE6CBC00ECDD0 /* resource.pb.cc */; }; + 2252357505C92A067DAC38B0 /* listen_source_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */; }; 226574601C3F6D14DF14C16B /* recovery_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 9C1AFCC9E616EC33D6E169CF /* recovery_spec_test.json */; }; 227CFA0B2A01884C277E4F1D /* hashing_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54511E8D209805F8005BD28F /* hashing_test.cc */; }; 229D1A9381F698D71F229471 /* string_win_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 79507DF8378D3C42F5B36268 /* string_win_test.cc */; }; @@ -508,6 +510,7 @@ 5150E9F256E6E82D6F3CB3F1 /* bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F7FC06E0A47D393DE1759AE1 /* bundle_cache_test.cc */; }; 518BF03D57FBAD7C632D18F8 /* FIRQueryUnitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */; }; 51A483DE202CC3E9FCD8FF6E /* Validation_BloomFilterTest_MD5_5000_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = B0520A41251254B3C24024A3 /* Validation_BloomFilterTest_MD5_5000_01_membership_test_result.json */; }; + 5250AE69A391E7A3310E013B /* listen_source_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */; }; 52967C3DD7896BFA48840488 /* byte_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5342CDDB137B4E93E2E85CCA /* byte_string_test.cc */; }; 529AB59F636060FEA21BD4FF /* garbage_collection_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = AAED89D7690E194EF3BA1132 /* garbage_collection_spec_test.json */; }; 5360D52DCAD1069B1E4B0B9D /* testing_hooks_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = A002425BC4FC4E805F4175B6 /* testing_hooks_test.cc */; }; @@ -816,6 +819,7 @@ 6F67601562343B63B8996F7A /* FSTTestingHooks.mm in Sources */ = {isa = PBXBuildFile; fileRef = D85AC18C55650ED230A71B82 /* FSTTestingHooks.mm */; }; 6F914209F46E6552B5A79570 /* async_queue_std_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6FB4681208EA0BE00554BA2 /* async_queue_std_test.cc */; }; 6FAC16B7FBD3B40D11A6A816 /* target.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE7D20B89AAC00B5BCE7 /* target.pb.cc */; }; + 6FB40B88ACB4CFB34917319C /* listen_source_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */; }; 6FC85C48CF8235BA1845E1C8 /* FSTUserDataReaderTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8D9892F204959C50613F16C8 /* FSTUserDataReaderTests.mm */; }; 6FCC64A1937E286E76C294D0 /* logic_utils_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 28B45B2104E2DAFBBF86DBB7 /* logic_utils_test.cc */; }; 6FD2369F24E884A9D767DD80 /* FIRDocumentSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04B202154AA00B64F25 /* FIRDocumentSnapshotTests.mm */; }; @@ -1050,6 +1054,7 @@ 9C86EEDEA131BFD50255EEF1 /* comparison_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 548DB928200D59F600E00ABC /* comparison_test.cc */; }; 9CC32ACF397022BB7DF11B52 /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = D22D4C211AC32E4F8B4883DA /* Validation_BloomFilterTest_MD5_500_0001_bloom_filter_proto.json */; }; 9CE07BAAD3D3BC5F069D38FE /* grpc_streaming_reader_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D964922154AB8F00EB9CFB /* grpc_streaming_reader_test.cc */; }; + 9CFF379C7404F7CE6B26AF29 /* listen_source_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */; }; 9D71628E38D9F64C965DF29E /* FSTAPIHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04E202154AA00B64F25 /* FSTAPIHelpers.mm */; }; 9E1997789F19BF2E9029012E /* FIRCompositeIndexQueryTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 65AF0AB593C3AD81A1F1A57E /* FIRCompositeIndexQueryTests.mm */; }; 9E656F4FE92E8BFB7F625283 /* to_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B696858D2214B53900271095 /* to_string_test.cc */; }; @@ -1059,6 +1064,7 @@ 9F9244225BE2EC88AA0CE4EF /* sorted_set_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA4C20A36DBB00BCEB75 /* sorted_set_test.cc */; }; A05BC6BDA2ABE405009211A9 /* target_id_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380CF82019382300D97691 /* target_id_generator_test.cc */; }; A06FBB7367CDD496887B86F8 /* leveldb_opener_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 75860CD13AF47EB1EA39EC2F /* leveldb_opener_test.cc */; }; + A0BC30D482B0ABD1A3A24CDC /* SnapshotListenerSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */; }; A0C6C658DFEE58314586907B /* offline_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA12A11F315EE100DD57A1 /* offline_spec_test.json */; }; A0D61250F959BC52CEFF9467 /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8FB22BCB9F454DA44BA80C8 /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json */; }; A0E1C7F5C7093A498F65C5CF /* memory_bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB4AB1388538CD3CB19EB028 /* memory_bundle_cache_test.cc */; }; @@ -1068,6 +1074,7 @@ A17DBC8F24127DA8A381F865 /* testutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352820A3B3BD003E0143 /* testutil.cc */; }; A186FECD0257B92FDB0E83B8 /* Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 5B96CC29E9946508F022859C /* Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json */; }; A192648233110B7B8BD65528 /* field_transform_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7515B47C92ABEEC66864B55C /* field_transform_test.cc */; }; + A1A466F55A1ED0AC5EE449BF /* listen_source_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */; }; A1F57CC739211F64F2E9232D /* hard_assert_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */; }; A215078DBFBB5A4F4DADE8A9 /* leveldb_index_manager_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 166CE73C03AB4366AAC5201C /* leveldb_index_manager_test.cc */; }; A21819C437C3C80450D7EEEE /* writer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BC3C788D290A935C353CEAA1 /* writer_test.cc */; }; @@ -1156,11 +1163,13 @@ AFCA3C24AA751B5B2D3E6FEF /* Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 0D964D4936953635AC7E0834 /* Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json */; }; AFE84E7B0C356CD2A113E56E /* status_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3CAA33F964042646FDDAF9F9 /* status_testing.cc */; }; AFF7D2CF35B51656E4744164 /* bloom_filter_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = A2E6F09AD1EE0A6A452E9A08 /* bloom_filter_test.cc */; }; + B00F8D1819EE20C45B660940 /* SnapshotListenerSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */; }; B03F286F3AEC3781C386C646 /* FIRNumericTransformTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D5B25E7E7D6873CBA4571841 /* FIRNumericTransformTests.mm */; }; B04E4FE20930384DF3A402F9 /* aggregate_query_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AF924C79F49F793992A84879 /* aggregate_query_test.cc */; }; B0B779769926304268200015 /* query_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 731541602214AFFA0037F4DC /* query_spec_test.json */; }; B0D10C3451EDFB016A6EAF03 /* writer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BC3C788D290A935C353CEAA1 /* writer_test.cc */; }; B0E745EAC5F37CA61F868F38 /* Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 4B3E4A77493524333133C5DC /* Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json */; }; + B104B69726EF6A5B41DAFB17 /* listen_source_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */; }; B15D17049414E2F5AE72C9C6 /* memory_local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F6CA0C5638AB6627CB5B4CF4 /* memory_local_store_test.cc */; }; B188D7EC9A100F365DB02490 /* Validation_BloomFilterTest_MD5_500_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = DD990FD89C165F4064B4F608 /* Validation_BloomFilterTest_MD5_500_01_membership_test_result.json */; }; B192F30DECA8C28007F9B1D0 /* array_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54EB764C202277B30088B8F3 /* array_sorted_map_test.cc */; }; @@ -1740,6 +1749,8 @@ 4B59C0A7B2A4548496ED4E7D /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json; sourceTree = ""; }; 4BD051DBE754950FEAC7A446 /* Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_01_bloom_filter_proto.json; sourceTree = ""; }; 4C73C0CC6F62A90D8573F383 /* string_apple_benchmark.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_benchmark.mm; sourceTree = ""; }; + 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SnapshotListenerSourceTests.swift; sourceTree = ""; }; + 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */ = {isa = PBXFileReference; includeInIndex = 1; path = listen_source_spec_test.json; sourceTree = ""; }; 4F5B96F3ABCD2CA901DB1CD4 /* bundle_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = bundle_builder.cc; sourceTree = ""; }; 526D755F65AC676234F57125 /* target_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = target_test.cc; sourceTree = ""; }; 52756B7624904C36FBB56000 /* fake_target_metadata_provider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = fake_target_metadata_provider.h; sourceTree = ""; }; @@ -2221,6 +2232,7 @@ 3355BE9391CC4857AF0BDAE3 /* DatabaseTests.swift */, 62E54B832A9E910A003347C8 /* IndexingTests.swift */, 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */, + 4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */, ); path = Integration; sourceTree = ""; @@ -2968,6 +2980,7 @@ 8C7278B604B8799F074F4E8C /* index_spec_test.json */, 54DA129E1F315EE100DD57A1 /* limbo_spec_test.json */, 54DA129F1F315EE100DD57A1 /* limit_spec_test.json */, + 4D9E51DA7A275D8B1CAEAEB2 /* listen_source_spec_test.json */, 54DA12A01F315EE100DD57A1 /* listen_spec_test.json */, 54DA12A11F315EE100DD57A1 /* offline_spec_test.json */, 54DA12A21F315EE100DD57A1 /* orderby_spec_test.json */, @@ -3378,6 +3391,7 @@ BFBE4732E93E38317B110778 /* index_spec_test.json in Resources */, 546877D72248206A005E3DE0 /* limbo_spec_test.json in Resources */, 546877D82248206A005E3DE0 /* limit_spec_test.json in Resources */, + 6FB40B88ACB4CFB34917319C /* listen_source_spec_test.json in Resources */, 546877D92248206A005E3DE0 /* listen_spec_test.json in Resources */, 546877DA2248206A005E3DE0 /* offline_spec_test.json in Resources */, 546877DB2248206A005E3DE0 /* orderby_spec_test.json in Resources */, @@ -3436,6 +3450,7 @@ 604B75044D6BEC2B7515EA1B /* index_spec_test.json in Resources */, 54ACB6CB224C11F400172E69 /* limbo_spec_test.json in Resources */, 54ACB6CC224C11F400172E69 /* limit_spec_test.json in Resources */, + 2252357505C92A067DAC38B0 /* listen_source_spec_test.json in Resources */, 54ACB6CD224C11F400172E69 /* listen_spec_test.json in Resources */, 54ACB6CE224C11F400172E69 /* offline_spec_test.json in Resources */, 54ACB6CF224C11F400172E69 /* orderby_spec_test.json in Resources */, @@ -3484,6 +3499,7 @@ 77C36312F8025EC73991D7DA /* index_spec_test.json in Resources */, F08DA55D31E44CB5B9170CCE /* limbo_spec_test.json in Resources */, 15A5F95DA733FD89A1E4147D /* limit_spec_test.json in Resources */, + 5250AE69A391E7A3310E013B /* listen_source_spec_test.json in Resources */, D73BBA4AB42940AB187169E3 /* listen_spec_test.json in Resources */, C15F5F1E7427738F20C2D789 /* offline_spec_test.json in Resources */, 4781186C01D33E67E07F0D0D /* orderby_spec_test.json in Resources */, @@ -3532,6 +3548,7 @@ 6156C6A837D78D49ED8B8812 /* index_spec_test.json in Resources */, 85BC2AB572A400114BF59255 /* limbo_spec_test.json in Resources */, 9F41D724D9947A89201495AD /* limit_spec_test.json in Resources */, + B104B69726EF6A5B41DAFB17 /* listen_source_spec_test.json in Resources */, 3CFFA6F016231446367E3A69 /* listen_spec_test.json in Resources */, A0C6C658DFEE58314586907B /* offline_spec_test.json in Resources */, D98430EA4FAA357D855FA50F /* orderby_spec_test.json in Resources */, @@ -3599,6 +3616,7 @@ 3783E25DFF9E5C0896D34FEF /* index_spec_test.json in Resources */, 54DA12A81F315EE100DD57A1 /* limbo_spec_test.json in Resources */, 54DA12A91F315EE100DD57A1 /* limit_spec_test.json in Resources */, + 9CFF379C7404F7CE6B26AF29 /* listen_source_spec_test.json in Resources */, 54DA12AA1F315EE100DD57A1 /* listen_spec_test.json in Resources */, 54DA12AB1F315EE100DD57A1 /* offline_spec_test.json in Resources */, 54DA12AC1F315EE100DD57A1 /* orderby_spec_test.json in Resources */, @@ -3665,6 +3683,7 @@ E04607A1E2964684184E8AEA /* index_spec_test.json in Resources */, 2AD8EE91928AE68DF268BEDA /* limbo_spec_test.json in Resources */, BC5AC8890974E0821431267E /* limit_spec_test.json in Resources */, + A1A466F55A1ED0AC5EE449BF /* listen_source_spec_test.json in Resources */, 5B89B1BA0AD400D9BF581420 /* listen_spec_test.json in Resources */, F660788F69B4336AC6CD2720 /* offline_spec_test.json in Resources */, 4F5714D37B6D119CB07ED8AE /* orderby_spec_test.json in Resources */, @@ -4572,6 +4591,7 @@ 3B1E27D951407FD237E64D07 /* FirestoreEncoderTests.swift in Sources */, 62E54B862A9E910B003347C8 /* IndexingTests.swift in Sources */, 621D620C28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, + 1CFBD4563960D8A20C4679A3 /* SnapshotListenerSourceTests.swift in Sources */, 4D42E5C756229C08560DD731 /* XCTestCase+Await.mm in Sources */, 09BE8C01EC33D1FD82262D5D /* aggregate_query_test.cc in Sources */, 0EC3921AE220410F7394729B /* aggregation_result.pb.cc in Sources */, @@ -4812,6 +4832,7 @@ 5E89B1A5A5430713C79C4854 /* FirestoreEncoderTests.swift in Sources */, 62E54B852A9E910B003347C8 /* IndexingTests.swift in Sources */, 621D620B28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, + A0BC30D482B0ABD1A3A24CDC /* SnapshotListenerSourceTests.swift in Sources */, 736C4E82689F1CA1859C4A3F /* XCTestCase+Await.mm in Sources */, 412BE974741729A6683C386F /* aggregate_query_test.cc in Sources */, DF983A9C1FBF758AF3AF110D /* aggregation_result.pb.cc in Sources */, @@ -5299,6 +5320,7 @@ 6F45846C159D3C063DBD3CBE /* FirestoreEncoderTests.swift in Sources */, 62E54B842A9E910B003347C8 /* IndexingTests.swift in Sources */, 621D620A28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, + B00F8D1819EE20C45B660940 /* SnapshotListenerSourceTests.swift in Sources */, 5492E0442021457E00B64F25 /* XCTestCase+Await.mm in Sources */, B04E4FE20930384DF3A402F9 /* aggregate_query_test.cc in Sources */, 1A3D8028303B45FCBB21CAD3 /* aggregation_result.pb.cc in Sources */, diff --git a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm index 622b3b527d7..f2b8ca2e4be 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm +++ b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm @@ -41,6 +41,7 @@ #include "Firestore/core/src/bundle/bundle_reader.h" #include "Firestore/core/src/bundle/bundle_serializer.h" #include "Firestore/core/src/core/field_filter.h" +#import "Firestore/core/src/core/listen_options.h" #include "Firestore/core/src/credentials/user.h" #include "Firestore/core/src/local/persistence.h" #include "Firestore/core/src/local/target_data.h" @@ -79,10 +80,12 @@ using firebase::firestore::Error; using firebase::firestore::google_firestore_v1_ArrayValue; using firebase::firestore::google_firestore_v1_Value; +using firebase::firestore::api::ListenSource; using firebase::firestore::api::LoadBundleTask; using firebase::firestore::bundle::BundleReader; using firebase::firestore::bundle::BundleSerializer; using firebase::firestore::core::DocumentViewChange; +using firebase::firestore::core::ListenOptions; using firebase::firestore::core::Query; using firebase::firestore::credentials::User; using firebase::firestore::local::Persistence; @@ -385,11 +388,25 @@ - (DocumentViewChange)parseChange:(NSDictionary *)jsonDoc ofType:(DocumentViewCh return DocumentViewChange{std::move(doc), type}; } +- (ListenOptions)parseOptions:(NSDictionary *)optionsSpec { + ListenOptions options = ListenOptions::FromIncludeMetadataChanges(true); + + if (optionsSpec != nil) { + ListenSource source = + [optionsSpec[@"source"] isEqual:@"cache"] ? ListenSource::Cache : ListenSource::Default; + // include_metadata_changes are default to true in spec tests + options = ListenOptions::FromOptions(true, source); + } + + return options; +} + #pragma mark - Methods for doing the steps of the spec test. - (void)doListen:(NSDictionary *)listenSpec { Query query = [self parseQuery:listenSpec[@"query"]]; - TargetId actualID = [self.driver addUserListenerWithQuery:std::move(query)]; + ListenOptions options = [self parseOptions:listenSpec[@"options"]]; + TargetId actualID = [self.driver addUserListenerWithQuery:std::move(query) options:options]; TargetId expectedID = [listenSpec[@"targetId"] intValue]; XCTAssertEqual(actualID, expectedID, @"targetID assigned to listen"); diff --git a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h index c99836f8406..978ae28a4e5 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h +++ b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h @@ -146,9 +146,10 @@ typedef std:: * Resulting events are captured and made available via the capturedEventsSinceLastCall method. * * @param query A valid query to execute against the backend. + * @param options A listen option to configure snapshot listener. * @return The target ID assigned by the system to track the query. */ -- (model::TargetId)addUserListenerWithQuery:(core::Query)query; +- (model::TargetId)addUserListenerWithQuery:(core::Query)query options:(core::ListenOptions)options; /** * Removes a listener from the FSTSyncEngine as if the user had removed a listener corresponding diff --git a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm index 41fe884c70f..7fe5dc5d91e 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm +++ b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm @@ -476,10 +476,8 @@ - (FSTOutstandingWrite *)receiveWriteError:(int)errorCode return result; } -- (TargetId)addUserListenerWithQuery:(Query)query { - // TODO(dimond): Allow customizing listen options in spec tests +- (TargetId)addUserListenerWithQuery:(Query)query options:(ListenOptions)options { // TODO(dimond): Change spec tests to verify isFromCache on snapshots - ListenOptions options = ListenOptions::FromIncludeMetadataChanges(true); auto listener = QueryListener::Create( query, options, [self, query](const StatusOr &maybe_snapshot) { FSTQueryEvent *event = [[FSTQueryEvent alloc] init]; diff --git a/Firestore/Example/Tests/SpecTests/json/listen_source_spec_test.json b/Firestore/Example/Tests/SpecTests/json/listen_source_spec_test.json new file mode 100644 index 00000000000..1912afc320f --- /dev/null +++ b/Firestore/Example/Tests/SpecTests/json/listen_source_spec_test.json @@ -0,0 +1,5895 @@ +{ + "Clients can have multiple listeners with different sources": { + "describeName": "Listens source options:", + "itName": "Clients can have multiple listeners with different sources", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 0, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + }, + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + }, + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Contents of query are cleared when listen is removed.": { + "comment": "Explicitly tests eager GC behavior", + "describeName": "Listens source options:", + "itName": "Contents of query are cleared when listen is removed.", + "tags": [ + "eager-gc" + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": true + }, + "steps": [ + { + "userSet": [ + "collection/a", + { + "key": "a" + } + ] + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "key": "a" + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "writeAck": { + "version": 1000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [ + ] + } + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 4 + }, + "expectedSnapshotEvents": [ + { + "added": [ + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "Documents are cleared when listen is removed.": { + "describeName": "Listens source options:", + "itName": "Documents are cleared when listen is removed.", + "tags": [ + "eager-gc" + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": true + }, + "steps": [ + { + "userSet": [ + "collection/a", + { + "matches": true + } + ] + }, + { + "userSet": [ + "collection/b", + { + "matches": true + } + ] + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + [ + "matches", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "matches": true + }, + "version": 0 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "matches": true + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + [ + "matches", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "writeAck": { + "version": 1000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [ + ] + } + } + }, + { + "writeAck": { + "version": 2000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/b" + ], + "rejectedDocs": [ + ] + } + } + }, + { + "userSet": [ + "collection/b", + { + "matches": false + } + ], + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + [ + "matches", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "matches": true + }, + "version": 0 + } + ] + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + [ + "matches", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "writeAck": { + "version": 3000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/b" + ], + "rejectedDocs": [ + ] + } + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 4 + }, + "expectedSnapshotEvents": [ + { + "added": [ + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "userUnlisten": [ + 4, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "Doesn't include unknown documents in cached result": { + "describeName": "Listens source options:", + "itName": "Doesn't include unknown documents in cached result", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": true + }, + "steps": [ + { + "userSet": [ + "collection/exists", + { + "key": "a" + } + ] + }, + { + "userPatch": [ + "collection/unknown", + { + "key": "b" + } + ] + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/exists", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "key": "a" + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "Doesn't raise 'hasPendingWrites' for deletes": { + "describeName": "Listens source options:", + "itName": "Doesn't raise 'hasPendingWrites' for deletes", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "userDelete": "collection/a", + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ] + } + ] + }, + { + "writeAck": { + "version": 2000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [ + ] + } + } + } + ] + }, + "Empty initial snapshot is raised from cache": { + "describeName": "Listens source options:", + "itName": "Empty initial snapshot is raised from cache", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "Empty-due-to-delete initial snapshot is raised from cache": { + "describeName": "Listens source options:", + "itName": "Empty-due-to-delete initial snapshot is raised from cache", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": 1 + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userDelete": "collection/a" + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "Listeners with different source shares watch changes between primary and secondary clients": { + "describeName": "Listens source options:", + "itName": "Listeners with different source shares watch changes between primary and secondary clients", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 3, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 2, + "drainQueue": true + }, + { + "clientIndex": 2, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 2, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "Local mutations notifies listeners sourced from cache in all tabs": { + "describeName": "Listens source options:", + "itName": "Local mutations notifies listeners sourced from cache in all tabs", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userSet": [ + "collection/a", + { + "key": "a" + } + ], + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "key": "a" + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "key": "a" + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Mirror queries being listened from different sources while listening to server in primary tab": { + "describeName": "Listens source options:", + "itName": "Mirror queries being listened from different sources while listening to server in primary tab", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": -1 + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": -1 + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ] + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": -1 + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ] + } + ] + } + ] + }, + "Mirror queries being listened in different clients sourced from cache ": { + "describeName": "Listens source options:", + "itName": "Mirror queries being listened in different clients sourced from cache ", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 0, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + }, + "targetId": 4 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "targetId": 4 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userUnlisten": [ + 4, + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "userSet": [ + "collection/c", + { + "sort": -1 + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "sort": -1 + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ] + } + ] + } + ] + }, + "Mirror queries being listened in the same secondary client sourced from cache": { + "describeName": "Listens source options:", + "itName": "Mirror queries being listened in the same secondary client sourced from cache", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 0, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + }, + "targetId": 4 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "targetId": 4 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 1, + "userUnlisten": [ + 4, + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 1, + "userSet": [ + "collection/c", + { + "sort": -1 + } + ], + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "sort": -1 + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ] + } + ] + } + ] + }, + "Mirror queries from different sources while listening to server in secondary tab": { + "describeName": "Listens source options:", + "itName": "Mirror queries from different sources while listening to server in secondary tab", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + }, + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 0 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": -1 + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": -1 + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "sort", + "desc" + ] + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ] + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": -1 + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "sort", + "asc" + ] + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "sort": 1 + }, + "version": 1000 + } + ] + } + ] + } + ] + }, + "Newer deleted docs from bundles should delete cached docs": { + "describeName": "Listens source options:", + "itName": "Newer deleted docs from bundles should delete cached docs", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "loadBundle": "127{\"metadata\":{\"id\":\"test-bundle\",\"createTime\":\"1970-01-01T00:00:00.003000000Z\",\"version\":1,\"totalDocuments\":1,\"totalBytes\":158}}155{\"documentMetadata\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"readTime\":\"1970-01-01T00:00:00.003000000Z\",\"exists\":false}}", + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "removed": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ] + } + ] + } + ] + }, + "Newer docs from bundles should keep not raise snapshot if there are unacknowledged writes": { + "describeName": "Listens source options:", + "itName": "Newer docs from bundles should keep not raise snapshot if there are unacknowledged writes", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 250 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-250" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 250 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 250 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 250 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "userPatch": [ + "collection/a", + { + "value": "patched" + } + ], + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "modified": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "value": "patched" + }, + "version": 0 + } + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "loadBundle": "127{\"metadata\":{\"id\":\"test-bundle\",\"createTime\":\"1970-01-01T00:00:00.001001000Z\",\"version\":1,\"totalDocuments\":1,\"totalBytes\":388}}154{\"documentMetadata\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"readTime\":\"1970-01-01T00:00:00.001001000Z\",\"exists\":true}}228{\"document\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"createTime\":\"1970-01-01T00:00:00.000250000Z\",\"updateTime\":\"1970-01-01T00:00:00.001001000Z\",\"fields\":{\"value\":{\"stringValue\":\"fromBundle\"}}}}" + } + ] + }, + "Newer docs from bundles should overwrite cache": { + "describeName": "Listens source options:", + "itName": "Newer docs from bundles should overwrite cache", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "loadBundle": "127{\"metadata\":{\"id\":\"test-bundle\",\"createTime\":\"1970-01-01T00:00:00.003000000Z\",\"version\":1,\"totalDocuments\":1,\"totalBytes\":379}}154{\"documentMetadata\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"readTime\":\"1970-01-01T00:00:00.003000000Z\",\"exists\":true}}219{\"document\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"createTime\":\"1970-01-01T00:00:00.001999000Z\",\"updateTime\":\"1970-01-01T00:00:00.002999000Z\",\"fields\":{\"value\":{\"stringValue\":\"b\"}}}}", + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "modified": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "b" + }, + "version": 2999 + } + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Newer docs from bundles should raise snapshot only when Watch catches up with acknowledged writes": { + "describeName": "Listens source options:", + "itName": "Newer docs from bundles should raise snapshot only when Watch catches up with acknowledged writes", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 250 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-250" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 250 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 250 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 250 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "userPatch": [ + "collection/a", + { + "value": "patched" + } + ], + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "modified": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "value": "patched" + }, + "version": 0 + } + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "writeAck": { + "version": 1000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [ + ] + } + } + }, + { + "loadBundle": "127{\"metadata\":{\"id\":\"test-bundle\",\"createTime\":\"1970-01-01T00:00:00.000500000Z\",\"version\":1,\"totalDocuments\":1,\"totalBytes\":379}}154{\"documentMetadata\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"readTime\":\"1970-01-01T00:00:00.000500000Z\",\"exists\":true}}219{\"document\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"createTime\":\"1970-01-01T00:00:00.000250000Z\",\"updateTime\":\"1970-01-01T00:00:00.000500000Z\",\"fields\":{\"value\":{\"stringValue\":\"b\"}}}}" + }, + { + "loadBundle": "127{\"metadata\":{\"id\":\"test-bundle\",\"createTime\":\"1970-01-01T00:00:00.001001000Z\",\"version\":1,\"totalDocuments\":1,\"totalBytes\":388}}154{\"documentMetadata\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"readTime\":\"1970-01-01T00:00:00.001001000Z\",\"exists\":true}}228{\"document\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"createTime\":\"1970-01-01T00:00:00.000250000Z\",\"updateTime\":\"1970-01-01T00:00:00.001001000Z\",\"fields\":{\"value\":{\"stringValue\":\"fromBundle\"}}}}", + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "modified": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "fromBundle" + }, + "version": 1001 + } + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Older deleted docs from bundles should do nothing": { + "describeName": "Listens source options:", + "itName": "Older deleted docs from bundles should do nothing", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "value": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "loadBundle": "127{\"metadata\":{\"id\":\"test-bundle\",\"createTime\":\"1970-01-01T00:00:00.000999000Z\",\"version\":1,\"totalDocuments\":1,\"totalBytes\":158}}155{\"documentMetadata\":{\"name\":\"projects/test-project/databases/(default)/documents/collection/a\",\"readTime\":\"1970-01-01T00:00:00.000999000Z\",\"exists\":false}}" + } + ] + }, + "Primary client should not invoke watch request while all clients are listening to cache": { + "describeName": "Listens source options:", + "itName": "Primary client should not invoke watch request while all clients are listening to cache", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "Query is executed by primary client even if primary client only has listeners sourced from cache": { + "describeName": "Listens source options:", + "itName": "Query is executed by primary client even if primary client only has listeners sourced from cache", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-2000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Query only raises events in participating clients": { + "describeName": "Listens source options:", + "itName": "Query only raises events in participating clients", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 4, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 2, + "drainQueue": true + }, + { + "clientIndex": 2, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 3, + "drainQueue": true + }, + { + "clientIndex": 3, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 2, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 3, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Un-listen to listeners from different source": { + "describeName": "Listens source options:", + "itName": "Un-listen to listeners from different source", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useEagerGCForMemory": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "userSet": [ + "collection/b", + { + "key": "b" + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "key": "b" + }, + "version": 0 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "onSnapshotsInSync fires for multiple listeners": { + "describeName": "Listens source options:", + "itName": "onSnapshotsInSync fires for multiple listeners", + "tags": [ + ], + "config": { + "numClients": 1, + "useEagerGCForMemory": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": 1 + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "options": { + "source": "cache" + }, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "addSnapshotsInSyncListener": true, + "expectedSnapshotsInSyncEvents": 1 + }, + { + "userSet": [ + "collection/a", + { + "v": 2 + } + ], + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "modified": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "v": 2 + }, + "version": 0 + } + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedSnapshotsInSyncEvents": 1 + }, + { + "addSnapshotsInSyncListener": true, + "expectedSnapshotsInSyncEvents": 1 + }, + { + "addSnapshotsInSyncListener": true, + "expectedSnapshotsInSyncEvents": 1 + }, + { + "userSet": [ + "collection/a", + { + "v": 3 + } + ], + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "modified": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "v": 3 + }, + "version": 0 + } + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedSnapshotsInSyncEvents": 3 + }, + { + "removeSnapshotsInSyncListener": true + }, + { + "userSet": [ + "collection/a", + { + "v": 4 + } + ], + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true, + "modified": [ + { + "createTime": 0, + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": true + }, + "value": { + "v": 4 + }, + "version": 0 + } + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedSnapshotsInSyncEvents": 2 + } + ] + } +} diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h index abd965beee3..a63fd66cd1b 100644 --- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h +++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h @@ -35,6 +35,7 @@ @class FIRQuery; @class FIRWriteBatch; @class FSTEventAccumulator; +@class FIRTransaction; NS_ASSUME_NONNULL_BEGIN @@ -113,6 +114,10 @@ extern "C" { - (FIRDocumentReference *)addDocumentRef:(FIRCollectionReference *)ref data:(NSDictionary *)data; +- (void)runTransaction:(FIRFirestore *)db + block:(id _Nullable (^)(FIRTransaction *, NSError **error))block + completion:(nullable void (^)(id _Nullable result, NSError *_Nullable error))completion; + - (void)mergeDocumentRef:(FIRDocumentReference *)ref data:(NSDictionary *)data; - (void)mergeDocumentRef:(FIRDocumentReference *)ref diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm index 6633ed03748..f42d10bcb01 100644 --- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm +++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm @@ -569,6 +569,22 @@ - (FIRDocumentReference *)addDocumentRef:(FIRCollectionReference *)ref return doc; } +- (void)runTransaction:(FIRFirestore *)db + block:(id _Nullable (^)(FIRTransaction *, NSError **error))block + completion: + (nullable void (^)(id _Nullable result, NSError *_Nullable error))completion { + XCTestExpectation *expectation = [self expectationWithDescription:@"runTransaction"]; + [db runTransactionWithOptions:nil + block:block + completion:^(id _Nullable result, NSError *_Nullable error) { + if (completion) { + completion(result, error); + } + [expectation fulfill]; + }]; + [self awaitExpectation:expectation]; +} + - (void)mergeDocumentRef:(FIRDocumentReference *)ref data:(NSDictionary *)data { XCTestExpectation *expectation = [self expectationWithDescription:@"setDataWithMerge"]; [ref setData:data merge:YES completion:[self completionForExpectation:expectation]]; diff --git a/Firestore/Source/API/FIRDocumentReference.mm b/Firestore/Source/API/FIRDocumentReference.mm index b6f326ee8d9..a50a2c7df71 100644 --- a/Firestore/Source/API/FIRDocumentReference.mm +++ b/Firestore/Source/API/FIRDocumentReference.mm @@ -27,6 +27,7 @@ #import "Firestore/Source/API/FIRFirestoreSource+Internal.h" #import "Firestore/Source/API/FIRListenerRegistration+Internal.h" #import "Firestore/Source/API/FSTUserDataReader.h" +#import "Firestore/Source/API/converters.h" #include "Firestore/core/src/api/collection_reference.h" #include "Firestore/core/src/api/document_reference.h" @@ -50,6 +51,7 @@ using firebase::firestore::api::DocumentSnapshotListener; using firebase::firestore::api::Firestore; using firebase::firestore::api::ListenerRegistration; +using firebase::firestore::api::MakeListenSource; using firebase::firestore::api::MakeSource; using firebase::firestore::api::Source; using firebase::firestore::core::EventListener; @@ -212,6 +214,13 @@ - (void)getDocumentWithSource:(FIRFirestoreSource)source return [self addSnapshotListenerInternalWithOptions:options listener:listener]; } +- (id)addSnapshotListenerWithOptions:(FIRSnapshotListenOptions *)options + listener:(FIRDocumentSnapshotBlock)listener { + ListenOptions listenOptions = + ListenOptions::FromOptions(options.includeMetadataChanges, MakeListenSource(options.source)); + return [self addSnapshotListenerInternalWithOptions:listenOptions listener:listener]; +} + - (id)addSnapshotListenerInternalWithOptions:(ListenOptions)internalOptions listener:(FIRDocumentSnapshotBlock) listener { diff --git a/Firestore/Source/API/FIRQuery.mm b/Firestore/Source/API/FIRQuery.mm index 98518183049..d4185488341 100644 --- a/Firestore/Source/API/FIRQuery.mm +++ b/Firestore/Source/API/FIRQuery.mm @@ -37,6 +37,7 @@ #import "Firestore/Source/API/FIRQuerySnapshot+Internal.h" #import "Firestore/Source/API/FIRSnapshotMetadata+Internal.h" #import "Firestore/Source/API/FSTUserDataReader.h" +#import "Firestore/Source/API/converters.h" #include "Firestore/core/src/api/query_core.h" #include "Firestore/core/src/api/query_listener_registration.h" @@ -69,6 +70,7 @@ using firebase::firestore::google_firestore_v1_Value; using firebase::firestore::google_firestore_v1_Value_fields; using firebase::firestore::api::Firestore; +using firebase::firestore::api::MakeListenSource; using firebase::firestore::api::Query; using firebase::firestore::api::QueryListenerRegistration; using firebase::firestore::api::QuerySnapshot; @@ -191,6 +193,13 @@ - (void)getDocumentsWithSource:(FIRFirestoreSource)publicSource return [self addSnapshotListenerInternalWithOptions:options listener:listener]; } +- (id)addSnapshotListenerWithOptions:(FIRSnapshotListenOptions *)options + listener:(FIRQuerySnapshotBlock)listener { + ListenOptions listenOptions = + ListenOptions::FromOptions(options.includeMetadataChanges, MakeListenSource(options.source)); + return [self addSnapshotListenerInternalWithOptions:listenOptions listener:listener]; +} + - (id)addSnapshotListenerInternalWithOptions:(ListenOptions)internalOptions listener: (FIRQuerySnapshotBlock)listener { diff --git a/Firestore/Source/API/FIRSnapshotListenOptions.mm b/Firestore/Source/API/FIRSnapshotListenOptions.mm new file mode 100644 index 00000000000..9e22d686428 --- /dev/null +++ b/Firestore/Source/API/FIRSnapshotListenOptions.mm @@ -0,0 +1,63 @@ +/* + * Copyright 2024 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 "FIRSnapshotListenOptions.h" + +#import + +#include +#include + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRSnapshotListenOptions + +- (instancetype)initPrivate:(FIRListenSource)source + includeMetadataChanges:(BOOL)includeMetadataChanges { + self = [self init]; + if (self) { + _source = source; + _includeMetadataChanges = includeMetadataChanges; + } + return self; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _source = FIRListenSourceDefault; + _includeMetadataChanges = NO; + } + return self; +} + +- (FIRSnapshotListenOptions *)optionsWithIncludeMetadataChanges:(BOOL)includeMetadataChanges { + FIRSnapshotListenOptions *newOptions = + [[FIRSnapshotListenOptions alloc] initPrivate:self.source + includeMetadataChanges:includeMetadataChanges]; + return newOptions; +} + +- (FIRSnapshotListenOptions *)optionsWithSource:(FIRListenSource)source { + FIRSnapshotListenOptions *newOptions = + [[FIRSnapshotListenOptions alloc] initPrivate:source + includeMetadataChanges:self.includeMetadataChanges]; + return newOptions; +} + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/Firestore/Source/API/converters.h b/Firestore/Source/API/converters.h index f5d0e4545b8..e777ba81a2c 100644 --- a/Firestore/Source/API/converters.h +++ b/Firestore/Source/API/converters.h @@ -24,6 +24,8 @@ #import #include +#import "FIRSnapshotListenOptions.h" +#import "Firestore/core/src/api/listen_source.h" @class FIRGeoPoint; @class FIRTimestamp; @@ -62,6 +64,8 @@ FIRTimestamp* MakeFIRTimestamp(const Timestamp& timestamp); FIRDocumentReference* MakeFIRDocumentReference(const model::DocumentKey& document_key, std::shared_ptr firestore); +ListenSource MakeListenSource(const FIRListenSource& source); + } // namespace api } // namespace firestore } // namespace firebase diff --git a/Firestore/Source/API/converters.mm b/Firestore/Source/API/converters.mm index 251d3e578bf..8bfd5a07090 100644 --- a/Firestore/Source/API/converters.mm +++ b/Firestore/Source/API/converters.mm @@ -25,6 +25,7 @@ #include "Firestore/core/include/firebase/firestore/geo_point.h" #include "Firestore/core/include/firebase/firestore/timestamp.h" #include "Firestore/core/src/api/firestore.h" +#import "Firestore/core/src/api/listen_source.h" #include "Firestore/core/src/model/document_key.h" NS_ASSUME_NONNULL_BEGIN @@ -61,6 +62,17 @@ Timestamp MakeTimestamp(NSDate* date) { return [[FIRDocumentReference alloc] initWithKey:key firestore:std::move(firestore)]; } +ListenSource MakeListenSource(const FIRListenSource& source) { + switch (source) { + case FIRListenSourceDefault: + return ListenSource::Default; + case FIRListenSourceCache: + return ListenSource::Cache; + default: + return ListenSource::Default; + } +} + } // namespace api } // namespace firestore } // namespace firebase diff --git a/Firestore/Source/Public/FirebaseFirestore/FIRDocumentReference.h b/Firestore/Source/Public/FirebaseFirestore/FIRDocumentReference.h index 70dbd0d02ad..b6f87450cb3 100644 --- a/Firestore/Source/Public/FirebaseFirestore/FIRDocumentReference.h +++ b/Firestore/Source/Public/FirebaseFirestore/FIRDocumentReference.h @@ -18,6 +18,7 @@ #import "FIRFirestoreSource.h" #import "FIRListenerRegistration.h" +#import "FIRSnapshotListenOptions.h" @class FIRCollectionReference; @class FIRDocumentSnapshot; @@ -270,6 +271,22 @@ addSnapshotListenerWithIncludeMetadataChanges:(BOOL)includeMetadataChanges NS_SWIFT_NAME(addSnapshotListener(includeMetadataChanges:listener:)); // clang-format on +/** + * Attaches a listener for `DocumentSnapshot` events. + * + * @param options Sets snapshot listener options, including whether metadata-only changes should + * trigger snapshot events, the source to listen to, the executor to use to call the + * listener, or the activity to scope the listener to. + * @param listener The listener to attach. + * + * @return A `ListenerRegistration` that can be used to remove this listener. + */ +- (id) + addSnapshotListenerWithOptions:(FIRSnapshotListenOptions *)options + listener:(void (^)(FIRDocumentSnapshot *_Nullable snapshot, + NSError *_Nullable error))listener + NS_SWIFT_NAME(addSnapshotListener(options:listener:)); + @end NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Public/FirebaseFirestore/FIRQuery.h b/Firestore/Source/Public/FirebaseFirestore/FIRQuery.h index bde102c212a..c75952876a2 100644 --- a/Firestore/Source/Public/FirebaseFirestore/FIRQuery.h +++ b/Firestore/Source/Public/FirebaseFirestore/FIRQuery.h @@ -18,6 +18,7 @@ #import "FIRFirestoreSource.h" #import "FIRListenerRegistration.h" +#import "FIRSnapshotListenOptions.h" @class FIRAggregateQuery; @class FIRAggregateField; @@ -104,6 +105,21 @@ NS_SWIFT_NAME(Query) NSError *_Nullable error))listener NS_SWIFT_NAME(addSnapshotListener(includeMetadataChanges:listener:)); +/** + * Attaches a listener for `QuerySnapshot` events. + * @param options Sets snapshot listener options, including whether metadata-only changes should + * trigger snapshot events, the source to listen to, the executor to use to call the + * listener, or the activity to scope the listener to. + * @param listener The listener to attach. + * + * @return A `ListenerRegistration` that can be used to remove this listener. + */ +- (id) + addSnapshotListenerWithOptions:(FIRSnapshotListenOptions *)options + listener:(void (^)(FIRQuerySnapshot *_Nullable snapshot, + NSError *_Nullable error))listener + NS_SWIFT_NAME(addSnapshotListener(options:listener:)); + #pragma mark - Filtering Data /** * Creates and returns a new Query with the additional filter. diff --git a/Firestore/Source/Public/FirebaseFirestore/FIRSnapshotListenOptions.h b/Firestore/Source/Public/FirebaseFirestore/FIRSnapshotListenOptions.h new file mode 100644 index 00000000000..13d9903abef --- /dev/null +++ b/Firestore/Source/Public/FirebaseFirestore/FIRSnapshotListenOptions.h @@ -0,0 +1,83 @@ +/* + * Copyright 2024 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 + +NS_ASSUME_NONNULL_BEGIN + +/** + * The source the snapshot listener retrieves data from. + */ +typedef NS_ENUM(NSUInteger, FIRListenSource) { + /** + * The default behavior. The listener attempts to return initial snapshot from cache and retrieve + * up-to-date snapshots from the Firestore server. Snapshot events will be triggered on local + * mutations and server-side updates. + */ + FIRListenSourceDefault, + /** + * The listener retrieves data and listens to updates from the local Firestore cache without + * attempting to send the query to the server. If some documents gets updated as a result from + * other queries, they will be picked up by listeners using the cache. + * + * Note that the data might be stale if the cache hasn't synchronized with recent server-side + * changes. + */ + FIRListenSourceCache +} NS_SWIFT_NAME(ListenSource); + +/** + * Options to configure the behavior of `Firestore.addSnapshotListenerWithOptions()`. Instances + * of this class control settings like whether metadata-only changes trigger events and the + * preferred data source. + */ +NS_SWIFT_NAME(SnapshotListenOptions) +@interface FIRSnapshotListenOptions : NSObject + +/** The source the snapshot listener retrieves data from. */ +@property(nonatomic, readonly) FIRListenSource source; +/** Indicates whether metadata-only changes should trigger snapshot events. */ +@property(nonatomic, readonly) BOOL includeMetadataChanges; + +/** + * Creates and returns a new `SnapshotListenOptions` object with all properties initialized to their + * default values. + * + * @return The created `SnapshotListenOptions` object. + */ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** + * Creates and returns a new `SnapshotListenOptions` object with with all properties of the current + * `SnapshotListenOptions` object plus the new property specifying whether metadata-only changes + * should trigger snapshot events + * + * @return The created `SnapshotListenOptions` object. + */ +- (FIRSnapshotListenOptions *)optionsWithIncludeMetadataChanges:(BOOL)includeMetadataChanges; + +/** + * Creates and returns a new `SnapshotListenOptions` object with with all properties of the current + * `SnapshotListenOptions` object plus the new property specifying the source that the snapshot + * listener listens to. + * + * @return The created `SnapshotListenOptions` object. + */ +- (FIRSnapshotListenOptions *)optionsWithSource:(FIRListenSource)source; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Public/FirebaseFirestore/FirebaseFirestore.h b/Firestore/Source/Public/FirebaseFirestore/FirebaseFirestore.h index 6746aa489e8..9a0574a8207 100644 --- a/Firestore/Source/Public/FirebaseFirestore/FirebaseFirestore.h +++ b/Firestore/Source/Public/FirebaseFirestore/FirebaseFirestore.h @@ -34,6 +34,7 @@ #import "FIRLocalCacheSettings.h" #import "FIRQuery.h" #import "FIRQuerySnapshot.h" +#import "FIRSnapshotListenOptions.h" #import "FIRSnapshotMetadata.h" #import "FIRTimestamp.h" #import "FIRTransaction.h" diff --git a/Firestore/Swift/Tests/BridgingHeader.h b/Firestore/Swift/Tests/BridgingHeader.h index 5bfed83adf4..58165c82944 100644 --- a/Firestore/Swift/Tests/BridgingHeader.h +++ b/Firestore/Swift/Tests/BridgingHeader.h @@ -18,6 +18,7 @@ #define FIRESTORE_SWIFT_TESTS_BRIDGINGHEADER_H_ #import "Firestore/Example/Tests/API/FSTAPIHelpers.h" +#import "Firestore/Example/Tests/Util/FSTEventAccumulator.h" #import "Firestore/Example/Tests/Util/FSTExceptionCatcher.h" #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h" diff --git a/Firestore/Swift/Tests/Integration/SnapshotListenerSourceTests.swift b/Firestore/Swift/Tests/Integration/SnapshotListenerSourceTests.swift new file mode 100644 index 00000000000..22c69679224 --- /dev/null +++ b/Firestore/Swift/Tests/Integration/SnapshotListenerSourceTests.swift @@ -0,0 +1,684 @@ +/* + * Copyright 2024 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 FirebaseFirestore +import FirebaseFirestoreSwift +import Foundation + +@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) +class SnapshotListenerSourceTests: FSTIntegrationTestCase { + func assertQuerySnapshotDataEquals(_ snapshot: Any, + _ expectedData: [[String: Any]]) throws { + let extractedData = FIRQuerySnapshotGetData(snapshot as! QuerySnapshot) + guard extractedData.count == expectedData.count else { + XCTFail( + "Result count mismatch: Expected \(expectedData.count), got \(extractedData.count)" + ) + return + } + for index in 0 ..< extractedData.count { + XCTAssertTrue(areDictionariesEqual(extractedData[index], expectedData[index])) + } + } + + // TODO(swift testing): update the function to be able to check other value types as well. + func areDictionariesEqual(_ dict1: [String: Any], _ dict2: [String: Any]) -> Bool { + guard dict1.count == dict2.count + else { return false } // Check if the number of elements matches + + for (key, value1) in dict1 { + guard let value2 = dict2[key] else { return false } + + // Value Checks (Assuming consistent types after the type check) + if let str1 = value1 as? String, let str2 = value2 as? String { + if str1 != str2 { return false } + } else if let int1 = value1 as? Int, let int2 = value2 as? Int { + if int1 != int2 { return false } + } else { + // Handle other potential types or return false for mismatch + return false + } + } + return true + } + + func testCanRaiseSnapshotFromCacheForQuery() throws { + let collRef = collectionRef(withDocuments: ["a": ["k": "a"]]) + readDocumentSet(forRef: collRef) // populate the cache. + + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let registration = collRef.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + + let querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "a"]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + eventAccumulator.assertNoAdditionalEvents() + registration.remove() + } + + func testCanRaiseSnapshotFromCacheForDocumentReference() throws { + let docRef = documentRef() + docRef.setData(["k": "a"]) + readDocument(forRef: docRef) // populate the cache. + + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let registration = docRef.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + + let docSnap = eventAccumulator.awaitEvent(withName: "snapshot") as! DocumentSnapshot + XCTAssertEqual(docSnap.data() as! [String: String], ["k": "a"]) + XCTAssertEqual(docSnap.metadata.isFromCache, true) + + eventAccumulator.assertNoAdditionalEvents() + registration.remove() + } + + func testListenToCacheShouldNotBeAffectedByOnlineStatusChange() throws { + let collRef = collectionRef(withDocuments: ["a": ["k": "a"]]) + readDocumentSet(forRef: collRef) // populate the cache. + + let options = SnapshotListenOptions().withSource(ListenSource.cache) + .withIncludeMetadataChanges(true) + let registration = collRef.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + + let querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "a"]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + disableNetwork() + enableNetwork() + + eventAccumulator.assertNoAdditionalEvents() + registration.remove() + } + + func testMultipleListenersSourcedFromCacheCanWorkIndependently() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + readDocumentSet(forRef: collRef) // populate the cache. + + let query = collRef.whereField("sort", isGreaterThan: 0).order(by: "sort") + + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let registration1 = query.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + let registration2 = query.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + + var expected = [["k": "b", "sort": 1]] + var querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + // Do a local mutation + addDocumentRef(collRef, data: ["k": "c", "sort": 2]) + + expected = [["k": "b", "sort": 1], ["k": "c", "sort": 2]] + querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + // Detach one listener, and do a local mutation. The other listener + // should not be affected. + registration1.remove() + addDocumentRef(collRef, data: ["k": "d", "sort": 3]) + + expected = [["k": "b", "sort": 1], ["k": "c", "sort": 2], ["k": "d", "sort": 3]] + querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + eventAccumulator.assertNoAdditionalEvents() + registration2.remove() + } + + // Two queries that mapped to the same target ID are referred to as + // "mirror queries". An example for a mirror query is a limitToLast() + // query and a limit() query that share the same backend Target ID. + // Since limitToLast() queries are sent to the backend with a modified + // orderBy() clause, they can map to the same target representation as + // limit() query, even if both queries appear separate to the user. + func testListenUnlistenRelistenToMirrorQueriesFromCache() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + "c": ["k": "c", "sort": 1], + ]) + readDocumentSet(forRef: collRef) // populate the cache. + let options = SnapshotListenOptions().withSource(ListenSource.cache) + + // Setup a `limit` query. + let limit = collRef.order(by: "sort", descending: false).limit(to: 2) + let limitAccumulator = FSTEventAccumulator.init(forTest: self) + var limitRegistration = limit.addSnapshotListener( + options: options, + listener: limitAccumulator.valueEventHandler + ) + // Setup a mirroring `limitToLast` query. + let limitToLast = collRef.order(by: "sort", descending: true).limit(toLast: 2) + let limitToLastAccumulator = FSTEventAccumulator + .init(forTest: self) + var limitToLastRegistration = limitToLast.addSnapshotListener( + options: options, + listener: limitToLastAccumulator.valueEventHandler + ) + + // Verify both queries get expected result. + var querySnap = limitAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "a", "sort": 0], ["k": "b", "sort": 1]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + querySnap = limitToLastAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "b", "sort": 1], ["k": "a", "sort": 0]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + // Un-listen then re-listen to the limit query. + limitRegistration.remove() + limitRegistration = limit.addSnapshotListener( + options: options, + listener: limitAccumulator.valueEventHandler + ) + querySnap = limitAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals( + querySnap, + [["k": "a", "sort": 0], ["k": "b", "sort": 1]] + ) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + // Add a document that would change the result set. + addDocumentRef(collRef, data: ["k": "d", "sort": -1]) + + // Verify both queries get expected result. + querySnap = limitAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "d", "sort": -1], ["k": "a", "sort": 0]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + XCTAssertEqual(querySnap.metadata.hasPendingWrites, true) + querySnap = limitToLastAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "a", "sort": 0], ["k": "d", "sort": -1]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + XCTAssertEqual(querySnap.metadata.hasPendingWrites, true) + + // Un-listen to limitToLast, update a doc, then re-listen to limitToLast + limitToLastRegistration.remove() + updateDocumentRef(collRef.document("a"), data: ["k": "a", "sort": -2]) + limitToLastRegistration = limitToLast.addSnapshotListener( + options: options, + listener: limitToLastAccumulator.valueEventHandler + ) + + // Verify both queries get expected result. + querySnap = limitAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "a", "sort": -2], ["k": "d", "sort": -1]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + XCTAssertEqual(querySnap.metadata.hasPendingWrites, true) + querySnap = limitToLastAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "d", "sort": -1], ["k": "a", "sort": -2]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + // We listened to LimitToLast query after the doc update. + XCTAssertEqual(querySnap.metadata.hasPendingWrites, false) + } + + func testCanListenToDefaultSourceFirstAndThenCache() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + let query = collRef.whereField("sort", isGreaterThanOrEqualTo: 1).order(by: "sort") + + // Listen to the query with default options, which will also populates the cache + let defaultAccumulator = FSTEventAccumulator.init(forTest: self) + let defaultRegistration = query.addSnapshotListener(defaultAccumulator.valueEventHandler) + + var querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "b", "sort": 1]]) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + // Listen to the same query from cache + let cacheAccumulator = FSTEventAccumulator + .init(forTest: self) + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "b", "sort": 1]]) + // The metadata is sync with server due to the default listener + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + defaultAccumulator.assertNoAdditionalEvents() + cacheAccumulator.assertNoAdditionalEvents() + defaultRegistration.remove() + cacheRegistration.remove() + } + + func testCanListenToCacheSourceFirstAndThenDefault() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + let query = collRef.whereField("sort", isNotEqualTo: 0).order(by: "sort") + + // Listen to the cache + let cacheAccumulator = FSTEventAccumulator + .init(forTest: self) + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + var querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + // Cache is empty + try assertQuerySnapshotDataEquals(querySnap, []) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + // Listen to the same query from server + let defaultAccumulator = FSTEventAccumulator.init(forTest: self) + let defaultRegistration = query.addSnapshotListener(defaultAccumulator.valueEventHandler) + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "b", "sort": 1]]) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + // Default listener updates the cache, whish triggers cache listener to raise snapshot. + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "b", "sort": 1]]) + // The metadata is sync with server due to the default listener + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + defaultAccumulator.assertNoAdditionalEvents() + cacheAccumulator.assertNoAdditionalEvents() + defaultRegistration.remove() + cacheRegistration.remove() + } + + func testWillNotGetMetadataOnlyUpdatesIfListeningToCacheOnly() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + readDocumentSet(forRef: collRef) // populate the cache. + + let query = collRef.whereField("sort", isNotEqualTo: 0).order(by: "sort") + let options = SnapshotListenOptions().withSource(ListenSource.cache) + + let registration = query.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + + var querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "b", "sort": 1]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + // Do a local mutation + addDocumentRef(collRef, data: ["k": "c", "sort": 2]) + + querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "b", "sort": 1], ["k": "c", "sort": 2]]) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + XCTAssertEqual(querySnap.metadata?.hasPendingWrites, true) + + // As we are not listening to server, the listener will not get notified + // when local mutation is acknowledged by server. + eventAccumulator.assertNoAdditionalEvents() + registration.remove() + } + + func testWillHaveSynceMetadataUpdatesWhenListeningToBothCacheAndDefaultSource() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + readDocumentSet(forRef: collRef) // populate the cache. + let query = collRef.whereField("sort", isNotEqualTo: 0).order(by: "sort") + + // Listen to the cache + let cacheAccumulator = FSTEventAccumulator.init(forTest: self) + let options = SnapshotListenOptions().withSource(ListenSource.cache) + .withIncludeMetadataChanges(true) + let cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + var querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + var expected = [["k": "b", "sort": 1]] + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + // Listen to the same query from server + let defaultAccumulator = FSTEventAccumulator.init(forTest: self) + let defaultRegistration = query.addSnapshotListener( + includeMetadataChanges: true, + listener: defaultAccumulator.valueEventHandler + ) + + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + // First snapshot will be raised from cache. + XCTAssertEqual(querySnap.metadata.isFromCache, true) + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + // Second snapshot will be raised from server result + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + // As listening to metadata changes, the cache listener also gets triggered and synced + // with default listener. + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + // The metadata is sync with server due to the default listener + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + // Do a local mutation + addDocumentRef(collRef, data: ["k": "c", "sort": 2]) + + // snapshot gets triggered by local mutation + expected = [["k": "b", "sort": 1], ["k": "c", "sort": 2]] + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.hasPendingWrites, true) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.hasPendingWrites, true) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + // Local mutation gets acknowledged by the server + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + XCTAssertEqual(querySnap.metadata.hasPendingWrites, false) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + XCTAssertEqual(querySnap.metadata.hasPendingWrites, false) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + defaultAccumulator.assertNoAdditionalEvents() + cacheAccumulator.assertNoAdditionalEvents() + defaultRegistration.remove() + cacheRegistration.remove() + } + + func testCanUnlistenToDefaultSourceWhileStillListeningToCache() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + let query = collRef.whereField("sort", isNotEqualTo: 0).order(by: "sort") + + // Listen to the query with both source options + let defaultAccumulator = FSTEventAccumulator.init(forTest: self) + let defaultRegistration = query.addSnapshotListener(defaultAccumulator.valueEventHandler) + defaultAccumulator.awaitEvent(withName: "snapshot") + let cacheAccumulator = FSTEventAccumulator + .init(forTest: self) + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + cacheAccumulator.awaitEvent(withName: "snapshot") + + // Un-listen to the default listener. + defaultRegistration.remove() + + // Add a document and verify listener to cache works as expected + addDocumentRef(collRef, data: ["k": "c", "sort": -1]) + defaultAccumulator.assertNoAdditionalEvents() + + let querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals( + querySnap, + [["k": "c", "sort": -1], ["k": "b", "sort": 1]] + ) + + cacheAccumulator.assertNoAdditionalEvents() + cacheRegistration.remove() + } + + func testCanUnlistenToCacheSourceWhileStillListeningToServer() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + let query = collRef.whereField("sort", isNotEqualTo: 0).order(by: "sort") + + // Listen to the query with both source options + let defaultAccumulator = FSTEventAccumulator.init(forTest: self) + let defaultRegistration = query.addSnapshotListener(defaultAccumulator.valueEventHandler) + defaultAccumulator.awaitEvent(withName: "snapshot") + let cacheAccumulator = FSTEventAccumulator + .init(forTest: self) + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + cacheAccumulator.awaitEvent(withName: "snapshot") + + // Un-listen to cache. + cacheRegistration.remove() + + // Add a document and verify listener to server works as expected. + addDocumentRef(collRef, data: ["k": "c", "sort": -1]) + cacheAccumulator.assertNoAdditionalEvents() + + let querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals( + querySnap, + [["k": "c", "sort": -1], ["k": "b", "sort": 1]] + ) + + defaultAccumulator.assertNoAdditionalEvents() + defaultRegistration.remove() + } + + func testCanListenUnlistenRelistenToSameQueryWithDifferentSourceOptions() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + let query = collRef.whereField("sort", isGreaterThan: 0).order(by: "sort") + + // Listen to the query with default options, which will also populates the cache + let defaultAccumulator = FSTEventAccumulator.init(forTest: self) + var defaultRegistration = query.addSnapshotListener(defaultAccumulator.valueEventHandler) + var querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + var expected = [["k": "b", "sort": 1]] + try assertQuerySnapshotDataEquals(querySnap, expected) + + // Listen to the same query from cache + let cacheAccumulator = FSTEventAccumulator + .init(forTest: self) + let options = SnapshotListenOptions().withSource(ListenSource.cache) + var cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + + // Un-listen to the default listener, add a doc and re-listen. + defaultRegistration.remove() + addDocumentRef(collRef, data: ["k": "c", "sort": 2]) + + expected = [["k": "b", "sort": 1], ["k": "c", "sort": 2]] + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + + defaultRegistration = query.addSnapshotListener(defaultAccumulator.valueEventHandler) + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + + // Un-listen to cache, update a doc, then re-listen to cache. + cacheRegistration.remove() + updateDocumentRef(collRef.document("b"), data: ["k": "b", "sort": 3]) + + expected = [["k": "c", "sort": 2], ["k": "b", "sort": 3]] + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals( + querySnap, expected + ) + + cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals( + querySnap, expected + ) + + defaultAccumulator.assertNoAdditionalEvents() + cacheAccumulator.assertNoAdditionalEvents() + defaultRegistration.remove() + cacheRegistration.remove() + } + + func testCanListenToCompositeIndexQueriesFromCache() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + readDocumentSet(forRef: collRef) // populate the cache. + + let query = collRef.whereField("k", isLessThanOrEqualTo: "a") + .whereField("sort", isGreaterThanOrEqualTo: 0) + + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let registration = query.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + + let querySnap = eventAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, [["k": "a", "sort": 0]]) + + eventAccumulator.assertNoAdditionalEvents() + registration.remove() + } + + func testCanRaiseInitialSnapshotFromCachedEmptyResults() throws { + let collRef = collectionRef() + + // Populate the cache with empty query result. + var querySnap = readDocumentSet(forRef: collRef) + try assertQuerySnapshotDataEquals(querySnap, []) + + // Add a snapshot listener whose first event should be raised from cache. + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let registration = collRef.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + + querySnap = eventAccumulator.awaitEvent(withName: "initial event") as! QuerySnapshot + try assertQuerySnapshotDataEquals(querySnap, []) + XCTAssertEqual(querySnap.metadata.isFromCache, true) + + eventAccumulator.assertNoAdditionalEvents() + registration.remove() + } + + func testWillNotBeTriggeredByTransactionsWhileListeningToCache() throws { + let collRef = collectionRef() + + // Add a snapshot listener whose first event should be raised from cache. + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let registration = collRef.addSnapshotListener( + options: options, + listener: eventAccumulator.valueEventHandler + ) + let querySnap = eventAccumulator.awaitEvent(withName: "initial event") + try assertQuerySnapshotDataEquals(querySnap, []) + + let docRef = documentRef() + // Use a transaction to perform a write without triggering any local events. + runTransaction(docRef.firestore, block: { transaction, errorPointer -> Any? in + transaction.updateData(["K": "a"], forDocument: docRef) + return nil + }) + + // There should be no events raised + eventAccumulator.assertNoAdditionalEvents() + registration.remove() + } + + func testSharesServerSideUpdatesWhenListeningToBothCacheAndDefault() throws { + let collRef = collectionRef(withDocuments: [ + "a": ["k": "a", "sort": 0], + "b": ["k": "b", "sort": 1], + ]) + let query = collRef.whereField("sort", isGreaterThan: 0).order(by: "sort") + + // Listen to the query with default options, which will also populates the cache + let defaultAccumulator = FSTEventAccumulator.init(forTest: self) + let defaultRegistration = query.addSnapshotListener(defaultAccumulator.valueEventHandler) + var querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + var expected = [["k": "b", "sort": 1]] + try assertQuerySnapshotDataEquals(querySnap, expected) + + // Listen to the same query from cache + let cacheAccumulator = FSTEventAccumulator + .init(forTest: self) + let options = SnapshotListenOptions().withSource(ListenSource.cache) + let cacheRegistration = query.addSnapshotListener( + options: options, + listener: cacheAccumulator.valueEventHandler + ) + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + + // Use a transaction to mock server side updates + let docRef = collRef.document() + runTransaction(docRef.firestore, block: { transaction, errorPointer -> Any? in + transaction.setData(["k": "c", "sort": 2], forDocument: docRef) + return nil + }) + + // Default listener receives the server update + querySnap = defaultAccumulator.awaitEvent(withName: "snapshot") + expected = [["k": "b", "sort": 1], ["k": "c", "sort": 2]] + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + // Cache listener raises snapshot as well + querySnap = cacheAccumulator.awaitEvent(withName: "snapshot") + try assertQuerySnapshotDataEquals(querySnap, expected) + XCTAssertEqual(querySnap.metadata.isFromCache, false) + + defaultAccumulator.assertNoAdditionalEvents() + cacheAccumulator.assertNoAdditionalEvents() + defaultRegistration.remove() + cacheRegistration.remove() + } +} diff --git a/Firestore/core/src/api/listen_source.h b/Firestore/core/src/api/listen_source.h new file mode 100644 index 00000000000..2053a92df39 --- /dev/null +++ b/Firestore/core/src/api/listen_source.h @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Google + * + * 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. + */ + +#ifndef FIRESTORE_CORE_SRC_API_LISTEN_SOURCE_H_ +#define FIRESTORE_CORE_SRC_API_LISTEN_SOURCE_H_ + +namespace firebase { +namespace firestore { +namespace api { + +/** + * An enum that configures the snapshot listener data source. Using this enum, + * specify whether snapshot events are triggered by local cache changes + * only, or from both local cache and watch changes(which is the default). + * + * See `FIRFirestoreListenSource` for more details. + */ +enum class ListenSource { Default, Cache }; + +} // namespace api +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_API_LISTEN_SOURCE_H_ diff --git a/Firestore/core/src/core/event_manager.cc b/Firestore/core/src/core/event_manager.cc index 283a8341076..d5c3f3542b9 100644 --- a/Firestore/core/src/core/event_manager.cc +++ b/Firestore/core/src/core/event_manager.cc @@ -37,11 +37,27 @@ EventManager::EventManager(QueryEventSource* query_event_source) model::TargetId EventManager::AddQueryListener( std::shared_ptr listener) { const Query& query = listener->query(); + ListenerSetupAction listener_action = + ListenerSetupAction::NoSetupActionRequired; auto inserted = queries_.emplace(query, QueryListenersInfo{}); + // If successfully inserted, it means we haven't listened to this query + // before. bool first_listen = inserted.second; QueryListenersInfo& query_info = inserted.first->second; + if (first_listen) { + listener_action = listener->listens_to_remote_store() + ? ListenerSetupAction:: + InitializeLocalListenAndRequireWatchConnection + : ListenerSetupAction::InitializeLocalListenOnly; + } else if (!query_info.has_remote_listeners() && + listener->listens_to_remote_store()) { + // Query has been listening to local cache, and tries to add a new listener + // sourced from watch. + listener_action = ListenerSetupAction::RequireWatchConnectionOnly; + } + query_info.listeners.push_back(listener); bool raised_event = listener->OnOnlineStateChanged(online_state_); @@ -56,8 +72,20 @@ model::TargetId EventManager::AddQueryListener( } } - if (first_listen) { - query_info.target_id = query_event_source_->Listen(query); + switch (listener_action) { + case ListenerSetupAction::InitializeLocalListenAndRequireWatchConnection: + query_info.target_id = query_event_source_->Listen( + query, /** should_listen_to_remote= */ true); + break; + case ListenerSetupAction::InitializeLocalListenOnly: + query_info.target_id = query_event_source_->Listen( + query, /** should_listen_to_remote= */ false); + break; + case ListenerSetupAction::RequireWatchConnectionOnly: + query_event_source_->ListenToRemoteStore(query); + break; + default: + break; } return query_info.target_id; } @@ -65,18 +93,41 @@ model::TargetId EventManager::AddQueryListener( void EventManager::RemoveQueryListener( std::shared_ptr listener) { const Query& query = listener->query(); - bool last_listen = false; + ListenerRemovalAction listener_action = + ListenerRemovalAction::NoRemovalActionRequired; auto found_iter = queries_.find(query); if (found_iter != queries_.end()) { QueryListenersInfo& query_info = found_iter->second; query_info.Erase(listener); - last_listen = query_info.listeners.empty(); + + if (query_info.listeners.empty()) { + listener_action = + listener->listens_to_remote_store() + ? ListenerRemovalAction:: + TerminateLocalListenAndRequireWatchDisconnection + : ListenerRemovalAction::TerminateLocalListenOnly; + } else if (!query_info.has_remote_listeners() && + listener->listens_to_remote_store()) { + // The removed listener is the last one that sourced from watch. + listener_action = ListenerRemovalAction::RequireWatchDisconnectionOnly; + } } - if (last_listen) { - queries_.erase(found_iter); - query_event_source_->StopListening(query); + switch (listener_action) { + case ListenerRemovalAction:: + TerminateLocalListenAndRequireWatchDisconnection: + queries_.erase(found_iter); + return query_event_source_->StopListening( + query, /** should_stop_remote_listening= */ true); + case ListenerRemovalAction::TerminateLocalListenOnly: + queries_.erase(found_iter); + return query_event_source_->StopListening( + query, /** should_stop_remote_listening= */ false); + case ListenerRemovalAction::RequireWatchDisconnectionOnly: + return query_event_source_->StopListeningToRemoteStoreOnly(query); + default: + return; } } diff --git a/Firestore/core/src/core/event_manager.h b/Firestore/core/src/core/event_manager.h index ba4f2ee56e9..9ee783a85bd 100644 --- a/Firestore/core/src/core/event_manager.h +++ b/Firestore/core/src/core/event_manager.h @@ -23,6 +23,7 @@ #include #include "Firestore/core/src/core/query.h" +#include "Firestore/core/src/core/query_listener.h" #include "Firestore/core/src/core/sync_engine_callback.h" #include "Firestore/core/src/core/view_snapshot.h" #include "Firestore/core/src/model/model_fwd.h" @@ -35,7 +36,6 @@ namespace firestore { namespace core { class QueryEventSource; -class QueryListener; /** * EventManager is responsible for mapping queries to query event listeners. @@ -97,12 +97,35 @@ class EventManager : public SyncEngineCallback { snapshot_ = snapshot; } + bool has_remote_listeners() { + for (const auto& listener : listeners) { + if (listener->listens_to_remote_store()) { + return true; + } + } + return false; + } + private: // Other members are public in this struct, ensure that any reads are // copies by requiring reads to go through a const getter. absl::optional snapshot_; }; + enum ListenerSetupAction { + InitializeLocalListenAndRequireWatchConnection = 0, + InitializeLocalListenOnly = 1, + RequireWatchConnectionOnly = 2, + NoSetupActionRequired = 3 + }; + + enum ListenerRemovalAction { + TerminateLocalListenAndRequireWatchDisconnection = 0, + TerminateLocalListenOnly = 1, + RequireWatchDisconnectionOnly = 2, + NoRemovalActionRequired = 3 + }; + QueryEventSource* query_event_source_ = nullptr; model::OnlineState online_state_ = model::OnlineState::Unknown; std::unordered_map queries_; diff --git a/Firestore/core/src/core/listen_options.h b/Firestore/core/src/core/listen_options.h index cf76d872878..2499b75e224 100644 --- a/Firestore/core/src/core/listen_options.h +++ b/Firestore/core/src/core/listen_options.h @@ -17,10 +17,14 @@ #ifndef FIRESTORE_CORE_SRC_CORE_LISTEN_OPTIONS_H_ #define FIRESTORE_CORE_SRC_CORE_LISTEN_OPTIONS_H_ +#include +#include "Firestore/core/src/api/listen_source.h" namespace firebase { namespace firestore { namespace core { +using api::ListenSource; + class ListenOptions { public: ListenOptions() = default; @@ -44,14 +48,36 @@ class ListenOptions { } /** - * Creates a default ListenOptions, with metadata changes and - * wait_for_sync_when_online disabled. + * Creates a new ListenOptions. + * + * @param include_query_metadata_changes Raise events when only metadata of + * the query changes. + * @param include_document_metadata_changes Raise events when only metadata of + * documents changes. + * @param wait_for_sync_when_online Wait for a sync with the server when + * online, but still raise events while offline. + * @param source sets the source a snapshot listener listens to. + */ + ListenOptions(bool include_query_metadata_changes, + bool include_document_metadata_changes, + bool wait_for_sync_when_online, + ListenSource source) + : include_query_metadata_changes_(include_query_metadata_changes), + include_document_metadata_changes_(include_document_metadata_changes), + wait_for_sync_when_online_(wait_for_sync_when_online), + source_(std::move(source)) { + } + + /** + * Creates a default ListenOptions, with metadata changes, + * wait_for_sync_when_online disabled, and listen source set to default. */ static ListenOptions DefaultOptions() { return ListenOptions( /*include_query_metadata_changes=*/false, /*include_document_metadata_changes=*/false, - /*wait_for_sync_when_online=*/false); + /*wait_for_sync_when_online=*/false, + /*source=*/ListenSource::Default); } /** @@ -63,7 +89,19 @@ class ListenOptions { return ListenOptions( /*include_query_metadata_changes=*/include_metadata_changes, /*include_document_metadata_changes=*/include_metadata_changes, - /*wait_for_sync_when_online=*/false); + /*wait_for_sync_when_online=*/false, + /*source=*/ListenSource::Default); + } + + /** + * Creates a ListenOptions which sets the source snapshot listener listens to. + */ + static ListenOptions FromOptions(bool include_metadata_changes, + ListenSource source) { + return ListenOptions( + /*include_query_metadata_changes=*/include_metadata_changes, + /*include_document_metadata_changes=*/include_metadata_changes, + /*wait_for_sync_when_online=*/false, std::move(source)); } bool include_query_metadata_changes() const { @@ -78,10 +116,15 @@ class ListenOptions { return wait_for_sync_when_online_; } + ListenSource source() const { + return source_; + } + private: bool include_query_metadata_changes_ = false; bool include_document_metadata_changes_ = false; bool wait_for_sync_when_online_ = false; + ListenSource source_ = ListenSource::Default; }; } // namespace core diff --git a/Firestore/core/src/core/query_listener.cc b/Firestore/core/src/core/query_listener.cc index 3e0cbb2cceb..c0ec38e752a 100644 --- a/Firestore/core/src/core/query_listener.cc +++ b/Firestore/core/src/core/query_listener.cc @@ -136,6 +136,11 @@ bool QueryListener::ShouldRaiseInitialEvent(const ViewSnapshot& snapshot, return true; } + // Always raise first event if listening to cache + if (!listens_to_remote_store()) { + return true; + } + // NOTE: We consider OnlineState::Unknown as online (it should become Offline // or Online if we wait long enough). bool maybe_online = online_state != OnlineState::Offline; diff --git a/Firestore/core/src/core/query_listener.h b/Firestore/core/src/core/query_listener.h index eec5ada73b8..6b934a0de59 100644 --- a/Firestore/core/src/core/query_listener.h +++ b/Firestore/core/src/core/query_listener.h @@ -63,6 +63,10 @@ class QueryListener { return query_; } + bool listens_to_remote_store() const { + return options_.source() != ListenSource::Cache; + } + /** The last received view snapshot. */ const absl::optional& snapshot() const { return snapshot_; diff --git a/Firestore/core/src/core/sync_engine.cc b/Firestore/core/src/core/sync_engine.cc index 24a4c3f7803..77223cb1fed 100644 --- a/Firestore/core/src/core/sync_engine.cc +++ b/Firestore/core/src/core/sync_engine.cc @@ -104,7 +104,7 @@ void SyncEngine::AssertCallbackExists(absl::string_view source) { "Tried to call '%s' before callback was registered.", source); } -TargetId SyncEngine::Listen(Query query) { +TargetId SyncEngine::Listen(Query query, bool should_listen_to_remote) { AssertCallbackExists("Listen"); HARD_ASSERT(query_views_by_query_.find(query) == query_views_by_query_.end(), @@ -121,7 +121,9 @@ TargetId SyncEngine::Listen(Query query) { snapshots.push_back(std::move(view_snapshot)); sync_engine_callback_->OnViewSnapshots(std::move(snapshots)); - remote_store_->Listen(std::move(target_data)); + if (should_listen_to_remote) { + remote_store_->Listen(std::move(target_data)); + } return target_id; } @@ -161,22 +163,48 @@ ViewSnapshot SyncEngine::InitializeViewAndComputeSnapshot( return view_change.snapshot().value(); } -void SyncEngine::StopListening(const Query& query) { +void SyncEngine::ListenToRemoteStore(Query query) { + AssertCallbackExists("ListenToRemoteStore"); + TargetData target_data = local_store_->AllocateTarget(query.ToTarget()); + remote_store_->Listen(std::move(target_data)); +} + +void SyncEngine::StopListening(const Query& query, + bool should_stop_remote_listening) { AssertCallbackExists("StopListening"); + StopListeningAndReleaseTarget(query, /** last_listen= */ true, + should_stop_remote_listening); +} + +void SyncEngine::StopListeningToRemoteStoreOnly(const Query& query) { + AssertCallbackExists("StopListeningToRemoteStoreOnly"); + StopListeningAndReleaseTarget(query, /** last_listen= */ false, + /** should_stop_remote_listening= */ true); +} +void SyncEngine::StopListeningAndReleaseTarget( + const Query& query, bool last_listen, bool should_stop_remote_listening) { auto query_view = query_views_by_query_[query]; HARD_ASSERT(query_view, "Trying to stop listening to a query not found"); - query_views_by_query_.erase(query); + if (last_listen) { + query_views_by_query_.erase(query); + } + // One target could have multiple queries mapped to it. TargetId target_id = query_view->target_id(); auto& queries = queries_by_target_[target_id]; queries.erase(std::remove(queries.begin(), queries.end(), query), queries.end()); - if (queries.empty()) { - local_store_->ReleaseTarget(target_id); + if (!queries.empty()) return; + + if (should_stop_remote_listening) { remote_store_->StopListening(target_id); + } + + if (last_listen) { + local_store_->ReleaseTarget(target_id); RemoveAndCleanupTarget(target_id, Status::OK()); } } diff --git a/Firestore/core/src/core/sync_engine.h b/Firestore/core/src/core/sync_engine.h index e8bfc028d02..bcf930fdd0c 100644 --- a/Firestore/core/src/core/sync_engine.h +++ b/Firestore/core/src/core/sync_engine.h @@ -70,16 +70,33 @@ class QueryEventSource { /** * Initiates a new listen. The LocalStore will be queried for initial data - * and the listen will be sent to the `RemoteStore` to get remote data. The - * registered SyncEngineCallback will be notified of resulting view + * and the listen will be sent to the RemoteStore if the query is listening to + * watch. The registered SyncEngineCallback will be notified of resulting view * snapshots and/or listen errors. * * @return the target ID assigned to the query. */ - virtual model::TargetId Listen(Query query) = 0; + virtual model::TargetId Listen(Query query, bool should_listen_to_remote) = 0; - /** Stops listening to a query previously listened to via `Listen`. */ - virtual void StopListening(const Query& query) = 0; + /** + * Sends the listen to the RemoteStore to get remote data. Invoked when a + * Query starts listening to the remote store, while already listening to the + * cache. + */ + virtual void ListenToRemoteStore(Query query) = 0; + + /** + * Stops listening to a query previously listened to via `Listen`. Un-listen + * to remote store if there is a watch connection established and stayed open. + */ + virtual void StopListening(const Query& query, + bool should_stop_remote_listening) = 0; + + /** + * Stops listening to a query from watch. Invoked when a Query stops listening + * to the remote store, while still listening to the cache. + */ + virtual void StopListeningToRemoteStoreOnly(const Query& query) = 0; }; /** @@ -107,8 +124,12 @@ class SyncEngine : public remote::RemoteStoreCallback, public QueryEventSource { void SetCallback(SyncEngineCallback* callback) override { sync_engine_callback_ = callback; } - model::TargetId Listen(Query query) override; - void StopListening(const Query& query) override; + model::TargetId Listen(Query query, + bool should_listen_to_remote = true) override; + void ListenToRemoteStore(Query query) override; + void StopListening(const Query& query, + bool should_stop_remote_listening = true) override; + void StopListeningToRemoteStoreOnly(const Query& query) override; /** * Initiates the write of local mutation batch which involves adding the @@ -244,6 +265,9 @@ class SyncEngine : public remote::RemoteStoreCallback, public QueryEventSource { nanopb::ByteString resume_token); void RemoveAndCleanupTarget(model::TargetId target_id, util::Status status); + void StopListeningAndReleaseTarget(const Query& query, + bool should_stop_remote_listening, + bool last_listen); void RemoveLimboTarget(const model::DocumentKey& key); diff --git a/Firestore/core/test/unit/core/event_manager_test.cc b/Firestore/core/test/unit/core/event_manager_test.cc index 9229dae919e..5d48a9aae0c 100644 --- a/Firestore/core/test/unit/core/event_manager_test.cc +++ b/Firestore/core/test/unit/core/event_manager_test.cc @@ -57,11 +57,21 @@ std::shared_ptr NoopQueryListener(core::Query query) { NoopViewSnapshotHandler()); } +std::shared_ptr NoopQueryCacheListener(core::Query query) { + return QueryListener::Create( + std::move(query), + ListenOptions::FromOptions(/** include_metadata_changes= */ false, + ListenSource::Cache), + NoopViewSnapshotHandler()); +} + class MockEventSource : public core::QueryEventSource { public: MOCK_METHOD1(SetCallback, void(core::SyncEngineCallback*)); - MOCK_METHOD1(Listen, model::TargetId(core::Query)); - MOCK_METHOD1(StopListening, void(const core::Query&)); + MOCK_METHOD2(Listen, model::TargetId(core::Query, bool)); + MOCK_METHOD1(ListenToRemoteStore, void(core::Query)); + MOCK_METHOD2(StopListening, void(const core::Query&, bool)); + MOCK_METHOD1(StopListeningToRemoteStoreOnly, void(const core::Query&)); }; TEST(EventManagerTest, HandlesManyListnersPerQuery) { @@ -73,14 +83,34 @@ TEST(EventManagerTest, HandlesManyListnersPerQuery) { EXPECT_CALL(mock_event_source, SetCallback(_)); EventManager event_manager(&mock_event_source); - EXPECT_CALL(mock_event_source, Listen(query)); + EXPECT_CALL(mock_event_source, Listen(query, true)); + event_manager.AddQueryListener(listener1); + + // Expecting no activity from mock_event_source. + event_manager.AddQueryListener(listener2); + event_manager.RemoveQueryListener(listener2); + + EXPECT_CALL(mock_event_source, StopListening(query, true)); + event_manager.RemoveQueryListener(listener1); +} + +TEST(EventManagerTest, HandlesManyCacheListnersPerQuery) { + core::Query query = Query("foo/bar"); + auto listener1 = NoopQueryCacheListener(query); + auto listener2 = NoopQueryCacheListener(query); + + StrictMock mock_event_source; + EXPECT_CALL(mock_event_source, SetCallback(_)); + EventManager event_manager(&mock_event_source); + + EXPECT_CALL(mock_event_source, Listen(query, false)); event_manager.AddQueryListener(listener1); // Expecting no activity from mock_event_source. event_manager.AddQueryListener(listener2); event_manager.RemoveQueryListener(listener2); - EXPECT_CALL(mock_event_source, StopListening(query)); + EXPECT_CALL(mock_event_source, StopListening(query, false)); event_manager.RemoveQueryListener(listener1); } @@ -91,7 +121,7 @@ TEST(EventManagerTest, HandlesUnlistenOnUnknownListenerGracefully) { MockEventSource mock_event_source; EventManager event_manager(&mock_event_source); - EXPECT_CALL(mock_event_source, StopListening(_)).Times(0); + EXPECT_CALL(mock_event_source, StopListening(_, true)).Times(0); event_manager.RemoveQueryListener(listener); } @@ -128,10 +158,10 @@ TEST(EventManagerTest, NotifiesListenersInTheRightOrder) { MockEventSource mock_event_source; EventManager event_manager(&mock_event_source); - EXPECT_CALL(mock_event_source, Listen(query1)); + EXPECT_CALL(mock_event_source, Listen(query1, true)); event_manager.AddQueryListener(listener1); - EXPECT_CALL(mock_event_source, Listen(query2)); + EXPECT_CALL(mock_event_source, Listen(query2, true)); event_manager.AddQueryListener(listener2); event_manager.AddQueryListener(listener3); From 90c33e404f515834fe4c753cc940fe22deed77b5 Mon Sep 17 00:00:00 2001 From: themiswang Date: Mon, 11 Mar 2024 16:13:04 -0400 Subject: [PATCH 13/25] [Rollouts] Feature rollouts merge to main (#12410) --- CoreOnly/Tests/FirebasePodTest/Podfile | 1 + Crashlytics/CHANGELOG.md | 1 + .../Components/FIRCLSUserLogging.h | 4 +- .../Components/FIRCLSUserLogging.m | 16 +- .../FIRCLSRolloutsPersistenceManager.h | 30 + .../FIRCLSRolloutsPersistenceManager.m | 67 ++ Crashlytics/Crashlytics/FIRCrashlytics.m | 51 +- .../Crashlytics/Handlers/FIRCLSException.h | 5 +- .../Crashlytics/Handlers/FIRCLSException.mm | 41 +- .../Crashlytics/Models/FIRCLSInternalReport.h | 1 + .../Crashlytics/Models/FIRCLSInternalReport.m | 1 + .../CrashlyticsRemoteConfigManager.swift | 141 +++ .../Rollouts/EncodedRolloutAssignment.swift | 44 + .../Rollouts/StringToHexConverter.swift | 38 + Crashlytics/UnitTests/FIRCLSFileTests.m | 31 + Crashlytics/UnitTests/FIRCLSLoggingTests.m | 10 +- .../FIRCLSRolloutsPersistenceManagerTests.m | 70 ++ .../UnitTests/FIRRecordExceptionModelTests.m | 2 +- .../CrashlyticsRemoteConfigManagerTests.swift | 136 +++ Example/watchOSSample/Podfile | 1 + FirebaseCrashlytics.podspec | 6 +- FirebaseRemoteConfig.podspec | 4 +- FirebaseRemoteConfig/CHANGELOG.md | 3 + .../Interop/RemoteConfigConstants.swift | 21 + .../Interop/RemoteConfigInterop.swift | 21 + .../Interop/RolloutAssignment.swift | 47 + .../Interop/RolloutsStateSubscriber.swift | 20 + .../Sources/FIRRemoteConfig.m | 106 +- .../Sources/FIRRemoteConfigComponent.h | 8 +- .../Sources/FIRRemoteConfigComponent.m | 49 +- .../Sources/Private/FIRRemoteConfig_Private.h | 4 + .../Sources/Private/RCNConfigSettings.h | 9 +- .../Sources/RCNConfigConstants.h | 12 +- .../Sources/RCNConfigContent.h | 5 + .../Sources/RCNConfigContent.m | 112 +- .../Sources/RCNConfigDBManager.h | 14 +- .../Sources/RCNConfigDBManager.m | 122 +- .../Sources/RCNConfigDefines.h | 2 + FirebaseRemoteConfig/Sources/RCNConfigFetch.m | 5 +- .../Sources/RCNConfigSettings.m | 11 +- FirebaseRemoteConfig/Sources/RCNConstants3P.m | 1 + .../Sources/RCNUserDefaultsManager.h | 4 +- .../Sources/RCNUserDefaultsManager.m | 19 +- .../project.pbxproj | 1059 +++++++++++++++++ .../FeatureRolloutsTestApp/ContentView.swift | 29 + .../FeatureRolloutsTestApp.entitlements | 10 + .../ContentView.swift | 27 + .../ContentView.swift | 26 + .../ContentView.swift | 25 + .../Tests/FeatureRolloutsTestApp/Podfile | 52 + .../Shared/CrashButtonView.swift | 62 + .../Shared/FeatureRolloutsTestAppApp.swift | 31 + .../Shared/RemoteConfigButtonView.swift | 51 + FirebaseRemoteConfig/Tests/Sample/Podfile | 1 + .../RemoteConfigSampleApp/ViewController.m | 9 +- .../SwiftUnit/RemoteConfigInteropTests.swift | 65 + .../Tests/Unit/FIRRemoteConfigComponentTest.m | 43 +- .../Tests/Unit/RCNConfigContentTest.m | 209 +++- .../Tests/Unit/RCNConfigDBManagerTest.m | 165 ++- .../Tests/Unit/RCNConfigTest.m | 33 +- .../Tests/Unit/RCNInstanceIDTest.m | 4 +- .../Tests/Unit/RCNRemoteConfigTest.m | 65 +- .../Tests/Unit/RCNThrottlingTests.m | 23 +- .../Tests/Unit/RCNUserDefaultsManagerTests.m | 27 +- .../generate_featureRolloutsTestApp.sh | 58 + FirebaseRemoteConfigInterop.podspec | 34 + ...ebaseRemoteConfigSwift_APIBuildTests.swift | 1 + FirebaseSessions/Tests/TestApp/Podfile | 1 + IntegrationTesting/ClientApp/Podfile | 1 + .../Podfile | 1 + Package.swift | 48 +- .../FirebaseManifest/FirebaseManifest.swift | 1 + scripts/localize_podfile.swift | 1 + 73 files changed, 3281 insertions(+), 177 deletions(-) create mode 100644 Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h create mode 100644 Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.m create mode 100644 Crashlytics/Crashlytics/Rollouts/CrashlyticsRemoteConfigManager.swift create mode 100644 Crashlytics/Crashlytics/Rollouts/EncodedRolloutAssignment.swift create mode 100644 Crashlytics/Crashlytics/Rollouts/StringToHexConverter.swift create mode 100644 Crashlytics/UnitTests/FIRCLSRolloutsPersistenceManagerTests.m create mode 100644 Crashlytics/UnitTestsSwift/CrashlyticsRemoteConfigManagerTests.swift create mode 100644 FirebaseRemoteConfig/Interop/RemoteConfigConstants.swift create mode 100644 FirebaseRemoteConfig/Interop/RemoteConfigInterop.swift create mode 100644 FirebaseRemoteConfig/Interop/RolloutAssignment.swift create mode 100644 FirebaseRemoteConfig/Interop/RolloutsStateSubscriber.swift create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp.xcodeproj/project.pbxproj create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/ContentView.swift create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/FeatureRolloutsTestApp.entitlements create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/ContentView.swift create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_Crashlytics_iOS/ContentView.swift create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_RemoteConfig_iOS/ContentView.swift create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Podfile create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/CrashButtonView.swift create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/FeatureRolloutsTestAppApp.swift create mode 100644 FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/RemoteConfigButtonView.swift create mode 100644 FirebaseRemoteConfig/Tests/SwiftUnit/RemoteConfigInteropTests.swift create mode 100755 FirebaseRemoteConfig/generate_featureRolloutsTestApp.sh create mode 100644 FirebaseRemoteConfigInterop.podspec diff --git a/CoreOnly/Tests/FirebasePodTest/Podfile b/CoreOnly/Tests/FirebasePodTest/Podfile index dfe7a0fa557..1e7dacbdb17 100644 --- a/CoreOnly/Tests/FirebasePodTest/Podfile +++ b/CoreOnly/Tests/FirebasePodTest/Podfile @@ -33,6 +33,7 @@ target 'FirebasePodTest' do pod 'FirebaseAppCheckInterop', :path => '../../../' pod 'FirebaseAuthInterop', :path => '../../../' pod 'FirebaseMessagingInterop', :path => '../../../' + pod 'FirebaseRemoteConfigInterop', :path => '../../../' pod 'FirebaseCoreInternal', :path => '../../../' pod 'FirebaseCoreExtension', :path => '../../../' pod 'FirebaseSessions', :path => '../../../' diff --git a/Crashlytics/CHANGELOG.md b/Crashlytics/CHANGELOG.md index 2c06843fcea..62f507a7c01 100644 --- a/Crashlytics/CHANGELOG.md +++ b/Crashlytics/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased - [added] Updated upload-symbols to 13.7 with VisionPro build phase support. (#12306) +- [changed] Added support for Crashlytics to report metadata about Remote Config keys and values. # 10.22.0 - [fixed] Force validation or rotation of FIDs for FirebaseSessions. diff --git a/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h b/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h index e0cadd483fb..0b2aa3922f8 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h +++ b/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h @@ -81,7 +81,9 @@ void FIRCLSUserLoggingRecordUserKeysAndValues(NSDictionary* keysAndValues); void FIRCLSUserLoggingRecordInternalKeyValue(NSString* key, id value); void FIRCLSUserLoggingWriteInternalKeyValue(NSString* key, NSString* value); -void FIRCLSUserLoggingRecordError(NSError* error, NSDictionary* additionalUserInfo); +void FIRCLSUserLoggingRecordError(NSError* error, + NSDictionary* additionalUserInfo, + NSString* rolloutsInfoJSON); NSDictionary* FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage* storage, bool decodeHex); diff --git a/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m b/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m index 31b4deef1e9..4da93b43450 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m @@ -355,7 +355,8 @@ static void FIRCLSUserLoggingWriteError(FIRCLSFile *file, NSError *error, NSDictionary *additionalUserInfo, NSArray *addresses, - uint64_t timestamp) { + uint64_t timestamp, + NSString *rolloutsInfoJSON) { FIRCLSFileWriteSectionStart(file, "error"); FIRCLSFileWriteHashStart(file); FIRCLSFileWriteHashEntryHexEncodedString(file, "domain", [[error domain] UTF8String]); @@ -374,12 +375,20 @@ static void FIRCLSUserLoggingWriteError(FIRCLSFile *file, FIRCLSUserLoggingRecordErrorUserInfo(file, "info", [error userInfo]); FIRCLSUserLoggingRecordErrorUserInfo(file, "extra_info", additionalUserInfo); + // rollouts + if (rolloutsInfoJSON) { + FIRCLSFileWriteHashKey(file, "rollouts"); + FIRCLSFileWriteStringUnquoted(file, [rolloutsInfoJSON UTF8String]); + FIRCLSFileWriteHashEnd(file); + } + FIRCLSFileWriteHashEnd(file); FIRCLSFileWriteSectionEnd(file); } void FIRCLSUserLoggingRecordError(NSError *error, - NSDictionary *additionalUserInfo) { + NSDictionary *additionalUserInfo, + NSString *rolloutsInfoJSON) { if (!error) { return; } @@ -396,7 +405,8 @@ void FIRCLSUserLoggingRecordError(NSError *error, FIRCLSUserLoggingWriteAndCheckABFiles( &_firclsContext.readonly->logging.errorStorage, &_firclsContext.writable->logging.activeErrorLogPath, ^(FIRCLSFile *file) { - FIRCLSUserLoggingWriteError(file, error, additionalUserInfo, addresses, timestamp); + FIRCLSUserLoggingWriteError(file, error, additionalUserInfo, addresses, timestamp, + rolloutsInfoJSON); }); } diff --git a/Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h b/Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h new file mode 100644 index 00000000000..bda6eabbf5e --- /dev/null +++ b/Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h @@ -0,0 +1,30 @@ +// Copyright 2024 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. + +#if SWIFT_PACKAGE +@import FirebaseCrashlyticsSwift; +#else // Swift Package Manager +#import +#endif // CocoaPods + +@interface FIRCLSRolloutsPersistenceManager : NSObject + +- (instancetype _Nullable)initWithFileManager:(FIRCLSFileManager *_Nonnull)fileManager; +- (instancetype _Nonnull)init NS_UNAVAILABLE; ++ (instancetype _Nonnull)new NS_UNAVAILABLE; + +- (void)updateRolloutsStateToPersistenceWithRollouts:(NSData *_Nonnull)rollouts + reportID:(NSString *_Nonnull)reportID; +- (void)debugLogWithMessage:(NSString *_Nonnull)message; +@end diff --git a/Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.m b/Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.m new file mode 100644 index 00000000000..3e7867dab76 --- /dev/null +++ b/Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.m @@ -0,0 +1,67 @@ +// Copyright 2024 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 +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" + +#if SWIFT_PACKAGE +@import FirebaseCrashlyticsSwift; +#else // Swift Package Manager +#import +#endif // CocoaPods + +@interface FIRCLSRolloutsPersistenceManager : NSObject +@property(nonatomic, readonly) FIRCLSFileManager *fileManager; +@end + +@implementation FIRCLSRolloutsPersistenceManager +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager { + self = [super init]; + if (!self) { + return nil; + } + _fileManager = fileManager; + return self; +} + +- (void)updateRolloutsStateToPersistenceWithRollouts:(NSData *_Nonnull)rollouts + reportID:(NSString *_Nonnull)reportID { + NSString *rolloutsPath = [[[_fileManager activePath] stringByAppendingPathComponent:reportID] + stringByAppendingPathComponent:FIRCLSReportRolloutsFile]; + if (![_fileManager fileExistsAtPath:rolloutsPath]) { + if (![_fileManager createFileAtPath:rolloutsPath contents:nil attributes:nil]) { + FIRCLSDebugLog(@"Could not create rollouts.clsrecord file. Error was code: %d - message: %s", + errno, strerror(errno)); + } + } + + NSFileHandle *rolloutsFile = [NSFileHandle fileHandleForUpdatingAtPath:rolloutsPath]; + + dispatch_sync(FIRCLSGetLoggingQueue(), ^{ + [rolloutsFile seekToEndOfFile]; + [rolloutsFile writeData:rollouts]; + NSData *newLineData = [@"\n" dataUsingEncoding:NSUTF8StringEncoding]; + [rolloutsFile writeData:newLineData]; + }); +} + +- (void)debugLogWithMessage:(NSString *_Nonnull)message { + FIRCLSDebugLog(message); +} + +@end diff --git a/Crashlytics/Crashlytics/FIRCrashlytics.m b/Crashlytics/Crashlytics/FIRCrashlytics.m index 4d112cddad4..85502b2a9d9 100644 --- a/Crashlytics/Crashlytics/FIRCrashlytics.m +++ b/Crashlytics/Crashlytics/FIRCrashlytics.m @@ -31,6 +31,7 @@ #import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" #include "Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h" #include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h" #import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" #import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" #import "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h" @@ -47,6 +48,7 @@ #import "Crashlytics/Crashlytics/Controllers/FIRCLSNotificationManager.h" #import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h" #import "Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h" +#import "Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h" #import "Crashlytics/Crashlytics/Private/FIRCLSExistingReportManager_Private.h" #import "Crashlytics/Crashlytics/Private/FIRCLSOnDemandModel_Private.h" #import "Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h" @@ -58,6 +60,12 @@ #import @import FirebaseSessions; +@import FirebaseRemoteConfigInterop; +#if SWIFT_PACKAGE +@import FirebaseCrashlyticsSwift; +#else // Swift Package Manager +#import +#endif // CocoaPods #if TARGET_OS_IPHONE #import @@ -76,7 +84,10 @@ @protocol FIRCrashlyticsInstanceProvider @end -@interface FIRCrashlytics () +@interface FIRCrashlytics () @property(nonatomic) BOOL didPreviouslyCrash; @property(nonatomic, copy) NSString *googleAppID; @@ -91,6 +102,8 @@ @interface FIRCrashlytics () )analytics - sessions:(id)sessions { + sessions:(id)sessions + remoteConfig:(id)remoteConfig { self = [super init]; if (self) { @@ -189,8 +203,19 @@ - (instancetype)initWithApp:(FIRApp *)app }] catch:^void(NSError *error) { FIRCLSErrorLog(@"Crash reporting failed to initialize with error: %@", error); }]; - } + // RemoteConfig subscription should be made after session report directory created. + if (remoteConfig) { + FIRCLSDebugLog(@"Registering RemoteConfig SDK subscription for rollouts data"); + + FIRCLSRolloutsPersistenceManager *persistenceManager = + [[FIRCLSRolloutsPersistenceManager alloc] initWithFileManager:_fileManager]; + _remoteConfigManager = + [[FIRCLSRemoteConfigManager alloc] initWithRemoteConfig:remoteConfig + persistenceDelegate:persistenceManager]; + [remoteConfig registerRolloutsStateSubscriber:self for:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform]; + } + } return self; } @@ -215,6 +240,7 @@ + (void)load { id analytics = FIR_COMPONENT(FIRAnalyticsInterop, container); id sessions = FIR_COMPONENT(FIRSessionsProvider, container); + id remoteConfig = FIR_COMPONENT(FIRRemoteConfigInterop, container); FIRInstallations *installations = [FIRInstallations installationsWithApp:container.app]; @@ -224,7 +250,8 @@ + (void)load { appInfo:NSBundle.mainBundle.infoDictionary installations:installations analytics:analytics - sessions:sessions]; + sessions:sessions + remoteConfig:remoteConfig]; }; FIRComponent *component = @@ -377,11 +404,13 @@ - (void)recordError:(NSError *)error { } - (void)recordError:(NSError *)error userInfo:(NSDictionary *)userInfo { - FIRCLSUserLoggingRecordError(error, userInfo); + NSString *rolloutsInfoJSON = [_remoteConfigManager getRolloutAssignmentsEncodedJsonString]; + FIRCLSUserLoggingRecordError(error, userInfo, rolloutsInfoJSON); } - (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel { - FIRCLSExceptionRecordModel(exceptionModel); + NSString *rolloutsInfoJSON = [_remoteConfigManager getRolloutAssignmentsEncodedJsonString]; + FIRCLSExceptionRecordModel(exceptionModel, rolloutsInfoJSON); } - (void)recordOnDemandExceptionModel:(FIRExceptionModel *)exceptionModel { @@ -407,4 +436,14 @@ - (FIRSessionsSubscriberName)sessionsSubscriberName { return FIRSessionsSubscriberNameCrashlytics; } +#pragma mark - FIRRolloutsStateSubscriber +- (void)rolloutsStateDidChange:(FIRRolloutsState *_Nonnull)rolloutsState { + if (!_remoteConfigManager) { + FIRCLSDebugLog(@"rolloutsStateDidChange gets called without init the rc manager."); + return; + } + NSString *currentReportID = _managerData.executionIDModel.executionID; + [_remoteConfigManager updateRolloutsStateWithRolloutsState:rolloutsState + reportID:currentReportID]; +} @end diff --git a/Crashlytics/Crashlytics/Handlers/FIRCLSException.h b/Crashlytics/Crashlytics/Handlers/FIRCLSException.h index ae53b916f8b..65aae9bfd32 100644 --- a/Crashlytics/Crashlytics/Handlers/FIRCLSException.h +++ b/Crashlytics/Crashlytics/Handlers/FIRCLSException.h @@ -60,7 +60,7 @@ void FIRCLSExceptionRaiseTestObjCException(void) __attribute((noreturn)); void FIRCLSExceptionRaiseTestCppException(void) __attribute((noreturn)); #ifdef __OBJC__ -void FIRCLSExceptionRecordModel(FIRExceptionModel* exceptionModel); +void FIRCLSExceptionRecordModel(FIRExceptionModel* exceptionModel, NSString* rolloutsInfoJSON); NSString* FIRCLSExceptionRecordOnDemandModel(FIRExceptionModel* exceptionModel, int previousRecordedOnDemandExceptions, int previousDroppedOnDemandExceptions); @@ -68,7 +68,8 @@ void FIRCLSExceptionRecordNSException(NSException* exception); void FIRCLSExceptionRecord(FIRCLSExceptionType type, const char* name, const char* reason, - NSArray* frames); + NSArray* frames, + NSString* rolloutsInfoJSON); NSString* FIRCLSExceptionRecordOnDemand(FIRCLSExceptionType type, const char* name, const char* reason, diff --git a/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm b/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm index 798a4548ded..b92cd9848dd 100644 --- a/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm +++ b/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm @@ -82,11 +82,11 @@ void FIRCLSExceptionInitialize(FIRCLSExceptionReadOnlyContext *roContext, rwContext->customExceptionCount = 0; } -void FIRCLSExceptionRecordModel(FIRExceptionModel *exceptionModel) { +void FIRCLSExceptionRecordModel(FIRExceptionModel *exceptionModel, NSString *rolloutsInfoJSON) { const char *name = [[exceptionModel.name copy] UTF8String]; const char *reason = [[exceptionModel.reason copy] UTF8String] ?: ""; - - FIRCLSExceptionRecord(FIRCLSExceptionTypeCustom, name, reason, [exceptionModel.stackTrace copy]); + FIRCLSExceptionRecord(FIRCLSExceptionTypeCustom, name, reason, [exceptionModel.stackTrace copy], + rolloutsInfoJSON); } NSString *FIRCLSExceptionRecordOnDemandModel(FIRExceptionModel *exceptionModel, @@ -122,7 +122,7 @@ void FIRCLSExceptionRecordNSException(NSException *exception) { } FIRCLSExceptionRecord(FIRCLSExceptionTypeObjectiveC, [name UTF8String], [reason UTF8String], - frames); + frames, nil); } static void FIRCLSExceptionRecordFrame(FIRCLSFile *file, FIRStackFrame *frame) { @@ -175,7 +175,8 @@ void FIRCLSExceptionWrite(FIRCLSFile *file, FIRCLSExceptionType type, const char *name, const char *reason, - NSArray *frames) { + NSArray *frames, + NSString *rolloutsInfoJSON) { FIRCLSFileWriteSectionStart(file, "exception"); FIRCLSFileWriteHashStart(file); @@ -196,6 +197,12 @@ void FIRCLSExceptionWrite(FIRCLSFile *file, FIRCLSFileWriteArrayEnd(file); } + if (rolloutsInfoJSON) { + FIRCLSFileWriteHashKey(file, "rollouts"); + FIRCLSFileWriteStringUnquoted(file, [rolloutsInfoJSON UTF8String]); + FIRCLSFileWriteHashEnd(file); + } + FIRCLSFileWriteHashEnd(file); FIRCLSFileWriteSectionEnd(file); @@ -204,7 +211,8 @@ void FIRCLSExceptionWrite(FIRCLSFile *file, void FIRCLSExceptionRecord(FIRCLSExceptionType type, const char *name, const char *reason, - NSArray *frames) { + NSArray *frames, + NSString *rolloutsInfoJSON) { if (!FIRCLSContextIsInitialized()) { return; } @@ -224,7 +232,7 @@ void FIRCLSExceptionRecord(FIRCLSExceptionType type, return; } - FIRCLSExceptionWrite(&file, type, name, reason, frames); + FIRCLSExceptionWrite(&file, type, name, reason, frames, nil); // We only want to do this work if we have the expectation that we'll actually crash FIRCLSHandler(&file, mach_thread_self(), NULL); @@ -235,7 +243,7 @@ void FIRCLSExceptionRecord(FIRCLSExceptionType type, FIRCLSUserLoggingWriteAndCheckABFiles( &_firclsContext.readonly->logging.customExceptionStorage, &_firclsContext.writable->logging.activeCustomExceptionPath, ^(FIRCLSFile *file) { - FIRCLSExceptionWrite(file, type, name, reason, frames); + FIRCLSExceptionWrite(file, type, name, reason, frames, rolloutsInfoJSON); }); } @@ -271,6 +279,7 @@ void FIRCLSExceptionRecord(FIRCLSExceptionType type, // Create new report and copy into it the current state of custom keys and log and the sdk.log, // binary_images.clsrecord, and metadata.clsrecord files. + // Also copy rollouts.clsrecord if applicable. NSError *error = nil; BOOL copied = [fileManager.underlyingFileManager copyItemAtPath:currentReportPath toPath:newReportPath @@ -343,7 +352,7 @@ void FIRCLSExceptionRecord(FIRCLSExceptionType type, FIRCLSSDKLog("Unable to open log file for on demand custom exception\n"); return nil; } - FIRCLSExceptionWrite(&file, type, name, reason, frames); + FIRCLSExceptionWrite(&file, type, name, reason, frames, nil); FIRCLSHandler(&file, mach_thread_self(), NULL); FIRCLSFileClose(&file); @@ -397,19 +406,21 @@ static void FIRCLSCatchAndRecordActiveException(std::type_info *typeInfo) { #endif } } catch (const char *exc) { - FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "const char *", exc, nil); + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "const char *", exc, nil, nil); } catch (const std::string &exc) { - FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::string", exc.c_str(), nil); + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::string", exc.c_str(), nil, nil); } catch (const std::exception &exc) { - FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc.what(), nil); + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc.what(), nil, + nil); } catch (const std::exception *exc) { - FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc->what(), nil); + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc->what(), nil, + nil); } catch (const std::bad_alloc &exc) { // it is especially important to avoid demangling in this case, because the expetation at this // point is that all allocations could fail - FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::bad_alloc", exc.what(), nil); + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::bad_alloc", exc.what(), nil, nil); } catch (...) { - FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), "", nil); + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), "", nil, nil); } } diff --git a/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h b/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h index 6303962c667..624c1990ae7 100644 --- a/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h +++ b/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h @@ -36,6 +36,7 @@ extern NSString *const FIRCLSReportInternalIncrementalKVFile; extern NSString *const FIRCLSReportInternalCompactedKVFile; extern NSString *const FIRCLSReportUserIncrementalKVFile; extern NSString *const FIRCLSReportUserCompactedKVFile; +extern NSString *const FIRCLSReportRolloutsFile; @class FIRCLSFileManager; diff --git a/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m b/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m index 61daf92f3e8..35160d1cbc1 100644 --- a/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m +++ b/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m @@ -41,6 +41,7 @@ NSString *const FIRCLSReportInternalCompactedKVFile = @"internal_compacted_kv.clsrecord"; NSString *const FIRCLSReportUserIncrementalKVFile = @"user_incremental_kv.clsrecord"; NSString *const FIRCLSReportUserCompactedKVFile = @"user_compacted_kv.clsrecord"; +NSString *const FIRCLSReportRolloutsFile = @"rollouts.clsrecord"; @interface FIRCLSInternalReport () { NSString *_identifier; diff --git a/Crashlytics/Crashlytics/Rollouts/CrashlyticsRemoteConfigManager.swift b/Crashlytics/Crashlytics/Rollouts/CrashlyticsRemoteConfigManager.swift new file mode 100644 index 00000000000..d6d5cb16b82 --- /dev/null +++ b/Crashlytics/Crashlytics/Rollouts/CrashlyticsRemoteConfigManager.swift @@ -0,0 +1,141 @@ +// 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 FirebaseRemoteConfigInterop +import Foundation + +@objc(FIRCLSPersistenceLog) +public protocol CrashlyticsPersistenceLog { + func updateRolloutsStateToPersistence(rollouts: Data, reportID: String) + func debugLog(message: String) +} + +@objc(FIRCLSRemoteConfigManager) +public class CrashlyticsRemoteConfigManager: NSObject { + public static let maxRolloutAssignments = 128 + public static let maxParameterValueLength = 256 + + private let lock = NSLock() + private var _rolloutAssignment: [RolloutAssignment] = [] + + var remoteConfig: RemoteConfigInterop + var persistenceDelegate: CrashlyticsPersistenceLog + + @objc public var rolloutAssignment: [RolloutAssignment] { + lock.lock() + defer { lock.unlock() } + let copy = _rolloutAssignment + return copy + } + + @objc public init(remoteConfig: RemoteConfigInterop, + persistenceDelegate: CrashlyticsPersistenceLog) { + self.remoteConfig = remoteConfig + self.persistenceDelegate = persistenceDelegate + } + + @objc public func updateRolloutsState(rolloutsState: RolloutsState, reportID: String) { + lock.lock() + _rolloutAssignment = normalizeRolloutAssignment(assignments: Array(rolloutsState.assignments)) + lock.unlock() + + // Writring to persistence + if let rolloutsData = + getRolloutsStateEncodedJsonData() { + persistenceDelegate.updateRolloutsStateToPersistence( + rollouts: rolloutsData, + reportID: reportID + ) + } + } + + /// Return string format: [{RolloutAssignment1}, {RolloutAssignment2}, {RolloutAssignment3}...] + /// This will get inserted into each clsrcord for non-fatal events. + /// Return a string type because later `FIRCLSFileWriteStringUnquoted` takes string as input + @objc public func getRolloutAssignmentsEncodedJsonString() -> String? { + let encodeData = getRolloutAssignmentsEncodedJsonData() + if let data = encodeData { + return String(data: data, encoding: .utf8) + } + + let debugInfo = encodeData?.debugDescription ?? "nil" + persistenceDelegate.debugLog(message: String( + format: "Failed to serialize rollouts: %@", + arguments: [debugInfo] + )) + + return nil + } +} + +private extension CrashlyticsRemoteConfigManager { + func normalizeRolloutAssignment(assignments: [RolloutAssignment]) -> [RolloutAssignment] { + var validatedAssignments = assignments + if assignments.count > CrashlyticsRemoteConfigManager.maxRolloutAssignments { + persistenceDelegate + .debugLog( + message: "Rollouts excess the maximum number of assignments can pass to Crashlytics" + ) + validatedAssignments = + Array(assignments[.. CrashlyticsRemoteConfigManager.maxParameterValueLength { + debugPrint( + "Rollouts excess the maximum length of parameter value can pass to Crashlytics", + assignment.parameterValue + ) + let upperBound = String.Index( + utf16Offset: CrashlyticsRemoteConfigManager.maxParameterValueLength, + in: assignment.parameterValue + ) + let slicedParameterValue = assignment.parameterValue[.. Data? { + let contentEncodedRolloutAssignments = rolloutAssignment.map { assignment in + EncodedRolloutAssignment(assignment: assignment) + } + + let encoder = JSONEncoder() + encoder.keyEncodingStrategy = .convertToSnakeCase + encoder.outputFormatting = .sortedKeys + let encodeData = try? encoder.encode(contentEncodedRolloutAssignments) + return encodeData + } + + /// Return string format: {"rollouts": [{RolloutAssignment1}, {RolloutAssignment2}, + /// {RolloutAssignment3}...]} + /// This will get stored in the separate rollouts.clsrecord + /// Return a data type because later `[NSFileHandler writeData:]` takes data as input + func getRolloutsStateEncodedJsonData() -> Data? { + let contentEncodedRolloutAssignments = rolloutAssignment.map { assignment in + EncodedRolloutAssignment(assignment: assignment) + } + + let state = EncodedRolloutsState(assignments: contentEncodedRolloutAssignments) + let encoder = JSONEncoder() + encoder.keyEncodingStrategy = .convertToSnakeCase + let encodeData = try? encoder.encode(state) + return encodeData + } +} diff --git a/Crashlytics/Crashlytics/Rollouts/EncodedRolloutAssignment.swift b/Crashlytics/Crashlytics/Rollouts/EncodedRolloutAssignment.swift new file mode 100644 index 00000000000..725b63050ec --- /dev/null +++ b/Crashlytics/Crashlytics/Rollouts/EncodedRolloutAssignment.swift @@ -0,0 +1,44 @@ +// Copyright 2024 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 FirebaseRemoteConfigInterop +import Foundation + +@objc(FIRCLSEncodedRolloutsState) +class EncodedRolloutsState: NSObject, Codable { + @objc public private(set) var rollouts: [EncodedRolloutAssignment] + + @objc public init(assignments: [EncodedRolloutAssignment]) { + rollouts = assignments + super.init() + } +} + +@objc(FIRCLSEncodedRolloutAssignment) +class EncodedRolloutAssignment: NSObject, Codable { + @objc public private(set) var rolloutId: String + @objc public private(set) var variantId: String + @objc public private(set) var templateVersion: Int64 + @objc public private(set) var parameterKey: String + @objc public private(set) var parameterValue: String + + public init(assignment: RolloutAssignment) { + rolloutId = FileUtility.stringToHexConverter(for: assignment.rolloutId) + variantId = FileUtility.stringToHexConverter(for: assignment.variantId) + templateVersion = assignment.templateVersion + parameterKey = FileUtility.stringToHexConverter(for: assignment.parameterKey) + parameterValue = FileUtility.stringToHexConverter(for: assignment.parameterValue) + super.init() + } +} diff --git a/Crashlytics/Crashlytics/Rollouts/StringToHexConverter.swift b/Crashlytics/Crashlytics/Rollouts/StringToHexConverter.swift new file mode 100644 index 00000000000..9d4365db927 --- /dev/null +++ b/Crashlytics/Crashlytics/Rollouts/StringToHexConverter.swift @@ -0,0 +1,38 @@ +// Copyright 2024 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 Foundation + +// This is a swift rewrite for the logic in FIRCLSFile for the function FIRCLSFileHexEncodeString() +@objc(FIRCLSwiftFileUtility) +public class FileUtility: NSObject { + @objc public static func stringToHexConverter(for string: String) -> String { + let hexMap = "0123456789abcdef" + + var processedString = "" + let utf8Array = string.utf8.map { UInt8($0) } + for c in utf8Array { + let index1 = String.Index( + utf16Offset: Int(c >> 4), + in: hexMap + ) + let index2 = String.Index( + utf16Offset: Int(c & 0x0F), + in: hexMap + ) + processedString = processedString + String(hexMap[index1]) + String(hexMap[index2]) + } + return processedString + } +} diff --git a/Crashlytics/UnitTests/FIRCLSFileTests.m b/Crashlytics/UnitTests/FIRCLSFileTests.m index 85ff6c36a57..b8895f68a67 100644 --- a/Crashlytics/UnitTests/FIRCLSFileTests.m +++ b/Crashlytics/UnitTests/FIRCLSFileTests.m @@ -14,6 +14,12 @@ #include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#if SWIFT_PACKAGE +@import FirebaseCrashlyticsSwift; +#else // Swift Package Manager +#import +#endif // CocoaPods + #import @interface FIRCLSFileTests : XCTestCase @@ -169,6 +175,31 @@ - (void)hexEncodingStringWithFile:(FIRCLSFile *)file buffered ? @"" : @"un"); } +// This is the test to compare FIRCLSwiftFileUtility.stringToHexConverter(for:) and +// FIRCLSFileWriteHexEncodedString return the same hex encoding value +- (void)testHexEncodingStringObjcAndSwiftResultsSame { + NSString *testedValueString = @"是themis的测试数据,输入中文"; + + FIRCLSFile *unbufferedFile = &_unbufferedFile; + FIRCLSFileWriteHashStart(unbufferedFile); + FIRCLSFileWriteHashEntryHexEncodedString(unbufferedFile, "hex", [testedValueString UTF8String]); + FIRCLSFileWriteHashEnd(unbufferedFile); + NSString *contentsFromObjcHexEncoding = [self contentsOfFileAtPath:self.unbufferedPath]; + + FIRCLSFile *bufferedFile = &_bufferedFile; + NSString *encodedValue = [FIRCLSwiftFileUtility stringToHexConverterFor:testedValueString]; + FIRCLSFileWriteHashStart(bufferedFile); + FIRCLSFileWriteHashKey(bufferedFile, "hex"); + FIRCLSFileWriteStringUnquoted(bufferedFile, "\""); + FIRCLSFileWriteStringUnquoted(bufferedFile, [encodedValue UTF8String]); + FIRCLSFileWriteStringUnquoted(bufferedFile, "\""); + FIRCLSFileWriteHashEnd(bufferedFile); + FIRCLSFileFlushWriteBuffer(bufferedFile); + NSString *contentsFromSwiftHexEncoding = [self contentsOfFileAtPath:self.bufferedPath]; + + XCTAssertTrue([contentsFromObjcHexEncoding isEqualToString:contentsFromSwiftHexEncoding]); +} + #pragma mark - - (void)testHexEncodingLongString { diff --git a/Crashlytics/UnitTests/FIRCLSLoggingTests.m b/Crashlytics/UnitTests/FIRCLSLoggingTests.m index a5c72f5c73c..b79341fe06e 100644 --- a/Crashlytics/UnitTests/FIRCLSLoggingTests.m +++ b/Crashlytics/UnitTests/FIRCLSLoggingTests.m @@ -365,7 +365,7 @@ - (void)testLoggedError { code:-1 userInfo:@{@"key1" : @"value", @"key2" : @"value2"}]; - FIRCLSUserLoggingRecordError(error, @{@"additional" : @"key"}); + FIRCLSUserLoggingRecordError(error, @{@"additional" : @"key"}, nil); NSArray* errors = [self errorAContents]; @@ -405,7 +405,7 @@ - (void)testWritingMaximumNumberOfLoggedErrors { userInfo:@{@"key1" : @"value", @"key2" : @"value2"}]; for (size_t i = 0; i < _firclsContext.readonly->logging.errorStorage.maxEntries; ++i) { - FIRCLSUserLoggingRecordError(error, nil); + FIRCLSUserLoggingRecordError(error, nil, nil); } NSArray* errors = [self errorAContents]; @@ -414,7 +414,7 @@ - (void)testWritingMaximumNumberOfLoggedErrors { // at this point, if we log one more, we should expect a roll over to the next file - FIRCLSUserLoggingRecordError(error, nil); + FIRCLSUserLoggingRecordError(error, nil, nil); XCTAssertEqual([[self errorAContents] count], 8, @""); XCTAssertEqual([[self errorBContents] count], 1, @""); @@ -422,7 +422,7 @@ - (void)testWritingMaximumNumberOfLoggedErrors { // and our next entry should continue into the B file - FIRCLSUserLoggingRecordError(error, nil); + FIRCLSUserLoggingRecordError(error, nil, nil); XCTAssertEqual([[self errorAContents] count], 8, @""); XCTAssertEqual([[self errorBContents] count], 2, @""); @@ -432,7 +432,7 @@ - (void)testWritingMaximumNumberOfLoggedErrors { - (void)testLoggedErrorWithNullsInAdditionalInfo { NSError* error = [NSError errorWithDomain:@"Domain" code:-1 userInfo:nil]; - FIRCLSUserLoggingRecordError(error, @{@"null-key" : [NSNull null]}); + FIRCLSUserLoggingRecordError(error, @{@"null-key" : [NSNull null]}, nil); NSArray* errors = [self errorAContents]; diff --git a/Crashlytics/UnitTests/FIRCLSRolloutsPersistenceManagerTests.m b/Crashlytics/UnitTests/FIRCLSRolloutsPersistenceManagerTests.m new file mode 100644 index 00000000000..aec030d7538 --- /dev/null +++ b/Crashlytics/UnitTests/FIRCLSRolloutsPersistenceManagerTests.m @@ -0,0 +1,70 @@ +// Copyright 2024 Google +// +// 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 +#import + +#import "Crashlytics/Crashlytics/Components/FIRCLSContext.h" +#import "Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" +#import "Crashlytics/UnitTests/Mocks/FIRCLSTempMockFileManager.h" +#if SWIFT_PACKAGE +@import FirebaseCrashlyticsSwift; +#else // Swift Package Manager +#import +#endif // CocoaPods + +NSString *reportId = @"1234567"; + +@interface FIRCLSRolloutsPersistenceManagerTests : XCTestCase +@property(nonatomic, strong) FIRCLSTempMockFileManager *fileManager; +@property(nonatomic, strong) FIRCLSRolloutsPersistenceManager *rolloutsPersistenceManager; +@end + +@implementation FIRCLSRolloutsPersistenceManagerTests +- (void)setUp { + [super setUp]; + FIRCLSContextBaseInit(); + self.fileManager = [[FIRCLSTempMockFileManager alloc] init]; + [self.fileManager createReportDirectories]; + [self.fileManager setupNewPathForExecutionIdentifier:reportId]; + + self.rolloutsPersistenceManager = + [[FIRCLSRolloutsPersistenceManager alloc] initWithFileManager:self.fileManager]; +} + +- (void)tearDown { + [self.fileManager removeItemAtPath:_fileManager.rootPath]; + FIRCLSContextBaseDeinit(); + [super tearDown]; +} + +- (void)testUpdateRolloutsStateToPersistenceWithRollouts { + NSString *encodedStateString = + @"{rollouts:[{\"parameter_key\":\"6d795f66656174757265\",\"parameter_value\":" + @"\"e8bf99e698af7468656d6973e79a84e6b58be8af95e695b0e68daeefbc8ce8be93e585a5e4b8ade69687\"," + @"\"rollout_id\":\"726f6c6c6f75745f31\",\"template_version\":1,\"variant_id\":" + @"\"636f6e74726f6c\"}]}"; + + NSData *data = [encodedStateString dataUsingEncoding:NSUTF8StringEncoding]; + NSString *rolloutsFilePath = + [[[self.fileManager activePath] stringByAppendingPathComponent:reportId] + stringByAppendingPathComponent:FIRCLSReportRolloutsFile]; + + [self.rolloutsPersistenceManager updateRolloutsStateToPersistenceWithRollouts:data + reportID:reportId]; + XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:rolloutsFilePath]); +} + +@end diff --git a/Crashlytics/UnitTests/FIRRecordExceptionModelTests.m b/Crashlytics/UnitTests/FIRRecordExceptionModelTests.m index 1908fea71db..e564614f8ae 100644 --- a/Crashlytics/UnitTests/FIRRecordExceptionModelTests.m +++ b/Crashlytics/UnitTests/FIRRecordExceptionModelTests.m @@ -75,7 +75,7 @@ - (void)testWrittenCLSRecordFile { FIRExceptionModel *exceptionModel = [FIRExceptionModel exceptionModelWithName:name reason:reason]; exceptionModel.stackTrace = stackTrace; - FIRCLSExceptionRecordModel(exceptionModel); + FIRCLSExceptionRecordModel(exceptionModel, nil); NSData *data = [NSData dataWithContentsOfFile:[self.reportPath diff --git a/Crashlytics/UnitTestsSwift/CrashlyticsRemoteConfigManagerTests.swift b/Crashlytics/UnitTestsSwift/CrashlyticsRemoteConfigManagerTests.swift new file mode 100644 index 00000000000..6c2e070e47f --- /dev/null +++ b/Crashlytics/UnitTestsSwift/CrashlyticsRemoteConfigManagerTests.swift @@ -0,0 +1,136 @@ +// 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. +#if SWIFT_PACKAGE + @testable import FirebaseCrashlyticsSwift +#else + @testable import FirebaseCrashlytics +#endif +import FirebaseRemoteConfigInterop +import XCTest + +class RemoteConfigConfigMock: RemoteConfigInterop { + func registerRolloutsStateSubscriber(_ subscriber: FirebaseRemoteConfigInterop + .RolloutsStateSubscriber, + for namespace: String) {} +} + +class PersistanceManagerMock: CrashlyticsPersistenceLog { + func updateRolloutsStateToPersistence(rollouts: Data, reportID: String) {} + func debugLog(message: String) {} +} + +final class CrashlyticsRemoteConfigManagerTests: XCTestCase { + let rollouts: RolloutsState = { + let assignment1 = RolloutAssignment( + rolloutId: "rollout_1", + variantId: "control", + templateVersion: 1, + parameterKey: "my_feature", + parameterValue: "false" + ) + let assignment2 = RolloutAssignment( + rolloutId: "rollout_2", + variantId: "enabled", + templateVersion: 1, + parameterKey: "themis_big_feature", + parameterValue: "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + ) + let rollouts = RolloutsState(assignmentList: [assignment1, assignment2]) + return rollouts + }() + + let singleRollout: RolloutsState = { + let assignment1 = RolloutAssignment( + rolloutId: "rollout_1", + variantId: "control", + templateVersion: 1, + parameterKey: "my_feature", + parameterValue: "这是themis的测试数据,输入中文" // check unicode + ) + let rollouts = RolloutsState(assignmentList: [assignment1]) + return rollouts + }() + + let rcInterop = RemoteConfigConfigMock() + + func testRemoteConfigManagerProperlyProcessRolloutsState() throws { + let rcManager = CrashlyticsRemoteConfigManager( + remoteConfig: rcInterop, + persistenceDelegate: PersistanceManagerMock() + ) + rcManager.updateRolloutsState(rolloutsState: rollouts, reportID: "12R") + XCTAssertEqual(rcManager.rolloutAssignment.count, 2) + + for assignment in rollouts.assignments { + if assignment.parameterKey == "themis_big_feature" { + XCTAssertEqual( + assignment.parameterValue.count, + CrashlyticsRemoteConfigManager.maxParameterValueLength + ) + } + } + } + + func testRemoteConfigManagerGenerateEncodedRolloutAssignmentsJson() throws { + let expectedString = + "[{\"parameter_key\":\"6d795f66656174757265\",\"parameter_value\":\"e8bf99e698af7468656d6973e79a84e6b58be8af95e695b0e68daeefbc8ce8be93e585a5e4b8ade69687\",\"rollout_id\":\"726f6c6c6f75745f31\",\"template_version\":1,\"variant_id\":\"636f6e74726f6c\"}]" + + let rcManager = CrashlyticsRemoteConfigManager( + remoteConfig: rcInterop, + persistenceDelegate: PersistanceManagerMock() + ) + rcManager.updateRolloutsState(rolloutsState: singleRollout, reportID: "456") + + let string = rcManager.getRolloutAssignmentsEncodedJsonString() + XCTAssertEqual(string, expectedString) + } + + func testMultiThreadsUpdateRolloutAssignments() throws { + let rcManager = CrashlyticsRemoteConfigManager( + remoteConfig: rcInterop, + persistenceDelegate: PersistanceManagerMock() + ) + DispatchQueue.main.async { [weak self] in + if let singleRollout = self?.singleRollout { + rcManager.updateRolloutsState(rolloutsState: singleRollout, reportID: "456") + XCTAssertEqual(rcManager.rolloutAssignment.count, 1) + } + } + + DispatchQueue.main.async { [weak self] in + if let rollouts = self?.rollouts { + rcManager.updateRolloutsState(rolloutsState: rollouts, reportID: "456") + XCTAssertEqual(rcManager.rolloutAssignment.count, 2) + } + } + } + + func testMultiThreadsReadAndWriteRolloutAssignments() throws { + let rcManager = CrashlyticsRemoteConfigManager( + remoteConfig: rcInterop, + persistenceDelegate: PersistanceManagerMock() + ) + rcManager.updateRolloutsState(rolloutsState: singleRollout, reportID: "456") + + DispatchQueue.main.async { [weak self] in + if let rollouts = self?.rollouts { + let oldAssignments = rcManager.rolloutAssignment + rcManager.updateRolloutsState(rolloutsState: rollouts, reportID: "456") + XCTAssertEqual(rcManager.rolloutAssignment.count, 2) + XCTAssertEqual(oldAssignments.count, 1) + } + } + XCTAssertEqual(rcManager.rolloutAssignment.count, 1) + } +} diff --git a/Example/watchOSSample/Podfile b/Example/watchOSSample/Podfile index 5dd5e804c13..2f862708597 100644 --- a/Example/watchOSSample/Podfile +++ b/Example/watchOSSample/Podfile @@ -19,6 +19,7 @@ target 'SampleWatchAppWatchKitExtension' do pod 'FirebaseDatabase', :path => '../../' pod 'FirebaseAppCheckInterop', :path => '../../' pod 'FirebaseAuthInterop', :path => '../../' + pod 'FirebaseRemoteConfigInterop', :path => '../../' pod 'Firebase/Messaging', :path => '../../' pod 'Firebase/Storage', :path => '../../' diff --git a/FirebaseCrashlytics.podspec b/FirebaseCrashlytics.podspec index 108645728e4..e67e886b399 100644 --- a/FirebaseCrashlytics.podspec +++ b/FirebaseCrashlytics.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.prefix_header_file = false s.source_files = [ - 'Crashlytics/Crashlytics/**/*.{c,h,m,mm}', + 'Crashlytics/Crashlytics/**/*.{c,h,m,mm,swift}', 'Crashlytics/Protogen/**/*.{c,h,m,mm}', 'Crashlytics/Shared/**/*.{c,h,m,mm}', 'Crashlytics/third_party/**/*.{c,h,m,mm}', @@ -62,6 +62,7 @@ Pod::Spec.new do |s| s.dependency 'FirebaseCore', '~> 10.5' s.dependency 'FirebaseInstallations', '~> 10.0' s.dependency 'FirebaseSessions', '~> 10.5' + s.dependency 'FirebaseRemoteConfigInterop', '~> 10.23' s.dependency 'PromisesObjC', '~> 2.1' s.dependency 'GoogleDataTransport', '~> 9.2' s.dependency 'GoogleUtilities/Environment', '~> 7.8' @@ -119,7 +120,8 @@ Pod::Spec.new do |s| :tvos => tvos_deployment_target } unit_tests.source_files = 'Crashlytics/UnitTests/*.[mh]', - 'Crashlytics/UnitTests/*/*.[mh]' + 'Crashlytics/UnitTests/*/*.[mh]', + 'Crashlytics/UnitTestsSwift/*.swift' unit_tests.resources = 'Crashlytics/UnitTests/Data/*', 'Crashlytics/UnitTests/*.clsrecord', 'Crashlytics/UnitTests/FIRCLSMachO/machO_data/*' diff --git a/FirebaseRemoteConfig.podspec b/FirebaseRemoteConfig.podspec index efef50fef50..9767a218a60 100644 --- a/FirebaseRemoteConfig.podspec +++ b/FirebaseRemoteConfig.podspec @@ -56,6 +56,7 @@ app update. s.dependency 'FirebaseInstallations', '~> 10.0' s.dependency 'GoogleUtilities/Environment', '~> 7.8' s.dependency 'GoogleUtilities/NSData+zlib', '~> 7.8' + s.dependency 'FirebaseRemoteConfigInterop', '~> 10.23' s.test_spec 'unit' do |unit_tests| unit_tests.scheme = { :code_coverage => true } @@ -80,7 +81,8 @@ app update. 'FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.m', 'FirebaseRemoteConfig/Tests/Unit/RCNUserDefaultsManagerTests.m', 'FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.h', - 'FirebaseRemoteConfig/Tests/Unit/RCNInstanceIDTest.m' + 'FirebaseRemoteConfig/Tests/Unit/RCNInstanceIDTest.m', + 'FirebaseRemoteConfig/Tests/SwiftUnit/*.swift' # Supply plist custom plist testing. unit_tests.resources = 'FirebaseRemoteConfig/Tests/Unit/Defaults-testInfo.plist', diff --git a/FirebaseRemoteConfig/CHANGELOG.md b/FirebaseRemoteConfig/CHANGELOG.md index 47e9aff902e..e56c9da1f2d 100644 --- a/FirebaseRemoteConfig/CHANGELOG.md +++ b/FirebaseRemoteConfig/CHANGELOG.md @@ -1,3 +1,6 @@ +# Unreleased +- [changed] Add support for other Firebase products to integrate with Remote Config. + # 10.17.0 - [feature] The `FirebaseRemoteConfig` module now contains Firebase Remote Config's Swift-only APIs that were previously only available via the diff --git a/FirebaseRemoteConfig/Interop/RemoteConfigConstants.swift b/FirebaseRemoteConfig/Interop/RemoteConfigConstants.swift new file mode 100644 index 00000000000..f9a10e409b7 --- /dev/null +++ b/FirebaseRemoteConfig/Interop/RemoteConfigConstants.swift @@ -0,0 +1,21 @@ +// Copyright 2024 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 Foundation + +@objc(FIRRemoteConfigConstants) +public final class RemoteConfigConstants: NSObject { + @objc(FIRNamespaceGoogleMobilePlatform) public static let NamespaceGoogleMobilePlatform = + "firebase" +} diff --git a/FirebaseRemoteConfig/Interop/RemoteConfigInterop.swift b/FirebaseRemoteConfig/Interop/RemoteConfigInterop.swift new file mode 100644 index 00000000000..b7988efa389 --- /dev/null +++ b/FirebaseRemoteConfig/Interop/RemoteConfigInterop.swift @@ -0,0 +1,21 @@ +// 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 Foundation + +@objc(FIRRemoteConfigInterop) +public protocol RemoteConfigInterop { + func registerRolloutsStateSubscriber(_ subscriber: RolloutsStateSubscriber, + for namespace: String) +} diff --git a/FirebaseRemoteConfig/Interop/RolloutAssignment.swift b/FirebaseRemoteConfig/Interop/RolloutAssignment.swift new file mode 100644 index 00000000000..715412bb4f1 --- /dev/null +++ b/FirebaseRemoteConfig/Interop/RolloutAssignment.swift @@ -0,0 +1,47 @@ +// 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 Foundation + +@objc(FIRRolloutAssignment) +public class RolloutAssignment: NSObject { + @objc public var rolloutId: String + @objc public var variantId: String + @objc public var templateVersion: Int64 + @objc public var parameterKey: String + @objc public var parameterValue: String + + @objc public init(rolloutId: String, variantId: String, templateVersion: Int64, + parameterKey: String, + parameterValue: String) { + self.rolloutId = rolloutId + self.variantId = variantId + self.templateVersion = templateVersion + self.parameterKey = parameterKey + self.parameterValue = parameterValue + super.init() + } +} + +@objc(FIRRolloutsState) +public class RolloutsState: NSObject { + @objc public var assignments: Set = Set() + + @objc public init(assignmentList: [RolloutAssignment]) { + for assignment in assignmentList { + assignments.insert(assignment) + } + super.init() + } +} diff --git a/FirebaseRemoteConfig/Interop/RolloutsStateSubscriber.swift b/FirebaseRemoteConfig/Interop/RolloutsStateSubscriber.swift new file mode 100644 index 00000000000..88e5ba8772d --- /dev/null +++ b/FirebaseRemoteConfig/Interop/RolloutsStateSubscriber.swift @@ -0,0 +1,20 @@ +// 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 Foundation + +@objc(FIRRolloutsStateSubscriber) +public protocol RolloutsStateSubscriber { + func rolloutsStateDidChange(_ rolloutsState: RolloutsState) +} diff --git a/FirebaseRemoteConfig/Sources/FIRRemoteConfig.m b/FirebaseRemoteConfig/Sources/FIRRemoteConfig.m index 4035d558707..561ada50693 100644 --- a/FirebaseRemoteConfig/Sources/FIRRemoteConfig.m +++ b/FirebaseRemoteConfig/Sources/FIRRemoteConfig.m @@ -45,6 +45,8 @@ /// Notification when config is successfully activated const NSNotificationName FIRRemoteConfigActivateNotification = @"FIRRemoteConfigActivateNotification"; +static NSNotificationName FIRRolloutsStateDidChangeNotificationName = + @"FIRRolloutsStateDidChangeNotification"; /// Listener for the get methods. typedef void (^FIRRemoteConfigListener)(NSString *_Nonnull, NSDictionary *_Nonnull); @@ -79,8 +81,9 @@ @implementation FIRRemoteConfig { *RCInstances; + (nonnull FIRRemoteConfig *)remoteConfigWithApp:(FIRApp *_Nonnull)firebaseApp { - return [FIRRemoteConfig remoteConfigWithFIRNamespace:FIRNamespaceGoogleMobilePlatform - app:firebaseApp]; + return [FIRRemoteConfig + remoteConfigWithFIRNamespace:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform + app:firebaseApp]; } + (nonnull FIRRemoteConfig *)remoteConfigWithFIRNamespace:(NSString *_Nonnull)firebaseNamespace { @@ -116,8 +119,9 @@ + (FIRRemoteConfig *)remoteConfig { @"initializer in SwiftUI."]; } - return [FIRRemoteConfig remoteConfigWithFIRNamespace:FIRNamespaceGoogleMobilePlatform - app:[FIRApp defaultApp]]; + return [FIRRemoteConfig + remoteConfigWithFIRNamespace:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform + app:[FIRApp defaultApp]]; } /// Singleton instance of serial queue for queuing all incoming RC calls. @@ -329,10 +333,20 @@ - (void)activateWithCompletion:(FIRRemoteConfigActivateChangeCompletion)completi // New config has been activated at this point FIRLogDebug(kFIRLoggerRemoteConfig, @"I-RCN000069", @"Config activated."); [strongSelf->_configContent activatePersonalization]; + // Update last active template version number in setting and userDefaults. + [strongSelf->_settings updateLastActiveTemplateVersion]; + // Update activeRolloutMetadata + [strongSelf->_configContent activateRolloutMetadata:^(BOOL success) { + if (success) { + [self notifyRolloutsStateChange:strongSelf->_configContent.activeRolloutMetadata + versionNumber:strongSelf->_settings.lastActiveTemplateVersion]; + } + }]; + // Update experiments only for 3p namespace NSString *namespace = [strongSelf->_FIRNamespace substringToIndex:[strongSelf->_FIRNamespace rangeOfString:@":"].location]; - if ([namespace isEqualToString:FIRNamespaceGoogleMobilePlatform]) { + if ([namespace isEqualToString:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform]) { dispatch_async(dispatch_get_main_queue(), ^{ [self notifyConfigHasActivated]; }); @@ -377,6 +391,17 @@ - (NSString *)fullyQualifiedNamespace:(NSString *)namespace { return fullyQualifiedNamespace; } +- (FIRRemoteConfigValue *)defaultValueForFullyQualifiedNamespace:(NSString *)namespace + key:(NSString *)key { + FIRRemoteConfigValue *value = self->_configContent.defaultConfig[namespace][key]; + if (!value) { + value = [[FIRRemoteConfigValue alloc] + initWithData:[NSData data] + source:(FIRRemoteConfigSource)FIRRemoteConfigSourceStatic]; + } + return value; +} + #pragma mark - Get Config Result - (FIRRemoteConfigValue *)objectForKeyedSubscript:(NSString *)key { @@ -402,13 +427,7 @@ - (FIRRemoteConfigValue *)configValueForKey:(NSString *)key { config:[self->_configContent getConfigAndMetadataForNamespace:FQNamespace]]; return; } - value = self->_configContent.defaultConfig[FQNamespace][key]; - if (value) { - return; - } - - value = [[FIRRemoteConfigValue alloc] initWithData:[NSData data] - source:FIRRemoteConfigSourceStatic]; + value = [self defaultValueForFullyQualifiedNamespace:FQNamespace key:key]; }); return value; } @@ -613,4 +632,67 @@ - (FIRConfigUpdateListenerRegistration *)addOnConfigUpdateListener: return [self->_configRealtime addConfigUpdateListener:listener]; } +#pragma mark - Rollout + +- (void)addRemoteConfigInteropSubscriber:(id)subscriber { + [[NSNotificationCenter defaultCenter] + addObserverForName:FIRRolloutsStateDidChangeNotificationName + object:self + queue:nil + usingBlock:^(NSNotification *_Nonnull notification) { + FIRRolloutsState *rolloutsState = + notification.userInfo[FIRRolloutsStateDidChangeNotificationName]; + [subscriber rolloutsStateDidChange:rolloutsState]; + }]; + // Send active rollout metadata stored in persistence while app launched if there is activeConfig + NSString *fullyQualifiedNamespace = [self fullyQualifiedNamespace:_FIRNamespace]; + NSDictionary *activeConfig = self->_configContent.activeConfig; + if (activeConfig[fullyQualifiedNamespace] && activeConfig[fullyQualifiedNamespace].count > 0) { + [self notifyRolloutsStateChange:self->_configContent.activeRolloutMetadata + versionNumber:self->_settings.lastActiveTemplateVersion]; + } +} + +- (void)notifyRolloutsStateChange:(NSArray *)rolloutMetadata + versionNumber:(NSString *)versionNumber { + NSArray *rolloutsAssignments = + [self rolloutsAssignmentsWith:rolloutMetadata versionNumber:versionNumber]; + FIRRolloutsState *rolloutsState = + [[FIRRolloutsState alloc] initWithAssignmentList:rolloutsAssignments]; + FIRLogDebug(kFIRLoggerRemoteConfig, @"I-RCN000069", + @"Send rollouts state notification with name %@ to RemoteConfigInterop.", + FIRRolloutsStateDidChangeNotificationName); + [[NSNotificationCenter defaultCenter] + postNotificationName:FIRRolloutsStateDidChangeNotificationName + object:self + userInfo:@{FIRRolloutsStateDidChangeNotificationName : rolloutsState}]; +} + +- (NSArray *)rolloutsAssignmentsWith: + (NSArray *)rolloutMetadata + versionNumber:(NSString *)versionNumber { + NSMutableArray *rolloutsAssignments = [[NSMutableArray alloc] init]; + NSString *FQNamespace = [self fullyQualifiedNamespace:_FIRNamespace]; + for (NSDictionary *metadata in rolloutMetadata) { + NSString *rolloutId = metadata[RCNFetchResponseKeyRolloutID]; + NSString *variantID = metadata[RCNFetchResponseKeyVariantID]; + NSArray *affectedParameterKeys = metadata[RCNFetchResponseKeyAffectedParameterKeys]; + if (rolloutId && variantID && affectedParameterKeys) { + for (NSString *key in affectedParameterKeys) { + FIRRemoteConfigValue *value = self->_configContent.activeConfig[FQNamespace][key]; + if (!value) { + value = [self defaultValueForFullyQualifiedNamespace:FQNamespace key:key]; + } + FIRRolloutAssignment *assignment = + [[FIRRolloutAssignment alloc] initWithRolloutId:rolloutId + variantId:variantID + templateVersion:[versionNumber longLongValue] + parameterKey:key + parameterValue:value.stringValue]; + [rolloutsAssignments addObject:assignment]; + } + } + } + return rolloutsAssignments; +} @end diff --git a/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.h b/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.h index f015ea14974..e8dda531a01 100644 --- a/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.h +++ b/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.h @@ -17,6 +17,7 @@ #import #import "FirebaseCore/Extension/FirebaseCoreInternal.h" +@import FirebaseRemoteConfigInterop; @class FIRApp; @class FIRRemoteConfig; @@ -37,7 +38,8 @@ NS_ASSUME_NONNULL_BEGIN /// A concrete implementation for FIRRemoteConfigInterop to create Remote Config instances and /// register with Core's component system. -@interface FIRRemoteConfigComponent : NSObject +@interface FIRRemoteConfigComponent + : NSObject /// The FIRApp that instances will be set up with. @property(nonatomic, weak, readonly) FIRApp *app; @@ -45,6 +47,10 @@ NS_ASSUME_NONNULL_BEGIN /// Cached instances of Remote Config objects. @property(nonatomic, strong) NSMutableDictionary *instances; +/// Clear all the component instances from the singleton which created previously, this is for +/// testing only ++ (void)clearAllComponentInstances; + /// Default method for retrieving a Remote Config instance, or creating one if it doesn't exist. - (FIRRemoteConfig *)remoteConfigForNamespace:(NSString *)remoteConfigNamespace; diff --git a/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.m b/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.m index e0adc7bccbf..81055451ae4 100644 --- a/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.m +++ b/FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.m @@ -24,6 +24,31 @@ @implementation FIRRemoteConfigComponent +// Because Component now need to register two protocols (provider and interop), we need a way to +// return the same component instance for both registered protocol, this singleton pattern allow us +// to return the same component object for both registration callback. +static NSMutableDictionary *_componentInstances = nil; + ++ (FIRRemoteConfigComponent *)getComponentForApp:(FIRApp *)app { + @synchronized(_componentInstances) { + // need to init the dictionary first + if (!_componentInstances) { + _componentInstances = [[NSMutableDictionary alloc] init]; + } + if (![_componentInstances objectForKey:app.name]) { + _componentInstances[app.name] = [[self alloc] initWithApp:app]; + } + return _componentInstances[app.name]; + } + return nil; +} + ++ (void)clearAllComponentInstances { + @synchronized(_componentInstances) { + [_componentInstances removeAllObjects]; + } +} + /// Default method for retrieving a Remote Config instance, or creating one if it doesn't exist. - (FIRRemoteConfig *)remoteConfigForNamespace:(NSString *)remoteConfigNamespace { if (!remoteConfigNamespace) { @@ -102,9 +127,29 @@ + (void)load { creationBlock:^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { // Cache the component so instances of Remote Config are cached. *isCacheable = YES; - return [[FIRRemoteConfigComponent alloc] initWithApp:container.app]; + return [FIRRemoteConfigComponent getComponentForApp:container.app]; + }]; + + // Unlike provider needs to setup a hard dependency on remote config, interop allows an optional + // dependency on RC + FIRComponent *rcInterop = [FIRComponent + componentWithProtocol:@protocol(FIRRemoteConfigInterop) + instantiationTiming:FIRInstantiationTimingAlwaysEager + dependencies:@[] + creationBlock:^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // Cache the component so instances of Remote Config are cached. + *isCacheable = YES; + return [FIRRemoteConfigComponent getComponentForApp:container.app]; }]; - return @[ rcProvider ]; + return @[ rcProvider, rcInterop ]; +} + +#pragma mark - Remote Config Interop Protocol + +- (void)registerRolloutsStateSubscriber:(id)subscriber + for:(NSString * _Nonnull)namespace { + FIRRemoteConfig *instance = [self remoteConfigForNamespace:namespace]; + [instance addRemoteConfigInteropSubscriber:subscriber]; } @end diff --git a/FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h b/FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h index ef7def6fd9d..4420dcb2679 100644 --- a/FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h +++ b/FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h @@ -23,6 +23,7 @@ @class RCNConfigFetch; @class RCNConfigRealtime; @protocol FIRAnalyticsInterop; +@protocol FIRRolloutsStateSubscriber; NS_ASSUME_NONNULL_BEGIN @@ -78,6 +79,9 @@ NS_ASSUME_NONNULL_BEGIN configContent:(RCNConfigContent *)configContent analytics:(nullable id)analytics; +/// Register RolloutsStateSubcriber to FIRRemoteConfig instance +- (void)addRemoteConfigInteropSubscriber:(id _Nonnull)subscriber; + @end NS_ASSUME_NONNULL_END diff --git a/FirebaseRemoteConfig/Sources/Private/RCNConfigSettings.h b/FirebaseRemoteConfig/Sources/Private/RCNConfigSettings.h index 987f3a98225..36fb8e7435f 100644 --- a/FirebaseRemoteConfig/Sources/Private/RCNConfigSettings.h +++ b/FirebaseRemoteConfig/Sources/Private/RCNConfigSettings.h @@ -79,8 +79,10 @@ @property(nonatomic, readwrite, assign) NSString *lastETag; /// The timestamp of the last eTag update. @property(nonatomic, readwrite, assign) NSTimeInterval lastETagUpdateTime; -// Last fetched template version. -@property(nonatomic, readwrite, assign) NSString *lastTemplateVersion; +/// Last fetched template version. +@property(nonatomic, readwrite, assign) NSString *lastFetchedTemplateVersion; +/// Last active template version. +@property(nonatomic, readwrite, assign) NSString *lastActiveTemplateVersion; #pragma mark Throttling properties @@ -134,6 +136,9 @@ /// indicates a server issue. - (void)updateRealtimeExponentialBackoffTime; +/// Update last active template version from last fetched template version. +- (void)updateLastActiveTemplateVersion; + /// Returns the difference between the Realtime backoff end time and the current time in a /// NSTimeInterval format. - (NSTimeInterval)getRealtimeBackoffInterval; diff --git a/FirebaseRemoteConfig/Sources/RCNConfigConstants.h b/FirebaseRemoteConfig/Sources/RCNConfigConstants.h index db0e0213ae1..51d248c4106 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigConstants.h +++ b/FirebaseRemoteConfig/Sources/RCNConfigConstants.h @@ -37,6 +37,14 @@ static NSString *const RCNFetchResponseKeyEntries = @"entries"; static NSString *const RCNFetchResponseKeyExperimentDescriptions = @"experimentDescriptions"; /// Key that includes data for Personalization metadata. static NSString *const RCNFetchResponseKeyPersonalizationMetadata = @"personalizationMetadata"; +/// Key that includes data for Rollout metadata. +static NSString *const RCNFetchResponseKeyRolloutMetadata = @"rolloutMetadata"; +/// Key that indicates rollout id in Rollout metadata. +static NSString *const RCNFetchResponseKeyRolloutID = @"rolloutId"; +/// Key that indicates variant id in Rollout metadata. +static NSString *const RCNFetchResponseKeyVariantID = @"variantId"; +/// Key that indicates affected parameter keys in Rollout Metadata. +static NSString *const RCNFetchResponseKeyAffectedParameterKeys = @"affectedParameterKeys"; /// Error key. static NSString *const RCNFetchResponseKeyError = @"error"; /// Error code. @@ -58,5 +66,7 @@ static NSString *const RCNFetchResponseKeyStateNoTemplate = @"NO_TEMPLATE"; static NSString *const RCNFetchResponseKeyStateNoChange = @"NO_CHANGE"; /// Template found, but evaluates to empty (e.g. all keys omitted). static NSString *const RCNFetchResponseKeyStateEmptyConfig = @"EMPTY_CONFIG"; -/// Template Version key +/// Fetched Template Version key static NSString *const RCNFetchResponseKeyTemplateVersion = @"templateVersion"; +/// Active Template Version key +static NSString *const RCNActiveKeyTemplateVersion = @"activeTemplateVersion"; diff --git a/FirebaseRemoteConfig/Sources/RCNConfigContent.h b/FirebaseRemoteConfig/Sources/RCNConfigContent.h index 34d0895243a..e8410074b30 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigContent.h +++ b/FirebaseRemoteConfig/Sources/RCNConfigContent.h @@ -39,6 +39,8 @@ typedef NS_ENUM(NSInteger, RCNDBSource) { @property(nonatomic, readonly, copy) NSDictionary *activeConfig; /// Local default config that is provided by external users; @property(nonatomic, readonly, copy) NSDictionary *defaultConfig; +/// Active Rollout metadata that is currently used. +@property(nonatomic, readonly, copy) NSArray *activeRolloutMetadata; - (instancetype)init NS_UNAVAILABLE; @@ -65,6 +67,9 @@ typedef NS_ENUM(NSInteger, RCNDBSource) { /// Gets the active config and Personalization metadata. - (NSDictionary *)getConfigAndMetadataForNamespace:(NSString *)FIRNamespace; +/// Sets the fetched rollout metadata to active with a success completion handler. +- (void)activateRolloutMetadata:(void (^)(BOOL success))completionHandler; + /// Returns the updated parameters between fetched and active config. - (FIRRemoteConfigUpdate *)getConfigUpdateForNamespace:(NSString *)FIRNamespace; diff --git a/FirebaseRemoteConfig/Sources/RCNConfigContent.m b/FirebaseRemoteConfig/Sources/RCNConfigContent.m index 4f55a2e9274..1c266734c40 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigContent.m +++ b/FirebaseRemoteConfig/Sources/RCNConfigContent.m @@ -38,6 +38,10 @@ @implementation RCNConfigContent { /// Pending Personalization metadata that is latest data from server that might or might not be /// applied. NSDictionary *_fetchedPersonalization; + /// Active Rollout metadata that is currently used. + NSArray *_activeRolloutMetadata; + /// Pending Rollout metadata that is latest data from server that might or might not be applied. + NSArray *_fetchedRolloutMetadata; /// DBManager RCNConfigDBManager *_DBManager; /// Current bundle identifier; @@ -80,6 +84,8 @@ - (instancetype)initWithDBManager:(RCNConfigDBManager *)DBManager { _defaultConfig = [[NSMutableDictionary alloc] init]; _activePersonalization = [[NSDictionary alloc] init]; _fetchedPersonalization = [[NSDictionary alloc] init]; + _activeRolloutMetadata = [[NSArray alloc] init]; + _fetchedRolloutMetadata = [[NSArray alloc] init]; _bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; if (!_bundleIdentifier) { FIRLogNotice(kFIRLoggerRemoteConfig, @"I-RCN000038", @@ -115,25 +121,30 @@ - (void)loadConfigFromMainTable { _isDatabaseLoadAlreadyInitiated = true; dispatch_group_enter(_dispatch_group); - [_DBManager - loadMainWithBundleIdentifier:_bundleIdentifier - completionHandler:^(BOOL success, NSDictionary *fetchedConfig, - NSDictionary *activeConfig, NSDictionary *defaultConfig) { - self->_fetchedConfig = [fetchedConfig mutableCopy]; - self->_activeConfig = [activeConfig mutableCopy]; - self->_defaultConfig = [defaultConfig mutableCopy]; - dispatch_group_leave(self->_dispatch_group); - }]; + [_DBManager loadMainWithBundleIdentifier:_bundleIdentifier + completionHandler:^( + BOOL success, NSDictionary *fetchedConfig, NSDictionary *activeConfig, + NSDictionary *defaultConfig, NSDictionary *rolloutMetadata) { + self->_fetchedConfig = [fetchedConfig mutableCopy]; + self->_activeConfig = [activeConfig mutableCopy]; + self->_defaultConfig = [defaultConfig mutableCopy]; + self->_fetchedRolloutMetadata = + [rolloutMetadata[@RCNRolloutTableKeyFetchedMetadata] copy]; + self->_activeRolloutMetadata = + [rolloutMetadata[@RCNRolloutTableKeyActiveMetadata] copy]; + dispatch_group_leave(self->_dispatch_group); + }]; // TODO(karenzeng): Refactor personalization to be returned in loadMainWithBundleIdentifier above dispatch_group_enter(_dispatch_group); - [_DBManager loadPersonalizationWithCompletionHandler:^( - BOOL success, NSDictionary *fetchedPersonalization, - NSDictionary *activePersonalization, NSDictionary *defaultConfig) { - self->_fetchedPersonalization = [fetchedPersonalization copy]; - self->_activePersonalization = [activePersonalization copy]; - dispatch_group_leave(self->_dispatch_group); - }]; + [_DBManager + loadPersonalizationWithCompletionHandler:^( + BOOL success, NSDictionary *fetchedPersonalization, NSDictionary *activePersonalization, + NSDictionary *defaultConfig, NSDictionary *rolloutMetadata) { + self->_fetchedPersonalization = [fetchedPersonalization copy]; + self->_activePersonalization = [activePersonalization copy]; + dispatch_group_leave(self->_dispatch_group); + }]; } /// Update the current config result to main table. @@ -269,6 +280,7 @@ - (void)updateConfigContentWithResponse:(NSDictionary *)response [self handleUpdateStateForConfigNamespace:currentNamespace withEntries:response[RCNFetchResponseKeyEntries]]; [self handleUpdatePersonalization:response[RCNFetchResponseKeyPersonalizationMetadata]]; + [self handleUpdateRolloutFetchedMetadata:response[RCNFetchResponseKeyRolloutMetadata]]; return; } } @@ -279,6 +291,15 @@ - (void)activatePersonalization { fromSource:RCNDBSourceActive]; } +- (void)activateRolloutMetadata:(void (^)(BOOL success))completionHandler { + _activeRolloutMetadata = _fetchedRolloutMetadata; + [_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyActiveMetadata + value:_activeRolloutMetadata + completionHandler:^(BOOL success, NSDictionary *result) { + completionHandler(success); + }]; +} + #pragma mark State handling - (void)handleNoChangeStateForConfigNamespace:(NSString *)currentNamespace { if (!_fetchedConfig[currentNamespace]) { @@ -342,6 +363,16 @@ - (void)handleUpdatePersonalization:(NSDictionary *)metadata { [_DBManager insertOrUpdatePersonalizationConfig:metadata fromSource:RCNDBSourceFetched]; } +- (void)handleUpdateRolloutFetchedMetadata:(NSArray *)metadata { + if (!metadata) { + metadata = [[NSArray alloc] init]; + } + _fetchedRolloutMetadata = metadata; + [_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyFetchedMetadata + value:metadata + completionHandler:nil]; +} + #pragma mark - getter/setter - (NSDictionary *)fetchedConfig { /// If this is the first time reading the fetchedConfig, we might still be reading it from the @@ -369,6 +400,11 @@ - (NSDictionary *)activePersonalization { return _activePersonalization; } +- (NSArray *)activeRolloutMetadata { + [self checkAndWaitForInitialDatabaseLoad]; + return _activeRolloutMetadata; +} + - (NSDictionary *)getConfigAndMetadataForNamespace:(NSString *)FIRNamespace { /// If this is the first time reading the active metadata, we might still be reading it from the /// database. @@ -411,6 +447,8 @@ - (FIRRemoteConfigUpdate *)getConfigUpdateForNamespace:(NSString *)FIRNamespace _activeConfig[FIRNamespace] ? _activeConfig[FIRNamespace] : [[NSDictionary alloc] init]; NSDictionary *fetchedP13n = _fetchedPersonalization; NSDictionary *activeP13n = _activePersonalization; + NSArray *fetchedRolloutMetadata = _fetchedRolloutMetadata; + NSArray *activeRolloutMetadata = _activeRolloutMetadata; // add new/updated params for (NSString *key in [fetchedConfig allKeys]) { @@ -439,8 +477,50 @@ - (FIRRemoteConfigUpdate *)getConfigUpdateForNamespace:(NSString *)FIRNamespace } } + NSDictionary *fetchedRollouts = + [self getParameterKeyToRolloutMetadata:fetchedRolloutMetadata]; + NSDictionary *activeRollouts = + [self getParameterKeyToRolloutMetadata:activeRolloutMetadata]; + + // add params with new/updated rollout metadata + for (NSString *key in [fetchedRollouts allKeys]) { + if (activeRollouts[key] == nil || + ![activeRollouts[key] isEqualToDictionary:fetchedRollouts[key]]) { + [updatedKeys addObject:key]; + } + } + // add params with deleted rollout metadata + for (NSString *key in [activeRollouts allKeys]) { + if (fetchedRollouts[key] == nil) { + [updatedKeys addObject:key]; + } + } + configUpdate = [[FIRRemoteConfigUpdate alloc] initWithUpdatedKeys:updatedKeys]; return configUpdate; } +- (NSDictionary *)getParameterKeyToRolloutMetadata: + (NSArray *)rolloutMetadata { + NSMutableDictionary *result = + [[NSMutableDictionary alloc] init]; + for (NSDictionary *metadata in rolloutMetadata) { + NSString *rolloutId = metadata[RCNFetchResponseKeyRolloutID]; + NSString *variantId = metadata[RCNFetchResponseKeyVariantID]; + NSArray *affectedKeys = metadata[RCNFetchResponseKeyAffectedParameterKeys]; + if (rolloutId && variantId && affectedKeys) { + for (NSString *key in affectedKeys) { + if (result[key]) { + NSMutableDictionary *rolloutIdToVariantId = result[key]; + [rolloutIdToVariantId setValue:variantId forKey:rolloutId]; + } else { + NSMutableDictionary *rolloutIdToVariantId = [@{rolloutId : variantId} mutableCopy]; + [result setValue:rolloutIdToVariantId forKey:key]; + } + } + } + } + return [result copy]; +} + @end diff --git a/FirebaseRemoteConfig/Sources/RCNConfigDBManager.h b/FirebaseRemoteConfig/Sources/RCNConfigDBManager.h index 39c3e213b73..fba094624ca 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigDBManager.h +++ b/FirebaseRemoteConfig/Sources/RCNConfigDBManager.h @@ -53,10 +53,12 @@ typedef void (^RCNDBCompletion)(BOOL success, NSDictionary *result); /// @param fetchedConfig Return fetchedConfig loaded from DB /// @param activeConfig Return activeConfig loaded from DB /// @param defaultConfig Return defaultConfig loaded from DB +/// @param rolloutMetadata Return fetched and active RolloutMetadata loaded from DB typedef void (^RCNDBLoadCompletion)(BOOL success, NSDictionary *fetchedConfig, NSDictionary *activeConfig, - NSDictionary *defaultConfig); + NSDictionary *defaultConfig, + NSDictionary *rolloutMetadata); /// Returns the current version of the Remote Config database. + (NSString *)remoteConfigPathForDatabase; @@ -78,7 +80,6 @@ typedef void (^RCNDBLoadCompletion)(BOOL success, /// Load Personalization from table. /// @param handler The callback when reading from DB is complete. - (void)loadPersonalizationWithCompletionHandler:(RCNDBLoadCompletion)handler; - /// Insert a record in metadata table. /// @param columnNameToValue The column name and its value to be inserted in metadata table. /// @param handler The callback. @@ -110,6 +111,15 @@ typedef void (^RCNDBLoadCompletion)(BOOL success, /// Insert or update the data in Personalization config. - (BOOL)insertOrUpdatePersonalizationConfig:(NSDictionary *)metadata fromSource:(RCNDBSource)source; +/// Insert rollout metadata in rollout table. +/// @param key Key indicating whether rollout metadata is fetched or active and defined in +/// RCNConfigDefines.h. +/// @param metadataList The metadata info for each rollout entry . +/// @param handler The callback. +- (void)insertOrUpdateRolloutTableWithKey:(NSString *)key + value:(NSArray *)metadataList + completionHandler:(RCNDBCompletion)handler; + /// Clear the record of given namespace and package name /// before updating the table. - (void)deleteRecordFromMainTableWithNamespace:(NSString *)namespace_p diff --git a/FirebaseRemoteConfig/Sources/RCNConfigDBManager.m b/FirebaseRemoteConfig/Sources/RCNConfigDBManager.m index 6550760c16b..5b21306a85a 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigDBManager.m +++ b/FirebaseRemoteConfig/Sources/RCNConfigDBManager.m @@ -31,6 +31,7 @@ #define RCNTableNameInternalMetadata "internal_metadata" #define RCNTableNameExperiment "experiment" #define RCNTableNamePersonalization "personalization" +#define RCNTableNameRollout "rollout" static BOOL gIsNewDatabase; /// SQLite file name in versions 0, 1 and 2. @@ -284,11 +285,14 @@ - (BOOL)createTableSchema { "create TABLE IF NOT EXISTS " RCNTableNamePersonalization " (_id INTEGER PRIMARY KEY, key INTEGER, value BLOB)"; + static const char *createTableRollout = "create TABLE IF NOT EXISTS " RCNTableNameRollout + " (_id INTEGER PRIMARY KEY, key TEXT, value BLOB)"; + return [self executeQuery:createTableMain] && [self executeQuery:createTableMainActive] && [self executeQuery:createTableMainDefault] && [self executeQuery:createTableMetadata] && [self executeQuery:createTableInternalMetadata] && [self executeQuery:createTableExperiment] && - [self executeQuery:createTablePersonalization]; + [self executeQuery:createTablePersonalization] && [self executeQuery:createTableRollout]; } - (void)removeDatabaseOnDatabaseQueueAtPath:(NSString *)path { @@ -618,6 +622,52 @@ - (BOOL)insertOrUpdatePersonalizationConfig:(NSDictionary *)dataValue return YES; } +- (void)insertOrUpdateRolloutTableWithKey:(NSString *)key + value:(NSArray *)metadataList + completionHandler:(RCNDBCompletion)handler { + dispatch_async(_databaseOperationQueue, ^{ + BOOL success = [self insertOrUpdateRolloutTableWithKey:key value:metadataList]; + if (handler) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + handler(success, nil); + }); + } + }); +} + +- (BOOL)insertOrUpdateRolloutTableWithKey:(NSString *)key + value:(NSArray *)arrayValue { + RCN_MUST_NOT_BE_MAIN_THREAD(); + NSError *error; + NSData *dataValue = [NSJSONSerialization dataWithJSONObject:arrayValue + options:NSJSONWritingPrettyPrinted + error:&error]; + const char *SQL = + "INSERT OR REPLACE INTO " RCNTableNameRollout + " (_id, key, value) values ((SELECT _id from " RCNTableNameRollout " WHERE key = ?), ?, ?)"; + sqlite3_stmt *statement = [self prepareSQL:SQL]; + if (!statement) { + return NO; + } + if (![self bindStringToStatement:statement index:1 string:key]) { + return [self logErrorWithSQL:SQL finalizeStatement:statement returnValue:NO]; + } + + if (![self bindStringToStatement:statement index:2 string:key]) { + return [self logErrorWithSQL:SQL finalizeStatement:statement returnValue:NO]; + } + + if (sqlite3_bind_blob(statement, 3, dataValue.bytes, (int)dataValue.length, NULL) != SQLITE_OK) { + return [self logErrorWithSQL:SQL finalizeStatement:statement returnValue:NO]; + } + + if (sqlite3_step(statement) != SQLITE_DONE) { + return [self logErrorWithSQL:SQL finalizeStatement:statement returnValue:NO]; + } + sqlite3_finalize(statement); + return YES; +} + #pragma mark - update - (void)updateMetadataWithOption:(RCNUpdateOption)option @@ -852,7 +902,6 @@ - (void)loadExperimentWithCompletionHandler:(RCNDBCompletion)handler { - (NSMutableArray *)loadExperimentTableFromKey:(NSString *)key { RCN_MUST_NOT_BE_MAIN_THREAD(); - NSMutableArray *results = [[NSMutableArray alloc] init]; const char *SQL = "SELECT value FROM " RCNTableNameExperiment " WHERE key = ?"; sqlite3_stmt *statement = [self prepareSQL:SQL]; if (!statement) { @@ -861,12 +910,49 @@ - (void)loadExperimentWithCompletionHandler:(RCNDBCompletion)handler { NSArray *params = @[ key ]; [self bindStringsToStatement:statement stringArray:params]; - NSData *experimentData; + NSMutableArray *results = [self loadValuesFromStatement:statement]; + return results; +} + +- (NSArray *)loadRolloutTableFromKey:(NSString *)key { + RCN_MUST_NOT_BE_MAIN_THREAD(); + const char *SQL = "SELECT value FROM " RCNTableNameRollout " WHERE key = ?"; + sqlite3_stmt *statement = [self prepareSQL:SQL]; + if (!statement) { + return nil; + } + NSArray *params = @[ key ]; + [self bindStringsToStatement:statement stringArray:params]; + NSMutableArray *results = [self loadValuesFromStatement:statement]; + // There should be only one entry in this table. + if (results.count != 1) { + return nil; + } + NSArray *rollout; + // Convert from NSData to NSArray + if (results[0]) { + NSError *error; + rollout = [NSJSONSerialization JSONObjectWithData:results[0] options:0 error:&error]; + if (!rollout) { + FIRLogError(kFIRLoggerRemoteConfig, @"I-RCN000011", + @"Failed to convert NSData to NSAarry for Rollout Metadata with error %@.", + error); + } + } + if (!rollout) { + rollout = [[NSArray alloc] init]; + } + return rollout; +} + +- (NSMutableArray *)loadValuesFromStatement:(sqlite3_stmt *)statement { + NSMutableArray *results = [[NSMutableArray alloc] init]; + NSData *value; while (sqlite3_step(statement) == SQLITE_ROW) { - experimentData = [NSData dataWithBytes:(char *)sqlite3_column_blob(statement, 0) - length:sqlite3_column_bytes(statement, 0)]; - if (experimentData) { - [results addObject:experimentData]; + value = [NSData dataWithBytes:(char *)sqlite3_column_blob(statement, 0) + length:sqlite3_column_bytes(statement, 0)]; + if (value) { + [results addObject:value]; } } @@ -880,7 +966,7 @@ - (void)loadPersonalizationWithCompletionHandler:(RCNDBLoadCompletion)handler { RCNConfigDBManager *strongSelf = weakSelf; if (!strongSelf) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - handler(NO, [NSMutableDictionary new], [NSMutableDictionary new], nil); + handler(NO, [NSMutableDictionary new], [NSMutableDictionary new], nil, nil); }); return; } @@ -913,7 +999,7 @@ - (void)loadPersonalizationWithCompletionHandler:(RCNDBLoadCompletion)handler { if (handler) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - handler(YES, fetchedPersonalization, activePersonalization, nil); + handler(YES, fetchedPersonalization, activePersonalization, nil, nil); }); } }); @@ -987,7 +1073,7 @@ - (void)loadMainWithBundleIdentifier:(NSString *)bundleIdentifier RCNConfigDBManager *strongSelf = weakSelf; if (!strongSelf) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - handler(NO, [NSDictionary new], [NSDictionary new], [NSDictionary new]); + handler(NO, [NSDictionary new], [NSDictionary new], [NSDictionary new], [NSDictionary new]); }); return; } @@ -1000,12 +1086,26 @@ - (void)loadMainWithBundleIdentifier:(NSString *)bundleIdentifier __block NSDictionary *defaultConfig = [strongSelf loadMainTableWithBundleIdentifier:bundleIdentifier fromSource:RCNDBSourceDefault]; + + __block NSArray *fetchedRolloutMetadata = + [strongSelf loadRolloutTableFromKey:@RCNRolloutTableKeyFetchedMetadata]; + __block NSArray *activeRolloutMetadata = + [strongSelf loadRolloutTableFromKey:@RCNRolloutTableKeyActiveMetadata]; + if (handler) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ fetchedConfig = fetchedConfig ? fetchedConfig : [[NSDictionary alloc] init]; activeConfig = activeConfig ? activeConfig : [[NSDictionary alloc] init]; defaultConfig = defaultConfig ? defaultConfig : [[NSDictionary alloc] init]; - handler(YES, fetchedConfig, activeConfig, defaultConfig); + fetchedRolloutMetadata = + fetchedRolloutMetadata ? fetchedRolloutMetadata : [[NSArray alloc] init]; + activeRolloutMetadata = + activeRolloutMetadata ? activeRolloutMetadata : [[NSArray alloc] init]; + NSDictionary *rolloutMetadata = @{ + @RCNRolloutTableKeyActiveMetadata : [activeRolloutMetadata copy], + @RCNRolloutTableKeyFetchedMetadata : [fetchedRolloutMetadata copy] + }; + handler(YES, fetchedConfig, activeConfig, defaultConfig, rolloutMetadata); }); } }); diff --git a/FirebaseRemoteConfig/Sources/RCNConfigDefines.h b/FirebaseRemoteConfig/Sources/RCNConfigDefines.h index cf08f738105..1e95373541b 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigDefines.h +++ b/FirebaseRemoteConfig/Sources/RCNConfigDefines.h @@ -31,5 +31,7 @@ #define RCNExperimentTableKeyPayload "experiment_payload" #define RCNExperimentTableKeyMetadata "experiment_metadata" #define RCNExperimentTableKeyActivePayload "experiment_active_payload" +#define RCNRolloutTableKeyActiveMetadata "active_rollout_metadata" +#define RCNRolloutTableKeyFetchedMetadata "fetched_rollout_metadata" #endif diff --git a/FirebaseRemoteConfig/Sources/RCNConfigFetch.m b/FirebaseRemoteConfig/Sources/RCNConfigFetch.m index c3a0f16ddd8..dbc4b9bec56 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigFetch.m +++ b/FirebaseRemoteConfig/Sources/RCNConfigFetch.m @@ -25,6 +25,7 @@ #import "FirebaseRemoteConfig/Sources/RCNConfigContent.h" #import "FirebaseRemoteConfig/Sources/RCNConfigExperiment.h" #import "FirebaseRemoteConfig/Sources/RCNDevice.h" +@import FirebaseRemoteConfigInterop; #ifdef RCN_STAGING_SERVER static NSString *const kServerURLDomain = @@ -105,7 +106,7 @@ - (instancetype)initWithContent:(RCNConfigContent *)content _content = content; _fetchSession = [self newFetchSession]; _options = options; - _templateVersionNumber = [self->_settings lastTemplateVersion]; + _templateVersionNumber = [self->_settings lastFetchedTemplateVersion]; } return self; } @@ -572,7 +573,7 @@ - (void)fetchWithUserProperties:(NSDictionary *)userProperties // Update experiments only for 3p namespace NSString *namespace = [strongSelf->_FIRNamespace substringToIndex:[strongSelf->_FIRNamespace rangeOfString:@":"].location]; - if ([namespace isEqualToString:FIRNamespaceGoogleMobilePlatform]) { + if ([namespace isEqualToString:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform]) { [strongSelf->_experiment updateExperimentsWithResponse: fetchedConfig[RCNFetchResponseKeyExperimentDescriptions]]; } diff --git a/FirebaseRemoteConfig/Sources/RCNConfigSettings.m b/FirebaseRemoteConfig/Sources/RCNConfigSettings.m index 0b3e3ad1164..e85a63f4873 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigSettings.m +++ b/FirebaseRemoteConfig/Sources/RCNConfigSettings.m @@ -110,7 +110,8 @@ - (instancetype)initWithDatabaseManager:(RCNConfigDBManager *)manager } _isFetchInProgress = NO; - _lastTemplateVersion = [_userDefaultsManager lastTemplateVersion]; + _lastFetchedTemplateVersion = [_userDefaultsManager lastFetchedTemplateVersion]; + _lastActiveTemplateVersion = [_userDefaultsManager lastActiveTemplateVersion]; _realtimeExponentialBackoffRetryInterval = [_userDefaultsManager currentRealtimeThrottlingRetryIntervalSeconds]; _realtimeExponentialBackoffThrottleEndTime = [_userDefaultsManager realtimeThrottleEndTime]; @@ -292,7 +293,8 @@ - (void)updateMetadataWithFetchSuccessStatus:(BOOL)fetchSuccess [self updateLastFetchTimeInterval:[[NSDate date] timeIntervalSince1970]]; // Note: We expect the googleAppID to always be available. _deviceContext = FIRRemoteConfigDeviceContextWithProjectIdentifier(_googleAppID); - [_userDefaultsManager setLastTemplateVersion:templateVersion]; + _lastFetchedTemplateVersion = templateVersion; + [_userDefaultsManager setLastFetchedTemplateVersion:templateVersion]; } [self updateMetadataTable]; @@ -377,6 +379,11 @@ - (void)updateMetadataTable { [_DBManager insertMetadataTableWithValues:columnNameToValue completionHandler:nil]; } +- (void)updateLastActiveTemplateVersion { + _lastActiveTemplateVersion = _lastFetchedTemplateVersion; + [_userDefaultsManager setLastActiveTemplateVersion:_lastActiveTemplateVersion]; +} + #pragma mark - fetch request /// Returns a fetch request with the latest device and config change. diff --git a/FirebaseRemoteConfig/Sources/RCNConstants3P.m b/FirebaseRemoteConfig/Sources/RCNConstants3P.m index 6bd5d78d094..e64295be62c 100644 --- a/FirebaseRemoteConfig/Sources/RCNConstants3P.m +++ b/FirebaseRemoteConfig/Sources/RCNConstants3P.m @@ -17,4 +17,5 @@ #import "FirebaseRemoteConfig/Sources/Public/FirebaseRemoteConfig/FIRRemoteConfig.h" /// Firebase Remote Config service default namespace. +/// TODO(doudounan): Change to use this namespace defined in RemoteConfigInterop. NSString *const FIRNamespaceGoogleMobilePlatform = @"firebase"; diff --git a/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.h b/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.h index acbcd5842f4..b235f217d81 100644 --- a/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.h +++ b/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.h @@ -44,7 +44,9 @@ NS_ASSUME_NONNULL_BEGIN /// Realtime retry count. @property(nonatomic, assign) int realtimeRetryCount; /// Last fetched template version. -@property(nonatomic, assign) NSString *lastTemplateVersion; +@property(nonatomic, assign) NSString *lastFetchedTemplateVersion; +/// Last active template version. +@property(nonatomic, assign) NSString *lastActiveTemplateVersion; /// Designated initializer. - (instancetype)initWithAppName:(NSString *)appName diff --git a/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.m b/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.m index 29ec2e87a06..880a2157fe1 100644 --- a/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.m +++ b/FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.m @@ -111,7 +111,7 @@ - (void)setLastETag:(NSString *)lastETag { } } -- (NSString *)lastTemplateVersion { +- (NSString *)lastFetchedTemplateVersion { NSDictionary *userDefaults = [self instanceUserDefaults]; if ([userDefaults objectForKey:RCNFetchResponseKeyTemplateVersion]) { return [userDefaults objectForKey:RCNFetchResponseKeyTemplateVersion]; @@ -120,12 +120,27 @@ - (NSString *)lastTemplateVersion { return @"0"; } -- (void)setLastTemplateVersion:(NSString *)templateVersion { +- (void)setLastFetchedTemplateVersion:(NSString *)templateVersion { if (templateVersion) { [self setInstanceUserDefaultsValue:templateVersion forKey:RCNFetchResponseKeyTemplateVersion]; } } +- (NSString *)lastActiveTemplateVersion { + NSDictionary *userDefaults = [self instanceUserDefaults]; + if ([userDefaults objectForKey:RCNActiveKeyTemplateVersion]) { + return [userDefaults objectForKey:RCNActiveKeyTemplateVersion]; + } + + return @"0"; +} + +- (void)setLastActiveTemplateVersion:(NSString *)templateVersion { + if (templateVersion) { + [self setInstanceUserDefaultsValue:templateVersion forKey:RCNActiveKeyTemplateVersion]; + } +} + - (NSTimeInterval)lastETagUpdateTime { NSNumber *lastETagUpdateTime = [[self instanceUserDefaults] objectForKey:kRCNUserDefaultsKeyNamelastETagUpdateTime]; diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp.xcodeproj/project.pbxproj b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..d7f955d7c07 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp.xcodeproj/project.pbxproj @@ -0,0 +1,1059 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 61A5654706089C41A7398CF3 /* Pods_FeatureRolloutsTestApp_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FE5945D035CAAB3297D2CAC /* Pods_FeatureRolloutsTestApp_iOS.framework */; }; + 848D345C8969AF72BCC0E2E4 /* Pods_FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1729B0ED2CACB9C5A62A6F8C /* Pods_FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.framework */; }; + 951D70152B71AD9B00BE7EED /* RemoteConfigButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951D70142B71AD9A00BE7EED /* RemoteConfigButtonView.swift */; }; + 951D70162B71AD9B00BE7EED /* RemoteConfigButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951D70142B71AD9A00BE7EED /* RemoteConfigButtonView.swift */; }; + AD11C57C978D52894BFDC47F /* Pods_FeatureRolloutsTestApp_RemoteConfig_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E60230146BDE14D306856CB /* Pods_FeatureRolloutsTestApp_RemoteConfig_iOS.framework */; }; + C427C4A32B4603F60088A488 /* FeatureRolloutsTestAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427C4A22B4603F60088A488 /* FeatureRolloutsTestAppApp.swift */; }; + C427C4A52B4603F60088A488 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427C4A42B4603F60088A488 /* ContentView.swift */; }; + C49C486C2B4704D900BC1456 /* FeatureRolloutsTestAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427C4A22B4603F60088A488 /* FeatureRolloutsTestAppApp.swift */; }; + C49C48702B4704F300BC1456 /* FeatureRolloutsTestAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427C4A22B4603F60088A488 /* FeatureRolloutsTestAppApp.swift */; }; + C49C487A2B4704F500BC1456 /* FeatureRolloutsTestAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427C4A22B4603F60088A488 /* FeatureRolloutsTestAppApp.swift */; }; + C49C48832B47074400BC1456 /* FirebaseCrashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C49C48822B47074400BC1456 /* FirebaseCrashlytics.framework */; }; + C49C48872B47075600BC1456 /* FirebaseRemoteConfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C49C48862B47075600BC1456 /* FirebaseRemoteConfig.framework */; }; + C49C488B2B47075C00BC1456 /* FirebaseCrashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C49C488A2B47075C00BC1456 /* FirebaseCrashlytics.framework */; }; + C49C488F2B47076200BC1456 /* FirebaseRemoteConfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C49C488E2B47076200BC1456 /* FirebaseRemoteConfig.framework */; }; + C49C48952B47207200BC1456 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49C48942B47207200BC1456 /* ContentView.swift */; }; + C49C48992B4720AE00BC1456 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49C48982B4720AE00BC1456 /* ContentView.swift */; }; + C49C489C2B4720DD00BC1456 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49C489B2B4720DD00BC1456 /* ContentView.swift */; }; + C49C489E2B4722C100BC1456 /* CrashButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49C489D2B4722C100BC1456 /* CrashButtonView.swift */; }; + C49C489F2B47233000BC1456 /* CrashButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49C489D2B4722C100BC1456 /* CrashButtonView.swift */; }; + C49C48A12B47261000BC1456 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C49C48A02B47261000BC1456 /* GoogleService-Info.plist */; }; + C49C48A22B47261000BC1456 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C49C48A02B47261000BC1456 /* GoogleService-Info.plist */; }; + C49C48A32B47261000BC1456 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C49C48A02B47261000BC1456 /* GoogleService-Info.plist */; }; + C49C48A42B47261000BC1456 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C49C48A02B47261000BC1456 /* GoogleService-Info.plist */; }; + F07A9478976524A8264259F0 /* Pods_FeatureRolloutsTestApp_Crashlytics_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5472955122D0CE0A8A3CE4D5 /* Pods_FeatureRolloutsTestApp_Crashlytics_iOS.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + C49C48852B47074400BC1456 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + C49C48892B47075600BC1456 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + C49C488D2B47075C00BC1456 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 025F972344BB0B489CC052D6 /* Pods-FeatureRolloutsTestApp_Crashlytics_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_Crashlytics_iOS.debug.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_Crashlytics_iOS/Pods-FeatureRolloutsTestApp_Crashlytics_iOS.debug.xcconfig"; sourceTree = ""; }; + 10710CAF870FA7E8D1ABF94C /* Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.release.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.release.xcconfig"; sourceTree = ""; }; + 1729B0ED2CACB9C5A62A6F8C /* Pods_FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2842D338F32EE531C752262E /* Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.debug.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.debug.xcconfig"; sourceTree = ""; }; + 2D15DD53784CDDE94D00AB02 /* Pods-FeatureRolloutsTestApp_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_iOS.release.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_iOS/Pods-FeatureRolloutsTestApp_iOS.release.xcconfig"; sourceTree = ""; }; + 2FE5945D035CAAB3297D2CAC /* Pods_FeatureRolloutsTestApp_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FeatureRolloutsTestApp_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 30BB126FCB8D5F53B5795500 /* Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.release.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.release.xcconfig"; sourceTree = ""; }; + 4E60230146BDE14D306856CB /* Pods_FeatureRolloutsTestApp_RemoteConfig_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FeatureRolloutsTestApp_RemoteConfig_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5472955122D0CE0A8A3CE4D5 /* Pods_FeatureRolloutsTestApp_Crashlytics_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FeatureRolloutsTestApp_Crashlytics_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D30A6D1F2CE622B6D5D563F /* Pods-FeatureRolloutsTestApp_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_iOS.debug.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_iOS/Pods-FeatureRolloutsTestApp_iOS.debug.xcconfig"; sourceTree = ""; }; + 8BA72854B19D7A9D9BE15E1D /* Pods-FeatureRolloutsTestApp_Crashlytics_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_Crashlytics_iOS.release.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_Crashlytics_iOS/Pods-FeatureRolloutsTestApp_Crashlytics_iOS.release.xcconfig"; sourceTree = ""; }; + 951D70142B71AD9A00BE7EED /* RemoteConfigButtonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteConfigButtonView.swift; sourceTree = ""; }; + AF260B513E38B2528E7B13CC /* Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.debug.xcconfig"; path = "Target Support Files/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.debug.xcconfig"; sourceTree = ""; }; + C427C49F2B4603F60088A488 /* FeatureRolloutsTestApp_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FeatureRolloutsTestApp_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + C427C4A22B4603F60088A488 /* FeatureRolloutsTestAppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureRolloutsTestAppApp.swift; sourceTree = ""; }; + C427C4A42B4603F60088A488 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + C427C4A82B4603F80088A488 /* FeatureRolloutsTestApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FeatureRolloutsTestApp.entitlements; sourceTree = ""; }; + C49C48412B460FC600BC1456 /* FeatureRolloutsTestApp_Crashlytics_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FeatureRolloutsTestApp_Crashlytics_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + C49C48772B4704F300BC1456 /* FeatureRolloutsTestApp_RemoteConfig_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FeatureRolloutsTestApp_RemoteConfig_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + C49C48812B4704F500BC1456 /* FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + C49C48822B47074400BC1456 /* FirebaseCrashlytics.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FirebaseCrashlytics.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C49C48862B47075600BC1456 /* FirebaseRemoteConfig.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FirebaseRemoteConfig.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C49C488A2B47075C00BC1456 /* FirebaseCrashlytics.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FirebaseCrashlytics.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C49C488E2B47076200BC1456 /* FirebaseRemoteConfig.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FirebaseRemoteConfig.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C49C48942B47207200BC1456 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + C49C48982B4720AE00BC1456 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + C49C489B2B4720DD00BC1456 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + C49C489D2B4722C100BC1456 /* CrashButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashButtonView.swift; sourceTree = ""; }; + C49C48A02B47261000BC1456 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + C427C49C2B4603F60088A488 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 61A5654706089C41A7398CF3 /* Pods_FeatureRolloutsTestApp_iOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C483E2B460FC600BC1456 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F07A9478976524A8264259F0 /* Pods_FeatureRolloutsTestApp_Crashlytics_iOS.framework in Frameworks */, + C49C48832B47074400BC1456 /* FirebaseCrashlytics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C48722B4704F300BC1456 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AD11C57C978D52894BFDC47F /* Pods_FeatureRolloutsTestApp_RemoteConfig_iOS.framework in Frameworks */, + C49C48872B47075600BC1456 /* FirebaseRemoteConfig.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C487C2B4704F500BC1456 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C49C488F2B47076200BC1456 /* FirebaseRemoteConfig.framework in Frameworks */, + 848D345C8969AF72BCC0E2E4 /* Pods_FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.framework in Frameworks */, + C49C488B2B47075C00BC1456 /* FirebaseCrashlytics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29E7B4F9D5112B2AFBA1C6F8 /* Pods */ = { + isa = PBXGroup; + children = ( + 2842D338F32EE531C752262E /* Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.debug.xcconfig */, + 10710CAF870FA7E8D1ABF94C /* Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.release.xcconfig */, + 025F972344BB0B489CC052D6 /* Pods-FeatureRolloutsTestApp_Crashlytics_iOS.debug.xcconfig */, + 8BA72854B19D7A9D9BE15E1D /* Pods-FeatureRolloutsTestApp_Crashlytics_iOS.release.xcconfig */, + AF260B513E38B2528E7B13CC /* Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.debug.xcconfig */, + 30BB126FCB8D5F53B5795500 /* Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.release.xcconfig */, + 6D30A6D1F2CE622B6D5D563F /* Pods-FeatureRolloutsTestApp_iOS.debug.xcconfig */, + 2D15DD53784CDDE94D00AB02 /* Pods-FeatureRolloutsTestApp_iOS.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 4D9F4C8E7175D4479AD28BAC /* Frameworks */ = { + isa = PBXGroup; + children = ( + C49C488E2B47076200BC1456 /* FirebaseRemoteConfig.framework */, + C49C488A2B47075C00BC1456 /* FirebaseCrashlytics.framework */, + C49C48862B47075600BC1456 /* FirebaseRemoteConfig.framework */, + C49C48822B47074400BC1456 /* FirebaseCrashlytics.framework */, + 1729B0ED2CACB9C5A62A6F8C /* Pods_FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.framework */, + 5472955122D0CE0A8A3CE4D5 /* Pods_FeatureRolloutsTestApp_Crashlytics_iOS.framework */, + 4E60230146BDE14D306856CB /* Pods_FeatureRolloutsTestApp_RemoteConfig_iOS.framework */, + 2FE5945D035CAAB3297D2CAC /* Pods_FeatureRolloutsTestApp_iOS.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + C427C4962B4603F60088A488 = { + isa = PBXGroup; + children = ( + C49C489A2B4720C700BC1456 /* FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS */, + C49C48972B47208B00BC1456 /* FeatureRolloutsTestApp_RemoteConfig_iOS */, + C49C48932B47205400BC1456 /* FeatureRolloutsTestApp_Crashlytics_iOS */, + C427C4A12B4603F60088A488 /* FeatureRolloutsTestApp */, + C49C486B2B47048000BC1456 /* Shared */, + C427C4A02B4603F60088A488 /* Products */, + 29E7B4F9D5112B2AFBA1C6F8 /* Pods */, + 4D9F4C8E7175D4479AD28BAC /* Frameworks */, + ); + sourceTree = ""; + }; + C427C4A02B4603F60088A488 /* Products */ = { + isa = PBXGroup; + children = ( + C427C49F2B4603F60088A488 /* FeatureRolloutsTestApp_iOS.app */, + C49C48412B460FC600BC1456 /* FeatureRolloutsTestApp_Crashlytics_iOS.app */, + C49C48772B4704F300BC1456 /* FeatureRolloutsTestApp_RemoteConfig_iOS.app */, + C49C48812B4704F500BC1456 /* FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.app */, + ); + name = Products; + sourceTree = ""; + }; + C427C4A12B4603F60088A488 /* FeatureRolloutsTestApp */ = { + isa = PBXGroup; + children = ( + C427C4A42B4603F60088A488 /* ContentView.swift */, + C427C4A82B4603F80088A488 /* FeatureRolloutsTestApp.entitlements */, + ); + path = FeatureRolloutsTestApp; + sourceTree = ""; + }; + C49C486B2B47048000BC1456 /* Shared */ = { + isa = PBXGroup; + children = ( + C49C48A02B47261000BC1456 /* GoogleService-Info.plist */, + C427C4A22B4603F60088A488 /* FeatureRolloutsTestAppApp.swift */, + 951D70142B71AD9A00BE7EED /* RemoteConfigButtonView.swift */, + C49C489D2B4722C100BC1456 /* CrashButtonView.swift */, + ); + path = Shared; + sourceTree = ""; + }; + C49C48932B47205400BC1456 /* FeatureRolloutsTestApp_Crashlytics_iOS */ = { + isa = PBXGroup; + children = ( + C49C48942B47207200BC1456 /* ContentView.swift */, + ); + path = FeatureRolloutsTestApp_Crashlytics_iOS; + sourceTree = ""; + }; + C49C48972B47208B00BC1456 /* FeatureRolloutsTestApp_RemoteConfig_iOS */ = { + isa = PBXGroup; + children = ( + C49C48982B4720AE00BC1456 /* ContentView.swift */, + ); + path = FeatureRolloutsTestApp_RemoteConfig_iOS; + sourceTree = ""; + }; + C49C489A2B4720C700BC1456 /* FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS */ = { + isa = PBXGroup; + children = ( + C49C489B2B4720DD00BC1456 /* ContentView.swift */, + ); + path = FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + C427C49E2B4603F60088A488 /* FeatureRolloutsTestApp_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = C427C4C42B4603F80088A488 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_iOS" */; + buildPhases = ( + 1C5C78EEA66C3693218AA186 /* [CP] Check Pods Manifest.lock */, + C427C49B2B4603F60088A488 /* Sources */, + C427C49C2B4603F60088A488 /* Frameworks */, + C427C49D2B4603F60088A488 /* Resources */, + 3FCED6F36D70B363DD56F3FB /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FeatureRolloutsTestApp_iOS; + productName = FeatureRolloutsTestApp; + productReference = C427C49F2B4603F60088A488 /* FeatureRolloutsTestApp_iOS.app */; + productType = "com.apple.product-type.application"; + }; + C49C48402B460FC600BC1456 /* FeatureRolloutsTestApp_Crashlytics_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = C49C48622B460FC800BC1456 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_Crashlytics_iOS" */; + buildPhases = ( + E894A1751ED4EBA12174B475 /* [CP] Check Pods Manifest.lock */, + C49C483D2B460FC600BC1456 /* Sources */, + C49C483E2B460FC600BC1456 /* Frameworks */, + C49C483F2B460FC600BC1456 /* Resources */, + 8809A9DD2155751AF47F697B /* [CP] Embed Pods Frameworks */, + C49C48852B47074400BC1456 /* Embed Frameworks */, + C49C48A72B47285600BC1456 /* Crashlytics run script */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FeatureRolloutsTestApp_Crashlytics_iOS; + productName = FeatureRolloutsTestApp_Crashlytics_iOS; + productReference = C49C48412B460FC600BC1456 /* FeatureRolloutsTestApp_Crashlytics_iOS.app */; + productType = "com.apple.product-type.application"; + }; + C49C486E2B4704F300BC1456 /* FeatureRolloutsTestApp_RemoteConfig_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = C49C48742B4704F300BC1456 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_RemoteConfig_iOS" */; + buildPhases = ( + 2E2005BA5C63DC9C5F6B0B5C /* [CP] Check Pods Manifest.lock */, + C49C486F2B4704F300BC1456 /* Sources */, + C49C48722B4704F300BC1456 /* Frameworks */, + C49C48732B4704F300BC1456 /* Resources */, + AE72CFC82C05D96F24F22349 /* [CP] Embed Pods Frameworks */, + C49C48892B47075600BC1456 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FeatureRolloutsTestApp_RemoteConfig_iOS; + productName = FeatureRolloutsTestApp_Crashlytics_iOS; + productReference = C49C48772B4704F300BC1456 /* FeatureRolloutsTestApp_RemoteConfig_iOS.app */; + productType = "com.apple.product-type.application"; + }; + C49C48782B4704F500BC1456 /* FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = C49C487E2B4704F500BC1456 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS" */; + buildPhases = ( + 1D1A7736C1202CF5AE3E74DF /* [CP] Check Pods Manifest.lock */, + C49C48792B4704F500BC1456 /* Sources */, + C49C487C2B4704F500BC1456 /* Frameworks */, + C49C487D2B4704F500BC1456 /* Resources */, + 1AFC789ACC0369540ADCC334 /* [CP] Embed Pods Frameworks */, + C49C488D2B47075C00BC1456 /* Embed Frameworks */, + C49C48A52B47279000BC1456 /* Crashlytics run script */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS; + productName = FeatureRolloutsTestApp_Crashlytics_iOS; + productReference = C49C48812B4704F500BC1456 /* FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C427C4972B4603F60088A488 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + C427C49E2B4603F60088A488 = { + CreatedOnToolsVersion = 15.0; + }; + C49C48402B460FC600BC1456 = { + CreatedOnToolsVersion = 15.0; + }; + }; + }; + buildConfigurationList = C427C49A2B4603F60088A488 /* Build configuration list for PBXProject "FeatureRolloutsTestApp" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = C427C4962B4603F60088A488; + productRefGroup = C427C4A02B4603F60088A488 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + C49C48782B4704F500BC1456 /* FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS */, + C49C48402B460FC600BC1456 /* FeatureRolloutsTestApp_Crashlytics_iOS */, + C49C486E2B4704F300BC1456 /* FeatureRolloutsTestApp_RemoteConfig_iOS */, + C427C49E2B4603F60088A488 /* FeatureRolloutsTestApp_iOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + C427C49D2B4603F60088A488 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C49C48A12B47261000BC1456 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C483F2B460FC600BC1456 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C49C48A22B47261000BC1456 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C48732B4704F300BC1456 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C49C48A32B47261000BC1456 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C487D2B4704F500BC1456 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C49C48A42B47261000BC1456 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1AFC789ACC0369540ADCC334 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 1C5C78EEA66C3693218AA186 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-FeatureRolloutsTestApp_iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 1D1A7736C1202CF5AE3E74DF /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 2E2005BA5C63DC9C5F6B0B5C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3FCED6F36D70B363DD56F3FB /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_iOS/Pods-FeatureRolloutsTestApp_iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_iOS/Pods-FeatureRolloutsTestApp_iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_iOS/Pods-FeatureRolloutsTestApp_iOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 8809A9DD2155751AF47F697B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_Crashlytics_iOS/Pods-FeatureRolloutsTestApp_Crashlytics_iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_Crashlytics_iOS/Pods-FeatureRolloutsTestApp_Crashlytics_iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_Crashlytics_iOS/Pods-FeatureRolloutsTestApp_Crashlytics_iOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + AE72CFC82C05D96F24F22349 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS/Pods-FeatureRolloutsTestApp_RemoteConfig_iOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C49C48A52B47279000BC1456 /* Crashlytics run script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${BUILD_NAME}", + "$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + ); + name = "Crashlytics run script"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n${PODS_ROOT}/../../../../Crashlytics/run\n"; + }; + C49C48A72B47285600BC1456 /* Crashlytics run script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${BUILD_DIR%Build/*}SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run", + "$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + ); + name = "Crashlytics run script"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n${PODS_ROOT}/../../../../Crashlytics/run\n"; + }; + E894A1751ED4EBA12174B475 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-FeatureRolloutsTestApp_Crashlytics_iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + C427C49B2B4603F60088A488 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C427C4A52B4603F60088A488 /* ContentView.swift in Sources */, + C427C4A32B4603F60088A488 /* FeatureRolloutsTestAppApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C483D2B460FC600BC1456 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C49C489F2B47233000BC1456 /* CrashButtonView.swift in Sources */, + C49C486C2B4704D900BC1456 /* FeatureRolloutsTestAppApp.swift in Sources */, + C49C48952B47207200BC1456 /* ContentView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C486F2B4704F300BC1456 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C49C48702B4704F300BC1456 /* FeatureRolloutsTestAppApp.swift in Sources */, + 951D70162B71AD9B00BE7EED /* RemoteConfigButtonView.swift in Sources */, + C49C48992B4720AE00BC1456 /* ContentView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C49C48792B4704F500BC1456 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 951D70152B71AD9B00BE7EED /* RemoteConfigButtonView.swift in Sources */, + C49C487A2B4704F500BC1456 /* FeatureRolloutsTestAppApp.swift in Sources */, + C49C489E2B4722C100BC1456 /* CrashButtonView.swift in Sources */, + C49C489C2B4720DD00BC1456 /* ContentView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C427C4C22B4603F80088A488 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + C427C4C32B4603F80088A488 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SWIFT_COMPILATION_MODE = wholemodule; + }; + name = Release; + }; + C427C4C52B4603F80088A488 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6D30A6D1F2CE622B6D5D563F /* Pods-FeatureRolloutsTestApp_iOS.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C427C4C62B4603F80088A488 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2D15DD53784CDDE94D00AB02 /* Pods-FeatureRolloutsTestApp_iOS.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + C49C48632B460FC800BC1456 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 025F972344BB0B489CC052D6 /* Pods-FeatureRolloutsTestApp_Crashlytics_iOS.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C49C48642B460FC800BC1456 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8BA72854B19D7A9D9BE15E1D /* Pods-FeatureRolloutsTestApp_Crashlytics_iOS.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C49C48752B4704F300BC1456 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AF260B513E38B2528E7B13CC /* Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C49C48762B4704F300BC1456 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 30BB126FCB8D5F53B5795500 /* Pods-FeatureRolloutsTestApp_RemoteConfig_iOS.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C49C487F2B4704F500BC1456 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2842D338F32EE531C752262E /* Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C49C48802B4704F500BC1456 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 10710CAF870FA7E8D1ABF94C /* Pods-FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.firebase.config.featureRolloutsTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C427C49A2B4603F60088A488 /* Build configuration list for PBXProject "FeatureRolloutsTestApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C427C4C22B4603F80088A488 /* Debug */, + C427C4C32B4603F80088A488 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C427C4C42B4603F80088A488 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C427C4C52B4603F80088A488 /* Debug */, + C427C4C62B4603F80088A488 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C49C48622B460FC800BC1456 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_Crashlytics_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C49C48632B460FC800BC1456 /* Debug */, + C49C48642B460FC800BC1456 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C49C48742B4704F300BC1456 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_RemoteConfig_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C49C48752B4704F300BC1456 /* Debug */, + C49C48762B4704F300BC1456 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C49C487E2B4704F500BC1456 /* Build configuration list for PBXNativeTarget "FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C49C487F2B4704F500BC1456 /* Debug */, + C49C48802B4704F500BC1456 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = C427C4972B4603F60088A488 /* Project object */; +} diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/ContentView.swift b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/ContentView.swift new file mode 100644 index 00000000000..cd875f49230 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/ContentView.swift @@ -0,0 +1,29 @@ +// +// Copyright 2024 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 SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("Hello, world!") + } + .padding() + } +} diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/FeatureRolloutsTestApp.entitlements b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/FeatureRolloutsTestApp.entitlements new file mode 100644 index 00000000000..f2ef3ae0265 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp/FeatureRolloutsTestApp.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/ContentView.swift b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/ContentView.swift new file mode 100644 index 00000000000..ac68e43b8a8 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS/ContentView.swift @@ -0,0 +1,27 @@ +// +// Copyright 2024 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 Foundation +import SwiftUI + +struct ContentView: View { + var body: some View { + CrashButtonView() + .padding() + RemoteConfigButtonView() + .padding() + } +} diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_Crashlytics_iOS/ContentView.swift b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_Crashlytics_iOS/ContentView.swift new file mode 100644 index 00000000000..acb951d35a1 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_Crashlytics_iOS/ContentView.swift @@ -0,0 +1,26 @@ +// +// Copyright 2024 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 FirebaseCrashlytics +import Foundation +import SwiftUI + +struct ContentView: View { + var body: some View { + CrashButtonView() + .padding() + } +} diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_RemoteConfig_iOS/ContentView.swift b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_RemoteConfig_iOS/ContentView.swift new file mode 100644 index 00000000000..51e437b030a --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/FeatureRolloutsTestApp_RemoteConfig_iOS/ContentView.swift @@ -0,0 +1,25 @@ +// +// Copyright 2024 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 Foundation +import SwiftUI + +struct ContentView: View { + var body: some View { + RemoteConfigButtonView() + .padding() + } +} diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Podfile b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Podfile new file mode 100644 index 00000000000..975c45eaa98 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Podfile @@ -0,0 +1,52 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +def shared_pods + pod 'FirebaseCore', :path => '../../../' + pod 'FirebaseInstallations', :path => '../../../' + pod 'FirebaseCoreInternal', :path => '../../../' + pod 'FirebaseCoreExtension', :path => '../../../' + pod 'FirebaseRemoteConfigInterop', :path => '../../../' + pod 'FirebasePerformance', :path => '../../../' +end + +target 'FeatureRolloutsTestApp_iOS' do + platform :ios, '11.0' + + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + shared_pods +end + +target 'FeatureRolloutsTestApp_Crashlytics_iOS' do + platform :ios, '11.0' + + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + shared_pods + pod 'FirebaseCrashlytics', :path => '../../../' +end + +target 'FeatureRolloutsTestApp_RemoteConfig_iOS' do + platform :ios, '11.0' + + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + shared_pods + pod 'FirebaseRemoteConfig', :path => '../../../' +end + +target 'FeatureRolloutsTestApp_CrashlyticsRemoteConfig_iOS' do + platform :ios, '11.0' + + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + shared_pods + pod 'FirebaseCrashlytics', :path => '../../../' + pod 'FirebaseRemoteConfig', :path => '../../../' +end + diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/CrashButtonView.swift b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/CrashButtonView.swift new file mode 100644 index 00000000000..4fb004e196c --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/CrashButtonView.swift @@ -0,0 +1,62 @@ +// +// Copyright 2024 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 FirebaseCrashlytics +import Foundation +import SwiftUI + +struct CrashButtonView: View { + var body: some View { + var counter = 0 + + NavigationView { + VStack( + alignment: .leading, + spacing: 10 + ) { + Button(action: { + Crashlytics.crashlytics().setUserID("ThisIsABot") + }) { + Text("Set User Id") + } + + Button(action: { + assertionFailure("Throw a Crash") + }) { + Text("Crash") + } + + Button(action: { + Crashlytics.crashlytics().record(error: NSError( + domain: "This is a test non-fatal", + code: 400 + )) + }) { + Text("Record Non-fatal event") + } + + Button(action: { + Crashlytics.crashlytics().setCustomValue(counter, forKey: "counter " + String(counter)) + let i = counter + counter = i + 1 + }) { + Text("Set custom key") + } + } + .navigationTitle("Crashlytics Example") + } + } +} diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/FeatureRolloutsTestAppApp.swift b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/FeatureRolloutsTestAppApp.swift new file mode 100644 index 00000000000..b00e9bc6e6b --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/FeatureRolloutsTestAppApp.swift @@ -0,0 +1,31 @@ +// +// Copyright 2024 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 FirebaseCore +import SwiftUI + +@main +struct FeatureRolloutsTestAppApp: App { + init() { + FirebaseApp.configure() + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/RemoteConfigButtonView.swift b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/RemoteConfigButtonView.swift new file mode 100644 index 00000000000..1391ad16e55 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared/RemoteConfigButtonView.swift @@ -0,0 +1,51 @@ +// +// Copyright 2024 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 FirebaseRemoteConfig +import Foundation +import SwiftUI + +struct RemoteConfigButtonView: View { + @State private var turnOnRealTimeRC = false + let rc = RemoteConfig.remoteConfig() + @RemoteConfigProperty(key: "ios_rollouts", fallback: "unfetched") var iosRollouts: String + + var body: some View { + NavigationView { + VStack( + alignment: .leading, + spacing: 10 + ) { + Button(action: { + rc.fetch() + }) { + Text("Fetch") + } + Button(action: { + rc.activate() + }) { + Text("Activate") + } + Text(iosRollouts) + Toggle("Turn on RealTime RC", isOn: $turnOnRealTimeRC).toggleStyle(.button).tint(.mint) + .onChange(of: self.turnOnRealTimeRC, perform: { value in + rc.addOnConfigUpdateListener { u, e in rc.activate() } + }) + } + .navigationTitle("Remote Config Example") + } + } +} diff --git a/FirebaseRemoteConfig/Tests/Sample/Podfile b/FirebaseRemoteConfig/Tests/Sample/Podfile index 961df70b58e..bfff53e6fea 100644 --- a/FirebaseRemoteConfig/Tests/Sample/Podfile +++ b/FirebaseRemoteConfig/Tests/Sample/Podfile @@ -14,6 +14,7 @@ target 'RemoteConfigSampleApp' do pod 'FirebaseInstallations', :path => '../../../' pod 'FirebaseRemoteConfig', :path => '../../../' pod 'FirebaseABTesting', :path => '../../..' + pod 'FirebaseRemoteConfigInterop', :path => '../../..' # Pods for RemoteConfigSampleApp diff --git a/FirebaseRemoteConfig/Tests/Sample/RemoteConfigSampleApp/ViewController.m b/FirebaseRemoteConfig/Tests/Sample/RemoteConfigSampleApp/ViewController.m index 57c766a9035..e57cc930ea2 100644 --- a/FirebaseRemoteConfig/Tests/Sample/RemoteConfigSampleApp/ViewController.m +++ b/FirebaseRemoteConfig/Tests/Sample/RemoteConfigSampleApp/ViewController.m @@ -21,6 +21,7 @@ #import #import "../../../Sources/Private/FIRRemoteConfig_Private.h" #import "FRCLog.h" +@import FirebaseRemoteConfigInterop; static NSString *const FIRPerfNamespace = @"fireperf"; static NSString *const FIRDefaultFIRAppName = @"__FIRAPP_DEFAULT"; @@ -81,7 +82,8 @@ - (void)viewDidLoad { // TODO(mandard): Add support for deleting and adding namespaces in the app. self.namespacePickerData = - [[NSArray alloc] initWithObjects:FIRNamespaceGoogleMobilePlatform, FIRPerfNamespace, nil]; + [[NSArray alloc] initWithObjects:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform, + FIRPerfNamespace, nil]; self.appPickerData = [[NSArray alloc] initWithObjects:FIRDefaultFIRAppName, FIRSecondFIRAppName, nil]; self.RCInstances = [[NSMutableDictionary alloc] init]; @@ -91,7 +93,8 @@ - (void)viewDidLoad { if (!self.RCInstances[namespaceString]) { self.RCInstances[namespaceString] = [[NSMutableDictionary alloc] init]; } - if ([namespaceString isEqualToString:FIRNamespaceGoogleMobilePlatform] && + if ([namespaceString + isEqualToString:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform] && [appString isEqualToString:FIRDefaultFIRAppName]) { self.RCInstances[namespaceString][appString] = [FIRRemoteConfig remoteConfig]; } else { @@ -120,7 +123,7 @@ - (void)viewDidLoad { [alert addAction:defaultAction]; // Add realtime listener for firebase namespace - [self.RCInstances[FIRNamespaceGoogleMobilePlatform][FIRDefaultFIRAppName] + [self.RCInstances[FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform][FIRDefaultFIRAppName] addOnConfigUpdateListener:^(FIRRemoteConfigUpdate *_Nullable update, NSError *_Nullable error) { if (error != nil) { diff --git a/FirebaseRemoteConfig/Tests/SwiftUnit/RemoteConfigInteropTests.swift b/FirebaseRemoteConfig/Tests/SwiftUnit/RemoteConfigInteropTests.swift new file mode 100644 index 00000000000..d4610a03d65 --- /dev/null +++ b/FirebaseRemoteConfig/Tests/SwiftUnit/RemoteConfigInteropTests.swift @@ -0,0 +1,65 @@ +// 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 FirebaseRemoteConfigInterop +import XCTest + +class MockRCInterop: RemoteConfigInterop { + weak var subscriber: FirebaseRemoteConfigInterop.RolloutsStateSubscriber? + func registerRolloutsStateSubscriber(_ subscriber: FirebaseRemoteConfigInterop + .RolloutsStateSubscriber, + for namespace: String) { + self.subscriber = subscriber + } +} + +class MockRolloutSubscriber: RolloutsStateSubscriber { + var isSubscriberCalled = false + var rolloutsState: RolloutsState? + func rolloutsStateDidChange(_ rolloutsState: FirebaseRemoteConfigInterop.RolloutsState) { + isSubscriberCalled = true + self.rolloutsState = rolloutsState + } +} + +final class RemoteConfigInteropTests: XCTestCase { + let rollouts: RolloutsState = { + let assignment1 = RolloutAssignment( + rolloutId: "rollout_1", + variantId: "control", + templateVersion: 1, + parameterKey: "my_feature", + parameterValue: "false" + ) + let assignment2 = RolloutAssignment( + rolloutId: "rollout_2", + variantId: "enabled", + templateVersion: 123, + parameterKey: "themis_big_feature", + parameterValue: "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + ) + let rollouts = RolloutsState(assignmentList: [assignment1, assignment2]) + return rollouts + }() + + func testRemoteConfigIntegration() throws { + let rcSubscriber = MockRolloutSubscriber() + let rcInterop = MockRCInterop() + rcInterop.registerRolloutsStateSubscriber(rcSubscriber, for: "namespace") + rcInterop.subscriber?.rolloutsStateDidChange(rollouts) + + XCTAssertTrue(rcSubscriber.isSubscriberCalled) + XCTAssertEqual(rcSubscriber.rolloutsState?.assignments.count, 2) + } +} diff --git a/FirebaseRemoteConfig/Tests/Unit/FIRRemoteConfigComponentTest.m b/FirebaseRemoteConfig/Tests/Unit/FIRRemoteConfigComponentTest.m index 077702b7b19..52d56bb3852 100644 --- a/FirebaseRemoteConfig/Tests/Unit/FIRRemoteConfigComponentTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/FIRRemoteConfigComponentTest.m @@ -20,6 +20,7 @@ #import "FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.h" #import "FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h" #import "FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.h" +@import FirebaseRemoteConfigInterop; @interface FIRRemoteConfigComponentTest : XCTestCase @end @@ -31,6 +32,7 @@ - (void)tearDown { // Clear out any apps that were called with `configure`. [FIRApp resetApps]; + [FIRRemoteConfigComponent clearAllComponentInstances]; } - (void)testRCInstanceCreationAndCaching { @@ -92,7 +94,8 @@ - (void)testInitialization { } - (void)testRegistersAsLibrary { - XCTAssertEqual([FIRRemoteConfigComponent componentsToRegister].count, 1); + // Now component has two register, one is provider and another one is Interop + XCTAssertEqual([FIRRemoteConfigComponent componentsToRegister].count, 2); // Configure a test FIRApp for fetching an instance of the FIRRemoteConfigProvider. NSString *appName = [self generatedTestAppName]; @@ -101,12 +104,50 @@ - (void)testRegistersAsLibrary { // Attempt to fetch the component and verify it's a valid instance. id provider = FIR_COMPONENT(FIRRemoteConfigProvider, app.container); + id interop = FIR_COMPONENT(FIRRemoteConfigInterop, app.container); XCTAssertNotNil(provider); + XCTAssertNotNil(interop); // Ensure that the instance that comes from the container is cached. id sameProvider = FIR_COMPONENT(FIRRemoteConfigProvider, app.container); + id sameInterop = FIR_COMPONENT(FIRRemoteConfigInterop, app.container); XCTAssertNotNil(sameProvider); + XCTAssertNotNil(sameInterop); XCTAssertEqual(provider, sameProvider); + XCTAssertEqual(interop, sameInterop); + + // Dynamic typing, both prototols are refering to the same component instance + id providerID = provider; + id interopID = interop; + XCTAssertEqualObjects(providerID, interopID); +} + +- (void)testTwoAppsCreateTwoComponents { + NSString *appName = [self generatedTestAppName]; + [FIRApp configureWithName:appName options:[self fakeOptions]]; + FIRApp *app = [FIRApp appNamed:appName]; + + [FIRApp configureWithOptions:[self fakeOptions]]; + FIRApp *defaultApp = [FIRApp defaultApp]; + XCTAssertNotNil(defaultApp); + XCTAssertNotEqualObjects(app, defaultApp); + + id provider = FIR_COMPONENT(FIRRemoteConfigProvider, app.container); + id interop = FIR_COMPONENT(FIRRemoteConfigInterop, app.container); + id defaultAppProvider = + FIR_COMPONENT(FIRRemoteConfigProvider, defaultApp.container); + id defaultAppInterop = + FIR_COMPONENT(FIRRemoteConfigInterop, defaultApp.container); + + id providerID = provider; + id interopID = interop; + id defaultAppProviderID = defaultAppProvider; + id defaultAppInteropID = defaultAppInterop; + + XCTAssertEqualObjects(providerID, interopID); + XCTAssertEqualObjects(defaultAppProviderID, defaultAppInteropID); + // Check two apps get their own component to register + XCTAssertNotEqualObjects(interopID, defaultAppInteropID); } - (void)testThrowsWithEmptyGoogleAppID { diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNConfigContentTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNConfigContentTest.m index d4f33bf0f71..e02f22f2454 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNConfigContentTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNConfigContentTest.m @@ -24,6 +24,7 @@ #import "FirebaseRemoteConfig/Sources/RCNConfigDBManager.h" #import "FirebaseRemoteConfig/Sources/RCNConfigValue_Internal.h" #import "FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.h" +@import FirebaseRemoteConfigInterop; @interface RCNConfigContent (Testing) - (BOOL)checkAndWaitForInitialDatabaseLoad; @@ -44,7 +45,7 @@ - (void)loadMainWithBundleIdentifier:(NSString *)bundleIdentifier dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(justSmallDelay * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ self.isLoadMainCompleted = YES; - handler(YES, nil, nil, nil); + handler(YES, nil, nil, nil, nil); }); } - (void)loadPersonalizationWithCompletionHandler:(RCNDBLoadCompletion)handler { @@ -53,7 +54,7 @@ - (void)loadPersonalizationWithCompletionHandler:(RCNDBLoadCompletion)handler { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(justOtherSmallDelay * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ self.isLoadPersonalizationCompleted = YES; - handler(YES, nil, nil, nil); + handler(YES, nil, nil, nil, nil); }); } @end @@ -62,6 +63,7 @@ @interface RCNConfigContentTest : XCTestCase { NSTimeInterval _expectationTimeout; RCNConfigContent *_configContent; NSString *namespaceApp1, *namespaceApp2; + NSString *_namespaceGoogleMobilePlatform; } @end @@ -70,11 +72,12 @@ @implementation RCNConfigContentTest - (void)setUp { [super setUp]; _expectationTimeout = 1.0; + _namespaceGoogleMobilePlatform = FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform; namespaceApp1 = [NSString - stringWithFormat:@"%@:%@", FIRNamespaceGoogleMobilePlatform, RCNTestsDefaultFIRAppName]; + stringWithFormat:@"%@:%@", _namespaceGoogleMobilePlatform, RCNTestsDefaultFIRAppName]; namespaceApp2 = [NSString - stringWithFormat:@"%@:%@", FIRNamespaceGoogleMobilePlatform, RCNTestsSecondFIRAppName]; + stringWithFormat:@"%@:%@", _namespaceGoogleMobilePlatform, RCNTestsSecondFIRAppName]; _configContent = [[RCNConfigContent alloc] initWithDBManager:nil]; @@ -129,14 +132,14 @@ - (void)testUpdateConfigContentWithResponse { NSDictionary *entries = @{@"key1" : @"value1", @"key2" : @"value2"}; [configToSet setValue:entries forKey:@"entries"]; [_configContent updateConfigContentWithResponse:configToSet - forNamespace:FIRNamespaceGoogleMobilePlatform]; + forNamespace:_namespaceGoogleMobilePlatform]; NSDictionary *fetchedConfig = _configContent.fetchedConfig; - XCTAssertNotNil(fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key1"]); - XCTAssertEqualObjects([fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key1"] stringValue], + XCTAssertNotNil(fetchedConfig[_namespaceGoogleMobilePlatform][@"key1"]); + XCTAssertEqualObjects([fetchedConfig[_namespaceGoogleMobilePlatform][@"key1"] stringValue], @"value1"); - XCTAssertNotNil(fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key2"]); - XCTAssertEqualObjects([fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key2"] stringValue], + XCTAssertNotNil(fetchedConfig[_namespaceGoogleMobilePlatform][@"key2"]); + XCTAssertEqualObjects([fetchedConfig[_namespaceGoogleMobilePlatform][@"key2"] stringValue], @"value2"); } @@ -147,20 +150,20 @@ - (void)testUpdateConfigContentWithStatusUpdateWithDifferentKeys { NSDictionary *entries = @{@"key1" : @"value1"}; [configToSet setValue:entries forKey:@"entries"]; [_configContent updateConfigContentWithResponse:configToSet - forNamespace:FIRNamespaceGoogleMobilePlatform]; + forNamespace:_namespaceGoogleMobilePlatform]; configToSet = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"UPDATE", @"state", nil]; entries = @{@"key2" : @"value2", @"key3" : @"value3"}; [configToSet setValue:entries forKey:@"entries"]; [_configContent updateConfigContentWithResponse:configToSet - forNamespace:FIRNamespaceGoogleMobilePlatform]; + forNamespace:_namespaceGoogleMobilePlatform]; NSDictionary *fetchedConfig = _configContent.fetchedConfig; - XCTAssertNil(fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key1"]); - XCTAssertNotNil(fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key2"]); - XCTAssertEqualObjects([fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key2"] stringValue], + XCTAssertNil(fetchedConfig[_namespaceGoogleMobilePlatform][@"key1"]); + XCTAssertNotNil(fetchedConfig[_namespaceGoogleMobilePlatform][@"key2"]); + XCTAssertEqualObjects([fetchedConfig[_namespaceGoogleMobilePlatform][@"key2"] stringValue], @"value2"); - XCTAssertNotNil(fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key3"]); - XCTAssertEqualObjects([fetchedConfig[FIRNamespaceGoogleMobilePlatform][@"key3"] stringValue], + XCTAssertNotNil(fetchedConfig[_namespaceGoogleMobilePlatform][@"key3"]); + XCTAssertEqualObjects([fetchedConfig[_namespaceGoogleMobilePlatform][@"key3"] stringValue], @"value3"); } @@ -332,7 +335,9 @@ - (void)testConfigUpdate_noChange_emptyResponse { // populate fetched config NSMutableDictionary *fetchResponse = - [self createFetchResponseWithConfigEntries:@{@"key1" : @"value1"} p13nMetadata:nil]; + [self createFetchResponseWithConfigEntries:@{@"key1" : @"value1"} + p13nMetadata:nil + rolloutMetadata:nil]; [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; // active config is the same as fetched config @@ -365,7 +370,8 @@ - (void)testConfigUpdate_paramAdded_returnsNewKey { // fetch response has new param NSMutableDictionary *fetchResponse = [self createFetchResponseWithConfigEntries:@{@"key1" : @"value1", newParam : @"value2"} - p13nMetadata:nil]; + p13nMetadata:nil + rolloutMetadata:nil]; [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; FIRRemoteConfigUpdate *update = [_configContent getConfigUpdateForNamespace:namespace]; @@ -391,7 +397,9 @@ - (void)testConfigUpdate_paramValueChanged_returnsUpdatedKey { // fetch response contains updated value NSMutableDictionary *fetchResponse = - [self createFetchResponseWithConfigEntries:@{existingParam : updatedValue} p13nMetadata:nil]; + [self createFetchResponseWithConfigEntries:@{existingParam : updatedValue} + p13nMetadata:nil + rolloutMetadata:nil]; [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; FIRRemoteConfigUpdate *update = [_configContent getConfigUpdateForNamespace:namespace]; @@ -417,7 +425,9 @@ - (void)testConfigUpdate_paramDeleted_returnsDeletedKey { // fetch response does not contain existing param NSMutableDictionary *fetchResponse = - [self createFetchResponseWithConfigEntries:@{newParam : value1} p13nMetadata:nil]; + [self createFetchResponseWithConfigEntries:@{newParam : value1} + p13nMetadata:nil + rolloutMetadata:nil]; [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; FIRRemoteConfigUpdate *update = [_configContent getConfigUpdateForNamespace:namespace]; @@ -437,7 +447,8 @@ - (void)testConfigUpdate_p13nMetadataUpdated_returnsKey { // popuate fetched config NSMutableDictionary *fetchResponse = [self createFetchResponseWithConfigEntries:@{existingParam : value1} - p13nMetadata:@{existingParam : oldMetadata}]; + p13nMetadata:@{existingParam : oldMetadata} + rolloutMetadata:nil]; [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; // populate active config with the same content @@ -461,6 +472,148 @@ - (void)testConfigUpdate_p13nMetadataUpdated_returnsKey { XCTAssertTrue([[update updatedKeys] containsObject:existingParam]); } +- (void)testConfigUpdate_rolloutMetadataUpdated_returnsKey { + NSString *namespace = @"test_namespace"; + NSString *key1 = @"key1"; + NSString *key2 = @"kety2"; + NSString *value = @"value"; + NSString *rolloutId1 = @"1"; + NSString *rolloutId2 = @"2"; + NSString *variantId1 = @"A"; + NSString *variantId2 = @"B"; + NSArray *rolloutMetadata = @[ @{ + RCNFetchResponseKeyRolloutID : rolloutId1, + RCNFetchResponseKeyVariantID : variantId1, + RCNFetchResponseKeyAffectedParameterKeys : @[ key1 ] + } ]; + // Update rolltou metadata + NSArray *updatedRolloutMetadata = @[ + @{ + RCNFetchResponseKeyRolloutID : rolloutId1, + RCNFetchResponseKeyVariantID : variantId2, + RCNFetchResponseKeyAffectedParameterKeys : @[ key1 ] + }, + @{ + RCNFetchResponseKeyRolloutID : rolloutId2, + RCNFetchResponseKeyVariantID : variantId1, + RCNFetchResponseKeyAffectedParameterKeys : @[ key2 ] + }, + ]; + // Populate fetched config + NSMutableDictionary *fetchResponse = [self createFetchResponseWithConfigEntries:@{key1 : value} + p13nMetadata:nil + rolloutMetadata:rolloutMetadata]; + [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; + // populate active config with the same content + [_configContent activateRolloutMetadata:nil]; + XCTAssertEqualObjects(rolloutMetadata, _configContent.activeRolloutMetadata); + FIRRemoteConfigValue *rcValue = + [[FIRRemoteConfigValue alloc] initWithData:[value dataUsingEncoding:NSUTF8StringEncoding] + source:FIRRemoteConfigSourceRemote]; + + NSDictionary *namespaceToConfig = @{namespace : @{key1 : rcValue}}; + [_configContent copyFromDictionary:namespaceToConfig + toSource:RCNDBSourceActive + forNamespace:namespace]; + // New fetch response has updated rollout metadata + [fetchResponse setValue:updatedRolloutMetadata forKey:RCNFetchResponseKeyRolloutMetadata]; + [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; + + FIRRemoteConfigUpdate *update = [_configContent getConfigUpdateForNamespace:namespace]; + + XCTAssertTrue([update updatedKeys].count == 2); + XCTAssertTrue([[update updatedKeys] containsObject:key1]); + XCTAssertTrue([[update updatedKeys] containsObject:key2]); +} + +- (void)testConfigUpdate_rolloutMetadataDeleted_returnsKey { + NSString *namespace = @"test_namespace"; + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + NSString *value = @"value"; + NSString *rolloutId1 = @"1"; + NSString *variantId1 = @"A"; + NSArray *rolloutMetadata = @[ @{ + RCNFetchResponseKeyRolloutID : rolloutId1, + RCNFetchResponseKeyVariantID : variantId1, + RCNFetchResponseKeyAffectedParameterKeys : @[ key1, key2 ] + } ]; + // Remove key2 from rollout metadata + NSArray *updatedRolloutMetadata = @[ @{ + RCNFetchResponseKeyRolloutID : rolloutId1, + RCNFetchResponseKeyVariantID : variantId1, + RCNFetchResponseKeyAffectedParameterKeys : @[ key1 ] + } ]; + // Populate fetched config + NSMutableDictionary *fetchResponse = + [self createFetchResponseWithConfigEntries:@{key1 : value, key2 : value} + p13nMetadata:nil + rolloutMetadata:rolloutMetadata]; + [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; + // populate active config with the same content + [_configContent activateRolloutMetadata:nil]; + XCTAssertEqualObjects(rolloutMetadata, _configContent.activeRolloutMetadata); + FIRRemoteConfigValue *rcValue = + [[FIRRemoteConfigValue alloc] initWithData:[value dataUsingEncoding:NSUTF8StringEncoding] + source:FIRRemoteConfigSourceRemote]; + + NSDictionary *namespaceToConfig = @{namespace : @{key1 : rcValue, key2 : rcValue}}; + [_configContent copyFromDictionary:namespaceToConfig + toSource:RCNDBSourceActive + forNamespace:namespace]; + // New fetch response has updated rollout metadata + [fetchResponse setValue:updatedRolloutMetadata forKey:RCNFetchResponseKeyRolloutMetadata]; + [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; + + FIRRemoteConfigUpdate *update = [_configContent getConfigUpdateForNamespace:namespace]; + + XCTAssertTrue([update updatedKeys].count == 1); + XCTAssertTrue([[update updatedKeys] containsObject:key2]); +} + +- (void)testConfigUpdate_rolloutMetadataDeletedAll_returnsKey { + NSString *namespace = @"test_namespace"; + NSString *key = @"key"; + NSString *value = @"value"; + NSString *rolloutId1 = @"1"; + NSString *variantId1 = @"A"; + NSArray *rolloutMetadata = @[ @{ + RCNFetchResponseKeyRolloutID : rolloutId1, + RCNFetchResponseKeyVariantID : variantId1, + RCNFetchResponseKeyAffectedParameterKeys : @[ key ] + } ]; + // Populate fetched config + NSMutableDictionary *fetchResponse = [self createFetchResponseWithConfigEntries:@{key : value} + p13nMetadata:nil + rolloutMetadata:rolloutMetadata]; + [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; + // populate active config with the same content + [_configContent activateRolloutMetadata:nil]; + XCTAssertEqualObjects(rolloutMetadata, _configContent.activeRolloutMetadata); + FIRRemoteConfigValue *rcValue = + [[FIRRemoteConfigValue alloc] initWithData:[value dataUsingEncoding:NSUTF8StringEncoding] + source:FIRRemoteConfigSourceRemote]; + + NSDictionary *namespaceToConfig = @{namespace : @{key : rcValue}}; + [_configContent copyFromDictionary:namespaceToConfig + toSource:RCNDBSourceActive + forNamespace:namespace]; + + // New fetch response has updated rollout metadata + NSMutableDictionary *updateFetchResponse = + [self createFetchResponseWithConfigEntries:@{key : value} + p13nMetadata:nil + rolloutMetadata:nil]; + [_configContent updateConfigContentWithResponse:updateFetchResponse forNamespace:namespace]; + + FIRRemoteConfigUpdate *update = [_configContent getConfigUpdateForNamespace:namespace]; + [_configContent activateRolloutMetadata:nil]; + + XCTAssertTrue([update updatedKeys].count == 1); + XCTAssertTrue([[update updatedKeys] containsObject:key]); + XCTAssertTrue(_configContent.activeRolloutMetadata.count == 0); +} + - (void)testConfigUpdate_valueSourceChanged_returnsKey { NSString *namespace = @"test_namespace"; NSString *existingParam = @"key1"; @@ -477,7 +630,9 @@ - (void)testConfigUpdate_valueSourceChanged_returnsKey { // fetch response contains same key->value NSMutableDictionary *fetchResponse = - [self createFetchResponseWithConfigEntries:@{existingParam : value1} p13nMetadata:nil]; + [self createFetchResponseWithConfigEntries:@{existingParam : value1} + p13nMetadata:nil + rolloutMetadata:nil]; [_configContent updateConfigContentWithResponse:fetchResponse forNamespace:namespace]; FIRRemoteConfigUpdate *update = [_configContent getConfigUpdateForNamespace:namespace]; @@ -489,14 +644,18 @@ - (void)testConfigUpdate_valueSourceChanged_returnsKey { #pragma mark - Test Helpers - (NSMutableDictionary *)createFetchResponseWithConfigEntries:(NSDictionary *)config - p13nMetadata:(NSDictionary *)metadata { + p13nMetadata:(NSDictionary *)p13nMetadata + rolloutMetadata:(NSArray *)rolloutMetadata { NSMutableDictionary *fetchResponse = [[NSMutableDictionary alloc] initWithObjectsAndKeys:RCNFetchResponseKeyStateUpdate, RCNFetchResponseKeyState, nil]; if (config) { [fetchResponse setValue:config forKey:RCNFetchResponseKeyEntries]; } - if (metadata) { - [fetchResponse setValue:metadata forKey:RCNFetchResponseKeyPersonalizationMetadata]; + if (p13nMetadata) { + [fetchResponse setValue:p13nMetadata forKey:RCNFetchResponseKeyPersonalizationMetadata]; + } + if (rolloutMetadata) { + [fetchResponse setValue:rolloutMetadata forKey:RCNFetchResponseKeyRolloutMetadata]; } return fetchResponse; } diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNConfigDBManagerTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNConfigDBManagerTest.m index 23705be1abf..773af690935 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNConfigDBManagerTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNConfigDBManagerTest.m @@ -83,8 +83,8 @@ - (void)testV1NamespaceMigrationToV2Namespace { BOOL loadSuccess, NSDictionary *> *fetchedConfig, NSDictionary *> *activeConfig, - NSDictionary *> - *defaultConfig) { + NSDictionary *> *defaultConfig, + NSDictionary *unusedRolloutMetadata) { XCTAssertTrue(loadSuccess); NSString *fullyQualifiedNamespace = [NSString stringWithFormat:@"%@:%@", namespace_p, kFIRDefaultAppName]; @@ -125,18 +125,19 @@ - (void)testWriteAndLoadMainTableResult { XCTAssertTrue(success); if (count == 100) { // check DB read correctly - [self->_DBManager loadMainWithBundleIdentifier:bundleIdentifier - completionHandler:^(BOOL success, NSDictionary *fetchedConfig, - NSDictionary *activeConfig, - NSDictionary *defaultConfig) { - NSMutableDictionary *res = [fetchedConfig mutableCopy]; - XCTAssertTrue(success); - FIRRemoteConfigValue *value = res[namespace_p][@"key100"]; - XCTAssertEqualObjects(value.stringValue, @"value100"); - if (success) { - [loadConfigContentExpectation fulfill]; - } - }]; + [self->_DBManager + loadMainWithBundleIdentifier:bundleIdentifier + completionHandler:^(BOOL success, NSDictionary *fetchedConfig, + NSDictionary *activeConfig, NSDictionary *defaultConfig, + NSDictionary *unusedRolloutMetadata) { + NSMutableDictionary *res = [fetchedConfig mutableCopy]; + XCTAssertTrue(success); + FIRRemoteConfigValue *value = res[namespace_p][@"key100"]; + XCTAssertEqualObjects(value.stringValue, @"value100"); + if (success) { + [loadConfigContentExpectation fulfill]; + } + }]; } }; NSString *value = [NSString stringWithFormat:@"value%d", i]; @@ -382,7 +383,8 @@ - (void)testDeleteParamAndLoadMainTable { [self->_DBManager loadMainWithBundleIdentifier:bundleIdentifier completionHandler:^(BOOL success, NSDictionary *fetchedConfig, - NSDictionary *activeConfig, NSDictionary *defaultConfig) { + NSDictionary *activeConfig, NSDictionary *defaultConfig, + NSDictionary *unusedRolloutMetadata) { NSMutableDictionary *res = [activeConfig mutableCopy]; XCTAssertTrue(success); FIRRemoteConfigValue *value = res[namespaceToDelete][@"keyToDelete"]; @@ -403,7 +405,8 @@ - (void)testDeleteParamAndLoadMainTable { [self->_DBManager loadMainWithBundleIdentifier:bundleIdentifier completionHandler:^(BOOL success, NSDictionary *fetchedConfig, - NSDictionary *activeConfig, NSDictionary *defaultConfig) { + NSDictionary *activeConfig, NSDictionary *defaultConfig, + NSDictionary *unusedRolloutMetadata) { NSMutableDictionary *res = [activeConfig mutableCopy]; XCTAssertTrue(success); FIRRemoteConfigValue *value2 = res[namespaceToKeep][@"keyToRetain"]; @@ -587,6 +590,136 @@ - (void)testWriteAndLoadMetadataMultipleTimes { [self waitForExpectationsWithTimeout:_expectionTimeout handler:nil]; } +- (void)testWriteAndLoadFetchedAndActiveRollout { + XCTestExpectation *writeAndLoadFetchedRolloutExpectation = + [self expectationWithDescription:@"Write and load rollout in database successfully"]; + + NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier; + + NSArray *fetchedRollout = @[ + @{ + @"rollout_id" : @"1", + @"variant_id" : @"B", + @"affected_parameter_keys" : @[ @"key_1", @"key_2" ] + }, + @{ + @"rollout_id" : @"2", + @"variant_id" : @"1", + @"affected_parameter_keys" : @[ @"key_1", @"key_3" ] + } + ]; + + NSArray *activeRollout = @[ + @{ + @"rollout_id" : @"1", + @"variant_id" : @"B", + @"affected_parameter_keys" : @[ @"key_1", @"key_2" ] + }, + @{ + @"rollout_id" : @"3", + @"variant_id" : @"a", + @"affected_parameter_keys" : @[ @"key_1", @"key_3" ] + } + ]; + + RCNDBCompletion writeRolloutCompletion = ^(BOOL success, NSDictionary *result) { + XCTAssertTrue(success); + RCNDBLoadCompletion loadCompletion = ^( + BOOL success, NSDictionary *unusedFetchedConfig, NSDictionary *unusedActiveConfig, + NSDictionary *unusedDefaultConfig, NSDictionary *rolloutMetadata) { + XCTAssertTrue(success); + XCTAssertNotNil(rolloutMetadata[@RCNRolloutTableKeyFetchedMetadata]); + XCTAssertEqualObjects(fetchedRollout, rolloutMetadata[@RCNRolloutTableKeyFetchedMetadata]); + XCTAssertNotNil(rolloutMetadata[@RCNRolloutTableKeyActiveMetadata]); + XCTAssertEqualObjects(activeRollout, rolloutMetadata[@RCNRolloutTableKeyActiveMetadata]); + + [writeAndLoadFetchedRolloutExpectation fulfill]; + }; + [self->_DBManager loadMainWithBundleIdentifier:bundleIdentifier + completionHandler:loadCompletion]; + }; + [_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyFetchedMetadata + value:fetchedRollout + completionHandler:nil]; + [_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyActiveMetadata + value:activeRollout + completionHandler:writeRolloutCompletion]; + + [self waitForExpectationsWithTimeout:_expectionTimeout handler:nil]; +} + +- (void)testUpdateAndLoadRollout { + XCTestExpectation *updateAndLoadFetchedRolloutExpectation = + [self expectationWithDescription:@"Update and load rollout in database successfully"]; + + NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier; + + NSArray *fetchedRollout = @[ @{ + @"rollout_id" : @"1", + @"variant_id" : @"B", + @"affected_parameter_keys" : @[ @"key_1", @"key_2" ] + } ]; + + NSArray *updatedFetchedRollout = @[ + @{ + @"rollout_id" : @"1", + @"variant_id" : @"B", + @"affected_parameter_keys" : @[ @"key_1", @"key_2" ] + }, + @{ + @"rollout_id" : @"2", + @"variant_id" : @"1", + @"affected_parameter_keys" : @[ @"key_1", @"key_3" ] + } + ]; + + RCNDBCompletion writeRolloutCompletion = ^(BOOL success, NSDictionary *result) { + XCTAssertTrue(success); + RCNDBLoadCompletion loadCompletion = + ^(BOOL success, NSDictionary *unusedFetchedConfig, NSDictionary *unusedActiveConfig, + NSDictionary *unusedDefaultConfig, NSDictionary *rolloutMetadata) { + XCTAssertTrue(success); + XCTAssertNotNil(rolloutMetadata[@RCNRolloutTableKeyFetchedMetadata]); + XCTAssertEqualObjects(updatedFetchedRollout, + rolloutMetadata[@RCNRolloutTableKeyFetchedMetadata]); + + [updateAndLoadFetchedRolloutExpectation fulfill]; + }; + [self->_DBManager loadMainWithBundleIdentifier:bundleIdentifier + completionHandler:loadCompletion]; + }; + [_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyFetchedMetadata + value:fetchedRollout + completionHandler:nil]; + [_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyFetchedMetadata + value:updatedFetchedRollout + completionHandler:writeRolloutCompletion]; + + [self waitForExpectationsWithTimeout:_expectionTimeout handler:nil]; +} +- (void)testLoadEmptyRollout { + XCTestExpectation *updateAndLoadFetchedRolloutExpectation = + [self expectationWithDescription:@"Load empty rollout in database successfully"]; + + NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier; + + NSArray *emptyResult = [[NSArray alloc] init]; + + RCNDBLoadCompletion loadCompletion = + ^(BOOL success, NSDictionary *unusedFetchedConfig, NSDictionary *unusedActiveConfig, + NSDictionary *unusedDefaultConfig, NSDictionary *rolloutMetadata) { + XCTAssertTrue(success); + XCTAssertNotNil(rolloutMetadata[@RCNRolloutTableKeyFetchedMetadata]); + XCTAssertEqualObjects(emptyResult, rolloutMetadata[@RCNRolloutTableKeyFetchedMetadata]); + XCTAssertNotNil(rolloutMetadata[@RCNRolloutTableKeyActiveMetadata]); + XCTAssertEqualObjects(emptyResult, rolloutMetadata[@RCNRolloutTableKeyActiveMetadata]); + + [updateAndLoadFetchedRolloutExpectation fulfill]; + }; + [self->_DBManager loadMainWithBundleIdentifier:bundleIdentifier completionHandler:loadCompletion]; + [self waitForExpectationsWithTimeout:_expectionTimeout handler:nil]; +} + - (void)testUpdateAndloadLastFetchStatus { XCTestExpectation *updateAndLoadMetadataExpectation = [self expectationWithDescription:@"Update and load last fetch status in database successfully."]; diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNConfigTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNConfigTest.m index 2a5bd7c67c9..9acb62e0717 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNConfigTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNConfigTest.m @@ -23,6 +23,7 @@ #import "FirebaseRemoteConfig/Sources/RCNConfigExperiment.h" #import "FirebaseRemoteConfig/Sources/RCNConfigValue_Internal.h" #import "FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.h" +@import FirebaseRemoteConfigInterop; static NSString *const RCNFakeSenderID = @"855865492447"; static NSString *const RCNFakeToken = @"ctToAh17Exk:" @@ -48,6 +49,7 @@ @interface RCNConfigTest : XCTestCase { RCNConfigExperiment *_experiment; RCNConfigFetch *_configFetch; dispatch_queue_t _queue; + NSString *_namespaceGoogleMobilePlatform; } @end @@ -66,9 +68,10 @@ - (void)setUp { experiment:_experiment queue:_queue]; _configFetch = OCMPartialMock(fetcher); + _namespaceGoogleMobilePlatform = FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform; // Fake a response with a default namespace and a custom namespace. NSDictionary *namespaceToConfig = @{ - FIRNamespaceGoogleMobilePlatform : @{@"key1" : @"value1", @"key2" : @"value2"}, + _namespaceGoogleMobilePlatform : @{@"key1" : @"value1", @"key2" : @"value2"}, FIRNamespaceGooglePlayPlatform : @{@"playerID" : @"36", @"gameLevel" : @"87"}, }; _response = @@ -149,19 +152,19 @@ - (void)testFetchAllConfigsSuccessfully { XCTAssertNotNil(result); [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key1" value:@"value1"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key2" value:@"value2"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGooglePlayPlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"playerID" value:@"36"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGooglePlayPlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"gameLevel" value:@"87"]; XCTAssertEqual(self->_settings.expirationInSeconds, 43200, @@ -200,11 +203,11 @@ - (void)testFetchConfigInCachedResults { NSDictionary *result = self->_configContent.fetchedConfig; XCTAssertNotNil(result); [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key1" value:@"value1"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key2" value:@"value2"]; @@ -246,19 +249,19 @@ - (void)testFetchFailedWithCachedResult { XCTAssertNotNil(result); [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key1" value:@"value1"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key2" value:@"value2"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGooglePlayPlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"playerID" value:@"36"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGooglePlayPlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"gameLevel" value:@"87"]; @@ -340,19 +343,19 @@ - (void)testFetchThrottledWithStaledCachedResult { NSDictionary *result = self->_configContent.fetchedConfig; XCTAssertNotNil(result); [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key1" value:@"value1"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGoogleMobilePlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"key2" value:@"value2"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGooglePlayPlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"playerID" value:@"36"]; [self checkConfigResult:result - withNamespace:FIRNamespaceGooglePlayPlatform + withNamespace:_namespaceGoogleMobilePlatform key:@"gameLevel" value:@"87"]; XCTAssertEqual( diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNInstanceIDTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNInstanceIDTest.m index 5d1b28fb61d..cbbcd0a91bd 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNInstanceIDTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNInstanceIDTest.m @@ -29,6 +29,7 @@ #import #import "FirebaseCore/Extension/FirebaseCoreInternal.h" #import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h" +@import FirebaseRemoteConfigInterop; @interface RCNConfigFetch (ForTest) - (instancetype)initWithContent:(RCNConfigContent *)content @@ -136,7 +137,8 @@ - (void)setUpConfigMock { case RCNTestRCInstanceSecondApp: currentAppName = RCNTestsSecondFIRAppName; currentOptions = [self secondAppOptions]; - currentNamespace = FIRNamespaceGoogleMobilePlatform; + currentNamespace = FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform; + ; break; case RCNTestRCInstanceDefault: default: diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m index e1a23b5a695..e02b8ecaabf 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m @@ -18,6 +18,7 @@ #import #import +#import "FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.h" #import "FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h" #import "FirebaseRemoteConfig/Sources/Private/RCNConfigFetch.h" #import "FirebaseRemoteConfig/Sources/Public/FirebaseRemoteConfig/FIRRemoteConfig.h" @@ -31,6 +32,9 @@ #import #import "FirebaseCore/Extension/FirebaseCoreInternal.h" +@import FirebaseRemoteConfigInterop; + +@protocol FIRRolloutsStateSubscriber; @interface RCNConfigFetch (ForTest) - (instancetype)initWithContent:(RCNConfigContent *)content @@ -130,6 +134,7 @@ @interface RCNRemoteConfigTest : XCTestCase { NSTimeInterval _checkCompletionTimeout; NSMutableArray *_configInstances; NSMutableArray *> *_entries; + NSArray *_rolloutMetadata; NSMutableArray *> *_response; NSMutableArray *_responseData; NSMutableArray *_URLResponse; @@ -145,6 +150,7 @@ @interface RCNRemoteConfigTest : XCTestCase { NSString *_fullyQualifiedNamespace; RCNConfigSettings *_settings; dispatch_queue_t _queue; + NSString *_namespaceGoogleMobilePlatform; } @end @@ -180,6 +186,7 @@ - (void)setUp { _URLResponse = [[NSMutableArray alloc] initWithCapacity:3]; _configFetch = [[NSMutableArray alloc] initWithCapacity:3]; _configRealtime = [[NSMutableArray alloc] initWithCapacity:3]; + _namespaceGoogleMobilePlatform = FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform; // Populate the default, second app, second namespace instances. for (int i = 0; i < RCNTestRCNumTotalInstances; i++) { @@ -204,7 +211,7 @@ - (void)setUp { case RCNTestRCInstanceSecondApp: currentAppName = RCNTestsSecondFIRAppName; currentOptions = [self secondAppOptions]; - currentNamespace = FIRNamespaceGoogleMobilePlatform; + currentNamespace = _namespaceGoogleMobilePlatform; break; case RCNTestRCInstanceDefault: default: @@ -259,7 +266,17 @@ __unsafe_unretained void (^handler)(FIRRemoteConfigFetchStatus status, updateCompletionHandler:nil]; }); - _response[i] = @{@"state" : @"UPDATE", @"entries" : _entries[i]}; + _rolloutMetadata = @[ @{ + RCNFetchResponseKeyRolloutID : @"1", + RCNFetchResponseKeyVariantID : @"0", + RCNFetchResponseKeyAffectedParameterKeys : @[ _entries[i].allKeys[0] ] + } ]; + + _response[i] = @{ + @"state" : @"UPDATE", + @"entries" : _entries[i], + RCNFetchResponseKeyRolloutMetadata : _rolloutMetadata + }; _responseData[i] = [NSJSONSerialization dataWithJSONObject:_response[i] options:0 error:nil]; @@ -286,6 +303,7 @@ __unsafe_unretained void (^handler)(FIRRemoteConfigFetchStatus status, - (void)tearDown { [_DBManager removeDatabaseOnDatabaseQueueAtPath:_DBPath]; + [FIRRemoteConfigComponent clearAllComponentInstances]; [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:_userDefaultsSuiteName]; [_DBManagerMock stopMocking]; _DBManagerMock = nil; @@ -594,7 +612,7 @@ - (void)testFetchConfigsFailed { case RCNTestRCInstanceSecondApp: currentAppName = RCNTestsSecondFIRAppName; currentOptions = [self secondAppOptions]; - currentNamespace = FIRNamespaceGoogleMobilePlatform; + currentNamespace = _namespaceGoogleMobilePlatform; break; case RCNTestRCInstanceDefault: default: @@ -707,7 +725,7 @@ - (void)testFetchConfigsFailedErrorNoNetwork { case RCNTestRCInstanceSecondApp: currentAppName = RCNTestsSecondFIRAppName; currentOptions = [self secondAppOptions]; - currentNamespace = FIRNamespaceGoogleMobilePlatform; + currentNamespace = _namespaceGoogleMobilePlatform; break; case RCNTestRCInstanceDefault: default: @@ -911,7 +929,7 @@ - (void)testActivateOnFetchNoChangeStatus { case RCNTestRCInstanceSecondApp: currentAppName = RCNTestsSecondFIRAppName; currentOptions = [self secondAppOptions]; - currentNamespace = FIRNamespaceGoogleMobilePlatform; + currentNamespace = _namespaceGoogleMobilePlatform; break; case RCNTestRCInstanceDefault: default: @@ -1782,6 +1800,43 @@ - (void)testRealtimeStreamRequestBody { XCTAssertTrue([strData containsString:@"appInstanceId:'iid'"]); } +- (void)testFetchAndActivateRolloutsNotifyInterop { + id mockNotificationCenter = [OCMockObject mockForClass:[NSNotificationCenter class]]; + [[mockNotificationCenter expect] postNotificationName:@"RolloutsStateDidChangeNotification" + object:[OCMArg any] + userInfo:[OCMArg any]]; + id mockSubscriber = [OCMockObject mockForProtocol:@protocol(FIRRolloutsStateSubscriber)]; + [[mockSubscriber expect] rolloutsStateDidChange:[OCMArg any]]; + + XCTestExpectation *expectation = [self + expectationWithDescription:[NSString + stringWithFormat:@"Test rollout update send notification"]]; + + XCTAssertEqual(_configInstances[RCNTestRCInstanceDefault].lastFetchStatus, + FIRRemoteConfigFetchStatusNoFetchYet); + + FIRRemoteConfigFetchAndActivateCompletion fetchAndActivateCompletion = + ^void(FIRRemoteConfigFetchAndActivateStatus status, NSError *error) { + XCTAssertEqual(status, FIRRemoteConfigFetchAndActivateStatusSuccessFetchedFromRemote); + XCTAssertNil(error); + + XCTAssertEqual(self->_configInstances[RCNTestRCInstanceDefault].lastFetchStatus, + FIRRemoteConfigFetchStatusSuccess); + XCTAssertNotNil(self->_configInstances[RCNTestRCInstanceDefault].lastFetchTime); + XCTAssertGreaterThan( + self->_configInstances[RCNTestRCInstanceDefault].lastFetchTime.timeIntervalSince1970, 0, + @"last fetch time interval should be set."); + [expectation fulfill]; + }; + + [_configInstances[RCNTestRCInstanceDefault] + fetchAndActivateWithCompletionHandler:fetchAndActivateCompletion]; + [self waitForExpectationsWithTimeout:_expectationTimeout + handler:^(NSError *error) { + XCTAssertNil(error); + }]; +} + #pragma mark - Test Helpers - (FIROptions *)firstAppOptions { diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNThrottlingTests.m b/FirebaseRemoteConfig/Tests/Unit/RCNThrottlingTests.m index 8721463feb8..5429c61df1f 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNThrottlingTests.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNThrottlingTests.m @@ -25,6 +25,7 @@ #import "FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.h" #import "FirebaseCore/Extension/FirebaseCoreInternal.h" +@import FirebaseRemoteConfigInterop; @interface RCNThrottlingTests : XCTestCase { RCNConfigContent *_configContentMock; @@ -53,20 +54,22 @@ - (void)setUp { RCNConfigDBManager *DBManager = [[RCNConfigDBManager alloc] init]; _configContentMock = OCMClassMock([RCNConfigContent class]); - _settings = [[RCNConfigSettings alloc] initWithDatabaseManager:DBManager - namespace:FIRNamespaceGoogleMobilePlatform - app:[FIRApp defaultApp]]; + _settings = [[RCNConfigSettings alloc] + initWithDatabaseManager:DBManager + namespace:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform + app:[FIRApp defaultApp]]; _experimentMock = OCMClassMock([RCNConfigExperiment class]); dispatch_queue_t _queue = dispatch_queue_create( "com.google.GoogleConfigService.FIRRemoteConfigTest", DISPATCH_QUEUE_SERIAL); - _configFetch = [[RCNConfigFetch alloc] initWithContent:_configContentMock - DBManager:DBManager - settings:_settings - experiment:_experimentMock - queue:_queue - namespace:FIRNamespaceGoogleMobilePlatform - app:[FIRApp defaultApp]]; + _configFetch = [[RCNConfigFetch alloc] + initWithContent:_configContentMock + DBManager:DBManager + settings:_settings + experiment:_experimentMock + queue:_queue + namespace:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform + app:[FIRApp defaultApp]]; } - (void)mockFetchResponseWithStatusCode:(NSInteger)statusCode { diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNUserDefaultsManagerTests.m b/FirebaseRemoteConfig/Tests/Unit/RCNUserDefaultsManagerTests.m index 0c3135e2edd..5f915d73632 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNUserDefaultsManagerTests.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNUserDefaultsManagerTests.m @@ -129,8 +129,17 @@ - (void)testUserDefaultsTemplateVersionWriteAndRead { [[RCNUserDefaultsManager alloc] initWithAppName:AppName bundleID:[NSBundle mainBundle].bundleIdentifier namespace:FQNamespace1]; - [manager setLastTemplateVersion:@"1"]; - XCTAssertEqual([manager lastTemplateVersion], @"1"); + [manager setLastFetchedTemplateVersion:@"1"]; + XCTAssertEqual([manager lastFetchedTemplateVersion], @"1"); +} + +- (void)testUserDefaultsActiveTemplateVersionWriteAndRead { + RCNUserDefaultsManager* manager = + [[RCNUserDefaultsManager alloc] initWithAppName:AppName + bundleID:[NSBundle mainBundle].bundleIdentifier + namespace:FQNamespace1]; + [manager setLastActiveTemplateVersion:@"1"]; + XCTAssertEqual([manager lastActiveTemplateVersion], @"1"); } - (void)testUserDefaultsRealtimeThrottleEndTimeWriteAndRead { @@ -229,10 +238,16 @@ - (void)testUserDefaultsForMultipleNamespaces { XCTAssertEqual([manager2 realtimeRetryCount], 2); /// Fetch template version. - [manager1 setLastTemplateVersion:@"1"]; - [manager2 setLastTemplateVersion:@"2"]; - XCTAssertEqualObjects([manager1 lastTemplateVersion], @"1"); - XCTAssertEqualObjects([manager2 lastTemplateVersion], @"2"); + [manager1 setLastFetchedTemplateVersion:@"1"]; + [manager2 setLastFetchedTemplateVersion:@"2"]; + XCTAssertEqualObjects([manager1 lastFetchedTemplateVersion], @"1"); + XCTAssertEqualObjects([manager2 lastFetchedTemplateVersion], @"2"); + + /// Active template version. + [manager1 setLastActiveTemplateVersion:@"1"]; + [manager2 setLastActiveTemplateVersion:@"2"]; + XCTAssertEqualObjects([manager1 lastActiveTemplateVersion], @"1"); + XCTAssertEqualObjects([manager2 lastActiveTemplateVersion], @"2"); } - (void)testUserDefaultsReset { diff --git a/FirebaseRemoteConfig/generate_featureRolloutsTestApp.sh b/FirebaseRemoteConfig/generate_featureRolloutsTestApp.sh new file mode 100755 index 00000000000..1667fc0fe5a --- /dev/null +++ b/FirebaseRemoteConfig/generate_featureRolloutsTestApp.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Copyright 2022 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. +# + +readonly DIR="$( git rev-parse --show-toplevel )" + +# +# This script attempts to copy the Google Services file from google3. If you are not a Google Employee, it will fail, so we'd recommend you create your own Firebase App and place the Google Services file in Tests/TestApp/Shared +# + +echoColor() { + COLOR='\033[0;35m' + NC='\033[0m' + printf "${COLOR}$1${NC}\n" +} + +echoRed() { + COLOR='\033[0;31m' + NC='\033[0m' + printf "${COLOR}$1${NC}\n" +} + +echoColor "Generating Firebase Remote Config Feature Rolouts Test App" +echoColor "Copying GoogleService-Info.plist from google3. Checking gcert status" +if gcertstatus; then + G3Path="/google/src/files/head/depot/google3/third_party/firebase/ios/Secrets/RemoteConfig/FeatureRollouts/GoogleService-Info.plist" + Dest="$DIR/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp/Shared" + cp $G3Path $Dest + echoColor "Copied $G3Path to $Dest" +else + echoRed "gcert token is not valid. If you are a Google Employee, run 'gcert', and then repeat this command. Non-Google employees will need to download a GoogleService-Info.plist and place it in $DIR/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp" +fi + + +echoColor "Running 'pod install'" +cd $DIR/FirebaseRemoteConfig/Tests/FeatureRolloutsTestApp +pod install + +# Upon a `pod install`, Crashlytics will copy these files at the root directory +# due to a funky interaction with its cocoapod. This line deletes these extra +# copies of the files as they should only live in Crashlytics/ +rm -f $DIR/run $DIR/upload-symbols + +open *.xcworkspace + diff --git a/FirebaseRemoteConfigInterop.podspec b/FirebaseRemoteConfigInterop.podspec new file mode 100644 index 00000000000..86b86b24e6a --- /dev/null +++ b/FirebaseRemoteConfigInterop.podspec @@ -0,0 +1,34 @@ +Pod::Spec.new do |s| + s.name = 'FirebaseRemoteConfigInterop' + s.version = '10.23.0' + s.summary = 'Interfaces that allow other Firebase SDKs to use Remote Config functionality.' + + s.description = <<-DESC + Not for public use. + A set of protocols that other Firebase SDKs can use to interoperate with FirebaseRemoetConfig in a safe + and reliable manner. + DESC + + s.homepage = 'https://firebase.google.com' + s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } + s.authors = 'Google, Inc.' + + # NOTE that these should not be used externally, this is for Firebase pods to depend on each + # other. + s.source = { + :git => 'https://github.com/firebase/firebase-ios-sdk.git', + :tag => 'CocoaPods-' + s.version.to_s + } + + s.swift_version = '5.3' + s.cocoapods_version = '>= 1.12.0' + s.prefix_header_file = false + + s.social_media_url = 'https://twitter.com/Firebase' + s.ios.deployment_target = '11.0' + s.osx.deployment_target = '10.13' + s.tvos.deployment_target = '12.0' + s.watchos.deployment_target = '6.0' + + s.source_files = 'FirebaseRemoteConfig/Interop/*.swift' +end diff --git a/FirebaseRemoteConfigSwift/Tests/SwiftAPI/FirebaseRemoteConfigSwift_APIBuildTests.swift b/FirebaseRemoteConfigSwift/Tests/SwiftAPI/FirebaseRemoteConfigSwift_APIBuildTests.swift index b695e375887..892f14ec834 100644 --- a/FirebaseRemoteConfigSwift/Tests/SwiftAPI/FirebaseRemoteConfigSwift_APIBuildTests.swift +++ b/FirebaseRemoteConfigSwift/Tests/SwiftAPI/FirebaseRemoteConfigSwift_APIBuildTests.swift @@ -16,6 +16,7 @@ import XCTest import FirebaseCore import FirebaseRemoteConfig +import FirebaseRemoteConfigInterop import FirebaseRemoteConfigSwift final class FirebaseRemoteConfigSwift_APIBuildTests: XCTestCase { diff --git a/FirebaseSessions/Tests/TestApp/Podfile b/FirebaseSessions/Tests/TestApp/Podfile index 67c05149217..4bea966bc4f 100644 --- a/FirebaseSessions/Tests/TestApp/Podfile +++ b/FirebaseSessions/Tests/TestApp/Podfile @@ -7,6 +7,7 @@ def shared_pods pod 'FirebaseCoreInternal', :path => '../../../' pod 'FirebaseCoreExtension', :path => '../../../' pod 'FirebaseSessions', :path => '../../../' + pod 'FirebaseRemoteConfigInterop', :path => '../../../' end target 'AppQualityDevApp_iOS' do diff --git a/IntegrationTesting/ClientApp/Podfile b/IntegrationTesting/ClientApp/Podfile index 7efd2cdd1ea..2a72d478739 100644 --- a/IntegrationTesting/ClientApp/Podfile +++ b/IntegrationTesting/ClientApp/Podfile @@ -17,6 +17,7 @@ target 'ClientApp-CocoaPods' do pod 'FirebaseAppCheck', :path => '../../' pod 'FirebaseRemoteConfig', :path => '../../' pod 'FirebaseRemoteConfigSwift', :path => '../../' + pod 'FirebaseRemoteConfigInterop', :path => '../../' pod 'FirebaseAppDistribution', :path => '../../' pod 'FirebaseAuth', :path => '../../' pod 'FirebaseCrashlytics', :path => '../../' diff --git a/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile b/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile index 03bfe2e2d04..e45e8cd4908 100644 --- a/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile +++ b/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile @@ -25,6 +25,7 @@ target 'CocoapodsIntegrationTest' do pod 'FirebaseInstallations', :path => '../../' pod 'FirebaseMessaging', :path => '../../' pod 'FirebaseMessagingInterop', :path => '../../' + pod 'FirebaseRemoteConfigInterop', :path => '../../' pod 'FirebasePerformance', :path => '../../' pod 'FirebaseStorage', :path => '../../' end diff --git a/Package.swift b/Package.swift index ae854aa3f10..cd16df6ca5f 100644 --- a/Package.swift +++ b/Package.swift @@ -497,11 +497,17 @@ let package = Package( ), .target( name: "FirebaseCrashlytics", - dependencies: ["FirebaseCore", "FirebaseInstallations", "FirebaseSessions", - .product(name: "GoogleDataTransport", package: "GoogleDataTransport"), - .product(name: "GULEnvironment", package: "GoogleUtilities"), - .product(name: "FBLPromises", package: "Promises"), - .product(name: "nanopb", package: "nanopb")], + dependencies: [ + "FirebaseCore", + "FirebaseInstallations", + "FirebaseSessions", + "FirebaseRemoteConfigInterop", + "FirebaseCrashlyticsSwift", + .product(name: "GoogleDataTransport", package: "GoogleDataTransport"), + .product(name: "GULEnvironment", package: "GoogleUtilities"), + .product(name: "FBLPromises", package: "Promises"), + .product(name: "nanopb", package: "nanopb"), + ], path: "Crashlytics", exclude: [ "run", @@ -514,6 +520,7 @@ let package = Package( "upload-symbols", "CrashlyticsInputFiles.xcfilelist", "third_party/libunwind/LICENSE", + "Crashlytics/Rollouts/", ], sources: [ "Crashlytics/", @@ -543,6 +550,19 @@ let package = Package( .linkedFramework("SystemConfiguration", .when(platforms: [.iOS, .macOS, .tvOS])), ] ), + .target( + name: "FirebaseCrashlyticsSwift", + dependencies: ["FirebaseRemoteConfigInterop"], + path: "Crashlytics", + sources: [ + "Crashlytics/Rollouts/", + ] + ), + .testTarget( + name: "FirebaseCrashlyticsSwiftUnit", + dependencies: ["FirebaseCrashlyticsSwift"], + path: "Crashlytics/UnitTestsSwift/" + ), .testTarget( name: "FirebaseCrashlyticsUnit", dependencies: ["FirebaseCrashlytics", .product(name: "OCMock", package: "ocmock")], @@ -967,6 +987,7 @@ let package = Package( "FirebaseCore", "FirebaseABTesting", "FirebaseInstallations", + "FirebaseRemoteConfigInterop", .product(name: "GULNSData", package: "GoogleUtilities"), ], path: "FirebaseRemoteConfig/Sources", @@ -996,6 +1017,14 @@ let package = Package( .headerSearchPath("../../.."), ] ), + .testTarget( + name: "RemoteConfigSwiftUnit", + dependencies: ["FirebaseRemoteConfigInternal"], + path: "FirebaseRemoteConfig/Tests/SwiftUnit", + cSettings: [ + .headerSearchPath("../../.."), + ] + ), .target( name: "FirebaseRemoteConfig", dependencies: [ @@ -1039,6 +1068,15 @@ let package = Package( .headerSearchPath("../../../"), ] ), + // Internal headers only for consuming from other SDK. + .target( + name: "FirebaseRemoteConfigInterop", + path: "FirebaseRemoteConfig/Interop", + publicHeadersPath: ".", + cSettings: [ + .headerSearchPath("../../"), + ] + ), // MARK: - Firebase Sessions diff --git a/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift b/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift index 5bd4f3dd5e2..8575cf37e36 100755 --- a/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift +++ b/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift @@ -32,6 +32,7 @@ public let shared = Manifest( Pod("FirebaseMessagingInterop"), Pod("FirebaseInstallations"), Pod("FirebaseSessions"), + Pod("FirebaseRemoteConfigInterop"), Pod("GoogleAppMeasurement", isClosedSource: true), Pod("GoogleAppMeasurementOnDeviceConversion", isClosedSource: true, platforms: ["ios"]), Pod("FirebaseAnalytics", isClosedSource: true, zip: true), diff --git a/scripts/localize_podfile.swift b/scripts/localize_podfile.swift index f07cb3124a0..8b60a2cbdd5 100755 --- a/scripts/localize_podfile.swift +++ b/scripts/localize_podfile.swift @@ -39,6 +39,7 @@ let implicitPods = [ "FirebaseAppCheckInterop", "FirebaseAuthInterop", "FirebaseMessagingInterop", "FirebaseCoreInternal", "FirebaseSessions", "FirebaseSharedSwift", + "FirebaseRemoteConfigInterop", ] let binaryPods = [ From b40cc2404bd07038ac18abe972f59111e5f8d21c Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Mon, 11 Mar 2024 15:51:38 -0700 Subject: [PATCH 14/25] [spm] Update grpc to 1.62.3 (#12520) --- Firestore/CHANGELOG.md | 1 + Package.swift | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Firestore/CHANGELOG.md b/Firestore/CHANGELOG.md index ceded5649ef..1a829eb0d68 100644 --- a/Firestore/CHANGELOG.md +++ b/Firestore/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased - [feature] Enable snapshot listener option to retrieve data from local cache only. (#12370) +- [fixed] Update gRPC dependency to 1.62.* (#12098, #12021) # 10.22.0 - [fixed] Fix the flaky offline behaviour when using `arrayRemove` on `Map` object. (#12378) diff --git a/Package.swift b/Package.swift index cd16df6ca5f..8a69c5c61b8 100644 --- a/Package.swift +++ b/Package.swift @@ -1373,7 +1373,7 @@ func abseilDependency() -> Package.Dependency { if ProcessInfo.processInfo.environment["FIREBASE_SOURCE_FIRESTORE"] != nil { packageInfo = ( "https://github.com/firebase/abseil-cpp-SwiftPM.git", - "0.20220623.0" ..< "0.20220624.0" + "0.20240116.1" ..< "0.20240117.0" ) } else { packageInfo = ( @@ -1391,7 +1391,7 @@ func grpcDependency() -> Package.Dependency { // If building Firestore from source, abseil will need to be built as source // as the headers in the binary version of abseil are unusable. if ProcessInfo.processInfo.environment["FIREBASE_SOURCE_FIRESTORE"] != nil { - packageInfo = ("https://github.com/grpc/grpc-ios.git", "1.49.1" ..< "1.50.0") + packageInfo = ("https://github.com/grpc/grpc-ios.git", "1.62.3" ..< "1.63.0") } else { packageInfo = ("https://github.com/google/grpc-binary.git", "1.49.1" ..< "1.50.0") } From 1de0529ed37beb6cbed9e98c4475496588e10857 Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Mon, 11 Mar 2024 19:22:04 -0400 Subject: [PATCH 15/25] [Release Tooling] Copy over macOS/macCatalyst plists (#12517) --- FirebaseCore/CHANGELOG.md | 3 +++ .../Sources/ZipBuilder/FrameworkBuilder.swift | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/FirebaseCore/CHANGELOG.md b/FirebaseCore/CHANGELOG.md index 79ec5d5f636..4337e81de12 100644 --- a/FirebaseCore/CHANGELOG.md +++ b/FirebaseCore/CHANGELOG.md @@ -1,3 +1,6 @@ +# Unreleased +- Fix validation issue for macOS and macCatalyst XCFrameworks. (#12505) + # Firebase 10.22.1 - [Swift Package Manager / CocoaPods] Fix app validation issues on Xcode 15.3 for those using the `FirebaseAnalyticsOnDeviceConversion` SDK. This issue was diff --git a/ReleaseTooling/Sources/ZipBuilder/FrameworkBuilder.swift b/ReleaseTooling/Sources/ZipBuilder/FrameworkBuilder.swift index 7c763834411..d322aa91ec4 100755 --- a/ReleaseTooling/Sources/ZipBuilder/FrameworkBuilder.swift +++ b/ReleaseTooling/Sources/ZipBuilder/FrameworkBuilder.swift @@ -674,7 +674,18 @@ struct FrameworkBuilder { let binaryName = frameworkPath.lastPathComponent.replacingOccurrences(of: ".framework", with: "") let fatBinary = frameworkPath.appendingPathComponent(binaryName).resolvingSymlinksInPath() - let infoPlist = frameworkPath.appendingPathComponent("Info.plist").resolvingSymlinksInPath() + let plistPathComponents = { + if platform == .catalyst || platform == .macOS { + // Frameworks for macOS and macCatalyst have a different directory + // structure so the framework-level `Info.plist` is found in a + // different spot. + return ["Versions", "A", "Resources", "Info.plist"] + } else { + return ["Info.plist"] + } + }() + let infoPlist = frameworkPath.appendingPathComponents(plistPathComponents) + .resolvingSymlinksInPath() let infoPlistDestination = platformFrameworkDir.appendingPathComponent("Info.plist") let fatBinaryDestination = platformFrameworkDir.appendingPathComponent(framework) do { @@ -698,7 +709,9 @@ struct FrameworkBuilder { try updatedPlistData.write(to: infoPlistDestination) } catch { - // The Catalyst and macos Info.plist's are in another location. Ignore failure. + fatalError( + "Could not copy framework-level plist to framework directory for \(framework): \(error)" + ) } // Use the appropriate moduleMaps From 5b3907f9913cd4e87323aa16c09d01e269e494b4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 07:17:50 -0700 Subject: [PATCH 16/25] NOTICES Change (#12524) Co-authored-by: runner --- CoreOnly/NOTICES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CoreOnly/NOTICES b/CoreOnly/NOTICES index 659f6159e33..802eaf57d93 100644 --- a/CoreOnly/NOTICES +++ b/CoreOnly/NOTICES @@ -18,6 +18,7 @@ FirebaseMessaging FirebaseMessagingInterop FirebasePerformance FirebaseRemoteConfig +FirebaseRemoteConfigInterop FirebaseSessions FirebaseStorage GTMSessionFetcher @@ -253,6 +254,7 @@ record keeping.) 27287199 27287880 27287883 + 263291445 OpenSSL License --------------- From 370385c42aeec4810368089158ac1f3e9181a0ce Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Tue, 12 Mar 2024 09:50:06 -0700 Subject: [PATCH 17/25] Changelog updates for 10.23.0 (#12533) --- Crashlytics/CHANGELOG.md | 2 +- FirebaseCore/CHANGELOG.md | 2 +- FirebaseMessaging/CHANGELOG.md | 3 +++ FirebaseRemoteConfig/CHANGELOG.md | 2 +- Firestore/CHANGELOG.md | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Crashlytics/CHANGELOG.md b/Crashlytics/CHANGELOG.md index 62f507a7c01..ce0e9c89eea 100644 --- a/Crashlytics/CHANGELOG.md +++ b/Crashlytics/CHANGELOG.md @@ -1,4 +1,4 @@ -# Unreleased +# 10.23.0 - [added] Updated upload-symbols to 13.7 with VisionPro build phase support. (#12306) - [changed] Added support for Crashlytics to report metadata about Remote Config keys and values. diff --git a/FirebaseCore/CHANGELOG.md b/FirebaseCore/CHANGELOG.md index 4337e81de12..c5a879602d9 100644 --- a/FirebaseCore/CHANGELOG.md +++ b/FirebaseCore/CHANGELOG.md @@ -1,4 +1,4 @@ -# Unreleased +# Firebase 10.23.0 - Fix validation issue for macOS and macCatalyst XCFrameworks. (#12505) # Firebase 10.22.1 diff --git a/FirebaseMessaging/CHANGELOG.md b/FirebaseMessaging/CHANGELOG.md index e51c663ce33..8191c09c6b3 100644 --- a/FirebaseMessaging/CHANGELOG.md +++ b/FirebaseMessaging/CHANGELOG.md @@ -1,3 +1,6 @@ +# 10.23.0 +- [fixed] [CocoaPods] Fix "no rule" warning when running `pod install`. (#12511) + # 10.20.0 - [fixed] Fix 10.19.0 regression where the FCM registration token was nil at first app start after update from 10.19.0 or earlier. (#12245) diff --git a/FirebaseRemoteConfig/CHANGELOG.md b/FirebaseRemoteConfig/CHANGELOG.md index e56c9da1f2d..b2ba32e782c 100644 --- a/FirebaseRemoteConfig/CHANGELOG.md +++ b/FirebaseRemoteConfig/CHANGELOG.md @@ -1,4 +1,4 @@ -# Unreleased +# 10.23.0 - [changed] Add support for other Firebase products to integrate with Remote Config. # 10.17.0 diff --git a/Firestore/CHANGELOG.md b/Firestore/CHANGELOG.md index 1a829eb0d68..ee98034ed48 100644 --- a/Firestore/CHANGELOG.md +++ b/Firestore/CHANGELOG.md @@ -1,4 +1,4 @@ -# Unreleased +# 10.23.0 - [feature] Enable snapshot listener option to retrieve data from local cache only. (#12370) - [fixed] Update gRPC dependency to 1.62.* (#12098, #12021) From 3e7aa393c12c360fc97df254e31f8dd42d5b0e7b Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:25:34 -0400 Subject: [PATCH 18/25] [Firestore] Improve logging in scripts/check_firestore_symbols.sh (#12535) --- scripts/check_firestore_symbols.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/check_firestore_symbols.sh b/scripts/check_firestore_symbols.sh index fe2d41b9b50..5fb2de75acc 100755 --- a/scripts/check_firestore_symbols.sh +++ b/scripts/check_firestore_symbols.sh @@ -153,7 +153,7 @@ nm ~/Library/Developer/Xcode/DerivedData/TestPkg-ObjC/Build/Products/Debug/TestP # return exit code 1, which will cause the set pipefail to terminate execution. # To avoid this, `|| true` ensures the exit code always indicates success. DIFF=$( - git diff --no-index \ + git diff --no-index --output-indicator-new="?" \ objc_symbols_without_linker_flag.txt \ objc_symbols_with_linker_flag.txt \ || true @@ -161,6 +161,9 @@ DIFF=$( if [[ -n "$DIFF" ]]; then echo "Failure: Unlinked Objective-C symbols have been detected:" echo "$DIFF" + echo -n "💡 To fix, follow the process shown in " + echo -n "https://github.com/firebase/firebase-ios-sdk/pull/12534 for the " + echo "above symbols that are prefixed with ?" exit 1 else echo "Success: No unlinked Objective-C symbols have been detected." From f7645725be44de731e712ac96d79fa5ba6c5fb90 Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Tue, 12 Mar 2024 17:00:41 -0400 Subject: [PATCH 19/25] [Firestore] Add unlinked symbol introduced in #12370 (#12534) --- Firestore/Source/API/FIRFirestore.mm | 4 +++- Firestore/Source/API/FIRSnapshotListenOptions.mm | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Firestore/Source/API/FIRFirestore.mm b/Firestore/Source/API/FIRFirestore.mm index 29b56fd2a6b..f6dbf9dc059 100644 --- a/Firestore/Source/API/FIRFirestore.mm +++ b/Firestore/Source/API/FIRFirestore.mm @@ -567,12 +567,14 @@ - (void)terminateInternalWithCompletion:(nullable void (^)(NSError *_Nullable er #pragma mark - Force Link Unreferenced Symbols extern void FSTIncludeFSTFirestoreComponent(void); +extern void FSTIncludeFIRSnapshotListenOptions(void); -/// This method forces the linker to include all the Analytics categories without requiring app +/// This method forces the linker to include all Firestore symbols without requiring app /// developers to include the '-ObjC' linker flag in their projects. DO NOT CALL THIS METHOD. + (void)notCalled { NSAssert(NO, @"+notCalled should never be called"); FSTIncludeFSTFirestoreComponent(); + FSTIncludeFIRSnapshotListenOptions(); } @end diff --git a/Firestore/Source/API/FIRSnapshotListenOptions.mm b/Firestore/Source/API/FIRSnapshotListenOptions.mm index 9e22d686428..c1cb4216d43 100644 --- a/Firestore/Source/API/FIRSnapshotListenOptions.mm +++ b/Firestore/Source/API/FIRSnapshotListenOptions.mm @@ -58,6 +58,11 @@ - (FIRSnapshotListenOptions *)optionsWithSource:(FIRListenSource)source { return newOptions; } +/// This function forces the linker to include `FIRSnapshotListenOptions`. +/// See `+[FIRFirestore notCalled]`. +void FSTIncludeFIRSnapshotListenOptions(void) { +} + @end NS_ASSUME_NONNULL_END \ No newline at end of file From 77920e36c4a9d75cb87c5f5ba555ed61fbe6c144 Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Tue, 12 Mar 2024 18:10:16 -0400 Subject: [PATCH 20/25] [Firestore] Re-export public header added in #12370 (#12537) --- .../FirebaseFirestore/FIRSnapshotListenOptions.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 FirebaseFirestoreInternal/FirebaseFirestore/FIRSnapshotListenOptions.h diff --git a/FirebaseFirestoreInternal/FirebaseFirestore/FIRSnapshotListenOptions.h b/FirebaseFirestoreInternal/FirebaseFirestore/FIRSnapshotListenOptions.h new file mode 100644 index 00000000000..6d61e32c56b --- /dev/null +++ b/FirebaseFirestoreInternal/FirebaseFirestore/FIRSnapshotListenOptions.h @@ -0,0 +1,15 @@ +// Copyright 2024 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 From c8acb7625b7759fb239829caa282e3cf8fd49bbe Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Tue, 12 Mar 2024 18:55:10 -0400 Subject: [PATCH 21/25] [Firestore] Bump dependency ranges for Firestore's binary SPM distro (#12538) --- Package.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index 8a69c5c61b8..889a72f7788 100644 --- a/Package.swift +++ b/Package.swift @@ -1378,7 +1378,7 @@ func abseilDependency() -> Package.Dependency { } else { packageInfo = ( "https://github.com/google/abseil-cpp-binary.git", - "1.2022062300.0" ..< "1.2022062400.0" + "1.2024011601.0" ..< "1.2024011700.0" ) } @@ -1393,7 +1393,7 @@ func grpcDependency() -> Package.Dependency { if ProcessInfo.processInfo.environment["FIREBASE_SOURCE_FIRESTORE"] != nil { packageInfo = ("https://github.com/grpc/grpc-ios.git", "1.62.3" ..< "1.63.0") } else { - packageInfo = ("https://github.com/google/grpc-binary.git", "1.49.1" ..< "1.50.0") + packageInfo = ("https://github.com/google/grpc-binary.git", "1.62.1" ..< "1.63.0") } return .package(url: packageInfo.url, packageInfo.range) @@ -1532,8 +1532,8 @@ func firestoreTargets() -> [Target] { } else { return .binaryTarget( name: "FirebaseFirestoreInternal", - url: "https://dl.google.com/firebase/ios/bin/firestore/10.22.0/FirebaseFirestoreInternal.zip", - checksum: "35c02539c6bbd43ec1c3b58f894984e48ff8c560db0c799fb8f6377b59c96099" + url: "https://dl.google.com/firebase/ios/bin/firestore/10.23.0/FirebaseFirestoreInternal.zip", + checksum: "80050185438caedcf70a78737ed4da675445f18694b7617bf251962546bdec3b" ) } }() From 455e7d5cee32a1c325500a901523759c9ce88309 Mon Sep 17 00:00:00 2001 From: cherylEnkidu <96084918+cherylEnkidu@users.noreply.github.com> Date: Tue, 12 Mar 2024 18:56:18 -0400 Subject: [PATCH 22/25] Fix Firestore build warnings (#12536) --- Firestore/core/src/local/index_backfiller.cc | 7 ++++--- Firestore/core/src/local/index_backfiller.h | 10 ++++++---- Firestore/core/src/local/local_documents_view.cc | 2 +- Firestore/core/src/local/local_documents_view.h | 3 ++- Firestore/core/src/remote/bloom_filter.cc | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Firestore/core/src/local/index_backfiller.cc b/Firestore/core/src/local/index_backfiller.cc index b0be8be8fdf..1991031d4c6 100644 --- a/Firestore/core/src/local/index_backfiller.cc +++ b/Firestore/core/src/local/index_backfiller.cc @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include #include @@ -44,7 +45,7 @@ IndexBackfiller::IndexBackfiller() { max_documents_to_process_ = kMaxDocumentsToProcess; } -int IndexBackfiller::WriteIndexEntries(const LocalStore* local_store) { +size_t IndexBackfiller::WriteIndexEntries(const LocalStore* local_store) { IndexManager* index_manager = local_store->index_manager(); std::unordered_set processed_collection_groups; size_t documents_remaining = max_documents_to_process_; @@ -64,10 +65,10 @@ int IndexBackfiller::WriteIndexEntries(const LocalStore* local_store) { return max_documents_to_process_ - documents_remaining; } -int IndexBackfiller::WriteEntriesForCollectionGroup( +size_t IndexBackfiller::WriteEntriesForCollectionGroup( const LocalStore* local_store, const std::string& collection_group, - int documents_remaining_under_cap) const { + size_t documents_remaining_under_cap) const { IndexManager* index_manager = local_store->index_manager(); const auto* const local_documents_view = local_store->local_documents(); diff --git a/Firestore/core/src/local/index_backfiller.h b/Firestore/core/src/local/index_backfiller.h index 5ebd3aa8014..46c3ef1468d 100644 --- a/Firestore/core/src/local/index_backfiller.h +++ b/Firestore/core/src/local/index_backfiller.h @@ -15,6 +15,7 @@ #ifndef FIRESTORE_CORE_SRC_LOCAL_INDEX_BACKFILLER_H_ #define FIRESTORE_CORE_SRC_LOCAL_INDEX_BACKFILLER_H_ +#include #include namespace firebase { @@ -43,7 +44,7 @@ class IndexBackfiller { * Writes index entries until the cap is reached. Returns the number of * documents processed. */ - int WriteIndexEntries(const LocalStore* local_store); + size_t WriteIndexEntries(const LocalStore* local_store); private: friend class IndexBackfillerTest; @@ -53,9 +54,10 @@ class IndexBackfiller { * Writes entries for the provided collection group. Returns the number of * documents processed. */ - int WriteEntriesForCollectionGroup(const LocalStore* local_store, - const std::string& collection_group, - int documents_remaining_under_cap) const; + size_t WriteEntriesForCollectionGroup( + const LocalStore* local_store, + const std::string& collection_group, + size_t documents_remaining_under_cap) const; /** Returns the next offset based on the provided documents. */ model::IndexOffset GetNewOffset(const model::IndexOffset& existing_offset, diff --git a/Firestore/core/src/local/local_documents_view.cc b/Firestore/core/src/local/local_documents_view.cc index b4e2cd78807..d3812e42a5f 100644 --- a/Firestore/core/src/local/local_documents_view.cc +++ b/Firestore/core/src/local/local_documents_view.cc @@ -134,7 +134,7 @@ model::DocumentMap LocalDocumentsView::GetDocumentsMatchingCollectionGroupQuery( LocalWriteResult LocalDocumentsView::GetNextDocuments( const std::string& collection_group, const IndexOffset& offset, - int count) const { + size_t count) const { auto docs = remote_document_cache_->GetAll(collection_group, offset, count); auto overlays = count - docs.size() > 0 ? document_overlay_cache_->GetOverlays( diff --git a/Firestore/core/src/local/local_documents_view.h b/Firestore/core/src/local/local_documents_view.h index 7fc12b378fa..549656dc44e 100644 --- a/Firestore/core/src/local/local_documents_view.h +++ b/Firestore/core/src/local/local_documents_view.h @@ -17,6 +17,7 @@ #ifndef FIRESTORE_CORE_SRC_LOCAL_LOCAL_DOCUMENTS_VIEW_H_ #define FIRESTORE_CORE_SRC_LOCAL_LOCAL_DOCUMENTS_VIEW_H_ +#include #include #include #include @@ -98,7 +99,7 @@ class LocalDocumentsView { */ local::LocalWriteResult GetNextDocuments(const std::string& collection_group, const model::IndexOffset& offset, - int count) const; + size_t count) const; /** * Similar to `GetDocuments`, but creates the local view from the given diff --git a/Firestore/core/src/remote/bloom_filter.cc b/Firestore/core/src/remote/bloom_filter.cc index ddf84b866e9..0e4c8e04f34 100644 --- a/Firestore/core/src/remote/bloom_filter.cc +++ b/Firestore/core/src/remote/bloom_filter.cc @@ -78,7 +78,7 @@ int32_t BloomFilter::GetBitIndex(const Hash& hash, int32_t hash_index) const { uint64_t bit_index = combined_hash % bit_count_uint64; HARD_ASSERT(bit_index <= INT32_MAX); - return bit_index; + return static_cast(bit_index); } bool BloomFilter::IsBitSet(int32_t index) const { From 0afde381071e310612d9c02a037a3b805468ee5c Mon Sep 17 00:00:00 2001 From: htcgh Date: Tue, 12 Mar 2024 16:37:30 -0700 Subject: [PATCH 23/25] Analytics 10.23.0 (#12539) --- FirebaseAnalytics.podspec | 2 +- GoogleAppMeasurement.podspec | 2 +- Package.swift | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/FirebaseAnalytics.podspec b/FirebaseAnalytics.podspec index 0259cc52c58..2e5ef18ec3a 100644 --- a/FirebaseAnalytics.podspec +++ b/FirebaseAnalytics.podspec @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.authors = 'Google, Inc.' s.source = { - :http => 'https://dl.google.com/firebase/ios/analytics/d9e6824c98c32455/FirebaseAnalytics-10.22.0.tar.gz' + :http => 'https://dl.google.com/firebase/ios/analytics/dedc8d0f648c53b6/FirebaseAnalytics-10.23.0.tar.gz' } s.cocoapods_version = '>= 1.12.0' diff --git a/GoogleAppMeasurement.podspec b/GoogleAppMeasurement.podspec index 2167fa94cb5..2a3eec8af1e 100644 --- a/GoogleAppMeasurement.podspec +++ b/GoogleAppMeasurement.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| s.authors = 'Google, Inc.' s.source = { - :http => 'https://dl.google.com/firebase/ios/analytics/a92666f1e01923b8/GoogleAppMeasurement-10.22.0.tar.gz' + :http => 'https://dl.google.com/firebase/ios/analytics/0019598badd9f3d1/GoogleAppMeasurement-10.23.0.tar.gz' } s.cocoapods_version = '>= 1.12.0' diff --git a/Package.swift b/Package.swift index 889a72f7788..96fb48f9eea 100644 --- a/Package.swift +++ b/Package.swift @@ -314,8 +314,8 @@ let package = Package( ), .binaryTarget( name: "FirebaseAnalytics", - url: "https://dl.google.com/firebase/ios/swiftpm/10.22.0/FirebaseAnalytics-rc1.zip", - checksum: "78ce96a59962a8946f5df8dd57c7d0d83fd3cf0e14f3efab65c8c65fbdf03a8a" + url: "https://dl.google.com/firebase/ios/swiftpm/10.23.0/FirebaseAnalytics.zip", + checksum: "3fb2f7a91480cffd1dfe9c8f212626cf67860f2686f4ec74122df0e9b411ec53" ), .target( name: "FirebaseAnalyticsSwiftTarget", @@ -1362,7 +1362,7 @@ func googleAppMeasurementDependency() -> Package.Dependency { return .package(url: appMeasurementURL, branch: "main") } - return .package(url: appMeasurementURL, exact: "10.22.1") + return .package(url: appMeasurementURL, exact: "10.23.0") } func abseilDependency() -> Package.Dependency { From 135d4c7a0a22b416d43b002c4d8c2c5c4f8b8ca5 Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:19:37 -0400 Subject: [PATCH 24/25] [Release] Update FirebaseFirestoreInternal checksum (#12545) --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 96fb48f9eea..92a9f259386 100644 --- a/Package.swift +++ b/Package.swift @@ -1533,7 +1533,7 @@ func firestoreTargets() -> [Target] { return .binaryTarget( name: "FirebaseFirestoreInternal", url: "https://dl.google.com/firebase/ios/bin/firestore/10.23.0/FirebaseFirestoreInternal.zip", - checksum: "80050185438caedcf70a78737ed4da675445f18694b7617bf251962546bdec3b" + checksum: "1948320535897e818554f7b2e6e1eff8f6e0f8d779979daed881187613334c13" ) } }() From fcf5ced6dae2d43fced2581e673cc3b59bdb8ffa Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:36:18 -0400 Subject: [PATCH 25/25] [Release] Re-spin FST with signed artifact (#12549) --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index 92a9f259386..6e59b210092 100644 --- a/Package.swift +++ b/Package.swift @@ -1532,8 +1532,8 @@ func firestoreTargets() -> [Target] { } else { return .binaryTarget( name: "FirebaseFirestoreInternal", - url: "https://dl.google.com/firebase/ios/bin/firestore/10.23.0/FirebaseFirestoreInternal.zip", - checksum: "1948320535897e818554f7b2e6e1eff8f6e0f8d779979daed881187613334c13" + url: "https://dl.google.com/firebase/ios/bin/firestore/10.23.0/rc1/FirebaseFirestoreInternal.zip", + checksum: "777f89e6c453cca8dfdcc375304cd3f3059b55c4beab86dce3061c0ece1e0556" ) } }()