@@ -220,6 +220,45 @@ - (nonnull NSString*)tokenDidChangeNotificationName {
220
220
EXPECT_EQ (" token2" , token_future.get ());
221
221
}
222
222
223
+ // Regression test for https://github.com/firebase/firebase-ios-sdk/issues/8895
224
+ TEST (FirebaseAppCheckCredentialsProviderTest,
225
+ ListenDoesNotCrashIfUnrelatedNotificationsAreInvalid) {
226
+ auto token_promise = std::make_shared<std::promise<std::string>>();
227
+
228
+ FIRApp* app = testutil::AppForUnitTesting ();
229
+ FSTAppCheckFake* app_check = [[FSTAppCheckFake alloc ] initWithToken: @" " ];
230
+ FirebaseAppCheckCredentialsProvider credentials_provider (app, app_check);
231
+
232
+ credentials_provider.SetCredentialChangeListener (
233
+ [token_promise](const std::string& result) {
234
+ if (result != " " ) {
235
+ token_promise->set_value (result);
236
+ }
237
+ });
238
+
239
+ // Sending this notifcation would cause a crash if it was processed in the
240
+ // AppCheck notification handlder since AppCheck expects the userInfo object
241
+ // to an NSDictionary.
242
+ id userInfo = @" this_should_be_a_dictionary" ;
243
+ [[NSNotificationCenter defaultCenter ] postNotificationName: @" unrelated"
244
+ object: app_check
245
+ userInfo: userInfo];
246
+
247
+ // Send another valid notification that we can block on.
248
+ userInfo = @{
249
+ [app_check notificationTokenKey ] : @" token" ,
250
+ [app_check notificationAppNameKey ] : [app name ],
251
+ };
252
+ [[NSNotificationCenter defaultCenter ]
253
+ postNotificationName: [app_check tokenDidChangeNotificationName ]
254
+ object: app_check
255
+ userInfo: userInfo];
256
+
257
+ auto kTimeout = std::chrono::seconds (5 );
258
+ auto token_future = token_promise->get_future ();
259
+ ASSERT_EQ (std::future_status::ready, token_future.wait_for (kTimeout ));
260
+ }
261
+
223
262
} // namespace credentials
224
263
} // namespace firestore
225
264
} // namespace firebase
0 commit comments