Repository navigation
[SDK-753] Stabilize flaky Android unit, instrumentation, and BCIT tests #1099
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |
| import org.junit.runner.RunWith; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Locale; | ||
| import java.util.concurrent.CountDownLatch; | ||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
|
|
@@ -28,6 +29,7 @@ | |
| import static junit.framework.Assert.assertNotNull; | ||
| import static junit.framework.Assert.assertNull; | ||
| import static junit.framework.Assert.assertTrue; | ||
| import static junit.framework.Assert.fail; | ||
| import static org.junit.Assert.assertThat; | ||
|
|
||
| @RunWith(AndroidJUnit4.class) | ||
|
|
@@ -130,21 +132,52 @@ public void onFailure(@NonNull String reason, @Nullable JSONObject data) { | |
|
|
||
| @Test | ||
| public void testResponseCode400WithoutMessage() throws Exception { | ||
| final CountDownLatch signal = new CountDownLatch(1); | ||
|
|
||
| stubAnyRequestReturningStatusCode(400, "{}"); | ||
| String lastReason = null; | ||
| boolean serverReceivedRequest = false; | ||
| for (int attempt = 1; attempt <= 3; attempt++) { | ||
| final CountDownLatch signal = new CountDownLatch(1); | ||
| final String[] reason = new String[1]; | ||
|
|
||
| stubAnyRequestReturningStatusCode(400, "{}"); | ||
|
|
||
| IterableApiRequest request = new IterableApiRequest("fake_key", "", new JSONObject(), IterableApiRequest.POST, null, null, new IterableHelper.FailureHandler() { | ||
| @Override | ||
| public void onFailure(@NonNull String failureReason, @Nullable JSONObject data) { | ||
| reason[0] = failureReason; | ||
| signal.countDown(); | ||
| } | ||
| }); | ||
| new IterableRequestTask().execute(request); | ||
|
|
||
| RecordedRequest recorded = server.takeRequest(5, TimeUnit.SECONDS); | ||
| boolean callbackFinished = signal.await(5, TimeUnit.SECONDS); | ||
| lastReason = reason[0]; | ||
| if (recorded != null) { | ||
| serverReceivedRequest = true; | ||
| } | ||
|
|
||
| IterableApiRequest request = new IterableApiRequest("fake_key", "", new JSONObject(), IterableApiRequest.POST, null, null, new IterableHelper.FailureHandler() { | ||
| @Override | ||
| public void onFailure(@NonNull String reason, @Nullable JSONObject data) { | ||
| assertEquals("Invalid Request", reason); | ||
| signal.countDown(); | ||
| if (callbackFinished && "Invalid Request".equals(lastReason)) { | ||
| return; | ||
| } | ||
| }); | ||
| new IterableRequestTask().execute(request); | ||
| if (recorded != null && callbackFinished && !isEmulatorTransportTimeout(lastReason)) { | ||
| assertEquals("Invalid Request", lastReason); | ||
| } | ||
|
Comment on lines
+162
to
+164
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest failing any completed callback with an unrecognized non-transport reason even when The request can reach |
||
| } | ||
|
|
||
| server.takeRequest(5, TimeUnit.SECONDS); | ||
| assertTrue("onFailure is called", signal.await(5, TimeUnit.SECONDS)); | ||
| if (isEmulatorTransportTimeout(lastReason)) { | ||
| fail("Emulator transport timeout: stubbed HTTP 400 was not applied before the HTTP timeout. " | ||
| + "MockWebServer received the request: " + serverReceivedRequest | ||
| + ". Last failure reason: " + lastReason); | ||
| } | ||
| fail("MockWebServer received the request but the SDK did not report Invalid Request. Last failure reason: " + lastReason); | ||
| } | ||
|
|
||
| private static boolean isEmulatorTransportTimeout(String reason) { | ||
| if (reason == null) { | ||
| return true; | ||
| } | ||
| String lower = reason.toLowerCase(Locale.US); | ||
| return lower.contains("timeout") || lower.contains("timed out") || lower.contains("failed to connect"); | ||
| } | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setMembershipLevel(level)only runs after a successful sync disagrees withpresent; if the standard placement is already absent, the helper returns after two matching syncs without ever settingmembershipLevel=standard.This can pass while testing an unset or stale profile.
The fix would be to establish the requested membership before accepting the placement state.
Suggest sending the update unconditionally, or forcing an observable transition, before polling for its resulting placement state.