From 9f282955d3673dc93212649cd8770c499b1eedbd Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 10:58:23 -0800 Subject: [PATCH 01/14] Add FLAKY_TEST_SECTION_RESET and use it to reset FCM in between flakes. --- .../integration_test/src/integration_test.cc | 60 +++++++++++++------ .../src/firebase_test_framework.h | 23 +++++++ 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 74b70c5698..4d8b0eb839 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -83,6 +83,9 @@ class FirebaseMessagingTest : public FirebaseTest { void SetUp() override; void TearDown() override; + bool InitializeMessaging(); + void TerminateMessaging(); + // Create a request and heads for a test message (returning false if unable to // do so). send_to can be a FCM token or a topic subscription. bool CreateTestMessage( @@ -145,6 +148,18 @@ void FirebaseMessagingTest::SetUpTestSuite() { LogDebug("Initializing Firebase Cloud Messaging."); shared_token_ = new std::string(); + if (InitializeMessaging()) { + LogDebug("Successfully initialized Firebase Cloud Messaging."); + } else { + LogDebug("Failed to initialize Firebase Cloud Messaging."); + } + is_desktop_stub_ = false; +#if !defined(ANDROID) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) + is_desktop_stub_ = true; +#endif // !defined(ANDROID) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) +} + +bool FirebaseMessagingTest::InitializeMessaging() { ::firebase::ModuleInitializer initializer; initializer.Initialize( shared_app_, &shared_listener_, [](::firebase::App* app, void* userdata) { @@ -176,23 +191,13 @@ void FirebaseMessagingTest::SetUpTestSuite() { ASSERT_EQ(initializer.InitializeLastResult().error(), 0) << initializer.InitializeLastResult().error_message(); - LogDebug("Successfully initialized Firebase Cloud Messaging."); - is_desktop_stub_ = false; -#if !defined(ANDROID) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) - is_desktop_stub_ = true; -#endif // !defined(ANDROID) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) + return (initializer.InitializeLastResult().error() == 0); } void FirebaseMessagingTest::TearDownTestSuite() { LogDebug("All tests finished, cleaning up."); - firebase::messaging::SetListener(nullptr); - delete shared_listener_; - shared_listener_ = nullptr; - delete shared_token_; - shared_token_ = nullptr; + TerminateMessaging(); - LogDebug("Shutdown Firebase Cloud Messaging."); - firebase::messaging::Terminate(); LogDebug("Shutdown Firebase App."); delete shared_app_; shared_app_ = nullptr; @@ -202,6 +207,18 @@ void FirebaseMessagingTest::TearDownTestSuite() { ProcessEvents(1000); } +void FirebaseMessagingTest::TerminateMessaging() { + firebase::messaging::SetListener(nullptr); + delete shared_listener_; + shared_listener_ = nullptr; + delete shared_token_; + shared_token_ = nullptr; + + LogDebug("Shutdown Firebase Cloud Messaging."); + firebase::messaging::Terminate(); +} + + FirebaseMessagingTest::FirebaseMessagingTest() { FindFirebaseConfig(FIREBASE_CONFIG_STRING); } @@ -362,15 +379,24 @@ TEST_F(FirebaseMessagingTest, TestReceiveToken) { SKIP_TEST_ON_ANDROID_EMULATOR; + FLAKY_TEST_SECTION_BEGIN(); + EXPECT_TRUE(RequestPermission()); EXPECT_TRUE(::firebase::messaging::IsTokenRegistrationOnInitEnabled()); - FLAKY_TEST_SECTION_BEGIN(); - EXPECT_TRUE(WaitForToken()); EXPECT_NE(*shared_token_, ""); + FLAKY_TEST_SECTION_RESET(); + + // This section will run after each failed flake attempt. If we failed to get + // a token, we might need to completely uninitialize messaging and + // reinitialize it. + TerminateMessaging(); + ProcessEvents(3000); // Pause a few seconds. + InitializeMessaging(); + FLAKY_TEST_SECTION_END(); } @@ -378,10 +404,8 @@ TEST_F(FirebaseMessagingTest, TestSubscribeAndUnsubscribe) { TEST_REQUIRES_USER_INTERACTION_ON_IOS; // TODO(b/196589796) Test fails on Android emulators and causes failures in - // our CI. Since we don't have a good way to deterine if the runtime is an - // emulator or real device, we should disable the test in CI until we find - // the cause of problem. - TEST_REQUIRES_USER_INTERACTION_ON_ANDROID; + // our CI. + SKIP_TEST_ON_ANDROID_EMULATOR; EXPECT_TRUE(RequestPermission()); EXPECT_TRUE(WaitForToken()); diff --git a/testing/test_framework/src/firebase_test_framework.h b/testing/test_framework/src/firebase_test_framework.h index c136657d79..ca585487b0 100644 --- a/testing/test_framework/src/firebase_test_framework.h +++ b/testing/test_framework/src/firebase_test_framework.h @@ -242,6 +242,10 @@ namespace firebase_test_framework { #define FLAKY_TEST_SECTION_BEGIN() RunFlakyTestSection([&]() { (void)0 #define FLAKY_TEST_SECTION_END() \ }) +// If you use FLAKY_TEST_SECTION_RESET, it will run the code in between this and +// FLAKY_TEST_SECTION_END after each failed flake attempt. +#define FLAKY_TEST_SECTION_RESET() \ + }, [&]() { (void)0 class FirebaseTest : public testing::Test { public: @@ -369,6 +373,25 @@ class FirebaseTest : public testing::Test { }); } + // This is the same as RunFlakyTestSection above, but it will call reset_function + // in between each flake attempt. + void RunFlakyTestSection(std::function flaky_test_section, + std::function reset_function) { + // Save the current state of test results. + auto saved_test_results = SaveTestPartResults(); + RunFlakyBlock([&]() { + RestoreTestPartResults(saved_test_results); + + flaky_test_section(); + + if (HasFailure()) { + reset_function(); + } + + return !HasFailure(); + }); + } + // Run an operation that returns a Future (via a callback), retrying with // exponential backoff if the operation fails. // From 0276fc93a65f1ff71d85aed408facbfff2f7b5a2 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 11:07:28 -0800 Subject: [PATCH 02/14] Format code. --- .../integration_test/src/integration_test.cc | 1 - .../src/firebase_test_framework.h | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 4d8b0eb839..5352ad3fe2 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -218,7 +218,6 @@ void FirebaseMessagingTest::TerminateMessaging() { firebase::messaging::Terminate(); } - FirebaseMessagingTest::FirebaseMessagingTest() { FindFirebaseConfig(FIREBASE_CONFIG_STRING); } diff --git a/testing/test_framework/src/firebase_test_framework.h b/testing/test_framework/src/firebase_test_framework.h index ca585487b0..11672f8909 100644 --- a/testing/test_framework/src/firebase_test_framework.h +++ b/testing/test_framework/src/firebase_test_framework.h @@ -237,15 +237,15 @@ namespace firebase_test_framework { #define DEATHTEST_SIGABRT "" #endif +// clang-format off // Macros to surround a flaky section of your test. // If this section fails, it will retry several times until it succeeds. #define FLAKY_TEST_SECTION_BEGIN() RunFlakyTestSection([&]() { (void)0 -#define FLAKY_TEST_SECTION_END() \ - }) +#define FLAKY_TEST_SECTION_END() }) // If you use FLAKY_TEST_SECTION_RESET, it will run the code in between this and // FLAKY_TEST_SECTION_END after each failed flake attempt. -#define FLAKY_TEST_SECTION_RESET() \ - }, [&]() { (void)0 +#define FLAKY_TEST_SECTION_RESET() }, [&]() { (void)0 +// clang-format on class FirebaseTest : public testing::Test { public: @@ -373,10 +373,10 @@ class FirebaseTest : public testing::Test { }); } - // This is the same as RunFlakyTestSection above, but it will call reset_function - // in between each flake attempt. + // This is the same as RunFlakyTestSection above, but it will call + // reset_function in between each flake attempt. void RunFlakyTestSection(std::function flaky_test_section, - std::function reset_function) { + std::function reset_function) { // Save the current state of test results. auto saved_test_results = SaveTestPartResults(); RunFlakyBlock([&]() { @@ -385,9 +385,9 @@ class FirebaseTest : public testing::Test { flaky_test_section(); if (HasFailure()) { - reset_function(); + reset_function(); } - + return !HasFailure(); }); } From c9a5c5cd9b084bc51631faa781bc3dc0150adfca Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 11:08:34 -0800 Subject: [PATCH 03/14] Fix statics. --- messaging/integration_test/src/integration_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 5352ad3fe2..5357141529 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -83,8 +83,8 @@ class FirebaseMessagingTest : public FirebaseTest { void SetUp() override; void TearDown() override; - bool InitializeMessaging(); - void TerminateMessaging(); + static bool InitializeMessaging(); + static void TerminateMessaging(); // Create a request and heads for a test message (returning false if unable to // do so). send_to can be a FCM token or a topic subscription. From 5bfbe2dec03d8b2e88701c98b79694a7d7fe19bc Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 11:33:35 -0800 Subject: [PATCH 04/14] Fix assert/return. --- messaging/integration_test/src/integration_test.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 5357141529..188b6a994f 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -148,11 +148,10 @@ void FirebaseMessagingTest::SetUpTestSuite() { LogDebug("Initializing Firebase Cloud Messaging."); shared_token_ = new std::string(); - if (InitializeMessaging()) { - LogDebug("Successfully initialized Firebase Cloud Messaging."); - } else { - LogDebug("Failed to initialize Firebase Cloud Messaging."); - } + ASSERT_TRUE(InitializeMessaging()); + + LogDebug("Successfully initialized Firebase Cloud Messaging."); + is_desktop_stub_ = false; #if !defined(ANDROID) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) is_desktop_stub_ = true; @@ -188,7 +187,7 @@ bool FirebaseMessagingTest::InitializeMessaging() { WaitForCompletion(initializer.InitializeLastResult(), "Initialize"); - ASSERT_EQ(initializer.InitializeLastResult().error(), 0) + EXPECT_EQ(initializer.InitializeLastResult().error(), 0) << initializer.InitializeLastResult().error_message(); return (initializer.InitializeLastResult().error() == 0); From 853101c5e630c53dbca24aa23d4f4ad0b0bcccac Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 12:03:38 -0800 Subject: [PATCH 05/14] Add log message when reinitializing FCM. --- messaging/integration_test/src/integration_test.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 188b6a994f..01a5dab865 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -391,6 +391,7 @@ TEST_F(FirebaseMessagingTest, TestReceiveToken) { // This section will run after each failed flake attempt. If we failed to get // a token, we might need to completely uninitialize messaging and // reinitialize it. + LogInfo("Reinitializing FCM before retry..."); TerminateMessaging(); ProcessEvents(3000); // Pause a few seconds. InitializeMessaging(); From 23c43bec1ad0cb57343d7014a0862bdd0e850fc6 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 12:51:07 -0800 Subject: [PATCH 06/14] Move log message. --- messaging/integration_test/src/integration_test.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 01a5dab865..0875db8628 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -150,8 +150,6 @@ void FirebaseMessagingTest::SetUpTestSuite() { ASSERT_TRUE(InitializeMessaging()); - LogDebug("Successfully initialized Firebase Cloud Messaging."); - is_desktop_stub_ = false; #if !defined(ANDROID) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) is_desktop_stub_ = true; @@ -190,6 +188,10 @@ bool FirebaseMessagingTest::InitializeMessaging() { EXPECT_EQ(initializer.InitializeLastResult().error(), 0) << initializer.InitializeLastResult().error_message(); + if (initializer.InitializeLastResult().error() == 0) { + LogDebug("Successfully initialized Firebase Cloud Messaging."); + } + return (initializer.InitializeLastResult().error() == 0); } From 44f367464f142449ac4d1282e445f63a0762674b Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 13:23:43 -0800 Subject: [PATCH 07/14] Fix reinitialization. --- messaging/integration_test/src/integration_test.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 0875db8628..988c97e23e 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -145,9 +145,6 @@ void FirebaseMessagingTest::SetUpTestSuite() { shared_app_ = ::firebase::App::Create(); #endif // defined(__ANDROID__) - LogDebug("Initializing Firebase Cloud Messaging."); - shared_token_ = new std::string(); - ASSERT_TRUE(InitializeMessaging()); is_desktop_stub_ = false; @@ -157,6 +154,9 @@ void FirebaseMessagingTest::SetUpTestSuite() { } bool FirebaseMessagingTest::InitializeMessaging() { + LogDebug("Initializing Firebase Cloud Messaging."); + shared_token_ = new std::string(); + ::firebase::ModuleInitializer initializer; initializer.Initialize( shared_app_, &shared_listener_, [](::firebase::App* app, void* userdata) { @@ -396,7 +396,7 @@ TEST_F(FirebaseMessagingTest, TestReceiveToken) { LogInfo("Reinitializing FCM before retry..."); TerminateMessaging(); ProcessEvents(3000); // Pause a few seconds. - InitializeMessaging(); + EXPECT_TRUE(InitializeMessaging()); FLAKY_TEST_SECTION_END(); } From 4b04915514fbcb9142512186bd7cb37d8536fb65 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 14:18:54 -0800 Subject: [PATCH 08/14] Format code. --- messaging/integration_test/src/integration_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 988c97e23e..397bd6a1c2 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -188,7 +188,7 @@ bool FirebaseMessagingTest::InitializeMessaging() { EXPECT_EQ(initializer.InitializeLastResult().error(), 0) << initializer.InitializeLastResult().error_message(); - if (initializer.InitializeLastResult().error() == 0) { + if (initializer.InitializeLastResult().error() == 0) { LogDebug("Successfully initialized Firebase Cloud Messaging."); } From b6c7d52e417944c7c8198964850f75d00bbb4c4c Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 14:20:21 -0800 Subject: [PATCH 09/14] Add nolint comments. --- testing/test_framework/src/firebase_test_framework.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/test_framework/src/firebase_test_framework.h b/testing/test_framework/src/firebase_test_framework.h index 11672f8909..1234a9b75f 100644 --- a/testing/test_framework/src/firebase_test_framework.h +++ b/testing/test_framework/src/firebase_test_framework.h @@ -240,10 +240,13 @@ namespace firebase_test_framework { // clang-format off // Macros to surround a flaky section of your test. // If this section fails, it will retry several times until it succeeds. +// NOLINTNEXTLINE #define FLAKY_TEST_SECTION_BEGIN() RunFlakyTestSection([&]() { (void)0 +// NOLINTNEXTLINE #define FLAKY_TEST_SECTION_END() }) // If you use FLAKY_TEST_SECTION_RESET, it will run the code in between this and // FLAKY_TEST_SECTION_END after each failed flake attempt. +// NOLINTNEXTLINE #define FLAKY_TEST_SECTION_RESET() }, [&]() { (void)0 // clang-format on From daead62c352c46a1c2fb002b11a38b7da124c64c Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 14:48:45 -0800 Subject: [PATCH 10/14] Also reinitialize App in between tests. --- .../integration_test/src/integration_test.cc | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 397bd6a1c2..da84b33db0 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -58,8 +58,9 @@ const char kRestEndpoint[] = "https://fcm.googleapis.com/fcm/send"; const char kNotificationLinkKey[] = "gcm.n.link"; const char kTestLink[] = "https://this-is-a-test-link/"; -// Give each operation approximately 120 seconds before failing. -const int kTimeoutSeconds = 120; +// Give each operation approximately 30 seconds before failing. +// Much longer than this and our FTL tests time out. +const int kTimeoutSeconds = 30; const char kTestingNotificationKey[] = "fcm_testing_notification"; using app_framework::LogDebug; @@ -136,15 +137,6 @@ firebase::messaging::PollableListener* FirebaseMessagingTest::shared_listener_ = bool FirebaseMessagingTest::is_desktop_stub_; void FirebaseMessagingTest::SetUpTestSuite() { - LogDebug("Initialize Firebase App."); - -#if defined(__ANDROID__) - shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(), - app_framework::GetActivity()); -#else - shared_app_ = ::firebase::App::Create(); -#endif // defined(__ANDROID__) - ASSERT_TRUE(InitializeMessaging()); is_desktop_stub_ = false; @@ -154,6 +146,15 @@ void FirebaseMessagingTest::SetUpTestSuite() { } bool FirebaseMessagingTest::InitializeMessaging() { + LogDebug("Initialize Firebase App."); + +#if defined(__ANDROID__) + shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(), + app_framework::GetActivity()); +#else + shared_app_ = ::firebase::App::Create(); +#endif // defined(__ANDROID__) + LogDebug("Initializing Firebase Cloud Messaging."); shared_token_ = new std::string(); @@ -197,11 +198,8 @@ bool FirebaseMessagingTest::InitializeMessaging() { void FirebaseMessagingTest::TearDownTestSuite() { LogDebug("All tests finished, cleaning up."); - TerminateMessaging(); - LogDebug("Shutdown Firebase App."); - delete shared_app_; - shared_app_ = nullptr; + TerminateMessaging(); // On iOS/FTL, most or all of the tests are skipped, so add a delay so the app // doesn't finish too quickly, as this makes test results flaky. @@ -217,6 +215,10 @@ void FirebaseMessagingTest::TerminateMessaging() { LogDebug("Shutdown Firebase Cloud Messaging."); firebase::messaging::Terminate(); + + LogDebug("Shutdown Firebase App."); + delete shared_app_; + shared_app_ = nullptr; } FirebaseMessagingTest::FirebaseMessagingTest() { From e2cbc99bbbe27a96da5b8880f0080f5a9f427b18 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Thu, 2 Feb 2023 19:26:14 -0800 Subject: [PATCH 11/14] Add better deflaking for other errors. --- .../integration_test/src/integration_test.cc | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index da84b33db0..ee3086d0af 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -539,11 +539,11 @@ TEST_F(FirebaseMessagingTest, TestSendMessageToToken) { SKIP_TEST_ON_ANDROID_EMULATOR; + FLAKY_TEST_SECTION_BEGIN(); + EXPECT_TRUE(RequestPermission()); EXPECT_TRUE(WaitForToken()); - FLAKY_TEST_SECTION_BEGIN(); - std::string unique_id = GetUniqueMessageId(); const char kNotificationTitle[] = "Token Test"; const char kNotificationBody[] = "Token Test notification body"; @@ -563,6 +563,16 @@ TEST_F(FirebaseMessagingTest, TestSendMessageToToken) { } EXPECT_EQ(message.link, kTestLink); + FLAKY_TEST_SECTION_RESET(); + + // This section will run after each failed flake attempt. If we failed to get + // a token, we might need to completely uninitialize messaging and + // reinitialize it. + LogInfo("Reinitializing FCM before retry..."); + TerminateMessaging(); + ProcessEvents(3000); // Pause a few seconds. + EXPECT_TRUE(InitializeMessaging()); + FLAKY_TEST_SECTION_END(); } @@ -613,6 +623,16 @@ TEST_F(FirebaseMessagingTest, TestSendMessageToTopic) { // shouldn't have. EXPECT_FALSE(WaitForMessage(&message, 5)); + FLAKY_TEST_SECTION_RESET(); + + // This section will run after each failed flake attempt. If we failed to get + // a token, we might need to completely uninitialize messaging and + // reinitialize it. + LogInfo("Reinitializing FCM before retry..."); + TerminateMessaging(); + ProcessEvents(3000); // Pause a few seconds. + EXPECT_TRUE(InitializeMessaging()); + FLAKY_TEST_SECTION_END(); } From 137010974358daca9b943ee57d21b199f13c5d44 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Fri, 3 Feb 2023 11:05:52 -0800 Subject: [PATCH 12/14] Toggle SetTokenRegistrationOnInitEnabled when a test flakes. --- messaging/integration_test/src/integration_test.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index ee3086d0af..0972bcda16 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -397,8 +397,12 @@ TEST_F(FirebaseMessagingTest, TestReceiveToken) { // reinitialize it. LogInfo("Reinitializing FCM before retry..."); TerminateMessaging(); - ProcessEvents(3000); // Pause a few seconds. + ProcessEvents(2000); // Pause a few seconds. EXPECT_TRUE(InitializeMessaging()); + ProcessEvents(2000); // Pause a few seconds. + // Toggle SetTokenRegistrationOnInitEnabled. + firebase::messaging::SetTokenRegistrationOnInitEnabled(false); + firebase::messaging::SetTokenRegistrationOnInitEnabled(true); FLAKY_TEST_SECTION_END(); } @@ -570,8 +574,12 @@ TEST_F(FirebaseMessagingTest, TestSendMessageToToken) { // reinitialize it. LogInfo("Reinitializing FCM before retry..."); TerminateMessaging(); - ProcessEvents(3000); // Pause a few seconds. + ProcessEvents(2000); // Pause a few seconds. EXPECT_TRUE(InitializeMessaging()); + ProcessEvents(2000); // Pause a few seconds. + // Toggle SetTokenRegistrationOnInitEnabled. + firebase::messaging::SetTokenRegistrationOnInitEnabled(false); + firebase::messaging::SetTokenRegistrationOnInitEnabled(true); FLAKY_TEST_SECTION_END(); } From c2c399412ba500910f6a6c57286cf5a92a6712a6 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Fri, 3 Feb 2023 11:36:43 -0800 Subject: [PATCH 13/14] When retrying SendMessageToToken, identify when we are receiving the older message and consume it. --- .../integration_test/src/integration_test.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/messaging/integration_test/src/integration_test.cc b/messaging/integration_test/src/integration_test.cc index 0972bcda16..1e53d27e7a 100644 --- a/messaging/integration_test/src/integration_test.cc +++ b/messaging/integration_test/src/integration_test.cc @@ -543,12 +543,16 @@ TEST_F(FirebaseMessagingTest, TestSendMessageToToken) { SKIP_TEST_ON_ANDROID_EMULATOR; + // When deflaking this test, sometimes we get out of sync, so attempt #2 + // receives the message that was meant for attempt #1. By storing the previous + // unique ID, we can catch this situation and consume the extraneous message. + std::string previous_unique_id = "XXX"; + std::string unique_id; FLAKY_TEST_SECTION_BEGIN(); EXPECT_TRUE(RequestPermission()); EXPECT_TRUE(WaitForToken()); - - std::string unique_id = GetUniqueMessageId(); + unique_id = GetUniqueMessageId(); const char kNotificationTitle[] = "Token Test"; const char kNotificationBody[] = "Token Test notification body"; SendTestMessage(shared_token()->c_str(), kNotificationTitle, @@ -558,7 +562,15 @@ TEST_F(FirebaseMessagingTest, TestSendMessageToToken) { {kNotificationLinkKey, kTestLink}}); LogDebug("Waiting for message."); firebase::messaging::Message message; + EXPECT_TRUE(WaitForMessage(&message)); + if (message.data["unique_id"] == previous_unique_id) { + // Flaky fix: We've received a leftover message from the previous attempt. + // Consume it and get another (with a short timeout), to see if it matches. + LogDebug( + "Message unique_id matches *previous* attempt, getting another..."); + EXPECT_TRUE(WaitForMessage(&message, 10)); + } EXPECT_EQ(message.data["unique_id"], unique_id); EXPECT_NE(message.notification, nullptr); if (message.notification) { @@ -569,6 +581,8 @@ TEST_F(FirebaseMessagingTest, TestSendMessageToToken) { FLAKY_TEST_SECTION_RESET(); + previous_unique_id = unique_id; + // This section will run after each failed flake attempt. If we failed to get // a token, we might need to completely uninitialize messaging and // reinitialize it. From 239031d33c4d24d6d2f73dbdf6f35f6832f143cb Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Fri, 3 Feb 2023 13:11:29 -0800 Subject: [PATCH 14/14] Add output of key hash for debugging. --- .github/workflows/integration_tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 3ddaea0630..fa03a37140 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -457,6 +457,8 @@ jobs: --short_output_paths \ --gha_build \ ${additional_flags[*]} + echo "Key hash used for building:" + echo | keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore - name: Prepare results summary artifact if: ${{ !cancelled() }} shell: bash