-
Notifications
You must be signed in to change notification settings - Fork 658
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
Fix bug calling onKeyUpdate when should not, and better error messages #780
Changes from all commits
ce3d47a
6dbff0a
263e12e
384cbe7
e5f8387
2e50eca
332b2eb
8c287d8
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 |
---|---|---|
|
@@ -54,18 +54,35 @@ TEphemeralKey getEphemeralKey() { | |
return mEphemeralKey; | ||
} | ||
|
||
@SuppressWarnings("checkstyle:IllegalCatch") | ||
private void updateKey( | ||
@NonNull String key, | ||
@Nullable String actionString, | ||
@Nullable Map<String, Object> arguments) { | ||
// Key is coming from the user, so even if it's @NonNull annotated we | ||
// want to double check it | ||
if (key == null) { | ||
mListener.onKeyError(HttpURLConnection.HTTP_INTERNAL_ERROR, | ||
"EphemeralKeyUpdateListener.onKeyUpdate was called " + | ||
"with a null value"); | ||
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. should we 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. ah yes, good catch |
||
return; | ||
} | ||
try { | ||
mEphemeralKey = AbstractEphemeralKey.fromString(key, mEphemeralKeyClass); | ||
mListener.onKeyUpdate(mEphemeralKey, actionString, arguments); | ||
} catch (JSONException e) { | ||
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. do we still need to explicitly catch 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. I think it helps the message be a tad more explicit |
||
mListener.onKeyError(HttpURLConnection.HTTP_INTERNAL_ERROR, | ||
"The JSON from the key could not be parsed: " | ||
+ e.getLocalizedMessage()); | ||
"EphemeralKeyUpdateListener.onKeyUpdate was passed " + | ||
"a value that could not be JSON parsed: [" | ||
+ e.getLocalizedMessage() + "]. The raw body from Stripe's response" + | ||
" should be passed"); | ||
} catch (Exception e) { | ||
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. did you add this for safety? 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. Yeah, if any other exception happens, the error will just be silenced, which was the case for a wrongly formatted JSON (the JSON is parsed, but then the |
||
mListener.onKeyError(HttpURLConnection.HTTP_INTERNAL_ERROR, | ||
"EphemeralKeyUpdateListener.onKeyUpdate was passed " + | ||
"a JSON String that was invalid: [" | ||
+ e.getLocalizedMessage() + "]. The raw body from Stripe's response" + | ||
" should be passed"); | ||
} | ||
mListener.onKeyUpdate(mEphemeralKey, actionString, arguments); | ||
} | ||
|
||
private void updateKeyError(int errorCode, @Nullable String errorMessage) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
import org.mockito.MockitoAnnotations; | ||
import org.robolectric.RobolectricTestRunner; | ||
|
||
import java.net.HttpURLConnection; | ||
import java.util.Calendar; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
@@ -25,6 +26,7 @@ | |
import static org.junit.Assert.assertTrue; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.ArgumentMatchers.isNull; | ||
import static org.mockito.Mockito.never; | ||
import static org.mockito.Mockito.reset; | ||
import static org.mockito.Mockito.times; | ||
import static org.mockito.Mockito.verify; | ||
|
@@ -250,4 +252,67 @@ public void updateKeyIfNecessary_whenReturnsError_setsExistingKeyToNull() { | |
verifyNoMoreInteractions(mKeyManagerListener); | ||
assertNull(keyManager.getEphemeralKey()); | ||
} | ||
|
||
@Test | ||
public void triggerCorrectErrorOnInvalidRawKey() { | ||
|
||
mTestEphemeralKeyProvider.setNextRawEphemeralKey("Not_a_JSON"); | ||
EphemeralKeyManager<CustomerEphemeralKey> keyManager = new EphemeralKeyManager<>( | ||
mTestEphemeralKeyProvider, | ||
mKeyManagerListener, | ||
TEST_SECONDS_BUFFER, | ||
null, | ||
CustomerEphemeralKey.class); | ||
|
||
verify(mKeyManagerListener, never()).onKeyUpdate( | ||
(CustomerEphemeralKey) isNull(), (String) isNull(), (Map<String, Object>) isNull()); | ||
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. I think this is better:
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. So I initially tried that, but it fails to error when 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. don't we expect it not to be called though? so I would assume "never with any" makes more logical sense than "never with nulls" 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. Ah yes, but if I change to the |
||
verify(mKeyManagerListener, times(1)).onKeyError( | ||
HttpURLConnection.HTTP_INTERNAL_ERROR, | ||
"EphemeralKeyUpdateListener.onKeyUpdate was passed a value that " + | ||
"could not be JSON parsed: [Value Not_a_JSON of type java.lang.String " + | ||
"cannot be converted to JSONObject]. The raw body from Stripe's " + | ||
"response should be passed"); | ||
assertNull(keyManager.getEphemeralKey()); | ||
} | ||
|
||
@Test | ||
public void triggerCorrectErrorOnInvalidJsonKey() { | ||
|
||
mTestEphemeralKeyProvider.setNextRawEphemeralKey("{}"); | ||
EphemeralKeyManager<CustomerEphemeralKey> keyManager = new EphemeralKeyManager<>( | ||
mTestEphemeralKeyProvider, | ||
mKeyManagerListener, | ||
TEST_SECONDS_BUFFER, | ||
null, | ||
CustomerEphemeralKey.class); | ||
|
||
verify(mKeyManagerListener, never()).onKeyUpdate( | ||
(CustomerEphemeralKey) isNull(), (String) isNull(), (Map<String, Object>) isNull()); | ||
verify(mKeyManagerListener, times(1)).onKeyError( | ||
HttpURLConnection.HTTP_INTERNAL_ERROR, | ||
"EphemeralKeyUpdateListener.onKeyUpdate was passed a JSON String " + | ||
"that was invalid: [Improperly formatted JSON for ephemeral " + | ||
"key CustomerEphemeralKey - No value for created]. The raw body " + | ||
"from Stripe's response should be passed"); | ||
assertNull(keyManager.getEphemeralKey()); | ||
} | ||
|
||
@Test | ||
public void triggerCorrectErrorOnNullKey() { | ||
|
||
mTestEphemeralKeyProvider.setNextRawEphemeralKey(null); | ||
EphemeralKeyManager<CustomerEphemeralKey> keyManager = new EphemeralKeyManager<>( | ||
mTestEphemeralKeyProvider, | ||
mKeyManagerListener, | ||
TEST_SECONDS_BUFFER, | ||
null, | ||
CustomerEphemeralKey.class); | ||
|
||
verify(mKeyManagerListener, never()).onKeyUpdate( | ||
(CustomerEphemeralKey) isNull(), (String) isNull(), (Map<String, Object>) isNull()); | ||
verify(mKeyManagerListener, times(1)).onKeyError( | ||
HttpURLConnection.HTTP_INTERNAL_ERROR, | ||
"EphemeralKeyUpdateListener.onKeyUpdate was called with a null value"); | ||
assertNull(keyManager.getEphemeralKey()); | ||
} | ||
} |
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.
I think we can remove the
e.getTargetException().getMessage()
part from the message because we're passinge.getTargetException()
as an argument.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.
hm, in an ideal world yes, but the interface of
onKeyError
only accepts a String, and that's what we're passing to the dev.So without explicitely dropping the message in the String, we risk losing it as it is surfaced, if that makes sense