Skip to content

Commit e7d6977

Browse files
authored
Deflake some integration tests including storage and FIS. (#295)
This test adds a convenience method RunFlakyBlock to firebase_test_framework that allows you to run a block multiple times, with exponential backoff until it succeeds (or fails a few times). This allows you to perform tests that have a chance of failure, such as uploading/downloading large files.
1 parent 3c8f78f commit e7d6977

File tree

6 files changed

+332
-96
lines changed

6 files changed

+332
-96
lines changed

installations/integration_test/src/integration_test.cc

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
namespace firebase_testapp_automated {
4242

4343
using app_framework::LogDebug;
44+
using app_framework::LogError;
4445

4546
using app_framework::ProcessEvents;
4647
using firebase_test_framework::FirebaseTest;
@@ -143,34 +144,90 @@ TEST_F(FirebaseInstallationsTest, TestCanGetId) {
143144
}
144145

145146
TEST_F(FirebaseInstallationsTest, TestGettingIdTwiceMatches) {
146-
firebase::Future<std::string> id = installations_->GetId();
147-
WaitForCompletion(id, "GetId");
148-
EXPECT_NE(*id.result(), "");
149-
std::string first_id = *id.result();
150-
id = installations_->GetId();
151-
WaitForCompletion(id, "GetId 2");
152-
EXPECT_EQ(*id.result(), first_id);
147+
if (!RunFlakyBlock(
148+
[](firebase::installations::Installations* installations) {
149+
firebase::Future<std::string> id = installations->GetId();
150+
WaitForCompletionAnyResult(id, "GetId");
151+
if (id.error() != 0) {
152+
LogError("GetId returned error %d: %s", id.error(),
153+
id.error_message());
154+
return false;
155+
}
156+
if (*id.result() == "") {
157+
LogError("GetId returned blank");
158+
return false;
159+
}
160+
std::string first_id = *id.result();
161+
id = installations->GetId();
162+
WaitForCompletionAnyResult(id, "GetId 2");
163+
if (id.error() != 0) {
164+
LogError("GetId 2 returned error %d: %s", id.error(),
165+
id.error_message());
166+
return false;
167+
}
168+
if (*id.result() != first_id) {
169+
LogError(
170+
"GetId 2 returned non-matching ID: first(%s) vs second(%s)",
171+
first_id.c_str(), id.result()->c_str());
172+
return false;
173+
}
174+
return true;
175+
},
176+
installations_)) {
177+
FAIL() << "Test failed, check error log for details.";
178+
}
153179
}
154180

155181
TEST_F(FirebaseInstallationsTest, TestDeleteGivesNewIdNextTime) {
156-
firebase::Future<std::string> id = installations_->GetId();
157-
WaitForCompletion(id, "GetId");
158-
EXPECT_NE(*id.result(), "");
159-
std::string first_id = *id.result();
160-
161-
firebase::Future<void> del = installations_->Delete();
162-
WaitForCompletion(del, "Delete");
163-
164-
// Ensure that we now get a different installations id.
165-
id = installations_->GetId();
166-
WaitForCompletion(id, "GetId 2");
167-
EXPECT_NE(*id.result(), "");
182+
if (!RunFlakyBlock(
183+
[](firebase::installations::Installations* installations) {
184+
firebase::Future<std::string> id = installations->GetId();
185+
WaitForCompletionAnyResult(id, "GetId");
186+
if (id.error() != 0) {
187+
LogError("GetId returned error %d: %s", id.error(),
188+
id.error_message());
189+
return false;
190+
}
191+
if (*id.result() == "") {
192+
LogError("GetId returned blank");
193+
return false;
194+
}
195+
std::string first_id = *id.result();
196+
197+
firebase::Future<void> del = installations->Delete();
198+
WaitForCompletionAnyResult(del, "Delete");
199+
if (del.error() != 0) {
200+
LogError("Delete returned error %d: %s", id.error(),
201+
id.error_message());
202+
return false;
203+
}
204+
205+
// Ensure that we now get a different installations id.
206+
id = installations->GetId();
207+
WaitForCompletionAnyResult(id, "GetId 2");
208+
if (id.error() != 0) {
209+
LogError("GetId 2 returned error %d: %s", id.error(),
210+
id.error_message());
211+
return false;
212+
}
213+
if (*id.result() == "") {
214+
LogError("GetId 2 returned blank");
215+
return false;
216+
}
168217
#if defined(__ANDROID__) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
169-
// Desktop is a stub and returns the same ID, but on mobile it should
170-
// return a new ID.
171-
EXPECT_NE(*id.result(), first_id);
218+
// Desktop is a stub and returns the same ID, but on mobile it
219+
// should return a new ID.
220+
if (*id.result() == first_id) {
221+
LogError("IDs match (should be different): %s", first_id.c_str());
222+
return false;
223+
}
172224
#endif // defined(__ANDROID__) || (defined(TARGET_OS_IPHONE) &&
173225
// TARGET_OS_IPHONE)
226+
return true;
227+
},
228+
installations_)) {
229+
FAIL() << "Test failed, check error log for details.";
230+
}
174231
}
175232

176233
TEST_F(FirebaseInstallationsTest, TestCanGetToken) {

messaging/integration_test/src/integration_test.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ void FirebaseMessagingTest::TearDownTestSuite() {
184184
LogDebug("Shutdown Firebase App.");
185185
delete shared_app_;
186186
shared_app_ = nullptr;
187+
188+
// On iOS/FTL, most or all of the tests are skipped, so add a delay so the app
189+
// doesn't finish too quickly, as this makes test results flaky.
190+
ProcessEvents(1000);
187191
}
188192

189193
FirebaseMessagingTest::FirebaseMessagingTest() {

scripts/gha/summarize_test_results.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ def main(argv):
308308
# Don't process this if meet another TEST SUMMARY
309309
if "TEST SUMMARY" in test_failure_line: break
310310
# Only get the lines showing paths.
311-
if "/firebase-cpp-sdk/" not in test_failure_line: continue
311+
if ("/firebase-cpp-sdk/" not in test_failure_line and
312+
"\\firebase-cpp-sdk\\" not in test_failure_line): continue
312313
test_filename = "";
313314
if "log tail" in test_failure_line:
314315
test_filename = re.match(r'^(.*) log tail', test_failure_line).group(1)
@@ -322,6 +323,7 @@ def main(argv):
322323
test_filename = re.match(r'^(.*integration_test\.app)', test_failure_line).group(1)
323324

324325
if test_filename:
326+
test_filename = test_filename.replace('\\', '/')
325327
m2 = re.search(r'/ta/(firebase)?([^/]+)/iti?/', test_filename, re.IGNORECASE)
326328
if not m2: m2 = re.search(r'/testapps/(firebase)?([^/]+)/integration_test', test_filename, re.IGNORECASE)
327329
if m2:

0 commit comments

Comments
 (0)