-
Notifications
You must be signed in to change notification settings - Fork 130
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: Adds fallback dictionary when serialising device info. #279
Conversation
Previously the device tab was serialised using the dictionary supplied from the report, which could be null if the keypath did not exist. This fix uses an empty dictionary as a fallback so that at least some information (freeDisk, locale, simulator) will always be returned.
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.
Looks good, left a few nits.
Source/BugsnagKSCrashSysInfoParser.m
Outdated
[[report valueForKeyPath:@"user.state.deviceState"] mutableCopy]; | ||
|
||
NSMutableDictionary *device = [NSMutableDictionary new]; | ||
NSDictionary *state = [[report valueForKeyPath:@"user.state.deviceState"] mutableCopy]; |
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.
This no longer needs to be a mutable copy since the entries are being copied instead of appending to the original.
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.
For consideration: Since valueForKey:
can throw exceptions for incorrect keys, and since keypaths can't be checked by the compiler, is it worth considering wrapping these in a @try
/@catch
? It's certainly very unlikely these will throw, but not impossible.
XCTAssertNotNil(device[@"simulator"]); | ||
} | ||
|
||
@end |
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.
What happens if the report argument is nil?
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've tested this out and a dictionary is returned with the same contents as if an empty dictionary had been passed in. Adding this as a test would currently fail the suite with an error, presumably due to the fact we've enabled strict build settings and this method parameter is enabled as NonNull. Do you feel we need to change anything so that this can be unit tested?
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.
Is it possible to loosen the restrictions on just the test files? It seems like it might be useful to have a test like that
👍 |
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.
Mostly looks good to me, added a question and a thought on the tests
NSMutableDictionary *device = | ||
[[report valueForKeyPath:@"user.state.deviceState"] mutableCopy]; | ||
|
||
NSMutableDictionary *device = [NSMutableDictionary new]; |
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.
Would it be better to do something like this? I'm not sure how initWithDictionary
handles nil
NSDictionary *state = [report valueForKeyPath:@"user.state.deviceState"];
NSMutableDictionary* device = [[NSMutableDictionary alloc] initWithDictionary: state];
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.
initWithDictionary:
requires a Nonnull parameter, whereas addEntriesFromDictionary:
handles a nil param.
XCTAssertNotNil(device[@"simulator"]); | ||
} | ||
|
||
@end |
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.
Is it possible to loosen the restrictions on just the test files? It seems like it might be useful to have a test like that
@martin308 I've added a test for a nil dictionary by using |
#pragma clang diagnostic ignored "-Wnonnull" | ||
|
||
- (void)testNilDictSerialisation { | ||
XCTAssertNotNil(BSGParseDevice(nil)); |
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.
This could return an empty dictionary and still pass. I think this should check the contents too.
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.
Ditto this 👆 - the test should check the values are what is expected.
#pragma clang diagnostic ignored "-Wnonnull" | ||
|
||
- (void)testNilDictSerialisation { | ||
XCTAssertNotNil(BSGParseDevice(nil)); |
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.
Ditto this 👆 - the test should check the values are what is expected.
} | ||
|
||
#pragma clang diagnostic push | ||
#pragma clang diagnostic ignored "-Wnonnull" |
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.
The pragma
declarations should wrap what is being ignored as closely as possible to avoid any unintended usages.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
NSDictionary *device = BSGParseDevice(nil);
#pragma clang diagnostic pop
XCTAssertNotNil(device);
// ... (more)
Thanks for the review comments - I've addressed the pragma + validation comments. |
} | ||
|
||
|
||
@end |
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.
Do we need a test for a valid dictionary that contains the expected key?
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.
This is tested elsewhere I believe
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.
Left one question about another possible test, otherwise this LGTM
Goal
Previously the device tab was serialised using the dictionary supplied from the report, which could be null if the keypath did not exist. This could result in the device tab being completely null. This fix uses an empty dictionary as a fallback so that at least some information (freeDisk, locale, simulator) will always be returned.
Changeset
Changed
Initialise empty dictionary and defensively add items from report to it.
Tests
Added a failing unit test for the encountered scenario then passed it.
Review
For the submitter, initial self-review:
For the pull request reviewer(s), this changeset has been reviewed for: