Skip to content
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

Keep File Manager from Error State on disallowed #1455

Merged
merged 11 commits into from Oct 24, 2019
6 changes: 6 additions & 0 deletions SmartDeviceLink/SDLFileManager.m
Expand Up @@ -181,6 +181,12 @@ - (void)didEnterStateFetchingInitialList {

// If there was an error, we'll pass the error to the startup handler and cancel out
if (error != nil) {
// HAX: In the case we are DISALLOWED we still want to transition to a ready state. Some head units return DISALLOWED for this RPC but otherwise work.
if([error.userInfo[@"resultCode"] isEqualToEnum:SDLResultDisallowed]) {
SDLLogW(@"ListFiles is disallowed. Certain file manager APIs may not work properly.");
[weakSelf.stateMachine transitionToState:SDLFileManagerStateReady];
BLOCK_RETURN;
}
[weakSelf.stateMachine transitionToState:SDLFileManagerStateStartupError];
BLOCK_RETURN;
}
Expand Down
9 changes: 8 additions & 1 deletion SmartDeviceLink/SDLListFilesOperation.m
Expand Up @@ -59,7 +59,14 @@ - (void)sdl_listFiles {
NSUInteger bytesAvailable = listFilesResponse.spaceAvailable != nil ? listFilesResponse.spaceAvailable.unsignedIntegerValue : 2000000000;

if (weakSelf.completionHandler != nil) {
weakSelf.completionHandler(success, bytesAvailable, fileNames, error);
if(error != nil) {
NSMutableDictionary *results = [error.userInfo mutableCopy];
results[@"resultCode"] = response.resultCode;
NSError *resultError = [NSError errorWithDomain:error.domain code:error.code userInfo:results];
weakSelf.completionHandler(success, bytesAvailable, fileNames, resultError);
} else {
weakSelf.completionHandler(success, bytesAvailable, fileNames, error);
}
}

[weakSelf finishOperation];
Expand Down
16 changes: 16 additions & 0 deletions SmartDeviceLinkTests/DevAPISpecs/SDLFileManagerSpec.m
Expand Up @@ -157,6 +157,22 @@ @implementation FileManagerSpecHelper
});
});

describe(@"after receiving a ListFiles error with a resultCode DISALLOWED", ^{
beforeEach(^{
SDLListFilesOperation *operation = testFileManager.pendingTransactions.firstObject;
NSMutableDictionary *userInfo = [[NSError sdl_fileManager_unableToStartError].userInfo mutableCopy];
userInfo[@"resultCode"] = SDLResultDisallowed;
NSError *errorWithResultCode = [NSError errorWithDomain:[NSError sdl_fileManager_unableToStartError].domain code:[NSError sdl_fileManager_unableToStartError].code userInfo:userInfo];
operation.completionHandler(NO, initialSpaceAvailable, testInitialFileNames, errorWithResultCode);
});

it(@"should handle the error properly", ^{
expect(testFileManager.currentState).to(match(SDLFileManagerStateReady));
expect(testFileManager.remoteFileNames).to(beEmpty());
expect(@(testFileManager.bytesAvailable)).to(equal(initialSpaceAvailable));
});
});

describe(@"after receiving a ListFiles response", ^{
beforeEach(^{
SDLListFilesOperation *operation = testFileManager.pendingTransactions.firstObject;
Expand Down
10 changes: 6 additions & 4 deletions SmartDeviceLinkTests/DevAPISpecs/SDLListFilesOperationSpec.m
Expand Up @@ -18,7 +18,7 @@
__block NSUInteger bytesAvailableResult = NO;
__block NSError *errorResult = nil;
__block NSArray<NSString *> *fileNamesResult = nil;

beforeEach(^{
testConnectionManager = [[TestConnectionManager alloc] init];
testOperation = [[SDLListFilesOperation alloc] initWithConnectionManager:testConnectionManager completionHandler:^(BOOL success, NSUInteger bytesAvailable, NSArray<NSString *> * _Nonnull fileNames, NSError * _Nullable error) {
Expand Down Expand Up @@ -92,13 +92,15 @@
badResponse.success = @NO;
badResponse.spaceAvailable = responseSpaceAvailable;
badResponse.filenames = responseFileNames;

badResponse.resultCode = SDLResultDisallowed;

[testConnectionManager respondToLastRequestWithResponse:badResponse error:[NSError sdl_lifecycle_unknownRemoteErrorWithDescription:responseErrorDescription andReason:responseErrorReason]];
});
it(@"should have called completion handler with error", ^{

it(@"should have called completion handler with error including a resultCode", ^{
expect(errorResult.localizedDescription).to(match(responseErrorDescription));
expect(errorResult.localizedFailureReason).to(match(responseErrorReason));
expect(errorResult.userInfo[@"resultCode"]).to(equal(@"DISALLOWED"));
expect(@(successResult)).to(equal(@NO));
});
});
Expand Down